Merge pull request #188 from Crystalwarrior/moStuff

Motion detectors, ducts, more chem effects and chems, fabricator/deconstructor overhaul, more footsteps, clown hitsounds...
This commit is contained in:
Joonas Rikkonen
2018-01-09 12:11:15 +02:00
committed by GitHub
69 changed files with 1411 additions and 539 deletions
@@ -1,4 +1,5 @@
using FarseerPhysics; using Barotrauma.Items.Components;
using FarseerPhysics;
using FarseerPhysics.Dynamics; using FarseerPhysics.Dynamics;
using FarseerPhysics.Dynamics.Joints; using FarseerPhysics.Dynamics.Joints;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
@@ -20,7 +21,12 @@ namespace Barotrauma
if (impact > 3.0f && limb.HitSound != null && limb.SoundTimer <= 0.0f) if (impact > 3.0f && limb.HitSound != null && limb.SoundTimer <= 0.0f)
{ {
limb.SoundTimer = Limb.SoundInterval; limb.SoundTimer = Limb.SoundInterval;
limb.HitSound.Play(volume, impact * 100.0f, limb.WorldPosition); SoundPlayer.PlaySound(limb.HitSound, volume, impact * 100.0f, limb.WorldPosition);
foreach(WearableSprite wearable in limb.WearingItems)
{
if (limb.type == wearable.Limb && wearable.Sound != null)
SoundPlayer.PlaySound(wearable.Sound, volume, impact * 100.0f, limb.WorldPosition);
}
} }
} }
else if (body.UserData is Limb || body == Collider.FarseerBody) else if (body.UserData is Limb || body == Collider.FarseerBody)
@@ -29,7 +35,7 @@ namespace Barotrauma
{ {
if (impact > ImpactTolerance) if (impact > ImpactTolerance)
{ {
SoundPlayer.PlayDamageSound(DamageSoundType.LimbBlunt, strongestImpact, Collider); SoundPlayer.PlayDamageSound("LimbBlunt", strongestImpact, Collider);
} }
} }
@@ -19,7 +19,7 @@ namespace Barotrauma
private Sound hitSound; private Sound hitSound;
public Sound HitSound public string HitSound
{ {
get { return hitSound; } get { return hitSound; }
} }
@@ -34,7 +34,7 @@ namespace Barotrauma
LightSource = new LightSource(subElement); LightSource = new LightSource(subElement);
break; break;
case "sound": case "sound":
hitSound = Sound.Load(subElement.GetAttributeString("file", "")); hitSound = subElement.GetAttributeString("file", "");
break; break;
} }
} }
@@ -26,7 +26,7 @@ namespace Barotrauma
{ {
bool singleplayer = GameMain.NetworkMember == null; bool singleplayer = GameMain.NetworkMember == null;
bool gameOver = gameSession.CrewManager.GetCharacters().All(c => c.IsDead); bool gameOver = gameSession.CrewManager.GetCharacters().All(c => c.IsDead || c.IsUnconscious);
bool progress = Submarine.MainSub.AtEndPosition; bool progress = Submarine.MainSub.AtEndPosition;
GUIFrame frame = new GUIFrame(new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), Color.Black * 0.8f, null); GUIFrame frame = new GUIFrame(new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), Color.Black * 0.8f, null);
@@ -36,19 +36,23 @@ namespace Barotrauma
int y = 0; int y = 0;
if (singleplayer) if (!singleplayer)
{ {
string summaryText = TextManager.Get(gameOver ? "RoundSummaryGameOver" : //Game over if everyone dead or didn't progress
(progress ? "RoundSummaryProgress" : "RoundSummaryReturn")); gameOver = gameOver || !progress;
SoundPlayer.OverrideMusicType = gameOver ? "crewdead" : "endround";
summaryText = summaryText
.Replace("[sub]", Submarine.MainSub.Name)
.Replace("[location]", GameMain.GameSession.StartLocation.Name);
var infoText = new GUITextBlock(new Rectangle(0, y, 0, 50), summaryText, "", innerFrame, true);
y += infoText.Rect.Height;
} }
string summaryText = TextManager.Get(gameOver ? "RoundSummaryGameOver" :
(progress ? "RoundSummaryProgress" : "RoundSummaryReturn"));
summaryText = summaryText
.Replace("[sub]", Submarine.MainSub.Name)
.Replace("[location]", GameMain.GameSession.StartLocation.Name);
var infoText = new GUITextBlock(new Rectangle(0, y, 0, 50), summaryText, "", innerFrame, true);
y += infoText.Rect.Height;
if (!string.IsNullOrWhiteSpace(endMessage)) if (!string.IsNullOrWhiteSpace(endMessage))
{ {
var endText = new GUITextBlock(new Rectangle(0, y, 0, 30), endMessage, "", innerFrame, true); var endText = new GUITextBlock(new Rectangle(0, y, 0, 30), endMessage, "", innerFrame, true);
@@ -143,6 +143,10 @@ namespace Barotrauma
{ {
wasPut = character.SelectedCharacter.Inventory.TryPutItem(doubleClickedItem, Character.Controlled, doubleClickedItem.AllowedSlots, true); wasPut = character.SelectedCharacter.Inventory.TryPutItem(doubleClickedItem, Character.Controlled, doubleClickedItem.AllowedSlots, true);
} }
else if (character.SelectedBy != null && Character.Controlled == character.SelectedBy && character.SelectedBy.Inventory != null)
{
wasPut = character.SelectedBy.Inventory.TryPutItem(doubleClickedItem, Character.Controlled, doubleClickedItem.AllowedSlots, true);
}
else //doubleclicked and no other inventory is selected else //doubleclicked and no other inventory is selected
{ {
//not equipped -> attempt to equip //not equipped -> attempt to equip
@@ -111,9 +111,9 @@ namespace Barotrauma.Items.Components
if (!inadequateSkills.Any()) if (!inadequateSkills.Any())
{ {
text = "Required items:\n"; text = "Required items:\n";
foreach (Tuple<ItemPrefab, int> ip in targetItem.RequiredItems) foreach (Tuple<ItemPrefab, int, float, bool> ip in targetItem.RequiredItems)
{ {
text += " - " + ip.Item1.Name + " x" + ip.Item2 + "\n"; text += " - " + ip.Item1.Name + " x" + ip.Item2 + (ip.Item3 < 1.0f ? ", " + ip.Item3 * 100 + "% condition\n" : "\n");
} }
text += "Required time: " + targetItem.RequiredTime + " s"; text += "Required time: " + targetItem.RequiredTime + " s";
} }
@@ -127,6 +127,7 @@ namespace Barotrauma.Items.Components
if (target.IsDead) if (target.IsDead)
{ {
texts.Add("Deceased"); texts.Add("Deceased");
texts.Add("Cause of Death: " + target.CauseOfDeath.ToString());
} }
else else
{ {
@@ -87,6 +87,10 @@ namespace Barotrauma
DebugConsole.ThrowError("File \"" + file + "\" not found!"); DebugConsole.ThrowError("File \"" + file + "\" not found!");
return null; return null;
} }
Sound dupe = Sound.loadedSounds.Find(s => s.filePath == file);
if (dupe != null)
return dupe;
return new Sound(file, destroyOnGameEnd); return new Sound(file, destroyOnGameEnd);
} }
@@ -100,6 +104,9 @@ namespace Barotrauma
{ {
newSound.baseVolume = element.GetAttributeFloat("volume", 1.0f); newSound.baseVolume = element.GetAttributeFloat("volume", 1.0f);
newSound.range = element.GetAttributeFloat("range", 1000.0f); newSound.range = element.GetAttributeFloat("range", 1000.0f);
Sound dupe = Sound.loadedSounds.Find(s => s.filePath == filePath && s.baseVolume == newSound.baseVolume && s.range == newSound.range);
if (dupe != null)
return dupe;
} }
return newSound; return newSound;
@@ -10,26 +10,19 @@ using System.Xml.Linq;
namespace Barotrauma namespace Barotrauma
{ {
public enum DamageSoundType
{
None,
StructureBlunt, StructureSlash,
LimbBlunt, LimbSlash, LimbArmor
}
public struct DamageSound public struct DamageSound
{ {
//the range of inflicted damage where the sound can be played //the range of inflicted damage where the sound can be played
//(10.0f, 30.0f) would be played when the inflicted damage is between 10 and 30 //(10.0f, 30.0f) would be played when the inflicted damage is between 10 and 30
public readonly Vector2 damageRange; public readonly Vector2 damageRange;
public readonly DamageSoundType damageType; public readonly string damageType;
public readonly Sound sound; public readonly Sound sound;
public readonly string requiredTag; public readonly string requiredTag;
public DamageSound(Sound sound, Vector2 damageRange, DamageSoundType damageType, string requiredTag = "") public DamageSound(Sound sound, Vector2 damageRange, string damageType, string requiredTag = "")
{ {
this.sound = sound; this.sound = sound;
this.damageRange = damageRange; this.damageRange = damageRange;
@@ -161,8 +154,7 @@ namespace Barotrauma
Sound damageSound = Sound.Load(subElement.GetAttributeString("file", ""), false); Sound damageSound = Sound.Load(subElement.GetAttributeString("file", ""), false);
if (damageSound == null) continue; if (damageSound == null) continue;
DamageSoundType damageSoundType = DamageSoundType.None; string damageSoundType = subElement.GetAttributeString("damagesoundtype", "None");
Enum.TryParse<DamageSoundType>(subElement.GetAttributeString("damagesoundtype", "None"), false, out damageSoundType);
damageSounds.Add(new DamageSound( damageSounds.Add(new DamageSound(
damageSound, damageSound,
@@ -271,7 +263,7 @@ namespace Barotrauma
public static Sound GetSound(string soundTag) public static Sound GetSound(string soundTag)
{ {
var matchingSounds = miscSounds[soundTag].ToList(); var matchingSounds = miscSounds[soundTag].ToList();
if (matchingSounds.Count == 0) return null; if (matchingSounds.Count == 0) return Sound.Load(soundTag);
return matchingSounds[Rand.Int(matchingSounds.Count)]; return matchingSounds[Rand.Int(matchingSounds.Count)];
} }
@@ -442,14 +434,14 @@ namespace Barotrauma
SplashSounds[splashIndex].Play(1.0f, 800.0f, worldPosition); SplashSounds[splashIndex].Play(1.0f, 800.0f, worldPosition);
} }
public static void PlayDamageSound(DamageSoundType damageType, float damage, PhysicsBody body) public static void PlayDamageSound(string damageType, float damage, PhysicsBody body)
{ {
Vector2 bodyPosition = body.DrawPosition; Vector2 bodyPosition = body.DrawPosition;
PlayDamageSound(damageType, damage, bodyPosition, 800.0f); PlayDamageSound(damageType, damage, bodyPosition, 800.0f);
} }
public static void PlayDamageSound(DamageSoundType damageType, float damage, Vector2 position, float range = 2000.0f, List<string> tags = null) public static void PlayDamageSound(string damageType, float damage, Vector2 position, float range = 2000.0f, List<string> tags = null)
{ {
damage = MathHelper.Clamp(damage+Rand.Range(-10.0f, 10.0f), 0.0f, 100.0f); damage = MathHelper.Clamp(damage+Rand.Range(-10.0f, 10.0f), 0.0f, 100.0f);
var sounds = damageSounds.FindAll(s => var sounds = damageSounds.FindAll(s =>
@@ -295,6 +295,9 @@
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Door\doors.xml"> <Content Include="$(MSBuildThisFileDirectory)Content\Items\Door\doors.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Door\duct.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Items\Door\hatch.png"> <Content Include="$(MSBuildThisFileDirectory)Content\Items\Door\hatch.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
@@ -740,7 +743,7 @@
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Include="$(MSBuildThisFileDirectory)Data\clientpermissions.xml"> <Content Include="$(MSBuildThisFileDirectory)Data\clientpermissions.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Include="$(MSBuildThisFileDirectory)Data\ContentPackages\Vanilla 0.7.xml"> <Content Include="$(MSBuildThisFileDirectory)Data\ContentPackages\Vanilla 0.7.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
@@ -925,6 +928,9 @@
<None Include="$(MSBuildThisFileDirectory)Content\Items\Button\beep.ogg"> <None Include="$(MSBuildThisFileDirectory)Content\Items\Button\beep.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
<None Include="$(MSBuildThisFileDirectory)Content\Items\Button\switch.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Content\Items\Diving\divingSuit.ogg"> <None Include="$(MSBuildThisFileDirectory)Content\Items\Diving\divingSuit.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
@@ -940,6 +946,18 @@
<None Include="$(MSBuildThisFileDirectory)Content\Items\Door\door.ogg"> <None Include="$(MSBuildThisFileDirectory)Content\Items\Door\door.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
<None Include="$(MSBuildThisFileDirectory)Content\Items\Door\DoorBreak1.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Content\Items\Door\DoorBreak2.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Content\Items\Door\duct.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Content\Items\Door\DuctBreak.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Content\Items\Electricity\powerOn.ogg"> <None Include="$(MSBuildThisFileDirectory)Content\Items\Electricity\powerOn.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
@@ -1144,6 +1162,18 @@
<None Include="$(MSBuildThisFileDirectory)Content\Sounds\Damage\HitArmor3.ogg"> <None Include="$(MSBuildThisFileDirectory)Content\Sounds\Damage\HitArmor3.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
<None Include="$(MSBuildThisFileDirectory)Content\Sounds\Damage\HitClown1.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Content\Sounds\Damage\HitClown2.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Content\Sounds\Damage\HitClown3.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Content\Sounds\Damage\HitClown4.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Content\Sounds\Damage\implode.ogg"> <None Include="$(MSBuildThisFileDirectory)Content\Sounds\Damage\implode.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
@@ -1210,6 +1240,45 @@
<None Include="$(MSBuildThisFileDirectory)Content\Sounds\firelarge.ogg"> <None Include="$(MSBuildThisFileDirectory)Content\Sounds\firelarge.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
<None Include="$(MSBuildThisFileDirectory)Content\Sounds\Footsteps\Armor\armor-01.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Content\Sounds\Footsteps\Armor\armor-02.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Content\Sounds\Footsteps\Armor\armor-03.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Content\Sounds\Footsteps\Clown\clown-01.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Content\Sounds\Footsteps\Clown\clown-02.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Content\Sounds\Footsteps\Metal\metal-01.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Content\Sounds\Footsteps\Metal\metal-02.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Content\Sounds\Footsteps\Metal\metal-03.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Content\Sounds\Footsteps\Metal\metal-04.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Content\Sounds\Footsteps\Metal\metal-05.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Content\Sounds\Footsteps\Metal\metal-06.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Content\Sounds\Footsteps\Metal\metal-07.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Content\Sounds\Footsteps\step.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Content\Sounds\Music\amb_JD_drone_clattering_machine.ogg"> <None Include="$(MSBuildThisFileDirectory)Content\Sounds\Music\amb_JD_drone_clattering_machine.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
@@ -1336,9 +1405,6 @@
<None Include="$(MSBuildThisFileDirectory)Content\Sounds\Water\WaterAmbience2.ogg"> <None Include="$(MSBuildThisFileDirectory)Content\Sounds\Water\WaterAmbience2.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
<None Include="$(MSBuildThisFileDirectory)Content\step.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Content\utg_4.xnb"> <None Include="$(MSBuildThisFileDirectory)Content\utg_4.xnb">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
@@ -1348,9 +1414,24 @@
<None Include="$(MSBuildThisFileDirectory)Content\watershader_opengl.xnb"> <None Include="$(MSBuildThisFileDirectory)Content\watershader_opengl.xnb">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
<None Include="$(MSBuildThisFileDirectory)Submarines\Nehalennia.sub" /> <None Include="$(MSBuildThisFileDirectory)Submarines\Aegir Mark III.sub">
<None Include="$(MSBuildThisFileDirectory)Submarines\TutorialSub.sub" /> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<None Include="$(MSBuildThisFileDirectory)Submarines\Vellamo.sub" /> </None>
<None Include="$(MSBuildThisFileDirectory)Submarines\Nehalennia.sub">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Submarines\The Blind Carp.sub">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Submarines\The Nibbler.sub">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Submarines\TutorialSub.sub">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Submarines\Vellamo.sub">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="$(MSBuildThisFileDirectory)Source\Characters\AICharacter.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Source\Characters\AICharacter.cs" />
@@ -65,7 +65,7 @@
<limb id = "8" radius="5" height="13" mass = "2" type ="LeftFoot" flip="true" pullpos="-5.0,0.0"> <limb id = "8" radius="5" height="13" mass = "2" type ="LeftFoot" flip="true" pullpos="-5.0,0.0">
<sprite texture="Content/Characters/Human/[GENDER]legs.png" sourcerect="35,53,16,25" depth="0.14" origin="0.5,0.5"/> <sprite texture="Content/Characters/Human/[GENDER]legs.png" sourcerect="35,53,16,25" depth="0.14" origin="0.5,0.5"/>
<damagedsprite texture="Content/Characters/Human/damagedlegs.png" sourcerect="35,53,16,25" origin="0.5,0.5"/> <damagedsprite texture="Content/Characters/Human/damagedlegs.png" sourcerect="35,53,16,25" origin="0.5,0.5"/>
<sound file ="Content/step.ogg"/> <sound file ="footstep_metal"/>
</limb> </limb>
<!-- right leg --> <!-- right leg -->
@@ -80,7 +80,7 @@
<limb id = "11" radius="5" height="13" mass = "2" type ="RightFoot" flip="true" pullpos="-5.0,0.0"> <limb id = "11" radius="5" height="13" mass = "2" type ="RightFoot" flip="true" pullpos="-5.0,0.0">
<sprite texture="Content/Characters/Human/[GENDER]legs.png" sourcerect="35,53,16,25" origin="0.5,0.5"/> <sprite texture="Content/Characters/Human/[GENDER]legs.png" sourcerect="35,53,16,25" origin="0.5,0.5"/>
<damagedsprite texture="Content/Characters/Human/damagedlegs.png" sourcerect="35,53,16,25" origin="0.5,0.5"/> <damagedsprite texture="Content/Characters/Human/damagedlegs.png" sourcerect="35,53,16,25" origin="0.5,0.5"/>
<sound file ="Content/step.ogg"/> <sound file ="footstep_metal"/>
</limb> </limb>
<!-- head to body --> <!-- head to body -->
@@ -73,7 +73,7 @@
<limb id = "8" radius="5" height="13" mass = "2" type ="LeftFoot" flip="true" pullpos="-5.0,0.0"> <limb id = "8" radius="5" height="13" mass = "2" type ="LeftFoot" flip="true" pullpos="-5.0,0.0">
<sprite texture="Content/Characters/Human/[GENDER]legs.png" sourcerect="35,53,16,25" depth="0.14" origin="0.5,0.5"/> <sprite texture="Content/Characters/Human/[GENDER]legs.png" sourcerect="35,53,16,25" depth="0.14" origin="0.5,0.5"/>
<damagedsprite texture="Content/Characters/Human/damagedlegs.png" sourcerect="35,53,16,25" origin="0.5,0.5"/> <damagedsprite texture="Content/Characters/Human/damagedlegs.png" sourcerect="35,53,16,25" origin="0.5,0.5"/>
<sound file ="Content/step.ogg"/> <sound file ="footstep_metal"/>
</limb> </limb>
<!-- right leg --> <!-- right leg -->
@@ -88,7 +88,7 @@
<limb id = "11" radius="5" height="13" mass = "2" type ="RightFoot" flip="true" pullpos="-5.0,0.0"> <limb id = "11" radius="5" height="13" mass = "2" type ="RightFoot" flip="true" pullpos="-5.0,0.0">
<sprite texture="Content/Characters/Human/[GENDER]legs.png" sourcerect="35,53,16,25" origin="0.5,0.5"/> <sprite texture="Content/Characters/Human/[GENDER]legs.png" sourcerect="35,53,16,25" origin="0.5,0.5"/>
<damagedsprite texture="Content/Characters/Human/damagedlegs.png" sourcerect="35,53,16,25" origin="0.5,0.5"/> <damagedsprite texture="Content/Characters/Human/damagedlegs.png" sourcerect="35,53,16,25" origin="0.5,0.5"/>
<sound file ="Content/step.ogg"/> <sound file ="footstep_metal"/>
</limb> </limb>
@@ -76,7 +76,7 @@
</limb> </limb>
<limb id = "8" radius="5" height="13" mass = "2" type ="LeftFoot" flip="true" pullpos="-5.0,0.0"> <limb id = "8" radius="5" height="13" mass = "2" type ="LeftFoot" flip="true" pullpos="-5.0,0.0">
<sprite texture="Content/Characters/Husk/legs.png" sourcerect="35,53,16,25" depth="0.14" origin="0.5,0.5"/> <sprite texture="Content/Characters/Husk/legs.png" sourcerect="35,53,16,25" depth="0.14" origin="0.5,0.5"/>
<sound file ="Content/step.ogg"/> <sound file ="footstep_armor"/>
</limb> </limb>
<!-- right leg --> <!-- right leg -->
@@ -88,7 +88,7 @@
</limb> </limb>
<limb id = "11" radius="5" height="13" mass = "2" type ="RightFoot" flip="true" pullpos="-5.0,0.0"> <limb id = "11" radius="5" height="13" mass = "2" type ="RightFoot" flip="true" pullpos="-5.0,0.0">
<sprite texture="Content/Characters/Husk/legs.png" sourcerect="35,53,16,25" origin="0.5,0.5"/> <sprite texture="Content/Characters/Husk/legs.png" sourcerect="35,53,16,25" origin="0.5,0.5"/>
<sound file ="Content/step.ogg"/> <sound file ="footstep_armor"/>
</limb> </limb>
<!-- head to body --> <!-- head to body -->
@@ -95,33 +95,40 @@
tags="alien,smallitem,oxygensource" tags="alien,smallitem,oxygensource"
impacttolerance="8"> impacttolerance="8">
<Deconstruct time="20">
<Item name="Steel Bar"/>
<Item name="Liquid Oxygenite" mincondition="0.1"/>
<Item name="Liquid Oxygenite" mincondition="0.5"/>
<Item name="Liquid Oxygenite" mincondition="0.9"/>
</Deconstruct>
<Sprite texture="artifact.png" depth="0.7" sourcerect="119,0,9,32"/> <Sprite texture="artifact.png" depth="0.7" sourcerect="119,0,9,32"/>
<Body width="9" height="32" density="15"/> <Body width="9" height="32" density="15"/>
<Holdable slots="Any,RightHand,LeftHand" handle1="0,-5"> <Throwable slots="Any,RightHand,LeftHand" handle1="0,-5" throwforce="4.0" aimpos="35,-10">
<StatusEffect type="Always" target="Hull" oxygen="5000.0"/> <StatusEffect type="Always" target="Hull" oxygen="5000.0"/>
<StatusEffect type="OnImpact" target="This" Condition="0.0" setvalue="true"> <StatusEffect type="OnImpact" target="This" Condition="0.0" setvalue="true">
<sound file="Content/Items/Reactor/explosion.ogg"/> <sound file="Content/Items/Reactor/explosion.ogg"/>
<Explosion range="600.0" structuredamage="400" damage="300" stun="5" force="20.0"/> <Explosion range="600.0" structuredamage="400" damage="300" stun="5" force="20.0"/>
</StatusEffect> </StatusEffect>
</Holdable> </Throwable>
</Item> </Item>
<Item <Item
name="Sulphurite Shard" name="Sulphurite Shard"
category="Alien" category="Alien"
tags="alien,smallitem" tags="alien,smallitem"
impacttolerance="8" impacttolerance="8"
spritecolor="1.0,0.0,0.0,1.0"> spritecolor="1.0,0.0,0.0,1.0">
<Deconstruct time="20"> <Deconstruct time="20">
<Item name="Steel Bar"/> <Item name="Steel Bar"/>
<Item name="Sulphuric Acid"/> <Item name="Sulphuric Acid" mincondition="0.1"/>
<Item name="Sulphuric Acid"/> <Item name="Sulphuric Acid" mincondition="0.5"/>
<Item name="Sulphuric Acid"/> <Item name="Sulphuric Acid" mincondition="0.9"/>
</Deconstruct> </Deconstruct>
<Sprite texture="artifact.png" depth="0.7" sourcerect="119,0,9,32"/> <Sprite texture="artifact.png" depth="0.7" sourcerect="119,0,9,32"/>
@@ -130,7 +137,7 @@
<Body width="8" height="32" density="15"/> <Body width="8" height="32" density="15"/>
<Holdable slots="Any,RightHand,LeftHand" handle1="0,-5"/> <Throwable slots="Any,RightHand,LeftHand" handle1="0,-5" throwforce="4.0" aimpos="35,-10"/>
</Item> </Item>
<Item <Item
@@ -193,7 +200,7 @@
<Sprite texture="Content/Map/ruins.png" sourcerect="747,0,260,95" depth="0.8" origin="0.5,0.5"/> <Sprite texture="Content/Map/ruins.png" sourcerect="747,0,260,95" depth="0.8" origin="0.5,0.5"/>
<Door canbeselected="true" horizontal="true"> <Door canbepicked="false" canbeselected="true" horizontal="true">
<Sprite texture="Content/Map/ruins.png" sourcerect="0,842,260,54" depth="0.6" origin="0.0,0.5"/> <Sprite texture="Content/Map/ruins.png" sourcerect="0,842,260,54" depth="0.6" origin="0.0,0.5"/>
<sound file="aliendoor.ogg" type="OnUse" range="1000.0"/> <sound file="aliendoor.ogg" type="OnUse" range="1000.0"/>
</Door> </Door>
@@ -215,7 +222,7 @@
<Sprite texture="Content/Map/ruins.png" sourcerect="746,101,93,259" depth="0.8" origin="0.5,0.5"/> <Sprite texture="Content/Map/ruins.png" sourcerect="746,101,93,259" depth="0.8" origin="0.5,0.5"/>
<Door canbeselected="true"> <Door canbepicked="false" canbeselected="true">
<Sprite texture="Content/Map/ruins.png" sourcerect="842,192,54,259" depth="0.6" origin="0.5,0.0"/> <Sprite texture="Content/Map/ruins.png" sourcerect="842,192,54,259" depth="0.6" origin="0.5,0.0"/>
<sound file="aliendoor.ogg" type="OnUse" range="3000.0"/> <sound file="aliendoor.ogg" type="OnUse" range="3000.0"/>
</Door> </Door>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

@@ -1,33 +1,66 @@
<Item <Items>
name="Button" <Item
category="Electrical" name="Button"
linkable="true" category="Electrical"
tags="smallitem" linkable="true"
tags="smallitem"
price="10">
price="10">
<Sprite texture ="button.png" depth="0.8"/> <Sprite texture ="button.png" sourcerect="0,0,24,27" depth="0.8"/>
<Deconstruct time="10"> <Deconstruct time="10">
<Item name="Polycarbonate Bar"/> <Item name="Steel Bar"/>
<Item name="FPGA Circuit"/> <Item name="FPGA Circuit"/>
</Deconstruct> </Deconstruct>
<Body width="32" height="32" density="40"/> <Body width="32" height="32" density="40"/>
<Controller direction ="None" canbepicked = "true" msg="Press [E]"> <Controller direction ="None" canbepicked = "true" msg="Press [E]">
<RequiredItem name="ID Card" type="Picked" msg="UNAUTHORIZED ACCESS"/> <RequiredItem name="ID Card" type="Picked" msg="UNAUTHORIZED ACCESS"/>
<sound file="beep.ogg" type="OnUse" range="500.0"/> <sound file="beep.ogg" type="OnUse" range="500.0"/>
</Controller> </Controller>
<ConnectionPanel selectkey="Action" canbeselected = "true" msg="Rewire [Screwdriver]"> <ConnectionPanel selectkey="Action" canbeselected = "true" msg="Rewire [Screwdriver]">
<RequiredItem name="Screwdriver" type="Equipped"/> <RequiredItem name="Screwdriver" type="Equipped"/>
<output name="signal_out"/> <output name="signal_out"/>
</ConnectionPanel> </ConnectionPanel>
<Holdable selectkey="Action" slots="Any,RightHand,LeftHand" msg="Detach [Wrench]" PickingTime="10.0" <Holdable selectkey="Action" slots="Any,RightHand,LeftHand" msg="Detach [Wrench]" PickingTime="10.0"
aimpos="35,-10" handle1="0,0" attachable="true" attachedbydefault="true" aimable="true"> aimpos="35,-10" handle1="0,0" attachable="true" attachedbydefault="true" aimable="true">
<requireditem name="Wrench" type="Equipped"/> <requireditem name="Wrench" type="Equipped"/>
</Holdable> </Holdable>
</Item>
</Item>
<Item
name="Switch"
category="Electrical"
linkable="true"
tags="smallitem"
price="10">
<Sprite texture ="button.png" sourcerect="24,0,11,16" depth="0.79"/>
<Deconstruct time="10">
<Item name="Steel Bar"/>
<Item name="FPGA Circuit"/>
</Deconstruct>
<Body width="16" height="16" density="20"/>
<Controller direction="None" canbepicked="true" msg="Press [E]">
<sound file="switch.ogg" type="OnUse" range="250.0"/>
</Controller>
<ConnectionPanel selectkey="Action" canbeselected = "true" msg="Rewire [Screwdriver]">
<RequiredItem name="Screwdriver" type="Equipped"/>
<output name="signal_out"/>
</ConnectionPanel>
<Holdable selectkey="Action" slots="Any,RightHand,LeftHand" msg="Detach [Wrench]" PickingTime="10.0"
aimpos="35,-10" handle1="0,0" attachable="true" attachedbydefault="true" aimable="true">
<requireditem name="Wrench" type="Equipped"/>
</Holdable>
</Item>
</Items>
@@ -68,6 +68,14 @@
fireproof="true" fireproof="true"
description="An atmospheric diving suit capable of withstanding the immense pressure under Europa's crust."> description="An atmospheric diving suit capable of withstanding the immense pressure under Europa's crust.">
<Deconstruct time="30">
<Item name="Steel Bar"/>
<Item name="Aluminium"/>
<Item name="Aluminium"/>
<Item name="Polycarbonate Bar"/>
<Item name="Polycarbonate Bar"/>
</Deconstruct>
<Sprite texture ="DivingSuit.png" sourcerect="85,0,43,128" depth="0.55"/> <Sprite texture ="DivingSuit.png" sourcerect="85,0,43,128" depth="0.55"/>
<Body width="37" height="113" density="15"/> <Body width="37" height="113" density="15"/>
@@ -89,8 +97,8 @@
<sprite texture="DivingSuit.png" limb="RightLeg" sourcerect="17,47,21,51" origin="0.5,0.55" hidelimb="true"/> <sprite texture="DivingSuit.png" limb="RightLeg" sourcerect="17,47,21,51" origin="0.5,0.55" hidelimb="true"/>
<sprite texture="DivingSuit.png" limb="LeftLeg" sourcerect="17,47,21,51" origin="0.5,0.55" hidelimb="true"/> <sprite texture="DivingSuit.png" limb="LeftLeg" sourcerect="17,47,21,51" origin="0.5,0.55" hidelimb="true"/>
<sprite texture="DivingSuit.png" limb="RightFoot" sourcerect="30,100,20,25" origin="0.5,0.5" depth="0.13" inheritlimbdepth="false" hidelimb="true"/> <sprite texture="DivingSuit.png" limb="RightFoot" sound="footstep_armor" sourcerect="30,100,20,25" origin="0.5,0.5" depth="0.13" inheritlimbdepth="false" hidelimb="true"/>
<sprite texture="DivingSuit.png" limb="LeftFoot" sourcerect="30,100,20,25" origin="0.5,0.5" depth="0.13" inheritlimbdepth="false" hidelimb="true"/> <sprite texture="DivingSuit.png" limb="LeftFoot" sound="footstep_armor" sourcerect="30,100,20,25" origin="0.5,0.5" depth="0.13" inheritlimbdepth="false" hidelimb="true"/>
<StatusEffect type="OnWearing" target="Character" HideFace="true" ObstructVision="true" PressureProtection="100.0" SpeedMultiplier="0.6" LowPassMultiplier="0.2" setvalue="true" disabledeltatime="true"/> <StatusEffect type="OnWearing" target="Character" HideFace="true" ObstructVision="true" PressureProtection="100.0" SpeedMultiplier="0.6" LowPassMultiplier="0.2" setvalue="true" disabledeltatime="true"/>
<StatusEffect type="OnWearing" target="Contained,Character" OxygenAvailable="1000.0" Condition="-0.5"> <StatusEffect type="OnWearing" target="Contained,Character" OxygenAvailable="1000.0" Condition="-0.5">
@@ -126,8 +134,9 @@
<Deconstruct time="20"> <Deconstruct time="20">
<Item name="Steel Bar"/> <Item name="Steel Bar"/>
<Item name="Copper Bar"/>
<Item name="Polycarbonate Bar"/> <Item name="Polycarbonate Bar"/>
<Item name="Polycarbonate Bar"/>
<Item name="FPGA Circuit"/>
</Deconstruct> </Deconstruct>
<Sprite texture ="Scooter.png" depth="0.55"/> <Sprite texture ="Scooter.png" depth="0.55"/>
@@ -6,13 +6,16 @@
<Sprite texture ="door.png" sourcerect="1,0,48,208" depth="0.01" origin="0.5,0.5"/> <Sprite texture ="door.png" sourcerect="1,0,48,208" depth="0.01" origin="0.5,0.5"/>
<Door canbeselected="true" selectkey="Action" msg="Force Open [Crowbar]" PickingTime="10.0"> <Door canbeselected="true" pickkey="Action" msg="Force Open [Crowbar]" PickingTime="10.0">
<requireditem name="Crowbar" type="Equipped"/> <requireditem name="Crowbar" type="Equipped"/>
<Sprite texture ="door.png" sourcerect="80,0,19,208" depth="0.05" origin="0.5,0.0"/> <Sprite texture ="door.png" sourcerect="80,0,19,208" depth="0.05" origin="0.5,0.0"/>
<WeldedSprite texture ="door.png" sourcerect="99,0,32,188" depth="0.0" origin="0.5,0.5"/> <WeldedSprite texture ="door.png" sourcerect="99,0,32,188" depth="0.0" origin="0.5,0.5"/>
<BrokenSprite texture ="door.png" sourcerect="133,0,58,208" depth="0.051" origin="0.5,0.0" scale="true"/> <BrokenSprite texture ="door.png" sourcerect="133,0,58,208" depth="0.051" origin="0.5,0.0" scale="true"/>
<sound file="door.ogg" type="OnUse" range="500.0"/> <sound file="door.ogg" type="OnUse" range="500.0"/>
<sound file="Content/Items/Tools/crowbar.ogg" type="OnPicked" range="2000.0"/> <sound file="Content/Items/Tools/crowbar.ogg" type="OnPicked" range="2000.0"/>
<StatusEffect type="OnBroken" target="This">
<sound file="Content/Items/Door/doorBreak2.ogg" range="3000"/>
</StatusEffect>
</Door> </Door>
<AiTarget sightrange="500.0"/> <AiTarget sightrange="500.0"/>
@@ -37,13 +40,16 @@
<Sprite texture="door.png" sourcerect="1,0,48,208" depth="0.01" origin="0.5,0.5"/> <Sprite texture="door.png" sourcerect="1,0,48,208" depth="0.01" origin="0.5,0.5"/>
<Door window="0,-32,10,75" canbeselected="true" selectkey="Action" msg="Force Open [Crowbar]" PickingTime="10.0"> <Door window="0,-32,10,75" canbeselected="true" pickkey="Action" msg="Force Open [Crowbar]" PickingTime="10.0">
<requireditem name="Crowbar" type="Equipped"/> <requireditem name="Crowbar" type="Equipped"/>
<Sprite texture="door.png" sourcerect="56,0,19,208" depth="0.05" origin="0.5,0.0"/> <Sprite texture="door.png" sourcerect="56,0,19,208" depth="0.05" origin="0.5,0.0"/>
<WeldedSprite texture="door.png" sourcerect="9,0,32,188" depth="0.0" origin="0.5,0.5"/> <WeldedSprite texture="door.png" sourcerect="9,0,32,188" depth="0.0" origin="0.5,0.5"/>
<BrokenSprite texture="door.png" sourcerect="192,0,40,208" depth="0.051" origin="0.5,0.0" scale="true"/> <BrokenSprite texture="door.png" sourcerect="192,0,40,208" depth="0.051" origin="0.5,0.0" scale="true"/>
<sound file="door.ogg" type="OnUse" range="500.0"/> <sound file="door.ogg" type="OnUse" range="500.0"/>
<sound file="Content/Items/Tools/crowbar.ogg" type="OnPicked" range="2000.0"/> <sound file="Content/Items/Tools/crowbar.ogg" type="OnPicked" range="2000.0"/>
<StatusEffect type="OnBroken" target="This">
<sound file="Content/Items/Door/doorBreak1.ogg" range="3000"/>
</StatusEffect>
</Door> </Door>
<AiTarget sightrange="500.0"/> <AiTarget sightrange="500.0"/>
@@ -68,13 +74,16 @@
<Sprite texture="hatch.png" sourcerect="0,0,128,46" depth="0.01" origin="0.5,0.5"/> <Sprite texture="hatch.png" sourcerect="0,0,128,46" depth="0.01" origin="0.5,0.5"/>
<Door canbeselected="true" horizontal="true" selectkey="Action" msg="Force Open [Crowbar]" PickingTime="10.0"> <Door canbeselected="true" horizontal="true" pickkey="Action" msg="Force Open [Crowbar]" PickingTime="10.0">
<requireditem name="Crowbar" type="Equipped"/> <requireditem name="Crowbar" type="Equipped"/>
<Sprite texture="hatch.png" sourcerect="128,0,128,19" depth="0.05" origin="0.0,0.5"/> <Sprite texture="hatch.png" sourcerect="128,0,128,19" depth="0.05" origin="0.0,0.5"/>
<WeldedSprite texture="hatch.png" sourcerect="0,56,108,33" depth="0.0" origin="0.5,0.5"/> <WeldedSprite texture="hatch.png" sourcerect="0,56,108,33" depth="0.0" origin="0.5,0.5"/>
<BrokenSprite texture="hatch.png" sourcerect="128,21,128,58" depth="0.051" origin="0.0,0.5" scale="true"/> <BrokenSprite texture="hatch.png" sourcerect="128,21,128,58" depth="0.051" origin="0.0,0.5" scale="true"/>
<sound file="door.ogg" type="OnUse" range="500.0"/> <sound file="door.ogg" type="OnUse" range="500.0"/>
<sound file="Content/Items/Tools/crowbar.ogg" type="OnPicked" range="2000.0"/> <sound file="Content/Items/Tools/crowbar.ogg" type="OnPicked" range="2000.0"/>
<StatusEffect type="OnBroken" target="This">
<sound file="Content/Items/Door/doorBreak1.ogg" range="3000"/>
</StatusEffect>
</Door> </Door>
<AiTarget sightrange="500.0"/> <AiTarget sightrange="500.0"/>
@@ -103,6 +112,9 @@
<Sprite texture ="dockingport.png" sourcerect="127,0,112,144" depth="0.05" origin="0.5,0.5"/> <Sprite texture ="dockingport.png" sourcerect="127,0,112,144" depth="0.05" origin="0.5,0.5"/>
<sound file="dockingport1.ogg" type="OnUse" range="1000.0"/> <sound file="dockingport1.ogg" type="OnUse" range="1000.0"/>
<sound file="dockingport2.ogg" type="OnSecondaryUse" range="1000.0"/> <sound file="dockingport2.ogg" type="OnSecondaryUse" range="1000.0"/>
<StatusEffect type="OnBroken" target="This">
<sound file="Content/Items/Door/doorBreak2.ogg" range="3000"/>
</StatusEffect>
</DockingPort> </DockingPort>
<PowerTransfer/> <PowerTransfer/>
@@ -134,6 +146,9 @@
<Sprite texture ="dockingport.png" sourcerect="127,144,48,112" depth="0.05" origin="0.5,0.5"/> <Sprite texture ="dockingport.png" sourcerect="127,144,48,112" depth="0.05" origin="0.5,0.5"/>
<sound file="dockingport1.ogg" type="OnUse" range="1000.0"/> <sound file="dockingport1.ogg" type="OnUse" range="1000.0"/>
<sound file="dockingport2.ogg" type="OnSecondaryUse" range="1000.0"/> <sound file="dockingport2.ogg" type="OnSecondaryUse" range="1000.0"/>
<StatusEffect type="OnBroken" target="This">
<sound file="Content/Items/Door/doorBreak2.ogg" range="3000"/>
</StatusEffect>
</DockingPort> </DockingPort>
<fixrequirement name="Electrical repairs"> <fixrequirement name="Electrical repairs">
@@ -158,5 +173,39 @@
<output name="state_out"/> <output name="state_out"/>
<output name="proximity_sensor"/> <output name="proximity_sensor"/>
</ConnectionPanel> </ConnectionPanel>
</Item> </Item>
<Item
name="Duct Block"
linkable="true"
>
<Sprite texture ="duct.png" sourcerect="0,0,33,33" depth="0.01" origin="0.5,0.5"/>
<Door canbeselected="true" pickkey="Action" msg="Force Open [Crowbar]" PickingTime="3.0">
<requireditem name="Crowbar" type="Equipped"/>
<Sprite texture ="duct.png" sourcerect="66,0,19,19" depth="0.05" origin="-0.4,0.5"/>
<WeldedSprite texture ="duct.png" sourcerect="33,0,33,33" depth="0.0" origin="0.5,0.5"/>
<BrokenSprite texture="duct.png" sourcerect="0,34,52,52" depth="0.051" origin="0.2,0.5" scale="true"/>
<sound file="duct.ogg" type="OnUse" range="300"/>
<sound file="Content/Items/Tools/crowbar.ogg" type="OnPicked" range="500.0"/>
<StatusEffect type="OnBroken" target="This">
<sound file="Content/Items/Door/ductBreak.ogg" range="2000"/>
</StatusEffect>
</Door>
<AiTarget sightrange="500.0"/>
<fixrequirement name="Mechanical repairs">
<skill name="Construction" level="30"/>
<item name="Welding Tool"/>
</fixrequirement>
<ConnectionPanel selectkey="Action" canbeselected = "true" msg="Rewire [Screwdriver]">
<requireditem name="Screwdriver" type="Equipped"/>
<input name="toggle"/>
<input name="set_state"/>
<output name="state_out"/>
</ConnectionPanel>
</Item>
</Items> </Items>
Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 17 KiB

@@ -99,6 +99,11 @@
price="100" price="100"
description="Field-programmable gate array - a multi-purpose circuit which can be reconfigured for use in a large variety of electrical devices."> description="Field-programmable gate array - a multi-purpose circuit which can be reconfigured for use in a large variety of electrical devices.">
<Deconstruct time="5">
<Item name="Copper Bar"/>
<Item name="Copper Bar"/>
</Deconstruct>
<Sprite texture="signalcomp.png" depth="0.8" sourcerect="32,16,16,16"/> <Sprite texture="signalcomp.png" depth="0.8" sourcerect="32,16,16,16"/>
<Body width="16" height="16" density="30"/> <Body width="16" height="16" density="30"/>
@@ -335,7 +340,7 @@
<Item name="FPGA Circuit"/> <Item name="FPGA Circuit"/>
</Deconstruct> </Deconstruct>
<Sprite texture="signalcomp.png" depth="0.8" sourcerect="96,0,31,24"/> <Sprite texture="signalcomp.png" depth="0.8" sourcerect="97,0,31,24"/>
<OxygenDetector canbeselected = "true"/> <OxygenDetector canbeselected = "true"/>
@@ -366,7 +371,7 @@
<Item name="FPGA Circuit"/> <Item name="FPGA Circuit"/>
</Deconstruct> </Deconstruct>
<Sprite texture="signalcomp.png" depth="0.8" sourcerect="64,0,31,25"/> <Sprite texture="signalcomp.png" depth="0.8" sourcerect="65,0,31,24"/>
<WaterDetector canbeselected = "true"/> <WaterDetector canbeselected = "true"/>
@@ -382,6 +387,37 @@
<output name="signal_out"/> <output name="signal_out"/>
</ConnectionPanel> </ConnectionPanel>
</Item> </Item>
<Item
name="Motion Detector"
category="Electrical"
Tags="smallitem"
linkable="true"
price="10"
description="Sends out a signal when it detects movement.">
<Deconstruct time="10">
<Item name="Steel Bar"/>
<Item name="FPGA Circuit"/>
</Deconstruct>
<Sprite texture="signalcomp.png" depth="0.8" sourcerect="65,24,31,24"/>
<MotionSensor range="100" canbeselected = "true"/>
<Body width="31" height="24" density="30"/>
<Holdable selectkey="Action" slots="Any,RightHand,LeftHand" msg="Detach [Wrench]" PickingTime="5.0"
aimpos="65,-10" handle1="0,0" attachable="true" aimable="true">
<requireditem name="Wrench" type="Equipped"/>
</Holdable>
<ConnectionPanel selectkey="Action" canbeselected = "true" msg="Rewire [Screwdriver]">
<requireditem name="Screwdriver,Wire" type="Equipped"/>
<output name="state_out"/>
</ConnectionPanel>
</Item>
<Item <Item
name="Signal Check Component" name="Signal Check Component"
@@ -561,7 +597,7 @@
<Item name="FPGA Circuit"/> <Item name="FPGA Circuit"/>
</Deconstruct> </Deconstruct>
<Sprite texture="signalcomp.png" depth="0.8" sourcerect="64,32,23,16"/> <Sprite texture="signalcomp.png" depth="0.8" sourcerect="34,64,23,16"/>
<Body width="20" height="16" density="20"/> <Body width="20" height="16" density="20"/>
@@ -19,6 +19,9 @@
<RequiredSkill name="Construction" level="30"/> <RequiredSkill name="Construction" level="30"/>
</fabricableitem> </fabricableitem>
<fabricableitem name="Spear" requireditems="Steel Bar" requiredtime="10"/> <fabricableitem name="Spear" requireditems="Steel Bar" requiredtime="10"/>
<fabricableitem name="Revolver Round" requireditems="Copper Bar" requiredtime="10">
<Item name="Aluminium" mincondition="0.5" usecondition="true"/>
</fabricableitem>
<fabricableitem name="Plasma Cutter" requireditems="Steel Bar, Polycarbonate Bar, Aluminium" requiredtime="20"> <fabricableitem name="Plasma Cutter" requireditems="Steel Bar, Polycarbonate Bar, Aluminium" requiredtime="20">
<RequiredSkill name="Construction" level="30"/> <RequiredSkill name="Construction" level="30"/>
@@ -33,10 +36,26 @@
<fabricableitem name="Nuclear Shell" requireditems="Steel Bar, Steel Bar, Uranium Bar, Polycarbonate Bar" requiredtime="30"> <fabricableitem name="Nuclear Shell" requireditems="Steel Bar, Steel Bar, Uranium Bar, Polycarbonate Bar" requiredtime="30">
<RequiredSkill name="Construction" level="40"/> <RequiredSkill name="Construction" level="40"/>
</fabricableitem> </fabricableitem>
<fabricableitem name="Depth Charge Shell" requireditems="Steel Bar, Steel Bar" requiredtime="20">
<RequiredSkill name="Construction" level="25"/>
</fabricableitem>
<fabricableitem name="Nuclear Depth Charge" requireditems="Steel Bar, Steel Bar, Uranium Bar" requiredtime="30">
<RequiredSkill name="Construction" level="40"/>
</fabricableitem>
<fabricableitem name="Diving Mask" requireditems="Polycarbonate Bar" requiredtime="20">
<RequiredSkill name="Construction" level="25"/>
</fabricableitem>
<fabricableitem name="Diving Suit" requireditems="Steel Bar, Polycarbonate Bar, Polycarbonate Bar, Aluminium, Aluminium" requiredtime="30">
<RequiredSkill name="Construction" level="40"/>
</fabricableitem>
<fabricableitem name="Fire Extinguisher" requireditems="Steel Bar, Polycarbonate Bar" requiredtime="10"/>
<fabricableitem name="Flashlight" requireditems="Copper Bar, Polycarbonate Bar" requiredtime="10"/>
<fabricableitem name="Wire" requireditems="Copper Bar" requiredtime="5"/> <fabricableitem name="Wire" requireditems="Copper Bar" requiredtime="5"/>
<fabricableitem name="Button" requireditems="Steel Bar, FPGA Circuit" requiredtime="10"/> <fabricableitem name="Button" requireditems="Steel Bar, FPGA Circuit" requiredtime="10"/>
<fabricableitem name="Switch" requireditems="Steel Bar, FPGA Circuit" requiredtime="10"/>
<fabricableitem name="And Component" requireditems="Steel Bar, FPGA Circuit" requiredtime="10"/> <fabricableitem name="And Component" requireditems="Steel Bar, FPGA Circuit" requiredtime="10"/>
<fabricableitem name="Or Component" requireditems="Steel Bar, FPGA Circuit" requiredtime="10"/> <fabricableitem name="Or Component" requireditems="Steel Bar, FPGA Circuit" requiredtime="10"/>
<fabricableitem name="Not Component" requireditems="Steel Bar, FPGA Circuit" requiredtime="10"/> <fabricableitem name="Not Component" requireditems="Steel Bar, FPGA Circuit" requiredtime="10"/>
@@ -45,6 +64,7 @@
<fabricableitem name="Light Component" requireditems="Steel Bar, FPGA Circuit" requiredtime="10"/> <fabricableitem name="Light Component" requireditems="Steel Bar, FPGA Circuit" requiredtime="10"/>
<fabricableitem name="Oxygen Detector" requireditems="Steel Bar, FPGA Circuit" requiredtime="10"/> <fabricableitem name="Oxygen Detector" requireditems="Steel Bar, FPGA Circuit" requiredtime="10"/>
<fabricableitem name="Water Detector" requireditems="Steel Bar, FPGA Circuit" requiredtime="10"/> <fabricableitem name="Water Detector" requireditems="Steel Bar, FPGA Circuit" requiredtime="10"/>
<fabricableitem name="Motion Detector" requireditems="Steel Bar, FPGA Circuit" requiredtime="10"/>
<fabricableitem name="Signal Check Component" requireditems="Steel Bar, FPGA Circuit" requiredtime="10"/> <fabricableitem name="Signal Check Component" requireditems="Steel Bar, FPGA Circuit" requiredtime="10"/>
<fabricableitem name="RegEx Find Component" requireditems="Steel Bar, FPGA Circuit" requiredtime="10"/> <fabricableitem name="RegEx Find Component" requireditems="Steel Bar, FPGA Circuit" requiredtime="10"/>
<fabricableitem name="Oscillator" requireditems="Steel Bar, FPGA Circuit" requiredtime="10"/> <fabricableitem name="Oscillator" requireditems="Steel Bar, FPGA Circuit" requiredtime="10"/>
@@ -54,25 +74,42 @@
<fabricableitem name="Underwater Scooter" requireditems="Steel Bar, Polycarbonate Bar, Polycarbonate Bar, FPGA Circuit" requiredtime="30"/> <fabricableitem name="Underwater Scooter" requireditems="Steel Bar, Polycarbonate Bar, Polycarbonate Bar, FPGA Circuit" requiredtime="30"/>
<fabricableitem name="Fulgurium Battery Cell" requireditems="Steel Bar, Fulgurium Bar, Sulphuric Acid" requiredtime="10"/> <fabricableitem name="Fulgurium Battery Cell" requireditems="Steel Bar, Fulgurium Bar" requiredtime="10">
<Item name="Sulphuric Acid" mincondition="0.75"/>
<fabricableitem name="Flare" requireditems="Phosphorus,Aluminium" requiredtime="10"/>
<fabricableitem name ="Stun Grenade" requireditems="Steel Bar, Flash Powder, Chloral Hydrate" requiredtime="20">
<RequiredSkill name="Construction" level="30"/>
</fabricableitem> </fabricableitem>
<fabricableitem name ="Incendium Grenade" requireditems="Stun Grenade, Incendium Bar" requiredtime="20"> <fabricableitem name="Flare" requiredtime="10">
<Item name="Phosphorus" mincondition="0.25" usecondition="true"/>
<Item name="Aluminium" mincondition="0.25" usecondition="true"/>
</fabricableitem>
<fabricableitem name ="Stun Grenade" requireditems="Steel Bar" requiredtime="20">
<RequiredSkill name="Construction" level="30"/>
<Item name="Flash Powder" mincondition="0.75"/>
<Item name="Chloral Hydrate" mincondition="0.75"/>
</fabricableitem>
<fabricableitem name ="Incendium Grenade" requireditems="Steel Bar, Incendium Bar" requiredtime="20">
<RequiredSkill name="Construction" level="40"/> <RequiredSkill name="Construction" level="40"/>
<Item name="Flash Powder" mincondition="0.75"/>
</fabricableitem> </fabricableitem>
<fabricableitem name ="IC-4 Block" requireditems="C-4 Block, Incendium Bar" requiredtime="20"/> <fabricableitem name ="IC-4 Block" requireditems="C-4 Block, Incendium Bar" requiredtime="20"/>
<fabricableitem name="Battery Cell" requireditems="Steel Bar, Copper Bar, Sulphuric Acid" requiredtime="10"/> <fabricableitem name="Battery Cell" requireditems="Steel Bar, Copper Bar" requiredtime="10">
<Item name="Sulphuric Acid" mincondition="0.75"/>
</fabricableitem>
<fabricableitem name="Fuel Rod" requireditems="Steel Bar, Uranium Bar"/> <fabricableitem name="Fuel Rod" requireditems="Steel Bar, Uranium Bar"/>
<fabricableitem name="Incendium Fuel Rod" requireditems="Steel Bar, Incendium Bar"/> <fabricableitem name="Incendium Fuel Rod" requireditems="Steel Bar, Incendium Bar"/>
<fabricableitem name="Uranium Bar">
<Item name="Uranium Powder" count="3" mincondition="0.75"/>
</fabricableitem>
<fabricableitem name="Oxygen Tank" requireditems="Steel Bar" outcondition="0.0"/>
<fabricableitem name="Welding Fuel Tank" requireditems="Steel Bar" outcondition="0.0"/>
</Fabricator> </Fabricator>
<ConnectionPanel selectkey="Action" canbeselected = "true"> <ConnectionPanel selectkey="Action" canbeselected = "true">
@@ -124,6 +161,10 @@
<RequiredSkill name="Medical" level="50"/> <RequiredSkill name="Medical" level="50"/>
</fabricableitem> </fabricableitem>
<fabricableitem name="Chloromydride" requireditems="Stabilozine, Erythrozine, Chloral Hydrate" requiredtime="20">
<RequiredSkill name="Medical" level="50"/>
</fabricableitem>
<fabricableitem name="Flash Powder" requireditems="Aluminium, Potassium" requiredtime="25"> <fabricableitem name="Flash Powder" requireditems="Aluminium, Potassium" requiredtime="25">
<RequiredSkill name="Medical" level="40"/> <RequiredSkill name="Medical" level="40"/>
</fabricableitem> </fabricableitem>
@@ -140,11 +181,17 @@
<RequiredSkill name="Medical" level="60"/> <RequiredSkill name="Medical" level="60"/>
</fabricableitem> </fabricableitem>
<fabricableitem name="Morbusanide" outcondition="0.25" requiredtime="10">
<RequiredSkill name="Medical" level="60"/>
<Item name="Morbusine" mincondition="0.25"/>
<Item name="Stabilozine" mincondition="0.25"/>
</fabricableitem>
<fabricableitem name="Calyxanide" requireditems="Velonaceps Calyx Eggs, Corrigodone" requiredtime="30"> <fabricableitem name="Calyxanide" requireditems="Velonaceps Calyx Eggs, Corrigodone" requiredtime="30">
<RequiredSkill name="Medical" level="60"/> <RequiredSkill name="Medical" level="60"/>
</fabricableitem> </fabricableitem>
<fabricableitem name="Liquid Oxygenite" requireditems="Stabilozine, Oxygenite Shard" requiredtime="30"> <fabricableitem name="Sufforin" requireditems="Erythrozine, Flash Powder, Sulphuric Acid" requiredtime="30">
<RequiredSkill name="Medical" level="60"/> <RequiredSkill name="Medical" level="60"/>
</fabricableitem> </fabricableitem>
</Fabricator> </Fabricator>
@@ -4,7 +4,9 @@
category="Equipment" category="Equipment"
tags="smallitem" tags="smallitem"
description="Allows remote communication between the crew."> description="Allows remote communication between the crew."
price="10">
<Sprite texture ="headset.png" depth="0.6"/> <Sprite texture ="headset.png" depth="0.6"/>
@@ -39,6 +41,10 @@
<Body width="10" radius="10" density="10"/> <Body width="10" radius="10" density="10"/>
<Deconstruct time="10">
<Item name="Bike Horn"/>
</Deconstruct>
<Wearable limbtype="Head" slots="Any,Face"> <Wearable limbtype="Head" slots="Any,Face">
<sprite texture="clownmask.png" limb="Head" origin="0.5,0.5"/> <sprite texture="clownmask.png" limb="Head" origin="0.5,0.5"/>
<StatusEffect type="OnWearing" target="Character" HideFace="true"/> <StatusEffect type="OnWearing" target="Character" HideFace="true"/>
@@ -56,6 +62,12 @@
<Body width="53" height="18" density="30"/> <Body width="53" height="18" density="30"/>
<Deconstruct time="40">
<Item name="Bike Horn"/>
<Item name="Bike Horn"/>
<Item name="Bike Horn"/>
</Deconstruct>
<Wearable slots="Any,Torso+Legs"> <Wearable slots="Any,Torso+Legs">
<sprite texture="clownshirt.png" limb="Torso" sourcerect="0,3,30,58" origin="0.5,0.48" depth="0.02"/> <sprite texture="clownshirt.png" limb="Torso" sourcerect="0,3,30,58" origin="0.5,0.48" depth="0.02"/>
@@ -72,9 +84,12 @@
<sprite texture="clownpants.png" limb="RightLeg" sourcerect="37,0,28,52" origin="0.55,0.5" depth="0.11" hidelimb="true"/> <sprite texture="clownpants.png" limb="RightLeg" sourcerect="37,0,28,52" origin="0.55,0.5" depth="0.11" hidelimb="true"/>
<sprite texture="clownpants.png" limb="LeftLeg" sourcerect="37,0,28,52" origin="0.55,0.5" depth="0.15" hidelimb="true"/> <sprite texture="clownpants.png" limb="LeftLeg" sourcerect="37,0,28,52" origin="0.55,0.5" depth="0.15" hidelimb="true"/>
<sprite texture="clownpants.png" limb="RightFoot" sourcerect="65,41,15,39" origin="0.5,0.35" depth="0.11" hidelimb="true"/> <sprite texture="clownpants.png" limb="RightFoot" sound="footstep_clown" sourcerect="65,41,15,39" origin="0.5,0.35" depth="0.11" hidelimb="true"/>
<sprite texture="clownpants.png" limb="LeftFoot" sourcerect="65,41,15,39" origin="0.5,0.35" depth="0.15" hidelimb="true"/> <sprite texture="clownpants.png" limb="LeftFoot" sound="footstep_clown" sourcerect="65,41,15,39" origin="0.5,0.35" depth="0.15" hidelimb="true"/>
<!-- HENK -->
<damagemodifier damagetype="Blunt" armorsector="0.0,360.0" damagemultiplier="1.0" damagesound="LimbClown"/>
<damagemodifier damagetype="Slash" armorsector="0.0,360.0" damagemultiplier="1.0" damagesound="LimbClown"/>
</Wearable> </Wearable>
</Item> </Item>
</Items> </Items>
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<Items> <Items>
<!-- Medical items -->
<Item <Item
name="Medical Syringe" name="Medical Syringe"
category="Equipment" category="Equipment"
@@ -48,15 +49,20 @@
<Body width="11" height="16" density="20"/> <Body width="11" height="16" density="20"/>
<MeleeWeapon slots="Any,RightHand,LeftHand" <MeleeWeapon canBeCombined="true" slots="Any,RightHand,LeftHand"
aimpos="5,0" handle1="-5,0" holdangle="10" reload="1.0"> aimpos="5,0" handle1="-5,0" holdangle="10" reload="1.0">
<StatusEffect type="OnUse" target="This" Condition="-25.0" disabledeltatime="true"/> <StatusEffect type="OnUse" target="This" Condition="-25.0" disabledeltatime="true"/>
<StatusEffect type="OnUse" target="This, Character" bleeding="-0.1" duration="5.0"> <StatusEffect type="OnUse" target="This, Character" bleeding="-0.1" duration="5.0">
<Sound file="Content/Items/Medical/bandage.ogg" range="500"/> <Sound file="Content/Items/Medical/bandage.ogg" range="500"/>
</StatusEffect> </StatusEffect>
<StatusEffect type="OnUse" target="This, Character" health="0.1" duration="5.0" checkconditionalalways="true">
<!-- Only give healing effect if their health is more than 50 -->
<Conditional Health="gt 50"/>
</StatusEffect>
</MeleeWeapon> </MeleeWeapon>
</Item> </Item>
<!-- Ingredients/weak chems -->
<Item <Item
name="Iron Powder" name="Iron Powder"
category="Material" category="Material"
@@ -67,7 +73,11 @@
<Body width="8" height="16" density="40"/> <Body width="8" height="16" density="40"/>
<Throwable slots="Any,RightHand,LeftHand" throwforce="4.0" aimpos="35,-10"/> <Throwable canBeCombined="true" slots="Any,RightHand,LeftHand" throwforce="4.0" aimpos="35,-10">
<StatusEffect tags="poison,iron" type="OnUse" target="Character" Health="-2" duration="10">
<RequiredItem name="Medical Syringe" type="Container"/>
</StatusEffect>
</Throwable>
</Item> </Item>
<Item <Item
@@ -75,7 +85,8 @@
category="Material" category="Material"
spritecolor="1.0,1.0,0.7,1.0" spritecolor="1.0,1.0,0.7,1.0"
Tags="smallitem,chem,medical" Tags="smallitem,chem,medical"
description="A mild stimulant which is used as an incredient in the manufacture of various medicines." description="A mild stimulant which is used as an ingredient in the manufacture of various medicines."
canuseonself="true"
price="10"> price="10">
<Sprite texture ="med.png" sourcerect="15,15,8,17" depth="0.6" /> <Sprite texture ="med.png" sourcerect="15,15,8,17" depth="0.6" />
@@ -83,17 +94,139 @@
<Body width="8" height="17" density="20"/> <Body width="8" height="17" density="20"/>
<ItemComponent> <ItemComponent>
<StatusEffect type="OnUse" target="Character" Health="0.1" duration="20"/> <StatusEffect tags="medical" type="OnUse" target="Character" Health="0.1" duration="20"/>
<StatusEffect type="OnUse" target="This" Condition="-25.0" disabledeltatime="true"/> <StatusEffect type="OnUse" target="This" Condition="-25.0" disabledeltatime="true"/>
</ItemComponent> </ItemComponent>
<Throwable slots="Any,RightHand,LeftHand" throwforce="4.0" aimpos="35,-10"> <Throwable canBeCombined="true" slots="Any,RightHand,LeftHand" throwforce="4.0" aimpos="35,-10">
<StatusEffect type="OnUse" target="Character" Health="0.3" Oxygen="0.3" duration="10"> <StatusEffect tags="medical" type="OnUse" target="Character" Health="0.3" Oxygen="0.3" duration="10">
<RequiredItem name="Medical Syringe" type="Container"/>
</StatusEffect>
</Throwable>
</Item>
<Item
name="Chlorine"
category="Material"
spritecolor="1.0,1.0,1.0,0.6"
Tags="smallitem,chem,medical"
price="20">
<Sprite texture ="med.png" sourcerect="15,15,8,17" depth="0.6"/>
<Body width="8" height="17" density="10"/>
<Throwable canBeCombined="true" slots="Any,RightHand,LeftHand" throwforce="4.0" aimpos="35,-10">
<StatusEffect tags="poison,chlorine" type="OnUse" target="Character" Health="-0.1" duration="20.0">
<RequiredItem name="Medical Syringe" type="Container"/> <RequiredItem name="Medical Syringe" type="Container"/>
</StatusEffect> </StatusEffect>
</Throwable> </Throwable>
</Item> </Item>
<Item
name="Ethanol"
category="Material"
spritecolor="0.0,0.9,0.1,1.0"
Tags="smallitem,chem,medical"
canuseonself="true"
price="20">
<ItemComponent>
<StatusEffect type="OnUse" target="This" Condition="-25.0" disabledeltatime="true"/>
<StatusEffect tags="drunk" type="OnUse" target="Character" SpeedMultiplier="0.8" setvalue="true" duration="20.0"/>
</ItemComponent>
<Sprite texture ="med.png" sourcerect="15,15,8,17" depth="0.6"/>
<Body width="8" height="7" density="10"/>
<Throwable canBeCombined="true" slots="Any,RightHand,LeftHand" throwforce="4.0" aimpos="35,-10">
<StatusEffect tags="drunk" type="OnUse" target="Character" SpeedMultiplier="0.8" setvalue="true" duration="20.0">
<RequiredItem name="Medical Syringe" type="Container"/>
</StatusEffect>
</Throwable>
</Item>
<Item
name="Aluminium"
category="Material"
spritecolor="0.7,0.7,0.7,1.0"
Tags="smallitem,chem,medical"
price="20">
<Sprite texture ="med.png" sourcerect="24,16,8,16" depth="0.6"/>
<Body width="8" height="16" density="10"/>
<Throwable canBeCombined="true" slots="Any,RightHand,LeftHand" throwforce="4.0" aimpos="35,-10">
<StatusEffect type="OnUse" target="Character" Health="-5.0" disabledeltatime="true">
<RequiredItem name="Medical Syringe" type="Container"/>
</StatusEffect>
</Throwable>
</Item>
<Item
name="Potassium"
category="Material"
spritecolor="0.8,0.8,0.8,1.0"
Tags="smallitem,chem,medical"
price="20">
<Sprite texture ="med.png" sourcerect="24,16,8,16" depth="0.6"/>
<Body width="8" height="16" density="10"/>
<Throwable canBeCombined="true" slots="Any,RightHand,LeftHand" throwforce="4.0" aimpos="35,-10">
<StatusEffect type="OnUse" target="Character" Health="-5.0" disabledeltatime="true">
<RequiredItem name="Medical Syringe" type="Container"/>
</StatusEffect>
<StatusEffect type="InWater" target="This" Condition="0.0" setvalue="true">
<Sound file="Content/Items/Reactor/explosion.ogg"/>
<Explosion range="250.0" structuredamage="10" damage="20" stun="5" force="5.0"/>
</StatusEffect>
</Throwable>
</Item>
<Item
name="Phosphorus"
category="Material"
spritecolor="0.5,0.0,0.0,1.0"
Tags="smallitem,chem,medical"
price="20">
<Sprite texture ="med.png" sourcerect="24,16,8,16" depth="0.6"/>
<Body width="8" height="16" density="10"/>
<Throwable canBeCombined="true" slots="Any,RightHand,LeftHand" throwforce="4.0" aimpos="35,-10">
<StatusEffect type="OnUse" target="Character" Health="-5.0" disabledeltatime="true">
<RequiredItem name="Medical Syringe" type="Container"/>
</StatusEffect>
</Throwable>
</Item>
<!-- Helpful chems -->
<Item
name="Chloromydride"
category="Material"
spritecolor="0.7,0.9,1.0,1.0"
Tags="smallitem,chem,medical"
description="A strong synaptic stimulant and cardiostimulant which is used as a preventative measure against critical condition. Should only be injected once every 30 seconds."
price="50">
<Sprite texture ="med.png" sourcerect="15,15,8,17" depth="0.6" />
<Body width="8" height="16" density="20"/>
<Throwable canBeCombined="true" slots="Any,RightHand,LeftHand" throwforce="4.0" aimpos="35,-10">
<StatusEffect tags="medical" type="OnUse" target="Character" health="1.0" bleeding="-0.2" Oxygen="0.6" duration="30" stackable="false" checkconditionalalways="true">
<!-- Rapidly removes bleeding and stabilizes oxygen intake while also counteracting crit damage so they won't die. Doesn't prevent poisons.
EXTREMELY useful to follow up with CPR, especially if they were bleeding before. -->
<Conditional Health="lt 0.1"/>
<RequiredItem name="Medical Syringe" type="Container"/>
</StatusEffect>
</Throwable>
</Item>
<Item <Item
name="Erythrozine" name="Erythrozine"
category="Material" category="Material"
@@ -107,8 +240,8 @@
<Body width="8" height="16" density="20"/> <Body width="8" height="16" density="20"/>
<Throwable slots="Any,RightHand,LeftHand" throwforce="4.0" aimpos="35,-10"> <Throwable canBeCombined="true" slots="Any,RightHand,LeftHand" throwforce="4.0" aimpos="35,-10">
<StatusEffect type="OnUse" target="Character" Health="-0.3" Oxygen="2.0" duration="10"> <StatusEffect tags="medical" type="OnUse" target="Character" Health="-0.3" Oxygen="2.0" duration="10">
<RequiredItem name="Medical Syringe" type="Container"/> <RequiredItem name="Medical Syringe" type="Container"/>
</StatusEffect> </StatusEffect>
</Throwable> </Throwable>
@@ -128,12 +261,12 @@
<Body width="8" height="16" density="20"/> <Body width="8" height="16" density="20"/>
<ItemComponent> <ItemComponent>
<StatusEffect type="OnUse" target="Character" Bleeding="-0.1" duration="10.0"/> <StatusEffect tags="medical" type="OnUse" target="Character" Bleeding="-0.1" duration="10.0"/>
<StatusEffect type="OnUse" target="This" Condition="-25.0" disabledeltatime="true"/> <StatusEffect type="OnUse" target="This" Condition="-25.0" disabledeltatime="true"/>
</ItemComponent> </ItemComponent>
<Throwable slots="Any,RightHand,LeftHand" throwforce="4.0" aimpos="35,-10"> <Throwable canBeCombined="true" slots="Any,RightHand,LeftHand" throwforce="4.0" aimpos="35,-10">
<StatusEffect type="OnUse" target="Character" Bleeding="-0.2" duration="5.0"> <StatusEffect tags="medical" type="OnUse" target="Character" Health="0.3" Bleeding="-0.2" duration="5.0">
<RequiredItem name="Medical Syringe" type="Container"/> <RequiredItem name="Medical Syringe" type="Container"/>
</StatusEffect> </StatusEffect>
</Throwable> </Throwable>
@@ -155,11 +288,11 @@
<ItemComponent> <ItemComponent>
<StatusEffect type="OnUse" target="This" Condition="-25.0" disabledeltatime="true"/> <StatusEffect type="OnUse" target="This" Condition="-25.0" disabledeltatime="true"/>
<StatusEffect type="OnUse" target="Character, This" Health="-0.5" duration="10"/> <StatusEffect tags="medical" type="OnUse" target="Character, This" Health="-0.5" duration="10"/>
</ItemComponent> </ItemComponent>
<Throwable slots="Any,RightHand,LeftHand" throwforce="4.0" aimpos="35,-10"> <Throwable canBeCombined="true" slots="Any,RightHand,LeftHand" throwforce="4.0" aimpos="35,-10">
<StatusEffect type="OnUse" target="Character" Health="3.0" duration="5.0"> <StatusEffect tags="medical" type="OnUse" target="Character" Health="3.0" duration="5.0">
<RequiredItem name="Medical Syringe" type="Container"/> <RequiredItem name="Medical Syringe" type="Container"/>
</StatusEffect> </StatusEffect>
</Throwable> </Throwable>
@@ -178,181 +311,8 @@
<Body width="8" height="16" density="20"/> <Body width="8" height="16" density="20"/>
<Throwable slots="Any,RightHand,LeftHand" throwforce="4.0" aimpos="35,-10"> <Throwable canBeCombined="true" slots="Any,RightHand,LeftHand" throwforce="4.0" aimpos="35,-10">
<StatusEffect type="OnUse" target="Character" Health="1.0" Oxygen="2.0" Bleeding="-0.05" duration="60.0"> <StatusEffect tags="medical" type="OnUse" target="Character" Health="0.5" Oxygen="0.5" Bleeding="-0.025" duration="60.0">
<RequiredItem name="Medical Syringe" type="Container"/>
</StatusEffect>
</Throwable>
</Item>
<Item
name="Chlorine"
category="Material"
spritecolor="1.0,1.0,1.0,0.6"
Tags="smallitem,chem,medical"
price="20">
<Sprite texture ="med.png" sourcerect="15,15,8,17" depth="0.6"/>
<Body width="8" height="17" density="10"/>
<Throwable slots="Any,RightHand,LeftHand" throwforce="4.0" aimpos="35,-10">
<StatusEffect type="OnUse" target="Character" Health="-0.1" duration="20.0">
<RequiredItem name="Medical Syringe" type="Container"/>
</StatusEffect>
</Throwable>
</Item>
<Item
name="Ethanol"
category="Material"
spritecolor="0.0,0.9,0.1,1.0"
Tags="smallitem,chem,medical"
canuseonself="true"
price="20">
<ItemComponent>
<StatusEffect type="OnUse" target="This" Condition="-25.0" disabledeltatime="true"/>
<StatusEffect type="OnUse" target="Character" SpeedMultiplier="0.8" setvalue="true" duration="20.0"/>
</ItemComponent>
<Sprite texture ="med.png" sourcerect="15,15,8,17" depth="0.6"/>
<Body width="8" height="7" density="10"/>
<Throwable slots="Any,RightHand,LeftHand" throwforce="4.0" aimpos="35,-10">
<StatusEffect type="OnUse" target="Character" SpeedMultiplier="0.8" setvalue="true" duration="20.0">
<RequiredItem name="Medical Syringe" type="Container"/>
</StatusEffect>
</Throwable>
</Item>
<Item
name="Aluminium"
category="Material"
spritecolor="0.7,0.7,0.7,1.0"
Tags="smallitem,chem,medical"
price="20">
<Sprite texture ="med.png" sourcerect="24,16,8,16" depth="0.6"/>
<Body width="8" height="16" density="10"/>
<Throwable slots="Any,RightHand,LeftHand" throwforce="4.0" aimpos="35,-10">
<StatusEffect type="OnUse" target="Character" Health="-5.0" disabledeltatime="true">
<RequiredItem name="Medical Syringe" type="Container"/>
</StatusEffect>
</Throwable>
</Item>
<Item
name="Potassium"
category="Material"
spritecolor="0.8,0.8,0.8,1.0"
Tags="smallitem,chem,medical"
price="20">
<Sprite texture ="med.png" sourcerect="24,16,8,16" depth="0.6"/>
<Body width="8" height="16" density="10"/>
<Throwable slots="Any,RightHand,LeftHand" throwforce="4.0" aimpos="35,-10">
<StatusEffect type="OnUse" target="Character" Health="-5.0" disabledeltatime="true">
<RequiredItem name="Medical Syringe" type="Container"/>
</StatusEffect>
</Throwable>
</Item>
<Item
name="Flash Powder"
category="Material"
spritecolor="0.1,0.1,0.1,1.0"
Tags="smallitem,chem,explosive"
impacttolerance="8"
price="50">
<Sprite texture ="med.png" sourcerect="24,16,8,16" depth="0.6"/>
<Body width="8" height="16" density="10"/>
<Throwable slots="Any,RightHand,LeftHand" throwforce="4.0" aimpos="35,-10">
<StatusEffect type="OnImpact" target="This" Condition="0.0" setvalue="true"/>
<StatusEffect type="OnFire" target="this" condition="-50"/>
<StatusEffect type="OnBroken" target="This" Condition="-100.0">
<Sound file="Content/Items/Reactor/explosion.ogg"/>
<Explosion range="500" damage="5" stun="3" force="0.1"/>
</StatusEffect>
</Throwable>
</Item>
<Item
name="Chloral Hydrate"
category="Material"
spritecolor="1.0,1.0,1.0,0.8"
Tags="smallitem,chem,medical"
price="20">
<Sprite texture ="med.png" sourcerect="15,15,8,17" depth="0.6"/>
<Body width="8" height="17" density="10"/>
<Throwable slots="Any,RightHand,LeftHand" throwforce="4.0" aimpos="35,-10">
<StatusEffect type="OnUse" target="Character" Health="-5.0" Stun="10" disabledeltatime="true">
<RequiredItem name="Medical Syringe" type="Container"/>
</StatusEffect>
</Throwable>
</Item>
<Item
name="Phosphorus"
category="Material"
spritecolor="0.5,0.0,0.0,1.0"
Tags="smallitem,chem,medical"
price="20">
<Sprite texture ="med.png" sourcerect="24,16,8,16" depth="0.6"/>
<Body width="8" height="16" density="10"/>
<Throwable slots="Any,RightHand,LeftHand" throwforce="4.0" aimpos="35,-10">
<StatusEffect type="OnUse" target="Character" Health="-5.0" disabledeltatime="true">
<RequiredItem name="Medical Syringe" type="Container"/>
</StatusEffect>
</Throwable>
</Item>
<Item
name="Sulphuric Acid"
category="Material"
spritecolor="0.5,0.0,0.0,1.0"
Tags="smallitem,chem,medical"
price="50">
<Sprite texture ="med.png" sourcerect="15,15,8,17" depth="0.6"/>
<Body width="8" height="17" density="10"/>
<Throwable slots="Any,RightHand,LeftHand" throwforce="4.0" aimpos="35,-10">
<StatusEffect type="OnUse" target="Character" Health="-1.0" duration="60.0">
<RequiredItem name="Medical Syringe" type="Container"/>
</StatusEffect>
</Throwable>
</Item>
<Item
name="Uranium Powder"
category="Material"
spritecolor="0.2,0.35,0.06,1.0"
Tags="smallitem,chem,medical"
price="50">
<Sprite texture ="med.png" sourcerect="24,16,8,16" depth="0.6"/>
<Body width="8" height="16" density="25"/>
<Throwable slots="Any,RightHand,LeftHand" throwforce="4.0" aimpos="35,-10">
<StatusEffect type="OnUse" target="Character" Health="-5.0" duration="60.0">
<RequiredItem name="Medical Syringe" type="Container"/> <RequiredItem name="Medical Syringe" type="Container"/>
</StatusEffect> </StatusEffect>
</Throwable> </Throwable>
@@ -370,27 +330,157 @@
<Body width="8" height="16" density="15"/> <Body width="8" height="16" density="15"/>
<Throwable slots="Any,RightHand,LeftHand" throwforce="4.0" aimpos="35,-10"> <Throwable canBeCombined="true" slots="Any,RightHand,LeftHand" throwforce="4.0" aimpos="35,-10">
<StatusEffect type="OnUse" target="Character" SpeedMultiplier="1.5" setvalue="true" duration="60.0"> <StatusEffect tags="medical" type="OnUse" target="Character" SpeedMultiplier="1.5" setvalue="true" duration="60.0">
<RequiredItem name="Medical Syringe" type="Container"/> <RequiredItem name="Medical Syringe" type="Container"/>
</StatusEffect> </StatusEffect>
</Throwable> </Throwable>
</Item> </Item>
<Item <Item
name="Morbusine" name="Calyxanide"
category="Material" category="Material"
spritecolor="0.0,0.0,0.0,1.0" spritecolor="0.0,0.0,0.0,1.0"
Tags="smallitem,chem,medical" Tags="smallitem,chem,medical"
description="A highly potent neurotoxin." description="An antiparasitic drug used in the treatment of husk parasite infections. Might require higher dosage to cure the infection at later stages."
price="200"> price="300">
<Sprite texture ="med.png" sourcerect="24,16,8,16" depth="0.6"/> <Sprite texture ="med.png" sourcerect="24,16,8,16" depth="0.6"/>
<Body width="8" height="16" density="10"/> <Body width="8" height="16" density="10"/>
<Throwable slots="Any,RightHand,LeftHand" throwforce="4.0" aimpos="35,-10"> <Throwable canBeCombined="true" slots="Any,RightHand,LeftHand" throwforce="4.0" aimpos="35,-10">
<StatusEffect type="OnUse" target="Character" Health="-10.0" duration="60.0"> <StatusEffect type="OnUse" target="Character" HuskInfectionState="-0.2" setvalue="true">
<Conditional HuskInfectionState="lt 1.0"/>
<RequiredItem name="Medical Syringe" type="Container"/>
</StatusEffect>
<StatusEffect tags="poison,calyxanide" type="OnUse" target="Character" Health="-3.0" duration="10.0">
<!-- Injecting a still-conscious Husk will only piss it off and kill the "conscious" faster -->
<Conditional HuskInfectionState="eq 1.0"/>
<RequiredItem name="Medical Syringe" type="Container"/>
</StatusEffect>
<StatusEffect tags="poison,calyxanide" type="OnUse" target="Character" Health="-5.0" duration="10.0">
<Conditional SpeciesName="husk"/>
<RequiredItem name="Medical Syringe" type="Container"/>
</StatusEffect>
</Throwable>
</Item>
<Item
name="Morbusanide"
category="Material"
spritecolor="0.0,0.0,0.2,1.0"
Tags="smallitem,chem,medical"
description="A morbusine antidote.">
<Sprite texture ="med.png" sourcerect="24,16,8,16" depth="0.6"/>
<Body width="8" height="16" density="10"/>
<Throwable canBeCombined="true" slots="Any,RightHand,LeftHand" throwforce="4.0" aimpos="35,-10">
<StatusEffect type="OnUse" target="Character">
<RequiredItem name="Medical Syringe" type="Container"/>
<Conditional hasstatustag="morbusine"/>
<Cancel/>
</StatusEffect>
</Throwable>
</Item>
<Item
name="Liquid Oxygenite"
category="Material"
spritecolor="0.6,0.8,1.0,1.0"
Tags="smallitem,chem,medical"
impacttolerance="8"
description="A mildy toxic solution that slowly releases oxygen into the bloodstream when injected.">
<Sprite texture ="med.png" sourcerect="24,16,8,16" depth="0.6" />
<Body width="8" height="16" density="20"/>
<Throwable canBeCombined="true" slots="Any,RightHand,LeftHand" throwforce="4.0" aimpos="35,-10">
<StatusEffect tags="medical" type="OnUse" target="Character" Health="-0.5" Oxygen="10.0" duration="60">
<RequiredItem name="Medical Syringe" type="Container"/>
</StatusEffect>
<StatusEffect type="OnImpact" target="This" Condition="0.0" setvalue="true">
<sound file="Content/Items/Reactor/explosion.ogg"/>
<Explosion range="300.0" structuredamage="50" damage="30" stun="5" force="10.0"/>
</StatusEffect>
</Throwable>
</Item>
<!-- Harmful and toxic chems -->
<Item
name="Flash Powder"
category="Material"
spritecolor="0.1,0.1,0.1,1.0"
Tags="smallitem,chem,explosive"
impacttolerance="8"
price="50">
<Sprite texture ="med.png" sourcerect="24,16,8,16" depth="0.6"/>
<Body width="8" height="16" density="10"/>
<Throwable canBeCombined="true" slots="Any,RightHand,LeftHand" throwforce="4.0" aimpos="35,-10">
<StatusEffect type="OnImpact" target="This" Condition="0.0" setvalue="true"/>
<StatusEffect type="OnFire" target="this" condition="-50"/>
<StatusEffect type="OnBroken" target="This" Condition="-100.0">
<Sound file="Content/Items/Reactor/explosion.ogg"/>
<Explosion range="500" damage="5" stun="3" force="0.1"/>
</StatusEffect>
</Throwable>
</Item>
<Item
name="Chloral Hydrate"
category="Material"
spritecolor="1.0,1.0,1.0,0.8"
Tags="smallitem,chem,medical"
price="20">
<Sprite texture ="med.png" sourcerect="15,15,8,17" depth="0.6"/>
<Body width="8" height="17" density="10"/>
<Throwable canBeCombined="true" slots="Any,RightHand,LeftHand" throwforce="4.0" aimpos="35,-10">
<StatusEffect type="OnUse" target="Character" Health="-5.0" Stun="10" disabledeltatime="true">
<RequiredItem name="Medical Syringe" type="Container"/>
</StatusEffect>
</Throwable>
</Item>
<Item
name="Sulphuric Acid"
category="Material"
spritecolor="0.5,0.0,0.0,1.0"
Tags="smallitem,chem,medical"
price="50">
<Sprite texture ="med.png" sourcerect="15,15,8,17" depth="0.6"/>
<Body width="8" height="17" density="10"/>
<Throwable canBeCombined="true" slots="Any,RightHand,LeftHand" throwforce="4.0" aimpos="35,-10">
<StatusEffect tags="poison,acid" type="OnUse" target="Character" Health="-1.0" duration="30.0">
<RequiredItem name="Medical Syringe" type="Container"/>
</StatusEffect>
</Throwable>
</Item>
<Item
name="Uranium Powder"
category="Material"
spritecolor="0.2,0.35,0.06,1.0"
Tags="smallitem,chem,medical"
price="50">
<Sprite texture ="med.png" sourcerect="24,16,8,16" depth="0.6"/>
<Body width="8" height="16" density="25"/>
<Throwable canBeCombined="true" slots="Any,RightHand,LeftHand" throwforce="4.0" aimpos="35,-10">
<StatusEffect tags="poison,uranium" type="OnUse" target="Character" bleeding="0.1" duration="60.0">
<RequiredItem name="Medical Syringe" type="Container"/> <RequiredItem name="Medical Syringe" type="Container"/>
</StatusEffect> </StatusEffect>
</Throwable> </Throwable>
@@ -402,52 +492,85 @@
spritecolor="0.0,0.0,0.0,1.0" spritecolor="0.0,0.0,0.0,1.0"
Tags="smallitem,chem,medical" Tags="smallitem,chem,medical"
description="Dormant eggs of the Europan lifeform colloquially referred to as 'husk parasite'." description="Dormant eggs of the Europan lifeform colloquially referred to as 'husk parasite'."
price="200"> price="2000">
<Sprite texture ="med.png" sourcerect="24,16,8,16" depth="0.6"/> <Sprite texture ="med.png" sourcerect="24,16,8,16" depth="0.6"/>
<Body width="8" height="16" density="10"/> <Body width="8" height="16" density="10"/>
<Throwable slots="Any,RightHand,LeftHand" throwforce="4.0" aimpos="35,-10"> <Throwable canBeCombined="true" slots="Any,RightHand,LeftHand" throwforce="4.0" aimpos="35,-10">
<StatusEffect type="OnUse" target="Character" HuskInfectionState="0.01"> <StatusEffect type="OnUse" target="Character" HuskInfectionState="0.01">
<!-- HuskInfectionState must be less than 0.01 so you can't speed up the infection -->
<Conditional HuskInfectionState="lt 0.01"/>
<RequiredItem name="Medical Syringe" type="Container"/> <RequiredItem name="Medical Syringe" type="Container"/>
</StatusEffect> </StatusEffect>
</Throwable> </Throwable>
</Item> </Item>
<Item <Item
name="Calyxanide" name="Morbusine"
category="Material" category="Material"
spritecolor="0.0,0.0,0.0,1.0" spritecolor="0.0,0.0,0.0,1.0"
Tags="smallitem,chem,medical" Tags="smallitem,chem,medical"
description="An antiparasitic drug used in the treatment of husk parasite infections." description="A highly potent neurotoxin."
price="300"> price="1000">
<Sprite texture ="med.png" sourcerect="24,16,8,16" depth="0.6"/> <Sprite texture ="med.png" sourcerect="24,16,8,16" depth="0.6"/>
<Body width="8" height="16" density="10"/> <Body width="8" height="16" density="10"/>
<Throwable slots="Any,RightHand,LeftHand" throwforce="4.0" aimpos="35,-10"> <Throwable canBeCombined="true" slots="Any,RightHand,LeftHand" throwforce="4.0" aimpos="35,-10">
<StatusEffect type="OnUse" target="Character" HuskInfectionState="0.0" setvalue="true"> <StatusEffect tags="poison,morbusine" type="OnUse" target="Character" Health="-5.0" duration="60.0">
<RequiredItem name="Medical Syringe" type="Container"/> <RequiredItem name="Medical Syringe" type="Container"/>
</StatusEffect> </StatusEffect>
</Throwable> </Throwable>
</Item> </Item>
<Item <Item
name="Liquid Oxygenite" name="Nitroglycerin"
category="Material" category="Material"
spritecolor="0.6,0.8,1.0,1.0" description="A highly unstable liquid that may explode when subjected to heat or physical shock."
Tags="smallitem,chem,medical" spritecolor="1.0,1.0,1.0,1.0"
canuseonself="true" Tags="smallitem,chem,medical"
description="A mildy toxic solution that slowly releases oxygen into the bloodstream when injected."> impacttolerance="4">
<Sprite texture ="med.png" sourcerect="24,16,8,16" depth="0.6" /> <Sprite texture ="Content/Items/Medical/med.png" sourcerect="24,16,8,16" depth="0.6"/>
<Body width="8" height="16" density="20"/> <Body width="25" height="5" density="10"/>
<Throwable slots="Any,RightHand,LeftHand" throwforce="4.0" aimpos="35,-10"> <Throwable canBeCombined="true" slots="Any,RightHand,LeftHand" throwforce="4.0" aimpos="35,-10">
<StatusEffect type="OnUse" target="Character" Health="-0.1" Oxygen="10.0" duration="60"> <StatusEffect type="OnImpact" target="This" Condition="0.0" setvalue="true"/>
<StatusEffect type="OnFire" target="This" Condition="-50.0"/>
<StatusEffect type="OnBroken" target="This" Condition="-100.0">
<sound file="Content/Items/Reactor/explosion.ogg" range="3000"/>
<Explosion range="600.0" structuredamage="400" damage="300" stun="5" force="20.0" severlimbsprobability="0.4" decal="explosion" decalsize="0.5"/>
</StatusEffect>
<StatusEffect type="OnUse" target="This" Condition="-100.0">
<RequiredItem name="Medical Syringe" type="Container"/>
</StatusEffect>
</Throwable>
</Item>
<Item
name="Sufforin"
category="Material"
spritecolor="1.0,0.3,0.3,1.0"
Tags="smallitem,chem,medical"
description="A devious poison with a delayed effect.">
<!-- Can only be crafted. Direct counter to Sufforin is Liquid Oxygenite, though it's not strictly an antidote.
Two injections to choke slightly faster than welding fuel. -->
<Sprite texture ="med.png" sourcerect="24,16,8,16" depth="0.6"/>
<Body width="8" height="16" density="10"/>
<Throwable canBeCombined="true" slots="Any,RightHand,LeftHand" throwforce="4.0" aimpos="35,-10">
<StatusEffect type="OnUse" target="Character" Health="-5.0">
<RequiredItem name="Medical Syringe" type="Container"/>
</StatusEffect>
<!-- Did You Know? If OxygenAvailable is too low, character will take -5 Oxygen loss per tick, otherwise they restore +10 oxygen. -->
<StatusEffect tags="poison,sufforin" type="OnUse" target="Character" Oxygen="-5.0" OxygenAvailable="-10000.0" Health="-0.5" duration="60.0" delay="20.0">
<RequiredItem name="Medical Syringe" type="Container"/> <RequiredItem name="Medical Syringe" type="Container"/>
</StatusEffect> </StatusEffect>
</Throwable> </Throwable>
@@ -61,7 +61,9 @@
<Deconstruct time="10"> <Deconstruct time="10">
<Item name="Steel Bar"/> <Item name="Steel Bar"/>
<Item name="Uranium Bar" requirefullcondition="true"/> <Item name="Uranium Powder" mincondition="0.1" maxcondition="0.5"/>
<Item name="Uranium Powder" mincondition="0.1" maxcondition="0.9"/>
<Item name="Uranium Bar" mincondition="0.9"/>
</Deconstruct> </Deconstruct>
<Sprite texture ="fuelrod.png" depth="0.55"/> <Sprite texture ="fuelrod.png" depth="0.55"/>
@@ -78,7 +80,7 @@
<Deconstruct time="10"> <Deconstruct time="10">
<Item name="Steel Bar"/> <Item name="Steel Bar"/>
<Item name="Incendium Bar" requirefullcondition="true"/> <Item name="Incendium Bar" mincondition="0.95"/>
</Deconstruct> </Deconstruct>
<Sprite texture ="fuelrod.png" depth="0.55"/> <Sprite texture ="fuelrod.png" depth="0.55"/>
@@ -92,7 +94,7 @@
<Item <Item
name="Heat Absorber" name="Heat Absorber"
Tags="smallitem" Tags="smallitem"
> price="50">
<Sprite texture ="heatabsorber.png"/> <Sprite texture ="heatabsorber.png"/>
@@ -181,7 +181,7 @@
<MeleeWeapon slots="Any,RightHand,LeftHand" <MeleeWeapon slots="Any,RightHand,LeftHand"
aimpos="50,0" handle1="-5,0" holdangle="30" reload="1.0"> aimpos="50,0" handle1="-5,0" holdangle="30" reload="1.0">
<Attack damage="5" stun="0.2" damagetype="Blunt" sound="Content/Items/Weapons/smack.ogg"/> <Attack damage="5" structuredamage="5" stun="0.2" damagetype="Blunt" sound="Content/Items/Weapons/smack.ogg"/>
</MeleeWeapon> </MeleeWeapon>
</Item> </Item>
@@ -198,7 +198,7 @@
<MeleeWeapon slots="RightHand+LeftHand,Any" <MeleeWeapon slots="RightHand+LeftHand,Any"
controlpose="true" aimpos="50,0" handle1="-5,0" handle2="-3,5" holdangle="30" reload="1.7"> controlpose="true" aimpos="50,0" handle1="-5,0" handle2="-3,5" holdangle="30" reload="1.7">
<Attack damage="20" stun="0.6" damagetype="Blunt" sound="Content/Items/Weapons/smack.ogg"/> <Attack damage="20" structuredamage="10" stun="0.6" damagetype="Blunt" sound="Content/Items/Weapons/smack.ogg"/>
</MeleeWeapon> </MeleeWeapon>
</Item> </Item>
@@ -271,8 +271,10 @@
tags="smallitem"> tags="smallitem">
<Deconstruct time="10"> <Deconstruct time="10">
<Item name="Phosphorus"/> <Item name="Phosphorus" mincondition="0.9" outcondition="0.25"/>
<Item name="Aluminium"/> <Item name="Aluminium" mincondition="0.9" outcondition="0.25"/>
<Item name="Phosphorus" mincondition="0.5" maxcondition="0.9" outcondition="0.1"/>
<Item name="Aluminium" mincondition="0.5" maxcondition="0.9" outcondition="0.1"/>
</Deconstruct> </Deconstruct>
@@ -104,31 +104,4 @@
</input> </input>
</ConnectionPanel> </ConnectionPanel>
</Item> </Item>
<Item
name="Nitroglycerin"
category="Material"
description="A highly unstable liquid that may explode when subjected to heat or physical shock."
spritecolor="1.0,1.0,1.0,1.0"
Tags="smallitem,chem,medical"
impacttolerance="4">
<Sprite texture ="Content/Items/Medical/med.png" sourcerect="24,16,8,16" depth="0.6"/>
<Body width="25" height="5" density="10"/>
<Throwable slots="Any,RightHand,LeftHand" throwforce="4.0" aimpos="35,-10">
<StatusEffect type="OnImpact" target="This" Condition="0.0" setvalue="true"/>
<StatusEffect type="OnFire" target="This" Condition="-50.0"/>
<StatusEffect type="OnBroken" target="This" Condition="-100.0">
<sound file="Content/Items/Reactor/explosion.ogg" range="3000"/>
<Explosion range="600.0" structuredamage="400" damage="300" stun="5" force="20.0" severlimbsprobability="0.4" decal="explosion" decalsize="0.5"/>
</StatusEffect>
<StatusEffect type="OnUse" target="This" Condition="-100.0">
<RequiredItem name="Medical Syringe" type="Container"/>
</StatusEffect>
</Throwable>
</Item>
</Items> </Items>
@@ -144,6 +144,12 @@
price="200" price="200"
tags="smallitem,weapon"> tags="smallitem,weapon">
<Deconstruct time="10">
<Item name="Steel Bar"/>
<Item name="Flash Powder" mincondition="0.9"/>
<Item name="Chloral Hydrate" mincondition="0.9"/>
</Deconstruct>
<Sprite texture="weapons.png" sourcerect="98,0,11,24" depth="0.55"/> <Sprite texture="weapons.png" sourcerect="98,0,11,24" depth="0.55"/>
<Body width="11" height="24" density="30"/> <Body width="11" height="24" density="30"/>
@@ -161,6 +167,12 @@
category="Equipment" category="Equipment"
tags="smallitem,weapon"> tags="smallitem,weapon">
<Deconstruct time="10">
<Item name="Steel Bar"/>
<Item name="Flash Powder" mincondition="0.9"/>
<Item name="Incendium Bar" mincondition="0.9"/>
</Deconstruct>
<Sprite texture="weapons.png" sourcerect="98,0,11,24" depth="0.55"/> <Sprite texture="weapons.png" sourcerect="98,0,11,24" depth="0.55"/>
<Body width="11" height="24" density="30"/> <Body width="11" height="24" density="30"/>
@@ -222,8 +234,8 @@
<Deconstruct time="10"> <Deconstruct time="10">
<Item name="Steel Bar"/> <Item name="Steel Bar"/>
<Item name="FPGA Circuit"/> <Item name="Copper Bar" mincondition="0.5"/>
<Item name="Copper Bar"/> <Item name="Sulphuric Acid" mincondition="0.9"/>
</Deconstruct> </Deconstruct>
<Sprite texture="weapons.png" sourcerect="0,0,20,9" depth="0.8"/> <Sprite texture="weapons.png" sourcerect="0,0,20,9" depth="0.8"/>
@@ -242,8 +254,8 @@
<Deconstruct time="10"> <Deconstruct time="10">
<Item name="Steel Bar"/> <Item name="Steel Bar"/>
<Item name="FPGA Circuit"/> <Item name="Fulgurium Bar" mincondition="0.8"/>
<Item name="Fulgurium Bar"/> <Item name="Sulphuric Acid" mincondition="0.9"/>
</Deconstruct> </Deconstruct>
<Sprite texture="weapons.png" sourcerect="0,0,20,9" depth="0.8"/> <Sprite texture="weapons.png" sourcerect="0,0,20,9" depth="0.8"/>
@@ -38,7 +38,11 @@
<damagesound file="Content/Sounds/Damage/HitArmor1.ogg" damagerange="5.0,80.0" damagesoundtype="LimbArmor"/> <damagesound file="Content/Sounds/Damage/HitArmor1.ogg" damagerange="5.0,80.0" damagesoundtype="LimbArmor"/>
<damagesound file="Content/Sounds/Damage/HitArmor2.ogg" damagerange="5.0,80.0" damagesoundtype="LimbArmor"/> <damagesound file="Content/Sounds/Damage/HitArmor2.ogg" damagerange="5.0,80.0" damagesoundtype="LimbArmor"/>
<damagesound file="Content/Sounds/Damage/HitArmor3.ogg" damagerange="40.0,100.0" damagesoundtype="LimbArmor"/> <damagesound file="Content/Sounds/Damage/HitArmor3.ogg" damagerange="40.0,100.0" damagesoundtype="LimbArmor"/>
<damagesound file="Content/Sounds/Damage/HitClown1.ogg" damagerange="0.0,40.0" damagesoundtype="LimbClown"/>
<damagesound file="Content/Sounds/Damage/HitClown2.ogg" damagerange="0.0,40.0" damagesoundtype="LimbClown"/>
<damagesound file="Content/Sounds/Damage/HitClown3.ogg" damagerange="25.0,75.0" damagesoundtype="LimbClown"/>
<damagesound file="Content/Sounds/Damage/HitClown4.ogg" damagerange="50.0,100.0" damagesoundtype="LimbClown"/>
<damagesound file="Content/Sounds/Damage/creak1.ogg" damagesoundtype="Pressure"/> <damagesound file="Content/Sounds/Damage/creak1.ogg" damagesoundtype="Pressure"/>
<damagesound file="Content/Sounds/Damage/creak2.ogg" damagesoundtype="Pressure"/> <damagesound file="Content/Sounds/Damage/creak2.ogg" damagesoundtype="Pressure"/>
@@ -52,6 +56,22 @@
<drown file="Content/Sounds/Water/Drown3.ogg"/> <drown file="Content/Sounds/Water/Drown3.ogg"/>
<drown file="Content/Sounds/Water/Drown4.ogg"/> <drown file="Content/Sounds/Water/Drown4.ogg"/>
<footstep file="Content/Sounds/Footsteps/step.ogg"/>
<footstep_metal file="Content/Sounds/Footsteps/Metal/metal-01.ogg"/>
<footstep_metal file="Content/Sounds/Footsteps/Metal/metal-02.ogg"/>
<footstep_metal file="Content/Sounds/Footsteps/Metal/metal-03.ogg"/>
<footstep_metal file="Content/Sounds/Footsteps/Metal/metal-04.ogg"/>
<footstep_metal file="Content/Sounds/Footsteps/Metal/metal-05.ogg"/>
<footstep_metal file="Content/Sounds/Footsteps/Metal/metal-06.ogg"/>
<footstep_metal file="Content/Sounds/Footsteps/Metal/metal-07.ogg"/>
<footstep_armor file="Content/Sounds/Footsteps/Armor/armor-01.ogg"/>
<footstep_armor file="Content/Sounds/Footsteps/Armor/armor-02.ogg"/>
<footstep_armor file="Content/Sounds/Footsteps/Armor/armor-03.ogg"/>
<footstep_clown file="Content/Sounds/Footsteps/Clown/clown-01.ogg"/>
<footstep_clown file="Content/Sounds/Footsteps/Clown/clown-02.ogg"/>
<ambient file="Content/Sounds/Ambient/Ambient1.ogg"/> <ambient file="Content/Sounds/Ambient/Ambient1.ogg"/>
<ambient file="Content/Sounds/Ambient/Ambient2.ogg"/> <ambient file="Content/Sounds/Ambient/Ambient2.ogg"/>
<ambient file="Content/Sounds/Ambient/Ambient3.ogg"/> <ambient file="Content/Sounds/Ambient/Ambient3.ogg"/>
@@ -1000,7 +1000,7 @@ namespace Barotrauma
{ {
target.AddDamage(CauseOfDeath.Bloodloss, 1.0f, character); target.AddDamage(CauseOfDeath.Bloodloss, 1.0f, character);
#if CLIENT #if CLIENT
SoundPlayer.PlayDamageSound(DamageSoundType.LimbBlunt, 25.0f, targetTorso.body); SoundPlayer.PlayDamageSound("LimbBlunt", 25.0f, targetTorso.body);
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
{ {
@@ -371,6 +371,7 @@ namespace Barotrauma
{ {
if (!MathUtils.IsValid(value)) return; if (!MathUtils.IsValid(value)) return;
if (GameMain.Client != null) return; if (GameMain.Client != null) return;
if (!DoesBleed) return;
float newBleeding = MathHelper.Clamp(value, 0.0f, 5.0f); float newBleeding = MathHelper.Clamp(value, 0.0f, 5.0f);
//if (newBleeding == bleeding) return; //if (newBleeding == bleeding) return;
@@ -1618,6 +1619,15 @@ namespace Barotrauma
lowPassMultiplier = MathHelper.Lerp(lowPassMultiplier, 1.0f, 0.1f); lowPassMultiplier = MathHelper.Lerp(lowPassMultiplier, 1.0f, 0.1f);
if (DoesBleed)
{
Health -= bleeding * deltaTime;
Bleeding -= BleedingDecreaseSpeed * deltaTime;
}
if (health <= minHealth) Kill(CauseOfDeath.Bloodloss);
if (!IsDead) LockHands = false;
//CPR stuff is handled in the UpdateCPR function in HumanoidAnimController //CPR stuff is handled in the UpdateCPR function in HumanoidAnimController
} }
@@ -49,8 +49,8 @@ namespace Barotrauma
#if CLIENT #if CLIENT
[Serialize(DamageSoundType.None, false)] [Serialize("", false)]
public DamageSoundType DamageSoundType public string DamageSound
{ {
get; get;
private set; private set;
@@ -3,23 +3,19 @@ using System.Xml.Linq;
namespace Barotrauma namespace Barotrauma
{ {
class DelayedListElement
{
public DelayedEffect Parent;
public Entity Entity;
public List<ISerializableEntity> Targets;
public float StartTimer;
}
class DelayedEffect : StatusEffect class DelayedEffect : StatusEffect
{ {
public static List<DelayedEffect> List = new List<DelayedEffect>(); public static List<DelayedListElement> DelayList = new List<DelayedListElement>();
private float delay; private float delay;
private float startTimer;
private Entity entity;
private List<ISerializableEntity> targets;
public float StartTimer
{
get { return startTimer; }
}
public DelayedEffect(XElement element) public DelayedEffect(XElement element)
: base(element) : base(element)
{ {
@@ -28,25 +24,36 @@ namespace Barotrauma
public override void Apply(ActionType type, float deltaTime, Entity entity, List<ISerializableEntity> targets) public override void Apply(ActionType type, float deltaTime, Entity entity, List<ISerializableEntity> targets)
{ {
if (this.type != type) return; if (this.type != type || !HasRequiredItems(entity)) return;
if (!base.Stackable && DelayList.Find(d => d.Parent == this && d.Entity == entity && d.Targets == targets) != null) return;
startTimer = delay;
this.entity = entity;
this.targets = targets; DelayedListElement element = new DelayedListElement();
element.Parent = this;
element.StartTimer = delay;
element.Entity = entity;
element.Targets = targets;
List.Add(this); DelayList.Add(element);
} }
public void Update(float deltaTime) public static void Update(float deltaTime)
{ {
startTimer -= deltaTime; for (int i = DelayList.Count - 1; i >= 0; i--)
{
DelayedListElement element = DelayList[i];
if (element.Parent.CheckConditionalAlways && !element.Parent.HasRequiredConditions(element.Targets))
{
DelayList.Remove(element);
continue;
}
if (startTimer > 0.0f) return; element.StartTimer -= deltaTime;
base.Apply(1.0f, entity, targets); if (element.StartTimer > 0.0f) continue;
List.Remove(this);
element.Parent.Apply(1.0f, element.Entity, element.Targets);
DelayList.Remove(element);
}
} }
} }
} }
@@ -373,13 +373,13 @@ namespace Barotrauma
#if CLIENT #if CLIENT
if (playSound) if (playSound)
{ {
DamageSoundType damageSoundType = (damageType == DamageType.Blunt) ? DamageSoundType.LimbBlunt : DamageSoundType.LimbSlash; string damageSoundType = (damageType == DamageType.Blunt) ? "LimbBlunt" : "LimbSlash";
foreach (DamageModifier damageModifier in appliedDamageModifiers) foreach (DamageModifier damageModifier in appliedDamageModifiers)
{ {
if (damageModifier.DamageSoundType != DamageSoundType.None) if (!string.IsNullOrWhiteSpace(damageModifier.DamageSound))
{ {
damageSoundType = damageModifier.DamageSoundType; damageSoundType = damageModifier.DamageSound;
break; break;
} }
} }
@@ -594,12 +594,6 @@ namespace Barotrauma
} }
#if CLIENT #if CLIENT
if (hitSound != null)
{
hitSound.Remove();
hitSound = null;
}
if (LightSource != null) if (LightSource != null)
{ {
LightSource.Remove(); LightSource.Remove();
@@ -9,6 +9,93 @@ using Barotrauma.Particles;
namespace Barotrauma namespace Barotrauma
{ {
class DurationListElement
{
public StatusEffect Parent;
public Entity Entity;
public List<ISerializableEntity> Targets;
public float StartTimer;
}
partial class PropertyConditional
{
public string Attribute;
public string Operator;
public object Value;
public PropertyConditional(string Attribute, string Operator, object Value)
{
this.Attribute = Attribute;
this.Operator = Operator;
this.Value = Value;
}
public bool Matches(SerializableProperty property)
{
if (property.GetValue() == null)
{
DebugConsole.ThrowError("Couldn't compare " + Value.ToString() + " (" + Value.GetType() + ") to property \"" + property.Name + "- property.GetValue() returns null!!");
return false;
}
Type type = property.GetValue().GetType();
float? floatValue = null;
float? floatProperty = null;
if (type == typeof(float) || type == typeof(int))
{
floatValue = Convert.ToSingle(Value);
floatProperty = Convert.ToSingle(property.GetValue());
}
switch (Operator)
{
case "==":
if (property.GetValue().Equals(floatValue == null ? Value : floatValue))
return true;
break;
case "!=":
if (property.GetValue().Equals(floatValue == null ? Value : floatValue))
return true;
break;
case ">":
if (floatValue == null)
{
DebugConsole.ThrowError("Couldn't compare " + Value.ToString() + " (" + Value.GetType() + ") to property \"" + property.Name + "\" (" + type + ")! "
+ "Make sure the type of the value set in the config files matches the type of the property.");
}
else if (floatProperty > floatValue)
return true;
break;
case "<":
if (floatValue == null)
{
DebugConsole.ThrowError("Couldn't compare " + Value.ToString() + " (" + Value.GetType() + ") to property \"" + property.Name + "\" (" + type + ")! "
+ "Make sure the type of the value set in the config files matches the type of the property.");
}
else if (floatProperty < floatValue)
return true;
break;
case ">=":
if (floatValue == null)
{
DebugConsole.ThrowError("Couldn't compare " + Value.ToString() + " (" + Value.GetType() + ") to property \"" + property.Name + "\" (" + type + ")! "
+ "Make sure the type of the value set in the config files matches the type of the property.");
}
else if (floatProperty >= floatValue)
return true;
break;
case "<=":
if (floatValue == null)
{
DebugConsole.ThrowError("Couldn't compare " + Value.ToString() + " (" + Value.GetType() + ") to property \"" + property.Name + "\" (" + type + ")! "
+ "Make sure the type of the value set in the config files matches the type of the property.");
}
else if (floatProperty <= floatValue)
return true;
break;
}
return false;
}
}
partial class StatusEffect partial class StatusEffect
{ {
[Flags] [Flags]
@@ -32,15 +119,24 @@ namespace Barotrauma
public string[] propertyNames; public string[] propertyNames;
private object[] propertyEffects; private object[] propertyEffects;
List<PropertyConditional> propertyConditionals;
private bool setValue; private bool setValue;
private bool disableDeltaTime; private bool disableDeltaTime;
private HashSet<string> onContainingNames; private HashSet<string> onContainingNames;
private HashSet<string> tags;
private readonly float duration; private readonly float duration;
public static List<DurationListElement> DurationList = new List<DurationListElement>();
private readonly bool useItem; public bool CheckConditionalAlways; //Always do the conditional checks for the duration/delay. If false, only check conditional on apply.
public bool Stackable; //Can the same status effect be applied several times to the same targets?
private readonly int useItemCount;
private readonly int cancelStatusEffect;
public readonly ActionType type; public readonly ActionType type;
@@ -63,6 +159,24 @@ namespace Barotrauma
get { return onContainingNames; } get { return onContainingNames; }
} }
public string Tags
{
get { return string.Join(",", tags); }
set
{
tags.Clear();
if (value == null) return;
string[] newTags = value.Split(',');
foreach (string tag in newTags)
{
string newTag = tag.Trim();
if (!tags.Contains(newTag)) tags.Add(newTag);
}
}
}
public static StatusEffect Load(XElement element) public static StatusEffect Load(XElement element)
{ {
if (element.Attribute("delay")!=null) if (element.Attribute("delay")!=null)
@@ -76,14 +190,16 @@ namespace Barotrauma
protected StatusEffect(XElement element) protected StatusEffect(XElement element)
{ {
requiredItems = new List<RelatedItem>(); requiredItems = new List<RelatedItem>();
tags = new HashSet<string>(element.GetAttributeString("tags", "").Split(','));
#if CLIENT #if CLIENT
particleEmitters = new List<ParticleEmitter>(); particleEmitters = new List<ParticleEmitter>();
#endif #endif
IEnumerable<XAttribute> attributes = element.Attributes(); IEnumerable<XAttribute> attributes = element.Attributes();
List<XAttribute> propertyAttributes = new List<XAttribute>(); List<XAttribute> propertyAttributes = new List<XAttribute>();
propertyConditionals = new List<PropertyConditional>();
foreach (XAttribute attribute in attributes) foreach (XAttribute attribute in attributes)
{ {
switch (attribute.Name.ToString()) switch (attribute.Name.ToString())
@@ -133,6 +249,12 @@ namespace Barotrauma
case "duration": case "duration":
duration = attribute.GetAttributeFloat(0.0f); duration = attribute.GetAttributeFloat(0.0f);
break; break;
case "stackable":
Stackable = attribute.GetAttributeBool(true);
break;
case "checkconditionalalways":
CheckConditionalAlways = attribute.GetAttributeBool(false);
break;
case "sound": case "sound":
DebugConsole.ThrowError("Error in StatusEffect " + element.Parent.Name.ToString() + DebugConsole.ThrowError("Error in StatusEffect " + element.Parent.Name.ToString() +
" - sounds should be defined as child elements of the StatusEffect, not as attributes."); " - sounds should be defined as child elements of the StatusEffect, not as attributes.");
@@ -167,7 +289,14 @@ namespace Barotrauma
break; break;
case "use": case "use":
case "useitem": case "useitem":
useItem = true; useItemCount++;
break;
case "cancel":
case "cancelstatuseffect":
//This only works if there's a conditional checking for status effect tags. There is no way to cancel *all* status effects atm.
cancelStatusEffect = 1;
if (subElement.GetAttributeBool("all", false) == true)
cancelStatusEffect = 2;
break; break;
case "requireditem": case "requireditem":
case "requireditems": case "requireditems":
@@ -177,6 +306,67 @@ namespace Barotrauma
requiredItems.Add(newRequiredItem); requiredItems.Add(newRequiredItem);
break; break;
case "conditional":
IEnumerable<XAttribute> conditionalAttributes = subElement.Attributes();
foreach(XAttribute attribute in conditionalAttributes)
{
string attributeString = XMLExtensions.GetAttributeObject(attribute).ToString();
string atStr = attributeString;
string[] splitString = atStr.Split(' ');
string op = splitString[0];
if (splitString.Length > 0)
{
for (int i=1; i<splitString.Length; i++)
{
atStr = splitString[i] + (i > 1 && i < splitString.Length ? " " : "");
}
}
//thanks xml for not letting me use < or > in attributes :(
switch (op)
{
case "e":
case "eq":
case "equals":
op = "==";
break;
case "ne":
case "neq":
case "notequals":
case "!":
case "!e":
case "!eq":
case "!equals":
op = "!=";
break;
case "gt":
case "greaterthan":
op = ">";
break;
case "lt":
case "lessthan":
op = "<";
break;
case "gte":
case "gteq":
case "greaterthanequals":
op = ">=";
break;
case "lte":
case "lteq":
case "lessthanequals":
op = "<=";
break;
default:
if (op != "==" && op != "!=" && op != ">" && op != "<" && op != ">=" && op != "<=") //Didn't use escape strings or anything
{
atStr = attributeString; //We probably don't even have an operator
op = "==";
}
break;
}
propertyConditionals.Add(new PropertyConditional(attribute.Name.ToString().ToLowerInvariant(), op, atStr));
}
break;
#if CLIENT #if CLIENT
case "particleemitter": case "particleemitter":
particleEmitters.Add(new ParticleEmitter(subElement)); particleEmitters.Add(new ParticleEmitter(subElement));
@@ -190,7 +380,7 @@ namespace Barotrauma
} }
} }
private bool HasRequiredItems(Entity entity) public virtual bool HasRequiredItems(Entity entity)
{ {
if (requiredItems == null) return true; if (requiredItems == null) return true;
foreach (RelatedItem requiredItem in requiredItems) foreach (RelatedItem requiredItem in requiredItems)
@@ -209,21 +399,97 @@ namespace Barotrauma
return true; return true;
} }
public virtual bool HasRequiredConditions(List<ISerializableEntity> targets)
{
if (!propertyConditionals.Any()) return true;
foreach (ISerializableEntity target in targets)
{
foreach (PropertyConditional pc in propertyConditionals)
{
if (target == null || target.SerializableProperties == null) continue;
if (!target.SerializableProperties.TryGetValue(pc.Attribute, out SerializableProperty property))
{
//Do special conditional checks
string valStr = pc.Value.ToString();
if (pc.Attribute == "name")
return pc.Operator == "==" ? target.Name == valStr : target.Name != valStr;
if (pc.Attribute == "speciesname" && target is Character)
return pc.Operator == "==" ? ((Character)target).SpeciesName == valStr : ((Character)target).SpeciesName != valStr;
if ((pc.Attribute == "hastag" || pc.Attribute == "hastags") && target is Item)
{
string[] readTags = valStr.Split(',');
int matches = 0;
foreach (string tag in readTags)
if (((Item)target).HasTag(tag)) matches++;
//If operator is == then it needs to match everything, otherwise if its != there must be zero matches.
return pc.Operator == "==" ? matches >= readTags.Length : matches <= 0;
}
List<DurationListElement> durations = DurationList.FindAll(d => d.Targets.Contains(target));
List<DelayedListElement> delays = DelayedEffect.DelayList.FindAll(d => d.Targets.Contains(target));
bool success = false;
if (pc.Attribute == "hasstatustag" || pc.Attribute == "hasstatustags" && (durations.Any() || delays.Any()))
{
string[] readTags = valStr.Split(',');
foreach (DurationListElement duration in durations)
{
int matches = 0;
foreach (string tag in readTags)
if (duration.Parent.HasTag(tag)) matches++;
success = pc.Operator == "==" ? matches >= readTags.Length : matches <= 0;
if (cancelStatusEffect > 0 && success)
DurationList.Remove(duration);
if (cancelStatusEffect != 2) //cancelStatusEffect 1 = only cancel once, cancelStatusEffect 2 = cancel all of matching tags
return success;
}
foreach (DelayedListElement delay in delays)
{
int matches = 0;
foreach (string tag in readTags)
if (delay.Parent.HasTag(tag)) matches++;
success = pc.Operator == "==" ? matches >= readTags.Length : matches <= 0;
if (cancelStatusEffect > 0 && success)
DelayedEffect.DelayList.Remove(delay);
if (cancelStatusEffect != 2) //ditto
return success;
}
}
return success;
}
else if (!pc.Matches(property))
return false;
}
}
return true;
}
public virtual void Apply(ActionType type, float deltaTime, Entity entity, ISerializableEntity target) public virtual void Apply(ActionType type, float deltaTime, Entity entity, ISerializableEntity target)
{ {
if (this.type != type || !HasRequiredItems(entity)) return; if (this.type != type || !HasRequiredItems(entity)) return;
if (targetNames != null && !targetNames.Contains(target.Name)) return; if (targetNames != null && !targetNames.Contains(target.Name)) return;
if (duration > 0.0f && !Stackable && DurationList.Find(d => d.Parent == this && d.Entity == entity && d.Targets.Contains(target)) != null) return;
List<ISerializableEntity> targets = new List<ISerializableEntity>(); List<ISerializableEntity> targets = new List<ISerializableEntity>();
targets.Add(target); targets.Add(target);
Apply(deltaTime, entity, targets); if (!HasRequiredConditions(targets)) return;
Apply(type, deltaTime, entity, targets);
} }
public virtual void Apply(ActionType type, float deltaTime, Entity entity, List<ISerializableEntity> targets) public virtual void Apply(ActionType type, float deltaTime, Entity entity, List<ISerializableEntity> targets)
{ {
if (this.type != type || !HasRequiredItems(entity)) return; if (this.type != type || !HasRequiredItems(entity) || !HasRequiredConditions(targets)) return;
Apply(deltaTime, entity, targets); Apply(deltaTime, entity, targets);
} }
@@ -251,35 +517,43 @@ namespace Barotrauma
} }
#endif #endif
if (useItem) if (useItemCount > 0)
{ {
foreach (Item item in targets.FindAll(t => t is Item).Cast<Item>()) for (int i=0; i<useItemCount; i++)
{ {
item.Use(deltaTime, targets.FirstOrDefault(t => t is Character) as Character); foreach (Item item in targets.FindAll(t => t is Item).Cast<Item>())
}
}
foreach (ISerializableEntity target in targets)
{
for (int i = 0; i < propertyNames.Length; i++)
{
SerializableProperty property;
if (target == null || target.SerializableProperties == null || !target.SerializableProperties.TryGetValue(propertyNames[i], out property)) continue;
if (duration > 0.0f)
{ {
CoroutineManager.StartCoroutine( item.Use(deltaTime, targets.FirstOrDefault(t => t is Character) as Character);
ApplyToPropertyOverDuration(duration, property, propertyEffects[i]), "statuseffect");
}
else
{
ApplyToProperty(property, propertyEffects[i], deltaTime);
} }
} }
} }
if (duration > 0.0f)
{
DurationListElement element = new DurationListElement();
element.Parent = this;
element.StartTimer = duration;
element.Entity = entity;
element.Targets = targets;
DurationList.Add(element);
}
else
{
foreach (ISerializableEntity target in targets)
{
for (int i = 0; i < propertyNames.Length; i++)
{
SerializableProperty property;
if (target == null || target.SerializableProperties == null || !target.SerializableProperties.TryGetValue(propertyNames[i], out property)) continue;
ApplyToProperty(property, propertyEffects[i], deltaTime);
}
}
}
if (explosion != null) explosion.Explode(entity.WorldPosition); if (explosion != null) explosion.Explode(entity.WorldPosition);
@@ -308,21 +582,6 @@ namespace Barotrauma
#endif #endif
} }
private IEnumerable<object> ApplyToPropertyOverDuration(float duration, SerializableProperty property, object value)
{
float timer = duration;
while (timer > 0.0f)
{
ApplyToProperty(property, value, CoroutineManager.UnscaledDeltaTime);
timer -= CoroutineManager.DeltaTime;
yield return CoroutineStatus.Running;
}
yield return CoroutineStatus.Success;
}
private void ApplyToProperty(SerializableProperty property, object value, float deltaTime) private void ApplyToProperty(SerializableProperty property, object value, float deltaTime)
{ {
if (disableDeltaTime || setValue) deltaTime = 1.0f; if (disableDeltaTime || setValue) deltaTime = 1.0f;
@@ -359,9 +618,33 @@ namespace Barotrauma
public static void UpdateAll(float deltaTime) public static void UpdateAll(float deltaTime)
{ {
for (int i = DelayedEffect.List.Count-1; i>= 0; i--) DelayedEffect.Update(deltaTime);
for (int i = DurationList.Count - 1; i >= 0; i--)
{ {
DelayedEffect.List[i].Update(deltaTime); DurationListElement element = DurationList[i];
if (element.Parent.CheckConditionalAlways && !element.Parent.HasRequiredConditions(element.Targets))
{
DurationList.Remove(element);
continue;
}
foreach (ISerializableEntity target in element.Targets)
{
for (int n = 0; n < element.Parent.propertyNames.Length; n++)
{
SerializableProperty property;
if (target == null || target.SerializableProperties == null || !target.SerializableProperties.TryGetValue(element.Parent.propertyNames[n], out property)) continue;
element.Parent.ApplyToProperty(property, element.Parent.propertyEffects[n], CoroutineManager.UnscaledDeltaTime);
}
}
element.StartTimer -= deltaTime;
if (element.StartTimer > 0.0f) continue;
DurationList.Remove(element);
} }
} }
@@ -369,5 +652,18 @@ namespace Barotrauma
{ {
CoroutineManager.StopCoroutines("statuseffect"); CoroutineManager.StopCoroutines("statuseffect");
} }
public void AddTag(string tag)
{
if (tags.Contains(tag)) return;
tags.Add(tag);
}
public bool HasTag(string tag)
{
if (tag == null) return true;
return (tags.Contains(tag) || tags.Contains(tag.ToLowerInvariant()));
}
} }
} }
@@ -203,8 +203,23 @@ namespace Barotrauma.Items.Components
#endif #endif
} }
public override bool HasRequiredItems(Character character, bool addMessage)
{
if (item.Condition <= 0.0f) return true; //For repairing
//this is a bit pointless atm because if canBePicked is false it won't allow you to do Pick() anyway, however it's still good for future-proofing.
return requiredItems.Any() ? base.HasRequiredItems(character, addMessage) : canBePicked;
}
public override bool Pick(Character picker)
{
return item.Condition <= 0.0f ? true : base.Pick(picker);
}
public override bool OnPicked(Character picker) public override bool OnPicked(Character picker)
{ {
if (item.Condition <= 0.0f) return true; //repairs
SetState(predictedState == null ? !isOpen : !predictedState.Value, false, true); //crowbar function SetState(predictedState == null ? !isOpen : !predictedState.Value, false, true); //crowbar function
#if CLIENT #if CLIENT
PlaySound(ActionType.OnPicked, item.WorldPosition); PlaySound(ActionType.OnPicked, item.WorldPosition);
@@ -369,7 +384,7 @@ namespace Barotrauma.Items.Components
if (Math.Sign(diff) != dir) if (Math.Sign(diff) != dir)
{ {
#if CLIENT #if CLIENT
SoundPlayer.PlayDamageSound(DamageSoundType.LimbBlunt, 1.0f, body); SoundPlayer.PlayDamageSound("LimbBlunt", 1.0f, body);
#endif #endif
if (isHorizontal) if (isHorizontal)
@@ -215,6 +215,7 @@ namespace Barotrauma.Items.Components
{ {
Character targetCharacter = null; Character targetCharacter = null;
Limb targetLimb = null; Limb targetLimb = null;
Structure targetStructure = null;
if (f2.Body.UserData is Limb) if (f2.Body.UserData is Limb)
{ {
@@ -224,8 +225,12 @@ namespace Barotrauma.Items.Components
} }
else if (f2.Body.UserData is Character) else if (f2.Body.UserData is Character)
{ {
targetCharacter = (Character)f2.Body.UserData; targetCharacter = (Character)f2.Body.UserData;
targetLimb = targetCharacter.AnimController.GetLimb(LimbType.Torso); //Otherwise armor can be bypassed in strange ways
}
else if (f2.Body.UserData is Structure)
{
targetStructure = (Structure)f2.Body.UserData;
} }
else else
{ {
@@ -236,14 +241,22 @@ namespace Barotrauma.Items.Components
if (attack != null) if (attack != null)
{ {
if (targetLimb == null) if (targetLimb != null)
{ {
attack.DoDamageToLimb(user, targetLimb, item.WorldPosition, 1.0f); attack.DoDamageToLimb(user, targetLimb, item.WorldPosition, 1.0f);
} }
else else if (targetCharacter != null)
{ {
attack.DoDamage(user, targetCharacter, item.WorldPosition, 1.0f); attack.DoDamage(user, targetCharacter, item.WorldPosition, 1.0f);
} }
else if (targetStructure != null)
{
attack.DoDamage(user, targetStructure, item.WorldPosition, 1.0f);
}
else
{
return false;
}
} }
RestoreCollision(); RestoreCollision();
@@ -251,7 +264,7 @@ namespace Barotrauma.Items.Components
if (GameMain.Client != null) return true; if (GameMain.Client != null) return true;
if (GameMain.Server != null) if (GameMain.Server != null && targetCharacter != null) //TODO: Log structure hits
{ {
GameMain.Server.CreateEntityEvent(item, new object[] { Networking.NetEntityEvent.Type.ApplyStatusEffect, ActionType.OnUse, targetCharacter.ID }); GameMain.Server.CreateEntityEvent(item, new object[] { Networking.NetEntityEvent.Type.ApplyStatusEffect, ActionType.OnUse, targetCharacter.ID });
@@ -263,8 +276,9 @@ namespace Barotrauma.Items.Components
logStr += " on " + targetCharacter.LogName + "."; logStr += " on " + targetCharacter.LogName + ".";
Networking.GameServer.Log(logStr, Networking.ServerLog.MessageType.Attack); Networking.GameServer.Log(logStr, Networking.ServerLog.MessageType.Attack);
} }
ApplyStatusEffects(ActionType.OnUse, 1.0f, targetLimb.character); if (targetCharacter != null) //TODO: Allow OnUse to happen on structures too maybe??
ApplyStatusEffects(ActionType.OnUse, 1.0f, targetCharacter != null ? targetCharacter : null);
return true; return true;
} }
@@ -30,6 +30,8 @@ namespace Barotrauma.Items.Components
protected bool canBePicked; protected bool canBePicked;
protected bool canBeSelected; protected bool canBeSelected;
protected bool canBeCombined;
protected bool removeOnCombined;
public bool WasUsed; public bool WasUsed;
@@ -47,7 +49,7 @@ namespace Barotrauma.Items.Components
private string msg; private string msg;
[Serialize(0.0f, false)] [Editable, Serialize(0.0f, false)]
public float PickingTime public float PickingTime
{ {
get; get;
@@ -103,7 +105,7 @@ namespace Barotrauma.Items.Components
} }
} }
[Serialize(false, false)] [Editable, Serialize(false, false)] //Editable for doors to do their magic
public bool CanBePicked public bool CanBePicked
{ {
get { return canBePicked; } get { return canBePicked; }
@@ -124,6 +126,22 @@ namespace Barotrauma.Items.Components
set { canBeSelected = value; } set { canBeSelected = value; }
} }
//Transfer conditions between same prefab items
[Serialize(false, false)]
public bool CanBeCombined
{
get { return canBeCombined; }
set { canBeCombined = value; }
}
//Remove item if combination results in 0 condition
[Serialize(false, false)]
public bool RemoveOnCombined
{
get { return removeOnCombined; }
set { removeOnCombined = value; }
}
public InputType PickKey public InputType PickKey
{ {
get; get;
@@ -153,7 +171,7 @@ namespace Barotrauma.Items.Components
get { return name; } get { return name; }
} }
[Serialize("", false)] [Editable, Serialize("", false)]
public string Msg public string Msg
{ {
get { return msg; } get { return msg; }
@@ -196,7 +214,7 @@ namespace Barotrauma.Items.Components
try try
{ {
string pickKeyStr = element.GetAttributeString("selectkey", "Select"); string pickKeyStr = element.GetAttributeString("pickkey", "Select");
pickKeyStr = ToolBox.ConvertInputType(pickKeyStr); pickKeyStr = ToolBox.ConvertInputType(pickKeyStr);
PickKey = (InputType)Enum.Parse(typeof(InputType),pickKeyStr, true); PickKey = (InputType)Enum.Parse(typeof(InputType),pickKeyStr, true);
} }
@@ -323,6 +341,43 @@ namespace Barotrauma.Items.Components
public virtual bool Combine(Item item) public virtual bool Combine(Item item)
{ {
if (canBeCombined && this.item.Prefab == item.Prefab && item.Condition > 0.0f && this.item.Condition > 0.0f)
{
float transferAmount = 0.0f;
if (this.Item.Condition <= item.Condition)
transferAmount = Math.Min(item.Condition, this.item.Prefab.Health - this.item.Condition);
else
transferAmount = -Math.Min(this.item.Condition, item.Prefab.Health - item.Condition);
if (transferAmount == 0.0f)
return false;
this.Item.Condition += transferAmount;
item.Condition -= transferAmount;
if (removeOnCombined)
{
if (item.Condition <= 0.0f)
{
if (item.ParentInventory != null)
{
Character owner = (Character)item.ParentInventory.Owner;
if (owner != null && owner.HasSelectedItem(item)) item.Unequip(owner);
item.ParentInventory.RemoveItem(item);
}
Entity.Spawner.AddToRemoveQueue(item);
}
if (this.Item.Condition <= 0.0f)
{
if (this.Item.ParentInventory != null)
{
Character owner = (Character)this.Item.ParentInventory.Owner;
if (owner != null && owner.HasSelectedItem(this.Item)) this.Item.Unequip(owner);
this.Item.ParentInventory.RemoveItem(this.Item);
}
Entity.Spawner.AddToRemoveQueue(this.Item);
}
}
return true;
}
return false; return false;
} }
@@ -437,7 +492,7 @@ namespace Barotrauma.Items.Components
return true; return true;
} }
public bool HasRequiredItems(Character character, bool addMessage) public virtual bool HasRequiredItems(Character character, bool addMessage)
{ {
if (!requiredItems.Any()) return true; if (!requiredItems.Any()) return true;
if (character.Inventory == null) return false; if (character.Inventory == null) return false;
@@ -170,7 +170,7 @@ namespace Barotrauma.Items.Components
if (effect.Targets.HasFlag(StatusEffect.TargetType.This)) if (effect.Targets.HasFlag(StatusEffect.TargetType.This))
effect.Apply(ActionType.OnContaining, deltaTime, item, item.AllPropertyObjects); effect.Apply(ActionType.OnContaining, deltaTime, item, item.AllPropertyObjects);
if (effect.Targets.HasFlag(StatusEffect.TargetType.Contained)) if (effect.Targets.HasFlag(StatusEffect.TargetType.Contained))
effect.Apply(ActionType.OnContaining, deltaTime, item, contained.AllPropertyObjects); effect.Apply(ActionType.OnContaining, deltaTime, item, contained.AllPropertyObjects);
} }
} }
@@ -192,7 +192,7 @@ namespace Barotrauma.Items.Components
return true; return true;
} }
return false; return false;
} }
public override void OnMapLoaded() public override void OnMapLoaded()
@@ -57,7 +57,8 @@ namespace Barotrauma.Items.Components
foreach (DeconstructItem deconstructProduct in targetItem.Prefab.DeconstructItems) foreach (DeconstructItem deconstructProduct in targetItem.Prefab.DeconstructItems)
{ {
if (deconstructProduct.RequireFullCondition && targetItem.Condition < targetItem.Prefab.Health) continue; float percentageHealth = targetItem.Condition / targetItem.Prefab.Health;
if (percentageHealth <= deconstructProduct.MinCondition || percentageHealth > deconstructProduct.MaxCondition) continue;
var itemPrefab = MapEntityPrefab.Find(deconstructProduct.ItemPrefabName) as ItemPrefab; var itemPrefab = MapEntityPrefab.Find(deconstructProduct.ItemPrefabName) as ItemPrefab;
if (itemPrefab == null) if (itemPrefab == null)
@@ -69,11 +70,11 @@ namespace Barotrauma.Items.Components
//container full, drop the items outside the deconstructor //container full, drop the items outside the deconstructor
if (containers[1].Inventory.Items.All(i => i != null)) if (containers[1].Inventory.Items.All(i => i != null))
{ {
Entity.Spawner.AddToSpawnQueue(itemPrefab, item.Position, item.Submarine); Entity.Spawner.AddToSpawnQueue(itemPrefab, item.Position, item.Submarine, itemPrefab.Health * deconstructProduct.OutCondition);
} }
else else
{ {
Entity.Spawner.AddToSpawnQueue(itemPrefab, containers[1].Inventory); Entity.Spawner.AddToSpawnQueue(itemPrefab, containers[1].Inventory, itemPrefab.Health * deconstructProduct.OutCondition);
} }
} }
@@ -12,10 +12,12 @@ namespace Barotrauma.Items.Components
{ {
public readonly ItemPrefab TargetItem; public readonly ItemPrefab TargetItem;
public readonly List<Tuple<ItemPrefab, int>> RequiredItems; public readonly List<Tuple<ItemPrefab, int, float, bool>> RequiredItems;
public readonly float RequiredTime; public readonly float RequiredTime;
public readonly float OutCondition; //Percentage-based from 0 to 1
public readonly List<Skill> RequiredSkills; public readonly List<Skill> RequiredSkills;
public FabricableItem(XElement element) public FabricableItem(XElement element)
@@ -31,8 +33,9 @@ namespace Barotrauma.Items.Components
RequiredSkills = new List<Skill>(); RequiredSkills = new List<Skill>();
RequiredTime = element.GetAttributeFloat("requiredtime", 1.0f); RequiredTime = element.GetAttributeFloat("requiredtime", 1.0f);
RequiredItems = new List<Tuple<ItemPrefab, int>>(); OutCondition = element.GetAttributeFloat("outcondition", 1.0f);
RequiredItems = new List<Tuple<ItemPrefab, int, float, bool>>();
//Backwards compatibility for string lists
string[] requiredItemNames = element.GetAttributeString("requireditems", "").Split(','); string[] requiredItemNames = element.GetAttributeString("requireditems", "").Split(',');
foreach (string requiredItemName in requiredItemNames) foreach (string requiredItemName in requiredItemNames)
{ {
@@ -48,12 +51,12 @@ namespace Barotrauma.Items.Components
var existing = RequiredItems.Find(r => r.Item1 == requiredItem); var existing = RequiredItems.Find(r => r.Item1 == requiredItem);
if (existing == null) if (existing == null)
{ {
RequiredItems.Add(new Tuple<ItemPrefab, int>(requiredItem, 1)); RequiredItems.Add(new Tuple<ItemPrefab, int, float, bool>(requiredItem, 1, 1.0f, false));
} }
else else
{ {
RequiredItems.Remove(existing); RequiredItems.Remove(existing);
RequiredItems.Add(new Tuple<ItemPrefab, int>(requiredItem, existing.Item2 + 1)); RequiredItems.Add(new Tuple<ItemPrefab, int, float, bool>(requiredItem, existing.Item2 + 1, 1.0f, false));
} }
} }
@@ -66,6 +69,34 @@ namespace Barotrauma.Items.Components
subElement.GetAttributeString("name", ""), subElement.GetAttributeString("name", ""),
subElement.GetAttributeInt("level", 0))); subElement.GetAttributeInt("level", 0)));
break; break;
case "item": //New system allowing for setting minimal item condition
string requiredItemName = subElement.GetAttributeString("name", "");
float minCondition = subElement.GetAttributeFloat("mincondition", 1.0f);
//Substract mincondition from required item's condition or delete it regardless?
bool useCondition = subElement.GetAttributeBool("usecondition", true);
int count = subElement.GetAttributeInt("count", 1);
if (string.IsNullOrWhiteSpace(requiredItemName)) continue;
ItemPrefab requiredItem = MapEntityPrefab.Find(requiredItemName.Trim()) as ItemPrefab;
if (requiredItem == null)
{
DebugConsole.ThrowError("Error in fabricable item " + name + "! Required item \"" + requiredItemName + "\" not found.");
continue;
}
var existing = RequiredItems.Find(r => r.Item1 == requiredItem);
if (existing == null)
{
RequiredItems.Add(new Tuple<ItemPrefab, int, float, bool>(requiredItem, count, minCondition, useCondition));
}
else
{
RequiredItems.Remove(existing);
RequiredItems.Add(new Tuple<ItemPrefab, int, float, bool>(requiredItem, existing.Item2 + count, minCondition, useCondition));
}
break;
} }
} }
@@ -236,25 +267,32 @@ namespace Barotrauma.Items.Components
return; return;
} }
foreach (Tuple<ItemPrefab, int> ip in fabricatedItem.RequiredItems) foreach (Tuple<ItemPrefab, int, float, bool> ip in fabricatedItem.RequiredItems)
{ {
for (int i = 0; i < ip.Item2; i++) for (int i = 0; i < ip.Item2; i++)
{ {
var requiredItem = containers[0].Inventory.Items.FirstOrDefault(it => it != null && it.Prefab == ip.Item1); var requiredItem = containers[0].Inventory.Items.FirstOrDefault(it => it != null && it.Prefab == ip.Item1 && it.Condition >= ip.Item1.Health * ip.Item3);
if (requiredItem == null) continue; if (requiredItem == null) continue;
//Item4 = use condition bool
if (ip.Item4 && requiredItem.Condition - ip.Item1.Health * ip.Item3 > 0.0f) //Leave it behind with reduced condition if it has enough to stay above 0
{
requiredItem.Condition -= ip.Item1.Health * ip.Item3;
continue;
}
Entity.Spawner.AddToRemoveQueue(requiredItem); Entity.Spawner.AddToRemoveQueue(requiredItem);
containers[0].Inventory.RemoveItem(requiredItem); containers[0].Inventory.RemoveItem(requiredItem);
} }
} }
//TODO: apply OutCondition
if (containers[1].Inventory.Items.All(i => i != null)) if (containers[1].Inventory.Items.All(i => i != null))
{ {
Entity.Spawner.AddToSpawnQueue(fabricatedItem.TargetItem, item.Position, item.Submarine); Entity.Spawner.AddToSpawnQueue(fabricatedItem.TargetItem, item.Position, item.Submarine, fabricatedItem.TargetItem.Health * fabricatedItem.OutCondition);
} }
else else
{ {
Entity.Spawner.AddToSpawnQueue(fabricatedItem.TargetItem, containers[1].Inventory); Entity.Spawner.AddToSpawnQueue(fabricatedItem.TargetItem, containers[1].Inventory, fabricatedItem.TargetItem.Health * fabricatedItem.OutCondition);
} }
CancelFabricating(null); CancelFabricating(null);
@@ -269,11 +307,10 @@ namespace Barotrauma.Items.Components
{ {
return false; return false;
} }
ItemContainer container = item.GetComponent<ItemContainer>(); ItemContainer container = item.GetComponent<ItemContainer>();
foreach (Tuple<ItemPrefab, int> ip in fabricableItem.RequiredItems) foreach (Tuple<ItemPrefab, int, float, bool> ip in fabricableItem.RequiredItems)
{ {
if (Array.FindAll(container.Inventory.Items, it => it != null && it.Prefab == ip.Item1).Length < ip.Item2) return false; if (Array.FindAll(container.Inventory.Items, it => it != null && it.Prefab == ip.Item1 && it.Condition >= ip.Item1.Health * ip.Item3).Length < ip.Item2) return false;
} }
return true; return true;
@@ -10,19 +10,23 @@ namespace Barotrauma.Items.Components
class WearableSprite class WearableSprite
{ {
public readonly Sprite Sprite; public readonly Sprite Sprite;
public readonly LimbType Limb;
public readonly bool HideLimb; public readonly bool HideLimb;
public readonly bool InheritLimbDepth; public readonly bool InheritLimbDepth;
public readonly LimbType DepthLimb; public readonly LimbType DepthLimb;
public readonly Wearable WearableComponent; public readonly Wearable WearableComponent;
public readonly string Sound;
public WearableSprite(Wearable item, Sprite sprite, bool hideLimb, bool inheritLimbDepth = true, LimbType depthLimb = LimbType.None) public WearableSprite(Wearable item, Sprite sprite, LimbType limb, bool hideLimb, bool inheritLimbDepth = true, LimbType depthLimb = LimbType.None, string sound = null)
{ {
WearableComponent = item; WearableComponent = item;
Sprite = sprite; Sprite = sprite;
Limb = limb;
HideLimb = hideLimb; HideLimb = hideLimb;
InheritLimbDepth = inheritLimbDepth; InheritLimbDepth = inheritLimbDepth;
DepthLimb = depthLimb; DepthLimb = depthLimb;
Sound = sound;
} }
} }
@@ -66,15 +70,16 @@ namespace Barotrauma.Items.Components
string spritePath = subElement.Attribute("texture").Value; string spritePath = subElement.Attribute("texture").Value;
spritePath = Path.GetDirectoryName(item.Prefab.ConfigFile) + "/" + spritePath; spritePath = Path.GetDirectoryName(item.Prefab.ConfigFile) + "/" + spritePath;
var sound = subElement.GetAttributeString("sound", "");
var sprite = new Sprite(subElement, "", spritePath); var sprite = new Sprite(subElement, "", spritePath);
wearableSprites[i] = new WearableSprite(this, sprite,
subElement.GetAttributeBool("hidelimb", false),
subElement.GetAttributeBool("inheritlimbdepth", true),
(LimbType)Enum.Parse(typeof(LimbType), subElement.GetAttributeString("depthlimb", "None"), true));
limbType[i] = (LimbType)Enum.Parse(typeof(LimbType), limbType[i] = (LimbType)Enum.Parse(typeof(LimbType),
subElement.GetAttributeString("limb", "Head"), true); subElement.GetAttributeString("limb", "Head"), true);
wearableSprites[i] = new WearableSprite(this, sprite, limbType[i],
subElement.GetAttributeBool("hidelimb", false),
subElement.GetAttributeBool("inheritlimbdepth", true),
(LimbType)Enum.Parse(typeof(LimbType), subElement.GetAttributeString("depthlimb", "None"), true), sound);
i++; i++;
break; break;
case "damagemodifier": case "damagemodifier":
@@ -335,18 +335,18 @@ namespace Barotrauma
} }
} }
public Item(ItemPrefab itemPrefab, Vector2 position, Submarine submarine) public Item(ItemPrefab itemPrefab, Vector2 position, Submarine submarine, float? spawnCondition = null)
: this(new Rectangle( : this(new Rectangle(
(int)(position.X - itemPrefab.sprite.size.X / 2), (int)(position.X - itemPrefab.sprite.size.X / 2),
(int)(position.Y + itemPrefab.sprite.size.Y / 2), (int)(position.Y + itemPrefab.sprite.size.Y / 2),
(int)itemPrefab.sprite.size.X, (int)itemPrefab.sprite.size.X,
(int)itemPrefab.sprite.size.Y), (int)itemPrefab.sprite.size.Y),
itemPrefab, submarine) itemPrefab, submarine, spawnCondition)
{ {
} }
public Item(Rectangle newRect, ItemPrefab itemPrefab, Submarine submarine) public Item(Rectangle newRect, ItemPrefab itemPrefab, Submarine submarine, float? spawnCondition = null)
: base(itemPrefab, submarine) : base(itemPrefab, submarine)
{ {
prefab = itemPrefab; prefab = itemPrefab;
@@ -361,8 +361,8 @@ namespace Barotrauma
rect = newRect; rect = newRect;
condition = prefab.Health; condition = (float)(spawnCondition ?? prefab.Health);
lastSentCondition = prefab.Health; lastSentCondition = condition;
XElement element = prefab.ConfigElement; XElement element = prefab.ConfigElement;
if (element == null) return; if (element == null) return;
@@ -781,7 +781,7 @@ namespace Barotrauma
float surfaceY = CurrentHull.Surface; float surfaceY = CurrentHull.Surface;
return Position.Y < surfaceY; return CurrentHull.WaterVolume > 0.0f && Position.Y < surfaceY;
} }
@@ -826,44 +826,46 @@ namespace Barotrauma
} }
} }
inWater = IsInWater(); if (body != null && body.Enabled)
if (inWater) ApplyStatusEffects(ActionType.InWater, deltaTime);
if (body == null || !body.Enabled) return;
System.Diagnostics.Debug.Assert(body.FarseerBody.FixtureList != null);
if (Math.Abs(body.LinearVelocity.X) > 0.01f || Math.Abs(body.LinearVelocity.Y) > 0.01f)
{ {
Submarine prevSub = Submarine; System.Diagnostics.Debug.Assert(body.FarseerBody.FixtureList != null);
FindHull(); if (Math.Abs(body.LinearVelocity.X) > 0.01f || Math.Abs(body.LinearVelocity.Y) > 0.01f)
{
Submarine prevSub = Submarine;
if (Submarine == null && prevSub != null) FindHull();
{
body.SetTransform(body.SimPosition + prevSub.SimPosition, body.Rotation);
}
else if (Submarine != null && prevSub == null)
{
body.SetTransform(body.SimPosition - Submarine.SimPosition, body.Rotation);
}
Vector2 displayPos = ConvertUnits.ToDisplayUnits(body.SimPosition);
rect.X = (int)(displayPos.X - rect.Width / 2.0f);
rect.Y = (int)(displayPos.Y + rect.Height / 2.0f);
if (Math.Abs(body.LinearVelocity.X) > MaxVel || Math.Abs(body.LinearVelocity.Y) > MaxVel) if (Submarine == null && prevSub != null)
{ {
body.LinearVelocity = new Vector2( body.SetTransform(body.SimPosition + prevSub.SimPosition, body.Rotation);
MathHelper.Clamp(body.LinearVelocity.X, -MaxVel, MaxVel), }
MathHelper.Clamp(body.LinearVelocity.Y, -MaxVel, MaxVel)); else if (Submarine != null && prevSub == null)
{
body.SetTransform(body.SimPosition - Submarine.SimPosition, body.Rotation);
}
Vector2 displayPos = ConvertUnits.ToDisplayUnits(body.SimPosition);
rect.X = (int)(displayPos.X - rect.Width / 2.0f);
rect.Y = (int)(displayPos.Y + rect.Height / 2.0f);
if (Math.Abs(body.LinearVelocity.X) > MaxVel || Math.Abs(body.LinearVelocity.Y) > MaxVel)
{
body.LinearVelocity = new Vector2(
MathHelper.Clamp(body.LinearVelocity.X, -MaxVel, MaxVel),
MathHelper.Clamp(body.LinearVelocity.Y, -MaxVel, MaxVel));
}
} }
UpdateNetPosition();
} }
UpdateNetPosition(); inWater = IsInWater();
if (!inWater || ParentInventory != null) return; if (inWater) ApplyStatusEffects(ActionType.InWater, deltaTime);
if (body == null || !body.Enabled || !inWater || ParentInventory != null) return;
ApplyWaterForces(); ApplyWaterForces();
CurrentHull?.ApplyFlowForces(deltaTime, this); CurrentHull?.ApplyFlowForces(deltaTime, this);
} }
@@ -1104,8 +1106,6 @@ namespace Barotrauma
ic.ApplyStatusEffects(ActionType.OnPicked, 1.0f, picker); ic.ApplyStatusEffects(ActionType.OnPicked, 1.0f, picker);
#if CLIENT #if CLIENT
ic.PlaySound(ActionType.OnPicked, picker.WorldPosition);
if (picker == Character.Controlled) GUIComponent.ForceMouseOn(null); if (picker == Character.Controlled) GUIComponent.ForceMouseOn(null);
#endif #endif
@@ -10,12 +10,16 @@ namespace Barotrauma
struct DeconstructItem struct DeconstructItem
{ {
public readonly string ItemPrefabName; public readonly string ItemPrefabName;
public readonly bool RequireFullCondition; public readonly float MinCondition;
public readonly float MaxCondition;
public readonly float OutCondition;
public DeconstructItem(string itemPrefabName, bool requireFullCondition) public DeconstructItem(string itemPrefabName, float minCondition, float maxCondition, float outCondition)
{ {
ItemPrefabName = itemPrefabName; ItemPrefabName = itemPrefabName;
RequireFullCondition = requireFullCondition; MinCondition = minCondition;
MaxCondition = maxCondition;
OutCondition = outCondition;
} }
} }
@@ -301,9 +305,14 @@ namespace Barotrauma
{ {
string deconstructItemName = deconstructItem.GetAttributeString("name", "not found"); string deconstructItemName = deconstructItem.GetAttributeString("name", "not found");
bool requireFullCondition = deconstructItem.GetAttributeBool("requirefullcondition", false); //minCondition does <= check, meaning that below or equeal to min condition will be skipped.
float minCondition = deconstructItem.GetAttributeFloat("mincondition", -0.1f);
//maxCondition does > check, meaning that above this max the deconstruct item will be skipped.
float maxCondition = deconstructItem.GetAttributeFloat("maxcondition", 1.0f);
//Condition of item on creation
float outCondition = deconstructItem.GetAttributeFloat("outcondition", 1.0f);
DeconstructItems.Add(new DeconstructItem(deconstructItemName, requireFullCondition)); DeconstructItems.Add(new DeconstructItem(deconstructItemName, minCondition, maxCondition, outCondition));
} }
@@ -518,7 +518,7 @@ namespace Barotrauma
float impact = Vector2.Dot(f2.Body.LinearVelocity, -normal)*f2.Body.Mass*0.1f; float impact = Vector2.Dot(f2.Body.LinearVelocity, -normal)*f2.Body.Mass*0.1f;
#if CLIENT #if CLIENT
SoundPlayer.PlayDamageSound(DamageSoundType.StructureBlunt, impact, SoundPlayer.PlayDamageSound("StructureBlunt", impact,
new Vector2( new Vector2(
sections[section].rect.X + sections[section].rect.Width / 2, sections[section].rect.X + sections[section].rect.Width / 2,
sections[section].rect.Y - sections[section].rect.Height / 2), tags: Tags); sections[section].rect.Y - sections[section].rect.Height / 2), tags: Tags);
@@ -679,7 +679,7 @@ namespace Barotrauma
#if CLIENT #if CLIENT
if (playSound)// && !SectionBodyDisabled(i)) if (playSound)// && !SectionBodyDisabled(i))
{ {
DamageSoundType damageSoundType = (attack.DamageType == DamageType.Blunt) ? DamageSoundType.StructureBlunt : DamageSoundType.StructureSlash; string damageSoundType = (attack.DamageType == DamageType.Blunt) ? "StructureBlunt" : "StructureSlash";
SoundPlayer.PlayDamageSound(damageSoundType, damageAmount, worldPosition, tags: Tags); SoundPlayer.PlayDamageSound(damageSoundType, damageAmount, worldPosition, tags: Tags);
} }
#endif #endif
@@ -681,7 +681,7 @@ namespace Barotrauma
if (maxDamageStructure != null) if (maxDamageStructure != null)
{ {
SoundPlayer.PlayDamageSound( SoundPlayer.PlayDamageSound(
DamageSoundType.StructureBlunt, "StructureBlunt",
impact * 10.0f, impact * 10.0f,
ConvertUnits.ToDisplayUnits(lastContactPoint), ConvertUnits.ToDisplayUnits(lastContactPoint),
MathHelper.Clamp(maxDamage * 4.0f, 1000.0f, 4000.0f), MathHelper.Clamp(maxDamage * 4.0f, 1000.0f, 4000.0f),
@@ -22,24 +22,28 @@ namespace Barotrauma
public readonly Vector2 Position; public readonly Vector2 Position;
public readonly Inventory Inventory; public readonly Inventory Inventory;
public readonly Submarine Submarine; public readonly Submarine Submarine;
public readonly float Condition;
public ItemSpawnInfo(ItemPrefab prefab, Vector2 worldPosition) public ItemSpawnInfo(ItemPrefab prefab, Vector2 worldPosition, float? condition = null)
{ {
Prefab = prefab; Prefab = prefab;
Position = worldPosition; Position = worldPosition;
Condition = (float)(condition ?? prefab.Health);
} }
public ItemSpawnInfo(ItemPrefab prefab, Vector2 position, Submarine sub) public ItemSpawnInfo(ItemPrefab prefab, Vector2 position, Submarine sub, float? condition = null)
{ {
Prefab = prefab; Prefab = prefab;
Position = position; Position = position;
Submarine = sub; Submarine = sub;
Condition = (float)(condition ?? prefab.Health);
} }
public ItemSpawnInfo(ItemPrefab prefab, Inventory inventory) public ItemSpawnInfo(ItemPrefab prefab, Inventory inventory, float? condition = null)
{ {
Prefab = prefab; Prefab = prefab;
Inventory = inventory; Inventory = inventory;
Condition = (float)(condition ?? prefab.Health);
} }
public Entity Spawn() public Entity Spawn()
@@ -48,12 +52,12 @@ namespace Barotrauma
if (Inventory != null) if (Inventory != null)
{ {
spawnedItem = new Item(Prefab, Vector2.Zero, null); spawnedItem = new Item(Prefab, Vector2.Zero, null, Condition);
Inventory.TryPutItem(spawnedItem, null, spawnedItem.AllowedSlots); Inventory.TryPutItem(spawnedItem, null, spawnedItem.AllowedSlots);
} }
else else
{ {
spawnedItem = new Item(Prefab, Position, Submarine); spawnedItem = new Item(Prefab, Position, Submarine, Condition);
} }
return spawnedItem; return spawnedItem;
@@ -83,25 +87,25 @@ namespace Barotrauma
removeQueue = new Queue<Entity>(); removeQueue = new Queue<Entity>();
} }
public void AddToSpawnQueue(ItemPrefab itemPrefab, Vector2 worldPosition) public void AddToSpawnQueue(ItemPrefab itemPrefab, Vector2 worldPosition, float? condition = null)
{ {
if (GameMain.Client != null) return; if (GameMain.Client != null) return;
spawnQueue.Enqueue(new ItemSpawnInfo(itemPrefab, worldPosition)); spawnQueue.Enqueue(new ItemSpawnInfo(itemPrefab, worldPosition, condition));
} }
public void AddToSpawnQueue(ItemPrefab itemPrefab, Vector2 position, Submarine sub) public void AddToSpawnQueue(ItemPrefab itemPrefab, Vector2 position, Submarine sub, float? condition = null)
{ {
if (GameMain.Client != null) return; if (GameMain.Client != null) return;
spawnQueue.Enqueue(new ItemSpawnInfo(itemPrefab, position, sub)); spawnQueue.Enqueue(new ItemSpawnInfo(itemPrefab, position, sub, condition));
} }
public void AddToSpawnQueue(ItemPrefab itemPrefab, Inventory inventory) public void AddToSpawnQueue(ItemPrefab itemPrefab, Inventory inventory, float? condition = null)
{ {
if (GameMain.Client != null) return; if (GameMain.Client != null) return;
spawnQueue.Enqueue(new ItemSpawnInfo(itemPrefab, inventory)); spawnQueue.Enqueue(new ItemSpawnInfo(itemPrefab, inventory, condition));
} }
public void AddToRemoveQueue(Entity entity) public void AddToRemoveQueue(Entity entity)
@@ -1509,7 +1509,9 @@ namespace Barotrauma.Networking
yield return CoroutineStatus.Running; yield return CoroutineStatus.Running;
} while (cinematic.Running);//(secondsLeft > 0.0f); } while (cinematic.Running);//(secondsLeft > 0.0f);
#if CLIENT
SoundPlayer.OverrideMusicType = null;
#endif
Submarine.Unload(); Submarine.Unload();
entityEventManager.Clear(); entityEventManager.Clear();