Merge remote-tracking branch 'refs/remotes/origin/master'

Conflicts:
	Subsurface/Barotrauma.csproj
	Subsurface/Source/Characters/AI/EnemyAIController.cs
	Subsurface/Source/Characters/AICharacter.cs
	Subsurface/Source/Characters/Character.cs
	Subsurface/Source/Items/Components/DockingPort.cs
	Subsurface/Source/Items/Components/Door.cs
	Subsurface/Source/Items/Item.cs
	Subsurface/Source/Networking/GameClient.cs
	Subsurface/Source/Networking/GameServer.cs
	Subsurface/Source/Physics/PhysicsBody.cs
This commit is contained in:
juanjp600
2016-08-30 18:04:49 -03:00
63 changed files with 2787 additions and 1927 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -15,7 +15,7 @@
<!-- lower yaw -->
<limb id = "1" radius="20" height="240" impacttolerance="50.0">
<sprite texture="Content/Characters/Coelanth/coelanth.png" sourcerect="425,1,101,309" depth="0.025" origin="0.5,0.5"/>
<attack type="PinchCCW" range="300" duration="0.5" damage="200" bleedingdamage="50" structuredamage="150" damagetype="slash" targetforce="-50"/>
<attack range="300" duration="0.5" damage="200" bleedingdamage="50" structuredamage="150" damagetype="slash" torque="100" targetforce="-50"/>
</limb>
<!-- body -->

View File

@@ -30,7 +30,7 @@
<limb id = "3" width="13" height="45" mass = "6" ignorecollisions="true" flip="true" impacttolerance="50.0">
<sprite texture="Content/Characters/Crawler/crawler.png" sourcerect="65,131,36,50" depth="0.15" origin="0.4,0.5"/>
<attack type="PinchCW" range="120" duration="0.5" damage="30" stun="0.1" bleedingdamage="3" structuredamage="50" damagetype="slash" targetforce="-30"/>
<attack range="120" duration="0.5" damage="30" stun="0.1" bleedingdamage="3" structuredamage="50" damagetype="slash" torque="-20" targetforce="-30"/>
</limb>
<limb id = "4" width="11" height="34" mass = "4" type="RightLeg" flip="true">

View File

@@ -44,12 +44,12 @@
<limb id = "8" width="50" height="320" impacttolerance="100.0">
<sprite texture="Content/Characters/Endworm/endworm.png" sourcerect="755,552,137,470" depth="0.08" origin="0.5,0.5"/>
<attack type="PinchCCW" range="800" duration="0.5" damage="30" stun="5.0" structuredamage="500" damagetype="slash"/>
<attack range="800" duration="0.5" damage="30" stun="5.0" torque="-100" structuredamage="500" damagetype="slash"/>
</limb>
<limb id = "9" width="50" height="320" impacttolerance="100.0">
<sprite texture="Content/Characters/Endworm/endworm.png" sourcerect="892,552,137,470" depth="0.08" origin="0.6,0.5"/>
<attack type="PinchCW" range="800" duration="0.5" damage="30" stun="5.0" structuredamage="500" damagetype="slash"/>
<attack range="800" duration="0.5" damage="30" stun="5.0" torque="100" structuredamage="500" damagetype="slash"/>
</limb>

View File

@@ -28,12 +28,12 @@
<limb id = "4" width="30" height="239" impacttolerance="100.0">
<sprite texture="Content/Characters/Fractalguardian/fractalguardian.png" sourcerect="183,0,53,238" depth="0.05" origin="0.5,0.5"/>
<attack type="PinchCCW" range="150" duration="0.5" damage="30" stun="1.0" damagetype="slash"/>
<attack range="150" duration="0.5" damage="30" stun="1.0" torque="-150" damagetype="slash"/>
</limb>
<limb id = "5" width="30" height="239" impacttolerance="100.0">
<sprite texture="Content/Characters/Fractalguardian/fractalguardian.png" sourcerect="236,0,53,238" size="-1,1" depth="0.05" origin="0.5,0.5"/>
<attack type="PinchCW" range="150" duration="0.5" damage="30" stun="1.0" damagetype="slash"/>
<attack range="150" duration="0.5" damage="30" stun="1.0" torque="150" damagetype="slash"/>
</limb>

View File

@@ -18,7 +18,7 @@
</limb>
<limb id = "2" width="30" height="175" impacttolerance="100">
<sprite texture="Content/Characters/Fractalguardian/fractalguardian.png" sourcerect="131,0,36,175" depth="0.1" origin="0.5,0.5"/>
<attack type="PinchCCW" range="150" duration="0.5" damage="30" stun="1.0" damagetype="slash"/>
<attack range="150" duration="0.5" damage="30" stun="1.0" torque="150" damagetype="slash"/>
</limb>
<limb id = "3" width="30" height="178" impacttolerance="100.0">
@@ -27,7 +27,7 @@
<limb id = "4" width="30" height="175" impacttolerance="100">
<sprite texture="Content/Characters/Fractalguardian/fractalguardian.png" sourcerect="131,0,36,175" depth="0.1" origin="0.5,0.5"/>
<attack type="PinchCW" range="150" duration="0.5" damage="30" stun="1.0" damagetype="slash"/>
<attack range="150" duration="0.5" damage="30" stun="1.0" torque="-150" damagetype="slash"/>
</limb>

View File

@@ -0,0 +1,118 @@
<?xml version="1.0" encoding="utf-8" ?>
<Character name ="human" humanoid="true" genders="true" maleheadid="1,8" femaleheadid="1,7" needsair="false" doesbleed="false">
<name firstname="Content/Characters/Human/[GENDER]firstnames.txt" lastname="Content/Characters/Human/lastnames.txt" />
<ragdoll headposition="134" torsoposition="108"
stepsize="42.0, 12.0"
walkanimspeed="4.58"
movementlerp="0.4"
legtorque="15.0"
thightorque="-5.0"
walkspeed="2.0"
swimspeed="2.0">
<!-- head -->
<limb id = "0" radius="13" mass = "6" type="Head" attackpriority="2" impacttolerance="5.0">
<sprite texture="Content/Characters/Human/[GENDER]head[HEADID].png" sourcerect="1,1,37,38" depth="0.04" origin="0.5,0.5"/>
<damagedsprite texture="Content/Characters/Human/damagedhead.png" sourcerect="1,1,37,38" origin="0.5,0.5"/>
</limb>
<!-- body -->
<limb id = "1" radius="14" height="21" mass = "20" type="Torso" attackpriority="3" impacttolerance="10.0">
<sprite texture="Content/Characters/Human/[GENDER]torso.png" sourcerect="0,0,29,58" depth="0.05" origin="0.5,0.6"/>
<damagedsprite texture="Content/Characters/Human/damagedtorso.png" sourcerect="0,0,29,58" origin="0.5,0.6"/>
</limb>
<limb id = "12" radius="13" mass = "20" type="Waist" impacttolerance="10.0">
<sprite texture="Content/Characters/Human/[GENDER]legs.png" sourcerect="0,0,32,29" depth="0.045" origin="0.5,0.5"/>
<damagedsprite texture="Content/Characters/Human/damagedlegs.png" sourcerect="0,0,32,29" origin="0.5,0.5"/>
</limb>
<!-- left arm -->
<limb id = "2" radius="8" height="20" mass="3" type="LeftArm">
<sprite texture="Content/Characters/Human/[GENDER]torso.png" sourcerect="30,2,17,39" depth="0.15" origin="0.5,0.5"/>
<damagedsprite texture="Content/Characters/Human/damagedtorso.png" sourcerect="30,2,17,39" origin="0.5,0.5"/>
</limb>
<limb id = "3" radius="6" height="26" mass="3" type="LeftHand" pullpos="0.0,-18.0">
<sprite texture="Content/Characters/Human/[GENDER]torso.png" sourcerect="49,2,13,47" depth="0.16" origin="0.5,0.5"/>
<damagedsprite texture="Content/Characters/Human/damagedtorso.png" sourcerect="49,2,13,47" origin="0.5,0.5"/>
</limb>
<!-- right arm -->
<limb id = "4" radius="8" height="20" mass="3" type="RightArm">
<sprite texture="Content/Characters/Human/[GENDER]torso.png" sourcerect="30,2,17,39" depth="0.01" origin="0.5,0.5"/>
<damagedsprite texture="Content/Characters/Human/damagedtorso.png" sourcerect="30,2,17,39" origin="0.5,0.5"/>
</limb>
<limb id = "5" radius="6" height="26" mass ="3" type="RightHand" pullpos="0.0,-18.0">
<sprite texture="Content/Characters/Human/[GENDER]torso.png" sourcerect="49,2,13,47" origin="0.5,0.5"/>
<damagedsprite texture="Content/Characters/Human/damagedtorso.png" sourcerect="49,2,13,47" origin="0.5,0.5"/>
</limb>
<!-- left leg -->
<limb id = "6" radius="10" height="30" mass = "8" type="LeftThigh">
<sprite texture="Content/Characters/Human/[GENDER]legs.png" sourcerect="0,32,26,48" depth="0.15" origin="0.5,0.5"/>
<damagedsprite texture="Content/Characters/Human/damagedlegs.png" sourcerect="0,32,26,48" origin="0.5,0.5"/>
</limb>
<limb id = "7" radius="6" height="39" mass = "5" type="LeftLeg">
<sprite texture="Content/Characters/Human/[GENDER]legs.png" sourcerect="32,0,22,50" depth="0.16" origin="0.5,0.5"/>
<damagedsprite texture="Content/Characters/Human/damagedlegs.png" sourcerect="32,0,22,50" origin="0.5,0.5"/>
</limb>
<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"/>
<damagedsprite texture="Content/Characters/Human/damagedlegs.png" sourcerect="35,53,16,25" origin="0.5,0.5"/>
<sound file ="Content/step.ogg"/>
</limb>
<!-- right leg -->
<limb id = "9" radius="10" height="30" mass = "8" type="RightThigh">
<sprite texture="Content/Characters/Human/[GENDER]legs.png" sourcerect="0,32,26,48" depth="0.11" origin="0.5,0.5"/>
<damagedsprite texture="Content/Characters/Human/[GENDER]legs.png" sourcerect="0,32,26,48" origin="0.5,0.5"/>
</limb>
<limb id = "10" radius="6" height="39" mass = "5" type="RightLeg">
<sprite texture="Content/Characters/Human/[GENDER]legs.png" sourcerect="32,0,22,50" depth="0.12" origin="0.5,0.5"/>
<damagedsprite texture="Content/Characters/Human/[GENDER]legs.png" sourcerect="32,0,22,50" origin="0.5,0.5"/>
</limb>
<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"/>
<damagedsprite texture="Content/Characters/Human/damagedlegs.png" sourcerect="35,53,16,25" origin="0.5,0.5"/>
<sound file ="Content/step.ogg"/>
</limb>
<limb id = "13" width="10" height="30" mass = "6" attackpriority="2" flip="true" impacttolerance="5.0" pullpos="0.0,25.0">
<sprite texture="Content/Characters/Husk/DivingSuit.png" sourcerect="110,76,18,52" depth="0.5" origin="0.5,0.5"/>
<attack range="70" duration="0.1" bleedingdamage="3" damage="10" stun="0.5" torque="-50" damagetype="slash" targetforce="10">
<StatusEffect type="OnUse" target="Character" HuskInfectionState="0.01" disabledeltatime="true"/>
<StatusEffect type="OnUse" target="This" Health="20.0" disabledeltatime="true"/>
</attack>
</limb>
<!-- head to body -->
<joint limb1="0" limb1anchor="0,-7" limb2="1" limb2anchor="-1,26" lowerlimit="-90" upperlimit="45"/>
<joint limb1="1" limb1anchor="0,-17" limb2="12" limb2anchor="0,7" lowerlimit="-10" upperlimit="10"/>
<!-- body to left arm -->
<joint limb1="1" limb1anchor="-3,14" limb2="2" limb2anchor="0,12"/>
<joint limb1="2" limb1anchor="0,-16" limb2="3" limb2anchor="-2,19" lowerlimit="5" upperlimit="170"/>
<!-- body to right arm -->
<joint limb1="1" limb1anchor="-3,14" limb2="4" limb2anchor="0,12"/>
<joint limb1="4" limb1anchor="0,-16" limb2="5" limb2anchor="-2,19" lowerlimit="5" upperlimit="170"/>
<!-- body to left leg -->
<joint limb1="12" limb1anchor="0,-1" limb2="6" limb2anchor="0,14" lowerlimit="-30" upperlimit="120"/>
<joint limb1="6" limb1anchor="0,-15" limb2="7" limb2anchor="0,20" lowerlimit="-120" upperlimit="0"/>
<joint limb1="7" limb1anchor="-3,-21" limb2="8" limb2anchor="5,7" lowerlimit="20" upperlimit="90"/>
<!-- body to right leg -->
<joint limb1="12" limb1anchor="0,-1" limb2="9" limb2anchor="0,14" lowerlimit="-30" upperlimit="120"/>
<joint limb1="9" limb1anchor="0,-15" limb2="10" limb2anchor="0,20" lowerlimit="-120" upperlimit="0"/>
<joint limb1="10" limb1anchor="-3,-21" limb2="11" limb2anchor="5,7" lowerlimit="20" upperlimit="90"/>
<joint limb1="1" limb1anchor="25,10" limb2="13" limb2anchor="25,0" lowerlimit="-40" upperlimit="0"/>
</ragdoll>
<ai attackhumans="500" attackrooms="5.0" attackweaker="50" attackstronger="-30"
sight="0.5" hearing="1.0"
attackcooldown="5.0"/>
</Character>

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8" ?>
<huskappendage>
<!-- spike/tentacle thingy -->
<limb id = "13" width="10" height="30" mass = "6" attackpriority="2" flip="true" impacttolerance="5.0" pullpos="0.0,25.0">
<sprite texture="Content/Characters/Husk/DivingSuit.png" sourcerect="110,76,18,52" depth="0.5" origin="0.5,0.5"/>
<attack range="70" duration="0.1" bleedingdamage="0.5" damage="10" stun="0.5" torque="-50" damagetype="slash" targetforce="10">
<StatusEffect type="OnUse" target="Character" HuskInfectionState="0.01"/>
<StatusEffect type="OnUse" target="This" Health="10.0" disabledeltatime="true"/>
</attack>
</limb>
<joint limb1="1" limb1anchor="25,10" limb2="13" limb2anchor="25,0" lowerlimit="-40" upperlimit="0"/>
</huskappendage>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

@@ -16,12 +16,22 @@
<!-- head -->
<limb id = "0" radius="13" mass = "6" type="Head" attackpriority="2" impacttolerance="5.0">
<sprite texture="Content/Characters/Husk/DivingSuit.png" sourcerect="93,1,34,31" depth="0.04" origin="0.5,0.5"/>
<attack type="PinchCCW" range="100" duration="0.5" damage="10" stun="0.1" bleedingdamage="3" structuredamage="30" damagetype="slash"/>
<sprite texture="Content/Characters/Husk/DivingSuit.png" sourcerect="95,0,33,25" depth="0.04" origin="0.5,0.5"/>
</limb>
<!-- spike/tentacle thingy -->
<limb id = "13" width="10" height="30" mass = "6" attackpriority="2" impacttolerance="5.0" flip="true" pullpos="0.0,25.0">
<sprite texture="Content/Characters/Husk/DivingSuit.png" sourcerect="110,76,18,52" depth="0.05" origin="0.5,0.5"/>
<attack range="70" duration="0.2" bleedingdamage="0.5" damage="10" stun="0.5" torque="-50" damagetype="slash" targetforce="10">
<StatusEffect type="OnUse" target="Character" HuskInfectionState="0.01" disabledeltatime="true"/>
<StatusEffect type="OnUse" target="This" Health="1.0" disabledeltatime="true"/>
</attack>
</limb>
<!-- body -->
<limb id = "1" radius="14" height="21" mass = "20" type="Torso" attackpriority="3" impacttolerance="10.0">
<sprite texture="Content/Characters/Husk/DivingSuit.png" limb="Torso" sourcerect="40,0,42,97" origin="0.5,0.55"/>
<sprite texture="Content/Characters/Husk/DivingSuit.png" limb="Torso" sourcerect="41,1,42,96" origin="0.5,0.55"/>
</limb>
<limb id = "12" radius="13" mass = "20" type="Waist" impacttolerance="10.0">
<sprite texture="Content/Characters/Husk/DivingSuit.png" sourcerect="0,0,1,1" depth="0.045" origin="0.5,0.5"/>
@@ -66,14 +76,14 @@
<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"/>
<sound file ="Content/step.ogg"/>
</limb>
</limb>
<!-- head to body -->
<joint limb1="0" limb1anchor="-10,-10" limb2="1" limb2anchor="-8,33" lowerlimit="0" upperlimit="10"/>
<joint limb1="1" limb1anchor="0,-17" limb2="12" limb2anchor="0,15" lowerlimit="30" upperlimit="60"/>
<joint limb1="0" limb1anchor="-10,-10" limb2="1" limb2anchor="-3,28" lowerlimit="0" upperlimit="10"/>
<!-- spike to head -->
<joint limb1="0" limb1anchor="35,-8" limb2="13" limb2anchor="30,0" lowerlimit="-40" upperlimit="0"/>
<joint limb1="1" limb1anchor="0,-17" limb2="12" limb2anchor="0,15" lowerlimit="30" upperlimit="60"/>
<!-- body to left arm -->
<joint limb1="1" limb1anchor="-3,14" limb2="2" limb2anchor="0,12"/>

View File

@@ -46,7 +46,7 @@
<!-- ""claw" -->
<limb id = "6" width="15" height="63" mass = "4" flip="true" pullpos="0.0,30.0" refjoint="0">
<sprite texture="Content/Characters/Mantis/mantis.png" sourcerect="228,1,28,76" depth="0.01" origin="0.5,0.5"/>
<attack type="PinchCW" range="200" duration="0.5" damage="30" stun="0.1" bleedingdamage="5" structuredamage="50" damagetype="slash" targetforce="-50"/>
<attack range="200" duration="0.5" damage="30" stun="0.1" bleedingdamage="5" structuredamage="50" torque="-20" damagetype="slash" targetforce="-50"/>
<sound file ="Content/Sounds/stepMetal.ogg"/>
</limb>

View File

@@ -11,7 +11,7 @@
<!-- head -->
<limb id = "0" radius="230" height="500" type="Head" steerforce="1.0" flip="true" armorsector="0.0,180.0" armorvalue="100.0" impacttolerance="100">
<sprite texture="Content/Characters/Moloch/moloch.png" sourcerect="0,0,628,1024" depth="0.02" origin ="0.4,0.5"/>
<attack type="Hit" range="700" duration="0.2" damage="200" stun="5" force="300" damagetype="blunt" targetforce="100"/>
<attack range="700" duration="0.2" damage="200" stun="5" force="25" damagetype="blunt" targetforce="100"/>
</limb>
<limb id = "1" width="50" height="440" flip="true">

View File

@@ -17,7 +17,7 @@
<limb id = "1" width="16" height="103" impacttolerance="50.0">
<sprite texture="Content/Characters/TigerThresher/tigerthresher.png" sourcerect="391,169,28,110" depth="0.025" origin="0.5,0.5"/>
<damagedsprite texture="Content/Characters/TigerThresher/damagedtigerthresher.png" sourcerect="391,169,28,110" origin="0.5,0.5"/>
<attack type="PinchCCW" range="200" duration="0.5" damage="150" bleedingdamage="10" structuredamage="200" damagetype="slash" targetforce="-50"/>
<attack range="200" duration="0.5" damage="150" bleedingdamage="10" structuredamage="200" damagetype="slash" torque="80" targetforce="-50"/>
</limb>
<!-- body -->

View File

@@ -6,6 +6,7 @@
<!-- head -->
<limb id = "0" width="350" height="320" type="Head" steerforce="1.0" flip="true" armorsector="0.0,360.0" armorvalue="100.0">
<sprite texture="Content/Characters/Watcher/watcher.png" sourcerect="0,0,369,348" depth="0.02" origin ="0.5,0.6"/>
<attack range="150" duration="0.2" damage="200" stun="5" force="10" damagetype="blunt" targetforce="100"/>
</limb>
@@ -13,8 +14,7 @@
<sprite texture="Content/Characters/Watcher/watcher.png" sourcerect="395,0,117,239" depth="0.025" origin="0.5,0.5"/>
<lightsource range="200.0" color="0.8,0.8,1.0,1.0">
<sprite texture="Content/Characters/Watcher/watcher.png" sourcerect="391,282,121,230" depth="0.025" origin="0.5,0.5"/>
</lightsource>
</lightsource>
</limb>
<limb id = "2" width="300" height="119" flip="true">

View File

@@ -11,6 +11,7 @@
<CauseOfDeath.Suffocation>Suffocated</CauseOfDeath.Suffocation>
<CauseOfDeath.Pressure>Crushed by water pressure</CauseOfDeath.Pressure>
<CauseOfDeath.Burn>Burned to death</CauseOfDeath.Burn>
<CauseOfDeath.Husk>Taken over by a parasite</CauseOfDeath.Husk>
<CauseOfDeath.Disconnected>Disconnected</CauseOfDeath.Disconnected>
<Self_CauseOfDeath.Damage>You have succumbed to your injuries.</Self_CauseOfDeath.Damage>
@@ -19,6 +20,17 @@
<Self_CauseOfDeath.Suffocation>You have suffocated.</Self_CauseOfDeath.Suffocation>
<Self_CauseOfDeath.Pressure>You have been crushed by water pressure.</Self_CauseOfDeath.Pressure>
<Self_CauseOfDeath.Burn>You have burned to death.</Self_CauseOfDeath.Burn>
<Self_CauseOfDeath.Husk>The parasite has taken over your body.</Self_CauseOfDeath.Husk>
<Self_CauseOfDeath.Disconnected>You have been disconnected from the server.</Self_CauseOfDeath.Disconnected>
<HuskDormant>Your throat feels sore</HuskDormant>
<HuskDormant>Your feel feverish</HuskDormant>
<HuskDormant>It feels as if something was stuck in your throat</HuskDormant>
<HuskDormant>Your muscles are aching</HuskDormant>
<HuskCantSpeak>You feel something moving in your throat. You try to scream but no sound comes out.</HuskCantSpeak>
<HuskActivate>A strange chitinous appendage bursts out from your mouth. Use it to inject eggs into a living body by pressing [Attack]!</HuskActivate>
</infotexts>

View File

@@ -131,7 +131,10 @@
<fabricableitem name="Morbusine" requireditems="Sulphuric Acid, Auxiliorizine" requiredtime="30">
<RequiredSkill name="Medical" level="60"/>
</fabricableitem>
<fabricableitem name="Calyxanide" requireditems="Velonaceps Calyx Eggs, Corrigodone" requiredtime="30">
<RequiredSkill name="Medical" level="60"/>
</fabricableitem>
</Fabricator>
<ConnectionPanel selectkey="Action" canbeselected = "true">

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -55,7 +55,7 @@
<Sprite texture ="med.png" sourcerect="24,16,8,16" depth="0.6" color="0.2,0.2,0.2,1.0"/>
<Body width="25" height="5" density="40"/>
<Body width="8" height="16" density="40"/>
<Holdable slots="Any,RightHand,LeftHand"/>
</Item>
@@ -68,9 +68,9 @@
pickdistance="150"
description="A mild stimulant which is used as an incredient in the manufacture of various medicines.">
<Sprite texture ="med.png" sourcerect="24,16,8,16" depth="0.6" />
<Sprite texture ="med.png" sourcerect="15,15,8,17" depth="0.6" />
<Body width="25" height="5" density="20"/>
<Body width="8" height="17" density="20"/>
<ItemComponent>
<StatusEffect type="OnUse" target="Character" Health="0.1" duration="20"/>
@@ -95,7 +95,7 @@
<Sprite texture ="med.png" sourcerect="24,16,8,16" depth="0.6" />
<Body width="25" height="5" density="20"/>
<Body width="8" height="16" density="20"/>
<Holdable slots="Any,RightHand,LeftHand">
<StatusEffect type="OnUse" target="Character" Health="-0.3" Oxygen="2.0" duration="10">
@@ -115,7 +115,7 @@
<Sprite texture ="med.png" sourcerect="24,16,8,16" depth="0.6" />
<Body width="25" height="5" density="20"/>
<Body width="8" height="16" density="20"/>
<ItemComponent>
<StatusEffect type="OnUse" target="Character" Bleeding="-0.1" duration="10.0"/>
@@ -140,7 +140,7 @@
<Sprite texture ="med.png" sourcerect="24,16,8,16" depth="0.6"/>
<Body width="25" height="5" density="20"/>
<Body width="8" height="16" density="20"/>
<ItemComponent>
<StatusEffect type="OnUse" target="This" Condition="-25.0" disabledeltatime="true"/>
@@ -164,7 +164,7 @@
<Sprite texture ="med.png" sourcerect="24,16,8,16" depth="0.6"/>
<Body width="25" height="5" density="20"/>
<Body width="8" height="16" density="20"/>
<Holdable slots="Any,RightHand,LeftHand">
<StatusEffect type="OnUse" target="Character" Health="1.0" Oxygen="2.0" Bleeding="-0.05" duration="60.0">
@@ -180,9 +180,9 @@
Tags="smallitem,chem,medical"
pickdistance="150">
<Sprite texture ="med.png" sourcerect="24,16,8,16" depth="0.6"/>
<Sprite texture ="med.png" sourcerect="15,15,8,17" depth="0.6"/>
<Body width="25" height="5" density="10"/>
<Body width="8" height="17" density="10"/>
<Holdable slots="Any,RightHand,LeftHand">
<StatusEffect type="OnUse" target="Character" Health="-0.1" duration="20.0">
@@ -204,9 +204,9 @@
<StatusEffect type="OnUse" target="Character" SpeedMultiplier="0.8" setvalue="true" duration="20.0"/>
</ItemComponent>
<Sprite texture ="med.png" sourcerect="24,16,8,16" depth="0.6"/>
<Sprite texture ="med.png" sourcerect="15,15,8,17" depth="0.6"/>
<Body width="25" height="5" density="10"/>
<Body width="8" height="7" density="10"/>
<Holdable slots="Any,RightHand,LeftHand">
<StatusEffect type="OnUse" target="Character" SpeedMultiplier="0.8" setvalue="true" duration="20.0">
@@ -224,7 +224,7 @@
<Sprite texture ="med.png" sourcerect="24,16,8,16" depth="0.6"/>
<Body width="25" height="5" density="10"/>
<Body width="8" height="16" density="10"/>
<Holdable slots="Any,RightHand,LeftHand">
<StatusEffect type="OnUse" target="Character" Health="-5.0" disabledeltatime="true">
@@ -242,7 +242,7 @@
<Sprite texture ="med.png" sourcerect="24,16,8,16" depth="0.6"/>
<Body width="25" height="5" density="10"/>
<Body width="8" height="16" density="10"/>
<Holdable slots="Any,RightHand,LeftHand">
<StatusEffect type="OnUse" target="Character" Health="-5.0" disabledeltatime="true">
@@ -260,7 +260,7 @@
<Sprite texture ="med.png" sourcerect="24,16,8,16" depth="0.6"/>
<Body width="25" height="5" density="10"/>
<Body width="8" height="16" density="10"/>
<Holdable slots="Any,RightHand,LeftHand">
<StatusEffect type="OnFire" target="this" condition="-50"/>
@@ -278,9 +278,9 @@
Tags="smallitem,chem,medical"
pickdistance="150">
<Sprite texture ="med.png" sourcerect="24,16,8,16" depth="0.6"/>
<Sprite texture ="med.png" sourcerect="15,15,8,17" depth="0.6"/>
<Body width="25" height="5" density="10"/>
<Body width="8" height="17" density="10"/>
<Holdable slots="Any,RightHand,LeftHand">
<StatusEffect type="OnUse" target="Character" Health="-5.0" Stun="10" disabledeltatime="true">
@@ -298,7 +298,7 @@
<Sprite texture ="med.png" sourcerect="24,16,8,16" depth="0.6"/>
<Body width="25" height="5" density="10"/>
<Body width="8" height="16" density="10"/>
<Holdable slots="Any,RightHand,LeftHand">
<StatusEffect type="OnUse" target="Character" Health="-5.0" disabledeltatime="true">
@@ -314,9 +314,9 @@
Tags="smallitem,chem,medical"
pickdistance="150">
<Sprite texture ="med.png" sourcerect="24,16,8,16" depth="0.6"/>
<Sprite texture ="med.png" sourcerect="15,15,8,17" depth="0.6"/>
<Body width="25" height="5" density="10"/>
<Body width="8" height="17" density="10"/>
<Holdable slots="Any,RightHand,LeftHand">
<StatusEffect type="OnUse" target="Character" Health="-1.0" duration="60.0">
@@ -334,7 +334,7 @@
<Sprite texture ="med.png" sourcerect="24,16,8,16" depth="0.6"/>
<Body width="25" height="5" density="15"/>
<Body width="8" height="16" density="25"/>
<Holdable slots="Any,RightHand,LeftHand">
<StatusEffect type="OnUse" target="Character" Health="-5.0" duration="60.0">
@@ -353,7 +353,7 @@
<Sprite texture ="med.png" sourcerect="24,16,8,16" depth="0.6"/>
<Body width="25" height="5" density="15"/>
<Body width="8" height="16" density="15"/>
<Holdable slots="Any,RightHand,LeftHand">
<StatusEffect type="OnUse" target="Character" SpeedMultiplier="1.5" setvalue="true" duration="60.0">
@@ -372,7 +372,7 @@
<Sprite texture ="med.png" sourcerect="24,16,8,16" depth="0.6"/>
<Body width="25" height="5" density="10"/>
<Body width="8" height="16" density="10"/>
<Holdable slots="Any,RightHand,LeftHand">
<StatusEffect type="OnUse" target="Character" Health="-10.0" duration="60.0">
@@ -380,6 +380,45 @@
</StatusEffect>
</Holdable>
</Item>
<Item
name="Velonaceps Calyx Eggs"
category="Material"
spritecolor="0.0,0.0,0.0,1.0"
Tags="smallitem,chem,medical"
pickdistance="150"
description="Dormant eggs of the Europan lifeform colloquially referred to as 'husk parasite'.">
<Sprite texture ="med.png" sourcerect="24,16,8,16" depth="0.6"/>
<Body width="8" height="16" density="10"/>
<Holdable slots="Any,RightHand,LeftHand">
<StatusEffect type="OnUse" target="Character" HuskInfectionState="0.01">
<RequiredItem name="Medical Syringe" type="Container"/>
</StatusEffect>
</Holdable>
</Item>
<Item
name="Calyxanide"
category="Material"
spritecolor="0.0,0.0,0.0,1.0"
Tags="smallitem,chem,medical"
pickdistance="150"
description="An antiparasitic drug used in the treatment of husk parasite infections.">
<Sprite texture ="med.png" sourcerect="24,16,8,16" depth="0.6"/>
<Body width="8" height="16" density="10"/>
<Holdable slots="Any,RightHand,LeftHand">
<StatusEffect type="OnUse" target="Character" HuskInfectionState="0.0" setvalue="true">
<RequiredItem name="Medical Syringe" type="Container"/>
</StatusEffect>
</Holdable>
</Item>
</Items>

View File

@@ -78,7 +78,7 @@
width="24" height="32" resizevertical="true"/>
<topwindow sprite="Content/Map/testroom.png" sourcerect="625,327,128,80" depth ="0.05"
width = "128" height ="80" body="true" health="100"/>
width = "128" height ="49" body="true" health="100"/>
<verticalwindow sprite="Content/Map/testroom.png" sourcerect="399,560,128,224" depth ="0.05"
width = "128" height ="224" body="true" health="100"/>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

After

Width:  |  Height:  |  Size: 1.2 MiB

View File

@@ -8,7 +8,7 @@
radarlabel="Infrasonic signal"
failuremessage="Retrieving the artifact failed"
successmessage="The artifact has been succesfully retrieved"
spawntype="ruin"
spawntype="ruin"
itemname="Skyholder Artifact">
<message header="Artifact collected" text="The artifact is now on board. Navigate the submarine out of the cavern to claim the reward."/>
</SalvageMission>
@@ -44,7 +44,7 @@
reward="800"
radarlabel="Tiger Thresher"
successmessage="The Tiger Thresher has been killed."
monsterfile="Content/Characters/TigerThresher/tigerthresher.xml">
monsterfile="Content/Characters/Tigerthresher/tigerthresher.xml">
<message header="Target terminated" text="The thresher is dead. Navigate the submarine out of the cavern to claim the reward."/>
</MonsterMission>
@@ -113,9 +113,10 @@
description="Reseachers of [location1] need someone to deliver some dangerous chemicals to [location2] for a reward of 200 credits."
commonness="10"
reward="200"
successmessage="The chemicals have been successfully delivered.">
successmessage="The chemicals have been successfully delivered."
requireddeliveryamount="20">
<Items>
<Item name="Chemical Crate" requireddeliveryamount="20">
<Item name="Chemical Crate">
<Item name="Auxiliorizine" amount="5"/>
<Item name="Sulphuric Acid" amount="5"/>
</Item>
@@ -127,6 +128,19 @@
</Items>
</CargoMission>
<CargoMission
name="Biohazard"
description="Local reseachers are offering 500 credits for delivering a container of husk parasite eggs to [location2]."
commonness="10"
reward="500"
successmessage="The husk eggs have been successfully delivered.">
<Items>
<Item name="Chemical Crate">
<Item name="Velonaceps Calyx Eggs" amount="10"/>
</Item>
</Items>
</CargoMission>
<CargoMission
name="Handle with care"
description="Local reseachers are offering 2000 credits for delivering a large amount of nitroglycerin to [location2]."
@@ -148,8 +162,9 @@
description="A local clown syndicate is offering 100 credits for delivering a shipment of clowning supplies to [location2]."
commonness="2"
reward="100"
successmessage="The clown gear has been successfully delivered.">
<Items requireddeliveryamount="35">
successmessage="The clown gear has been successfully delivered."
requireddeliveryamount="35">
<Items >
<Item name="Metal Crate">
<Item name="Clown Mask" amount="10"/>
<Item name="Clown Costume" amount="10"/>

View File

@@ -9,7 +9,7 @@
musictype="monster"/>
<MonsterEvent name="Under attack" description=""
characterfile="Content/Characters/TigerThresher/tigerthresher.xml"
characterfile="Content/Characters/Tigerthresher/tigerthresher.xml"
commonness="10"
difficulty="20"
minamount="1" maxamount="3"

View File

@@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.5.0.3")]
[assembly: AssemblyFileVersion("0.5.0.3")]
[assembly: AssemblyVersion("0.5.1.1")]
[assembly: AssemblyFileVersion("0.5.1.1")]

View File

@@ -10,6 +10,8 @@ namespace Barotrauma
public enum AiState { None, Attack, GoTo, Escape }
public enum SteeringState { Wander, Seek, Escape }
public bool Enabled;
public readonly Character Character;
protected AiState state;
@@ -51,6 +53,8 @@ namespace Barotrauma
public AIController (Character c)
{
Character = c;
Enabled = true;
}
public virtual void DebugDraw(SpriteBatch spriteBatch) { }

View File

@@ -218,24 +218,27 @@ namespace Barotrauma
}
//steeringManager.SteeringAvoid(deltaTime, 1.0f);
steeringManager.SteeringSeek(attackSimPosition);
Limb attackLimb = attackingLimb;
//check if any of the limbs is close enough to attack the target
if (attackingLimb == null)
{
foreach (Limb limb in Character.AnimController.Limbs)
{
if (limb.attack==null || limb.attack.Type == AttackType.None) continue;
if (limb.attack==null) continue;
attackLimb = limb;
if (ConvertUnits.ToDisplayUnits(Vector2.Distance(limb.SimPosition, attackSimPosition)) > limb.attack.Range) continue;
attackingLimb = limb;
break;
}
return;
}
UpdateLimbAttack(deltaTime, attackingLimb, attackSimPosition);
if (attackLimb != null)
{
steeringManager.SteeringSeek(attackSimPosition - (attackLimb.SimPosition - SimPosition));
if (attackingLimb != null) UpdateLimbAttack(deltaTime, attackingLimb, attackSimPosition);
}
}
private void UpdateCoolDown(Vector2 attackPosition, float deltaTime)
@@ -330,84 +333,15 @@ namespace Barotrauma
private void UpdateLimbAttack(float deltaTime, Limb limb, Vector2 attackPosition)
{
IDamageable damageTarget = null;
var damageTarget = (wallAttackPos != Vector2.Zero && targetEntity != null) ? targetEntity : selectedAiTarget.Entity as IDamageable;
float dist = ConvertUnits.ToDisplayUnits(Vector2.Distance(limb.SimPosition, attackPosition));
limb.UpdateAttack(deltaTime, attackPosition, damageTarget);
switch (limb.attack.Type)
{
case AttackType.PinchCW:
case AttackType.PinchCCW:
float dir = (limb.attack.Type == AttackType.PinchCW) ? 1.0f : -1.0f;
damageTarget = (wallAttackPos != Vector2.Zero && targetEntity != null) ? targetEntity : selectedAiTarget.Entity as IDamageable;
attackTimer += deltaTime*0.05f;
if (damageTarget == null)
{
attackTimer = limb.attack.Duration;
break;
}
if (dist < limb.attack.Range * 0.5f)
{
attackTimer += deltaTime;
limb.body.ApplyTorque(limb.Mass * 50.0f * Character.AnimController.Dir * dir);
if (attackTimer >= limb.attack.Duration)
{
limb.attack.DoDamage(Character, damageTarget, limb.WorldPosition, 1.0f, (limb.soundTimer <= 0.0f));
limb.soundTimer = Limb.SoundInterval;
}
}
Vector2 diff = attackPosition - limb.SimPosition;
if (diff.LengthSquared() > 0.00001f)
{
limb.body.ApplyLinearImpulse(limb.Mass * 10.0f *
Vector2.Normalize(attackPosition - limb.SimPosition));
}
steeringManager.SteeringSeek(attackPosition + (limb.SimPosition-SimPosition), 5.0f);
break;
case AttackType.Hit:
damageTarget = (wallAttackPos != Vector2.Zero && targetEntity != null) ? targetEntity : selectedAiTarget.Entity as IDamageable;
if (damageTarget == null)
{
attackTimer = limb.attack.Duration;
break;
}
if (dist < limb.attack.Range)
{
attackTimer += deltaTime;
limb.body.ApplyForce(limb.Mass * limb.attack.Force * Vector2.Normalize(attackPosition - limb.SimPosition));
if (damageTarget is Character && dist<limb.attack.Range*0.5f)
{
limb.attack.DoDamage(Character, damageTarget, limb.WorldPosition, deltaTime, (limb.soundTimer <= 0.0f));
limb.soundTimer = Limb.SoundInterval;
}
}
steeringManager.SteeringSeek(attackPosition + (limb.SimPosition-SimPosition), 5.0f);
break;
default:
attackTimer = limb.attack.Duration;
break;
}
if (attackTimer >= limb.attack.Duration)
if (limb.AttackTimer >= limb.attack.Duration)
{
wallAttackPos = Vector2.Zero;
attackTimer = 0.0f;
if (Vector2.Distance(limb.SimPosition, attackPosition)<5.0) coolDownTimer = attackCoolDown;
limb.AttackTimer = 0.0f;
if (Vector2.Distance(limb.SimPosition, attackPosition)<5.0) coolDownTimer = attackCoolDown;
}
}

View File

@@ -49,7 +49,7 @@ namespace Barotrauma
if (isDead || health <= 0.0f) return;
if (Controlled == this) return;
if (Controlled == this || !aiController.Enabled) return;
if (soundTimer > 0)
{

View File

@@ -338,13 +338,13 @@ namespace Barotrauma
if (!onGround || (LowestLimb.SimPosition.Y - floorY > 0.5f && stairs == null)) return;
float? ceilingY = null;
if (Submarine.PickBody(head.SimPosition, head.SimPosition + Vector2.UnitY, null, Physics.CollisionWall)!=null)
{
ceilingY = Submarine.LastPickedPosition.Y;
//float? ceilingY = null;
//if (Submarine.PickBody(head.SimPosition, head.SimPosition + Vector2.UnitY, null, Physics.CollisionWall)!=null)
//{
// ceilingY = Submarine.LastPickedPosition.Y;
if (ceilingY - floorY < HeadPosition) Crouching = true;
}
// if (ceilingY - floorY < HeadPosition) Crouching = true;
//}
getUpSpeed = getUpSpeed * Math.Max(head.SimPosition.Y - colliderPos.Y, 0.5f);
@@ -456,24 +456,20 @@ namespace Barotrauma
else
{
float movementFactor = (movement.X / 4.0f) * movement.X * Math.Sign(movement.X);
//MoveLimb(leftFoot, footPos, 2.5f);
for (int i = -1; i < 2; i+=2 )
for (int i = -1; i < 2; i += 2)
{
Vector2 footPos = new Vector2(
Crouching ? waist.SimPosition.X + Math.Sign(stepSize.X*i)*Dir*0.3f : waist.SimPosition.X,
colliderPos.Y - 0.2f);
Vector2 footPos = new Vector2(
Crouching ? waist.SimPosition.X + Math.Sign(stepSize.X * i) * Dir * 0.3f : GetCenterOfMass().X,
colliderPos.Y - 0.1f);
var foot = i == -1 ? rightFoot : leftFoot;
MoveLimb(foot, footPos, Math.Abs(foot.SimPosition.X - footPos.X)*50.0f);
MoveLimb(foot, footPos, Math.Abs(foot.SimPosition.X - footPos.X) * 100.0f, true);
}
leftFoot.body.SmoothRotate(Dir * MathHelper.PiOver2, 5.0f);
rightFoot.body.SmoothRotate(Dir * MathHelper.PiOver2, 5.0f);
leftFoot.body.SmoothRotate(Dir * MathHelper.PiOver2, 50.0f);
rightFoot.body.SmoothRotate(Dir * MathHelper.PiOver2, 50.0f);
if (!rightHand.Disabled)
{
@@ -1183,7 +1179,7 @@ namespace Barotrauma
Vector2 position = limb.SimPosition;
if (!limb.pullJoint.Enabled && mirror)
if ((limb.pullJoint==null || !limb.pullJoint.Enabled) && mirror)
{
difference = limb.body.SimPosition - torso.SimPosition;
difference = Vector2.Transform(difference, torsoTransform);

View File

@@ -30,8 +30,8 @@ namespace Barotrauma
protected float strongestImpact;
float headPosition, headAngle;
float torsoPosition, torsoAngle;
public float headPosition, headAngle;
public float torsoPosition, torsoAngle;
protected double onFloorTimer;
@@ -231,8 +231,7 @@ namespace Barotrauma
byte ID = Convert.ToByte(subElement.Attribute("id").Value);
Limb limb = new Limb(character, subElement, scale);
limb.body.FarseerBody.OnCollision += OnLimbCollision;
Limbs[ID] = limb;
@@ -240,38 +239,7 @@ namespace Barotrauma
if (!limbDictionary.ContainsKey(limb.type)) limbDictionary.Add(limb.type, limb);
break;
case "joint":
Byte limb1ID = Convert.ToByte(subElement.Attribute("limb1").Value);
Byte limb2ID = Convert.ToByte(subElement.Attribute("limb2").Value);
Vector2 limb1Pos = ToolBox.GetAttributeVector2(subElement, "limb1anchor", Vector2.Zero) * scale;
limb1Pos = ConvertUnits.ToSimUnits(limb1Pos);
Vector2 limb2Pos = ToolBox.GetAttributeVector2(subElement, "limb2anchor", Vector2.Zero) * scale;
limb2Pos = ConvertUnits.ToSimUnits(limb2Pos);
RevoluteJoint joint = new RevoluteJoint(Limbs[limb1ID].body.FarseerBody, Limbs[limb2ID].body.FarseerBody, limb1Pos, limb2Pos);
joint.CollideConnected = false;
if (subElement.Attribute("lowerlimit")!=null)
{
joint.LimitEnabled = true;
joint.LowerLimit = float.Parse(subElement.Attribute("lowerlimit").Value) * ((float)Math.PI / 180.0f);
joint.UpperLimit = float.Parse(subElement.Attribute("upperlimit").Value) * ((float)Math.PI / 180.0f);
}
joint.MotorEnabled = true;
joint.MaxMotorTorque = 0.25f;
GameMain.World.AddJoint(joint);
for (int i = 0; i < limbJoints.Length; i++ )
{
if (limbJoints[i] != null) continue;
limbJoints[i] = joint;
break;
}
AddJoint(subElement, scale);
break;
}
@@ -308,6 +276,58 @@ namespace Barotrauma
FindLowestLimb();
}
public void AddJoint(XElement subElement, float scale = 1.0f)
{
byte limb1ID = Convert.ToByte(subElement.Attribute("limb1").Value);
byte limb2ID = Convert.ToByte(subElement.Attribute("limb2").Value);
Vector2 limb1Pos = ToolBox.GetAttributeVector2(subElement, "limb1anchor", Vector2.Zero) * scale;
limb1Pos = ConvertUnits.ToSimUnits(limb1Pos);
Vector2 limb2Pos = ToolBox.GetAttributeVector2(subElement, "limb2anchor", Vector2.Zero) * scale;
limb2Pos = ConvertUnits.ToSimUnits(limb2Pos);
RevoluteJoint joint = new RevoluteJoint(Limbs[limb1ID].body.FarseerBody, Limbs[limb2ID].body.FarseerBody, limb1Pos, limb2Pos);
joint.CollideConnected = false;
if (subElement.Attribute("lowerlimit") != null)
{
joint.LimitEnabled = true;
joint.LowerLimit = float.Parse(subElement.Attribute("lowerlimit").Value) * ((float)Math.PI / 180.0f);
joint.UpperLimit = float.Parse(subElement.Attribute("upperlimit").Value) * ((float)Math.PI / 180.0f);
}
joint.MotorEnabled = true;
joint.MaxMotorTorque = 0.25f;
GameMain.World.AddJoint(joint);
for (int i = 0; i < limbJoints.Length; i++)
{
if (limbJoints[i] != null) continue;
limbJoints[i] = joint;
return;
}
Array.Resize(ref limbJoints, limbJoints.Length + 1);
limbJoints[limbJoints.Length - 1] = joint;
}
public void AddLimb(Limb limb)
{
limb.body.FarseerBody.OnCollision += OnLimbCollision;
Array.Resize(ref Limbs, Limbs.Length + 1);
Limbs[Limbs.Length-1] = limb;
Mass += limb.Mass;
if (!limbDictionary.ContainsKey(limb.type)) limbDictionary.Add(limb.type, limb);
}
public bool OnLimbCollision(Fixture f1, Fixture f2, Contact contact)
{

View File

@@ -2,22 +2,18 @@
using Barotrauma.Particles;
using System;
using System.Xml.Linq;
using System.Collections.Generic;
namespace Barotrauma
{
enum CauseOfDeath
{
Damage, Bloodloss, Pressure, Suffocation, Drowning, Burn, Disconnected
Damage, Bloodloss, Pressure, Suffocation, Drowning, Burn, Husk, Disconnected
}
public enum DamageType { None, Blunt, Slash, Burn }
public enum AttackType
{
None, PinchCW, PinchCCW, Hit
}
struct AttackResult
{
public readonly float Damage;
@@ -36,8 +32,6 @@ namespace Barotrauma
class Attack
{
public readonly AttackType Type;
public readonly float Range;
public readonly float Duration;
@@ -47,8 +41,12 @@ namespace Barotrauma
private readonly float damage;
private readonly float bleedingDamage;
private readonly List<StatusEffect> statusEffects;
public readonly float Force;
public readonly float Torque;
public readonly float TargetForce;
private Sound sound;
@@ -74,23 +72,8 @@ namespace Barotrauma
return (Duration == 0.0f) ? structureDamage : structureDamage * deltaTime;
}
//public Attack(AttackType type, float range,)
//{
//}
public Attack(XElement element)
{
try
{
Type = (AttackType)Enum.Parse(typeof(AttackType), element.Attribute("type").Value, true);
}
catch
{
Type = AttackType.None;
}
try
{
DamageType = (DamageType)Enum.Parse(typeof(DamageType), ToolBox.GetAttributeString(element, "damagetype", "None"), true);
@@ -106,9 +89,10 @@ namespace Barotrauma
bleedingDamage = ToolBox.GetAttributeFloat(element, "bleedingdamage", 0.0f);
Force = ToolBox.GetAttributeFloat(element,"force", 0.0f);
TargetForce = ToolBox.GetAttributeFloat(element, "targetforce", 0.0f);
Torque = ToolBox.GetAttributeFloat(element, "torque", 0.0f);
Stun = ToolBox.GetAttributeFloat(element, "stun", 0.0f);
string soundPath = ToolBox.GetAttributeString(element, "sound", "");
@@ -123,10 +107,20 @@ namespace Barotrauma
priority = ToolBox.GetAttributeFloat(element, "priority", 1.0f);
statusEffects = new List<StatusEffect>();
foreach (XElement subElement in element.Elements())
{
if (subElement.Name.ToString().ToLowerInvariant() != "particleemitter") continue;
particleEmitterPrefab = new ParticleEmitterPrefab(subElement);
switch (subElement.Name.ToString().ToLowerInvariant())
{
case "particleemitter":
particleEmitterPrefab = new ParticleEmitterPrefab(subElement);
break;
case "statuseffect":
statusEffects.Add(StatusEffect.Load(subElement));
break;
}
}
}
@@ -142,9 +136,24 @@ namespace Barotrauma
{
sound.Play(1.0f, 500.0f, worldPosition);
}
var attackResult = target.AddDamage(attacker, worldPosition, this, deltaTime, playSound);
return target.AddDamage(attacker, worldPosition, this, deltaTime, playSound);
var effectType = attackResult.Damage > 0.0f ? ActionType.OnUse : ActionType.OnFailure;
foreach (StatusEffect effect in statusEffects)
{
if (effect.Targets.HasFlag(StatusEffect.TargetType.This) && attacker is Character)
{
effect.Apply(effectType, deltaTime, (Character)attacker, (Character)attacker);
}
if (effect.Targets.HasFlag(StatusEffect.TargetType.Character) && target is Character)
{
effect.Apply(effectType, deltaTime, (Character)target, (Character)target);
}
}
return attackResult;
}
}
}

View File

@@ -112,6 +112,8 @@ namespace Barotrauma
//which AIstate each sound is for
private AIController.AiState[] soundStates;
private float attackCoolDown;
public Entity ViewTarget
{
get;
@@ -248,6 +250,7 @@ namespace Barotrauma
public bool NeedsAir
{
get { return needsAir; }
set { needsAir = value; }
}
public float Oxygen
@@ -298,6 +301,38 @@ namespace Barotrauma
}
}
public HuskInfection huskInfection;
public float HuskInfectionState
{
get
{
return huskInfection == null ? 0.0f : huskInfection.IncubationTimer;
}
set
{
if (ConfigPath != humanConfigFile) return;
if (value <= 0.0f)
{
if (huskInfection != null && huskInfection.State == HuskInfection.InfectionState.Active) return;
huskInfection = null;
}
else
{
if (huskInfection == null) huskInfection = new HuskInfection(this);
huskInfection.IncubationTimer = MathHelper.Clamp(value, 0.0f, 1.0f);
}
}
}
public bool CanSpeak
{
get
{
return !IsUnconscious && Stun <= 0.0f && (huskInfection == null || huskInfection.CanSpeak);
}
}
public bool DoesBleed
{
get;
@@ -310,7 +345,6 @@ namespace Barotrauma
private set;
}
public float PressureTimer
{
get;
@@ -474,13 +508,16 @@ namespace Barotrauma
Properties = ObjectProperty.GetProperties(this);
if (file == humanConfigFile)
Info = characterInfo;
if (file == humanConfigFile && characterInfo == null)
{
Info = characterInfo == null ? new CharacterInfo(file) : characterInfo;
Info = new CharacterInfo(file);
}
XDocument doc = ToolBox.TryLoadXml(file);
if (doc == null || doc.Root == null) return;
SpeciesName = ToolBox.GetAttributeString(doc.Root, "name", "Unknown");
@@ -696,6 +733,49 @@ namespace Barotrauma
}
}
if (attackCoolDown >0.0f)
{
attackCoolDown -= deltaTime;
}
else if (IsKeyDown(InputType.Attack))
{
var attackLimb = AnimController.Limbs.FirstOrDefault(l => l.attack != null);
if (attackLimb != null)
{
Vector2 attackPos =
attackLimb.SimPosition + Vector2.Normalize(cursorPosition - attackLimb.Position) * ConvertUnits.ToSimUnits(attackLimb.attack.Range);
var body = Submarine.PickBody(
attackLimb.SimPosition,
attackPos,
AnimController.Limbs.Select(l => l.body.FarseerBody).ToList(),
Physics.CollisionCharacter | Physics.CollisionWall);
IDamageable attackTarget = null;
if (body != null)
{
if (body.UserData is IDamageable)
{
attackTarget = (IDamageable)body.UserData;
}
else if (body.UserData is Limb)
{
attackTarget = ((Limb)body.UserData).character;
}
attackPos = Submarine.LastPickedPosition;
}
attackLimb.UpdateAttack(deltaTime, attackPos, attackTarget);
if (attackLimb.AttackTimer > attackLimb.attack.Duration)
{
attackLimb.AttackTimer = 0.0f;
attackCoolDown = 1.0f;
}
}
}
for (int i = 0; i < selectedItems.Length; i++ )
{
if (selectedItems[i] == null) continue;
@@ -784,6 +864,14 @@ namespace Barotrauma
return owner.isDead || owner.IsUnconscious || owner.Stun > 0.0f || owner.LockHands;
}
if (inventory.Owner is Item)
{
var owner = (Item)inventory.Owner;
if (!CanAccessItem(owner))
{
return false;
}
}
return true;
}
@@ -791,10 +879,22 @@ namespace Barotrauma
{
if (item.ParentInventory != null)
{
if (!CanAccessInventory(item.ParentInventory)) return false;
return CanAccessInventory(item.ParentInventory);
}
return true;
float maxDist = item.PickDistance * 1.2f;
if (maxDist <= 0.01f)
{
maxDist = 150.0f;
}
if (Vector2.Distance(WorldPosition, item.WorldPosition) < maxDist ||
item.IsInsideTrigger(WorldPosition))
{
return true;
}
return item.GetComponent<Items.Components.Ladder>() != null;
}
private Item FindClosestItem(Vector2 mouseSimPos, out float distance)
@@ -859,7 +959,7 @@ namespace Barotrauma
foreach (Limb limb in selectedCharacter.AnimController.Limbs)
{
limb.pullJoint.Enabled = false;
if (limb.pullJoint != null) limb.pullJoint.Enabled = false;
}
selectedCharacter = null;
@@ -923,7 +1023,6 @@ namespace Barotrauma
}
}
if (!LockHands)
{
//find the closest item if selectkey has been hit, or if the Character is being
@@ -1014,9 +1113,9 @@ namespace Barotrauma
// new Character(NewCharacterQueue.Dequeue(), Vector2.Zero);
//}
foreach (Character c in CharacterList)
for (int i = 0; i<CharacterList.Count; i++)
{
c.Update(cam, deltaTime);
CharacterList[i].Update(cam, deltaTime);
}
}
@@ -1039,6 +1138,8 @@ namespace Barotrauma
}
}
if (huskInfection != null) huskInfection.Update(deltaTime, this);
if (isDead) return;
if (networkUpdateSent)
@@ -1084,7 +1185,7 @@ namespace Barotrauma
Lights.LightManager.ViewTarget = this;
CharacterHUD.Update(deltaTime, this);
}
if (IsUnconscious)
{
UpdateUnconscious(deltaTime);
@@ -1096,7 +1197,12 @@ namespace Barotrauma
ControlLocalPlayer(deltaTime, cam);
}
if (controlled == this || !(this is AICharacter)) Control(deltaTime, cam);
if (controlled == this ||
!(this is AICharacter) ||
!((AICharacter)this).AIController.Enabled)
{
Control(deltaTime, cam);
}
if (selectedCharacter != null && AnimController.Anim == AnimController.Animation.CPR)
{
@@ -1323,10 +1429,18 @@ namespace Barotrauma
if (GameMain.NetworkMember != null && controlled != this) return;
}
Vector2 centerOfMass = AnimController.GetCenterOfMass();
health = minHealth;
BreakJoints();
Kill(CauseOfDeath.Pressure, isNetworkMessage);
}
public void BreakJoints()
{
Vector2 centerOfMass = AnimController.GetCenterOfMass();
foreach (Limb limb in AnimController.Limbs)
{
limb.AddDamage(limb.SimPosition, DamageType.Blunt, 500.0f, 0.0f, false);
@@ -1334,28 +1448,27 @@ namespace Barotrauma
Vector2 diff = centerOfMass - limb.SimPosition;
if (diff == Vector2.Zero) continue;
limb.body.ApplyLinearImpulse(diff * 10.0f);
// limb.Damage = 100.0f;
// limb.Damage = 100.0f;
}
SoundPlayer.PlayDamageSound(DamageSoundType.Implode, 50.0f, AnimController.RefLimb.body);
for (int i = 0; i < 10; i++)
{
Particle p = GameMain.ParticleManager.CreateParticle("waterblood",
ConvertUnits.ToDisplayUnits(centerOfMass) + Rand.Vector(5.0f),
Rand.Vector(10.0f));
if (p!=null) p.Size *= 2.0f;
if (p != null) p.Size *= 2.0f;
GameMain.ParticleManager.CreateParticle("bubbles",
ConvertUnits.ToDisplayUnits(centerOfMass) + Rand.Vector(5.0f),
new Vector2(Rand.Range(-50f, 50f), Rand.Range(-100f,50f)));
new Vector2(Rand.Range(-50f, 50f), Rand.Range(-100f, 50f)));
}
foreach (var joint in AnimController.limbJoints)
{
joint.LimitEnabled = false;
}
Kill(CauseOfDeath.Pressure, isNetworkMessage);
}
public void Kill(CauseOfDeath causeOfDeath, bool isNetworkMessage = false)

View File

@@ -197,6 +197,7 @@ namespace Barotrauma
if (Character.Controlled != null)
{
Character.Controlled.Kill(Character.Controlled.CauseOfDeath);
Character.Controlled = null;
}
return true;
};
@@ -232,11 +233,12 @@ namespace Barotrauma
healthBar.Draw(spriteBatch);
}
int bloodDropCount = (int)Math.Floor(character.Bleeding);
bloodDropCount = MathHelper.Clamp(bloodDropCount, 0, 5);
for (int i = 1; i < bloodDropCount; i++)
float bloodDropCount = character.Bleeding;
bloodDropCount = MathHelper.Clamp(bloodDropCount, 0.0f, 5.0f);
for (int i = 0; i < Math.Ceiling(bloodDropCount); i++)
{
spriteBatch.Draw(statusIcons.Texture, new Vector2(5.0f + 20 * i, healthBar.Rect.Y - 20.0f), new Rectangle(39, 3, 15, 19), Color.White * 0.8f);
float alpha = MathHelper.Clamp(bloodDropCount-i, 0.2f, 1.0f);
spriteBatch.Draw(statusIcons.Texture, new Vector2(25.0f + 20 * i, healthBar.Rect.Y - 20.0f), new Rectangle(39, 3, 15, 19), Color.White * alpha);
}
float pressureFactor = (character.AnimController.CurrentHull == null) ?

View File

@@ -0,0 +1,186 @@
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace Barotrauma
{
class HuskInfection
{
public enum InfectionState
{
Dormant, Transition, Active
}
const float IncubationDuration = 300.0f;
private InfectionState state;
private float incubationTimer;
public float IncubationTimer
{
get { return incubationTimer; }
set
{
incubationTimer = MathHelper.Clamp(value, 0.0f, 1.0f);
}
}
public InfectionState State
{
get { return state; }
}
public bool CanSpeak
{
get { return IncubationTimer < 0.5f; }
}
public HuskInfection(Character character)
{
character.OnDeath += CharacterDead;
}
public void Update(float deltaTime, Character character)
{
if (IncubationTimer < 0.5f)
{
UpdateDormantState(deltaTime, character);
}
else if (IncubationTimer < 1.0f)
{
UpdateTransitionState(deltaTime, character);
}
else
{
UpdateActiveState(deltaTime, character);
}
}
private void UpdateDormantState(float deltaTime, Character character)
{
float prevTimer = IncubationTimer;
state = InfectionState.Dormant;
IncubationTimer += deltaTime / IncubationDuration;
if (Character.Controlled != character) return;
if (prevTimer % 0.1f > 0.05f && IncubationTimer % 0.1f < 0.05f)
{
GUI.AddMessage(InfoTextManager.GetInfoText("HuskDormant"), Color.Red, 4.0f);
}
}
private void UpdateTransitionState(float deltaTime, Character character)
{
IncubationTimer += deltaTime / IncubationDuration;
if (state == InfectionState.Dormant && Character.Controlled == character)
{
new GUIMessageBox("", InfoTextManager.GetInfoText("HuskCantSpeak"));
}
state = InfectionState.Transition;
}
private void UpdateActiveState(float deltaTime, Character character)
{
if (state != InfectionState.Active)
{
if (Character.Controlled==character) new GUIMessageBox("", InfoTextManager.GetInfoText("HuskActivate"));
ActivateHusk(character);
state = InfectionState.Active;
}
character.AddDamage(CauseOfDeath.Husk, 0.5f*deltaTime, null);
if (character.AnimController.limbJoints[0].LimitEnabled &&
(character.AnimController.CurrentHull == null ||
character.AnimController.CurrentHull.LethalPressure > 50.0f))
{
character.BreakJoints();
character.AnimController.limbJoints.Last().LimitEnabled = true;
}
}
private void ActivateHusk(Character character)
{
character.NeedsAir = false;
AttachHuskAppendage(character);
}
private void AttachHuskAppendage(Character character)
{
XDocument doc = ToolBox.TryLoadXml(Path.Combine("Content", "Characters", "Human", "huskappendage.xml"));
if (doc == null || doc.Root == null) return;
var limbElement = doc.Root.Element("limb");
if (limbElement == null)
{
DebugConsole.ThrowError("Error in huskappendage.xml - limb element not found");
return;
}
var jointElement = doc.Root.Element("joint");
if (jointElement == null)
{
DebugConsole.ThrowError("Error in huskappendage.xml - joint element not found");
return;
}
character.StartStun(0.5f);
if (character.AnimController.Dir < 1.0f)
{
character.AnimController.Flip();
}
var torso = character.AnimController.GetLimb(LimbType.Torso);
torso.body.SetTransform(torso.SimPosition, 0.0f);
var newLimb = new Limb(character, limbElement);
newLimb.body.Submarine = character.Submarine;
newLimb.body.SetTransform(torso.SimPosition, 0.0f);
character.AnimController.AddLimb(newLimb);
character.AnimController.AddJoint(jointElement);
}
private void CharacterDead(Character character, CauseOfDeath causeOfDeath)
{
var husk = Character.Create(
Path.Combine("Content", "Characters", "Human", "humanhusk.xml"),
character.WorldPosition,
character.Info,
false, true);
foreach (Limb limb in husk.AnimController.Limbs)
{
if (limb.type == LimbType.None)
{
limb.body.SetTransform(character.SimPosition, 0.0f);
continue;
}
var matchingLimb = character.AnimController.GetLimb(limb.type);
limb.body.SetTransform(matchingLimb.SimPosition, matchingLimb.Rotation);
}
for (int i = 0; i < character.Inventory.Items.Length; i++)
{
if (character.Inventory.Items[i] == null) continue;
husk.Inventory.TryPutItem(character.Inventory.Items[i], i, false, true);
}
character.Enabled = false;
husk.SpawnedMidRound = true;
}
}
}

View File

@@ -156,6 +156,8 @@ namespace Barotrauma
private float scale;
public float AttackTimer;
//public float Damage
//{
// get { return damage; }
@@ -223,6 +225,8 @@ namespace Barotrauma
refJointIndex = -1;
Vector2 pullJointPos = Vector2.Zero;
if (element.Attribute("type") != null)
{
try
@@ -236,25 +240,26 @@ namespace Barotrauma
}
Vector2 jointPos = ToolBox.GetAttributeVector2(element, "pullpos", Vector2.Zero) * scale;
jointPos = ConvertUnits.ToSimUnits(jointPos);
pullJointPos = ToolBox.GetAttributeVector2(element, "pullpos", Vector2.Zero) * scale;
pullJointPos = ConvertUnits.ToSimUnits(pullJointPos);
stepOffset = ToolBox.GetAttributeVector2(element, "stepoffset", Vector2.Zero) * scale;
stepOffset = ConvertUnits.ToSimUnits(stepOffset);
refJointIndex = ToolBox.GetAttributeInt(element, "refjoint", -1);
pullJoint = new FixedMouseJoint(body.FarseerBody, jointPos);
pullJoint.Enabled = false;
pullJoint.MaxForce = ((type == LimbType.LeftHand || type == LimbType.RightHand) ? 400.0f : 150.0f) * body.Mass;
GameMain.World.AddJoint(pullJoint);
}
else
{
type = LimbType.None;
}
pullJoint = new FixedMouseJoint(body.FarseerBody, pullJointPos);
pullJoint.Enabled = false;
pullJoint.MaxForce = ((type == LimbType.LeftHand || type == LimbType.RightHand) ? 400.0f : 150.0f) * body.Mass;
GameMain.World.AddJoint(pullJoint);
steerForce = ToolBox.GetAttributeFloat(element, "steerforce", 0.0f);
//maxHealth = Math.Max(ToolBox.GetAttributeFloat(element, "health", 100.0f),1.0f);
@@ -484,6 +489,36 @@ namespace Barotrauma
//}
}
public void ActivateDamagedSprite()
{
damage = 100.0f;
}
public void UpdateAttack(float deltaTime, Vector2 attackPosition, IDamageable damageTarget)
{
float dist = ConvertUnits.ToDisplayUnits(Vector2.Distance(SimPosition, attackPosition));
AttackTimer += deltaTime;
body.ApplyTorque(Mass * character.AnimController.Dir * attack.Torque);
if (dist < attack.Range * 0.5f)
{
if (AttackTimer >= attack.Duration && damageTarget != null)
{
attack.DoDamage(character, damageTarget, WorldPosition, 1.0f, (soundTimer <= 0.0f));
soundTimer = Limb.SoundInterval;
}
}
Vector2 diff = attackPosition - SimPosition;
if (diff.LengthSquared() > 0.00001f)
{
Vector2 pos = pullJoint == null ? body.SimPosition : pullJoint.WorldAnchorA;
body.ApplyLinearImpulse(Mass * attack.Force *
Vector2.Normalize(attackPosition - SimPosition), pos);
}
}
public void Draw(SpriteBatch spriteBatch)
{
@@ -492,7 +527,9 @@ namespace Barotrauma
body.Dir = Dir;
if (wearingItems.Find(w => w != null && w.HideLimb) == null)
bool hideLimb = wearingItems.Any(w => w != null && w.HideLimb);
if (!hideLimb)
{
body.Draw(spriteBatch, sprite, color, null, scale);
}
@@ -526,7 +563,7 @@ namespace Barotrauma
scale, spriteEffect, depth);
}
if (damage>0.0f && damagedSprite!=null)
if (damage>0.0f && damagedSprite!=null && !hideLimb)
{
SpriteEffects spriteEffect = (dir == Direction.Right) ? SpriteEffects.None : SpriteEffects.FlipHorizontally;

View File

@@ -173,20 +173,8 @@ namespace Barotrauma
break;
}
}
//oxygen = ToolBox.GetAttributeFloat(element, "oxygen", 0.0f);
//deteriorateOnActive = ToolBox.GetAttributeFloat(element, "deteriorateonactive", 0.0f);
//deteriorateOnUse = ToolBox.GetAttributeFloat(element, "deteriorateonuse", 0.0f);
}
//public virtual void Apply(ActionType type, float deltaTime, Item item, Character Character = null)
//{
// if (this.type == type) Apply(deltaTime, Character, item);
//}
private bool HasRequiredItems(Entity entity)
{
if (requiredItems == null) return true;

View File

@@ -56,55 +56,49 @@ namespace Barotrauma
{
Coroutines.RemoveAll(c => c == handle);
}
private static bool IsDone(CoroutineHandle handle)
{
try
{
if (handle.Coroutine.Current != null)
{
WaitForSeconds wfs = handle.Coroutine.Current as WaitForSeconds;
if (wfs != null)
{
if (!wfs.CheckFinished(UnscaledDeltaTime)) return false;
}
else
{
switch ((CoroutineStatus)handle.Coroutine.Current)
{
case CoroutineStatus.Success:
return true;
case CoroutineStatus.Failure:
DebugConsole.ThrowError("Coroutine ''" + handle.Name + "'' has failed");
return true;
}
}
}
handle.Coroutine.MoveNext();
return false;
}
catch (Exception e)
{
DebugConsole.ThrowError("Coroutine " + handle.Name + " threw an exception: " + e.Message);
return true;
}
}
// Updating just means stepping through all the coroutines
public static void Update(float unscaledDeltaTime, float deltaTime)
{
UnscaledDeltaTime = unscaledDeltaTime;
DeltaTime = deltaTime;
for (int i = Coroutines.Count-1; i>=0; i--)
{
CoroutineHandle handle = Coroutines[i];
try
{
if (handle.Coroutine.Current != null)
{
WaitForSeconds wfs = handle.Coroutine.Current as WaitForSeconds;
if (wfs != null)
{
if (!wfs.CheckFinished(unscaledDeltaTime)) continue;
}
else
{
switch ((CoroutineStatus)handle.Coroutine.Current)
{
case CoroutineStatus.Success:
Coroutines.RemoveAt(i);
continue;
case CoroutineStatus.Failure:
DebugConsole.ThrowError("Coroutine ''" + handle.Name + "'' has failed");
continue;
}
}
}
handle.Coroutine.MoveNext();
}
catch (Exception e)
{
DebugConsole.ThrowError("Coroutine " + handle.Name + " threw an exception: " + e.Message);
//#if DEBUG
// throw e;
//#endif
Coroutines.Remove(handle);
}
}
foreach (var x in Coroutines.ToList())
if(IsDone(x))
Coroutines.Remove(x);
}
}

View File

@@ -363,8 +363,47 @@ namespace Barotrauma
case "controlcharacter":
case "control":
if (commands.Length < 2) break;
string name = string.Join(" ", commands.Skip(1)).ToLowerInvariant();
Character.Controlled = Character.CharacterList.Find(c => !c.IsNetworkPlayer && c.Name.ToLowerInvariant() == name);
int characterIndex;
string characterName;
if (int.TryParse(commands.Last(), out characterIndex))
{
characterName = string.Join(" ", commands.Skip(1).Take(commands.Length-2)).ToLowerInvariant();
}
else
{
characterName = string.Join(" ", commands.Skip(1)).ToLowerInvariant();
characterIndex = -1;
}
var matchingCharacters = Character.CharacterList.FindAll(c => !c.IsNetworkPlayer && c.Name.ToLowerInvariant() == characterName);
if (!matchingCharacters.Any())
{
ThrowError("Matching characters not found");
return;
}
if (characterIndex==-1)
{
Character.Controlled = matchingCharacters.First();
if (matchingCharacters.Count > 1)
{
NewMessage(
"Found multiple matching characters. "+
"Use \"control [charactername] [0-"+(matchingCharacters.Count-1)+"]\" to choose which character to control.",
Color.LightGray);
}
}
else if (characterIndex<0 || characterIndex>= matchingCharacters.Count)
{
ThrowError("Character index out of range. Select an index between 0 and " + (matchingCharacters.Count - 1));
}
else
{
Character.Controlled = matchingCharacters[characterIndex];
}
break;
case "godmode":
if (Submarine.MainSub == null) return;

View File

@@ -31,7 +31,8 @@ namespace Barotrauma
protected override void Start()
{
Vector2 position = Level.Loaded.GetRandomItemPos(Level.PositionType.Cave, 30.0f);
Vector2 position = Level.Loaded.GetRandomItemPos(
Level.PositionType.Cave | Level.PositionType.MainPath | Level.PositionType.Ruin, 500.0f, 30.0f);
item = new Item(itemPrefab, position, null);
item.MoveWithLevel = true;

View File

@@ -49,7 +49,7 @@ namespace Barotrauma
public override void Start(Level level)
{
Vector2 position = Level.Loaded.GetRandomItemPos(spawnPositionType, 30.0f);
Vector2 position = Level.Loaded.GetRandomItemPos(spawnPositionType, 100.0f, 30.0f);
item = new Item(itemPrefab, position, null);
item.MoveWithLevel = true;

View File

@@ -157,7 +157,7 @@ namespace Barotrauma
SetTextPos();
if (rect.Height == 0 && !string.IsNullOrWhiteSpace(Text))
if (rect.Height == 0 && !string.IsNullOrEmpty(Text))
{
this.rect.Height = (int)Font.MeasureString(wrappedText).Y;
}

View File

@@ -7,7 +7,7 @@ namespace Barotrauma
{
class GameSession
{
public enum InfoFrameTab { Crew, Mission };
public enum InfoFrameTab { Crew, Mission, ManagePlayers };
public readonly TaskManager TaskManager;
@@ -244,6 +244,13 @@ namespace Barotrauma
missionButton.UserData = InfoFrameTab.Mission;
missionButton.OnClicked = SelectInfoFrameTab;
if (GameMain.Server != null)
{
var manageButton = new GUIButton(new Rectangle(200, -30, 130, 20), "Manage players", GUI.Style, infoFrame);
manageButton.UserData = InfoFrameTab.ManagePlayers;
manageButton.OnClicked = SelectInfoFrameTab;
}
var closeButton = new GUIButton(new Rectangle(0, 0, 80, 20), "Close", Alignment.BottomCenter, GUI.Style, infoFrame);
closeButton.OnClicked = ToggleInfoFrame;
@@ -262,6 +269,9 @@ namespace Barotrauma
break;
case InfoFrameTab.Mission:
CreateMissionInfo(infoFrame);
break;
case InfoFrameTab.ManagePlayers:
GameMain.Server.ManagePlayersFrame(infoFrame);
break;
}
@@ -283,7 +293,7 @@ namespace Barotrauma
}
public void Update(float deltaTime)
{
TaskManager.Update(deltaTime);

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Linq;
@@ -51,6 +52,11 @@ namespace Barotrauma
string text = infoList[Rand.Int(infoList.Count)];
foreach (InputType inputType in Enum.GetValues(typeof(InputType)))
{
text = text.Replace("[" + inputType.ToString() + "]", GameMain.Config.KeyBind(inputType).ToString());
}
if (Submarine.MainSub != null) text = text.Replace("[sub]", Submarine.MainSub.Name);
if (GameMain.GameSession != null && GameMain.GameSession.Map != null)
{

View File

@@ -203,6 +203,16 @@ namespace Barotrauma
}
}
foreach (InputType inputType in Enum.GetValues(typeof(InputType)))
{
if (keyMapping[(int)inputType]==null)
{
DebugConsole.ThrowError("Key binding for the input type ''" + inputType + " not set!");
keyMapping[(int)inputType] = new KeyOrMouse(Keys.D1);
}
}
UnsavedSettings = false;
}
@@ -383,6 +393,7 @@ namespace Barotrauma
{
new GUITextBlock(new Rectangle(x, y, 100, 20), inputNames[i]+": ", GUI.Style, settingsFrame);
var keyBox = new GUITextBox(new Rectangle(x + 100, y, 120, 15), GUI.Style, settingsFrame);
keyBox.Text = keyMapping[i].ToString();
keyBox.UserData = i;
keyBox.OnSelected += KeyBoxSelected;

View File

@@ -1,18 +1,18 @@
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using Barotrauma.Items.Components;
using Barotrauma.Networking;
using FarseerPhysics;
using FarseerPhysics.Dynamics;
using FarseerPhysics.Dynamics.Contacts;
using Lidgren.Network;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Barotrauma.Networking;
using System;
using Barotrauma.Items.Components;
using System.ComponentModel;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using FarseerPhysics.Dynamics;
using FarseerPhysics.Dynamics.Contacts;
using System.ComponentModel;
using System.Linq;
using System.Xml.Linq;
namespace Barotrauma
{
@@ -648,7 +648,7 @@ namespace Barotrauma
public AttackResult AddDamage(IDamageable attacker, Vector2 worldPosition, Attack attack, float deltaTime, bool playSound = true)
{
float damageAmount = attack.GetDamage(deltaTime);
float damageAmount = attack.GetStructureDamage(deltaTime);
Condition -= damageAmount;
return new AttackResult(damageAmount, 0.0f, false);

View File

@@ -203,11 +203,6 @@ namespace Barotrauma
pathNodes.Add(new Vector2(x, Rand.Range(pathBorders.Y, pathBorders.Bottom, false)));
}
for (int i = 2; i < pathNodes.Count; i+=3 )
{
positionsOfInterest.Add(new InterestingPosition(pathNodes[i], PositionType.MainPath));
}
pathNodes.Add(endPosition);
pathNodes.Add(new Vector2(endPosition.X, borders.Height));
@@ -277,6 +272,12 @@ namespace Barotrauma
List<VoronoiCell> mainPath = CaveGenerator.GeneratePath(pathNodes, cells, cellGrid, GridCellSize,
new Rectangle(pathBorders.X, pathBorders.Y, pathBorders.Width, borders.Height), 0.3f, mirror);
for (int i = 2; i < mainPath.Count; i += 3)
{
positionsOfInterest.Add(new InterestingPosition(mainPath[i].Center, PositionType.MainPath));
}
List<VoronoiCell> pathCells = new List<VoronoiCell>(mainPath);
EnlargeMainPath(pathCells, minWidth);
@@ -734,7 +735,7 @@ namespace Barotrauma
return newCells;
}
public Vector2 GetRandomItemPos(PositionType spawnPosType, float offsetFromWall = 10.0f)
public Vector2 GetRandomItemPos(PositionType spawnPosType, float randomSpread, float offsetFromWall = 10.0f)
{
if (!positionsOfInterest.Any()) return Size*0.5f;
@@ -746,6 +747,8 @@ namespace Barotrauma
do
{
Vector2 startPos = Level.Loaded.GetRandomInterestingPosition(true, spawnPosType);
startPos += Rand.Vector(Rand.Range(0.0f, randomSpread, false), false);
Vector2 endPos = startPos - Vector2.UnitY * Size.Y;

View File

@@ -104,6 +104,19 @@ namespace Barotrauma
{
get { return prefab.MaxHealth; }
}
public override Rectangle Rect
{
get
{
return base.Rect;
}
set
{
base.Rect = value;
if (prefab.HasBody) CreateSections();
}
}
public override void Move(Vector2 amount)
{
@@ -130,15 +143,6 @@ namespace Barotrauma
{
convexHulls.ForEach(x => x.Move(amount));
}
//if (gaps != null)
//{
// foreach (Gap g in gaps)
// {
// g.Move(amount);
// //g.position.X += amount.X;
// //g.position.Y -= amount.Y;
// }
//}
}
public Structure(Rectangle rectangle, StructurePrefab sp, Submarine submarine)
@@ -173,37 +177,8 @@ namespace Barotrauma
bodies.Add(newBody);
WallList.Add(this);
int xsections = 1;
int ysections = 1;
int width, height;
if (isHorizontal)
{
xsections = (int)Math.Ceiling((float)rect.Width / wallSectionSize);
sections = new WallSection[xsections];
width = (int)wallSectionSize;
height = rect.Height;
}
else
{
ysections = (int)Math.Ceiling((float)rect.Height / wallSectionSize);
sections = new WallSection[ysections];
width = rect.Width;
height = (int)wallSectionSize;
}
for (int x = 0; x < xsections; x++ )
{
for (int y = 0; y < ysections; y++)
{
Rectangle sectionRect = new Rectangle(rect.X + x * width, rect.Y - y * height, width, height);
sectionRect.Width -= (int)Math.Max((sectionRect.X + sectionRect.Width) - (rect.X + rect.Width), 0.0f);
sectionRect.Height -= (int)Math.Max((rect.Y - rect.Height)-(sectionRect.Y - sectionRect.Height), 0.0f);
sections[x+y] = new WallSection(sectionRect);
}
}
CreateSections();
}
else
{
@@ -245,6 +220,39 @@ namespace Barotrauma
InsertToList();
}
private void CreateSections()
{
int xsections = 1, ysections = 1;
int width, height;
if (isHorizontal)
{
xsections = (int)Math.Ceiling((float)rect.Width / wallSectionSize);
sections = new WallSection[xsections];
width = (int)wallSectionSize;
height = rect.Height;
}
else
{
ysections = (int)Math.Ceiling((float)rect.Height / wallSectionSize);
sections = new WallSection[ysections];
width = rect.Width;
height = (int)wallSectionSize;
}
for (int x = 0; x < xsections; x++)
{
for (int y = 0; y < ysections; y++)
{
Rectangle sectionRect = new Rectangle(rect.X + x * width, rect.Y - y * height, width, height);
sectionRect.Width -= (int)Math.Max((sectionRect.X + sectionRect.Width) - (rect.X + rect.Width), 0.0f);
sectionRect.Height -= (int)Math.Max((rect.Y - rect.Height) - (sectionRect.Y - sectionRect.Height), 0.0f);
sections[x + y] = new WallSection(sectionRect);
}
}
}
private void GenerateConvexHull()
{
// If not null and not empty , remove the hulls from the system
@@ -374,11 +382,14 @@ namespace Barotrauma
}
Vector2 drawOffset = Submarine == null ? Vector2.Zero : Submarine.DrawPosition;
prefab.sprite.DrawTiled(spriteBatch, new Vector2(rect.X + drawOffset.X, -(rect.Y + drawOffset.Y)), new Vector2(rect.Width, rect.Height), Vector2.Zero, color);
if(sections.Length == 1)
prefab.sprite.DrawTiled(spriteBatch, new Vector2(rect.X + drawOffset.X, -(rect.Y + drawOffset.Y)), new Vector2(rect.Width, rect.Height), Vector2.Zero, color,Point.Zero);
foreach (WallSection s in sections)
{
Point offset = new Point(Math.Abs(rect.Location.X - s.rect.Location.X), Math.Abs(rect.Location.Y - s.rect.Location.Y));
if (sections.Length != 1 && s.damage < prefab.MaxHealth)
prefab.sprite.DrawTiled(spriteBatch, new Vector2(s.rect.X + drawOffset.X, -(s.rect.Y + drawOffset.Y)), new Vector2(s.rect.Width, s.rect.Height), Vector2.Zero, color, offset);
if (s.isHighLighted)
{
@@ -390,10 +401,10 @@ namespace Barotrauma
s.isHighLighted = false;
if (s.damage < 0.01f) continue;
GUI.DrawRectangle(spriteBatch,
GUI.DrawRectangle(spriteBatch,
new Vector2(s.rect.X + drawOffset.X, -(s.rect.Y + drawOffset.Y)), new Vector2(s.rect.Width, s.rect.Height),
Color.Black * (s.damage / prefab.MaxHealth), true);
Color.Black * (s.damage / prefab.MaxHealth), true);
}
/*
if(_convexHulls == null) return;
@@ -592,8 +603,8 @@ namespace Barotrauma
}
}
if (sections[sectionIndex].gap != null)
sections[sectionIndex].gap.Open = (float)Math.Pow(((damage / prefab.MaxHealth)-0.5)*2.0, 2.0);
if (sections[sectionIndex].gap != null)
sections[sectionIndex].gap.Open = (damage/prefab.MaxHealth - 0.5f)*2;
bool hadHole = SectionBodyDisabled(sectionIndex);
sections[sectionIndex].damage = MathHelper.Clamp(damage, 0.0f, prefab.MaxHealth);

View File

@@ -115,21 +115,46 @@ namespace Barotrauma.Networking
public void WriteNetworkMessage(NetOutgoingMessage msg)
{
msg.WriteRangedInteger(0, Enum.GetValues(typeof(ChatMessageType)).Length, (byte)Type);
msg.Write(Sender == null ? (ushort)0 : Sender.ID);
msg.Write(SenderName);
msg.WriteRangedInteger(0, Enum.GetValues(typeof(ChatMessageType)).Length, (byte)Type);
if (GameMain.Server != null)
{
msg.Write(Sender == null ? (ushort)0 : Sender.ID);
msg.Write(SenderName);
}
msg.Write(Text);
}
public static ChatMessage ReadNetworkMessage(NetBuffer msg)
{
ChatMessageType type = (ChatMessageType)msg.ReadRangedInteger(0, Enum.GetValues(typeof(ChatMessageType)).Length);
ushort senderId = msg.ReadUInt16();
string senderName = msg.ReadString();
ChatMessageType type = (ChatMessageType)msg.ReadRangedInteger(0, Enum.GetValues(typeof(ChatMessageType)).Length);
string senderName="";
Character character = null;
if (GameMain.Server == null)
{
ushort senderId = msg.ReadUInt16();
character = Entity.FindEntityByID(senderId) as Character;
senderName = msg.ReadString();
}
else
{
NetIncomingMessage inc = msg as NetIncomingMessage;
if (inc == null) return null;
Client sender = GameMain.Server.ConnectedClients.Find(x => x.Connection == inc.SenderConnection);
if (sender == null) return null;
character = sender.Character;
if (character != null)
{
senderName = character.Name;
}
else
{
senderName = sender.name;
}
}
string text = msg.ReadString();
return new ChatMessage(senderName, text, type, Entity.FindEntityByID(senderId) as Character);
return new ChatMessage(senderName, text, type, character);
}
}
}

View File

@@ -29,6 +29,11 @@ namespace Barotrauma.Networking
public string version;
public bool inGame;
public List<string> ChatMessages = new List<string>();
public float ChatSpamSpeed;
public float ChatSpamTimer;
public int ChatSpamCount;
private List<Client> kickVoters;
public bool ReadyToStart;
@@ -84,8 +89,21 @@ namespace Barotrauma.Networking
{
name = name.Substring(0, 20);
}
string rName = "";
for (int i=0;i<name.Length;i++)
{
if (name[i] < 32 || name[i] > 126)
{
//TODO: allow safe unicode characters, this is just to prevent players from taking names that look similar but aren't the same
rName += '?';
}
else
{
rName += name[i];
}
}
return name;
return rName;
}
public void SetPermissions(ClientPermissions permissions)
@@ -105,7 +123,7 @@ namespace Barotrauma.Networking
public bool HasPermission(ClientPermissions permission)
{
return Permissions.HasFlag(permission);
return false; //Permissions.HasFlag(permission);
}
public T GetVote<T>(VoteType voteType)

View File

@@ -5,6 +5,7 @@ using System.Collections.Generic;
using FarseerPhysics;
using System.IO;
using System.Linq;
using System.Text;
using Barotrauma.Items.Components;
using System.ComponentModel;
@@ -165,7 +166,12 @@ namespace Barotrauma.Networking
reconnectBox.Buttons[0].OnClicked += reconnectBox.Close;
}
CoroutineManager.StartCoroutine(WaitForStartingInfo(password));
String sendPw = "";
if (password.Length>0)
{
sendPw = Encoding.UTF8.GetString(NetUtility.ComputeSHAHash(Encoding.UTF8.GetBytes(password)));
}
CoroutineManager.StartCoroutine(WaitForStartingInfo(sendPw));
// Start the timer
//update.Start();
@@ -408,43 +414,7 @@ namespace Barotrauma.Networking
byte characterCount = inc.ReadByte();
for (int i = 0; i < characterCount; i++)
{
bool isAiCharacter = inc.ReadBoolean();
ushort id = inc.ReadUInt16();
if (isAiCharacter)
{
string configPath = inc.ReadString();
Vector2 position = new Vector2(inc.ReadFloat(), inc.ReadFloat());
var existingEntity = Entity.FindEntityByID(id);
if (existingEntity is AICharacter && existingEntity.ID == id)
{
continue;
}
var character = Character.Create(configPath, position, null, true);
if (character != null) character.ID = id;
}
else
{
bool hasOwner = inc.ReadBoolean();
int ownerId = -1;
if (hasOwner)
{
ownerId = inc.ReadByte();
}
Character newCharacter = ReadCharacterData(inc, ownerId == myID);
if (ownerId != myID)
{
var characterOwner = otherClients.Find(c => c.ID == ownerId);
if (characterOwner != null) characterOwner.Character = newCharacter;
}
crew.Add(newCharacter);
}
ReadCharacterData(inc);
}
gameStarted = true;
@@ -509,7 +479,7 @@ namespace Barotrauma.Networking
public bool HasPermission(ClientPermissions permission)
{
return permissions.HasFlag(permission);
return false;// permissions.HasFlag(permission);
}
public override void Draw(Microsoft.Xna.Framework.Graphics.SpriteBatch spriteBatch)
@@ -547,15 +517,23 @@ namespace Barotrauma.Networking
GUI.DrawRectangle(spriteBatch, new Rectangle(x, y, width, height), Color.Black * 0.7f, true);
spriteBatch.DrawString(GUI.Font, "Network statistics:", new Vector2(x + 10, y + 10), Color.White);
spriteBatch.DrawString(GUI.Font, "Ping: " + (int)(client.ServerConnection.AverageRoundtripTime * 1000.0f) + " ms", new Vector2(x + 10, y + 25), Color.White);
if (client.ServerConnection != null)
{
spriteBatch.DrawString(GUI.Font, "Ping: " + (int)(client.ServerConnection.AverageRoundtripTime * 1000.0f) + " ms", new Vector2(x + 10, y + 25), Color.White);
y += 15;
y += 15;
spriteBatch.DrawString(GUI.SmallFont, "Received bytes: " + client.Statistics.ReceivedBytes, new Vector2(x + 10, y + 45), Color.White);
spriteBatch.DrawString(GUI.SmallFont, "Received packets: " + client.Statistics.ReceivedPackets, new Vector2(x + 10, y + 60), Color.White);
spriteBatch.DrawString(GUI.SmallFont, "Received bytes: " + client.Statistics.ReceivedBytes, new Vector2(x + 10, y + 45), Color.White);
spriteBatch.DrawString(GUI.SmallFont, "Received packets: " + client.Statistics.ReceivedPackets, new Vector2(x + 10, y + 60), Color.White);
spriteBatch.DrawString(GUI.SmallFont, "Sent bytes: " + client.Statistics.SentBytes, new Vector2(x + 10, y + 75), Color.White);
spriteBatch.DrawString(GUI.SmallFont, "Sent packets: " + client.Statistics.SentPackets, new Vector2(x + 10, y + 90), Color.White);
}
else
{
spriteBatch.DrawString(GUI.Font, "Disconnected", new Vector2(x + 10, y + 25), Color.White);
}
spriteBatch.DrawString(GUI.SmallFont, "Sent bytes: " + client.Statistics.SentBytes, new Vector2(x + 10, y + 75), Color.White);
spriteBatch.DrawString(GUI.SmallFont, "Sent packets: " + client.Statistics.SentPackets, new Vector2(x + 10, y + 90), Color.White);
}
@@ -609,25 +587,6 @@ namespace Barotrauma.Networking
return true;
}
public void ReadCharacterSpawnMessage(NetIncomingMessage message)
{
string configPath = message.ReadString();
if (configPath != Character.HumanConfigFile)
{
ushort id = message.ReadUInt16();
Vector2 position = new Vector2(message.ReadFloat(), message.ReadFloat());
var character = Character.Create(configPath, position, null, true);
if (character != null) character.ID = id;
}
else
{
ReadCharacterData(message, false, true);
}
}
public void RequestFile(string file, FileTransferMessageType fileType)
{
if (fileStreamReceiver!=null)
@@ -812,35 +771,77 @@ namespace Barotrauma.Networking
client.SendMessage(msg, NetDeliveryMethod.ReliableUnordered);
}
public Character ReadCharacterData(NetIncomingMessage inc, bool isMyCharacter, bool hasAi = false)
public Character ReadCharacterData(NetIncomingMessage inc)
{
string newName = inc.ReadString();
ushort ID = inc.ReadUInt16();
bool isFemale = inc.ReadBoolean();
bool noInfo = inc.ReadBoolean();
ushort id = inc.ReadUInt16();
string configPath = inc.ReadString();
int headSpriteID = inc.ReadByte();
Vector2 position = new Vector2(inc.ReadFloat(), inc.ReadFloat());
bool enabled = inc.ReadBoolean();
string jobName = inc.ReadString();
JobPrefab jobPrefab = JobPrefab.List.Find(jp => jp.Name == jobName);
Character character = null;
CharacterInfo ch = new CharacterInfo(Character.HumanConfigFile, newName, isFemale ? Gender.Female : Gender.Male, jobPrefab);
ch.HeadSpriteId = headSpriteID;
Character character = Character.Create(ch, position, !isMyCharacter, hasAi);
GameMain.GameSession.CrewManager.characters.Add(character);
character.ID = ID;
if (isMyCharacter)
if (noInfo)
{
myCharacter = character;
Character.Controlled = character;
GameMain.LightManager.LosEnabled = true;
var existingEntity = Entity.FindEntityByID(id);
if (existingEntity is AICharacter && existingEntity.ID == id)
{
return (Character)existingEntity;
}
if (endVoteTickBox != null) endVoteTickBox.Visible = Voting.AllowEndVoting;
character = Character.Create(configPath, position, null, true);
character.ID = id;
}
else
{
bool hasOwner = inc.ReadBoolean();
int ownerId = -1;
if (hasOwner)
{
ownerId = inc.ReadByte();
}
string newName = inc.ReadString();
bool hasAi = inc.ReadBoolean();
bool isFemale = inc.ReadBoolean();
int headSpriteID = inc.ReadByte();
string jobName = inc.ReadString();
JobPrefab jobPrefab = JobPrefab.List.Find(jp => jp.Name == jobName);
CharacterInfo ch = new CharacterInfo(configPath, newName, isFemale ? Gender.Female : Gender.Male, jobPrefab);
ch.HeadSpriteId = headSpriteID;
character = Character.Create(configPath, position, ch, ownerId != myID, hasAi);
character.ID = id;
if (configPath == Character.HumanConfigFile)
{
GameMain.GameSession.CrewManager.characters.Add(character);
}
Item.Spawner.ReadNetworkData(inc);
if (ownerId == myID)
{
myCharacter = character;
Character.Controlled = character;
GameMain.LightManager.LosEnabled = true;
if (endVoteTickBox != null) endVoteTickBox.Visible = Voting.AllowEndVoting;
}
else
{
var characterOwner = otherClients.Find(c => c.ID == ownerId);
if (characterOwner != null) characterOwner.Character = character;
}
}
character.Enabled = enabled;
return character;
}

View File

@@ -3,6 +3,7 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using Lidgren.Network;
using Microsoft.Xna.Framework;
using RestSharp;
@@ -54,7 +55,11 @@ namespace Barotrauma.Networking
name = name.Replace(";", "");
this.name = name;
this.password = password;
this.password = "";
if (password.Length>0)
{
this.password = Encoding.UTF8.GetString(NetUtility.ComputeSHAHash(Encoding.UTF8.GetBytes(password)));
}
config = new NetPeerConfiguration("barotrauma");
@@ -104,6 +109,10 @@ namespace Barotrauma.Networking
return true;
};
GUIButton settingsButton = new GUIButton(new Rectangle(GameMain.GraphicsWidth - 170 - 170 - 170, 20, 150, 20), "Settings", Alignment.TopLeft, GUI.Style, inGameHUD);
settingsButton.OnClicked = ToggleSettingsFrame;
settingsButton.UserData = "settingsButton";
banList = new BanList();
LoadSettings();
@@ -342,7 +351,13 @@ namespace Barotrauma.Networking
foreach (Client c in connectedClients)
{
if (c.FileStreamSender != null) UpdateFileTransfer(c, deltaTime);
if (c.FileStreamSender != null) UpdateFileTransfer(c, deltaTime);
c.ReliableChannel.Update(deltaTime);
//slowly reset spam timers
c.ChatSpamTimer = Math.Max(0.0f, c.ChatSpamTimer - deltaTime);
c.ChatSpamSpeed = Math.Max(0.0f, c.ChatSpamSpeed - deltaTime);
}
NetIncomingMessage inc = null;
@@ -974,35 +989,7 @@ namespace Barotrauma.Networking
msg.Write((byte)characters.Count);
foreach (Character c in characters)
{
msg.Write(c is AICharacter);
msg.Write(c.ID);
if (c is AICharacter)
{
msg.Write(c.ConfigPath);
msg.Write(c.Position.X);
msg.Write(c.Position.Y);
}
else
{
Client client = connectedClients.Find(cl => cl.Character == c);
if (client != null)
{
msg.Write(true);
msg.Write(client.ID);
}
else if (myCharacter == c)
{
msg.Write(true);
msg.Write((byte)0);
}
else
{
msg.Write(false);
}
WriteCharacterData(msg, c.Name, c);
}
WriteCharacterData(msg, c.Name, c);
}
return msg;
@@ -1435,12 +1422,15 @@ namespace Barotrauma.Networking
private void ReadChatMessage(NetIncomingMessage inc)
{
Client sender = connectedClients.Find(x => x.Connection == inc.SenderConnection);
ChatMessage message = ChatMessage.ReadNetworkMessage(inc);
if (message == null) return;
List<Client> recipients = new List<Client>();
foreach (Client c in connectedClients)
{
if (!sender.inGame && c.inGame) continue; //people in lobby can't talk to people ingame
switch (message.Type)
{
case ChatMessageType.Dead:
@@ -1462,7 +1452,71 @@ namespace Barotrauma.Networking
recipients.Add(c);
}
AddChatMessage(message);
//SPAM FILTER
if (sender.ChatSpamTimer > 0.0f)
{
//player has already been spamming, stop again
ChatMessage denyMsg = ChatMessage.Create("", "You have been blocked by the spam filter. Try again after 10 seconds.", ChatMessageType.Server, null);
sender.ChatSpamTimer = 10.0f;
SendChatMessage(denyMsg, sender);
return;
}
float similarity = 0;
similarity += sender.ChatSpamSpeed * 0.05f; //the faster messages are being sent, the faster the filter will block
for (int i = 0; i < sender.ChatMessages.Count; i++)
{
float closeFactor = 1.0f / (20.0f - i);
int levenshteinDist = ToolBox.LevenshteinDistance(message.Text, sender.ChatMessages[i]);
similarity += Math.Max((message.Text.Length - levenshteinDist) / message.Text.Length * closeFactor, 0.0f);
}
if (similarity > 5.0f)
{
sender.ChatSpamCount++;
if (sender.ChatSpamCount > 3)
{
//kick for spamming too much
KickClient(sender, false);
}
else
{
ChatMessage denyMsg = ChatMessage.Create("", "You have been blocked by the spam filter. Try again after 10 seconds.", ChatMessageType.Server, null);
sender.ChatSpamTimer = 10.0f;
SendChatMessage(denyMsg, sender);
}
return;
}
sender.ChatMessages.Add(message.Text);
if (sender.ChatMessages.Count > 20)
{
sender.ChatMessages.RemoveAt(0);
}
if (sender.inGame || (Screen.Selected == GameMain.NetLobbyScreen))
{
AddChatMessage(message);
}
else
{
GameServer.Log(message.TextWithSender, message.Color);
}
sender.ChatSpamSpeed += 5.0f;
foreach (Client c in recipients)
{
ReliableMessage msg = c.ReliableChannel.CreateMessage();
msg.InnerMessage.Write((byte)PacketTypes.Chatmessage);
message.WriteNetworkMessage(msg.InnerMessage);
c.ReliableChannel.SendMessage(msg, c.Connection);
}
}
public override void SendChatMessage(string message, ChatMessageType? type = null)
@@ -1521,6 +1575,16 @@ namespace Barotrauma.Networking
SendChatMessage(chatMessage, recipients);
}
public void SendChatMessage(ChatMessage chatMessage, Client recipient)
{
ReliableMessage msg = recipient.ReliableChannel.CreateMessage();
msg.InnerMessage.Write((byte)PacketTypes.Chatmessage);
chatMessage.WriteNetworkMessage(msg.InnerMessage);
recipient.ReliableChannel.SendMessage(msg, recipient.Connection);
}
public void SendChatMessage(ChatMessage chatMessage, List<Client> recipients)
{
@@ -1528,6 +1592,9 @@ namespace Barotrauma.Networking
private void ReadCharacterData(NetIncomingMessage message)
{
Client sender = connectedClients.Find(c => c.Connection == message.SenderConnection);
if (sender == null) return;
string name = "";
Gender gender = Gender.Male;
int headSpriteId = 0;
@@ -1545,6 +1612,11 @@ namespace Barotrauma.Networking
headSpriteId = 0;
}
if (sender.characterInfo != null)
{
//clients can't change their character's name once it's been set
name = sender.characterInfo.Name;
}
List<JobPrefab> jobPreferences = new List<JobPrefab>();
int count = message.ReadByte();
@@ -1555,51 +1627,60 @@ namespace Barotrauma.Networking
if (jobPrefab != null) jobPreferences.Add(jobPrefab);
}
foreach (Client c in connectedClients)
{
if (c.Connection != message.SenderConnection) continue;
c.characterInfo = new CharacterInfo(Character.HumanConfigFile, name, gender);
c.characterInfo.HeadSpriteId = headSpriteId;
c.jobPreferences = jobPreferences;
break;
}
sender.characterInfo = new CharacterInfo(Character.HumanConfigFile, name, gender);
sender.characterInfo.HeadSpriteId = headSpriteId;
sender.jobPreferences = jobPreferences;
}
public void WriteCharacterData(NetOutgoingMessage message, string name, Character character)
public void WriteCharacterData(NetOutgoingMessage msg, string name, Character c)
{
message.Write(name);
message.Write(character.ID);
message.Write(character.Info.Gender == Gender.Female);
msg.Write(c.Info == null);
msg.Write(c.ID);
msg.Write(c.ConfigPath);
message.Write((byte)character.Info.HeadSpriteId);
msg.Write(c.WorldPosition.X);
msg.Write(c.WorldPosition.Y);
message.Write(character.WorldPosition.X);
message.Write(character.WorldPosition.Y);
message.Write(character.Info.Job.Name);
msg.Write(c.Enabled);
if (c.Info != null)
{
Client client = connectedClients.Find(cl => cl.Character == c);
if (client != null)
{
msg.Write(true);
msg.Write(client.ID);
}
else if (myCharacter == c)
{
msg.Write(true);
msg.Write((byte)0);
}
else
{
msg.Write(false);
}
msg.Write(name);
msg.Write(c is AICharacter);
msg.Write(c.Info.Gender == Gender.Female);
msg.Write((byte)c.Info.HeadSpriteId);
msg.Write(c.Info.Job == null ? "" : c.Info.Job.Name);
Item.Spawner.FillNetworkData(msg, c.SpawnItems);
}
}
public void SendCharacterSpawnMessage(Character character, List<NetConnection> recipients = null)
{
if (recipients != null && !recipients.Any()) return;
NetOutgoingMessage message = server.CreateMessage();
message.Write((byte)PacketTypes.NewCharacter);
message.Write(character.ConfigPath);
if (character.ConfigPath == Character.HumanConfigFile)
{
WriteCharacterData(message, character.Name, character);
}
else
{
message.Write(character.ID);
message.Write(character.Position.X);
message.Write(character.Position.Y);
}
WriteCharacterData(message, character.Name, character);
SendMessage(message, NetDeliveryMethod.ReliableUnordered, recipients);
}

View File

@@ -61,11 +61,14 @@ namespace Barotrauma.Networking
{
unauthenticatedClients.Remove(unauthenticatedClient);
NetEncryption algo = new NetXtea(server, password);
string saltedPw = password;
saltedPw = saltedPw + Convert.ToString(unauthenticatedClient.Nonce);
saltedPw = Encoding.UTF8.GetString(NetUtility.ComputeSHAHash(Encoding.UTF8.GetBytes(saltedPw)));
NetEncryption algo = new NetXtea(server, saltedPw);
inc.Decrypt(algo);
int nonce = inc.ReadInt32();
if (nonce != unauthenticatedClient.Nonce)
string rdPw = inc.ReadString();
if (rdPw != saltedPw)
{
inc.SenderConnection.Disconnect("Wrong password!");
return;
@@ -74,6 +77,13 @@ namespace Barotrauma.Networking
else
{
inc.SenderConnection.Disconnect("Authentication failed");
return;
}
if (ConnectedClients.Count>=config.MaximumConnections)
{
inc.SenderConnection.Disconnect("Server full");
return;
}
DebugConsole.NewMessage("New player has joined the server", Color.White);

View File

@@ -646,5 +646,38 @@ namespace Barotrauma.Networking
return false;
}
public void ManagePlayersFrame(GUIFrame infoFrame)
{
GUIListBox cList = new GUIListBox(new Rectangle(0, 0, 0, 300), Color.White * 0.7f, GUI.Style, infoFrame);
cList.Padding = new Vector4(10.0f, 10.0f, 10.0f, 10.0f);
//crewList.OnSelected = SelectCrewCharacter;
foreach (Client c in ConnectedClients)
{
GUIFrame frame = new GUIFrame(new Rectangle(0, 0, 0, 40), Color.Transparent, null, cList);
frame.Padding = new Vector4(5.0f, 5.0f, 5.0f, 5.0f);
frame.Color = (c.inGame && c.Character!=null && !c.Character.IsDead) ? Color.Gold * 0.2f : Color.Transparent;
frame.HoverColor = Color.LightGray * 0.5f;
frame.SelectedColor = Color.Gold * 0.5f;
GUITextBlock textBlock = new GUITextBlock(
new Rectangle(40, 0, 0, 25),
c.name + " (" + c.Connection.RemoteEndPoint.Address.ToString() + ")",
Color.Transparent, Color.White,
Alignment.Left, Alignment.Left,
null, frame);
var banButton = new GUIButton(new Rectangle(-120, 0, 100, 20), "Ban", Alignment.Right | Alignment.CenterY, GUI.Style, frame);
banButton.UserData = c.name;
banButton.OnClicked += GameMain.NetLobbyScreen.BanPlayer;
var kickButton = new GUIButton(new Rectangle(0, 0, 100, 20), "Kick", Alignment.Right | Alignment.CenterY, GUI.Style, frame);
kickButton.UserData = c.name;
kickButton.OnClicked += GameMain.NetLobbyScreen.KickPlayer;
textBlock.Padding = new Vector4(5.0f, 0.0f, 5.0f, 0.0f);
}
}
}
}

View File

@@ -264,6 +264,7 @@ namespace Barotrauma.Networking
public void AddChatMessage(ChatMessage message)
{
if (message.Type == ChatMessageType.Radio &&
Character.Controlled != null &&
message.Sender != null && message.Sender != myCharacter)
@@ -278,6 +279,8 @@ namespace Barotrauma.Networking
return;
}
GameServer.Log(message.TextWithSender, message.Color);
string displayedText = message.Text;
if (message.Sender != null)
@@ -293,8 +296,6 @@ namespace Barotrauma.Networking
GameMain.NetLobbyScreen.NewChatMessage(message);
GameServer.Log(message.Text, message.Color);
while (chatBox.CountChildren > 20)
{
chatBox.RemoveChild(chatBox.children[1]);
@@ -304,11 +305,12 @@ namespace Barotrauma.Networking
{
displayedText = message.SenderName + ": " + displayedText;
}
GUITextBlock msg = new GUITextBlock(new Rectangle(0, 0, 0, 20), displayedText,
((chatBox.CountChildren % 2) == 0) ? Color.Transparent : Color.Black * 0.1f, message.Color,
Alignment.Left, null, null, true);
msg.Font = GUI.SmallFont;
msg.UserData = message.SenderName;
msg.Padding = new Vector4(20.0f, 0, 0, 0);
@@ -340,15 +342,12 @@ namespace Barotrauma.Networking
{
if (gameStarted && Screen.Selected == GameMain.GameScreen)
{
chatMsgBox.Visible = Character.Controlled == null ||
(!Character.Controlled.IsUnconscious && Character.Controlled.Stun <= 0.0f);
chatMsgBox.Visible = Character.Controlled == null || Character.Controlled.CanSpeak;
inGameHUD.Update(deltaTime);
GameMain.GameSession.CrewManager.Update(deltaTime);
//if (crewFrameOpen) crewFrame.Update(deltaTime);
if (Character.Controlled == null || Character.Controlled.IsDead)
{
GameMain.GameScreen.Cam.TargetPos = Vector2.Zero;

View File

@@ -532,7 +532,7 @@ namespace Barotrauma.Networking
{
byte clientId = inc.ReadByte();
var character = client.ReadCharacterData(inc, clientId == client.ID);
var character = client.ReadCharacterData(inc);
}
if (state != newState)

View File

@@ -98,10 +98,10 @@ namespace Barotrauma.Networking
{
float prevSize = listBox.BarSize;
var textBlock = new GUITextBlock(new Rectangle(0, 0, 0, 0), line.Text, GUI.Style, Alignment.TopLeft, Alignment.TopLeft, null, true, GUI.SmallFont);
var textBlock = new GUITextBlock(new Rectangle(0, 0, 0, 0), line.Text, GUI.Style, Alignment.TopLeft, Alignment.TopLeft, listBox, true, GUI.SmallFont);
textBlock.Rect = new Rectangle(textBlock.Rect.X, textBlock.Rect.Y, textBlock.Rect.Width, Math.Max(13, textBlock.Rect.Height));
listBox.AddChild(textBlock);
//listBox.AddChild(textBlock);
textBlock.TextColor = line.Color;
textBlock.CanBeFocused = false;

View File

@@ -10,6 +10,7 @@ namespace Barotrauma
Use,
Aim,
Up, Down, Left, Right,
Attack,
Run, Crouch,
Chat, CrewOrders
}

View File

@@ -989,6 +989,7 @@ namespace Barotrauma
((chatBox.CountChildren % 2) == 0) ? Color.Transparent : Color.Black*0.1f, message.Color,
Alignment.Left, GUI.Style, null, true);
msg.Font = GUI.SmallFont;
msg.UserData = message.SenderName;
msg.CanBeFocused = false;
msg.Padding = new Vector4(20, 0, 0, 0);

View File

@@ -222,7 +222,56 @@ namespace Barotrauma
{
DrawTiled(spriteBatch, pos, targetSize, Vector2.Zero, color);
}
public void DrawTiled(SpriteBatch spriteBatch, Vector2 pos, Vector2 targetSize, Vector2 startOffset, Color color, Point offset)
{
//how many times the texture needs to be drawn on the x-axis
int xTiles = (int)Math.Ceiling((targetSize.X + startOffset.X) / sourceRect.Width);
//how many times the texture needs to be drawn on the y-axis
int yTiles = (int)Math.Ceiling((targetSize.Y + startOffset.Y) / sourceRect.Height);
Rectangle TexPerspective = sourceRect;
TexPerspective.Location += offset;
while (TexPerspective.Location.X >= sourceRect.X + sourceRect.Width)
TexPerspective.X = sourceRect.X + (TexPerspective.Location.X - (sourceRect.X + sourceRect.Width));
while (TexPerspective.Location.Y >= sourceRect.Y + sourceRect.Height)
TexPerspective.Y = sourceRect.Y + (TexPerspective.Location.Y - (sourceRect.Y + sourceRect.Height));
TexPerspective.Width = (int)Math.Min(targetSize.X, sourceRect.Width);
TexPerspective.Height = (int)Math.Min(targetSize.Y, sourceRect.Height);
for (int y = 0; y < yTiles; y++)
{
TexPerspective.Width = (int)Math.Min(targetSize.X, sourceRect.Width);
TexPerspective.Height = (int)Math.Min(targetSize.Y, sourceRect.Height);
float top = pos.Y + TexPerspective.Height * y;
for (int x = 0; x < xTiles; x++)
{
float left = pos.X + TexPerspective.Width * x;
TexPerspective.Width = Math.Min((int)(targetSize.X - TexPerspective.Width * x), TexPerspective.Width);
TexPerspective.Height = Math.Min((int)(targetSize.Y - TexPerspective.Height * y), TexPerspective.Height);
var movementX = TexPerspective.Width;
var movementY = TexPerspective.Height;
if (TexPerspective.X+TexPerspective.Width > sourceRect.X + sourceRect.Width)
{
float diff = (TexPerspective.X + TexPerspective.Width) - (sourceRect.X + sourceRect.Width);
TexPerspective.Width -= (int)diff;
spriteBatch.Draw(texture, new Vector2(left+ TexPerspective.Width, top), new Rectangle(sourceRect.X, TexPerspective.Y,(int)diff, TexPerspective.Height), color, rotation, Vector2.Zero, 1.0f, effects, depth);
}
else if (TexPerspective.Y + TexPerspective.Height > sourceRect.Y + sourceRect.Height)
{
float diff = (TexPerspective.Y + TexPerspective.Height) - (sourceRect.Y + sourceRect.Height);
TexPerspective.Height -= (int)diff;
spriteBatch.Draw(texture, new Vector2(left, top+ TexPerspective.Height), new Rectangle(TexPerspective.X, sourceRect.Y, TexPerspective.Width, (int)diff), color, rotation, Vector2.Zero, 1.0f, effects, depth);
}
spriteBatch.Draw(texture, new Vector2(left,top),TexPerspective, color, rotation, Vector2.Zero, 1.0f, effects, depth);
if (TexPerspective.X+ movementX >= sourceRect.X + sourceRect.Width)
TexPerspective.X = sourceRect.X;
if (TexPerspective.Y + movementY >= sourceRect.Y + sourceRect.Height)
TexPerspective.Y = sourceRect.Y;
}
}
}
public void DrawTiled(SpriteBatch spriteBatch, Vector2 pos, Vector2 targetSize, Vector2 startOffset, Color color)
{
//pos.X = (int)pos.X;

View File

@@ -365,6 +365,35 @@ namespace Barotrauma
return inputType;
}
/// <summary>
/// Calculates the minimum number of single-character edits (i.e. insertions, deletions or substitutions) required to change one string into the other
/// </summary>
public static int LevenshteinDistance(string s, string t)
{
int n = s.Length;
int m = t.Length;
int[,] d = new int[n + 1, m + 1];
if (n == 0 || m == 0) return 0;
for (int i = 0; i <= n; d[i, 0] = i++);
for (int j = 0; j <= m; d[0, j] = j++);
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
int cost = (t[j - 1] == s[i - 1]) ? 0 : 1;
d[i, j] = Math.Min(
Math.Min(d[i - 1, j] + 1, d[i, j - 1] + 1),
d[i - 1, j - 1] + cost);
}
}
return d[n, m];
}
public static string WrapText(string text, float lineLength, SpriteFont font)
{

Binary file not shown.

Binary file not shown.

View File

@@ -1,3 +1,31 @@
---------------------------------------------------------------------------------------------------------
v0.5.1.1
---------------------------------------------------------------------------------------------------------
- fixed non-password protected servers being impossible to join to
- some more security checks
---------------------------------------------------------------------------------------------------------
v0.5.1.0
---------------------------------------------------------------------------------------------------------
- getting attacked by a husk will slowly turn the victim into a husk
- spam filter
- added server options to the ingame HUD
- fixed tiger thresher spawning on Linux
- a more secure password authentication method (again)
- ingame players can't receive messages from lobby players anymore
- more server-side security checks
- medical doctors always have a high enough medical skill to fabricate any drug
- ai-controlled crew can be spawned using the console in multiplayer
- it's possible to manually attack when controlling a creature
- randomly spawned artifacts are spread out better throughout the level
- characters won't let go of a person they're dragging when entering/exiting the sub
- respawned players get the same ID card tags they would've gotten if they had spawned inside the main sub
- highlighted characters glow in the dark
---------------------------------------------------------------------------------------------------------
v0.5.0.3
---------------------------------------------------------------------------------------------------------

View File

@@ -2,5 +2,5 @@
<config masterserverurl="http://www.undertowgames.com/baromaster" autocheckupdates="true" musicvolume="0.0" soundvolume="0.0" verboselogging="true">
<graphicsmode width="1280" height="720" fullscreen="false" />
<contentpackage path="Data/ContentPackages/Vanilla 0.3.xml" />
<keymapping Select="E" Use="0" Aim="1" Up="W" Down="S" Left="A" Right="D" Run="LeftShift" Crouch="LeftControl" Chat="Tab" CrewOrders="C" />
<keymapping Select="E" Use="0" Aim="1" Up="W" Down="S" Left="A" Right="D" Attack="R" Run="LeftShift" Crouch="LeftControl" Chat="Tab" CrewOrders="C" />
</config>