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:
File diff suppressed because it is too large
Load Diff
@@ -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 -->
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
|
||||
118
Subsurface/Content/Characters/Human/humanhusk.xml
Normal file
118
Subsurface/Content/Characters/Human/humanhusk.xml
Normal 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>
|
||||
|
||||
13
Subsurface/Content/Characters/Human/huskappendage.xml
Normal file
13
Subsurface/Content/Characters/Human/huskappendage.xml
Normal 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 |
@@ -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"/>
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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 -->
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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>
|
||||
@@ -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 |
@@ -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>
|
||||
|
||||
|
||||
|
||||
@@ -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 |
@@ -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"/>
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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")]
|
||||
|
||||
@@ -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) { }
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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) ?
|
||||
|
||||
186
Subsurface/Source/Characters/HuskInfection.cs
Normal file
186
Subsurface/Source/Characters/HuskInfection.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace Barotrauma
|
||||
Use,
|
||||
Aim,
|
||||
Up, Down, Left, Right,
|
||||
Attack,
|
||||
Run, Crouch,
|
||||
Chat, CrewOrders
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
Binary file not shown.
@@ -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
|
||||
---------------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -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>
|
||||
Reference in New Issue
Block a user