water ambience sounds change according to speed, oxygengenerator fills oxygen tanks even if their condition is 0, submarine refactoring & bugfixes, wire node editing bugfixes
This commit is contained in:
@@ -1,31 +1,31 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" ?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<Items>
|
<Items>
|
||||||
|
|
||||||
<Item
|
<Item
|
||||||
name="Engine"
|
name="Engine"
|
||||||
linkable="true"
|
linkable="true"
|
||||||
pickdistance="150">
|
pickdistance="150">
|
||||||
|
|
||||||
<Sprite texture ="engine.png" depth="0.8"/>
|
<Sprite texture ="engine.png" depth="0.8"/>
|
||||||
|
|
||||||
<Engine minvoltage="0.5" powerperforce="10.0" maxforce="500" canbeselected = "true">
|
<Engine minvoltage="0.5" powerperforce="10.0" maxforce="500" canbeselected = "true">
|
||||||
<GuiFrame rect="0,0,0.3,0.3" alignment="Center" color="0.0,0.0,0.0,0.8"/>
|
<GuiFrame rect="0,0,0.3,0.3" alignment="Center" color="0.0,0.0,0.0,0.8"/>
|
||||||
<sound file="engine.ogg" type="OnActive" range="3000.0" volume="CurrentVolume"/>
|
<sound file="engine.ogg" type="OnActive" range="3000.0" volume="CurrentVolume"/>
|
||||||
</Engine>
|
</Engine>
|
||||||
|
|
||||||
<ConnectionPanel canbeselected = "true" msg="Rewire [Screwdriver]">
|
<ConnectionPanel canbeselected = "true" msg="Rewire [Screwdriver]">
|
||||||
<requireditem name="Screwdriver" type="Equipped"/>
|
<requireditem name="Screwdriver" type="Equipped"/>
|
||||||
<input name="power_in"/>
|
<input name="power_in"/>
|
||||||
<input name="set_force"/>
|
<input name="set_force"/>
|
||||||
</ConnectionPanel>
|
</ConnectionPanel>
|
||||||
</Item>
|
</Item>
|
||||||
|
|
||||||
<Item
|
<Item
|
||||||
name="Navigation Terminal"
|
name="Navigation Terminal"
|
||||||
linkable="true"
|
linkable="true"
|
||||||
pickdistance="150">
|
pickdistance="150">
|
||||||
|
|
||||||
<Sprite texture ="fabricator.png" depth="0.8"/>
|
<Sprite texture ="fabricator.png" depth="0.8"/>
|
||||||
|
|
||||||
<Steering minvoltage="0.5" canbeselected = "true">
|
<Steering minvoltage="0.5" canbeselected = "true">
|
||||||
<GuiFrame rect="0,0,0.5,0.5" alignment="Center" color="0.0,0.0,0.0,0.8"/>
|
<GuiFrame rect="0,0,0.5,0.5" alignment="Center" color="0.0,0.0,0.0,0.8"/>
|
||||||
@@ -38,12 +38,12 @@
|
|||||||
<ScreenOverlay texture="Content/Items/Engine/radarOverlay.png" origin="0.5,0.5"/>
|
<ScreenOverlay texture="Content/Items/Engine/radarOverlay.png" origin="0.5,0.5"/>
|
||||||
</Radar>
|
</Radar>
|
||||||
|
|
||||||
<ConnectionPanel canbeselected = "true" msg="Rewire [Screwdriver]">
|
<ConnectionPanel canbeselected = "true" msg="Rewire [Screwdriver]">
|
||||||
<requireditem name="Screwdriver" type="Equipped"/>
|
<requireditem name="Screwdriver" type="Equipped"/>
|
||||||
<input name="power_in"/>
|
<input name="power_in"/>
|
||||||
<input name="velocity_in"/>
|
<input name="velocity_in"/>
|
||||||
<output name="velocity_x_out"/>
|
<output name="velocity_x_out"/>
|
||||||
<output name="velocity_y_out"/>
|
<output name="velocity_y_out"/>
|
||||||
</ConnectionPanel>
|
</ConnectionPanel>
|
||||||
</Item>
|
</Item>
|
||||||
</Items>
|
</Items>
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
<sound file="reactor.ogg" type="OnActive" range="2000.0" volume="FissionRate" volumemultiplier="0.02f"/>
|
<sound file="reactor.ogg" type="OnActive" range="2000.0" volume="FissionRate" volumemultiplier="0.02f"/>
|
||||||
|
|
||||||
<StatusEffect type="OnBroken" target="This" FissionRate="0.0" disabledeltatime="true" sound="Content/Items/Reactor/explosion.ogg">
|
<StatusEffect type="OnBroken" target="This" FissionRate="0.0" disabledeltatime="true" sound="Content/Items/Reactor/explosion.ogg">
|
||||||
<Explosion range ="6.0" damage="500" structuredamage="600" stun="5.0" force="5.0"/>
|
<Explosion range ="800" damage="500" structuredamage="400" stun="5.0" force="5.0"/>
|
||||||
</StatusEffect>
|
</StatusEffect>
|
||||||
</Reactor>
|
</Reactor>
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@
|
|||||||
|
|
||||||
<!-- if using the item fails (due to a insufficient skill level for example), the contained tank will break and an explosion will occurr -->
|
<!-- if using the item fails (due to a insufficient skill level for example), the contained tank will break and an explosion will occurr -->
|
||||||
<StatusEffect type="OnFailure" target="Contained" targetnames="Welding Fuel Tank,Oxygen Tank" Condition="-100.0" sound="Content/Items/Weapons/stunGrenade.ogg">
|
<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"/>
|
<Explosion range="500" damage="20" stun="10" force="5.0"/>
|
||||||
</StatusEffect>
|
</StatusEffect>
|
||||||
|
|
||||||
<LightComponent color="1.0,0.9,0.7,1.0" Flicker="0.5">
|
<LightComponent color="1.0,0.9,0.7,1.0" Flicker="0.5">
|
||||||
@@ -74,7 +74,7 @@
|
|||||||
<RequiredSkill name="Construction" level="30"/>
|
<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">
|
<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"/>
|
<Explosion range="500" damage="20" stun="10" force="5.0"/>
|
||||||
</StatusEffect>
|
</StatusEffect>
|
||||||
|
|
||||||
<LightComponent color="0.1,0.8,1.0,1.0" Flicker="0.5">
|
<LightComponent color="0.1,0.8,1.0,1.0" Flicker="0.5">
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
<Pickable slots="Any">
|
<Pickable slots="Any">
|
||||||
<StatusEffect type="OnBroken" target="This" Condition="-100.0" sound="Content/Items/Reactor/explosion.ogg">
|
<StatusEffect type="OnBroken" target="This" Condition="-100.0" sound="Content/Items/Reactor/explosion.ogg">
|
||||||
<Explosion range="5.0" structuredamage="300" damage="200" stun="5" force="20.0"/>
|
<Explosion range="500.0" structuredamage="300" damage="200" stun="5" force="20.0"/>
|
||||||
</StatusEffect>
|
</StatusEffect>
|
||||||
</Pickable>
|
</Pickable>
|
||||||
</Item>
|
</Item>
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
rotationlimits="180,360"
|
rotationlimits="180,360"
|
||||||
powerconsumption="500.0">
|
powerconsumption="500.0">
|
||||||
<StatusEffect type="OnUse" target="This" sound="Content/Items/Weapons/railgun.ogg">
|
<StatusEffect type="OnUse" target="This" sound="Content/Items/Weapons/railgun.ogg">
|
||||||
<Explosion range="10.0" structuredamage="0" force="0.05"/>
|
<Explosion range="1000.0" structuredamage="0" force="0.01"/>
|
||||||
</StatusEffect>
|
</StatusEffect>
|
||||||
</Turret>
|
</Turret>
|
||||||
|
|
||||||
|
|||||||
@@ -51,7 +51,7 @@
|
|||||||
|
|
||||||
<Throwable slots="Any,RightHand,LeftHand" holdpos="0,0" handle1="0,0" throwforce="5.0" aimpos="35,-10">
|
<Throwable slots="Any,RightHand,LeftHand" holdpos="0,0" handle1="0,0" throwforce="5.0" aimpos="35,-10">
|
||||||
<StatusEffect type="OnUse" target="This" Condition="-100.0" delay="3.0" sound="Content/Items/Weapons/stunGrenade.ogg">
|
<StatusEffect type="OnUse" target="This" Condition="-100.0" delay="3.0" sound="Content/Items/Weapons/stunGrenade.ogg">
|
||||||
<Explosion range="5" damage="5" stun="10" force="0.1"/>
|
<Explosion range="500" damage="5" stun="10" force="0.1"/>
|
||||||
</StatusEffect>
|
</StatusEffect>
|
||||||
</Throwable>
|
</Throwable>
|
||||||
</Item>
|
</Item>
|
||||||
|
|||||||
Binary file not shown.
@@ -44,6 +44,8 @@ namespace Subsurface
|
|||||||
steeringManager = new SteeringManager(this);
|
steeringManager = new SteeringManager(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual void OnAttacked(IDamageable attacker, float amount) { }
|
||||||
|
|
||||||
public virtual void SelectTarget(AITarget target) { }
|
public virtual void SelectTarget(AITarget target) { }
|
||||||
|
|
||||||
public virtual void Update(float deltaTime) { }
|
public virtual void Update(float deltaTime) { }
|
||||||
|
|||||||
@@ -262,6 +262,13 @@ namespace Subsurface
|
|||||||
targetEntity = closestBody.UserData as IDamageable;
|
targetEntity = closestBody.UserData as IDamageable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void OnAttacked(IDamageable attacker, float amount)
|
||||||
|
{
|
||||||
|
if (attacker==null || attacker.AiTarget==null) return;
|
||||||
|
AITargetMemory targetMemory = FindTargetMemory(attacker.AiTarget);
|
||||||
|
targetMemory.Priority += amount;
|
||||||
|
}
|
||||||
|
|
||||||
private void UpdateLimbAttack(float deltaTime, Limb limb, Vector2 attackPosition)
|
private void UpdateLimbAttack(float deltaTime, Limb limb, Vector2 attackPosition)
|
||||||
{
|
{
|
||||||
IDamageable damageTarget = null;
|
IDamageable damageTarget = null;
|
||||||
@@ -296,7 +303,7 @@ namespace Subsurface
|
|||||||
attackTimer += deltaTime;
|
attackTimer += deltaTime;
|
||||||
limb.body.ApplyTorque(limb.Mass * 50.0f * Character.AnimController.Dir * dir);
|
limb.body.ApplyTorque(limb.Mass * 50.0f * Character.AnimController.Dir * dir);
|
||||||
|
|
||||||
limb.attack.DoDamage(damageTarget, limb.SimPosition, deltaTime, (limb.soundTimer <= 0.0f));
|
limb.attack.DoDamage(Character, damageTarget, limb.SimPosition, deltaTime, (limb.soundTimer <= 0.0f));
|
||||||
|
|
||||||
limb.soundTimer = Limb.SoundInterval;
|
limb.soundTimer = Limb.SoundInterval;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ namespace Subsurface
|
|||||||
{
|
{
|
||||||
class AICharacter : Character
|
class AICharacter : Character
|
||||||
{
|
{
|
||||||
|
const float AttackBackPriority = 1.0f;
|
||||||
|
|
||||||
private AIController aiController;
|
private AIController aiController;
|
||||||
|
|
||||||
public AICharacter(string file) : this(file, Vector2.Zero, null)
|
public AICharacter(string file) : this(file, Vector2.Zero, null)
|
||||||
@@ -57,6 +59,15 @@ namespace Subsurface
|
|||||||
aiController.Update(deltaTime);
|
aiController.Update(deltaTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override AttackResult AddDamage(IDamageable attacker, Vector2 position, Attack attack, bool playSound = false)
|
||||||
|
{
|
||||||
|
AttackResult result = base.AddDamage(attacker, position, attack, playSound);
|
||||||
|
|
||||||
|
aiController.OnAttacked(attacker, (result.Damage + result.Bleeding)/Math.Max(health,1.0f));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public override void FillNetworkData(NetworkEventType type, NetOutgoingMessage message, object data)
|
public override void FillNetworkData(NetworkEventType type, NetOutgoingMessage message, object data)
|
||||||
{
|
{
|
||||||
if (type == NetworkEventType.KillCharacter)
|
if (type == NetworkEventType.KillCharacter)
|
||||||
|
|||||||
@@ -51,6 +51,12 @@ namespace Subsurface
|
|||||||
|
|
||||||
private float priority;
|
private float priority;
|
||||||
|
|
||||||
|
|
||||||
|
//public Attack(AttackType type, float range,)
|
||||||
|
//{
|
||||||
|
|
||||||
|
//}
|
||||||
|
|
||||||
public Attack(XElement element)
|
public Attack(XElement element)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -94,10 +100,10 @@ namespace Subsurface
|
|||||||
{
|
{
|
||||||
if (subElement.Name.ToString().ToLower() == "particleemitter") particleEmitterPrefab = new ParticleEmitterPrefab(subElement);
|
if (subElement.Name.ToString().ToLower() == "particleemitter") particleEmitterPrefab = new ParticleEmitterPrefab(subElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public AttackResult DoDamage(IDamageable target, Vector2 position, float deltaTime, bool playSound = true)
|
|
||||||
|
public AttackResult DoDamage(IDamageable attacker, IDamageable target, Vector2 position, float deltaTime, bool playSound = true)
|
||||||
{
|
{
|
||||||
float damageAmount = 0.0f;
|
float damageAmount = 0.0f;
|
||||||
//DamageSoundType damageSoundType = DamageSoundType.None;
|
//DamageSoundType damageSoundType = DamageSoundType.None;
|
||||||
@@ -125,7 +131,7 @@ namespace Subsurface
|
|||||||
sound.Play(1.0f, 500.0f, position);
|
sound.Play(1.0f, 500.0f, position);
|
||||||
}
|
}
|
||||||
|
|
||||||
return target.AddDamage(position, DamageType, damageAmount, bleedingAmount, Stun, playSound);
|
return target.AddDamage(attacker, position, this, playSound);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -856,7 +856,12 @@ namespace Subsurface
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public AttackResult AddDamage(Vector2 position, DamageType damageType, float amount, float bleedingAmount, float stun, bool playSound = false)
|
public virtual AttackResult AddDamage(IDamageable attacker, Vector2 position, Attack attack, bool playSound = false)
|
||||||
|
{
|
||||||
|
return AddDamage(position, attack.DamageType, attack.Damage, attack.BleedingDamage, attack.Stun, playSound);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AttackResult AddDamage(Vector2 position, DamageType damageType, float amount, float bleedingAmount, float stun, bool playSound)
|
||||||
{
|
{
|
||||||
AnimController.StunTimer = Math.Max(AnimController.StunTimer, stun);
|
AnimController.StunTimer = Math.Max(AnimController.StunTimer, stun);
|
||||||
|
|
||||||
@@ -882,7 +887,6 @@ namespace Subsurface
|
|||||||
bleeding += attackResult.Bleeding;
|
bleeding += attackResult.Bleeding;
|
||||||
|
|
||||||
return attackResult;
|
return attackResult;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Stun()
|
public void Stun()
|
||||||
|
|||||||
@@ -669,13 +669,13 @@ namespace Subsurface
|
|||||||
foreach (MapEntity e in MapEntity.mapEntityList)
|
foreach (MapEntity e in MapEntity.mapEntityList)
|
||||||
{
|
{
|
||||||
Gap gap = e as Gap;
|
Gap gap = e as Gap;
|
||||||
if (gap == null || gap.FlowTargetHull != currentHull || gap.FlowForce == Vector2.Zero) continue;
|
if (gap == null || gap.FlowTargetHull != currentHull || gap.LerpedFlowForce == Vector2.Zero) continue;
|
||||||
|
|
||||||
Vector2 gapPos = gap.SimPosition;
|
Vector2 gapPos = gap.SimPosition;
|
||||||
|
|
||||||
float dist = Vector2.Distance(limbPos, gapPos);
|
float dist = Vector2.Distance(limbPos, gapPos);
|
||||||
|
|
||||||
force += Vector2.Normalize(gap.FlowForce) * (Math.Max(gap.FlowForce.Length() - dist, 0.0f) / 500.0f);
|
force += Vector2.Normalize(gap.LerpedFlowForce) * (Math.Max(gap.LerpedFlowForce.Length() - dist, 0.0f) / 500.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (force.Length() > 20.0f) return force;
|
if (force.Length() > 20.0f) return force;
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ namespace Subsurface
|
|||||||
|
|
||||||
int amount = Rand.Range(minAmount, maxAmount, false);
|
int amount = Rand.Range(minAmount, maxAmount, false);
|
||||||
|
|
||||||
monsters = new Character[amount];
|
monsters = new AICharacter[amount];
|
||||||
|
|
||||||
for (int i = 0; i < amount; i++)
|
for (int i = 0; i < amount; i++)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -245,9 +245,9 @@ namespace Subsurface.Items.Components
|
|||||||
public override void UpdateBroken(float deltaTime, Camera cam)
|
public override void UpdateBroken(float deltaTime, Camera cam)
|
||||||
{
|
{
|
||||||
body.Enabled = false;
|
body.Enabled = false;
|
||||||
convexHull.Enabled = false;
|
//convexHull.Enabled = false;
|
||||||
linkedGap.Open = 1.0f;
|
linkedGap.Open = 1.0f;
|
||||||
if (convexHull2 != null) convexHull2.Enabled = false;
|
//if (convexHull2 != null) convexHull2.Enabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Draw(SpriteBatch spriteBatch, bool editing)
|
public override void Draw(SpriteBatch spriteBatch, bool editing)
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ namespace Subsurface.Items.Components
|
|||||||
|
|
||||||
private float range;
|
private float range;
|
||||||
|
|
||||||
|
private Character user;
|
||||||
|
|
||||||
[HasDefaultValue(0.0f, false)]
|
[HasDefaultValue(0.0f, false)]
|
||||||
public float Range
|
public float Range
|
||||||
{
|
{
|
||||||
@@ -45,6 +47,8 @@ namespace Subsurface.Items.Components
|
|||||||
if (character == null) return false;
|
if (character == null) return false;
|
||||||
if (!character.GetInputState(InputType.SecondaryHeld) || hitting) return false;
|
if (!character.GetInputState(InputType.SecondaryHeld) || hitting) return false;
|
||||||
|
|
||||||
|
user = character;
|
||||||
|
|
||||||
if (hitPos < MathHelper.Pi * 0.69f) return false;
|
if (hitPos < MathHelper.Pi * 0.69f) return false;
|
||||||
|
|
||||||
item.body.FarseerBody.CollisionCategories = Physics.CollisionProjectile;
|
item.body.FarseerBody.CollisionCategories = Physics.CollisionProjectile;
|
||||||
@@ -178,7 +182,7 @@ namespace Subsurface.Items.Components
|
|||||||
|
|
||||||
if (target == null) return false;
|
if (target == null) return false;
|
||||||
|
|
||||||
attack.DoDamage(target, item.Position, 1.0f);
|
attack.DoDamage(user, target, item.Position, 1.0f);
|
||||||
|
|
||||||
RestoreCollision();
|
RestoreCollision();
|
||||||
hitting = false;
|
hitting = false;
|
||||||
|
|||||||
@@ -1,106 +1,106 @@
|
|||||||
using Microsoft.Xna.Framework;
|
//using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
//using Microsoft.Xna.Framework.Graphics;
|
||||||
using System;
|
//using System;
|
||||||
using System.Collections.Generic;
|
//using System.Collections.Generic;
|
||||||
using System.Linq;
|
//using System.Linq;
|
||||||
using System.Text;
|
//using System.Text;
|
||||||
using System.Xml.Linq;
|
//using System.Xml.Linq;
|
||||||
|
|
||||||
namespace Subsurface.Items.Components
|
//namespace Subsurface.Items.Components
|
||||||
{
|
//{
|
||||||
class Label : ItemComponent
|
// class Label : ItemComponent
|
||||||
{
|
// {
|
||||||
GUITextBox textBox;
|
// GUITextBox textBox;
|
||||||
|
|
||||||
private string text;
|
// private string text;
|
||||||
|
|
||||||
[HasDefaultValue("", true)]
|
// [HasDefaultValue("", true)]
|
||||||
public string Text
|
// public string Text
|
||||||
{
|
// {
|
||||||
get { return text; }
|
// get { return text; }
|
||||||
set
|
// set
|
||||||
{
|
// {
|
||||||
text = value;
|
// text = value;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
public Label(Item item, XElement element)
|
// public Label(Item item, XElement element)
|
||||||
: base(item, element)
|
// : base(item, element)
|
||||||
{
|
// {
|
||||||
|
|
||||||
}
|
// }
|
||||||
|
|
||||||
public override bool Select(Character character)
|
// public override bool Select(Character character)
|
||||||
{
|
// {
|
||||||
if (textBox == null)
|
// if (textBox == null)
|
||||||
{
|
// {
|
||||||
textBox = new GUITextBox(Rectangle.Empty, GUI.Style, GuiFrame);
|
// textBox = new GUITextBox(Rectangle.Empty, GUI.Style, GuiFrame);
|
||||||
textBox.Wrap = true;
|
// textBox.Wrap = true;
|
||||||
textBox.OnTextChanged = TextChanged;
|
// textBox.OnTextChanged = TextChanged;
|
||||||
textBox.LimitText = true;
|
// textBox.LimitText = true;
|
||||||
|
|
||||||
GUIButton button = new GUIButton(new Rectangle(0,0,100,15), "OK", null, Alignment.BottomRight, GUI.Style, GuiFrame);
|
// GUIButton button = new GUIButton(new Rectangle(0,0,100,15), "OK", null, Alignment.BottomRight, GUI.Style, GuiFrame);
|
||||||
button.OnClicked = Close;
|
// button.OnClicked = Close;
|
||||||
}
|
// }
|
||||||
|
|
||||||
textBox.Text = text;
|
// textBox.Text = text;
|
||||||
|
|
||||||
textBox.Select();
|
// textBox.Select();
|
||||||
|
|
||||||
return base.Select(character);
|
// return base.Select(character);
|
||||||
}
|
// }
|
||||||
|
|
||||||
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
|
// public override void DrawHUD(SpriteBatch spriteBatch, Character character)
|
||||||
{
|
// {
|
||||||
//isActive = true;
|
// //isActive = true;
|
||||||
GuiFrame.Update((float)Physics.step);
|
// GuiFrame.Update((float)Physics.step);
|
||||||
GuiFrame.Draw(spriteBatch);
|
// GuiFrame.Draw(spriteBatch);
|
||||||
|
|
||||||
//int width = 300, height = 300;
|
// //int width = 300, height = 300;
|
||||||
//int x = Game1.GraphicsWidth / 2 - width / 2;
|
// //int x = Game1.GraphicsWidth / 2 - width / 2;
|
||||||
//int y = Game1.GraphicsHeight / 2 - height / 2 - 50;
|
// //int y = Game1.GraphicsHeight / 2 - height / 2 - 50;
|
||||||
|
|
||||||
//GUI.DrawRectangle(spriteBatch, new Rectangle(x, y, width, height), Color.Black, true);
|
// //GUI.DrawRectangle(spriteBatch, new Rectangle(x, y, width, height), Color.Black, true);
|
||||||
if (!textBox.Selected) character.SelectedConstruction = null;
|
// if (!textBox.Selected) character.SelectedConstruction = null;
|
||||||
}
|
// }
|
||||||
|
|
||||||
private bool TextChanged(GUITextBox textBox, string text)
|
// private bool TextChanged(GUITextBox textBox, string text)
|
||||||
{
|
// {
|
||||||
this.text = text;
|
// this.text = text;
|
||||||
item.NewComponentEvent(this, true);
|
// item.NewComponentEvent(this, true);
|
||||||
|
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
|
|
||||||
private bool Close(GUIButton button, object obj)
|
// private bool Close(GUIButton button, object obj)
|
||||||
{
|
// {
|
||||||
textBox.Deselect();
|
// textBox.Deselect();
|
||||||
|
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
|
|
||||||
public override void FillNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetOutgoingMessage message)
|
// public override void FillNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetOutgoingMessage message)
|
||||||
{
|
// {
|
||||||
message.Write(Text);
|
// message.Write(Text);
|
||||||
}
|
// }
|
||||||
|
|
||||||
public override void ReadNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetIncomingMessage message)
|
// public override void ReadNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetIncomingMessage message)
|
||||||
{
|
// {
|
||||||
string newText = "";
|
// string newText = "";
|
||||||
try
|
// try
|
||||||
{
|
// {
|
||||||
newText = message.ReadString();
|
// newText = message.ReadString();
|
||||||
}
|
// }
|
||||||
|
|
||||||
catch (Exception e)
|
// catch (Exception e)
|
||||||
{
|
// {
|
||||||
#if DEBUG
|
//#if DEBUG
|
||||||
DebugConsole.ThrowError("invalid network message", e);
|
// DebugConsole.ThrowError("invalid network message", e);
|
||||||
#endif
|
//#endif
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
|
||||||
Text = newText;
|
// Text = newText;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|||||||
@@ -145,11 +145,11 @@ namespace Subsurface.Items.Components
|
|||||||
Structure structure;
|
Structure structure;
|
||||||
if ((limb = (f2.Body.UserData as Limb)) != null)
|
if ((limb = (f2.Body.UserData as Limb)) != null)
|
||||||
{
|
{
|
||||||
attackResult = attack.DoDamage(limb.character, item.SimPosition, 1.0f);
|
attackResult = attack.DoDamage(null, limb.character, item.SimPosition, 1.0f);
|
||||||
}
|
}
|
||||||
else if ((structure = (f2.Body.UserData as Structure)) != null)
|
else if ((structure = (f2.Body.UserData as Structure)) != null)
|
||||||
{
|
{
|
||||||
attackResult = attack.DoDamage(structure, item.SimPosition, 1.0f);
|
attackResult = attack.DoDamage(null, structure, item.SimPosition, 1.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -289,37 +289,39 @@ namespace Subsurface.Items.Components
|
|||||||
{
|
{
|
||||||
GUI.DrawRectangle(spriteBatch, new Rectangle((int)Nodes[i].X - 3, (int)-Nodes[i].Y - 3, 6, 6), Color.Red, true, 0.0f);
|
GUI.DrawRectangle(spriteBatch, new Rectangle((int)Nodes[i].X - 3, (int)-Nodes[i].Y - 3, 6, 6), Color.Red, true, 0.0f);
|
||||||
|
|
||||||
if (GUIComponent.MouseOn == null &&
|
if (GUIComponent.MouseOn != null ||
|
||||||
Vector2.Distance(GameMain.EditMapScreen.Cam.ScreenToWorld(PlayerInput.MousePosition), Nodes[i]) < 20.0f)
|
Vector2.Distance(GameMain.EditMapScreen.Cam.ScreenToWorld(PlayerInput.MousePosition), Nodes[i]) > 20.0f)
|
||||||
{
|
{
|
||||||
GUI.DrawRectangle(spriteBatch, new Rectangle((int)Nodes[i].X - 10, (int)-Nodes[i].Y - 10, 20, 20), Color.Red, false, 0.0f);
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (selectedNodeIndex==null)// && selectedNodeIndex>0 && selectedNodeIndex<Nodes.Count-1)
|
GUI.DrawRectangle(spriteBatch, new Rectangle((int)Nodes[i].X - 10, (int)-Nodes[i].Y - 10, 20, 20), Color.Red, false, 0.0f);
|
||||||
|
|
||||||
|
if (selectedNodeIndex == null && !MapEntity.SelectedAny)
|
||||||
|
{
|
||||||
|
if (PlayerInput.LeftButtonDown())
|
||||||
{
|
{
|
||||||
if (PlayerInput.LeftButtonDown())
|
MapEntity.SelectEntity(item);
|
||||||
{
|
selectedNodeIndex = i;
|
||||||
MapEntity.SelectEntity(item);
|
MapEntity.DisableSelect = true;
|
||||||
selectedNodeIndex = i;
|
}
|
||||||
}
|
else if (PlayerInput.RightButtonClicked())
|
||||||
else if (PlayerInput.RightButtonClicked())
|
{
|
||||||
{
|
Nodes.RemoveAt(i);
|
||||||
Nodes.RemoveAt(i);
|
break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PlayerInput.LeftButtonDown())
|
if (PlayerInput.LeftButtonDown())
|
||||||
{
|
{
|
||||||
|
if (selectedNodeIndex != null && item.IsSelected)
|
||||||
if (selectedNodeIndex!=null && item.IsSelected)
|
|
||||||
{
|
{
|
||||||
MapEntity.DisableSelect = true;
|
MapEntity.DisableSelect = true;
|
||||||
Nodes[(int)selectedNodeIndex] = GameMain.EditMapScreen.Cam.ScreenToWorld(PlayerInput.MousePosition);
|
Nodes[(int)selectedNodeIndex] = GameMain.EditMapScreen.Cam.ScreenToWorld(PlayerInput.MousePosition);
|
||||||
|
|
||||||
Vector2 pos = Nodes[(int)selectedNodeIndex];
|
Vector2 pos = Nodes[(int)selectedNodeIndex];
|
||||||
|
|
||||||
|
|
||||||
Nodes[(int)selectedNodeIndex] = RoundNode(Nodes[(int)selectedNodeIndex], Hull.FindHull(Nodes[(int)selectedNodeIndex]));
|
Nodes[(int)selectedNodeIndex] = RoundNode(Nodes[(int)selectedNodeIndex], Hull.FindHull(Nodes[(int)selectedNodeIndex]));
|
||||||
MapEntity.SelectEntity(item);
|
MapEntity.SelectEntity(item);
|
||||||
}
|
}
|
||||||
@@ -328,9 +330,6 @@ namespace Subsurface.Items.Components
|
|||||||
{
|
{
|
||||||
selectedNodeIndex = null;
|
selectedNodeIndex = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawSection(SpriteBatch spriteBatch, Vector2 start, Vector2 end, Color color)
|
private void DrawSection(SpriteBatch spriteBatch, Vector2 start, Vector2 end, Color color)
|
||||||
|
|||||||
@@ -459,11 +459,11 @@ namespace Subsurface
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public AttackResult AddDamage(Vector2 position, DamageType damageType, float amount, float bleedingAmount, float stun, bool playSound = true)
|
public AttackResult AddDamage(IDamageable attacker, Vector2 position, Attack attack, bool playSound = true)
|
||||||
{
|
{
|
||||||
Condition -= amount;
|
Condition -= attack.Damage;
|
||||||
|
|
||||||
return new AttackResult(amount, 0.0f, false);
|
return new AttackResult(attack.Damage, 0.0f, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -601,7 +601,7 @@ namespace Subsurface
|
|||||||
GUI.DrawLine(spriteBatch,
|
GUI.DrawLine(spriteBatch,
|
||||||
new Vector2(rect.X + rect.Width / 2, -rect.Y + rect.Height / 2),
|
new Vector2(rect.X + rect.Width / 2, -rect.Y + rect.Height / 2),
|
||||||
new Vector2(e.Rect.X + e.Rect.Width / 2, -e.Rect.Y + e.Rect.Height / 2),
|
new Vector2(e.Rect.X + e.Rect.Width / 2, -e.Rect.Y + e.Rect.Height / 2),
|
||||||
Color.Red);
|
Color.Red*0.3f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,10 +11,7 @@ namespace Subsurface
|
|||||||
{
|
{
|
||||||
private Vector2 position;
|
private Vector2 position;
|
||||||
|
|
||||||
private float range;
|
private Attack attack;
|
||||||
private float damage;
|
|
||||||
private float structureDamage;
|
|
||||||
private float stun;
|
|
||||||
|
|
||||||
private float force;
|
private float force;
|
||||||
|
|
||||||
@@ -22,26 +19,24 @@ namespace Subsurface
|
|||||||
|
|
||||||
public float CameraShake;
|
public float CameraShake;
|
||||||
|
|
||||||
public Explosion(Vector2 position, float range, float damage, float structureDamage, float stun = 0.0f, float force = 0.0f)
|
//public Explosion(Vector2 position, float range, float damage, float structureDamage, float stun = 0.0f, float force = 0.0f)
|
||||||
{
|
//{
|
||||||
this.position = position;
|
// this.position = position;
|
||||||
this.range = Math.Max(range, 1.0f);
|
|
||||||
this.damage = damage;
|
|
||||||
this.structureDamage = structureDamage;
|
|
||||||
this.stun = stun;
|
|
||||||
this.force = force;
|
|
||||||
|
|
||||||
CameraShake = range*10.0f;
|
// attack = new Attack(,);
|
||||||
}
|
|
||||||
|
// this.force = force;
|
||||||
|
|
||||||
|
|
||||||
|
//}
|
||||||
|
|
||||||
public Explosion(XElement element)
|
public Explosion(XElement element)
|
||||||
{
|
{
|
||||||
range = Math.Max(ToolBox.GetAttributeFloat(element, "range", 1.0f), 1.0f);
|
attack = new Attack(element);
|
||||||
damage = ToolBox.GetAttributeFloat(element, "damage", 0.0f);
|
|
||||||
structureDamage = ToolBox.GetAttributeFloat(element, "structuredamage", 0.0f);
|
|
||||||
stun = ToolBox.GetAttributeFloat(element, "stun", 0.0f);
|
|
||||||
|
|
||||||
force = ToolBox.GetAttributeFloat(element, "force", 0.0f);
|
force = ToolBox.GetAttributeFloat(element, "force", 0.0f);
|
||||||
|
|
||||||
|
CameraShake = attack.Range*10.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Explode()
|
public void Explode()
|
||||||
@@ -56,7 +51,7 @@ namespace Subsurface
|
|||||||
GameMain.ParticleManager.CreateParticle("shockwave", displayPosition,
|
GameMain.ParticleManager.CreateParticle("shockwave", displayPosition,
|
||||||
Vector2.Zero, 0.0f);
|
Vector2.Zero, 0.0f);
|
||||||
|
|
||||||
for (int i = 0; i < range * 10; i++)
|
for (int i = 0; i < attack.Range * 10; i++)
|
||||||
{
|
{
|
||||||
GameMain.ParticleManager.CreateParticle("spark", displayPosition,
|
GameMain.ParticleManager.CreateParticle("spark", displayPosition,
|
||||||
Rand.Vector(Rand.Range(500.0f, 800.0f)), 0.0f);
|
Rand.Vector(Rand.Range(500.0f, 800.0f)), 0.0f);
|
||||||
@@ -67,7 +62,7 @@ namespace Subsurface
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
float displayRange = ConvertUnits.ToDisplayUnits(range);
|
float displayRange = ConvertUnits.ToDisplayUnits(attack.Range);
|
||||||
|
|
||||||
light = new LightSource(displayPosition, displayRange, Color.LightYellow);
|
light = new LightSource(displayPosition, displayRange, Color.LightYellow);
|
||||||
CoroutineManager.StartCoroutine(DimLight());
|
CoroutineManager.StartCoroutine(DimLight());
|
||||||
@@ -75,7 +70,7 @@ namespace Subsurface
|
|||||||
float cameraDist = Vector2.Distance(GameMain.GameScreen.Cam.Position, displayPosition)/2.0f;
|
float cameraDist = Vector2.Distance(GameMain.GameScreen.Cam.Position, displayPosition)/2.0f;
|
||||||
GameMain.GameScreen.Cam.Shake = CameraShake * Math.Max((displayRange - cameraDist)/displayRange, 0.0f);
|
GameMain.GameScreen.Cam.Shake = CameraShake * Math.Max((displayRange - cameraDist)/displayRange, 0.0f);
|
||||||
|
|
||||||
if (structureDamage > 0.0f)
|
if (attack.StructureDamage > 0.0f)
|
||||||
{
|
{
|
||||||
List<Structure> structureList = new List<Structure>();
|
List<Structure> structureList = new List<Structure>();
|
||||||
|
|
||||||
@@ -98,7 +93,7 @@ namespace Subsurface
|
|||||||
for (int i = 0; i < structure.SectionCount; i++)
|
for (int i = 0; i < structure.SectionCount; i++)
|
||||||
{
|
{
|
||||||
float distFactor = 1.0f - (Vector2.Distance(structure.SectionPosition(i), displayPosition) / displayRange);
|
float distFactor = 1.0f - (Vector2.Distance(structure.SectionPosition(i), displayPosition) / displayRange);
|
||||||
if (distFactor > 0.0f) structure.AddDamage(i, structureDamage*distFactor);
|
if (distFactor > 0.0f) structure.AddDamage(i, attack.StructureDamage*distFactor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -107,16 +102,16 @@ namespace Subsurface
|
|||||||
{
|
{
|
||||||
float dist = Vector2.Distance(c.SimPosition, simPosition);
|
float dist = Vector2.Distance(c.SimPosition, simPosition);
|
||||||
|
|
||||||
if (dist > range) continue;
|
if (dist > attack.Range) continue;
|
||||||
|
|
||||||
float distFactor = 1.0f - dist / range;
|
float distFactor = 1.0f - dist / attack.Range;
|
||||||
|
|
||||||
foreach (Limb limb in c.AnimController.Limbs)
|
foreach (Limb limb in c.AnimController.Limbs)
|
||||||
{
|
{
|
||||||
distFactor = 1.0f - Vector2.Distance(limb.SimPosition, simPosition)/range;
|
distFactor = 1.0f - Vector2.Distance(limb.SimPosition, simPosition)/attack.Range;
|
||||||
|
|
||||||
c.AddDamage(limb.SimPosition, DamageType.None, damage / c.AnimController.Limbs.Length * distFactor, 0.0f, stun * distFactor);
|
|
||||||
|
|
||||||
|
c.AddDamage(limb.SimPosition, DamageType.None,
|
||||||
|
attack.Damage / c.AnimController.Limbs.Length * distFactor, 0.0f, attack.Stun * distFactor, true);
|
||||||
if (force>0.0f)
|
if (force>0.0f)
|
||||||
{
|
{
|
||||||
limb.body.ApplyLinearImpulse(Vector2.Normalize(limb.SimPosition - simPosition) * distFactor * force);
|
limb.body.ApplyLinearImpulse(Vector2.Normalize(limb.SimPosition - simPosition) * distFactor * force);
|
||||||
|
|||||||
@@ -40,6 +40,13 @@ namespace Subsurface
|
|||||||
get { return flowForce*soundVolume; }
|
get { return flowForce*soundVolume; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Vector2 LerpedFlowForce
|
||||||
|
{
|
||||||
|
get { return lerpedFlowForce; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private Vector2 lerpedFlowForce;
|
||||||
|
|
||||||
public Hull FlowTargetHull
|
public Hull FlowTargetHull
|
||||||
{
|
{
|
||||||
get { return flowTargetHull; }
|
get { return flowTargetHull; }
|
||||||
@@ -178,6 +185,14 @@ namespace Subsurface
|
|||||||
|
|
||||||
public override void Draw(SpriteBatch sb, bool editing)
|
public override void Draw(SpriteBatch sb, bool editing)
|
||||||
{
|
{
|
||||||
|
if (GameMain.DebugDraw)
|
||||||
|
{
|
||||||
|
Vector2 center = new Vector2(rect.X + rect.Width / 2.0f, -(rect.Y - rect.Width / 2.0f));
|
||||||
|
GUI.DrawLine(sb, center, center + flowForce/10.0f, Color.Red);
|
||||||
|
|
||||||
|
GUI.DrawLine(sb, center + Vector2.One * 5.0f, center + lerpedFlowForce / 10.0f + Vector2.One * 5.0f, Color.Orange);
|
||||||
|
}
|
||||||
|
|
||||||
if (!editing) return;
|
if (!editing) return;
|
||||||
|
|
||||||
Color clr = (open == 0.0f) ? Color.Red : Color.Cyan;
|
Color clr = (open == 0.0f) ? Color.Red : Color.Cyan;
|
||||||
@@ -251,6 +266,8 @@ namespace Subsurface
|
|||||||
UpdateRoomToRoom(deltaTime);
|
UpdateRoomToRoom(deltaTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lerpedFlowForce = Vector2.Lerp(lerpedFlowForce, flowForce, 0.1f);
|
||||||
|
|
||||||
if (FlowForce.Length() > 150.0f && flowTargetHull != null && flowTargetHull.Volume < flowTargetHull.FullVolume)
|
if (FlowForce.Length() > 150.0f && flowTargetHull != null && flowTargetHull.Volume < flowTargetHull.FullVolume)
|
||||||
{
|
{
|
||||||
//UpdateFlowForce();
|
//UpdateFlowForce();
|
||||||
|
|||||||
@@ -19,6 +19,6 @@ namespace Subsurface
|
|||||||
get;
|
get;
|
||||||
}
|
}
|
||||||
|
|
||||||
AttackResult AddDamage(Vector2 position, DamageType damageType, float amount, float bleedingAmount, float stun, bool playSound=true);
|
AttackResult AddDamage(IDamageable attacker, Vector2 position, Attack attack, bool playSound=true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,9 +41,10 @@ namespace Subsurface
|
|||||||
public static bool DisableSelect
|
public static bool DisableSelect
|
||||||
{
|
{
|
||||||
get { return disableSelect; }
|
get { return disableSelect; }
|
||||||
set {
|
set
|
||||||
|
{
|
||||||
disableSelect = value;
|
disableSelect = value;
|
||||||
if (disableSelect==true)
|
if (disableSelect)
|
||||||
{
|
{
|
||||||
startMovingPos = Vector2.Zero;
|
startMovingPos = Vector2.Zero;
|
||||||
selectionSize = Vector2.Zero;
|
selectionSize = Vector2.Zero;
|
||||||
@@ -52,6 +53,12 @@ namespace Subsurface
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static bool SelectedAny
|
||||||
|
{
|
||||||
|
get { return selectedList.Count > 0; }
|
||||||
|
}
|
||||||
|
|
||||||
public bool MoveWithLevel
|
public bool MoveWithLevel
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
|
|||||||
@@ -386,11 +386,11 @@ namespace Subsurface
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int FindSectionIndex(Vector2 pos)
|
public int FindSectionIndex(Vector2 displayPos)
|
||||||
{
|
{
|
||||||
int index = (isHorizontal) ?
|
int index = (isHorizontal) ?
|
||||||
(int)Math.Floor((pos.X - rect.X) / wallSectionSize) :
|
(int)Math.Floor((displayPos.X - rect.X) / wallSectionSize) :
|
||||||
(int)Math.Floor((rect.Y - pos.Y) / wallSectionSize);
|
(int)Math.Floor((rect.Y - displayPos.Y) / wallSectionSize);
|
||||||
|
|
||||||
if (index < 0 || index > sections.Length - 1) return -1;
|
if (index < 0 || index > sections.Length - 1) return -1;
|
||||||
return index;
|
return index;
|
||||||
@@ -412,7 +412,7 @@ namespace Subsurface
|
|||||||
sections[sectionIndex].rect.Y - sections[sectionIndex].rect.Height / 2.0f);
|
sections[sectionIndex].rect.Y - sections[sectionIndex].rect.Height / 2.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AttackResult AddDamage(Vector2 position, DamageType damageType, float amount, float bleedingAmount, float stun, bool playSound = false)
|
public AttackResult AddDamage(IDamageable attacker, Vector2 position, Attack attack, bool playSound = false)
|
||||||
{
|
{
|
||||||
if (!prefab.HasBody || prefab.IsPlatform) return new AttackResult(0.0f, 0.0f);
|
if (!prefab.HasBody || prefab.IsPlatform) return new AttackResult(0.0f, 0.0f);
|
||||||
|
|
||||||
@@ -423,13 +423,13 @@ namespace Subsurface
|
|||||||
|
|
||||||
if (playSound && !SectionHasHole(i))
|
if (playSound && !SectionHasHole(i))
|
||||||
{
|
{
|
||||||
DamageSoundType damageSoundType = (damageType == DamageType.Blunt) ? DamageSoundType.StructureBlunt : DamageSoundType.StructureSlash;
|
DamageSoundType damageSoundType = (attack.DamageType == DamageType.Blunt) ? DamageSoundType.StructureBlunt : DamageSoundType.StructureSlash;
|
||||||
AmbientSoundManager.PlayDamageSound(damageSoundType, amount, position);
|
AmbientSoundManager.PlayDamageSound(damageSoundType, attack.Damage, position);
|
||||||
}
|
}
|
||||||
|
|
||||||
AddDamage(i, amount);
|
AddDamage(i, attack.Damage);
|
||||||
|
|
||||||
return new AttackResult(amount, 0.0f);
|
return new AttackResult(attack.Damage, 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetDamage(int sectionIndex, float damage)
|
private void SetDamage(int sectionIndex, float damage)
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
using FarseerPhysics;
|
using FarseerPhysics;
|
||||||
using FarseerPhysics.Collision;
|
using FarseerPhysics.Collision;
|
||||||
using FarseerPhysics.Common;
|
using FarseerPhysics.Common;
|
||||||
using FarseerPhysics.Common.Decomposition;
|
|
||||||
using FarseerPhysics.Dynamics;
|
using FarseerPhysics.Dynamics;
|
||||||
using FarseerPhysics.Dynamics.Contacts;
|
|
||||||
using FarseerPhysics.Factories;
|
|
||||||
using Lidgren.Network;
|
using Lidgren.Network;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
@@ -15,7 +12,6 @@ using System.IO;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
using Voronoi2;
|
|
||||||
|
|
||||||
namespace Subsurface
|
namespace Subsurface
|
||||||
{
|
{
|
||||||
@@ -32,20 +28,14 @@ namespace Subsurface
|
|||||||
|
|
||||||
private static Submarine loaded;
|
private static Submarine loaded;
|
||||||
|
|
||||||
|
private SubmarineBody subBody;
|
||||||
|
|
||||||
private static Vector2 lastPickedPosition;
|
private static Vector2 lastPickedPosition;
|
||||||
private static float lastPickedFraction;
|
private static float lastPickedFraction;
|
||||||
|
|
||||||
static string SaveFolder;
|
static string SaveFolder;
|
||||||
Md5Hash hash;
|
Md5Hash hash;
|
||||||
|
|
||||||
Vector2 speed;
|
|
||||||
|
|
||||||
Vector2 targetPosition;
|
|
||||||
|
|
||||||
private Rectangle borders;
|
|
||||||
|
|
||||||
private Body hullBody;
|
|
||||||
|
|
||||||
private string filePath;
|
private string filePath;
|
||||||
private string name;
|
private string name;
|
||||||
|
|
||||||
@@ -70,12 +60,6 @@ namespace Subsurface
|
|||||||
get { return lastPickedFraction; }
|
get { return lastPickedFraction; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Vector2> HullVertices
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
private set;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Md5Hash MD5Hash
|
public Md5Hash MD5Hash
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -98,14 +82,11 @@ namespace Subsurface
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return (loaded==null) ? Rectangle.Empty : loaded.borders;
|
return (loaded==null) ? Rectangle.Empty : Loaded.subBody.Borders;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector2 Center
|
|
||||||
{
|
|
||||||
get { return new Vector2(borders.X+borders.Width/2, borders.Y - borders.Height/2); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public Vector2 Position
|
public Vector2 Position
|
||||||
{
|
{
|
||||||
@@ -114,14 +95,16 @@ namespace Subsurface
|
|||||||
|
|
||||||
public Vector2 Speed
|
public Vector2 Speed
|
||||||
{
|
{
|
||||||
get { return speed; }
|
get { return subBody.Speed; }
|
||||||
set
|
set { subBody.Speed = value; }
|
||||||
{
|
|
||||||
if (!MathUtils.IsValid(value)) return;
|
|
||||||
speed = value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Vector2> HullVertices
|
||||||
|
{
|
||||||
|
get { return subBody.HullVertices; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public string FilePath
|
public string FilePath
|
||||||
{
|
{
|
||||||
get { return filePath; }
|
get { return filePath; }
|
||||||
@@ -162,69 +145,6 @@ namespace Subsurface
|
|||||||
ID = -1;
|
ID = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Vector2> GenerateConvexHull()
|
|
||||||
{
|
|
||||||
List<Vector2> points = new List<Vector2>();
|
|
||||||
|
|
||||||
Vector2 leftMost = Vector2.Zero;
|
|
||||||
|
|
||||||
foreach (Structure wall in Structure.wallList)
|
|
||||||
{
|
|
||||||
for (int x = -1; x <= 1; x += 2)
|
|
||||||
{
|
|
||||||
for (int y = -1; y <= 1; y += 2)
|
|
||||||
{
|
|
||||||
Vector2 corner = new Vector2(wall.Rect.X + wall.Rect.Width / 2.0f, wall.Rect.Y - wall.Rect.Height / 2.0f);
|
|
||||||
corner.X += x * wall.Rect.Width / 2.0f;
|
|
||||||
corner.Y += y * wall.Rect.Height / 2.0f;
|
|
||||||
|
|
||||||
if (points.Contains(corner)) continue;
|
|
||||||
|
|
||||||
points.Add(corner);
|
|
||||||
if (leftMost == Vector2.Zero || corner.X < leftMost.X) leftMost = corner;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Vector2> hullPoints = new List<Vector2>();
|
|
||||||
|
|
||||||
Vector2 currPoint = leftMost;
|
|
||||||
Vector2 endPoint;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
hullPoints.Add(currPoint);
|
|
||||||
endPoint = points[0];
|
|
||||||
|
|
||||||
for (int i = 1; i < points.Count; i++)
|
|
||||||
{
|
|
||||||
if ((currPoint == endPoint)
|
|
||||||
|| (Orientation(currPoint, endPoint, points[i]) == -1))
|
|
||||||
{
|
|
||||||
endPoint = points[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
currPoint = endPoint;
|
|
||||||
|
|
||||||
}
|
|
||||||
while (endPoint != hullPoints[0]);
|
|
||||||
|
|
||||||
return hullPoints;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int Orientation(Vector2 p1, Vector2 p2, Vector2 p)
|
|
||||||
{
|
|
||||||
// Determinant
|
|
||||||
float Orin = (p2.X - p1.X) * (p.Y - p1.Y) - (p.X - p1.X) * (p2.Y - p1.Y);
|
|
||||||
|
|
||||||
if (Orin > 0)
|
|
||||||
return -1; // (* Orientation is to the left-hand side *)
|
|
||||||
if (Orin < 0)
|
|
||||||
return 1; // (* Orientation is to the right-hand side *)
|
|
||||||
|
|
||||||
return 0; // (* Orientation is neutral aka collinear *)
|
|
||||||
}
|
|
||||||
|
|
||||||
//drawing ----------------------------------------------------
|
//drawing ----------------------------------------------------
|
||||||
|
|
||||||
public static void Draw(SpriteBatch spriteBatch, bool editing = false)
|
public static void Draw(SpriteBatch spriteBatch, bool editing = false)
|
||||||
@@ -419,188 +339,41 @@ namespace Subsurface
|
|||||||
|
|
||||||
//movement ----------------------------------------------------
|
//movement ----------------------------------------------------
|
||||||
|
|
||||||
float collisionRigidness = 1.0f;
|
|
||||||
|
|
||||||
public void Update(float deltaTime)
|
public void Update(float deltaTime)
|
||||||
{
|
{
|
||||||
Vector2 translateAmount = speed * deltaTime;
|
if (Level.Loaded == null) return;
|
||||||
translateAmount += ConvertUnits.ToDisplayUnits(hullBody.Position) * collisionRigidness;
|
|
||||||
|
|
||||||
if (targetPosition != Vector2.Zero && Vector2.Distance(targetPosition, Position) > 50.0f)
|
|
||||||
{
|
|
||||||
translateAmount += (targetPosition - Position) * 0.01f;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
targetPosition = Vector2.Zero;
|
|
||||||
}
|
|
||||||
|
|
||||||
Translate(translateAmount);
|
|
||||||
|
|
||||||
//-------------------------
|
|
||||||
|
|
||||||
Vector2 totalForce = CalculateBuoyancy();
|
|
||||||
|
|
||||||
float dragCoefficient = 0.00001f;
|
|
||||||
|
|
||||||
float speedLength = (speed == Vector2.Zero) ? 0.0f : speed.Length();
|
|
||||||
float drag = speedLength * speedLength * dragCoefficient * mass;
|
|
||||||
|
|
||||||
if (speed != Vector2.Zero)
|
|
||||||
{
|
|
||||||
totalForce += -Vector2.Normalize(speed) * drag;
|
|
||||||
}
|
|
||||||
|
|
||||||
ApplyForce(totalForce);
|
|
||||||
|
|
||||||
//hullBodies[0].body.LinearVelocity = -hullBodies[0].body.Position;
|
|
||||||
|
|
||||||
//hullBody.SetTransform(Vector2.Zero , 0.0f);
|
|
||||||
hullBody.LinearVelocity = -hullBody.Position/(float)Physics.step;
|
|
||||||
|
|
||||||
if (collidingCell == null)
|
|
||||||
{
|
|
||||||
collisionRigidness = MathHelper.Lerp(collisionRigidness, 1.0f, 0.1f);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (GraphEdge ge in collidingCell.edges)
|
|
||||||
{
|
|
||||||
Body body = PickBody(
|
|
||||||
ConvertUnits.ToSimUnits(ge.point1+ GameMain.GameSession.Level.Position),
|
|
||||||
ConvertUnits.ToSimUnits(ge.point2 + GameMain.GameSession.Level.Position), new List<Body>(){collidingCell.body});
|
|
||||||
if (body == null || body.UserData == null) continue;
|
|
||||||
|
|
||||||
Structure structure = body.UserData as Structure;
|
|
||||||
if (structure == null) continue;
|
|
||||||
structure.AddDamage(lastPickedPosition, DamageType.Blunt, 50.0f, 0.0f, 0.0f, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
collidingCell = null;
|
|
||||||
|
|
||||||
//hullBodies[0].body.SetTransform(Vector2.Zero, 0.0f);
|
|
||||||
|
|
||||||
//position = hullBodies[0].body.Position;
|
|
||||||
|
|
||||||
//Level.Loaded.Move(-ConvertUnits.ToDisplayUnits(position - prevPosition));
|
|
||||||
|
|
||||||
//prevPosition = hullBodies[0].body.Position;
|
|
||||||
|
|
||||||
|
subBody.Update(deltaTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Vector2 CalculateBuoyancy()
|
public void ApplyForce(Vector2 force)
|
||||||
{
|
{
|
||||||
float waterVolume = 0.0f;
|
subBody.ApplyForce(force);
|
||||||
float volume = 0.0f;
|
|
||||||
foreach (Hull hull in Hull.hullList)
|
|
||||||
{
|
|
||||||
waterVolume += hull.Volume;
|
|
||||||
volume += hull.FullVolume;
|
|
||||||
}
|
|
||||||
|
|
||||||
float waterPercentage = waterVolume / volume;
|
|
||||||
|
|
||||||
float neutralPercentage = 0.07f;
|
|
||||||
|
|
||||||
float buoyancy = neutralPercentage-waterPercentage;
|
|
||||||
buoyancy *= mass * 30.0f;
|
|
||||||
|
|
||||||
return new Vector2(0.0f, buoyancy);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetPosition(Vector2 position)
|
public void SetPosition(Vector2 position)
|
||||||
{
|
{
|
||||||
//hullBodies[0].body.SetTransform(position, 0.0f);
|
if (!MathUtils.IsValid(position)) return;
|
||||||
Level.Loaded.SetPosition(-position);
|
Level.Loaded.SetPosition(-position);
|
||||||
//prevPosition = position;
|
//prevPosition = position;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Translate(Vector2 amount)
|
public void Translate(Vector2 amount)
|
||||||
{
|
{
|
||||||
if (amount == Vector2.Zero || !amount.IsValid()) return;
|
if (amount == Vector2.Zero || !MathUtils.IsValid(amount)) return;
|
||||||
|
|
||||||
Level.Loaded.Move(-amount);
|
Level.Loaded.Move(-amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
float mass = 10000.0f;
|
|
||||||
public void ApplyForce(Vector2 force)
|
|
||||||
{
|
|
||||||
speed += force/mass;
|
|
||||||
}
|
|
||||||
|
|
||||||
VoronoiCell collidingCell;
|
|
||||||
public bool OnCollision(Fixture f1, Fixture f2, Contact contact)
|
|
||||||
{
|
|
||||||
System.Diagnostics.Debug.WriteLine("colliding");
|
|
||||||
VoronoiCell cell = f2.Body.UserData as VoronoiCell;
|
|
||||||
if (cell==null) return true;
|
|
||||||
|
|
||||||
Vector2 normal = contact.Manifold.LocalNormal;
|
|
||||||
Vector2 simSpeed = ConvertUnits.ToSimUnits(speed);
|
|
||||||
float impact = Vector2.Dot(simSpeed, normal);
|
|
||||||
|
|
||||||
Vector2 u = Vector2.Dot(simSpeed, -normal)*-normal;
|
|
||||||
Vector2 w = simSpeed - u;
|
|
||||||
|
|
||||||
Vector2 limbForce = normal * impact;
|
|
||||||
|
|
||||||
foreach (Character c in Character.CharacterList)
|
|
||||||
{
|
|
||||||
if (c.AnimController.CurrentHull == null) continue;
|
|
||||||
|
|
||||||
if (impact > 2.0f) c.AnimController.StunTimer = (impact - 2.0f) * 0.1f;
|
|
||||||
|
|
||||||
foreach (Limb limb in c.AnimController.Limbs)
|
|
||||||
{
|
|
||||||
limb.body.ApplyLinearImpulse(limb.Mass * limbForce);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (impact >= 1.0f)
|
|
||||||
{
|
|
||||||
AmbientSoundManager.PlayDamageSound(DamageSoundType.StructureBlunt, impact * 10.0f, cell.body);
|
|
||||||
|
|
||||||
FixedArray2<Vector2> worldPoints;
|
|
||||||
contact.GetWorldManifold(out normal, out worldPoints);
|
|
||||||
|
|
||||||
|
|
||||||
AmbientSoundManager.PlayDamageSound(DamageSoundType.StructureBlunt, impact * 10.0f, ConvertUnits.ToDisplayUnits(worldPoints[0]));
|
|
||||||
|
|
||||||
GameMain.GameScreen.Cam.Shake = impact*2.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
System.Diagnostics.Debug.WriteLine("IMPACT: "+impact + " normal: "+normal+" simspeed: "+simSpeed+" u: "+u+" w: " +w);
|
|
||||||
if (impact < 4.0f)
|
|
||||||
{
|
|
||||||
speed = ConvertUnits.ToDisplayUnits(w * 0.9f - u * 0.2f);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
speed = ConvertUnits.ToDisplayUnits(w * 0.9f + u * 0.5f);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
collisionRigidness = 0.8f;
|
|
||||||
|
|
||||||
collidingCell = cell;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnSeparation(Fixture f1, Fixture f2)
|
|
||||||
{
|
|
||||||
collidingCell = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void FillNetworkData(Networking.NetworkEventType type, NetOutgoingMessage message, object data)
|
public override void FillNetworkData(Networking.NetworkEventType type, NetOutgoingMessage message, object data)
|
||||||
{
|
{
|
||||||
message.Write((float)NetTime.Now);
|
message.Write((float)NetTime.Now);
|
||||||
message.Write(Position.X);
|
message.Write(Position.X);
|
||||||
message.Write(Position.Y);
|
message.Write(Position.Y);
|
||||||
|
|
||||||
message.Write(speed.X);
|
message.Write(Speed.X);
|
||||||
message.Write(speed.Y);
|
message.Write(Speed.Y);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -630,14 +403,13 @@ namespace Subsurface
|
|||||||
|
|
||||||
//newTargetPosition = newTargetPosition + newSpeed * (float)(NetTime.Now - sendingTime);
|
//newTargetPosition = newTargetPosition + newSpeed * (float)(NetTime.Now - sendingTime);
|
||||||
|
|
||||||
targetPosition = newTargetPosition;
|
subBody.TargetPosition = newTargetPosition;
|
||||||
speed = newSpeed;
|
subBody.Speed = newSpeed;
|
||||||
|
|
||||||
lastNetworkUpdate = sendingTime;
|
lastNetworkUpdate = sendingTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//saving/loading ----------------------------------------------------
|
//saving/loading ----------------------------------------------------
|
||||||
|
|
||||||
public void Save()
|
public void Save()
|
||||||
@@ -829,42 +601,7 @@ namespace Subsurface
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Vector2> convexHull = GenerateConvexHull();
|
subBody = new SubmarineBody(this);
|
||||||
|
|
||||||
HullVertices = convexHull;
|
|
||||||
|
|
||||||
for (int i = 0; i < convexHull.Count; i++)
|
|
||||||
{
|
|
||||||
convexHull[i] = ConvertUnits.ToSimUnits(convexHull[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
convexHull.Reverse();
|
|
||||||
|
|
||||||
//get farseer 'vertices' from vectors
|
|
||||||
Vertices shapevertices = new Vertices(convexHull);
|
|
||||||
|
|
||||||
AABB hullAABB = shapevertices.GetAABB();
|
|
||||||
|
|
||||||
borders = new Rectangle(
|
|
||||||
(int)ConvertUnits.ToDisplayUnits(hullAABB.LowerBound.X),
|
|
||||||
(int)ConvertUnits.ToDisplayUnits(hullAABB.UpperBound.Y),
|
|
||||||
(int)ConvertUnits.ToDisplayUnits(hullAABB.Extents.X * 2.0f),
|
|
||||||
(int)ConvertUnits.ToDisplayUnits(hullAABB.Extents.Y * 2.0f));
|
|
||||||
|
|
||||||
|
|
||||||
var triangulatedVertices = Triangulate.ConvexPartition(shapevertices, TriangulationAlgorithm.Bayazit);
|
|
||||||
|
|
||||||
hullBody = BodyFactory.CreateCompoundPolygon(GameMain.World, triangulatedVertices, 5.0f);
|
|
||||||
hullBody.BodyType = BodyType.Dynamic;
|
|
||||||
|
|
||||||
hullBody.CollisionCategories = Physics.CollisionMisc;
|
|
||||||
hullBody.CollidesWith = Physics.CollisionLevel;
|
|
||||||
hullBody.FixedRotation = true;
|
|
||||||
hullBody.Awake = true;
|
|
||||||
hullBody.SleepingAllowed = false;
|
|
||||||
hullBody.GravityScale = 0.0f;
|
|
||||||
hullBody.OnCollision += OnCollision;
|
|
||||||
hullBody.OnSeparation += OnSeparation;
|
|
||||||
|
|
||||||
MapEntity.LinkAll();
|
MapEntity.LinkAll();
|
||||||
|
|
||||||
@@ -908,6 +645,8 @@ namespace Subsurface
|
|||||||
{
|
{
|
||||||
if (GameMain.GameScreen.Cam != null) GameMain.GameScreen.Cam.TargetPos = Vector2.Zero;
|
if (GameMain.GameScreen.Cam != null) GameMain.GameScreen.Cam.TargetPos = Vector2.Zero;
|
||||||
|
|
||||||
|
subBody = null;
|
||||||
|
|
||||||
Entity.RemoveAll();
|
Entity.RemoveAll();
|
||||||
|
|
||||||
PhysicsBody.list.Clear();
|
PhysicsBody.list.Clear();
|
||||||
|
|||||||
@@ -0,0 +1,318 @@
|
|||||||
|
using FarseerPhysics;
|
||||||
|
using FarseerPhysics.Collision;
|
||||||
|
using FarseerPhysics.Common;
|
||||||
|
using FarseerPhysics.Common.Decomposition;
|
||||||
|
using FarseerPhysics.Dynamics;
|
||||||
|
using FarseerPhysics.Dynamics.Contacts;
|
||||||
|
using FarseerPhysics.Factories;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Voronoi2;
|
||||||
|
|
||||||
|
namespace Subsurface
|
||||||
|
{
|
||||||
|
class SubmarineBody
|
||||||
|
{
|
||||||
|
|
||||||
|
public List<Vector2> HullVertices
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Submarine sub;
|
||||||
|
|
||||||
|
private Body body;
|
||||||
|
|
||||||
|
private Vector2 speed;
|
||||||
|
|
||||||
|
private Vector2 targetPosition;
|
||||||
|
|
||||||
|
public Rectangle Borders
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector2 Speed
|
||||||
|
{
|
||||||
|
get { return speed; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (!MathUtils.IsValid(value)) return;
|
||||||
|
speed = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector2 TargetPosition
|
||||||
|
{
|
||||||
|
get { return targetPosition; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (!MathUtils.IsValid(value)) return;
|
||||||
|
targetPosition = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Vector2 Center
|
||||||
|
{
|
||||||
|
get { return new Vector2(Borders.X + Borders.Width / 2, Borders.Y - Borders.Height / 2); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public SubmarineBody(Submarine sub)
|
||||||
|
{
|
||||||
|
this.sub = sub;
|
||||||
|
|
||||||
|
|
||||||
|
List<Vector2> convexHull = GenerateConvexHull();
|
||||||
|
HullVertices = convexHull;
|
||||||
|
|
||||||
|
for (int i = 0; i < convexHull.Count; i++)
|
||||||
|
{
|
||||||
|
convexHull[i] = ConvertUnits.ToSimUnits(convexHull[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
convexHull.Reverse();
|
||||||
|
|
||||||
|
//get farseer 'vertices' from vectors
|
||||||
|
Vertices shapevertices = new Vertices(convexHull);
|
||||||
|
|
||||||
|
AABB hullAABB = shapevertices.GetAABB();
|
||||||
|
|
||||||
|
Borders = new Rectangle(
|
||||||
|
(int)ConvertUnits.ToDisplayUnits(hullAABB.LowerBound.X),
|
||||||
|
(int)ConvertUnits.ToDisplayUnits(hullAABB.UpperBound.Y),
|
||||||
|
(int)ConvertUnits.ToDisplayUnits(hullAABB.Extents.X * 2.0f),
|
||||||
|
(int)ConvertUnits.ToDisplayUnits(hullAABB.Extents.Y * 2.0f));
|
||||||
|
|
||||||
|
|
||||||
|
var triangulatedVertices = Triangulate.ConvexPartition(shapevertices, TriangulationAlgorithm.Bayazit);
|
||||||
|
|
||||||
|
body = BodyFactory.CreateCompoundPolygon(GameMain.World, triangulatedVertices, 5.0f);
|
||||||
|
body.BodyType = BodyType.Dynamic;
|
||||||
|
|
||||||
|
body.CollisionCategories = Physics.CollisionMisc;
|
||||||
|
body.CollidesWith = Physics.CollisionLevel;
|
||||||
|
body.FixedRotation = true;
|
||||||
|
body.Awake = true;
|
||||||
|
body.SleepingAllowed = false;
|
||||||
|
body.GravityScale = 0.0f;
|
||||||
|
body.OnCollision += OnCollision;
|
||||||
|
body.OnSeparation += OnSeparation;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private List<Vector2> GenerateConvexHull()
|
||||||
|
{
|
||||||
|
List<Vector2> points = new List<Vector2>();
|
||||||
|
|
||||||
|
Vector2 leftMost = Vector2.Zero;
|
||||||
|
|
||||||
|
foreach (Structure wall in Structure.wallList)
|
||||||
|
{
|
||||||
|
for (int x = -1; x <= 1; x += 2)
|
||||||
|
{
|
||||||
|
for (int y = -1; y <= 1; y += 2)
|
||||||
|
{
|
||||||
|
Vector2 corner = new Vector2(wall.Rect.X + wall.Rect.Width / 2.0f, wall.Rect.Y - wall.Rect.Height / 2.0f);
|
||||||
|
corner.X += x * wall.Rect.Width / 2.0f;
|
||||||
|
corner.Y += y * wall.Rect.Height / 2.0f;
|
||||||
|
|
||||||
|
if (points.Contains(corner)) continue;
|
||||||
|
|
||||||
|
points.Add(corner);
|
||||||
|
if (leftMost == Vector2.Zero || corner.X < leftMost.X) leftMost = corner;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Vector2> hullPoints = new List<Vector2>();
|
||||||
|
|
||||||
|
Vector2 currPoint = leftMost;
|
||||||
|
Vector2 endPoint;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
hullPoints.Add(currPoint);
|
||||||
|
endPoint = points[0];
|
||||||
|
|
||||||
|
for (int i = 1; i < points.Count; i++)
|
||||||
|
{
|
||||||
|
if ((currPoint == endPoint)
|
||||||
|
|| (MathUtils.VectorOrientation(currPoint, endPoint, points[i]) == -1))
|
||||||
|
{
|
||||||
|
endPoint = points[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
currPoint = endPoint;
|
||||||
|
|
||||||
|
}
|
||||||
|
while (endPoint != hullPoints[0]);
|
||||||
|
|
||||||
|
return hullPoints;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float collisionRigidness = 1.0f;
|
||||||
|
|
||||||
|
public void Update(float deltaTime)
|
||||||
|
{
|
||||||
|
Vector2 translateAmount = speed * deltaTime;
|
||||||
|
translateAmount += ConvertUnits.ToDisplayUnits(body.Position) * collisionRigidness;
|
||||||
|
|
||||||
|
if (targetPosition != Vector2.Zero && Vector2.Distance(targetPosition, sub.Position) > 50.0f)
|
||||||
|
{
|
||||||
|
translateAmount += (targetPosition - sub.Position) * 0.01f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
targetPosition = Vector2.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub.Translate(translateAmount);
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
|
Vector2 totalForce = CalculateBuoyancy();
|
||||||
|
|
||||||
|
float dragCoefficient = 0.00001f;
|
||||||
|
|
||||||
|
float speedLength = (speed == Vector2.Zero) ? 0.0f : speed.Length();
|
||||||
|
float drag = speedLength * speedLength * dragCoefficient * mass;
|
||||||
|
|
||||||
|
if (speed != Vector2.Zero)
|
||||||
|
{
|
||||||
|
totalForce += -Vector2.Normalize(speed) * drag;
|
||||||
|
}
|
||||||
|
|
||||||
|
ApplyForce(totalForce);
|
||||||
|
|
||||||
|
//hullBodies[0].body.LinearVelocity = -hullBodies[0].body.Position;
|
||||||
|
|
||||||
|
//hullBody.SetTransform(Vector2.Zero , 0.0f);
|
||||||
|
body.LinearVelocity = -body.Position / (float)Physics.step;
|
||||||
|
|
||||||
|
if (collidingCell == null)
|
||||||
|
{
|
||||||
|
collisionRigidness = MathHelper.Lerp(collisionRigidness, 1.0f, 0.1f);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (GraphEdge ge in collidingCell.edges)
|
||||||
|
{
|
||||||
|
Body wallBody = Submarine.PickBody(
|
||||||
|
ConvertUnits.ToSimUnits(ge.point1 + GameMain.GameSession.Level.Position),
|
||||||
|
ConvertUnits.ToSimUnits(ge.point2 + GameMain.GameSession.Level.Position), new List<Body>() { collidingCell.body });
|
||||||
|
if (wallBody == null || wallBody.UserData == null) continue;
|
||||||
|
|
||||||
|
Structure structure = wallBody.UserData as Structure;
|
||||||
|
if (structure == null) continue;
|
||||||
|
structure.AddDamage(
|
||||||
|
structure.FindSectionIndex(ConvertUnits.ToDisplayUnits(Submarine.LastPickedPosition)), 50.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
collidingCell = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Vector2 CalculateBuoyancy()
|
||||||
|
{
|
||||||
|
float waterVolume = 0.0f;
|
||||||
|
float volume = 0.0f;
|
||||||
|
foreach (Hull hull in Hull.hullList)
|
||||||
|
{
|
||||||
|
waterVolume += hull.Volume;
|
||||||
|
volume += hull.FullVolume;
|
||||||
|
}
|
||||||
|
|
||||||
|
float waterPercentage = waterVolume / volume;
|
||||||
|
|
||||||
|
float neutralPercentage = 0.07f;
|
||||||
|
|
||||||
|
float buoyancy = neutralPercentage - waterPercentage;
|
||||||
|
buoyancy *= mass * 30.0f;
|
||||||
|
|
||||||
|
return new Vector2(0.0f, buoyancy);
|
||||||
|
}
|
||||||
|
|
||||||
|
float mass = 10000.0f;
|
||||||
|
public void ApplyForce(Vector2 force)
|
||||||
|
{
|
||||||
|
speed += force / mass;
|
||||||
|
}
|
||||||
|
|
||||||
|
VoronoiCell collidingCell;
|
||||||
|
public bool OnCollision(Fixture f1, Fixture f2, Contact contact)
|
||||||
|
{
|
||||||
|
VoronoiCell cell = f2.Body.UserData as VoronoiCell;
|
||||||
|
if (cell == null)
|
||||||
|
{
|
||||||
|
speed = new Vector2(speed.X * 0.9f, speed.Y * 0.2f);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2 normal = contact.Manifold.LocalNormal;
|
||||||
|
Vector2 simSpeed = ConvertUnits.ToSimUnits(speed);
|
||||||
|
float impact = Vector2.Dot(simSpeed, normal);
|
||||||
|
|
||||||
|
Vector2 u = Vector2.Dot(simSpeed, -normal) * -normal;
|
||||||
|
Vector2 w = simSpeed - u;
|
||||||
|
|
||||||
|
Vector2 limbForce = normal * impact;
|
||||||
|
|
||||||
|
float length = limbForce.Length();
|
||||||
|
if (length > 10.0f) limbForce = (limbForce / length) * 10.0f;
|
||||||
|
|
||||||
|
foreach (Character c in Character.CharacterList)
|
||||||
|
{
|
||||||
|
if (c.AnimController.CurrentHull == null) continue;
|
||||||
|
|
||||||
|
if (impact > 2.0f) c.AnimController.StunTimer = (impact - 2.0f) * 0.1f;
|
||||||
|
|
||||||
|
foreach (Limb limb in c.AnimController.Limbs)
|
||||||
|
{
|
||||||
|
if (c.AnimController.LowestLimb == limb) continue;
|
||||||
|
limb.body.ApplyLinearImpulse(limb.Mass * limbForce);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (impact >= 1.0f)
|
||||||
|
{
|
||||||
|
AmbientSoundManager.PlayDamageSound(DamageSoundType.StructureBlunt, impact * 10.0f, cell.body);
|
||||||
|
|
||||||
|
FarseerPhysics.Common.FixedArray2<Vector2> worldPoints;
|
||||||
|
contact.GetWorldManifold(out normal, out worldPoints);
|
||||||
|
|
||||||
|
AmbientSoundManager.PlayDamageSound(DamageSoundType.StructureBlunt, impact * 10.0f, ConvertUnits.ToDisplayUnits(worldPoints[0]));
|
||||||
|
|
||||||
|
GameMain.GameScreen.Cam.Shake = impact * 2.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
System.Diagnostics.Debug.WriteLine("IMPACT: " + impact + " normal: " + normal + " simspeed: " + simSpeed + " u: " + u + " w: " + w);
|
||||||
|
if (impact < 4.0f)
|
||||||
|
{
|
||||||
|
speed = ConvertUnits.ToDisplayUnits(w * 0.9f - u * 0.2f);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
speed = ConvertUnits.ToDisplayUnits(w * 0.9f + u * 0.5f);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
collisionRigidness = 0.8f;
|
||||||
|
|
||||||
|
collidingCell = cell;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnSeparation(Fixture f1, Fixture f2)
|
||||||
|
{
|
||||||
|
collidingCell = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -98,7 +98,10 @@ namespace Subsurface
|
|||||||
|
|
||||||
Ragdoll.UpdateAll((float)Physics.step);
|
Ragdoll.UpdateAll((float)Physics.step);
|
||||||
|
|
||||||
if (GameMain.GameSession != null && GameMain.GameSession.Level != null) GameMain.GameSession.Submarine.Update((float)Physics.step);
|
if (GameMain.GameSession != null && GameMain.GameSession.Level != null)
|
||||||
|
{
|
||||||
|
GameMain.GameSession.Submarine.Update((float)Physics.step);
|
||||||
|
}
|
||||||
|
|
||||||
GameMain.World.Step((float)Physics.step);
|
GameMain.World.Step((float)Physics.step);
|
||||||
|
|
||||||
|
|||||||
@@ -55,8 +55,8 @@ namespace Subsurface
|
|||||||
|
|
||||||
private const float MusicLerpSpeed = 0.01f;
|
private const float MusicLerpSpeed = 0.01f;
|
||||||
|
|
||||||
private static Sound waterAmbience;
|
private static Sound[] waterAmbiences = new Sound[2];
|
||||||
private static int waterAmbienceIndex;
|
private static int[] waterAmbienceIndexes = new int[2];
|
||||||
|
|
||||||
private static DamageSound[] damageSounds;
|
private static DamageSound[] damageSounds;
|
||||||
|
|
||||||
@@ -78,7 +78,9 @@ namespace Subsurface
|
|||||||
yield return CoroutineStatus.Running;
|
yield return CoroutineStatus.Running;
|
||||||
|
|
||||||
|
|
||||||
waterAmbience = Sound.Load("Content/Sounds/Water/WaterAmbience.ogg");
|
waterAmbiences[0] = Sound.Load("Content/Sounds/Water/WaterAmbience1.ogg");
|
||||||
|
yield return CoroutineStatus.Running;
|
||||||
|
waterAmbiences[1] = Sound.Load("Content/Sounds/Water/WaterAmbience2.ogg");
|
||||||
yield return CoroutineStatus.Running;
|
yield return CoroutineStatus.Running;
|
||||||
flowSounds[0] = Sound.Load("Content/Sounds/Water/FlowSmall.ogg");
|
flowSounds[0] = Sound.Load("Content/Sounds/Water/FlowSmall.ogg");
|
||||||
yield return CoroutineStatus.Running;
|
yield return CoroutineStatus.Running;
|
||||||
@@ -162,22 +164,33 @@ namespace Subsurface
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float ambienceVolume = 0.5f;
|
float ambienceVolume = 0.6f;
|
||||||
float lowpassHFGain = 1.0f;
|
float lowpassHFGain = 1.0f;
|
||||||
if (Character.Controlled != null)
|
if (Character.Controlled != null)
|
||||||
{
|
{
|
||||||
AnimController animController = Character.Controlled.AnimController;
|
AnimController animController = Character.Controlled.AnimController;
|
||||||
if (animController.HeadInWater)
|
if (animController.HeadInWater)
|
||||||
{
|
{
|
||||||
ambienceVolume = 0.5f;
|
ambienceVolume = 0.8f;
|
||||||
ambienceVolume += animController.Limbs[0].LinearVelocity.Length();
|
ambienceVolume += animController.Limbs[0].LinearVelocity.Length();
|
||||||
|
|
||||||
lowpassHFGain = 0.2f;
|
lowpassHFGain = 0.2f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//how fast the sub is moving, scaled to 0.0 -> 1.0
|
||||||
|
float movementFactor = 0.0f;
|
||||||
|
if (Submarine.Loaded!=null)
|
||||||
|
{
|
||||||
|
movementFactor = (Submarine.Loaded.Speed == Vector2.Zero) ? 0.0f : Submarine.Loaded.Speed.Length() / 500.0f;
|
||||||
|
|
||||||
|
movementFactor = MathHelper.Clamp(movementFactor, 0.0f, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
SoundManager.LowPassHFGain = lowpassHFGain;
|
SoundManager.LowPassHFGain = lowpassHFGain;
|
||||||
waterAmbienceIndex = waterAmbience.Loop(waterAmbienceIndex, ambienceVolume);
|
waterAmbienceIndexes[0] = waterAmbiences[0].Loop(waterAmbienceIndexes[0], ambienceVolume * (1.0f-movementFactor));
|
||||||
|
waterAmbienceIndexes[1] = waterAmbiences[1].Loop(waterAmbienceIndexes[1], ambienceVolume * movementFactor);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void UpdateMusic()
|
private static void UpdateMusic()
|
||||||
|
|||||||
@@ -37,6 +37,21 @@ namespace Subsurface
|
|||||||
return (IsValid(vector.X) && IsValid(vector.Y));
|
return (IsValid(vector.X) && IsValid(vector.Y));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static int VectorOrientation(Vector2 p1, Vector2 p2, Vector2 p)
|
||||||
|
{
|
||||||
|
// Determinant
|
||||||
|
float Orin = (p2.X - p1.X) * (p.Y - p1.Y) - (p.X - p1.X) * (p2.Y - p1.Y);
|
||||||
|
|
||||||
|
if (Orin > 0)
|
||||||
|
return -1; // (* Orientation is to the left-hand side *)
|
||||||
|
if (Orin < 0)
|
||||||
|
return 1; // (* Orientation is to the right-hand side *)
|
||||||
|
|
||||||
|
return 0; // (* Orientation is neutral aka collinear *)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static float CurveAngle(float from, float to, float step)
|
public static float CurveAngle(float from, float to, float step)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|||||||
@@ -94,6 +94,7 @@
|
|||||||
<Compile Include="Source\Items\FixRequirement.cs" />
|
<Compile Include="Source\Items\FixRequirement.cs" />
|
||||||
<Compile Include="Source\Map\Lights\LightSource.cs" />
|
<Compile Include="Source\Map\Lights\LightSource.cs" />
|
||||||
<Compile Include="Source\Map\LocationType.cs" />
|
<Compile Include="Source\Map\LocationType.cs" />
|
||||||
|
<Compile Include="Source\Map\SubmarineHull.cs" />
|
||||||
<Compile Include="Source\Networking\NetConfig.cs" />
|
<Compile Include="Source\Networking\NetConfig.cs" />
|
||||||
<Compile Include="Source\Particles\ParticleEmitter.cs" />
|
<Compile Include="Source\Particles\ParticleEmitter.cs" />
|
||||||
<Compile Include="Source\Screens\ServerListScreen.cs" />
|
<Compile Include="Source\Screens\ServerListScreen.cs" />
|
||||||
@@ -682,7 +683,7 @@
|
|||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
<Content Include="Content\Map\testroom.png">
|
<Content Include="Content\Map\testroom.png">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
<Content Include="Content\Map\StructurePrefabs.xml">
|
<Content Include="Content\Map\StructurePrefabs.xml">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
@@ -706,6 +707,7 @@
|
|||||||
</Content>
|
</Content>
|
||||||
<Content Include="Content\Sounds\sounds.xml">
|
<Content Include="Content\Sounds\sounds.xml">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
<SubType>Designer</SubType>
|
||||||
</Content>
|
</Content>
|
||||||
<Content Include="Content\UI\titleBackground.png">
|
<Content Include="Content\UI\titleBackground.png">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
@@ -943,13 +945,16 @@
|
|||||||
<None Include="Content\Sounds\startDrone.ogg">
|
<None Include="Content\Sounds\startDrone.ogg">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
|
<None Include="Content\Sounds\Water\WaterAmbience2.ogg">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
<None Include="Content\SpriteFont1.xnb">
|
<None Include="Content\SpriteFont1.xnb">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
<None Include="Content\step.ogg">
|
<None Include="Content\step.ogg">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
<None Include="Content\Sounds\Water\WaterAmbience.ogg">
|
<None Include="Content\Sounds\Water\WaterAmbience1.ogg">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
<None Include="Content\watershader.mgfx">
|
<None Include="Content\watershader.mgfx">
|
||||||
|
|||||||
Binary file not shown.
Reference in New Issue
Block a user