Loaded sounds are properly freed, ObjectProperty optimization, expanded skill effects (rangedweapon accuracy, welding efficiency, electrical shocks), armored wearables + ballistic vest & helmet

This commit is contained in:
Regalis
2015-09-28 19:48:31 +03:00
parent 97c3ac1412
commit cc16bb3ad7
34 changed files with 411 additions and 183 deletions

View File

@@ -14,17 +14,17 @@
flip="true">
<!-- head -->
<limb id = "0" radius="22" height="45" mass = "6" type="Head" flip="true" steerforce="1.0" armorsector="0.0,180.0" armorvalue="5.0f">
<limb id = "0" radius="22" height="45" mass = "6" type="Head" flip="true" steerforce="1.0" armorsector="0.0,180.0" armorvalue="30.0">
<sprite texture="Content/Characters/Crawler/crawler.png" sourcerect="0,0,51,121" depth="0.02" origin="0.45,0.63"/>
</limb>
<!-- middle part -->
<limb id = "1" width="36" height="40" mass = "6" flip="true" armorsector="0.0,180.0" armorvalue="5.0f">
<limb id = "1" width="36" height="40" mass = "6" flip="true" armorsector="0.0,180.0" armorvalue="20.0">
<sprite texture="Content/Characters/Crawler/crawler.png" sourcerect="57,7,59,57" depth="0.021" origin="0.3,0.65"/>
</limb>
<!-- tail -->
<limb id = "2" width="41" height="63" mass = "6" type="Tail" flip="true" armorsector="0.0,180.0" armorvalue="5.0f">
<limb id = "2" width="41" height="63" mass = "6" type="Tail" flip="true" armorsector="0.0,180.0" armorvalue="20.0">
<sprite texture="Content/Characters/Crawler/crawler.png" sourcerect="6,141,60,95" depth="0.022" origin="0.37,0.43"/>
</limb>

View File

@@ -16,22 +16,22 @@
flip="true">
<!-- head -->
<limb id = "0" radius="30" height="86" mass = "6" type="Head" flip="true" steerforce="1.0" armorsector="0.0,180.0" armorvalue="5.0f">
<limb id = "0" radius="30" height="86" mass = "6" type="Head" flip="true" steerforce="1.0" armorsector="0.0,180.0" armorvalue="10.0">
<sprite texture="Content/Characters/Mantis/mantis.png" sourcerect="0,0,101,168" depth="0.02" origin="0.4,0.53"/>
</limb>
<!-- middle part -->
<limb id = "1" width="42" height="61" mass = "6" flip="true" armorsector="0.0,180.0" armorvalue="5.0f">
<limb id = "1" width="42" height="61" mass = "6" flip="true" armorsector="0.0,180.0" armorvalue="10.0">
<sprite texture="Content/Characters/Mantis/mantis.png" sourcerect="3,168,59,64" depth="0.021" origin="0.3,0.65"/>
</limb>
<!-- middle part -->
<limb id = "2" width="35" height="52" mass = "6" flip="true" armorsector="0.0,180.0" armorvalue="5.0f">
<limb id = "2" width="35" height="52" mass = "6" flip="true" armorsector="0.0,180.0" armorvalue="10.0">
<sprite texture="Content/Characters/Mantis/mantis.png" sourcerect="66,180,65,70" depth="0.022" origin="0.3,0.65"/>
</limb>
<!-- tail -->
<limb id = "3" radius="20" mass = "6" type="Tail" flip="true" armorsector="0.0,180.0" armorvalue="5.0f">
<limb id = "3" radius="20" mass = "6" type="Tail" flip="true" armorsector="0.0,180.0" armorvalue="10.0">
<sprite texture="Content/Characters/Mantis/mantis.png" sourcerect="130,158,46,93" depth="0.023" origin="0.37,0.3"/>
</limb>
@@ -44,7 +44,7 @@
<sound file ="Content/Sounds/stepMetal.ogg"/>
</limb>
<!-- ""claw" -->
<limb id = "6" width="15" height="63" mass = "4" flip="true" pullpos="0.0,30.0" frefjoint="0">
<limb id = "6" width="15" height="63" mass = "4" flip="true" pullpos="0.0,30.0" refjoint="0">
<sprite texture="Content/Characters/Mantis/mantis.png" sourcerect="228,1,28,76" depth="0.01" origin="0.5,0.5"/>
<attack type="PinchCW" range="120" duration="0.5" damage="30" stun="0.1" bleedingdamage="5" structuredamage="50" damagetype="slash"/>
<sound file ="Content/Sounds/stepMetal.ogg"/>

View File

@@ -9,7 +9,7 @@
<ragdoll waveamplitude="0.0" swimspeed="1.0" walkspeed="0.3" flip="true" rotatetowardsmovement="false" headangle="-90">
<!-- head -->
<limb id = "0" radius="230" height="500" type="Head" steerforce="1.0" flip="true" armorsector="0.0,180.0" armorvalue="10.0f">
<limb id = "0" radius="230" height="500" type="Head" steerforce="1.0" flip="true" armorsector="0.0,180.0" armorvalue="100.0">
<sprite texture="Content/Characters/Moloch/moloch.png" sourcerect="0,0,628,1024" depth="0.02" origin ="0.4,0.5"/>
</limb>

View File

@@ -52,5 +52,35 @@
</Wearable>
</Item>
<Item
name="Body Armour"
pickdistance="150"
tags="smallitem">
<Sprite texture ="securitygear.png" sourcerect="68,0,60,31" depth="0.4"/>
<Body width="52" height="17"/>
<Wearable slots="Any,Torso" armorvalue="10.0">
<sprite texture="securitygear.png" limb="Torso" sourcerect="0,0,38,58" origin="0.47,0.48"/>
<sprite texture="securitygear.png" limb="RightArm" sourcerect="41,0,21,21" origin="0.5,1.1"/>
</Wearable>
</Item>
<Item
name="Ballistic Helmet"
pickdistance="150"
tags="smallitem">
<Sprite texture ="securitygear.png" sourcerect="40,32,34,25" depth="0.4"/>
<Body radius="12"/>
<Wearable slots="Any,Head" armorvalue="20.0">
<sprite texture="securitygear.png" limb="Head" sourcerect="39,31,29,22" origin="0.5,1.5"/>
</Wearable>
</Item>
</Items>

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -46,7 +46,7 @@
<Body width="37" height="113" density="5"/>
<Wearable slots="Head,Torso,Legs">
<Wearable slots="Head,Torso,Legs" armorvalue="10.0">
<sprite texture="DivingSuit.png" limb="Torso" sourcerect="40,0,42,97" origin="0.5,0.55" depthlimb="Head" hidelimb="true"/>
<sprite texture="DivingSuit.png" limb="RightHand" sourcerect="0,78,15,50" origin="0.45,0.4" hidelimb="true"/>

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="utf-8" ?>
<Items>
<Item
name="Junction Box"
linkable="true"
pickdistance="150">
<Sprite texture ="junctionbox.png" depth="0.8"/>
<Item
name="Junction Box"
linkable="true"
pickdistance="150">
<Sprite texture ="junctionbox.png" depth="0.8"/>
<fixrequirement name="Electrical repairs">
<skill name="Electrical Engineering" level="40"/>
@@ -17,33 +17,41 @@
<GuiFrame rect="0,0,0.3,0.3" alignment="Center" color="0.0,0.0,0.0,0.8"/>
</PowerTransfer>
<ConnectionPanel canbeselected = "true" msg="Rewire [Screwdriver]">
<requireditem name="Screwdriver" type="Equipped"/>
<output name="power"/>
<ConnectionPanel canbeselected = "true" msg="Rewire [Screwdriver]">
<RequiredSkill name="Electrical Engineering" level="30"/>
<StatusEffect type="OnFailure" target="Character">
<Explosion range="100.0" damage="5" stun="10" force="2.0" flames="false" shockwave="false" sparks="true"/>
</StatusEffect>
<requireditem name="Screwdriver" type="Equipped"/>
<output name="power"/>
<output name="signal_0"/>
<output name="signal_1"/>
<output name="signal_2"/>
<output name="signal_3"/>
</ConnectionPanel>
</Item>
</Item>
<Item
name="Battery"
linkable="true"
pickdistance="150">
<Item
name="Battery"
linkable="true"
pickdistance="150">
<Sprite texture ="battery.png" depth="0.8"/>
<Sprite texture ="battery.png" depth="0.8"/>
<PowerContainer capacity="2000.0" maxrechargespeed="500.0" maxoutput="1000.0" canbeselected = "true">
<GuiFrame rect="0,0,0.3,0.3" alignment="Center" color="0.0,0.0,0.0,0.8"/>
</PowerContainer>
<ConnectionPanel canbeselected = "true" msg="Rewire [Screwdriver]">
<requireditem name="Screwdriver" type="Equipped"/>
<input name="power"/>
</ConnectionPanel>
</Item>
<ConnectionPanel canbeselected = "true" msg="Rewire [Screwdriver]">
<StatusEffect type="OnFailure" target="Character">
<Explosion range="100.0" damage="15" stun="10" force="3.0" flames="false" shockwave="false" sparks="true"/>
</StatusEffect>
<requireditem name="Screwdriver" type="Equipped"/>
<input name="power"/>
</ConnectionPanel>
</Item>
<Item
name="Supercapacitor"
@@ -57,11 +65,11 @@
</PowerContainer>
<ConnectionPanel canbeselected = "true" msg="Rewire [Screwdriver]">
<StatusEffect type="OnFailure" target="Character">
<Explosion range="100.0" damage="30" stun="20" force="5.0" shockwave="false" sparks="true"/>
</StatusEffect>
<requireditem name="Screwdriver" type="Equipped"/>
<input name="power"/>
</ConnectionPanel>
</Item>
</Items>

View File

@@ -32,10 +32,7 @@
<!-- construction skill 20 required to use the item -->
<RequiredSkill name="Construction" level="20"/>
<!-- 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">
<Explosion range="500" damage="20" stun="10" force="5.0"/>
</StatusEffect>
<StatusEffect type="OnFailure" target="Contained" targetnames="Welding Fuel Tank,Oxygen Tank" Condition="-3.0"/>
<LightComponent color="1.0,0.9,0.7,1.0" Flicker="0.5">
<sprite texture="Content/Items/Electricity/lightsprite.png" origin="0.5,0.5"/>
@@ -73,9 +70,7 @@
<RequiredSkill name="Construction" level="30"/>
<StatusEffect type="OnFailure" target="Contained" targetnames="Welding Fuel Tank,Oxygen Tank" Condition="-100.0" sound="Content/Items/Weapons/stunGrenade.ogg">
<Explosion range="500" damage="20" stun="10" force="5.0"/>
</StatusEffect>
<StatusEffect type="OnFailure" target="Contained" targetnames="Welding Fuel Tank,Oxygen Tank" Condition="-3.0"/>
<LightComponent color="0.1,0.8,1.0,1.0" Flicker="0.5">
<sprite texture="Content/Items/Electricity/lightsprite.png" origin="0.5,0.5"/>

View File

@@ -1,18 +1,18 @@
<prefabs>
<largehorizontalback sprite="Content/Map/testroom.png" sourcerect="0,0,896,64" depth ="0.4"
<largehorizontalback sprite="Content/Map/testroom.png" sourcerect="0,0,896,64" depth ="0.9"
width = "128" height ="64" resizehorizontal="true"/>
<smallhorizontalback sprite="Content/Map/testroom.png" sourcerect="0,64,896,32" depth ="0.4"
<smallhorizontalback sprite="Content/Map/testroom.png" sourcerect="0,64,896,32" depth ="0.9"
width = "128" height ="32" resizehorizontal="true"/>
<largeverticalback sprite="Content/Map/testroom.png" sourcerect="0,96,64,448" depth ="0.4"
<largeverticalback sprite="Content/Map/testroom.png" sourcerect="0,96,64,448" depth ="0.9"
width = "64" height ="128" resizevertical="true"/>
<largeverticalback2 sprite="Content/Map/testroom.png" sourcerect="64,96,64,448" depth ="0.4"
<largeverticalback2 sprite="Content/Map/testroom.png" sourcerect="64,96,64,448" depth ="0.9"
width = "64" height ="128" resizevertical="true"/>
<smallverticalback sprite="Content/Map/testroom.png" sourcerect="128,96,32,352" depth ="0.85"
<smallverticalback sprite="Content/Map/testroom.png" sourcerect="128,96,32,352" depth ="0.9"
width = "32" height ="128" resizevertical="true"/>
<smallverticalback2 sprite="Content/Map/testroom.png" sourcerect="160,96,32,352" depth ="0.85"
<smallverticalback2 sprite="Content/Map/testroom.png" sourcerect="160,96,32,352" depth ="0.9"
width = "32" height ="128" resizevertical="true"/>
<engineeringLabel sprite="Content/Map/testroom.png" sourcerect="464,336,153,16" depth ="0.99"
@@ -45,10 +45,10 @@
<rightwall sprite="Content/Map/testroom.png" sourcerect="688,368,32,496" depth ="0.05" castshadow="true"
width = "32" height ="64" resizevertical="true" body="true" health="500"/>
<topwall sprite="Content/Map/testroom.png" sourcerect="144,464,496,32" depth ="0.05" castshadow="true"
<topwall sprite="Content/Map/testroom.png" sourcerect="144,464,496,32" depth ="0.06" castshadow="true"
width = "64" height ="32" resizehorizontal="true" body="true" health="500"/>
<bottomwall sprite="Content/Map/testroom.png" flipvertical ="true" sourcerect="144,496,640,32" depth ="0.05" castshadow="true"
<bottomwall sprite="Content/Map/testroom.png" flipvertical ="true" sourcerect="144,496,640,32" depth ="0.06" castshadow="true"
width = "64" height ="32" resizehorizontal="true" body="true" health="500"/>
<topwindow sprite="Content/Map/testroom.png" sourcerect="208,352,128,80" depth ="0.05"

View File

@@ -18,4 +18,11 @@
commonness="10"
difficulty="50"
musictype="monster"/>
<MonsterEvent name="Under attack" description=""
characterfile="Content/Characters/Mantis/mantis.xml"
commonness="10"
difficulty="25"
minamount="1" maxamount="2"
musictype="monster"/>
</Randomevents>

View File

@@ -15,6 +15,7 @@ using System.Xml.Linq;
namespace Subsurface
{
class Character : Entity, IDamageable, IPropertyObject
{
public static List<Character> CharacterList = new List<Character>();
@@ -170,6 +171,12 @@ namespace Subsurface
}
}
public float Stun
{
get { return AnimController.StunTimer; }
set { StartStun(value); }
}
public float Health
{
get
@@ -873,8 +880,7 @@ namespace Subsurface
public AttackResult AddDamage(Vector2 simPosition, DamageType damageType, float amount, float bleedingAmount, float stun, bool playSound)
{
AnimController.StunTimer = Math.Max(AnimController.StunTimer, stun);
StartStun(stun);
if (controlled == this) CharacterHUD.TakeDamage();
Limb closestLimb = null;
@@ -901,14 +907,11 @@ namespace Subsurface
return attackResult;
}
public void Stun()
public void StartStun(float stunTimer)
{
//for (int i = 0; i < selectedItems.Length; i++ )
//{
// if (selectedItems[i] == null) continue;
// selectedItems[i].Drop();
// selectedItems[i] = null;
//}
if (stunTimer <= 0.0f) return;
AnimController.StunTimer = Math.Max(AnimController.StunTimer, stunTimer);
selectedConstruction = null;
}
@@ -1268,7 +1271,7 @@ namespace Subsurface
}
catch { return; }
AnimController.StunTimer = newStunTimer;
StartStun(newStunTimer);
Health = newHealth;
LargeUpdateTimer = 1;

View File

@@ -125,8 +125,7 @@ namespace Subsurface
//stun (= disable the animations) if the ragdoll receives a large enough impact
if (strongestImpact > 0.0f)
{
character.Stun();
stunTimer = MathHelper.Clamp(strongestImpact * 0.5f, stunTimer, 5.0f);
character.StartStun(MathHelper.Min(strongestImpact * 0.5f, 5.0f));
}
strongestImpact = 0.0f;

View File

@@ -62,7 +62,7 @@ namespace Subsurface
private Direction dir;
private Item wearingItem;
private Wearable wearingItem;
private WearableSprite wearingItemSprite;
private Vector2 animTargetPos;
@@ -92,6 +92,7 @@ namespace Subsurface
get { return body.Rotation; }
}
//where an animcontroller is trying to pull the limb, only used for debug visualization
public Vector2 AnimTargetPos
{
get { return animTargetPos; }
@@ -156,7 +157,7 @@ namespace Subsurface
// set { bleeding = MathHelper.Clamp(value, 0.0f, 100.0f); }
//}
public Item WearingItem
public Wearable WearingItem
{
get { return wearingItem; }
set { wearingItem = value; }
@@ -238,7 +239,7 @@ namespace Subsurface
armorSector.X = MathHelper.ToRadians(armorSector.X);
armorSector.Y = MathHelper.ToRadians(armorSector.Y);
armorValue = Math.Max(ToolBox.GetAttributeFloat(element, "armor", 1.0f), 1.0f);
armorValue = Math.Max(ToolBox.GetAttributeFloat(element, "armor", 0.0f), 0.0f);
body.BodyType = BodyType.Dynamic;
body.FarseerBody.AngularDamping = LimbAngularDamping;
@@ -290,27 +291,33 @@ namespace Subsurface
DamageSoundType damageSoundType = (damageType == DamageType.Blunt) ? DamageSoundType.LimbBlunt : DamageSoundType.LimbSlash;
bool hitArmor = false;
if (armorSector != Vector2.Zero)
float totalArmorValue = 0.0f;
if (armorValue>0.0f && SectorHit(armorSector, simPosition))
{
float rot = body.Rotation;
if (Dir == -1) rot -= MathHelper.Pi;
Vector2 armorLimits = new Vector2(rot-armorSector.X*Dir, rot-armorSector.Y*Dir);
float mid = (armorLimits.X + armorLimits.Y) / 2.0f;
float angleDiff = MathUtils.GetShortestAngle(MathUtils.VectorToAngle(simPosition - SimPosition), mid);
if (Math.Abs(angleDiff) < (armorSector.Y - armorSector.X) / 2.0f)
{
hitArmor = true;
damageSoundType = DamageSoundType.LimbArmor;
amount /= armorValue;
bleedingAmount /= armorValue;
}
hitArmor = true;
totalArmorValue += armorValue;
}
if (playSound && amount>0.0f)
if (wearingItem!=null &&
wearingItem.ArmorValue>0.0f &&
SectorHit(wearingItem.ArmorSectorLimits, simPosition))
{
hitArmor = true;
totalArmorValue += wearingItem.ArmorValue;
}
if (hitArmor)
{
totalArmorValue = Math.Max(totalArmorValue, 0.0f);
damageSoundType = DamageSoundType.LimbArmor;
amount = Math.Max(0.0f, amount - totalArmorValue);
bleedingAmount = Math.Max(0.0f, bleedingAmount - totalArmorValue); ;
}
if (playSound)
{
AmbientSoundManager.PlayDamageSound(damageSoundType, amount, ConvertUnits.ToDisplayUnits(simPosition));
}
@@ -338,6 +345,21 @@ namespace Subsurface
return new AttackResult(amount, bleedingAmount, hitArmor);
}
public bool SectorHit(Vector2 armorSector, Vector2 simPosition)
{
if (armorSector == Vector2.Zero) return false;
float rot = body.Rotation;
if (Dir == -1) rot -= MathHelper.Pi;
Vector2 armorLimits = new Vector2(rot - armorSector.X * Dir, rot - armorSector.Y * Dir);
float mid = (armorLimits.X + armorLimits.Y) / 2.0f;
float angleDiff = MathUtils.GetShortestAngle(MathUtils.VectorToAngle(simPosition - SimPosition), mid);
return (Math.Abs(angleDiff) < (armorSector.Y - armorSector.X) / 2.0f);
}
public void Update(float deltaTime)
{
if (LinearVelocity.X>100.0f)
@@ -416,7 +438,7 @@ namespace Subsurface
float depth = sprite.Depth - 0.000001f;
if (wearingItemSprite.DepthLimb==LimbType.None)
if (wearingItemSprite.DepthLimb!=LimbType.None)
{
Limb depthLimb = character.AnimController.GetLimb(wearingItemSprite.DepthLimb);
if (depthLimb!=null)

View File

@@ -228,6 +228,7 @@ namespace Subsurface
if (type == typeof(float))
{
float floatValue = (float)value * deltaTime;
if (!setValue) floatValue += (float)property.GetValue();
property.TrySetValue(floatValue);
}
@@ -253,7 +254,6 @@ namespace Subsurface
{
DelayedEffect.List[i].Update(deltaTime);
}
}
}
}
}

View File

@@ -49,7 +49,7 @@ namespace Subsurface
graphicsDevice = graphics;
sounds = new Sound[2];
sounds[0] = Sound.Load("Content/Sounds/UI/UImsg.ogg");
sounds[0] = Sound.Load("Content/Sounds/UI/UImsg.ogg", false);
// create 1x1 texture for line drawing
t = new Texture2D(graphicsDevice, 1, 1);

View File

@@ -138,7 +138,8 @@ namespace Subsurface
}
else if (GameMain.Client==null)
{
{
Submarine.Unload();
GameMain.LobbyScreen.Select();
}

View File

@@ -56,8 +56,6 @@ namespace Subsurface.Items.Components
if (!character.GetInputState(InputType.SecondaryHeld) || reload > 0.0f) return false;
isActive = true;
reload = 1.0f;
bool failed = DoesUseFail(character);
List<Body> limbBodies = new List<Body>();
foreach (Limb l in character.AnimController.Limbs)
@@ -68,6 +66,15 @@ namespace Subsurface.Items.Components
Item[] containedItems = item.ContainedItems;
if (containedItems == null || !containedItems.Any()) return false;
float degreeOfFailure = (100.0f - DegreeOfSuccess(character))/100.0f;
degreeOfFailure *= degreeOfFailure;
if (degreeOfFailure > Rand.Range(0.0f, 1.0f))
{
ApplyStatusEffects(ActionType.OnFailure, 1.0f, character);
}
foreach (Item projectile in containedItems)
{
if (projectile == null) continue;
@@ -76,35 +83,28 @@ namespace Subsurface.Items.Components
//so that the player can't shoot himself
Projectile projectileComponent= projectile.GetComponent<Projectile>();
if (projectileComponent == null) continue;
projectile.body.ResetDynamics();
projectile.SetTransform(TransformedBarrelPos,
(item.body.Dir == 1.0f) ? item.body.Rotation : item.body.Rotation - MathHelper.Pi);
((item.body.Dir == 1.0f) ? item.body.Rotation : item.body.Rotation - MathHelper.Pi)
+ Rand.Range(-degreeOfFailure, degreeOfFailure));
projectile.Use(deltaTime);
if (failed)
{
Vector2 modifiedVelocity = projectile.body.LinearVelocity;
modifiedVelocity.X *= Rand.Range(0.0f, 0.5f);
modifiedVelocity.Y *= Rand.Range(0.0f, 0.5f);
projectile.body.LinearVelocity = modifiedVelocity;
projectile.body.ApplyTorque(projectile.body.Mass * Rand.Range(-10.0f, 10.0f));
projectile.body.ApplyTorque(projectile.body.Mass * degreeOfFailure * Rand.Range(-10.0f, 10.0f));
//recoil
//item.body.ApplyLinearImpulse(
// new Vector2((float)Math.Cos(projectile.body.Rotation), (float)Math.Sin(projectile.body.Rotation)) * item.body.Mass * -10.0f);
}
else
{
item.body.ApplyLinearImpulse(
new Vector2((float)Math.Cos(projectile.body.Rotation), (float)Math.Sin(projectile.body.Rotation)) * item.body.Mass * -50.0f);
//else
//{
projectileComponent.ignoredBodies = limbBodies;
//recoil
//item.body.ApplyLinearImpulse(
// new Vector2((float)Math.Cos(projectile.body.Rotation), (float)Math.Sin(projectile.body.Rotation)) * -item.body.Mass);
}
//}
item.RemoveContained(projectile);

View File

@@ -104,13 +104,21 @@ namespace Subsurface.Items.Components
if (character == null) return false;
if (!character.GetInputState(InputType.SecondaryHeld)) return false;
if (DoesUseFail(character)) return false;
//if (DoesUseFail(character)) return false;
isActive = true;
Vector2 targetPosition = item.body.SimPosition;
//targetPosition = targetPosition.X, -targetPosition.Y);
float degreeOfSuccess = DegreeOfSuccess(character);
if (Rand.Range(0.0f, 1.0f) > degreeOfSuccess * degreeOfSuccess)
{
ApplyStatusEffects(ActionType.OnFailure, 1.0f, character);
return false;
}
targetPosition += new Vector2(
(float)Math.Cos(item.body.Rotation),
(float)Math.Sin(item.body.Rotation)) * range * item.body.Dir;
@@ -118,6 +126,7 @@ namespace Subsurface.Items.Components
List<Body> ignoredBodies = new List<Body>();
foreach (Limb limb in character.AnimController.Limbs)
{
if (Rand.Range(0.0f, 1.0f) > degreeOfSuccess) continue;
ignoredBodies.Add(limb.body.FarseerBody);
}

View File

@@ -426,24 +426,44 @@ namespace Subsurface.Items.Components
return true;
}
protected bool DoesUseFail(Character character)
/// <summary>
/// Returns 0.0f-1.0f based on how well the character can use the itemcomponent
/// </summary>
/// <returns>0.5f if all the skills meet the skill requirements exactly, 1.0f if they're way above and 0.0f if way less</returns>
protected float DegreeOfSuccess(Character character)
{
foreach (Skill skill in requiredSkills)
{
int characterLevel = character.GetSkillLevel(skill.Name);
if (characterLevel > skill.Level) continue;
if (requiredSkills.Count == 0) return 100.0f;
if (Rand.Int(characterLevel) - skill.Level < 0)
{
item.ApplyStatusEffects(ActionType.OnFailure, 1.0f, character);
//Item.ApplyStatusEffects();
return true;
}
float[] skillSuccess = new float[requiredSkills.Count];
for (int i = 0; i < requiredSkills.Count; i++ )
{
int characterLevel = character.GetSkillLevel(requiredSkills[i].Name);
skillSuccess[i] = (characterLevel - requiredSkills[i].Level);
}
return false;
float average = skillSuccess.Average();
return (average+100.0f)/2.0f;
}
//public bool CheckFailure(Character character)
//{
// foreach (Skill skill in requiredSkills)
// {
// int characterLevel = character.GetSkillLevel(skill.Name);
// if (characterLevel > skill.Level) continue;
// item.ApplyStatusEffects(ActionType.OnFailure, 1.0f, character);
// //Item.ApplyStatusEffects();
// return true;
// }
// return false;
//}
public bool HasRequiredContainedItems(bool addMessage)
{
List<RelatedItem> requiredContained = requiredItems.FindAll(ri=> ri.Type == RelatedItem.RelationType.Contained);

View File

@@ -72,7 +72,7 @@ namespace Subsurface.Items.Components
{
if (powerOnSound == null)
{
powerOnSound = Sound.Load("Content/Items/Electricity/powerOn.ogg");
powerOnSound = Sound.Load("Content/Items/Electricity/powerOn.ogg", false);
}
if (sparkSounds == null)
@@ -81,7 +81,7 @@ namespace Subsurface.Items.Components
string dir = Path.GetDirectoryName(item.Prefab.ConfigFile) + "\\";
for (int i = 0; i < 4; i++)
{
sparkSounds[i] = Sound.Load("Content/Items/Electricity/zap" + (i + 1) + ".ogg");
sparkSounds[i] = Sound.Load("Content/Items/Electricity/zap" + (i + 1) + ".ogg", false);
}
}
}

View File

@@ -71,6 +71,35 @@ namespace Subsurface.Items.Components
return true;
}
public override bool Use(float deltaTime, Character character = null)
{
if (character == null || character!=user) return false;
var powered = item.GetComponent<Powered>();
if (powered != null)
{
if (powered.Voltage < 0.1f) return false;
}
float degreeOfSuccess = DegreeOfSuccess(character);
if (Rand.Range(0.0f, 0.5f) < degreeOfSuccess) return false;
item.ApplyStatusEffects(ActionType.OnFailure, 1.0f, character);
//Vector2 baseVel = Rand.Vector(300.0f);
//for (int i = 0; i < 10; i++)
//{
// var particle = GameMain.ParticleManager.CreateParticle("spark", item.Position,
// baseVel + Rand.Vector(100.0f), 0.0f);
// if (particle != null) particle.Size *= Rand.Range(0.5f, 1.0f);
//}
//character.AddDamage(item.SimPosition, DamageType.None, Math.Abs(degreeOfSuccess-100.0f)/10.0f, 0.0f, 3.0f, false);
return true;
}
public override void Load(XElement element)
{
base.Load(element);

View File

@@ -1,4 +1,5 @@
using System;
using Microsoft.Xna.Framework;
using System;
using System.IO;
using System.Linq;
using System.Xml.Linq;
@@ -26,6 +27,34 @@ namespace Subsurface.Items.Components
LimbType[] limbType;
Limb[] limb;
private float armorValue;
private Vector2 armorSector;
[HasDefaultValue(0.0f, false)]
public float ArmorValue
{
get { return armorValue; }
set { armorValue = MathHelper.Clamp(value, 0.0f, 100.0f); }
}
[HasDefaultValue("0.0,360.0", false)]
public string ArmorSector
{
get { return ToolBox.Vector2ToString(armorSector); }
set
{
armorSector = ToolBox.ParseToVector2(value);
armorSector.X = MathHelper.ToRadians(armorSector.X);
armorSector.Y = MathHelper.ToRadians(armorSector.Y);
}
}
public Vector2 ArmorSectorLimits
{
get { return armorSector; }
}
public Wearable (Item item, XElement element)
: base(item, element)
{
@@ -76,7 +105,7 @@ namespace Subsurface.Items.Components
if (equipLimb == null) continue;
//something is already on the limb -> unequip it
if (equipLimb.WearingItem != null && equipLimb.WearingItem != item)
if (equipLimb.WearingItem != null && equipLimb.WearingItem != this)
{
equipLimb.WearingItem.Unequip(character);
}
@@ -88,7 +117,7 @@ namespace Subsurface.Items.Components
isActive = true;
limb[i] = equipLimb;
equipLimb.WearingItem = item;
equipLimb.WearingItem = this;
equipLimb.WearingItemSprite = wearableSprite[i];
}
}
@@ -111,7 +140,7 @@ namespace Subsurface.Items.Components
Limb equipLimb = character.AnimController.GetLimb(limbType[i]);
if (equipLimb == null) continue;
if (equipLimb.WearingItem != item) continue;
if (equipLimb.WearingItem != this) continue;
limb[i] = null;
equipLimb.WearingItem = null;

View File

@@ -1256,7 +1256,6 @@ namespace Subsurface
{
ic.Remove();
}
itemList.Remove(this);
foreach (Item it in itemList)

View File

@@ -19,6 +19,8 @@ namespace Subsurface
public float CameraShake;
private bool sparks, shockwave, flames;
//public Explosion(Vector2 position, float range, float damage, float structureDamage, float stun = 0.0f, float force = 0.0f)
//{
// this.position = position;
@@ -36,6 +38,10 @@ namespace Subsurface
force = ToolBox.GetAttributeFloat(element, "force", 0.0f);
sparks = ToolBox.GetAttributeBool(element, "sparks", true);
shockwave = ToolBox.GetAttributeBool(element, "shockwave", true);
flames = ToolBox.GetAttributeBool(element, "flames", true);
CameraShake = attack.Range*10.0f;
}
@@ -48,16 +54,25 @@ namespace Subsurface
{
Vector2 displayPosition = ConvertUnits.ToDisplayUnits(simPosition);
GameMain.ParticleManager.CreateParticle("shockwave", displayPosition,
Vector2.Zero, 0.0f);
if (shockwave)
{
GameMain.ParticleManager.CreateParticle("shockwave", displayPosition,
Vector2.Zero, 0.0f);
}
for (int i = 0; i < attack.Range * 10; i++)
{
GameMain.ParticleManager.CreateParticle("spark", displayPosition,
Rand.Vector(Rand.Range(500.0f, 800.0f)), 0.0f);
GameMain.ParticleManager.CreateParticle("explosionfire", displayPosition + Rand.Vector(50f),
Rand.Vector(Rand.Range(50f, 100.0f)), 0.0f);
if (sparks)
{
GameMain.ParticleManager.CreateParticle("spark", displayPosition,
Rand.Vector(Rand.Range(500.0f, 800.0f)), 0.0f);
}
if (flames)
{
GameMain.ParticleManager.CreateParticle("explosionfire", displayPosition + Rand.Vector(50f),
Rand.Vector(Rand.Range(50f, 100.0f)), 0.0f);
}
}
float displayRange = ConvertUnits.ToDisplayUnits(attack.Range);

View File

@@ -607,7 +607,6 @@ namespace Subsurface
foreach (Item item in Item.itemList)
{
System.Diagnostics.Debug.WriteLine(item.ID);
foreach (ItemComponent ic in item.components)
{
ic.OnMapLoaded();
@@ -634,6 +633,8 @@ namespace Subsurface
public static void Unload()
{
if (loaded == null) return;
Sound.OnGameEnd();
loaded.Remove();

View File

@@ -436,6 +436,9 @@ namespace Subsurface.Networking
userID = inc.ReadInt32();
userPassword = inc.ReadString();
version = inc.ReadString();
#if DEBUG
version = GameMain.Version.ToString();
#endif
packageName = inc.ReadString();
packageHash = inc.ReadString();
name = inc.ReadString();

View File

@@ -1,9 +1,11 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Xml.Linq;
using System.ComponentModel;
namespace Subsurface
@@ -37,12 +39,13 @@ namespace Subsurface
this.isSaveable = isSaveable;
}
}
class ObjectProperty
{
readonly PropertyDescriptor property;
readonly PropertyInfo propertyInfo;
readonly object obj;
public string Name
{
get { return property.Name; }
@@ -56,6 +59,7 @@ namespace Subsurface
public ObjectProperty(PropertyDescriptor property, object obj)
{
this.property = property;
propertyInfo = property.ComponentType.GetProperty(property.Name);
this.obj = obj;
}
@@ -65,7 +69,7 @@ namespace Subsurface
if (property.PropertyType == typeof(string))
{
property.SetValue(obj, value);
propertyInfo.SetValue(obj, value, null);
}
else if (property.PropertyType == typeof(float))
{
@@ -73,19 +77,19 @@ namespace Subsurface
if (float.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out floatVal))
{
property.SetValue(obj, floatVal);
propertyInfo.SetValue(obj, floatVal, null);
}
}
else if (property.PropertyType == typeof(bool))
{
property.SetValue(obj, (value.ToLower()=="true"));
propertyInfo.SetValue(obj, (value.ToLower() == "true"), null);
}
else if (property.PropertyType == typeof(int))
{
int intVal = 0;
if (int.TryParse(value, out intVal))
{
property.SetValue(obj, intVal);
propertyInfo.SetValue(obj, intVal, null);
}
}
else
@@ -114,7 +118,47 @@ namespace Subsurface
if (obj == null || property == null) return false;
try
{
property.SetValue(obj, value);
propertyInfo.SetValue(obj, value, null);
}
catch
{
return false;
}
return true;
}
public bool TrySetValue(float value)
{
try
{
propertyInfo.SetValue(obj, value, null);
}
catch
{
return false;
}
return true;
}
public bool TrySetValue(bool value)
{
try
{
propertyInfo.SetValue(obj, value, null);
}
catch
{
return false;
}
return true;
}
public bool TrySetValue(int value)
{
try
{
propertyInfo.SetValue(obj, value, null);
}
catch
{
@@ -129,7 +173,7 @@ namespace Subsurface
try
{
return property.GetValue(obj);
return propertyInfo.GetValue(obj, null);
}
catch
{

View File

@@ -80,8 +80,7 @@ namespace Subsurface
GameMain.ParticleManager.Update((float)deltaTime);
StatusEffect.UpdateAll((float)deltaTime);
Physics.accumulator = Math.Min(Physics.accumulator, Physics.step * 4);
while (Physics.accumulator >= Physics.step)
{
@@ -147,7 +146,7 @@ namespace Subsurface
public void DrawMap(GraphicsDevice graphics, SpriteBatch spriteBatch)
{
GameMain.LightManager.DrawLightmap(graphics, spriteBatch, cam);
//----------------------------------------------------------------------------------------
//1. draw the background, characters and the parts of the submarine that are behind them
//----------------------------------------------------------------------------------------

View File

@@ -73,6 +73,7 @@ namespace Subsurface
GUIButton button = new GUIButton(new Rectangle(0, 70, 100, 30), "Map", null, Alignment.Left, GUI.Style, leftPanel);
button.UserData = PanelTab.Map;
button.OnClicked = SelectRightPanel;
SelectRightPanel(button, button.UserData);
button = new GUIButton(new Rectangle(0, 110, 100, 30), "Crew", null, Alignment.Left, GUI.Style, leftPanel);
button.UserData = PanelTab.Crew;
@@ -149,8 +150,6 @@ namespace Subsurface
gameMode = GameMain.GameSession.gameMode as SinglePlayerMode;
selectedRightPanel = (int)PanelTab.Crew;
//Map.Unload();
UpdateCharacterLists();

View File

@@ -71,22 +71,22 @@ namespace Subsurface
{
startDrone = Sound.Load("Content/Sounds/startDrone.ogg");
startDrone = Sound.Load("Content/Sounds/startDrone.ogg", false);
startDrone.Play();
yield return CoroutineStatus.Running;
waterAmbiences[0] = Sound.Load("Content/Sounds/Water/WaterAmbience1.ogg");
waterAmbiences[0] = Sound.Load("Content/Sounds/Water/WaterAmbience1.ogg", false);
yield return CoroutineStatus.Running;
waterAmbiences[1] = Sound.Load("Content/Sounds/Water/WaterAmbience2.ogg");
waterAmbiences[1] = Sound.Load("Content/Sounds/Water/WaterAmbience2.ogg", false);
yield return CoroutineStatus.Running;
flowSounds[0] = Sound.Load("Content/Sounds/Water/FlowSmall.ogg");
flowSounds[0] = Sound.Load("Content/Sounds/Water/FlowSmall.ogg", false);
yield return CoroutineStatus.Running;
flowSounds[1] = Sound.Load("Content/Sounds/Water/FlowMedium.ogg");
flowSounds[1] = Sound.Load("Content/Sounds/Water/FlowMedium.ogg", false);
yield return CoroutineStatus.Running;
flowSounds[2] = Sound.Load("Content/Sounds/Water/FlowLarge.ogg");
flowSounds[2] = Sound.Load("Content/Sounds/Water/FlowLarge.ogg", false);
yield return CoroutineStatus.Running;
XDocument doc = ToolBox.TryLoadXml("Content/Sounds/sounds.xml");
@@ -124,7 +124,7 @@ namespace Subsurface
{
yield return CoroutineStatus.Running;
Sound sound = Sound.Load(ToolBox.GetAttributeString(element, "file", ""));
Sound sound = Sound.Load(ToolBox.GetAttributeString(element, "file", ""), false);
if (sound == null) continue;
DamageSoundType damageSoundType = DamageSoundType.None;
@@ -155,13 +155,10 @@ namespace Subsurface
{
UpdateMusic();
if (startDrone!=null)
if (startDrone!=null && !startDrone.IsPlaying)
{
if (!startDrone.IsPlaying)
{
startDrone.Remove();
startDrone = null;
}
startDrone.Remove();
startDrone = null;
}
float ambienceVolume = 0.6f;

View File

@@ -21,6 +21,8 @@ namespace Subsurface
string filePath;
private int alSourceId;
private bool destroyOnGameEnd;
//public float Volume
@@ -28,6 +30,25 @@ namespace Subsurface
// set { SoundManager.Volume(sourceIndex, value); }
//}
private Sound(string file, bool destroyOnGameEnd)
{
filePath = file;
foreach (Sound loadedSound in loadedSounds)
{
if (loadedSound.filePath == file) oggSound = loadedSound.oggSound;
}
if (oggSound == null)
{
oggSound = OggSound.Load(file);
}
this.destroyOnGameEnd = destroyOnGameEnd;
loadedSounds.Add(this);
}
public string FilePath
{
get { return filePath; }
@@ -43,32 +64,15 @@ namespace Subsurface
SoundManager.Init();
}
public static Sound Load(string file)
public static Sound Load(string file, bool destroyOnGameEnd = true)
{
if (!File.Exists(file))
{
DebugConsole.ThrowError("File ''" + file + "'' not found!");
return null;
}
Sound s = new Sound();
s.filePath = file;
foreach (Sound loadedSound in loadedSounds)
{
if (loadedSound.filePath == file) s.oggSound = loadedSound.oggSound;
}
if (s.oggSound == null)
{
s.oggSound = OggSound.Load(file);
}
loadedSounds.Add(s);
return s;
return new Sound(file, destroyOnGameEnd);
}
public int Play(float volume = 1.0f)
@@ -212,12 +216,27 @@ namespace Subsurface
//{
// SoundManager.Stop(this);
//}
public static void OnGameEnd()
{
List<Sound> removableSounds = loadedSounds.FindAll(s => s.destroyOnGameEnd);
foreach (Sound sound in removableSounds)
{
sound.Remove();
}
}
public void Remove()
{
loadedSounds.Remove(this);
System.Diagnostics.Debug.WriteLine(AlBufferId);
System.Diagnostics.Debug.WriteLine("Removing sound " + filePath + " (buffer id" + AlBufferId + ")");
if (alSourceId>0 && SoundManager.IsPlaying(alSourceId))
{
SoundManager.Stop(alSourceId);
}
foreach (Sound s in loadedSounds)
{

View File

@@ -335,6 +335,9 @@
<Content Include="Content\Items\Clothes\captainTorso.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\Items\Clothes\securitygear.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\Items\Electricity\lamp.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>

View File

@@ -396,7 +396,4 @@ Global
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(Performance) = preSolution
HasPerformanceSessions = true
EndGlobalSection
EndGlobal

Binary file not shown.