Merge branch 'ai-overhaul'

Conflicts:
	Barotrauma/Source/Characters/Attack.cs
This commit is contained in:
Joonas Rikkonen
2017-06-29 17:02:37 +03:00
46 changed files with 1148 additions and 488 deletions
+13
View File
@@ -387,6 +387,7 @@
</Content> </Content>
<Content Include="Content\Characters\Charybdis\charybdis.xml"> <Content Include="Content\Characters\Charybdis\charybdis.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<SubType>Designer</SubType>
</Content> </Content>
<Content Include="Content\Characters\Coelanth\coelanth.png"> <Content Include="Content\Characters\Coelanth\coelanth.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
@@ -868,9 +869,21 @@
<Content Include="Content\Particles\shrapnel.png"> <Content Include="Content\Particles\shrapnel.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Include="Content\Particles\Smoke.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\Particles\SmokeParticleSheet.png"> <Content Include="Content\Particles\SmokeParticleSheet.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Include="Content\Particles\Spatter1.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\Particles\Spatter2.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\Particles\Spatter3.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\Sounds\Damage\StructureBlunt10.ogg"> <Content Include="Content\Sounds\Damage\StructureBlunt10.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
+1 -1
View File
@@ -9,7 +9,7 @@
<ErrorReportUrlHistory /> <ErrorReportUrlHistory />
<FallbackCulture>en-US</FallbackCulture> <FallbackCulture>en-US</FallbackCulture>
<VerifyUploadedFiles>false</VerifyUploadedFiles> <VerifyUploadedFiles>false</VerifyUploadedFiles>
<ProjectView>ProjectFiles</ProjectView> <ProjectView>ShowAllFiles</ProjectView>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<ReferencePath> <ReferencePath>
@@ -8,6 +8,16 @@
<sound file="Content/Characters/Carrier/carrier3.ogg" state="None" range="4000"/> <sound file="Content/Characters/Carrier/carrier3.ogg" state="None" range="4000"/>
<sound file="Content/Characters/Carrier/ping.ogg" state="Die" range="3000"/> <sound file="Content/Characters/Carrier/ping.ogg" state="Die" range="3000"/>
<ai
combatstrength="1000"
attackpriorityhumans="100.0"
attackpriorityrooms="50.0"
attackpriorityweaker="0.0"
attackprioritystronger="-80.0"
attackcooldown="15.0"
sight="0.5"
hearing="1.0"/>
<ragdoll waveamplitude="0.0" swimspeed="4.0" mirror="true" rotatetowardsmovement="false" headangle="-90" canentersubmarine="false"> <ragdoll waveamplitude="0.0" swimspeed="4.0" mirror="true" rotatetowardsmovement="false" headangle="-90" canentersubmarine="false">
@@ -44,16 +54,12 @@
</limb> </limb>
<joint limb1="0" limb1anchor="92,-200" limb2="1" limb2anchor="0,-100" lowerlimit="180" upperlimit="210"/> <joint limb1="0" limb1anchor="92,-200" limb2="1" limb2anchor="0,-100" lowerlimit="180" upperlimit="210" canbesevered="true"/>
<joint limb1="0" limb1anchor="64,-264" limb2="2" limb2anchor="0,-100" lowerlimit="180" upperlimit="210"/> <joint limb1="0" limb1anchor="64,-264" limb2="2" limb2anchor="0,-100" lowerlimit="180" upperlimit="210" canbesevered="true"/>
<joint limb1="0" limb1anchor="-100,100" limb2="3" limb2anchor="38,0" lowerlimit="-50" upperlimit="5"/> <joint limb1="0" limb1anchor="-100,100" limb2="3" limb2anchor="38,0" lowerlimit="-50" upperlimit="5" canbesevered="true"/>
<joint limb1="0" limb1anchor="140,268" limb2="4" limb2anchor="0,0" lowerlimit="87" upperlimit="93"/> <joint limb1="0" limb1anchor="140,268" limb2="4" limb2anchor="0,0" lowerlimit="87" upperlimit="93"/>
</ragdoll> </ragdoll>
<ai attackhumans="100.0" attackrooms="50.0"
attackweaker="50.0" attackstronger="-30.0"
attackcooldown="15.0"
sight="0.5" hearing="1.0"/>
</Character> </Character>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 609 KiB

After

Width:  |  Height:  |  Size: 617 KiB

@@ -2,20 +2,36 @@
<Character name ="charybdis" humanoid="false" health="1000.0" bleedingdecreasespeed="0.2"> <Character name ="charybdis" humanoid="false" health="1000.0" bleedingdecreasespeed="0.2">
<sound file="Content/Characters/Charybdis/charybdisattack.ogg" state="Attack" range="8000" /> <sound file="Content/Characters/Charybdis/charybdisattack.ogg" state="Attack" range="8000" />
<ai
combatstrength="1500"
attackpriorityhumans="100.0"
attackpriorityrooms="50.0"
attackpriorityweaker="50"
attackprioritystronger="-30"
eatpriority="40"
sight="0.5"
hearing="1.0"/>
<ragdoll waveamplitude="150.0" wavelength="10000" swimspeed="4.0" scale="1.5" canentersubmarine="false"> <ragdoll
waveamplitude="150.0"
wavelength="10000"
steertorque="1000"
swimspeed="4.0"
scale="1.5"
canentersubmarine="false">
<collider radius="80" height="440"/> <collider radius="80" height="440"/>
<!-- body --> <!-- body -->
<limb id = "0" radius="100" height="470" type="Torso" steerforce="1.0"> <limb id = "0" radius="100" height="470" type="Torso" steerforce="1.0" mouthpos="0,260">
<sprite texture="Content/Characters/Charybdis/charybdis.png" sourcerect="160,0,242,688" depth="0.015" origin="0.5,0.5"/> <sprite texture="Content/Characters/Charybdis/charybdis.png" sourcerect="160,0,242,688" depth="0.015" origin="0.5,0.5"/>
</limb> </limb>
<!-- lower yaw --> <!-- lower yaw -->
<limb id = "1" radius="70" height="100"> <limb id = "1" radius="70" height="100">
<sprite texture="Content/Characters/Charybdis/charybdis.png" sourcerect="416,0,192,256" depth="0.025" origin="0.65,0.5"/> <sprite texture="Content/Characters/Charybdis/charybdis.png" sourcerect="416,0,192,256" depth="0.025" origin="0.65,0.5"/>
<attack range="500" duration="0.5" damage="5.00" bleedingdamage="50" structuredamage="500" damagetype="slash" torque="200" force="50" targetforce="-50"/> <attack range="500" duration="0.5" damage="5.00" bleedingdamage="50" structuredamage="500" damagetype="slash" torque="200" force="50" targetforce="-50" severlimbsprobability="1.0"/>
</limb> </limb>
<!-- front fins --> <!-- front fins -->
@@ -24,18 +40,25 @@
</limb> </limb>
<!-- tail --> <!-- tail -->
<limb id = "3" radius="80" height="580" type="Tail"> <limb id = "3" radius="60" height="250" type="Tail">
<sprite texture="Content/Characters/Charybdis/charybdis.png" sourcerect="0,0,160,752" depth="0.02" origin="0.5,0.5"/> <sprite texture="Content/Characters/Charybdis/charybdis.png" sourcerect="0,0,160,379" depth="0.02" origin="0.5,0.5"/>
</limb> </limb>
<limb id = "4" radius="30" height="168" type="Tail">
<sprite texture="Content/Characters/Charybdis/charybdis.png" sourcerect="24,402,83,228" depth="0.02" origin="0.5,0.5"/>
</limb>
<limb id = "5" radius="20" height="200" type="Tail">
<sprite texture="Content/Characters/Charybdis/charybdis.png" sourcerect="33,645,77,244" depth="0.02" origin="0.5,0.5"/>
</limb>
<!-- body to lower yaw --> <!-- body to lower yaw -->
<joint limb1="0" limb1anchor="48,128" limb2="1" limb2anchor="-30,-90" lowerlimit="-10" upperlimit="30"/> <joint limb1="0" limb1anchor="48,128" limb2="1" limb2anchor="-30,-90" lowerlimit="-10" upperlimit="30"/>
<!-- body to front fin --> <!-- body to front fin -->
<joint limb1="0" limb1anchor="32,-32" limb2="2" limb2anchor="-32,260" lowerlimit="-50" upperlimit="0"/> <joint limb1="0" limb1anchor="32,-32" limb2="2" limb2anchor="-32,260" lowerlimit="-50" upperlimit="0"/>
<!-- body to tail --> <!-- body to tail -->
<joint limb1="0" limb1anchor="0,-270" limb2="3" limb2anchor="0,280" lowerlimit="-20" upperlimit="20"/> <joint limb1="0" limb1anchor="0,-270" limb2="3" limb2anchor="2,134" lowerlimit="-30" upperlimit="30"/>
<joint limb1="3" limb1anchor="-10,-153" limb2="4" limb2anchor="6,88" lowerlimit="-30" upperlimit="30"/>
<joint limb1="4" limb1anchor="-14,-95" limb2="5" limb2anchor="-18,108" lowerlimit="-30" upperlimit="30"/>
</ragdoll> </ragdoll>
<ai attackhumans="100.0" attackrooms="50.0" attackweaker="50" attackstronger="-30" sight="0.5" hearing="1.0"/>
</Character> </Character>
@@ -5,19 +5,35 @@
<sound file="Content/Characters/Coelanth/idle1.ogg" state="None" /> <sound file="Content/Characters/Coelanth/idle1.ogg" state="None" />
<sound file="Content/Characters/Coelanth/idle2.ogg" state="None" /> <sound file="Content/Characters/Coelanth/idle2.ogg" state="None" />
<ragdoll waveamplitude="50.0" wavelength="2500" swimspeed="5.0" walkspeed="3.5" canentersubmarine="false"> <ai
combatstrength="400"
attackpriorityhumans="90.0"
attackpriorityrooms="50.0"
attackpriorityweaker="50"
attackprioritystronger="-100"
eatpriority="40"
sight="0.1"
hearing="1.0"/>
<ragdoll
waveamplitude="50.0"
wavelength="2500"
steertorque="500"
swimspeed="5.0"
walkspeed="3.5"
canentersubmarine="false">
<collider radius="50" height="250"/> <collider radius="50" height="250"/>
<!-- head --> <!-- head -->
<limb id = "0" radius="50" height="270" type="Head" steerforce="1.0"> <limb id = "0" radius="50" height="270" type="Head" steerforce="1.0" mouthpos="50,75">
<sprite texture="Content/Characters/Coelanth/coelanth.png" sourcerect="267,171,162,392" depth="0.02" origin ="0.5,0.5"/> <sprite texture="Content/Characters/Coelanth/coelanth.png" sourcerect="267,171,162,392" depth="0.02" origin ="0.5,0.5"/>
</limb> </limb>
<!-- lower yaw --> <!-- lower yaw -->
<limb id = "1" radius="20" height="240"> <limb id = "1" radius="20" height="240">
<sprite texture="Content/Characters/Coelanth/coelanth.png" sourcerect="425,1,101,309" depth="0.025" origin="0.5,0.5"/> <sprite texture="Content/Characters/Coelanth/coelanth.png" sourcerect="425,1,101,309" depth="0.025" origin="0.5,0.5"/>
<attack range="300" duration="0.5" damage="200" bleedingdamage="50" structuredamage="150" damagetype="slash" torque="100" targetforce="-50"/> <attack range="300" duration="0.5" damage="200" bleedingdamage="50" structuredamage="150" damagetype="slash" torque="100" targetforce="-50" severlimbsprobability="0.8"/>
</limb> </limb>
<!-- body --> <!-- body -->
@@ -51,10 +67,7 @@
<joint limb1="2" limb1anchor="65,100" limb2="4" limb2anchor="0,160" lowerlimit="-50" upperlimit="0"/> <joint limb1="2" limb1anchor="65,100" limb2="4" limb2anchor="0,160" lowerlimit="-50" upperlimit="0"/>
<!-- body to back fin --> <!-- body to back fin -->
<joint limb1="2" limb1anchor="46,-48" limb2="5" limb2anchor="0,55" lowerlimit="-50" upperlimit="0"/> <joint limb1="2" limb1anchor="46,-48" limb2="5" limb2anchor="0,55" lowerlimit="-50" upperlimit="0"/>
</ragdoll> </ragdoll>
<ai attackhumans="100.0" attackrooms="50.0" attackweaker="50" attackstronger="-30" sight="0.1" hearing="1.0"/>
</Character> </Character>
@@ -1,14 +1,28 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<Character name ="crawler" humanoid="false"> <Character name ="crawler" humanoid="false" health="100">
<sound file="Content/Characters/Crawler/attack1.ogg" state="Attack" range="500"/> <sound file="Content/Characters/Crawler/attack1.ogg" state="Attack" range="500"/>
<sound file="Content/Characters/Crawler/attack2.ogg" state="Attack" range="500"/> <sound file="Content/Characters/Crawler/attack2.ogg" state="Attack" range="500"/>
<sound file="Content/Characters/Crawler/idle1.ogg" state="None" range="500"/> <sound file="Content/Characters/Crawler/idle1.ogg" state="None" range="500"/>
<sound file="Content/Characters/Crawler/idle2.ogg" state="None" range="500"/> <sound file="Content/Characters/Crawler/idle2.ogg" state="None" range="500"/>
<ai
combatstrength="100"
attackpriorityhumans="500"
attackpriorityrooms="50.0"
attackpriorityweaker="50"
attackprioritystronger="-60"
eatpriority="55"
sight="0.5"
hearing="1.0"
fleehealththreshold="10"
attachtowalls="true"
attackcooldown="3.0"/>
<ragdoll headposition="50" headangle="-70" <ragdoll headposition="50" headangle="-70"
waveamplitude="2.0" wavelength="5000" waveamplitude="2.0" wavelength="3000"
swimspeed="3.0" walkspeed="2.0" swimspeed="2.0" walkspeed="2.0"
runspeedmultiplier="2" swimspeedmultiplier="2.0"
stepsize ="15.0,20.0" stepsize ="15.0,20.0"
legtorque="10" legtorque="10"
flip="true"> flip="true">
@@ -16,7 +30,7 @@
<collider width="45" radius="22"/> <collider width="45" radius="22"/>
<!-- head --> <!-- head -->
<limb id = "0" radius="22" height="45" type="Head" flip="true" steerforce="1.0" armorsector="0.0,180.0" armorvalue="30.0"> <limb id = "0" radius="22" height="45" type="Head" flip="true" steerforce="1.0" armorsector="0.0,180.0" armorvalue="30.0" mouthpos="17,35">
<sprite texture="Content/Characters/Crawler/crawler.png" sourcerect="0,0,51,121" depth="0.02" origin="0.45,0.63"/> <sprite texture="Content/Characters/Crawler/crawler.png" sourcerect="0,0,51,121" depth="0.02" origin="0.45,0.63"/>
</limb> </limb>
@@ -32,7 +46,9 @@
<limb id = "3" width="13" height="45" ignorecollisions="true" flip="true"> <limb id = "3" width="13" height="45" ignorecollisions="true" flip="true">
<sprite texture="Content/Characters/Crawler/crawler.png" sourcerect="65,131,36,50" depth="0.15" origin="0.4,0.5"/> <sprite texture="Content/Characters/Crawler/crawler.png" sourcerect="65,131,36,50" depth="0.15" origin="0.4,0.5"/>
<attack range="120" duration="0.5" damage="30" stun="0.1" bleedingdamage="3" structuredamage="50" damagetype="slash" force="20" torque="-20" targetforce="-30"/> <attack range="120" duration="0.5" damage="30" stun="0.1" bleedingdamage="3" structuredamage="50"
damagetype="slash" targetforce="-30" severlimbsprobability="0.5"
force="5" applyforceonlimbs="0" torque="-20" />
</limb> </limb>
<limb id = "4" width="11" height="34" type="RightLeg" flip="true"> <limb id = "4" width="11" height="34" type="RightLeg" flip="true">
@@ -59,25 +75,21 @@
<sound file ="Content/Sounds/stepMetal.ogg"/> <sound file ="Content/Sounds/stepMetal.ogg"/>
</limb> </limb>
<joint limb1="0" limb1anchor="-5,-38" limb2="1" limb2anchor="-2,25" lowerlimit="-20" upperlimit="40"/> <joint limb1="0" limb1anchor="-5,-38" limb2="1" limb2anchor="-2,25" lowerlimit="-20" upperlimit="40" canbesevered="true"/>
<joint limb1="1" limb1anchor="0,-15" limb2="2" limb2anchor="-10,31" lowerlimit="-20" upperlimit="40"/> <joint limb1="1" limb1anchor="0,-15" limb2="2" limb2anchor="-10,31" lowerlimit="-20" upperlimit="40" canbesevered="true"/>
<joint limb1="0" limb1anchor="7,30" limb2="3" limb2anchor="-2,-17" lowerlimit="-180" upperlimit="-90"/> <joint limb1="0" limb1anchor="7,30" limb2="3" limb2anchor="-2,-17" lowerlimit="-180" upperlimit="-90" canbesevered="true"/>
<joint limb1="0" limb1anchor="13,6" limb2="4" limb2anchor="0,14" lowerlimit="-270" upperlimit="-180"/> <joint limb1="0" limb1anchor="13,6" limb2="4" limb2anchor="0,14" lowerlimit="-270" upperlimit="-180" canbesevered="true"/>
<joint limb1="4" limb1anchor="0,-17" limb2="5" limb2anchor="0,-17" lowerlimit="-350" upperlimit="-190"/> <joint limb1="4" limb1anchor="0,-17" limb2="5" limb2anchor="0,-17" lowerlimit="-350" upperlimit="-190" canbesevered="true"/>
<joint limb1="0" limb1anchor="13,-15" limb2="6" limb2anchor="0,14" lowerlimit="-270" upperlimit="-180"/> <joint limb1="0" limb1anchor="13,-15" limb2="6" limb2anchor="0,14" lowerlimit="-270" upperlimit="-180" canbesevered="true"/>
<joint limb1="6" limb1anchor="0,-17" limb2="7" limb2anchor="0,-17" lowerlimit="-350" upperlimit="-190"/> <joint limb1="6" limb1anchor="0,-17" limb2="7" limb2anchor="0,-17" lowerlimit="-350" upperlimit="-190" canbesevered="true"/>
<joint limb1="0" limb1anchor="13,-35" limb2="8" limb2anchor="0,14" lowerlimit="-270" upperlimit="-180"/> <joint limb1="0" limb1anchor="13,-35" limb2="8" limb2anchor="0,14" lowerlimit="-270" upperlimit="-180" canbesevered="true"/>
<joint limb1="8" limb1anchor="0,-17" limb2="9" limb2anchor="0,-17" lowerlimit="-350" upperlimit="-190"/> <joint limb1="8" limb1anchor="0,-17" limb2="9" limb2anchor="0,-17" lowerlimit="-350" upperlimit="-190" canbesevered="true"/>
</ragdoll> </ragdoll>
<ai attackhumans="500" attackrooms="50.0" attackweaker="50" attackstronger="-30"
sight="0.5" hearing="1.0"
attackcooldown="3.0"/>
</Character> </Character>
@@ -1,10 +1,18 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<Character name ="endworm" humanoid="false" health="10000.0" doesbleed="false"> <Character name ="endworm" humanoid="false" health="10000.0" doesbleed="false">
<sound file="Content/Characters/Endworm/endwormidle.ogg" state="None" range="8000" /> <sound file="Content/Characters/Endworm/endwormidle.ogg" state="None" range="8000" />
<sound file="Content/Characters/Endworm/endwormattack1.ogg" state="Attack" range="8000" /> <sound file="Content/Characters/Endworm/endwormattack1.ogg" state="Attack" range="8000" />
<sound file="Content/Characters/Endworm/endwormattack2.ogg" state="Attack" range="8000" /> <sound file="Content/Characters/Endworm/endwormattack2.ogg" state="Attack" range="8000" />
<ai
combatstrength="10000"
attackpriorityrooms="100.0"
attackpriorityweaker="0"
attackstronger="-30"
sight="0.1"
hearing="2.0"/>
<ragdoll waveamplitude="100.0" wavelength="1000" speed="2.0" scale ="2.0" flip="false" canentersubmarine="false"> <ragdoll waveamplitude="100.0" wavelength="1000" speed="2.0" scale ="2.0" flip="false" canentersubmarine="false">
<collider radius="300"/> <collider radius="300"/>
@@ -75,6 +83,5 @@
<joint limb1="0" limb1anchor="160,50" limb2="9" limb2anchor="0,-200" lowerlimit="-50" upperlimit="20"/> <joint limb1="0" limb1anchor="160,50" limb2="9" limb2anchor="0,-200" lowerlimit="-50" upperlimit="20"/>
</ragdoll> </ragdoll>
<ai attackrooms="100.0" attackweaker="50" attackstronger="-30" sight="0.1" hearing="2.0"/>
</Character> </Character>
@@ -5,6 +5,14 @@
<sound file="Content/Characters/Fractalguardian/guardian2.ogg" state="Attack" range="3000" /> <sound file="Content/Characters/Fractalguardian/guardian2.ogg" state="Attack" range="3000" />
<sound file="Content/Characters/Fractalguardian/Die1.ogg" state="Die" range="3000" /> <sound file="Content/Characters/Fractalguardian/Die1.ogg" state="Die" range="3000" />
<sound file="Content/Characters/Fractalguardian/Die2.ogg" state="Die" range="3000" /> <sound file="Content/Characters/Fractalguardian/Die2.ogg" state="Die" range="3000" />
<ai
combatstrength="500"
attackpriorityrooms="0.0"
attackpriorityhumans="100"
sight="1.0"
hearing="2.0"
attackcooldown="1"/>
<ragdoll waveamplitude="50.0" wavelength="500" swimspeed="3.0" walkspeed="0.3" flip="false" canentersubmarine="false"> <ragdoll waveamplitude="50.0" wavelength="500" swimspeed="3.0" walkspeed="0.3" flip="false" canentersubmarine="false">
@@ -41,16 +49,15 @@
<!-- head to body --> <!-- head to body -->
<joint limb1="0" limb1anchor="0,-60" limb2="1" limb2anchor="0,30" lowerlimit="-30" upperlimit="30"/> <joint limb1="0" limb1anchor="0,-60" limb2="1" limb2anchor="0,30" lowerlimit="-30" upperlimit="30" canbesevered="true"/>
<joint limb1="1" limb1anchor="0,-47" limb2="2" limb2anchor="0,56" lowerlimit="-30" upperlimit="30"/> <joint limb1="1" limb1anchor="0,-47" limb2="2" limb2anchor="0,56" lowerlimit="-30" upperlimit="30" canbesevered="true"/>
<joint limb1="2" limb1anchor="0,-60" limb2="3" limb2anchor="0,80" lowerlimit="-30" upperlimit="30"/> <joint limb1="2" limb1anchor="0,-60" limb2="3" limb2anchor="0,80" lowerlimit="-30" upperlimit="30" canbesevered="true"/>
<joint limb1="0" limb1anchor="30,10" limb2="4" limb2anchor="0,-110" lowerlimit="-180" upperlimit="-90"/> <joint limb1="0" limb1anchor="30,10" limb2="4" limb2anchor="0,-110" lowerlimit="-180" upperlimit="-90" canbesevered="true"/>
<joint limb1="0" limb1anchor="-30,10" limb2="5" limb2anchor="0,-110" lowerlimit="90" upperlimit="180"/> <joint limb1="0" limb1anchor="-30,10" limb2="5" limb2anchor="0,-110" lowerlimit="90" upperlimit="180" canbesevered="true"/>
</ragdoll> </ragdoll>
<ai attackrooms="0.0" attackhumans="100" sight="1.0" hearing="2.0" attackcooldown="1"/>
</Character> </Character>
@@ -5,6 +5,14 @@
<sound file="Content/Characters/Fractalguardian/guardian2.ogg" state="Attack" range="3000" /> <sound file="Content/Characters/Fractalguardian/guardian2.ogg" state="Attack" range="3000" />
<sound file="Content/Characters/Fractalguardian/Die1.ogg" state="Die" range="3000" /> <sound file="Content/Characters/Fractalguardian/Die1.ogg" state="Die" range="3000" />
<sound file="Content/Characters/Fractalguardian/Die2.ogg" state="Die" range="3000" /> <sound file="Content/Characters/Fractalguardian/Die2.ogg" state="Die" range="3000" />
<ai
combatstrength="500"
attackpriorityrooms="0.0"
attackpriorityhumans="100"
sight="1.0"
hearing="2.0"
attackcooldown="1"/>
<ragdoll waveamplitude="0.0" swimspeed="1.0" walkspeed="0.3" flip="false" canentersubmarine="false" rotatetowardsmovement="false"> <ragdoll waveamplitude="0.0" swimspeed="1.0" walkspeed="0.3" flip="false" canentersubmarine="false" rotatetowardsmovement="false">
@@ -32,19 +40,16 @@
<limb id = "4" width="30" height="175"> <limb id = "4" width="30" height="175">
<sprite texture="Content/Characters/Fractalguardian/fractalguardian.png" sourcerect="131,0,36,175" depth="0.1" origin="0.5,0.5"/> <sprite texture="Content/Characters/Fractalguardian/fractalguardian.png" sourcerect="131,0,36,175" depth="0.1" origin="0.5,0.5"/>
<attack range="150" duration="0.5" damage="30" stun="1.0" torque="-150" damagetype="slash"/> <attack range="150" duration="0.5" damage="30" stun="1.0" torque="-150" damagetype="slash"/>
</limb> </limb>
<!-- head to body --> <!-- head to body -->
<joint limb1="0" limb1anchor="-37,-40" limb2="1" limb2anchor="0,80" lowerlimit="-60" upperlimit="0"/> <joint limb1="0" limb1anchor="-37,-40" limb2="1" limb2anchor="0,80" lowerlimit="-60" upperlimit="0" canbesevered="true"/>
<joint limb1="1" limb1anchor="0,-80" limb2="2" limb2anchor="0,80" lowerlimit="0" upperlimit="120"/> <joint limb1="1" limb1anchor="0,-80" limb2="2" limb2anchor="0,80" lowerlimit="0" upperlimit="120" canbesevered="true"/>
<joint limb1="0" limb1anchor="37,-40" limb2="3" limb2anchor="0,80" lowerlimit="0" upperlimit="60"/>
<joint limb1="3" limb1anchor="0,-80" limb2="4" limb2anchor="0,80" lowerlimit="-120" upperlimit="0"/>
<joint limb1="0" limb1anchor="37,-40" limb2="3" limb2anchor="0,80" lowerlimit="0" upperlimit="60" canbesevered="true"/>
<joint limb1="3" limb1anchor="0,-80" limb2="4" limb2anchor="0,80" lowerlimit="-120" upperlimit="0" canbesevered="true"/>
</ragdoll> </ragdoll>
<ai attackrooms="0.0" attackhumans="100" sight="1.0" hearing="2.0" attackcooldown="1"/>
</Character> </Character>
+11 -11
View File
@@ -9,8 +9,8 @@
movementlerp="0.4" movementlerp="0.4"
legtorque="15.0" legtorque="15.0"
thightorque="-5.0" thightorque="-5.0"
walkspeed="1.5" walkspeed="1.5" swimspeed="2.0"
swimspeed="2.0" runspeedmultiplier="3.0" swimspeedmultiplier="1.5"
colliderheightfromfloor="55" colliderheightfromfloor="55"
impacttolerance="7.5"> impacttolerance="7.5">
@@ -84,25 +84,25 @@
</limb> </limb>
<!-- head to body --> <!-- head to body -->
<joint limb1="0" limb1anchor="0,-7" limb2="1" limb2anchor="-1,26" lowerlimit="-90" upperlimit="45"/> <joint limb1="0" limb1anchor="0,-7" limb2="1" limb2anchor="-1,26" lowerlimit="-90" upperlimit="45" canbesevered="true"/>
<joint limb1="1" limb1anchor="0,-17" limb2="12" limb2anchor="0,7" lowerlimit="-10" upperlimit="10"/> <joint limb1="1" limb1anchor="0,-17" limb2="12" limb2anchor="0,7" lowerlimit="-10" upperlimit="10"/>
<!-- body to left arm --> <!-- body to left arm -->
<joint limb1="1" limb1anchor="-3,14" limb2="2" limb2anchor="0,12"/> <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"/> <joint limb1="2" limb1anchor="0,-16" limb2="3" limb2anchor="-2,19" lowerlimit="5" upperlimit="170" canbesevered="true"/>
<!-- body to right arm --> <!-- body to right arm -->
<joint limb1="1" limb1anchor="-3,14" limb2="4" limb2anchor="0,12"/> <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"/> <joint limb1="4" limb1anchor="0,-16" limb2="5" limb2anchor="-2,19" lowerlimit="5" upperlimit="170" canbesevered="true"/>
<!-- body to left leg --> <!-- body to left leg -->
<joint limb1="12" limb1anchor="0,-1" limb2="6" limb2anchor="0,14" lowerlimit="-30" upperlimit="120"/> <joint limb1="12" limb1anchor="0,-1" limb2="6" limb2anchor="0,14" lowerlimit="-30" upperlimit="120" canbesevered="true"/>
<joint limb1="6" limb1anchor="0,-15" limb2="7" limb2anchor="0,20" lowerlimit="-120" upperlimit="0"/> <joint limb1="6" limb1anchor="0,-15" limb2="7" limb2anchor="0,20" lowerlimit="-120" upperlimit="0" canbesevered="true"/>
<joint limb1="7" limb1anchor="-3,-21" limb2="8" limb2anchor="5,7" lowerlimit="20" upperlimit="90"/> <joint limb1="7" limb1anchor="-3,-21" limb2="8" limb2anchor="5,7" lowerlimit="20" upperlimit="90" canbesevered="true"/>
<!-- body to right leg --> <!-- body to right leg -->
<joint limb1="12" limb1anchor="0,-1" limb2="9" limb2anchor="0,14" lowerlimit="-30" upperlimit="120"/> <joint limb1="12" limb1anchor="0,-1" limb2="9" limb2anchor="0,14" lowerlimit="-30" upperlimit="120" canbesevered="true"/>
<joint limb1="9" limb1anchor="0,-15" limb2="10" limb2anchor="0,20" lowerlimit="-120" upperlimit="0"/> <joint limb1="9" limb1anchor="0,-15" limb2="10" limb2anchor="0,20" lowerlimit="-120" upperlimit="0" canbesevered="true"/>
<joint limb1="10" limb1anchor="-3,-21" limb2="11" limb2anchor="5,7" lowerlimit="20" upperlimit="90"/> <joint limb1="10" limb1anchor="-3,-21" limb2="11" limb2anchor="5,7" lowerlimit="20" upperlimit="90" canbesevered="true"/>
</ragdoll> </ragdoll>
</Character> </Character>
@@ -9,12 +9,12 @@
movementlerp="0.4" movementlerp="0.4"
legtorque="15.0" legtorque="15.0"
thightorque="-5.0" thightorque="-5.0"
walkspeed="1.5" walkspeed="1.5" swimspeed="2.5"
swimspeed="2.5" runspeedmultiplier="2.0" swimspeedmultiplier="1.5"
impacttolerance="7.5"> impacttolerance="7.5">
<collider height="80" radius="15"/> <collider height="80" radius="15"/>
<collider height="40" radius="15"/> <collider height="40" radius="15"/>
<!-- head --> <!-- head -->
<limb id = "0" radius="13" mass = "6" type="Head" attackpriority="2"> <limb id = "0" radius="13" mass = "6" type="Head" attackpriority="2">
@@ -84,34 +84,35 @@
<limb id = "13" width="10" height="30" mass = "6" attackpriority="2" flip="true" pullpos="0.0,25.0"> <limb id = "13" width="10" height="30" mass = "6" attackpriority="2" flip="true" 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"/> <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"> <attack range="70" duration="0.1" bleedingdamage="3" damage="10" stun="0.5" damagetype="slash" targetforce="10"
force="5" applyforceonlimbs="1" torque="-10">
<StatusEffect type="OnUse" target="Character" HuskInfectionState="0.01" disabledeltatime="true"/> <StatusEffect type="OnUse" target="Character" HuskInfectionState="0.01" disabledeltatime="true"/>
<StatusEffect type="OnUse" target="This" Health="20.0" disabledeltatime="true"/> <StatusEffect type="OnUse" target="This" Health="20.0" disabledeltatime="true"/>
</attack> </attack>
</limb> </limb>
<!-- head to body --> <!-- head to body -->
<joint limb1="0" limb1anchor="0,-7" limb2="1" limb2anchor="-1,26" lowerlimit="-90" upperlimit="45"/> <joint limb1="0" limb1anchor="0,-7" limb2="1" limb2anchor="-1,26" lowerlimit="-90" upperlimit="45" canbesevered="true"/>
<joint limb1="1" limb1anchor="0,-17" limb2="12" limb2anchor="0,7" lowerlimit="-10" upperlimit="10"/> <joint limb1="1" limb1anchor="0,-17" limb2="12" limb2anchor="0,7" lowerlimit="-10" upperlimit="10"/>
<!-- body to left arm --> <!-- body to left arm -->
<joint limb1="1" limb1anchor="-3,14" limb2="2" limb2anchor="0,12"/> <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"/> <joint limb1="2" limb1anchor="0,-16" limb2="3" limb2anchor="-2,19" lowerlimit="5" upperlimit="170" canbesevered="true"/>
<!-- body to right arm --> <!-- body to right arm -->
<joint limb1="1" limb1anchor="-3,14" limb2="4" limb2anchor="0,12"/> <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"/> <joint limb1="4" limb1anchor="0,-16" limb2="5" limb2anchor="-2,19" lowerlimit="5" upperlimit="170" canbesevered="true"/>
<!-- body to left leg --> <!-- body to left leg -->
<joint limb1="12" limb1anchor="0,-1" limb2="6" limb2anchor="0,14" lowerlimit="-30" upperlimit="120"/> <joint limb1="12" limb1anchor="0,-1" limb2="6" limb2anchor="0,14" lowerlimit="-30" upperlimit="120" canbesevered="true"/>
<joint limb1="6" limb1anchor="0,-15" limb2="7" limb2anchor="0,20" lowerlimit="-120" upperlimit="0"/> <joint limb1="6" limb1anchor="0,-15" limb2="7" limb2anchor="0,20" lowerlimit="-120" upperlimit="0" canbesevered="true"/>
<joint limb1="7" limb1anchor="-3,-21" limb2="8" limb2anchor="5,7" lowerlimit="20" upperlimit="90"/> <joint limb1="7" limb1anchor="-3,-21" limb2="8" limb2anchor="5,7" lowerlimit="20" upperlimit="90" canbesevered="true"/>
<!-- body to right leg --> <!-- body to right leg -->
<joint limb1="12" limb1anchor="0,-1" limb2="9" limb2anchor="0,14" lowerlimit="-30" upperlimit="120"/> <joint limb1="12" limb1anchor="0,-1" limb2="9" limb2anchor="0,14" lowerlimit="-30" upperlimit="120" canbesevered="true"/>
<joint limb1="9" limb1anchor="0,-15" limb2="10" limb2anchor="0,20" lowerlimit="-120" upperlimit="0"/> <joint limb1="9" limb1anchor="0,-15" limb2="10" limb2anchor="0,20" lowerlimit="-120" upperlimit="0" canbesevered="true"/>
<joint limb1="10" limb1anchor="-3,-21" limb2="11" limb2anchor="5,7" lowerlimit="20" upperlimit="90"/> <joint limb1="10" limb1anchor="-3,-21" limb2="11" limb2anchor="5,7" lowerlimit="20" upperlimit="90" canbesevered="true"/>
<joint limb1="1" limb1anchor="25,10" limb2="13" limb2anchor="25,0" lowerlimit="-40" upperlimit="0"/> <joint limb1="1" limb1anchor="25,10" limb2="13" limb2anchor="25,0" lowerlimit="-40" upperlimit="0" canbesevered="true"/>
</ragdoll> </ragdoll>
+24 -19
View File
@@ -5,28 +5,38 @@
<sound file="Content/Characters/Husk/Husk2.ogg" state="Attack" range="1000"/> <sound file="Content/Characters/Husk/Husk2.ogg" state="Attack" range="1000"/>
<sound file="Content/Characters/Husk/Husk3.ogg" state="Attack" range="1000"/> <sound file="Content/Characters/Husk/Husk3.ogg" state="Attack" range="1000"/>
<ai
combatstrength="100"
attackpriorityhumans="500"
attackpriorityrooms="5.0"
attackpriorityweaker="50"
attackprioritystronger="-30"
sight="0.5"
hearing="1.0"
attackcooldown="1.0"/>
<ragdoll headposition="134" torsoposition="108" <ragdoll headposition="134" torsoposition="108"
stepsize="42.0, 12.0" stepsize="42.0, 12.0"
walkanimspeed="4.58" walkanimspeed="4.58"
movementlerp="0.4" movementlerp="0.4"
legtorque="15.0" legtorque="15.0"
thightorque="-5.0" thightorque="-5.0"
walkspeed="1.2" walkspeed="1.2" swimspeed="2.5"
swimspeed="2.5"> runspeedmultiplier="2.0" swimspeedmultiplier="1.5">
<collider height="80" radius="15"/> <collider height="80" radius="15"/>
<collider height="40" radius="15"/> <collider height="40" radius="15"/>
<!-- head --> <!-- head -->
<limb id = "0" radius="13" mass = "6" type="Head" attackpriority="2"> <limb id = "0" radius="13" mass = "6" type="Head" attackpriority="2">
<sprite texture="Content/Characters/Husk/DivingSuit.png" sourcerect="95,0,33,25" depth="0.04" origin="0.5,0.5"/> <sprite texture="Content/Characters/Husk/DivingSuit.png" sourcerect="95,0,33,25" depth="0.04" origin="0.5,0.5"/>
</limb> </limb>
<!-- spike/tentacle thingy --> <!-- spike/tentacle thingy -->
<limb id = "13" width="10" height="30" mass = "6" attackpriority="2" flip="true" pullpos="0.0,25.0"> <limb id = "13" width="10" height="30" mass = "6" attackpriority="2" 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"/> <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" force="1" torque="-50" damagetype="slash" targetforce="10"> <attack range="70" duration="0.2" bleedingdamage="0.5" damage="10" stun="0.5" damagetype="slash" targetforce="10"
force="5" applyforceonlimbs="1" torque="-10">
<StatusEffect type="OnUse" target="Character" HuskInfectionState="0.01" disabledeltatime="true"/> <StatusEffect type="OnUse" target="Character" HuskInfectionState="0.01" disabledeltatime="true"/>
<StatusEffect type="OnUse" target="This" Health="1.0" disabledeltatime="true"/> <StatusEffect type="OnUse" target="This" Health="1.0" disabledeltatime="true"/>
</attack> </attack>
@@ -82,7 +92,7 @@
</limb> </limb>
<!-- head to body --> <!-- head to body -->
<joint limb1="0" limb1anchor="-10,-10" limb2="1" limb2anchor="-3,28" lowerlimit="0" upperlimit="10"/> <joint limb1="0" limb1anchor="-10,-10" limb2="1" limb2anchor="-3,28" lowerlimit="0" upperlimit="10" canbesevered="true"/>
<!-- spike to head --> <!-- spike to head -->
<joint limb1="0" limb1anchor="35,-8" limb2="13" limb2anchor="30,0" lowerlimit="-40" upperlimit="0"/> <joint limb1="0" limb1anchor="35,-8" limb2="13" limb2anchor="30,0" lowerlimit="-40" upperlimit="0"/>
@@ -90,26 +100,21 @@
<!-- body to left arm --> <!-- body to left arm -->
<joint limb1="1" limb1anchor="-3,14" limb2="2" limb2anchor="0,12"/> <joint limb1="1" limb1anchor="-3,14" limb2="2" limb2anchor="0,12"/>
<joint limb1="2" limb1anchor="0,-16" limb2="3" limb2anchor="-2,19" lowerlimit="0" upperlimit="170"/> <joint limb1="2" limb1anchor="0,-16" limb2="3" limb2anchor="-2,19" lowerlimit="0" upperlimit="170" canbesevered="true"/>
<!-- body to right arm --> <!-- body to right arm -->
<joint limb1="1" limb1anchor="-3,14" limb2="4" limb2anchor="0,12"/> <joint limb1="1" limb1anchor="-3,14" limb2="4" limb2anchor="0,12"/>
<joint limb1="4" limb1anchor="0,-16" limb2="5" limb2anchor="-2,19" lowerlimit="0" upperlimit="170"/> <joint limb1="4" limb1anchor="0,-16" limb2="5" limb2anchor="-2,19" lowerlimit="0" upperlimit="170" canbesevered="true"/>
<!-- body to left leg --> <!-- body to left leg -->
<joint limb1="12" limb1anchor="0,-1" limb2="6" limb2anchor="0,14" lowerlimit="-30" upperlimit="120"/> <joint limb1="12" limb1anchor="0,-1" limb2="6" limb2anchor="0,14" lowerlimit="-30" upperlimit="120" canbesevered="true"/>
<joint limb1="6" limb1anchor="0,-15" limb2="7" limb2anchor="0,20" lowerlimit="-150" upperlimit="-10"/> <joint limb1="6" limb1anchor="0,-15" limb2="7" limb2anchor="0,20" lowerlimit="-150" upperlimit="-10" canbesevered="true"/>
<joint limb1="7" limb1anchor="-3,-21" limb2="8" limb2anchor="5,7" lowerlimit="20" upperlimit="90"/> <joint limb1="7" limb1anchor="-3,-21" limb2="8" limb2anchor="5,7" lowerlimit="20" upperlimit="90" canbesevered="true"/>
<!-- body to right leg --> <!-- body to right leg -->
<joint limb1="12" limb1anchor="0,-1" limb2="9" limb2anchor="0,14" lowerlimit="-30" upperlimit="120"/> <joint limb1="12" limb1anchor="0,-1" limb2="9" limb2anchor="0,14" lowerlimit="-30" upperlimit="120" canbesevered="true"/>
<joint limb1="9" limb1anchor="0,-15" limb2="10" limb2anchor="0,20" lowerlimit="-150" upperlimit="-10"/> <joint limb1="9" limb1anchor="0,-15" limb2="10" limb2anchor="0,20" lowerlimit="-150" upperlimit="-10" canbesevered="true"/>
<joint limb1="10" limb1anchor="-3,-21" limb2="11" limb2anchor="5,7" lowerlimit="20" upperlimit="90"/> <joint limb1="10" limb1anchor="-3,-21" limb2="11" limb2anchor="5,7" lowerlimit="20" upperlimit="90" canbesevered="true"/>
</ragdoll> </ragdoll>
<ai attackhumans="500" attackrooms="5.0" attackweaker="50" attackstronger="-30"
sight="0.5" hearing="1.0"
attackcooldown="1.0"/>
</Character> </Character>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

After

Width:  |  Height:  |  Size: 88 KiB

+29 -18
View File
@@ -7,10 +7,24 @@
<sound file="Content/Characters/Mantis/idle1.ogg" state="None" range="500"/> <sound file="Content/Characters/Mantis/idle1.ogg" state="None" range="500"/>
<sound file="Content/Characters/Mantis/idle2.ogg" state="None" range="500"/> <sound file="Content/Characters/Mantis/idle2.ogg" state="None" range="500"/>
<sound file="Content/Characters/Mantis/idle3.ogg" state="None" range="500"/> <sound file="Content/Characters/Mantis/idle3.ogg" state="None" range="500"/>
<ai
combatstrength="250"
attackpriorityhumans="500.0"
attackpriorityrooms="50.0"
attackpriorityweaker="60"
attackprioritystronger="-70"
eatpriority="65"
attackcooldown="1.0"
sight="0.5"
hearing="1.0"
attachtowalls="true"
fleehealththreshold="20"/>
<ragdoll headposition="120" headangle="-90" <ragdoll headposition="120" headangle="-90"
waveamplitude="50.0" wavelength="2500" waveamplitude="50.0" wavelength="2500"
swimspeed="2.0" walkspeed="3.0" swimspeed="2.0" walkspeed="2.0"
runspeedmultiplier="1.5" swimspeedmultiplier="1.5"
stepsize ="20.0,20.0" stepsize ="20.0,20.0"
legtorque="10" legtorque="10"
footrotation ="180.0" footrotation ="180.0"
@@ -19,7 +33,7 @@
<collider radius="60"/> <collider radius="60"/>
<!-- head --> <!-- head -->
<limb id = "0" radius="30" height="86" mass = "6" type="Head" flip="true" steerforce="1.0" armorsector="0.0,180.0" armor="10.0"> <limb id = "0" radius="30" height="86" mass = "6" type="Head" flip="true" steerforce="1.0" armorsector="0.0,180.0" armor="10.0" mouthpos="30,65">
<sprite texture="Content/Characters/Mantis/mantis.png" sourcerect="0,0,101,168" depth="0.02" origin="0.4,0.53"/> <sprite texture="Content/Characters/Mantis/mantis.png" sourcerect="0,0,101,168" depth="0.02" origin="0.4,0.53"/>
</limb> </limb>
@@ -35,7 +49,7 @@
<!-- tail --> <!-- tail -->
<limb id = "3" radius="20" mass = "6" type="Tail" flip="true" armorsector="0.0,180.0" armor="10.0"> <limb id = "3" radius="20" mass = "6" type="Tail" flip="true" armorsector="0.0,180.0" armor="10.0">
<sprite texture="Content/Characters/Mantis/mantis.png" sourcerect="130,158,46,93" depth="0.023" origin="0.37,0.3"/> <sprite texture="Content/Characters/Mantis/mantis.png" sourcerect="133,158,46,93" depth="0.023" origin="0.37,0.3"/>
</limb> </limb>
@@ -49,7 +63,8 @@
<!-- ""claw" --> <!-- ""claw" -->
<limb id = "6" width="15" height="63" mass = "4" flip="true" pullpos="0.0,30.0" refjoint="0"> <limb id = "6" width="15" height="63" mass = "4" flip="true" pullpos="0.0,30.0" refjoint="0">
<sprite texture="Content/Characters/Mantis/mantis.png" sourcerect="228,1,28,76" depth="0.01" origin="0.5,0.5"/> <sprite texture="Content/Characters/Mantis/mantis.png" sourcerect="228,1,28,76" depth="0.01" origin="0.5,0.5"/>
<attack range="200" duration="0.5" damage="30" stun="0.1" bleedingdamage="5" structuredamage="50" torque="-20" damagetype="slash" force="10" targetforce="-30"/> <attack range="200" duration="0.25" damage="50" stun="0.1" bleedingdamage="5" structuredamage="50" damagetype="slash" targetforce="-100" severlimbsprobability="0.8"
torque="-20" force="10" applyforceonlimbs="0,1,6"/>
<sound file ="Content/Sounds/stepMetal.ogg"/> <sound file ="Content/Sounds/stepMetal.ogg"/>
</limb> </limb>
@@ -69,27 +84,23 @@
<sound file ="Content/Sounds/stepMetal.ogg"/> <sound file ="Content/Sounds/stepMetal.ogg"/>
</limb> </limb>
<joint limb1="0" limb1anchor="-5,-53" limb2="1" limb2anchor="0,20" lowerlimit="-20" upperlimit="20"/> <joint limb1="0" limb1anchor="-5,-53" limb2="1" limb2anchor="0,20" lowerlimit="-20" upperlimit="20" canbesevered="true"/>
<joint limb1="1" limb1anchor="6,-18" limb2="2" limb2anchor="-2,36" lowerlimit="-20" upperlimit="30"/> <joint limb1="1" limb1anchor="6,-18" limb2="2" limb2anchor="-2,36" lowerlimit="-20" upperlimit="30" canbesevered="true"/>
<joint limb1="2" limb1anchor="1,7" limb2="3" limb2anchor="6,15" lowerlimit="-20" upperlimit="40"/> <joint limb1="2" limb1anchor="1,7" limb2="3" limb2anchor="0,20" lowerlimit="-20" upperlimit="40" canbesevered="true"/>
<joint limb1="0" limb1anchor="16,2" limb2="4" limb2anchor="-5,-20" lowerlimit="-90" upperlimit="0"/> <joint limb1="0" limb1anchor="16,2" limb2="4" limb2anchor="-5,-20" lowerlimit="-90" upperlimit="0" canbesevered="true"/>
<joint limb1="4" limb1anchor="-2,21" limb2="5" limb2anchor="-5,-20" lowerlimit="-290" upperlimit="-190"/> <joint limb1="4" limb1anchor="-2,21" limb2="5" limb2anchor="-5,-20" lowerlimit="-290" upperlimit="-190" canbesevered="true"/>
<joint limb1="5" limb1anchor="-2,27" limb2="6" limb2anchor="0,-30" lowerlimit="-190" upperlimit="-30"/> <joint limb1="5" limb1anchor="-2,27" limb2="6" limb2anchor="0,-30" lowerlimit="-190" upperlimit="-30" canbesevered="true"/>
<joint limb1="0" limb1anchor="52,-34" limb2="7" limb2anchor="-4,-19" lowerlimit="-90" upperlimit="0"/> <joint limb1="0" limb1anchor="52,-34" limb2="7" limb2anchor="-4,-19" lowerlimit="-90" upperlimit="0" canbesevered="true"/>
<joint limb1="7" limb1anchor="-2,28" limb2="8" limb2anchor="2,-32" lowerlimit="-190" upperlimit="-30"/> <joint limb1="7" limb1anchor="-2,28" limb2="8" limb2anchor="2,-32" lowerlimit="-190" upperlimit="-30" canbesevered="true"/>
<joint limb1="0" limb1anchor="43,-67" limb2="9" limb2anchor="0,21" lowerlimit="-180" upperlimit="-10"/> <joint limb1="0" limb1anchor="43,-67" limb2="9" limb2anchor="0,21" lowerlimit="-180" upperlimit="-10" canbesevered="true"/>
<joint limb1="9" limb1anchor="0,-28" limb2="10" limb2anchor="-11,-46" lowerlimit="-190" upperlimit="-50"/> <joint limb1="9" limb1anchor="0,-28" limb2="10" limb2anchor="-11,-46" lowerlimit="-190" upperlimit="-50" canbesevered="true"/>
</ragdoll> </ragdoll>
<ai attackhumans="500" attackrooms="50.0" attackweaker="50" attackstronger="-30"
sight="0.5" hearing="1.0"
attackcooldown="1.0"/>
</Character> </Character>
+17 -13
View File
@@ -6,6 +6,14 @@
<sound file="Content/Characters/Moloch/idle1.ogg" state="None" range="3000"/> <sound file="Content/Characters/Moloch/idle1.ogg" state="None" range="3000"/>
<sound file="Content/Characters/Moloch/idle2.ogg" state="None" range="3000"/> <sound file="Content/Characters/Moloch/idle2.ogg" state="None" range="3000"/>
<ai
combatstrength="1200"
attackpriorityhumans="40.0"
attackpriorityrooms="50.0"
attackprioritystronger="-100.0"
attackcooldown="15.0"
sight="0.5" hearing="1.0"/>
<ragdoll waveamplitude="0.0" swimspeed="2.0" mirror="true" rotatetowardsmovement="false" headangle="-90" canentersubmarine="false"> <ragdoll waveamplitude="0.0" swimspeed="2.0" mirror="true" rotatetowardsmovement="false" headangle="-90" canentersubmarine="false">
<collider radius ="230"/> <collider radius ="230"/>
@@ -46,22 +54,18 @@
<sprite texture="Content/Characters/Moloch/moloch.png" sourcerect="867,474,101,550" depth="0.025" origin="0.5,0.5"/> <sprite texture="Content/Characters/Moloch/moloch.png" sourcerect="867,474,101,550" depth="0.025" origin="0.5,0.5"/>
</limb> </limb>
<joint limb1="0" limb1anchor="112,77" limb2="1" limb2anchor="0,-190" lowerlimit="-180" upperlimit="-90"/> <joint limb1="0" limb1anchor="112,77" limb2="1" limb2anchor="0,-190" lowerlimit="-180" upperlimit="-90" canbesevered="true"/>
<joint limb1="1" limb1anchor="0,190" limb2="2" limb2anchor="0,-100" lowerlimit="-50" upperlimit="0"/> <joint limb1="1" limb1anchor="0,190" limb2="2" limb2anchor="0,-100" lowerlimit="-50" upperlimit="0" canbesevered="true"/>
<joint limb1="2" limb1anchor="0,120" limb2="3" limb2anchor="15,-250" lowerlimit="-50" upperlimit="0"/> <joint limb1="2" limb1anchor="0,120" limb2="3" limb2anchor="15,-250" lowerlimit="-50" upperlimit="0" canbesevered="true"/>
<joint limb1="0" limb1anchor="0,0" limb2="4" limb2anchor="0,-190" lowerlimit="-180" upperlimit="-90"/> <joint limb1="0" limb1anchor="0,0" limb2="4" limb2anchor="0,-190" lowerlimit="-180" upperlimit="-90" canbesevered="true"/>
<joint limb1="4" limb1anchor="0,190" limb2="5" limb2anchor="0,-100" lowerlimit="-50" upperlimit="0"/> <joint limb1="4" limb1anchor="0,190" limb2="5" limb2anchor="0,-100" lowerlimit="-50" upperlimit="0" canbesevered="true"/>
<joint limb1="5" limb1anchor="0,120" limb2="6" limb2anchor="15,-250" lowerlimit="-50" upperlimit="0"/> <joint limb1="5" limb1anchor="0,120" limb2="6" limb2anchor="15,-250" lowerlimit="-50" upperlimit="0" canbesevered="true"/>
<joint limb1="0" limb1anchor="-53,-164" limb2="7" limb2anchor="0,-190" lowerlimit="-180" upperlimit="-90"/> <joint limb1="0" limb1anchor="-53,-164" limb2="7" limb2anchor="0,-190" lowerlimit="-180" upperlimit="-90" canbesevered="true"/>
<joint limb1="7" limb1anchor="0,190" limb2="8" limb2anchor="0,-100" lowerlimit="-50" upperlimit="0"/> <joint limb1="7" limb1anchor="0,190" limb2="8" limb2anchor="0,-100" lowerlimit="-50" upperlimit="0" canbesevered="true"/>
<joint limb1="8" limb1anchor="0,120" limb2="9" limb2anchor="15,-250" lowerlimit="-50" upperlimit="0"/> <joint limb1="8" limb1anchor="0,120" limb2="9" limb2anchor="15,-250" lowerlimit="-50" upperlimit="0" canbesevered="true"/>
</ragdoll> </ragdoll>
<ai attackhumans="100.0" attackrooms="50.0"
attackweaker="50.0" attackstronger="-30.0"
attackcooldown="15.0"
sight="0.5" hearing="1.0"/>
</Character> </Character>
@@ -5,12 +5,27 @@
<sound file="Content/Characters/Scorpion/scorpionidle1.ogg" state="None" /> <sound file="Content/Characters/Scorpion/scorpionidle1.ogg" state="None" />
<sound file="Content/Characters/Scorpion/scorpionidle2.ogg" state="None" /> <sound file="Content/Characters/Scorpion/scorpionidle2.ogg" state="None" />
<ragdoll waveamplitude="50.0" wavelength="2500" swimspeed="4.0" walkspeed="3.5" canentersubmarine="false"> <ai
combatstrength="400"
attackpriorityhumans="100.0"
attackpriorityrooms="50.0"
attackpriorityweaker="50"
attackprioritystronger="-30"
eatpriority="55"
sight="0.5"
hearing="1.0"/>
<ragdoll waveamplitude="50.0"
wavelength="2500"
steertorque="100"
swimspeed="4.0"
swimspeedmultiplier="1.5"
canentersubmarine="false">
<collider radius="50" height="320"/> <collider radius="50" height="320"/>
<!-- head --> <!-- head -->
<limb id = "0" radius="12" height="100" type="Head" steerforce="1.0"> <limb id = "0" radius="12" height="100" type="Head" steerforce="1.0" mouthpos="20,0">
<sprite texture="Content/Characters/Tigerthresher/tigerthresher.png" sourcerect="371,15,66,136" depth="0.02" origin ="0.5,0.5"/> <sprite texture="Content/Characters/Tigerthresher/tigerthresher.png" sourcerect="371,15,66,136" depth="0.02" origin ="0.5,0.5"/>
<damagedsprite texture="Content/Characters/Tigerthresher/damagedtigerthresher.png" sourcerect="371,15,66,136" origin ="0.5,0.5"/> <damagedsprite texture="Content/Characters/Tigerthresher/damagedtigerthresher.png" sourcerect="371,15,66,136" origin ="0.5,0.5"/>
</limb> </limb>
@@ -19,7 +34,7 @@
<limb id = "1" width="16" height="103"> <limb id = "1" width="16" height="103">
<sprite texture="Content/Characters/Tigerthresher/tigerthresher.png" sourcerect="391,169,28,110" depth="0.025" origin="0.5,0.5"/> <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"/> <damagedsprite texture="Content/Characters/Tigerthresher/damagedtigerthresher.png" sourcerect="391,169,28,110" origin="0.5,0.5"/>
<attack range="300" duration="0.5" damage="150" bleedingdamage="10" structuredamage="200" damagetype="slash" force="10" torque="80" targetforce="-50"/> <attack range="300" duration="0.5" damage="150" bleedingdamage="10" structuredamage="200" damagetype="slash" force="80" torque="80" targetforce="-50" severlimbsprobability="0.8"/>
</limb> </limb>
<!-- body --> <!-- body -->
@@ -67,10 +82,8 @@
<joint limb1="2" limb1anchor="5,-30" limb2="5" limb2anchor="7,57" lowerlimit="-50" upperlimit="0"/> <joint limb1="2" limb1anchor="5,-30" limb2="5" limb2anchor="7,57" lowerlimit="-50" upperlimit="0"/>
<!-- body to long --> <!-- body to long -->
<joint limb1="2" limb1anchor="-5,-137" limb2="6" limb2anchor="-8,132" lowerlimit="-30" upperlimit="0"/> <joint limb1="2" limb1anchor="-5,-137" limb2="6" limb2anchor="-8,132" lowerlimit="-30" upperlimit="0"/>
</ragdoll> </ragdoll>
<ai attackhumans="100.0" attackrooms="50.0" attackweaker="50" attackstronger="-30" sight="0.5" hearing="1.0"/>
</Character> </Character>
@@ -12,6 +12,14 @@
<sound file="Content/Characters/Watcher/watch5.ogg" state="None" range="500"/> <sound file="Content/Characters/Watcher/watch5.ogg" state="None" range="500"/>
<sound file="Content/Characters/Watcher/watch6.ogg" state="None" range="500"/> <sound file="Content/Characters/Watcher/watch6.ogg" state="None" range="500"/>
<ai
attackpriorityhumans="0.0"
attackpriorityrooms="0.0"
combatstrength="1000"
attackwhenprovoked="true"
sight="1.0"
hearing="0.0" />
<ragdoll waveamplitude="0.0" swimspeed="0.5" walkspeed="0.3" mirror="true" rotatetowardsmovement="false" headangle="-90"> <ragdoll waveamplitude="0.0" swimspeed="0.5" walkspeed="0.3" mirror="true" rotatetowardsmovement="false" headangle="-90">
<collider radius="100"/> <collider radius="100"/>
@@ -19,7 +27,7 @@
<!-- head --> <!-- head -->
<limb id = "0" type="Head" width="350" height="320" steerforce="1.0" flip="true" armorsector="0.0,360.0" armorvalue="100.0"> <limb id = "0" type="Head" width="350" height="320" 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"/> <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.05" damage="200" stun="5" force="20" damagetype="blunt" targetforce="100"/> <attack range="250" duration="0.05" damage="200" stun="5" force="20" damagetype="blunt" targetforce="100"/>
</limb> </limb>
<limb id = "1" radius="50" height="120" flip="true"> <limb id = "1" radius="50" height="120" flip="true">
@@ -36,6 +44,4 @@
<joint limb1="0" limb1anchor="60,130" limb2="1" limb2anchor="-30,100" lowerlimit="70" upperlimit="80"/> <joint limb1="0" limb1anchor="60,130" limb2="1" limb2anchor="-30,100" lowerlimit="70" upperlimit="80"/>
<joint limb1="0" limb1anchor="72,110" limb2="2" limb2anchor="120,-20" lowerlimit="90" upperlimit="180"/> <joint limb1="0" limb1anchor="72,110" limb2="2" limb2anchor="120,-20" lowerlimit="90" upperlimit="180"/>
</ragdoll> </ragdoll>
<ai attackhumans="0.0" attackrooms="0.0" sight="1.0" hearing="0.0" attackwhenprovoked="true"/>
</Character> </Character>
@@ -13,7 +13,7 @@
<Pickable slots="Any"> <Pickable slots="Any">
<StatusEffect type="OnBroken" target="This" Condition="-100.0" sound="Content/Items/Reactor/explosion.ogg"> <StatusEffect type="OnBroken" target="This" Condition="-100.0" sound="Content/Items/Reactor/explosion.ogg">
<Explosion range="500.0" structuredamage="250" damage="200" stun="5" force="20.0"/> <Explosion range="500.0" structuredamage="250" damage="200" stun="5" force="20.0" severlimbsprobability="0.5"/>
</StatusEffect> </StatusEffect>
</Pickable> </Pickable>
</Item> </Item>
@@ -31,7 +31,7 @@
<Pickable slots="Any"> <Pickable slots="Any">
<StatusEffect type="OnFire" target="This" Condition="-50.0"/> <StatusEffect type="OnFire" target="This" Condition="-50.0"/>
<StatusEffect type="OnBroken" target="This" Condition="-100.0" sound="Content/Items/Reactor/explosion.ogg"> <StatusEffect type="OnBroken" target="This" Condition="-100.0" sound="Content/Items/Reactor/explosion.ogg">
<Explosion range="600.0" structuredamage="150" damage="300" stun="5" force="20.0"/> <Explosion range="600.0" structuredamage="150" damage="300" stun="5" force="20.0" severlimbsprobability="0.6"/>
</StatusEffect> </StatusEffect>
</Pickable> </Pickable>
</Item> </Item>
@@ -50,7 +50,7 @@
<StatusEffect type="Always" target="This" Condition="-0.35"/> <StatusEffect type="Always" target="This" Condition="-0.35"/>
<StatusEffect type="OnFire" target="This" Condition="-50.0"/> <StatusEffect type="OnFire" target="This" Condition="-50.0"/>
<StatusEffect type="OnBroken" target="This" Condition="-100.0" sound="Content/Items/Reactor/explosion.ogg"> <StatusEffect type="OnBroken" target="This" Condition="-100.0" sound="Content/Items/Reactor/explosion.ogg">
<Explosion range="600.0" structuredamage="150" damage="300" stun="5" force="20.0"/> <Explosion range="600.0" structuredamage="150" damage="300" stun="5" force="20.0" severlimbsprobability="0.6"/>
</StatusEffect> </StatusEffect>
</Pickable> </Pickable>
</Item> </Item>
@@ -69,7 +69,7 @@
<Pickable slots="Any"> <Pickable slots="Any">
<StatusEffect type="OnFire" target="This" Condition="-50.0"/> <StatusEffect type="OnFire" target="This" Condition="-50.0"/>
<StatusEffect type="OnBroken" target="This" Condition="-100.0" sound="Content/Items/Reactor/explosion.ogg"> <StatusEffect type="OnBroken" target="This" Condition="-100.0" sound="Content/Items/Reactor/explosion.ogg">
<Explosion range="500.0" structuredamage="50" damage="300" stun="5" force="20.0"/> <Explosion range="500.0" structuredamage="50" damage="300" stun="5" force="20.0" severlimbsprobability="0.6"/>
<Fire size="500"/> <Fire size="500"/>
</StatusEffect> </StatusEffect>
</Pickable> </Pickable>
@@ -121,7 +121,7 @@
<StatusEffect type="OnFire" target="This" Condition="-50.0"/> <StatusEffect type="OnFire" target="This" Condition="-50.0"/>
<StatusEffect type="OnBroken" target="This" Condition="-100.0" sound="Content/Items/Reactor/explosion.ogg"> <StatusEffect type="OnBroken" target="This" Condition="-100.0" sound="Content/Items/Reactor/explosion.ogg">
<Explosion range="600.0" structuredamage="400" damage="300" stun="5" force="20.0"/> <Explosion range="600.0" structuredamage="400" damage="300" stun="5" force="20.0" severlimbsprobability="0.4"/>
</StatusEffect> </StatusEffect>
<StatusEffect type="OnUse" target="This" Condition="-100.0"> <StatusEffect type="OnUse" target="This" Condition="-100.0">
+3 -3
View File
@@ -83,7 +83,7 @@
<Holdable slots="RightHand+LeftHand" holdpos="0,-50" handle1="-10,0" handle2="10,0" aimable="false"/> <Holdable slots="RightHand+LeftHand" holdpos="0,-50" handle1="-10,0" handle2="10,0" aimable="false"/>
<Projectile launchimpulse="80.0"> <Projectile launchimpulse="80.0">
<Attack damage="100" bleedingdamage="10" structuredamage="200" damagetype="Blunt"/> <Attack damage="100" bleedingdamage="10" structuredamage="200" damagetype="Blunt" severlimbsprobability="1.0"/>
<StatusEffect type="OnActive" target="This"> <StatusEffect type="OnActive" target="This">
<ParticleEmitter particle="bubbles" anglemin="0" anglemax="360" particleamount="10" velocitymin="0" velocitymax="50" scalemin="2" scalemax="5"/> <ParticleEmitter particle="bubbles" anglemin="0" anglemax="360" particleamount="10" velocitymin="0" velocitymax="50" scalemin="2" scalemax="5"/>
@@ -115,10 +115,10 @@
<Holdable slots="RightHand+LeftHand" holdpos="0,-50" handle1="-10,0" handle2="10,0" aimable="false"/> <Holdable slots="RightHand+LeftHand" holdpos="0,-50" handle1="-10,0" handle2="10,0" aimable="false"/>
<Projectile launchimpulse="80.0"> <Projectile launchimpulse="80.0">
<Attack damage="1000" bleedingdamage="10" structuredamage="200" damagetype="Blunt"/> <Attack damage="1000" bleedingdamage="10" structuredamage="200" damagetype="Blunt" severlimbsprobability="1.0"/>
<StatusEffect type="OnUse" Condition="-100.0" stun="10.0" disabledeltatime="true" sound="Content/Items/Weapons/bigexplosion.ogg"> <StatusEffect type="OnUse" Condition="-100.0" stun="10.0" disabledeltatime="true" sound="Content/Items/Weapons/bigexplosion.ogg">
<Explosion range="1000.0" structuredamage="1000" damage="1000" stun="10" force="50.0"/> <Explosion range="1000.0" structuredamage="1000" damage="1000" stun="10" force="50.0" severlimbsprobability="0.8"/>
</StatusEffect> </StatusEffect>
<StatusEffect type="OnActive" target="This"> <StatusEffect type="OnActive" target="This">
@@ -57,31 +57,29 @@
</bubbles> </bubbles>
<blood <blood
startsizemin="0.05,0.05" startsizemax="0.6,0.6" startsizemin="0.5,0.5" startsizemax="1.0,1.0"
sizechangemin="0.3,0.2" sizechangemax="0.4,0.2"
startrotationmin ="0.0" startrotationmax="360" startrotationmin ="0.0" startrotationmax="360"
startcolor="0.5, 0.0, 0.0" startalpha="1.0" startcolor="0.5, 0.0, 0.0" startalpha="1.0"
colorchange="0.0, 0.0, 0.0, -1.0" lifetime="1"
lifetime="2"
growtime ="0.1" growtime ="0.1"
deleteoncollision="true" velocitychange="0.0, -0.1">
rotatetodirection="true" <animatedsprite texture="Content/Particles/Spatter1.png" sourcerect="0,0,1024,1024" columns="4" rows="8" origin="0.2,0.5"/>
velocitychange="0.0, -9.8"> <animatedsprite texture="Content/Particles/Spatter2.png" sourcerect="0,0,1024,1024" columns="4" rows="8" origin="0.5,0.5"/>
<sprite texture="Content/Particles/spatter.png" sourcerect="0,0,128,128"/> <animatedsprite texture="Content/Particles/Spatter3.png" sourcerect="0,0,1024,1024" columns="4" rows="8" origin="0.3,0.5"/>
<sprite texture="Content/Particles/spatter.png" sourcerect="128,0,128,128"/>
<sprite texture="Content/Particles/spatter.png" sourcerect="0,128,128,128"/>
</blood> </blood>
<waterblood <waterblood
startsize="0.05,0.05" startsizemin="0.1,0.1" startsizemax="0.3,0.3"
sizechangemin="0.1,0.1" sizechangemax="0.15,0.15" sizechangemin="0.1,0.1" sizechangemax="0.2,0.2"
startrotationmin ="0.0" startrotationmax="360" startrotationmin ="0.0" startrotationmax="360"
startcolor="0.5, 0.0, 0.0" startalpha="1.0" startcolor="0.3, 0.0, 0.0" startalpha="1.0"
colorchange="0.0, 0.0, 0.0, -0.25" animduration="5"
colorchange="0.0, 0.0, 0.0, -0.2"
growtime ="0.1"
lifetime="5.0" lifetime="5.0"
drawtarget="water" drawtarget="water"
velocitychange="0.0, 0.0"> velocitychange="0.0, 0.0">
<sprite texture="Content/Particles/spatter.png" sourcerect="128,128,128,128"/> <animatedsprite texture="Content/Particles/Smoke.png" sourcerect="0,0,4096,4096" columns="8" rows="8" origin="0.5,0.5"/>
</waterblood> </waterblood>
<spark <spark
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 750 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

+5 -3
View File
@@ -2,9 +2,10 @@
<Randomevents> <Randomevents>
<MonsterEvent name="Under attack" description="" <MonsterEvent name="Under attack" description=""
characterfile="Content/Characters/Crawler/crawler.xml" characterfile="Content/Characters/Crawler/crawler.xml"
commonness="10" commonness="15"
difficulty="10" difficulty="10"
minamount="2" maxamount="3" minamount="2" maxamount="3"
repeat="true"
spawntype="mainpath,cave,ruin" spawntype="mainpath,cave,ruin"
musictype="monster"/> musictype="monster"/>
@@ -20,13 +21,14 @@
characterfile="Content/Characters/Moloch/moloch.xml" characterfile="Content/Characters/Moloch/moloch.xml"
commonness="10" commonness="10"
difficulty="30" difficulty="30"
spawntype="mainpath" spawntype="mainpath"
musictype="monster"/> musictype="monster"/>
<MonsterEvent name="Under attack" description="" <MonsterEvent name="Under attack" description=""
characterfile="Content/Characters/Mantis/mantis.xml" characterfile="Content/Characters/Mantis/mantis.xml"
commonness="10" commonness="10"
difficulty="15" difficulty="15"
repeat="true"
minamount="1" maxamount="2" minamount="1" maxamount="2"
spawntype="mainpath,cave,ruin" spawntype="mainpath,cave,ruin"
musictype="monster"/> musictype="monster"/>
@@ -70,7 +72,7 @@
commonness="5" commonness="5"
difficulty="10" difficulty="10"
minamount="2" maxamount="3" minamount="2" maxamount="3"
repeat="true"
spawntype="mainpath,cave,ruin" spawntype="mainpath,cave,ruin"
musictype="monster"/> musictype="monster"/>
@@ -6,15 +6,13 @@ namespace Barotrauma
{ {
class AIController : ISteerable class AIController : ISteerable
{ {
public enum AIState { None, Attack, GoTo, Escape, Eat }
public enum AiState { None, Attack, GoTo, Escape }
public enum SteeringState { Wander, Seek, Escape }
public bool Enabled; public bool Enabled;
public readonly Character Character; public readonly Character Character;
protected AiState state; protected AIState state;
protected SteeringManager steeringManager; protected SteeringManager steeringManager;
@@ -44,7 +42,7 @@ namespace Barotrauma
get { return Character.AnimController.Collider.LinearVelocity; } get { return Character.AnimController.Collider.LinearVelocity; }
} }
public AiState State public AIState State
{ {
get { return state; } get { return state; }
set { state = value; } set { state = value; }
+6 -1
View File
@@ -11,7 +11,11 @@ namespace Barotrauma
public static List<AITarget> List = new List<AITarget>(); public static List<AITarget> List = new List<AITarget>();
public readonly Entity Entity; public Entity Entity
{
get;
private set;
}
private float soundRange; private float soundRange;
private float sightRange; private float sightRange;
@@ -47,6 +51,7 @@ namespace Barotrauma
public void Remove() public void Remove()
{ {
List.Remove(this); List.Remove(this);
Entity = null;
} }
public void Draw(SpriteBatch spriteBatch) public void Draw(SpriteBatch spriteBatch)
@@ -1,9 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Xml.Linq; using System.Xml.Linq;
using FarseerPhysics; using FarseerPhysics;
using Lidgren.Network;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using FarseerPhysics.Dynamics; using FarseerPhysics.Dynamics;
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Graphics;
@@ -23,21 +21,22 @@ namespace Barotrauma
//0.0 = doesn't attack targets of the type //0.0 = doesn't attack targets of the type
//positive values = attacks targets of this type //positive values = attacks targets of this type
//negative values = escapes targets of this type //negative values = escapes targets of this type
private float attackRooms, attackHumans, attackWeaker, attackStronger; private float attackRooms, attackHumans, attackWeaker, attackStronger, eatDeadPriority;
//determines which characters are considered weaker/stronger
private float combatStrength;
private SteeringManager outsideSteering, insideSteering; private SteeringManager outsideSteering, insideSteering;
private float updateTargetsTimer; private float updateTargetsTimer;
private float raycastTimer; private float raycastTimer;
//a timer for attacks such as biting that last for a specific amount of time
//the duration is determined by the attackDuration of the attacking limb
private float attackTimer;
//a "cooldown time" after an attack during which the Character doesn't try to attack again //a "cooldown time" after an attack during which the Character doesn't try to attack again
private float attackCoolDown; private float attackCoolDown;
private float coolDownTimer; private float coolDownTimer;
private bool attachToWalls;
//a point in a wall which the Character is currently targeting //a point in a wall which the Character is currently targeting
private Vector2 wallAttackPos; private Vector2 wallAttackPos;
@@ -46,10 +45,15 @@ namespace Barotrauma
//the limb selected for the current attack //the limb selected for the current attack
private Limb attackingLimb; private Limb attackingLimb;
//flee when the health is below this value
private float fleeHealthThreshold;
private AITarget selectedAiTarget; private AITarget selectedAiTarget;
private AITargetMemory selectedTargetMemory; private AITargetMemory selectedTargetMemory;
private float targetValue; private float targetValue;
private float eatTimer;
private Dictionary<AITarget, AITargetMemory> targetMemories; private Dictionary<AITarget, AITargetMemory> targetMemories;
@@ -73,10 +77,13 @@ namespace Barotrauma
XElement aiElement = doc.Root.Element("ai"); XElement aiElement = doc.Root.Element("ai");
if (aiElement == null) return; if (aiElement == null) return;
attackRooms = ToolBox.GetAttributeFloat(aiElement, "attackrooms", 0.0f) / 100.0f; attackRooms = ToolBox.GetAttributeFloat(aiElement, 0.0f, "attackrooms", "attackpriorityrooms") / 100.0f;
attackHumans = ToolBox.GetAttributeFloat(aiElement, "attackhumans", 0.0f) / 100.0f; attackHumans = ToolBox.GetAttributeFloat(aiElement, 0.0f, "attackhumans", "attackpriorityhumans") / 100.0f;
attackWeaker = ToolBox.GetAttributeFloat(aiElement, "attackweaker", 0.0f) / 100.0f; attackWeaker = ToolBox.GetAttributeFloat(aiElement, 0.0f, "attackweaker", "attackpriorityweaker") / 100.0f;
attackStronger = ToolBox.GetAttributeFloat(aiElement, "attackstronger", 0.0f) / 100.0f; attackStronger = ToolBox.GetAttributeFloat(aiElement, 0.0f, "attackstronger", "attackprioritystronger") / 100.0f;
eatDeadPriority = ToolBox.GetAttributeFloat(aiElement, "eatpriority", 0.0f) / 100.0f;
combatStrength = ToolBox.GetAttributeFloat(aiElement, "combatstrength", 1.0f);
attackCoolDown = ToolBox.GetAttributeFloat(aiElement, "attackcooldown", 5.0f); attackCoolDown = ToolBox.GetAttributeFloat(aiElement, "attackcooldown", 5.0f);
@@ -85,12 +92,16 @@ namespace Barotrauma
attackWhenProvoked = ToolBox.GetAttributeBool(aiElement, "attackwhenprovoked", false); attackWhenProvoked = ToolBox.GetAttributeBool(aiElement, "attackwhenprovoked", false);
fleeHealthThreshold = ToolBox.GetAttributeFloat(aiElement, "fleehealththreshold", 0.0f);
attachToWalls = ToolBox.GetAttributeBool(aiElement, "attachtowalls", false);
outsideSteering = new SteeringManager(this); outsideSteering = new SteeringManager(this);
insideSteering = new IndoorsSteeringManager(this, false); insideSteering = new IndoorsSteeringManager(this, false);
steeringManager = outsideSteering; steeringManager = outsideSteering;
state = AiState.None; state = AIState.None;
} }
public override void SelectTarget(AITarget target) public override void SelectTarget(AITarget target)
@@ -138,54 +149,140 @@ namespace Barotrauma
if (selectedAiTarget == null) if (selectedAiTarget == null)
{ {
state = AiState.None; state = AIState.None;
}
else if ((selectedAiTarget.Entity is Character) && ((Character)selectedAiTarget.Entity).IsDead)
{
if (state != AIState.Eat)
{
eatTimer = 0.0f;
state = AIState.Eat;
}
} }
else else
{ {
state = (targetValue > 0.0f) ? AiState.Attack : AiState.Escape; state = (targetValue < 0.0f || Character.Health < fleeHealthThreshold) ? AIState.Escape : AIState.Attack;
} }
//if (coolDownTimer >= 0.0f) return; //if (coolDownTimer >= 0.0f) return;
} }
steeringManager = Character.Submarine == null ? outsideSteering : insideSteering; steeringManager = Character.Submarine == null ? outsideSteering : insideSteering;
bool run = false;
switch (state) switch (state)
{ {
case AiState.None: case AIState.None:
UpdateNone(deltaTime); UpdateNone(deltaTime);
break; break;
case AiState.Attack: case AIState.Attack:
run = coolDownTimer <= 0.0f;
UpdateAttack(deltaTime); UpdateAttack(deltaTime);
break; break;
case AIState.Eat:
UpdateEating(deltaTime);
break;
case AIState.Escape:
run = true;
UpdateEscape(deltaTime);
break;
default:
throw new NotImplementedException();
} }
steeringManager.Update(); if (run)
}
private void UpdateNone(float deltaTime)
{
//wander around randomly
if (Character.Submarine==null && SimPosition.Y < ConvertUnits.ToSimUnits(SubmarineBody.DamageDepth*0.5f))
{ {
steeringManager.SteeringManual(deltaTime, Vector2.UnitY); steeringManager.Update(Character.AnimController.InWater ?
Character.AnimController.SwimSpeedMultiplier : Character.AnimController.RunSpeedMultiplier);
} }
else else
{ {
steeringManager.SteeringAvoid(deltaTime, 0.1f); steeringManager.Update();
steeringManager.SteeringWander(0.5f); }
}
#region Idle
private void UpdateNone(float deltaTime)
{
attackingLimb = null;
coolDownTimer -= deltaTime;
if (Character.Submarine == null && SimPosition.Y < ConvertUnits.ToSimUnits(SubmarineBody.DamageDepth * 0.5f))
{
//steer straight up if very deep
steeringManager.SteeringManual(deltaTime, Vector2.UnitY);
return;
} }
attackingLimb = null; if (attachToWalls && Character.Submarine == null)
attackTimer = 0.0f; {
raycastTimer -= deltaTime;
//check if there are any walls nearby the character could attach to
if (raycastTimer < 1.0f)
{
wallAttackPos = Vector2.Zero;
coolDownTimer -= deltaTime; var cells = Level.Loaded.GetCells(WorldPosition, 1);
if (cells.Count > 0)
{
Body closestBody = Submarine.CheckVisibility(Character.SimPosition, ConvertUnits.ToSimUnits(cells[0].Center));
if (closestBody != null && closestBody.UserData is Voronoi2.VoronoiCell)
{
wallAttackPos = Submarine.LastPickedPosition;
}
}
raycastTimer = RaycastInterval;
}
}
else
{
wallAttackPos = Vector2.Zero;
}
if (wallAttackPos == Vector2.Zero)
{
//wander around randomly
steeringManager.SteeringAvoid(deltaTime, 0.1f);
steeringManager.SteeringWander(0.5f);
return;
}
float dist = Vector2.Distance(SimPosition, wallAttackPos);
if (dist < Math.Max(Math.Max(Character.AnimController.Collider.radius, Character.AnimController.Collider.width), Character.AnimController.Collider.height) * 1.2f)
{
//close enough to a wall -> attach
Character.AnimController.Collider.MoveToPos(wallAttackPos, 1.0f);
steeringManager.Reset();
}
else
{
//move closer to the wall
steeringManager.SteeringAvoid(deltaTime, 0.1f);
steeringManager.SteeringSeek(wallAttackPos);
}
} }
#endregion
#region Escape
private void UpdateEscape(float deltaTime)
{
SteeringManager.SteeringManual(deltaTime, Vector2.Normalize(SimPosition - selectedAiTarget.SimPosition) * 5);
SteeringManager.SteeringWander(1.0f);
SteeringManager.SteeringAvoid(deltaTime, 2f);
}
#endregion
#region Attack
private void UpdateAttack(float deltaTime) private void UpdateAttack(float deltaTime)
{ {
if (selectedAiTarget == null || selectedAiTarget.Entity == null || selectedAiTarget.Entity.Removed) if (selectedAiTarget == null || selectedAiTarget.Entity == null || selectedAiTarget.Entity.Removed)
{ {
state = AiState.None; state = AIState.None;
return; return;
} }
@@ -198,7 +295,22 @@ namespace Barotrauma
if (selectedAiTarget.Entity != null && Character.Submarine == null && selectedAiTarget.Entity.Submarine != null) attackSimPosition += ConvertUnits.ToSimUnits(selectedAiTarget.Entity.Submarine.Position); if (selectedAiTarget.Entity != null && Character.Submarine == null && selectedAiTarget.Entity.Submarine != null) attackSimPosition += ConvertUnits.ToSimUnits(selectedAiTarget.Entity.Submarine.Position);
} }
else if (selectedAiTarget.Entity is Character)
{
//target the closest limb if the target is a character
float closestDist = Vector2.DistanceSquared(selectedAiTarget.SimPosition, SimPosition);
foreach (Limb limb in ((Character)selectedAiTarget.Entity).AnimController.Limbs)
{
if (limb == null) continue;
float dist = Vector2.DistanceSquared(limb.SimPosition, SimPosition);
if (dist < closestDist)
{
closestDist = dist;
attackSimPosition = limb.SimPosition;
}
}
}
if (Math.Abs(Character.AnimController.movement.X) > 0.1f && !Character.AnimController.InWater) if (Math.Abs(Character.AnimController.movement.X) > 0.1f && !Character.AnimController.InWater)
{ {
Character.AnimController.TargetDir = Character.SimPosition.X < attackSimPosition.X ? Direction.Right : Direction.Left; Character.AnimController.TargetDir = Character.SimPosition.X < attackSimPosition.X ? Direction.Right : Direction.Left;
@@ -229,13 +341,13 @@ namespace Barotrauma
{ {
foreach (Limb limb in Character.AnimController.Limbs) foreach (Limb limb in Character.AnimController.Limbs)
{ {
if (limb.attack==null) continue; if (limb.attack == null) continue;
attackLimb = limb; attackLimb = limb;
if (ConvertUnits.ToDisplayUnits(Vector2.Distance(limb.SimPosition, attackSimPosition)) > limb.attack.Range) continue; if (ConvertUnits.ToDisplayUnits(Vector2.Distance(limb.SimPosition, attackSimPosition)) > limb.attack.Range) continue;
attackingLimb = limb; attackingLimb = limb;
break; break;
} }
if (Character.IsRemotePlayer) if (Character.IsRemotePlayer)
@@ -245,36 +357,18 @@ namespace Barotrauma
} }
if (attackLimb != null) if (attackLimb != null)
{ {
steeringManager.SteeringSeek(attackSimPosition - (attackLimb.SimPosition - SimPosition)); steeringManager.SteeringSeek(attackSimPosition - (attackLimb.SimPosition - SimPosition), 3);
if (steeringManager is IndoorsSteeringManager) if (steeringManager is IndoorsSteeringManager)
{ {
var indoorsSteering = (IndoorsSteeringManager)steeringManager; var indoorsSteering = (IndoorsSteeringManager)steeringManager;
if (indoorsSteering.CurrentPath!=null && (indoorsSteering.CurrentPath.Finished || indoorsSteering.CurrentPath.Unreachable)) if (indoorsSteering.CurrentPath != null && (indoorsSteering.CurrentPath.Finished || indoorsSteering.CurrentPath.Unreachable))
{ {
steeringManager.SteeringManual(deltaTime, attackSimPosition - attackLimb.SimPosition); steeringManager.SteeringManual(deltaTime, attackSimPosition - attackLimb.SimPosition);
} }
} }
if (attackingLimb != null) UpdateLimbAttack(deltaTime, attackingLimb, attackSimPosition); if (attackingLimb != null) UpdateLimbAttack(deltaTime, attackingLimb, attackSimPosition);
}
}
private void UpdateCoolDown(Vector2 attackPosition, float deltaTime)
{
coolDownTimer -= deltaTime;
attackingLimb = null;
if (selectedAiTarget.Entity is Hull ||
Vector2.Distance(attackPosition, Character.AnimController.Limbs[0].SimPosition) < ConvertUnits.ToSimUnits(500.0f))
{
steeringManager.SteeringSeek(attackPosition, -0.8f);
steeringManager.SteeringAvoid(deltaTime, 1.0f);
}
else
{
steeringManager.SteeringSeek(attackPosition, -0.5f);
steeringManager.SteeringAvoid(deltaTime, 1.0f);
} }
} }
@@ -339,13 +433,16 @@ namespace Barotrauma
updateTargetsTimer = Math.Min(updateTargetsTimer, 0.1f); updateTargetsTimer = Math.Min(updateTargetsTimer, 0.1f);
coolDownTimer *= 0.1f; coolDownTimer *= 0.1f;
if (amount > 0.1f && attackWhenProvoked) if (amount > 0.0f && attackWhenProvoked)
{ {
attackHumans = 100.0f; if (!(attacker is AICharacter) || (((AICharacter)attacker).AIController is HumanAIController))
attackRooms = 100.0f; {
attackHumans = 100.0f;
attackRooms = 100.0f;
}
} }
if (attacker==null || attacker.AiTarget==null) return; if (attacker == null || attacker.AiTarget == null) return;
AITargetMemory targetMemory = FindTargetMemory(attacker.AiTarget); AITargetMemory targetMemory = FindTargetMemory(attacker.AiTarget);
targetMemory.Priority += amount; targetMemory.Priority += amount;
} }
@@ -363,7 +460,112 @@ namespace Barotrauma
coolDownTimer = attackCoolDown; coolDownTimer = attackCoolDown;
} }
} }
private void UpdateCoolDown(Vector2 attackPosition, float deltaTime)
{
coolDownTimer -= deltaTime;
attackingLimb = null;
float dist = Vector2.Distance(attackPosition, Character.SimPosition);
if (dist < ConvertUnits.ToSimUnits(500.0f))
{
steeringManager.SteeringSeek(attackPosition, -0.8f);
steeringManager.SteeringManual(deltaTime, Vector2.Normalize(Character.SimPosition - attackPosition) * (1.0f - (dist / 500.0f)));
}
steeringManager.SteeringAvoid(deltaTime, 1.0f);
}
#endregion
#region Eat
private void UpdateEating(float deltaTime)
{
if (selectedAiTarget == null || selectedAiTarget.Entity == null || selectedAiTarget.Entity.Removed)
{
state = AIState.None;
return;
}
Limb mouthLimb = Array.Find(Character.AnimController.Limbs, l => l != null && l.MouthPos.HasValue);
if (mouthLimb == null) mouthLimb = Character.AnimController.GetLimb(LimbType.Head);
if (mouthLimb == null)
{
DebugConsole.ThrowError("Character \"" + Character.SpeciesName + "\" failed to eat a target (a head or a limb with a mouthpos required)");
state = AIState.None;
return;
}
Character targetCharacter = selectedAiTarget.Entity as Character;
float eatSpeed = Character.Mass / targetCharacter.Mass * 0.1f;
eatTimer += deltaTime * eatSpeed;
Vector2 mouthPos = mouthLimb.SimPosition;
if (mouthLimb.MouthPos.HasValue)
{
float cos = (float)Math.Cos(mouthLimb.Rotation);
float sin = (float)Math.Sin(mouthLimb.Rotation);
mouthPos += new Vector2(
mouthLimb.MouthPos.Value.X * cos - mouthLimb.MouthPos.Value.Y * sin,
mouthLimb.MouthPos.Value.X * sin + mouthLimb.MouthPos.Value.Y * cos);
}
Vector2 attackSimPosition = Character.Submarine == null ? ConvertUnits.ToSimUnits(selectedAiTarget.WorldPosition) : selectedAiTarget.SimPosition;
Vector2 limbDiff = attackSimPosition - mouthPos;
float limbDist = limbDiff.Length();
if (limbDist < 1.0f)
{
//pull the target character to the position of the mouth
//(+ make the force fluctuate to waggle the character a bit)
targetCharacter.AnimController.MainLimb.MoveToPos(mouthPos, (float)(Math.Sin(eatTimer) + 10.0f));
//pull the character's mouth to the target character (again with a fluctuating force)
float pullStrength = (float)(Math.Sin(eatTimer) * Math.Max(Math.Sin(eatTimer * 0.5f), 0.0f));
steeringManager.SteeringManual(deltaTime, limbDiff * pullStrength);
mouthLimb.body.ApplyForce(limbDiff * mouthLimb.Mass * 50.0f * pullStrength);
if (eatTimer % 1.0f < 0.5f && (eatTimer - deltaTime * eatSpeed) % 1.0f > 0.5f)
{
//apply damage to the target character to get some blood particles flying
targetCharacter.AnimController.MainLimb.AddDamage(targetCharacter.SimPosition, DamageType.None, Rand.Range(10.0f, 25.0f), 10.0f, false);
//keep severing joints until there is only one limb left
LimbJoint[] nonSeveredJoints = Array.FindAll(targetCharacter.AnimController.LimbJoints, l => !l.IsSevered);
if (nonSeveredJoints.Length == 0)
{
//only one limb left, the character is now full eaten
Entity.Spawner.AddToRemoveQueue(targetCharacter);
selectedAiTarget = null;
state = AIState.None;
}
else //sever a random joint
{
targetCharacter.AnimController.SeverLimbJoint(nonSeveredJoints[Rand.Int(nonSeveredJoints.Length)]);
}
}
}
else if (limbDist < 2.0f)
{
steeringManager.SteeringManual(deltaTime, limbDiff);
Character.AnimController.Collider.ApplyForce(limbDiff * mouthLimb.Mass * 50.0f, mouthPos);
}
else
{
steeringManager.SteeringSeek(attackSimPosition + (mouthPos - SimPosition), 3);
}
}
#endregion
#region Targeting
//goes through all the AItargets, evaluates how preferable it is to attack the target, //goes through all the AItargets, evaluates how preferable it is to attack the target,
//whether the Character can see/hear the target and chooses the most preferable target within //whether the Character can see/hear the target and chooses the most preferable target within
//sight/hearing range //sight/hearing range
@@ -387,33 +589,62 @@ namespace Barotrauma
float valueModifier = 0.0f; float valueModifier = 0.0f;
float dist = 0.0f; float dist = 0.0f;
IDamageable targetDamageable = target.Entity as IDamageable;
if (targetDamageable!=null && targetDamageable.Health <= 0.0f) continue;
Character targetCharacter = target.Entity as Character; Character targetCharacter = target.Entity as Character;
//ignore the aitarget if it is the Character itself //ignore the aitarget if it is the Character itself
if (targetCharacter == character) continue; if (targetCharacter == character) continue;
if (targetCharacter!=null) if (targetCharacter != null)
{ {
if (attackHumans == 0.0f || targetCharacter.SpeciesName != "human") continue; if (targetCharacter.IsDead)
{
valueModifier = attackHumans; if (eatDeadPriority == 0.0f) continue;
valueModifier = eatDeadPriority;
}
else if (targetCharacter.SpeciesName == "human")
{
if (attackHumans == 0.0f) continue;
valueModifier = attackHumans;
}
else
{
EnemyAIController enemy = targetCharacter.AIController as EnemyAIController;
if (enemy != null)
{
if (enemy.combatStrength > combatStrength)
{
valueModifier = attackStronger;
}
else if (enemy.combatStrength < combatStrength)
{
valueModifier = attackWeaker;
}
else
{
continue;
}
}
}
} }
else if (target.Entity!=null && attackRooms != 0.0f) else if (target.Entity!=null && attackRooms != 0.0f)
{ {
IDamageable targetDamageable = target.Entity as IDamageable;
if (targetDamageable != null && targetDamageable.Health <= 0.0f) continue;
//skip the target if it's the room the Character is inside of //skip the target if it's the room the Character is inside of
if (character.AnimController.CurrentHull != null && character.AnimController.CurrentHull == target.Entity as Hull) continue; if (character.AnimController.CurrentHull != null && character.AnimController.CurrentHull == target.Entity as Hull) continue;
valueModifier = attackRooms; valueModifier = attackRooms;
} }
if (valueModifier == 0.0f) continue;
dist = Vector2.Distance(character.WorldPosition, target.WorldPosition); dist = Vector2.Distance(character.WorldPosition, target.WorldPosition);
//if the target has been within range earlier, the character will notice it more easily //if the target has been within range earlier, the character will notice it more easily
//(i.e. remember where the target was) //(i.e. remember where the target was)
if (targetMemories.ContainsKey(target)) dist *= 0.1f; if (targetMemories.ContainsKey(target)) dist *= 0.5f;
//ignore target if it's too far to see or hear //ignore target if it's too far to see or hear
if (dist > target.SightRange * sight && dist > target.SoundRange * hearing) continue; if (dist > target.SightRange * sight && dist > target.SoundRange * hearing) continue;
@@ -433,20 +664,7 @@ namespace Barotrauma
Body closestBody = Submarine.CheckVisibility(rayStart, rayEnd); Body closestBody = Submarine.CheckVisibility(rayStart, rayEnd);
Structure closestStructure = (closestBody == null) ? null : closestBody.UserData as Structure; Structure closestStructure = (closestBody == null) ? null : closestBody.UserData as Structure;
if (targetDamageable != null)
{
valueModifier = valueModifier / targetDamageable.Health;
}
else if (closestStructure!=null)
{
valueModifier = valueModifier / ((IDamageable)closestStructure).Health;
}
else
{
valueModifier = valueModifier / 1000.0f;
}
if (selectedAiTarget == null || Math.Abs(valueModifier) > Math.Abs(targetValue)) if (selectedAiTarget == null || Math.Abs(valueModifier) > Math.Abs(targetValue))
{ {
selectedAiTarget = target; selectedAiTarget = target;
@@ -497,6 +715,8 @@ namespace Barotrauma
} }
} }
#endregion
public override void DebugDraw(SpriteBatch spriteBatch) public override void DebugDraw(SpriteBatch spriteBatch)
{ {
if (Character.IsDead) return; if (Character.IsDead) return;
+1 -1
View File
@@ -51,7 +51,7 @@ namespace Barotrauma
{ {
switch (aiController.State) switch (aiController.State)
{ {
case AIController.AiState.Attack: case AIController.AIState.Attack:
PlaySound(CharacterSound.SoundType.Attack); PlaySound(CharacterSound.SoundType.Attack);
break; break;
default: default:
@@ -12,13 +12,25 @@ namespace Barotrauma
protected Character character; protected Character character;
protected float walkSpeed, swimSpeed; protected float walkSpeed, swimSpeed;
protected float walkPos; protected float walkPos;
protected readonly Vector2 stepSize; protected readonly Vector2 stepSize;
protected readonly float legTorque; protected readonly float legTorque;
public float RunSpeedMultiplier
{
get;
private set;
}
public float SwimSpeedMultiplier
{
get;
private set;
}
public AnimController(Character character, XElement element) public AnimController(Character character, XElement element)
: base(character, element) : base(character, element)
{ {
@@ -30,6 +42,9 @@ namespace Barotrauma
walkSpeed = ToolBox.GetAttributeFloat(element, "walkspeed", 1.0f); walkSpeed = ToolBox.GetAttributeFloat(element, "walkspeed", 1.0f);
swimSpeed = ToolBox.GetAttributeFloat(element, "swimspeed", 1.0f); swimSpeed = ToolBox.GetAttributeFloat(element, "swimspeed", 1.0f);
RunSpeedMultiplier = ToolBox.GetAttributeFloat(element, "runspeedmultiplier", 2f);
SwimSpeedMultiplier = ToolBox.GetAttributeFloat(element, "swimspeedmultiplier", 1.5f);
legTorque = ToolBox.GetAttributeFloat(element, "legtorque", 0.0f); legTorque = ToolBox.GetAttributeFloat(element, "legtorque", 0.0f);
} }
@@ -37,7 +52,7 @@ namespace Barotrauma
public virtual void HoldItem(float deltaTime, Item item, Vector2[] handlePos, Vector2 holdPos, Vector2 aimPos, bool aim, float holdAngle) { } public virtual void HoldItem(float deltaTime, Item item, Vector2[] handlePos, Vector2 holdPos, Vector2 aimPos, bool aim, float holdAngle) { }
public virtual void DragCharacter(Character target, LimbType rightHandTarget = LimbType.RightHand, LimbType leftHandTarget = LimbType.LeftHand) { } public virtual void DragCharacter(Character target) { }
} }
@@ -15,6 +15,8 @@ namespace Barotrauma
private float waveAmplitude; private float waveAmplitude;
private float waveLength; private float waveLength;
private float steerTorque;
private bool rotateTowardsMovement; private bool rotateTowardsMovement;
private bool mirror, flip; private bool mirror, flip;
@@ -23,16 +25,20 @@ namespace Barotrauma
private float? footRotation; private float? footRotation;
private float deathAnimTimer, deathAnimDuration = 5.0f;
public FishAnimController(Character character, XElement element) public FishAnimController(Character character, XElement element)
: base(character, element) : base(character, element)
{ {
waveAmplitude = ConvertUnits.ToSimUnits(ToolBox.GetAttributeFloat(element, "waveamplitude", 0.0f)); waveAmplitude = ConvertUnits.ToSimUnits(ToolBox.GetAttributeFloat(element, "waveamplitude", 0.0f));
waveLength = ConvertUnits.ToSimUnits(ToolBox.GetAttributeFloat(element, "wavelength", 0.0f)); waveLength = ConvertUnits.ToSimUnits(ToolBox.GetAttributeFloat(element, "wavelength", 0.0f));
steerTorque = ToolBox.GetAttributeFloat(element, "steertorque", 25.0f);
flip = ToolBox.GetAttributeBool(element, "flip", true); flip = ToolBox.GetAttributeBool(element, "flip", true);
mirror = ToolBox.GetAttributeBool(element, "mirror", false); mirror = ToolBox.GetAttributeBool(element, "mirror", false);
float footRot = ToolBox.GetAttributeFloat(element,"footrotation", float.NaN); float footRot = ToolBox.GetAttributeFloat(element, "footrotation", float.NaN);
if (float.IsNaN(footRot)) if (float.IsNaN(footRot))
{ {
footRotation = null; footRotation = null;
@@ -63,6 +69,12 @@ namespace Barotrauma
Collider.LinearVelocity = (MainLimb.SimPosition - Collider.SimPosition) * 60.0f; Collider.LinearVelocity = (MainLimb.SimPosition - Collider.SimPosition) * 60.0f;
Collider.SmoothRotate(MainLimb.Rotation); Collider.SmoothRotate(MainLimb.Rotation);
} }
if (character.IsDead && deathAnimTimer < deathAnimDuration)
{
deathAnimTimer += deltaTime;
UpdateDying(deltaTime);
}
return; return;
} }
@@ -176,12 +188,12 @@ namespace Barotrauma
if (rotateTowardsMovement) if (rotateTowardsMovement)
{ {
Collider.SmoothRotate(movementAngle, 25.0f); Collider.SmoothRotate(movementAngle, 25.0f);
MainLimb.body.SmoothRotate(movementAngle, 25.0f); MainLimb.body.SmoothRotate(movementAngle, steerTorque);
} }
else else
{ {
Collider.SmoothRotate(HeadAngle * Dir, 25.0f); Collider.SmoothRotate(HeadAngle * Dir, 25.0f);
MainLimb.body.SmoothRotate(HeadAngle * Dir, 25.0f); MainLimb.body.SmoothRotate(HeadAngle * Dir, steerTorque);
} }
Limb tail = GetLimb(LimbType.Tail); Limb tail = GetLimb(LimbType.Tail);
@@ -260,7 +272,7 @@ namespace Barotrauma
if (limb.RefJointIndex>-1) if (limb.RefJointIndex>-1)
{ {
RevoluteJoint refJoint = limbJoints[limb.RefJointIndex]; RevoluteJoint refJoint = LimbJoints[limb.RefJointIndex];
footPos.X = refJoint.WorldAnchorA.X; footPos.X = refJoint.WorldAnchorA.X;
} }
footPos.X += limb.StepOffset.X * Dir; footPos.X += limb.StepOffset.X * Dir;
@@ -297,8 +309,8 @@ namespace Barotrauma
Limb head = GetLimb(LimbType.Head); Limb head = GetLimb(LimbType.Head);
Limb tail = GetLimb(LimbType.Tail); Limb tail = GetLimb(LimbType.Tail);
if (head != null) head.body.ApplyTorque(head.Mass * Dir * (float)Math.Sin(walkPos) * 5.0f); if (head != null && !head.IsSevered) head.body.ApplyTorque((float)(Math.Sqrt(head.Mass) * Dir * Math.Sin(walkPos)) * 10.0f);
if (tail != null) tail.body.ApplyTorque(tail.Mass * -Dir * (float)Math.Sin(walkPos) * 5.0f); if (tail != null && !tail.IsSevered) tail.body.ApplyTorque((float)(Math.Sqrt(tail.Mass) * -Dir * (float)Math.Sin(walkPos)) * 10.0f);
walkPos += deltaTime * 5.0f; walkPos += deltaTime * 5.0f;
@@ -306,9 +318,9 @@ namespace Barotrauma
foreach (Limb limb in Limbs) foreach (Limb limb in Limbs)
{ {
if (limb.type == LimbType.Head || limb.type == LimbType.Tail) continue; if (limb.type == LimbType.Head || limb.type == LimbType.Tail || limb.IsSevered) continue;
limb.body.ApplyForce((centerOfMass - limb.SimPosition) * (float)Math.Sin(walkPos) * limb.Mass * 10.0f); limb.body.ApplyForce((centerOfMass - limb.SimPosition) * (float)(Math.Sin(walkPos) * Math.Sqrt(limb.Mass)) * 10.0f);
} }
} }
@@ -571,7 +571,6 @@ namespace Barotrauma
} }
float targetSpeed = TargetMovement.Length(); float targetSpeed = TargetMovement.Length();
if (targetSpeed > 0.0f) TargetMovement /= targetSpeed;
if (targetSpeed > 0.1f) if (targetSpeed > 0.1f)
{ {
@@ -633,7 +632,7 @@ namespace Barotrauma
Collider.LinearVelocity = Vector2.Lerp(Collider.LinearVelocity, movement * swimSpeed, movementLerp); Collider.LinearVelocity = Vector2.Lerp(Collider.LinearVelocity, movement * swimSpeed, movementLerp);
} }
walkPos += movement.Length() * 0.15f; walkPos += movement.Length() * 0.2f;
footPos = Collider.SimPosition - new Vector2((float)Math.Sin(-Collider.Rotation), (float)Math.Cos(-Collider.Rotation)) * 0.4f; footPos = Collider.SimPosition - new Vector2((float)Math.Sin(-Collider.Rotation), (float)Math.Cos(-Collider.Rotation)) * 0.4f;
for (int i = -1; i<2; i+=2) for (int i = -1; i<2; i+=2)
@@ -691,7 +690,7 @@ namespace Barotrauma
handPos += head.LinearVelocity * 0.1f; handPos += head.LinearVelocity * 0.1f;
float handCyclePos = walkPos / 3.0f * -Dir; float handCyclePos = walkPos / 2.0f * -Dir;
float handPosX = (float)Math.Cos(handCyclePos) * 0.4f; float handPosX = (float)Math.Cos(handCyclePos) * 0.4f;
float handPosY = (float)Math.Sin(handCyclePos) * 1.0f; float handPosY = (float)Math.Sin(handCyclePos) * 1.0f;
handPosY = MathHelper.Clamp(handPosY, -0.8f, 0.8f); handPosY = MathHelper.Clamp(handPosY, -0.8f, 0.8f);
@@ -883,23 +882,48 @@ namespace Barotrauma
head.pullJoint.WorldAnchorB = new Vector2(targetHead.SimPosition.X, targetHead.SimPosition.Y + 0.6f + yPos); head.pullJoint.WorldAnchorB = new Vector2(targetHead.SimPosition.X, targetHead.SimPosition.Y + 0.6f + yPos);
head.pullJoint.Enabled = true; head.pullJoint.Enabled = true;
} }
public override void DragCharacter(Character target, LimbType rightHandTarget = LimbType.RightHand, LimbType leftHandTarget = LimbType.LeftHand) public override void DragCharacter(Character target)
{ {
if (target == null) return; if (target == null) return;
Limb leftHand = GetLimb(LimbType.LeftHand); Limb leftHand = GetLimb(LimbType.LeftHand);
Limb rightHand = GetLimb(LimbType.RightHand); Limb rightHand = GetLimb(LimbType.RightHand);
Limb targetLeftHand = target.AnimController.GetLimb(LimbType.LeftHand);
Limb targetRightHand = target.AnimController.GetLimb(LimbType.RightHand);
//only grab with one hand when swimming //only grab with one hand when swimming
leftHand.Disabled = true; leftHand.Disabled = true;
if (!inWater) rightHand.Disabled = true; if (!inWater) rightHand.Disabled = true;
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
{ {
LimbType type = i == 0 ? leftHandTarget : rightHandTarget; Limb targetLimb = target.AnimController.GetLimb(LimbType.Torso);
Limb targetLimb = target.AnimController.GetLimb(type);
Limb pullLimb = GetLimb(i == 0 ? LimbType.LeftHand : LimbType.RightHand); if (i == 0)
{
if (!targetLeftHand.IsSevered)
{
targetLimb = targetLeftHand;
}
else if (!targetRightHand.IsSevered)
{
targetLimb = targetRightHand;
}
}
else
{
if (!targetRightHand.IsSevered)
{
targetLimb = targetRightHand;
}
else if (!targetLeftHand.IsSevered)
{
targetLimb = targetLeftHand;
}
}
Limb pullLimb = i == 0 ? leftHand : rightHand;
if (i == 1 && inWater) if (i == 1 && inWater)
{ {
@@ -1013,7 +1037,7 @@ namespace Barotrauma
itemAngle = (torso.body.Rotation + holdAngle * Dir); itemAngle = (torso.body.Rotation + holdAngle * Dir);
} }
Vector2 shoulderPos = limbJoints[2].WorldAnchorA; Vector2 shoulderPos = LimbJoints[2].WorldAnchorA;
Vector2 transformedHoldPos = shoulderPos; Vector2 transformedHoldPos = shoulderPos;
if (itemPos == Vector2.Zero || Anim == Animation.Climbing || usingController) if (itemPos == Vector2.Zero || Anim == Animation.Climbing || usingController)
@@ -1072,7 +1096,7 @@ namespace Barotrauma
private void HandIK(Limb hand, Vector2 pos, float force = 1.0f) private void HandIK(Limb hand, Vector2 pos, float force = 1.0f)
{ {
Vector2 shoulderPos = limbJoints[2].WorldAnchorA; Vector2 shoulderPos = LimbJoints[2].WorldAnchorA;
Limb arm = (hand.type == LimbType.LeftHand) ? GetLimb(LimbType.LeftArm) : GetLimb(LimbType.RightArm); Limb arm = (hand.type == LimbType.LeftHand) ? GetLimb(LimbType.LeftArm) : GetLimb(LimbType.RightArm);
+105 -49
View File
@@ -28,17 +28,13 @@ namespace Barotrauma
if (frozen == value) return; if (frozen == value) return;
frozen = value; frozen = value;
/*foreach (Limb l in Limbs)
{
l.body.PhysEnabled = !frozen;
}*/
Collider.PhysEnabled = !frozen; Collider.PhysEnabled = !frozen;
} }
} }
private Dictionary<LimbType, Limb> limbDictionary; private Dictionary<LimbType, Limb> limbDictionary;
public RevoluteJoint[] limbJoints; public LimbJoint[] LimbJoints;
private bool simplePhysicsEnabled; private bool simplePhysicsEnabled;
@@ -163,18 +159,20 @@ namespace Barotrauma
foreach (Limb limb in Limbs) foreach (Limb limb in Limbs)
{ {
if (limb.IsSevered) continue;
limb.body.Enabled = !simplePhysicsEnabled; limb.body.Enabled = !simplePhysicsEnabled;
} }
foreach (RevoluteJoint joint in limbJoints) foreach (LimbJoint joint in LimbJoints)
{ {
joint.Enabled = !simplePhysicsEnabled; joint.Enabled = !joint.IsSevered && !simplePhysicsEnabled;
} }
if (!simplePhysicsEnabled) if (!simplePhysicsEnabled)
{ {
foreach (Limb limb in Limbs) foreach (Limb limb in Limbs)
{ {
if (limb.IsSevered) continue;
limb.body.SetTransform(Collider.SimPosition, Collider.Rotation); limb.body.SetTransform(Collider.SimPosition, Collider.Rotation);
} }
} }
@@ -278,9 +276,9 @@ namespace Barotrauma
float scale = ToolBox.GetAttributeFloat(element, "scale", 1.0f); float scale = ToolBox.GetAttributeFloat(element, "scale", 1.0f);
Limbs = new Limb[element.Elements("limb").Count()]; Limbs = new Limb[element.Elements("limb").Count()];
limbJoints = new RevoluteJoint[element.Elements("joint").Count()]; LimbJoints = new LimbJoint[element.Elements("joint").Count()];
limbDictionary = new Dictionary<LimbType, Limb>(); limbDictionary = new Dictionary<LimbType, Limb>();
headPosition = ToolBox.GetAttributeFloat(element, "headposition", 50.0f); headPosition = ToolBox.GetAttributeFloat(element, "headposition", 50.0f);
headPosition = ConvertUnits.ToSimUnits(headPosition); headPosition = ConvertUnits.ToSimUnits(headPosition);
@@ -346,7 +344,7 @@ namespace Barotrauma
UpdateCollisionCategories(); UpdateCollisionCategories();
foreach (var joint in limbJoints) foreach (var joint in LimbJoints)
{ {
joint.BodyB.SetTransform( joint.BodyB.SetTransform(
joint.BodyA.Position + (joint.LocalAnchorA - joint.LocalAnchorB)*0.1f, joint.BodyA.Position + (joint.LocalAnchorA - joint.LocalAnchorB)*0.1f,
@@ -385,9 +383,8 @@ namespace Barotrauma
Vector2 limb2Pos = ToolBox.GetAttributeVector2(subElement, "limb2anchor", Vector2.Zero) * scale; Vector2 limb2Pos = ToolBox.GetAttributeVector2(subElement, "limb2anchor", Vector2.Zero) * scale;
limb2Pos = ConvertUnits.ToSimUnits(limb2Pos); limb2Pos = ConvertUnits.ToSimUnits(limb2Pos);
RevoluteJoint joint = new RevoluteJoint(Limbs[limb1ID].body.FarseerBody, Limbs[limb2ID].body.FarseerBody, limb1Pos, limb2Pos); LimbJoint joint = new LimbJoint(Limbs[limb1ID], Limbs[limb2ID], limb1Pos, limb2Pos);
joint.CanBeSevered = ToolBox.GetAttributeBool(subElement, "canbesevered", false);
joint.CollideConnected = false;
if (subElement.Attribute("lowerlimit") != null) if (subElement.Attribute("lowerlimit") != null)
{ {
@@ -396,22 +393,18 @@ namespace Barotrauma
joint.UpperLimit = float.Parse(subElement.Attribute("upperlimit").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); GameMain.World.AddJoint(joint);
for (int i = 0; i < limbJoints.Length; i++) for (int i = 0; i < LimbJoints.Length; i++)
{ {
if (limbJoints[i] != null) continue; if (LimbJoints[i] != null) continue;
limbJoints[i] = joint; LimbJoints[i] = joint;
return; return;
} }
Array.Resize(ref limbJoints, limbJoints.Length + 1); Array.Resize(ref LimbJoints, LimbJoints.Length + 1);
limbJoints[limbJoints.Length - 1] = joint; LimbJoints[LimbJoints.Length - 1] = joint;
} }
public void AddLimb(Limb limb) public void AddLimb(Limb limb)
@@ -509,9 +502,9 @@ namespace Barotrauma
{ {
Limb limb = (Limb)f1.Body.UserData; Limb limb = (Limb)f1.Body.UserData;
if (impact > 3.0f && limb.HitSound != null && limb.soundTimer <= 0.0f) if (impact > 3.0f && limb.HitSound != null && limb.SoundTimer <= 0.0f)
{ {
limb.soundTimer = Limb.SoundInterval; limb.SoundTimer = Limb.SoundInterval;
limb.HitSound.Play(volume, impact * 100.0f, limb.WorldPosition); limb.HitSound.Play(volume, impact * 100.0f, limb.WorldPosition);
} }
} }
@@ -531,6 +524,51 @@ namespace Barotrauma
} }
} }
public void SeverLimbJoint(LimbJoint limbJoint)
{
limbJoint.IsSevered = true;
limbJoint.Enabled = false;
List<Limb> connectedLimbs = new List<Limb>();
List<LimbJoint> checkedJoints = new List<LimbJoint>();
GetConnectedLimbs(connectedLimbs, checkedJoints, MainLimb);
foreach (Limb limb in Limbs)
{
if (!connectedLimbs.Contains(limb))
{
limb.IsSevered = true;
}
}
}
private void GetConnectedLimbs(List<Limb> connectedLimbs, List<LimbJoint> checkedJoints, Limb limb)
{
connectedLimbs.Add(limb);
foreach (LimbJoint joint in LimbJoints)
{
if (joint.IsSevered || checkedJoints.Contains(joint)) continue;
if (joint.LimbA == limb)
{
if (!connectedLimbs.Contains(joint.LimbB))
{
checkedJoints.Add(joint);
GetConnectedLimbs(connectedLimbs, checkedJoints, joint.LimbB);
}
}
else if (joint.LimbB == limb)
{
if (!connectedLimbs.Contains(joint.LimbA))
{
checkedJoints.Add(joint);
GetConnectedLimbs(connectedLimbs, checkedJoints, joint.LimbA);
}
}
}
}
public virtual void Draw(SpriteBatch spriteBatch) public virtual void Draw(SpriteBatch spriteBatch)
{ {
if (simplePhysicsEnabled) return; if (simplePhysicsEnabled) return;
@@ -559,13 +597,15 @@ namespace Barotrauma
GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X, (int)pos.Y, 5, 5), Color.Red, true, 0.01f); GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X, (int)pos.Y, 5, 5), Color.Red, true, 0.01f);
} }
limb.body.DebugDraw(spriteBatch, inWater ? Color.Cyan : Color.White); Color limbColor = inWater ? Color.Cyan : Color.White;
if (limb.IsSevered) limbColor = Color.Red;
limb.body.DebugDraw(spriteBatch, limbColor);
} }
Collider.DebugDraw(spriteBatch, frozen ? Color.Red : (inWater ? Color.SkyBlue : Color.Gray)); Collider.DebugDraw(spriteBatch, frozen ? Color.Red : (inWater ? Color.SkyBlue : Color.Gray));
GUI.Font.DrawString(spriteBatch, Collider.LinearVelocity.X.ToString(), new Vector2(Collider.DrawPosition.X, -Collider.DrawPosition.Y), Color.Orange); GUI.Font.DrawString(spriteBatch, Collider.LinearVelocity.X.ToString(), new Vector2(Collider.DrawPosition.X, -Collider.DrawPosition.Y), Color.Orange);
foreach (RevoluteJoint joint in limbJoints) foreach (RevoluteJoint joint in LimbJoints)
{ {
Vector2 pos = ConvertUnits.ToDisplayUnits(joint.WorldAnchorA); Vector2 pos = ConvertUnits.ToDisplayUnits(joint.WorldAnchorA);
GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X, (int)-pos.Y, 5, 5), Color.White, true); GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X, (int)-pos.Y, 5, 5), Color.White, true);
@@ -619,22 +659,24 @@ namespace Barotrauma
{ {
dir = (dir == Direction.Left) ? Direction.Right : Direction.Left; dir = (dir == Direction.Left) ? Direction.Right : Direction.Left;
for (int i = 0; i < limbJoints.Length; i++) for (int i = 0; i < LimbJoints.Length; i++)
{ {
float lowerLimit = -limbJoints[i].UpperLimit; float lowerLimit = -LimbJoints[i].UpperLimit;
float upperLimit = -limbJoints[i].LowerLimit; float upperLimit = -LimbJoints[i].LowerLimit;
limbJoints[i].LowerLimit = lowerLimit; LimbJoints[i].LowerLimit = lowerLimit;
limbJoints[i].UpperLimit = upperLimit; LimbJoints[i].UpperLimit = upperLimit;
limbJoints[i].LocalAnchorA = new Vector2(-limbJoints[i].LocalAnchorA.X, limbJoints[i].LocalAnchorA.Y); LimbJoints[i].LocalAnchorA = new Vector2(-LimbJoints[i].LocalAnchorA.X, LimbJoints[i].LocalAnchorA.Y);
limbJoints[i].LocalAnchorB = new Vector2(-limbJoints[i].LocalAnchorB.X, limbJoints[i].LocalAnchorB.Y); LimbJoints[i].LocalAnchorB = new Vector2(-LimbJoints[i].LocalAnchorB.X, LimbJoints[i].LocalAnchorB.Y);
} }
foreach (Limb limb in Limbs) foreach (Limb limb in Limbs)
{ {
if (limb == null) continue; if (limb == null || limb.IsSevered) continue;
limb.Dir = Dir;
if (limb.sprite != null) if (limb.sprite != null)
{ {
@@ -643,12 +685,13 @@ namespace Barotrauma
limb.sprite.Origin = spriteOrigin; limb.sprite.Origin = spriteOrigin;
} }
limb.Dir = Dir;
if (limb.MouthPos.HasValue)
/*if (limb.LightSource != null)
{ {
limb.LightSource.FlipX(); limb.MouthPos = new Vector2(
}*/ -limb.MouthPos.Value.X,
limb.MouthPos.Value.Y);
}
if (limb.pullJoint != null) if (limb.pullJoint != null)
{ {
@@ -663,12 +706,15 @@ namespace Barotrauma
public Vector2 GetCenterOfMass() public Vector2 GetCenterOfMass()
{ {
Vector2 centerOfMass = Vector2.Zero; Vector2 centerOfMass = Vector2.Zero;
float totalMass = 0.0f;
foreach (Limb limb in Limbs) foreach (Limb limb in Limbs)
{ {
if (limb.IsSevered) continue;
centerOfMass += limb.Mass * limb.SimPosition; centerOfMass += limb.Mass * limb.SimPosition;
totalMass += limb.Mass;
} }
centerOfMass /= Mass; centerOfMass /= totalMass;
return centerOfMass; return centerOfMass;
} }
@@ -769,6 +815,7 @@ namespace Barotrauma
{ {
foreach (Limb limb in Limbs) foreach (Limb limb in Limbs)
{ {
if (limb.IsSevered) continue;
if (limb.body.FarseerBody.ContactList == null) continue; if (limb.body.FarseerBody.ContactList == null) continue;
ContactEdge ce = limb.body.FarseerBody.ContactList; ContactEdge ce = limb.body.FarseerBody.ContactList;
@@ -781,6 +828,7 @@ namespace Barotrauma
foreach (Limb limb in Limbs) foreach (Limb limb in Limbs)
{ {
if (limb.IsSevered) continue;
limb.body.LinearVelocity += velocityChange; limb.body.LinearVelocity += velocityChange;
} }
@@ -805,7 +853,7 @@ namespace Barotrauma
foreach (Limb limb in Limbs) foreach (Limb limb in Limbs)
{ {
if (limb.ignoreCollisions) continue; if (limb.ignoreCollisions || limb.IsSevered) continue;
try try
{ {
@@ -1145,6 +1193,7 @@ namespace Barotrauma
foreach (Limb limb in Limbs) foreach (Limb limb in Limbs)
{ {
if (limb.IsSevered) continue;
//check visibility from the new position of the collider to the new position of this limb //check visibility from the new position of the collider to the new position of this limb
Vector2 movePos = limb.SimPosition + limbMoveAmount; Vector2 movePos = limb.SimPosition + limbMoveAmount;
@@ -1208,6 +1257,7 @@ namespace Barotrauma
//(in case the ragdoll has gotten stuck somewhere) //(in case the ragdoll has gotten stuck somewhere)
foreach (Limb limb in Limbs) foreach (Limb limb in Limbs)
{ {
if (limb.IsSevered) continue;
limb.body.CollidesWith = Physics.CollisionNone; limb.body.CollidesWith = Physics.CollisionNone;
} }
@@ -1463,22 +1513,28 @@ namespace Barotrauma
public void Remove() public void Remove()
{ {
foreach (Limb l in Limbs) if (Limbs != null)
{ {
l.Remove(); foreach (Limb l in Limbs)
{
l.Remove();
}
Limbs = null;
} }
Limbs = null;
foreach (PhysicsBody b in collider) foreach (PhysicsBody b in collider)
{ {
b.Remove(); b.Remove();
} }
foreach (RevoluteJoint joint in limbJoints) if (LimbJoints != null)
{ {
GameMain.World.RemoveJoint(joint); foreach (RevoluteJoint joint in LimbJoints)
{
GameMain.World.RemoveJoint(joint);
}
LimbJoints = null;
} }
limbJoints = null;
list.Remove(this); list.Remove(this);
} }
+32 -14
View File
@@ -18,7 +18,7 @@ namespace Barotrauma
{ {
public readonly float Damage; public readonly float Damage;
public readonly float Bleeding; public readonly float Bleeding;
public readonly bool HitArmor; public readonly bool HitArmor;
public AttackResult(float damage, float bleeding, bool hitArmor=false) public AttackResult(float damage, float bleeding, bool hitArmor=false)
@@ -49,6 +49,12 @@ namespace Barotrauma
public readonly float TargetForce; public readonly float TargetForce;
public readonly float SeverLimbsProbability;
//the indices of the limbs Force is applied on
//(if none, force is applied only to the limb the attack is attached to)
public readonly List<int> ApplyForceOnLimbs;
private Sound sound; private Sound sound;
private ParticleEmitterPrefab particleEmitterPrefab; private ParticleEmitterPrefab particleEmitterPrefab;
@@ -91,29 +97,41 @@ namespace Barotrauma
DamageType = DamageType.None; DamageType = DamageType.None;
} }
damage = ToolBox.GetAttributeFloat(element, "damage", 0.0f);
damage = ToolBox.GetAttributeFloat(element, "damage", 0.0f);
structureDamage = ToolBox.GetAttributeFloat(element, "structuredamage", 0.0f); structureDamage = ToolBox.GetAttributeFloat(element, "structuredamage", 0.0f);
bleedingDamage = ToolBox.GetAttributeFloat(element, "bleedingdamage", 0.0f); bleedingDamage = ToolBox.GetAttributeFloat(element, "bleedingdamage", 0.0f);
Stun = ToolBox.GetAttributeFloat(element, "stun", 0.0f);
Force = ToolBox.GetAttributeFloat(element,"force", 0.0f); SeverLimbsProbability = ToolBox.GetAttributeFloat(element, "severlimbsprobability", 0.0f);
TargetForce = ToolBox.GetAttributeFloat(element, "targetforce", 0.0f);
Torque = ToolBox.GetAttributeFloat(element, "torque", 0.0f);
Stun = ToolBox.GetAttributeFloat(element, "stun", 0.0f);
Force = ToolBox.GetAttributeFloat(element, "force", 0.0f);
TargetForce = ToolBox.GetAttributeFloat(element, "targetforce", 0.0f);
Torque = ToolBox.GetAttributeFloat(element, "torque", 0.0f);
string soundPath = ToolBox.GetAttributeString(element, "sound", ""); string soundPath = ToolBox.GetAttributeString(element, "sound", "");
if (!string.IsNullOrWhiteSpace(soundPath)) if (!string.IsNullOrWhiteSpace(soundPath))
{ {
sound = Sound.Load(soundPath); sound = Sound.Load(soundPath);
} }
Range = ToolBox.GetAttributeFloat(element, "range", 0.0f); Range = ToolBox.GetAttributeFloat(element, "range", 0.0f);
Duration = ToolBox.GetAttributeFloat(element, "duration", 0.0f);
Duration = ToolBox.GetAttributeFloat(element, "duration", 0.0f); priority = ToolBox.GetAttributeFloat(element, "priority", 1.0f);
priority = ToolBox.GetAttributeFloat(element, "priority", 1.0f); string limbIndicesStr = ToolBox.GetAttributeString(element, "applyforceonlimbs", "");
if (!string.IsNullOrWhiteSpace(limbIndicesStr))
{
ApplyForceOnLimbs = new List<int>();
foreach (string limbIndexStr in limbIndicesStr.Split(','))
{
int limbIndex;
if (int.TryParse(limbIndexStr, out limbIndex))
{
ApplyForceOnLimbs.Add(limbIndex);
}
}
}
foreach (XElement subElement in element.Elements()) foreach (XElement subElement in element.Elements())
{ {
+76 -29
View File
@@ -785,16 +785,14 @@ namespace Barotrauma
if (IsKeyDown(InputType.Run)) if (IsKeyDown(InputType.Run))
{ {
//can't run if //can't run if
// - not a humanoid
// - dragging someone // - dragging someone
// - crouching // - crouching
// - moving backwards // - moving backwards
if (AnimController is HumanoidAnimController && if (selectedCharacter == null &&
selectedCharacter == null && (!(AnimController is HumanoidAnimController) || !((HumanoidAnimController)AnimController).Crouching) &&
!((HumanoidAnimController)AnimController).Crouching &&
Math.Sign(targetMovement.X) != -Math.Sign(AnimController.Dir)) Math.Sign(targetMovement.X) != -Math.Sign(AnimController.Dir))
{ {
targetMovement *= 3.0f; targetMovement *= AnimController.InWater ? AnimController.SwimSpeedMultiplier : AnimController.RunSpeedMultiplier;
} }
} }
@@ -1161,9 +1159,10 @@ namespace Barotrauma
} }
} }
if (moveCam && needsAir) if (moveCam)
{ {
if (pressureProtection < 80.0f && if (needsAir &&
pressureProtection < 80.0f &&
(AnimController.CurrentHull == null || AnimController.CurrentHull.LethalPressure > 50.0f)) (AnimController.CurrentHull == null || AnimController.CurrentHull.LethalPressure > 50.0f))
{ {
float pressure = AnimController.CurrentHull == null ? 100.0f : AnimController.CurrentHull.LethalPressure; float pressure = AnimController.CurrentHull == null ? 100.0f : AnimController.CurrentHull.LethalPressure;
@@ -1172,7 +1171,16 @@ namespace Barotrauma
(pressure / 50.0f) * Rand.Range(1.0f, 1.05f), (pressure / 50.0f) * Rand.Range(1.0f, 1.05f),
(pressure - 50.0f) / 50.0f); (pressure - 50.0f) / 50.0f);
} }
cam.OffsetAmount = MathHelper.Lerp(cam.OffsetAmount, 250.0f, 0.05f);
if (IsHumanoid)
{
cam.OffsetAmount = MathHelper.Lerp(cam.OffsetAmount, 250.0f, deltaTime);
}
else
{
//increased visibility range when controlling large a non-humanoid
cam.OffsetAmount = MathHelper.Lerp(cam.OffsetAmount, MathHelper.Clamp(Mass, 250.0f, 800.0f), deltaTime);
}
} }
cursorPosition = cam.ScreenToWorld(PlayerInput.MousePosition); cursorPosition = cam.ScreenToWorld(PlayerInput.MousePosition);
@@ -1721,46 +1729,77 @@ namespace Barotrauma
public virtual AttackResult AddDamage(IDamageable attacker, Vector2 worldPosition, Attack attack, float deltaTime, bool playSound = false) public virtual AttackResult AddDamage(IDamageable attacker, Vector2 worldPosition, Attack attack, float deltaTime, bool playSound = false)
{ {
var attackResult = AddDamage(worldPosition, attack.DamageType, attack.GetDamage(deltaTime), attack.GetBleedingDamage(deltaTime), attack.Stun, playSound, attack.TargetForce); Limb limbHit = null;
var attackResult = AddDamage(worldPosition, attack.DamageType, attack.GetDamage(deltaTime), attack.GetBleedingDamage(deltaTime), attack.Stun, playSound, attack.TargetForce, out limbHit);
if (limbHit == null) return new AttackResult();
var attackingCharacter = attacker as Character; var attackingCharacter = attacker as Character;
if (attackingCharacter != null && attackingCharacter.AIController == null) if (attackingCharacter != null && attackingCharacter.AIController == null)
{ {
GameServer.Log(Name + " attacked by " + attackingCharacter.Name+". Damage: "+attackResult.Damage+" Bleeding damage: "+attackResult.Bleeding, ServerLog.MessageType.Attack); GameServer.Log(Name + " attacked by " + attackingCharacter.Name+". Damage: "+attackResult.Damage+" Bleeding damage: "+attackResult.Bleeding, ServerLog.MessageType.Attack);
} }
if (GameMain.Client == null &&
isDead &&
health - attackResult.Damage <= minHealth && Rand.Range(0.0f, 1.0f) < attack.SeverLimbsProbability)
{
foreach (LimbJoint joint in AnimController.LimbJoints)
{
if (joint.CanBeSevered && (joint.LimbA == limbHit || joint.LimbB == limbHit))
{
AnimController.SeverLimbJoint(joint);
if (joint.LimbA == limbHit)
{
joint.LimbB.body.LinearVelocity += limbHit.LinearVelocity * 0.5f;
}
else
{
joint.LimbA.body.LinearVelocity += limbHit.LinearVelocity * 0.5f;
}
}
}
}
return attackResult; return attackResult;
} }
public AttackResult AddDamage(Vector2 worldPosition, DamageType damageType, float amount, float bleedingAmount, float stun, bool playSound, float attackForce = 0.0f) public AttackResult AddDamage(Vector2 worldPosition, DamageType damageType, float amount, float bleedingAmount, float stun, bool playSound, float attackForce = 0.0f)
{ {
Limb temp = null;
return AddDamage(worldPosition, damageType, amount, bleedingAmount, stun, playSound, attackForce, out temp);
}
public AttackResult AddDamage(Vector2 worldPosition, DamageType damageType, float amount, float bleedingAmount, float stun, bool playSound, float attackForce, out Limb hitLimb)
{
hitLimb = null;
if (Removed) return new AttackResult(); if (Removed) return new AttackResult();
SetStun(stun); SetStun(stun);
Limb closestLimb = null;
float closestDistance = 0.0f; float closestDistance = 0.0f;
foreach (Limb limb in AnimController.Limbs) foreach (Limb limb in AnimController.Limbs)
{ {
float distance = Vector2.Distance(worldPosition, limb.WorldPosition); float distance = Vector2.Distance(worldPosition, limb.WorldPosition);
if (closestLimb == null || distance < closestDistance) if (hitLimb == null || distance < closestDistance)
{ {
closestLimb = limb; hitLimb = limb;
closestDistance = distance; closestDistance = distance;
} }
} }
if (Math.Abs(attackForce) > 0.0f) if (Math.Abs(attackForce) > 0.0f)
{ {
closestLimb.body.ApplyForce((closestLimb.WorldPosition - worldPosition) * attackForce); Vector2 diff = hitLimb.WorldPosition - worldPosition;
if (diff == Vector2.Zero) diff = Rand.Vector(1.0f);
hitLimb.body.ApplyForce(Vector2.Normalize(diff) * attackForce, hitLimb.SimPosition + ConvertUnits.ToSimUnits(diff));
} }
AttackResult attackResult = closestLimb.AddDamage(worldPosition, damageType, amount, bleedingAmount, playSound); AttackResult attackResult = hitLimb.AddDamage(worldPosition, damageType, amount, bleedingAmount, playSound);
AddDamage(damageType == DamageType.Burn ? CauseOfDeath.Burn : causeOfDeath, attackResult.Damage, null); AddDamage(damageType == DamageType.Burn ? CauseOfDeath.Burn : causeOfDeath, attackResult.Damage, null);
//health -= attackResult.Damage;
//if (health <= 0.0f && damageType == DamageType.Burn) Kill(CauseOfDeath.Burn);
if (DoesBleed) if (DoesBleed)
{ {
Bleeding += attackResult.Bleeding; Bleeding += attackResult.Bleeding;
@@ -1834,7 +1873,7 @@ namespace Barotrauma
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) foreach (var joint in AnimController.LimbJoints)
{ {
joint.LimitEnabled = false; joint.LimitEnabled = false;
} }
@@ -1884,20 +1923,14 @@ namespace Barotrauma
{ {
if (selectedItems[i] != null) selectedItems[i].Drop(this); if (selectedItems[i] != null) selectedItems[i].Drop(this);
} }
if (aiTarget != null)
{
aiTarget.Remove();
aiTarget = null;
}
foreach (Limb limb in AnimController.Limbs) foreach (Limb limb in AnimController.Limbs)
{ {
if (limb.pullJoint == null) continue; if (limb.pullJoint == null) continue;
limb.pullJoint.Enabled = false; limb.pullJoint.Enabled = false;
} }
foreach (RevoluteJoint joint in AnimController.limbJoints) foreach (RevoluteJoint joint in AnimController.LimbJoints)
{ {
joint.MotorEnabled = false; joint.MotorEnabled = false;
} }
@@ -1916,9 +1949,16 @@ namespace Barotrauma
Health = Math.Max(maxHealth * 0.1f, health); Health = Math.Max(maxHealth * 0.1f, health);
foreach (RevoluteJoint joint in AnimController.limbJoints) foreach (LimbJoint joint in AnimController.LimbJoints)
{ {
joint.MotorEnabled = true; joint.MotorEnabled = true;
joint.Enabled = true;
joint.IsSevered = false;
}
foreach (Limb limb in AnimController.Limbs)
{
limb.IsSevered = false;
} }
if (GameMain.GameSession != null) if (GameMain.GameSession != null)
@@ -1929,6 +1969,13 @@ namespace Barotrauma
public override void Remove() public override void Remove()
{ {
#if DEBUG
if (Removed)
{
DebugConsole.ThrowError("Attempting to remove an already removed character\n" + Environment.StackTrace);
}
#endif
base.Remove(); base.Remove();
if (info != null) info.Remove(); if (info != null) info.Remove();
@@ -1939,7 +1986,7 @@ namespace Barotrauma
if (GameMain.Client != null && GameMain.Client.Character == this) GameMain.Client.Character = null; if (GameMain.Client != null && GameMain.Client.Character == this) GameMain.Client.Character = null;
if (aiTarget != null) aiTarget.Remove(); if (aiTarget != null) aiTarget.Remove();
if (AnimController != null) AnimController.Remove(); if (AnimController != null) AnimController.Remove();
@@ -638,6 +638,19 @@ namespace Barotrauma
if (isDead) if (isDead)
{ {
msg.Write((byte)causeOfDeath); msg.Write((byte)causeOfDeath);
List<int> severedJointIndices = new List<int>();
for (int i = 0; i < AnimController.LimbJoints.Length; i++)
{
if (AnimController.LimbJoints[i] != null && AnimController.LimbJoints[i].IsSevered)
{
severedJointIndices.Add(i);
}
}
msg.Write((byte)severedJointIndices.Count);
foreach (int jointIndex in severedJointIndices)
{
msg.Write((byte)jointIndex);
}
} }
else else
{ {
@@ -677,6 +690,7 @@ namespace Barotrauma
if (isDead) if (isDead)
{ {
causeOfDeath = (CauseOfDeath)msg.ReadByte(); causeOfDeath = (CauseOfDeath)msg.ReadByte();
byte severedLimbCount = msg.ReadByte();
if (causeOfDeath == CauseOfDeath.Pressure) if (causeOfDeath == CauseOfDeath.Pressure)
{ {
Implode(true); Implode(true);
@@ -685,6 +699,11 @@ namespace Barotrauma
{ {
Kill(causeOfDeath, true); Kill(causeOfDeath, true);
} }
for (int i = 0; i < severedLimbCount; i++)
{
int severedJointIndex = msg.ReadByte();
AnimController.SeverLimbJoint(AnimController.LimbJoints[severedJointIndex]);
}
} }
else else
{ {
+120 -79
View File
@@ -19,11 +19,33 @@ namespace Barotrauma
LeftLeg, RightLeg, LeftFoot, RightFoot, Head, Torso, Tail, Legs, RightThigh, LeftThigh, Waist LeftLeg, RightLeg, LeftFoot, RightFoot, Head, Torso, Tail, Legs, RightThigh, LeftThigh, Waist
}; };
class LimbJoint : RevoluteJoint
{
public bool IsSevered;
public bool CanBeSevered;
public readonly Limb LimbA, LimbB;
public LimbJoint(Limb limbA, Limb limbB, Vector2 anchor1, Vector2 anchor2)
: base(limbA.body.FarseerBody, limbB.body.FarseerBody, anchor1, anchor2)
{
CollideConnected = false;
MotorEnabled = true;
MaxMotorTorque = 0.25f;
LimbA = limbA;
LimbB = limbB;
}
}
class Limb class Limb
{ {
private const float LimbDensity = 15; private const float LimbDensity = 15;
private const float LimbAngularDamping = 7; private const float LimbAngularDamping = 7;
//how long it takes for severed limbs to fade out
private const float SeveredFadeOutTime = 10.0f;
public readonly Character character; public readonly Character character;
//the physics body of the limb //the physics body of the limb
@@ -51,12 +73,17 @@ namespace Barotrauma
private float damage, burnt; private float damage, burnt;
private bool isSevered;
private float severedFadeOutTimer;
private readonly Vector2 armorSector; private readonly Vector2 armorSector;
private readonly float armorValue; private readonly float armorValue;
Sound hitSound; public Vector2? MouthPos;
private Sound hitSound;
//a timer for delaying when a hitsound/attacksound can be played again //a timer for delaying when a hitsound/attacksound can be played again
public float soundTimer; public float SoundTimer;
public const float SoundInterval = 0.4f; public const float SoundInterval = 0.4f;
public readonly Attack attack; public readonly Attack attack;
@@ -66,7 +93,24 @@ namespace Barotrauma
private List<WearableSprite> wearingItems; private List<WearableSprite> wearingItems;
private Vector2 animTargetPos; private Vector2 animTargetPos;
private float scale;
public float AttackTimer;
public bool IsSevered
{
get { return isSevered; }
set
{
isSevered = value;
if (isSevered)
{
damage = 100.0f;
}
}
}
public bool DoesFlip public bool DoesFlip
{ {
get { return doesFlip; } get { return doesFlip; }
@@ -92,6 +136,11 @@ namespace Barotrauma
get { return body.Rotation; } get { return body.Rotation; }
} }
public float Scale
{
get { return scale; }
}
//where an animcontroller is trying to pull the limb, only used for debug visualization //where an animcontroller is trying to pull the limb, only used for debug visualization
public Vector2 AnimTargetPos public Vector2 AnimTargetPos
{ {
@@ -135,55 +184,23 @@ namespace Barotrauma
{ {
get { return stepOffset; } get { return stepOffset; }
} }
public float Burnt public float Burnt
{ {
get { return burnt; } get { return burnt; }
set { burnt = MathHelper.Clamp(value,0.0f,100.0f); } set { burnt = MathHelper.Clamp(value,0.0f,100.0f); }
} }
private float scale;
public float AttackTimer;
//public float Damage
//{
// get { return damage; }
// set
// {
// damage = Math.Max(value, 0.0f);
// if (damage >=maxHealth) Character.Kill();
// }
//}
//public float MaxHealth
//{
// get { return maxHealth; }
//}
//public float Bleeding
//{
// get { return bleeding; }
// set { bleeding = MathHelper.Clamp(value, 0.0f, 100.0f); }
//}
public List<WearableSprite> WearingItems public List<WearableSprite> WearingItems
{ {
get { return wearingItems; } get { return wearingItems; }
set { wearingItems = value; }
} }
//public WearableSprite WearingItemSprite
//{
// get { return wearingItemSprite; }
// set { wearingItemSprite = value; }
//}
public Limb (Character character, XElement element, float scale = 1.0f) public Limb (Character character, XElement element, float scale = 1.0f)
{ {
this.character = character; this.character = character;
WearingItems = new List<WearableSprite>(); wearingItems = new List<WearableSprite>();
dir = Direction.Right; dir = Direction.Right;
@@ -255,7 +272,12 @@ namespace Barotrauma
armorSector.Y = MathHelper.ToRadians(armorSector.Y); armorSector.Y = MathHelper.ToRadians(armorSector.Y);
armorValue = Math.Max(ToolBox.GetAttributeFloat(element, "armor", 0.0f), 0.0f); armorValue = Math.Max(ToolBox.GetAttributeFloat(element, "armor", 0.0f), 0.0f);
if (element.Attribute("mouthpos") != null)
{
MouthPos = ConvertUnits.ToSimUnits(ToolBox.GetAttributeVector2(element, "mouthpos", Vector2.Zero));
}
body.BodyType = BodyType.Dynamic; body.BodyType = BodyType.Dynamic;
body.FarseerBody.AngularDamping = LimbAngularDamping; body.FarseerBody.AngularDamping = LimbAngularDamping;
@@ -340,7 +362,7 @@ namespace Barotrauma
bool hitArmor = false; bool hitArmor = false;
float totalArmorValue = 0.0f; float totalArmorValue = 0.0f;
if (armorValue>0.0f && SectorHit(armorSector, position)) if (armorValue > 0.0f && SectorHit(armorSector, position))
{ {
hitArmor = true; hitArmor = true;
totalArmorValue += armorValue; totalArmorValue += armorValue;
@@ -354,8 +376,7 @@ namespace Barotrauma
hitArmor = true; hitArmor = true;
totalArmorValue += wearable.WearableComponent.ArmorValue; totalArmorValue += wearable.WearableComponent.ArmorValue;
} }
} }
if (hitArmor) if (hitArmor)
{ {
@@ -371,28 +392,19 @@ namespace Barotrauma
SoundPlayer.PlayDamageSound(damageSoundType, amount, position); SoundPlayer.PlayDamageSound(damageSoundType, amount, position);
} }
//Bleeding += bleedingAmount; float bloodParticleAmount = hitArmor || bleedingAmount <= 0.0f ? 0 : (int)Math.Min(amount / 5, 10);
//Damage += amount; float bloodParticleSize = MathHelper.Clamp(amount / 50.0f, 0.1f, 1.0f);
float bloodAmount = hitArmor || bleedingAmount<=0.0f ? 0 : (int)Math.Min((int)(amount * 2.0f), 20); for (int i = 0; i < bloodParticleAmount; i++)
{
var blood = GameMain.ParticleManager.CreateParticle(inWater ? "waterblood" : "blood", WorldPosition, Vector2.Zero, 0.0f, character.AnimController.CurrentHull);
if (blood != null)
{
blood.Size *= bloodParticleSize;
}
}
for (int i = 0; i < bloodAmount; i++) damage += Math.Max(amount, bleedingAmount) / character.MaxHealth * 100.0f;
{
Vector2 particleVel = SimPosition - position;
if (particleVel != Vector2.Zero) particleVel = Vector2.Normalize(particleVel);
GameMain.ParticleManager.CreateParticle("blood",
WorldPosition,
particleVel * Rand.Range(100.0f, 300.0f), 0.0f, character.AnimController.CurrentHull);
}
for (int i = 0; i < bloodAmount / 2; i++)
{
GameMain.ParticleManager.CreateParticle("waterblood", WorldPosition, Vector2.Zero, 0.0f, character.AnimController.CurrentHull);
}
damage += Math.Max(amount,bleedingAmount) / character.MaxHealth * 100.0f;
return new AttackResult(amount, bleedingAmount, hitArmor); return new AttackResult(amount, bleedingAmount, hitArmor);
} }
@@ -418,9 +430,7 @@ namespace Barotrauma
{ {
LightSource.ParentSub = body.Submarine; LightSource.ParentSub = body.Submarine;
} }
if (!character.IsDead) damage = Math.Max(0.0f, damage-deltaTime*0.1f);
if (burnt > 0.0f) Burnt -= deltaTime; if (burnt > 0.0f) Burnt -= deltaTime;
if (LinearVelocity.X > 500.0f) if (LinearVelocity.X > 500.0f)
@@ -435,9 +445,19 @@ namespace Barotrauma
body.ApplyWaterForces(); body.ApplyWaterForces();
} }
if (isSevered)
{
severedFadeOutTimer += deltaTime;
if (severedFadeOutTimer > SeveredFadeOutTime)
{
body.Enabled = false;
}
}
if (character.IsDead) return; if (character.IsDead) return;
soundTimer -= deltaTime; damage = Math.Max(0.0f, damage - deltaTime * 0.1f);
SoundTimer -= deltaTime;
//if (MathUtils.RandomFloat(0.0f, 1000.0f) < Bleeding) //if (MathUtils.RandomFloat(0.0f, 1000.0f) < Bleeding)
//{ //{
@@ -446,12 +466,7 @@ namespace Barotrauma
// SimPosition, Vector2.Zero); // SimPosition, Vector2.Zero);
//} //}
} }
public void ActivateDamagedSprite()
{
damage = 100.0f;
}
public void UpdateAttack(float deltaTime, Vector2 attackPosition, IDamageable damageTarget) public void UpdateAttack(float deltaTime, Vector2 attackPosition, IDamageable damageTarget)
{ {
float dist = ConvertUnits.ToDisplayUnits(Vector2.Distance(SimPosition, attackPosition)); float dist = ConvertUnits.ToDisplayUnits(Vector2.Distance(SimPosition, attackPosition));
@@ -464,19 +479,34 @@ namespace Barotrauma
{ {
if (AttackTimer >= attack.Duration && damageTarget != null) if (AttackTimer >= attack.Duration && damageTarget != null)
{ {
attack.DoDamage(character, damageTarget, WorldPosition, 1.0f, (soundTimer <= 0.0f)); attack.DoDamage(character, damageTarget, WorldPosition, 1.0f, (SoundTimer <= 0.0f));
soundTimer = Limb.SoundInterval; SoundTimer = SoundInterval;
} }
} }
Vector2 diff = attackPosition - SimPosition; Vector2 diff = attackPosition - SimPosition;
if (diff.LengthSquared() > 0.00001f) if (diff.LengthSquared() < 0.00001f) return;
if (attack.ApplyForceOnLimbs != null)
{ {
Vector2 pos = pullJoint == null ? body.SimPosition : pullJoint.WorldAnchorA; foreach (int limbIndex in attack.ApplyForceOnLimbs)
body.ApplyLinearImpulse(Mass * attack.Force * {
Vector2.Normalize(attackPosition - SimPosition), pos); if (limbIndex < 0 || limbIndex >= character.AnimController.Limbs.Length) continue;
Limb limb = character.AnimController.Limbs[limbIndex];
Vector2 forcePos = limb.pullJoint == null ? limb.body.SimPosition : limb.pullJoint.WorldAnchorA;
limb.body.ApplyLinearImpulse(
limb.Mass * attack.Force * Vector2.Normalize(attackPosition - SimPosition), forcePos);
}
} }
else
{
Vector2 forcePos = pullJoint == null ? body.SimPosition : pullJoint.WorldAnchorA;
body.ApplyLinearImpulse(Mass * attack.Force *
Vector2.Normalize(attackPosition - SimPosition), forcePos);
}
} }
public void Draw(SpriteBatch spriteBatch) public void Draw(SpriteBatch spriteBatch)
@@ -484,10 +514,21 @@ namespace Barotrauma
float brightness = 1.0f - (burnt / 100.0f) * 0.5f; float brightness = 1.0f - (burnt / 100.0f) * 0.5f;
Color color = new Color(brightness, brightness, brightness); Color color = new Color(brightness, brightness, brightness);
if (isSevered)
{
if (severedFadeOutTimer > SeveredFadeOutTime)
{
return;
}
else if (severedFadeOutTimer > SeveredFadeOutTime - 1.0f)
{
color *= SeveredFadeOutTime - severedFadeOutTimer;
}
}
body.Dir = Dir; body.Dir = Dir;
bool hideLimb = wearingItems.Any(w => w != null && w.HideLimb); bool hideLimb = wearingItems.Any(w => w != null && w.HideLimb);
if (!hideLimb) if (!hideLimb)
{ {
body.Draw(spriteBatch, sprite, color, null, scale); body.Draw(spriteBatch, sprite, color, null, scale);
+37 -8
View File
@@ -17,6 +17,8 @@ namespace Barotrauma
private bool spawnDeep; private bool spawnDeep;
private bool disallowed; private bool disallowed;
private bool repeat;
private Level.PositionType spawnPosType; private Level.PositionType spawnPosType;
@@ -39,7 +41,9 @@ namespace Barotrauma
{ {
characterFile = ToolBox.GetAttributeString(element, "characterfile", ""); characterFile = ToolBox.GetAttributeString(element, "characterfile", "");
minAmount = ToolBox.GetAttributeInt(element, "minamount", 1); int defaultAmount = ToolBox.GetAttributeInt(element, "amount", 1);
minAmount = ToolBox.GetAttributeInt(element, "minamount", defaultAmount);
maxAmount = Math.Max(ToolBox.GetAttributeInt(element, "maxamount", 1), minAmount); maxAmount = Math.Max(ToolBox.GetAttributeInt(element, "maxamount", 1), minAmount);
var spawnPosTypeStr = ToolBox.GetAttributeString(element, "spawntype", ""); var spawnPosTypeStr = ToolBox.GetAttributeString(element, "spawntype", "");
@@ -52,6 +56,8 @@ namespace Barotrauma
spawnDeep = ToolBox.GetAttributeBool(element, "spawndeep", false); spawnDeep = ToolBox.GetAttributeBool(element, "spawndeep", false);
repeat = ToolBox.GetAttributeBool(element, "repeat", repeat);
if (GameMain.NetworkMember != null) if (GameMain.NetworkMember != null)
{ {
List<string> monsterNames = GameMain.NetworkMember.monsterEnabled.Keys.ToList(); List<string> monsterNames = GameMain.NetworkMember.monsterEnabled.Keys.ToList();
@@ -67,18 +73,17 @@ namespace Barotrauma
{ {
base.Init(); base.Init();
SpawnMonsters(); SpawnMonsters(Rand.Range(minAmount, maxAmount, false));
} }
private void SpawnMonsters() private Character[] SpawnMonsters(int amount)
{ {
if (disallowed) return; if (disallowed) return null;
Vector2 spawnPos = Level.Loaded.GetRandomInterestingPosition(true, spawnPosType, true); Vector2 spawnPos = Level.Loaded.GetRandomInterestingPosition(true, spawnPosType, true);
int amount = Rand.Range(minAmount, maxAmount, false);
monsters = new Character[amount]; var monsters = new Character[amount];
if (spawnDeep) spawnPos.Y -= Level.Loaded.Size.Y; if (spawnDeep) spawnPos.Y -= Level.Loaded.Size.Y;
@@ -88,6 +93,8 @@ namespace Barotrauma
spawnPos.Y += Rand.Range(-0.5f, 0.5f, false); spawnPos.Y += Rand.Range(-0.5f, 0.5f, false);
monsters[i] = Character.Create(characterFile, spawnPos, null, GameMain.Client != null); monsters[i] = Character.Create(characterFile, spawnPos, null, GameMain.Client != null);
} }
return monsters;
} }
public override void Update(float deltaTime) public override void Update(float deltaTime)
@@ -97,7 +104,29 @@ namespace Barotrauma
Finished(); Finished();
return; return;
} }
if (monsters == null) SpawnMonsters();
if (monsters == null)
{
monsters = SpawnMonsters(Rand.Range(minAmount, maxAmount, false));
return;
}
if (repeat)
{
//clients aren't allowed to spawn more monsters mid-round
if (GameMain.Client != null)
{
return;
}
for (int i = 0; i < monsters.Length; i++)
{
if (monsters[i] == null || monsters[i].Removed || monsters[i].IsDead)
{
monsters[i] = SpawnMonsters(1)[0];
}
}
}
if (isFinished) return; if (isFinished) return;
@@ -128,7 +157,7 @@ namespace Barotrauma
} }
} }
if (monstersDead) Finished(); if (monstersDead && !repeat) Finished();
} }
} }
} }
@@ -655,7 +655,7 @@ namespace Barotrauma.Tutorials
enemy.Health = 50.0f; enemy.Health = 50.0f;
enemy.AIController.State = AIController.AiState.None; enemy.AIController.State = AIController.AIState.None;
Vector2 targetPos = Character.Controlled.WorldPosition + new Vector2(0.0f, 3000.0f); Vector2 targetPos = Character.Controlled.WorldPosition + new Vector2(0.0f, 3000.0f);
@@ -60,6 +60,8 @@ namespace Barotrauma.Items.Components
{ {
if (character != null && !characterUsable) return false; if (character != null && !characterUsable) return false;
User = character;
Launch(new Vector2( Launch(new Vector2(
(float)Math.Cos(item.body.Rotation), (float)Math.Cos(item.body.Rotation),
(float)Math.Sin(item.body.Rotation)) * launchImpulse * item.body.Mass); (float)Math.Sin(item.body.Rotation)) * launchImpulse * item.body.Mass);
@@ -147,7 +149,7 @@ namespace Barotrauma.Items.Components
return false; return false;
} }
AttackResult attackResult = new AttackResult(0.0f, 0.0f); AttackResult attackResult = new AttackResult();
if (attack != null) if (attack != null)
{ {
var submarine = f2.Body.UserData as Submarine; var submarine = f2.Body.UserData as Submarine;
+3 -2
View File
@@ -190,7 +190,7 @@ namespace Barotrauma.Items.Components
} }
} }
Launch(projectiles[0].Item); Launch(projectiles[0].Item, character);
if (character != null) if (character != null)
{ {
@@ -200,7 +200,7 @@ namespace Barotrauma.Items.Components
return true; return true;
} }
private void Launch(Item projectile) private void Launch(Item projectile, Character user = null)
{ {
reload = reloadTime; reload = reloadTime;
@@ -217,6 +217,7 @@ namespace Barotrauma.Items.Components
if (projectileComponent != null) if (projectileComponent != null)
{ {
projectileComponent.Use((float)Timing.Step); projectileComponent.Use((float)Timing.Step);
projectileComponent.User = user;
} }
if (projectile.Container != null) projectile.Container.RemoveContained(projectile); if (projectile.Container != null) projectile.Container.RemoveContained(projectile);
+24 -11
View File
@@ -90,7 +90,7 @@ namespace Barotrauma
if (force == 0.0f && attack.Stun == 0.0f && attack.GetDamage(1.0f) == 0.0f) return; if (force == 0.0f && attack.Stun == 0.0f && attack.GetDamage(1.0f) == 0.0f) return;
ApplyExplosionForces(worldPosition, attack.Range, force, attack.GetDamage(1.0f), attack.Stun); ApplyExplosionForces(worldPosition, attack, force);
if (flames && GameMain.Client == null) if (flames && GameMain.Client == null)
{ {
@@ -141,9 +141,9 @@ namespace Barotrauma
yield return CoroutineStatus.Success; yield return CoroutineStatus.Success;
} }
public static void ApplyExplosionForces(Vector2 worldPosition, float range, float force, float damage = 0.0f, float stun = 0.0f) public static void ApplyExplosionForces(Vector2 worldPosition, Attack attack, float force)
{ {
if (range <= 0.0f) return; if (attack.Range <= 0.0f) return;
foreach (Character c in Character.CharacterList) foreach (Character c in Character.CharacterList)
{ {
@@ -152,6 +152,7 @@ namespace Barotrauma
explosionPos = ConvertUnits.ToSimUnits(explosionPos); explosionPos = ConvertUnits.ToSimUnits(explosionPos);
bool wasDead = c.IsDead;
foreach (Limb limb in c.AnimController.Limbs) foreach (Limb limb in c.AnimController.Limbs)
{ {
float dist = Vector2.Distance(limb.WorldPosition, worldPosition); float dist = Vector2.Distance(limb.WorldPosition, worldPosition);
@@ -160,24 +161,36 @@ namespace Barotrauma
//doesn't take the rotation of the limb into account, but should be accurate enough for this purpose //doesn't take the rotation of the limb into account, but should be accurate enough for this purpose
float limbRadius = Math.Max(Math.Max(limb.body.width * 0.5f, limb.body.height * 0.5f), limb.body.radius); float limbRadius = Math.Max(Math.Max(limb.body.width * 0.5f, limb.body.height * 0.5f), limb.body.radius);
dist = Math.Max(0.0f, dist - FarseerPhysics.ConvertUnits.ToDisplayUnits(limbRadius)); dist = Math.Max(0.0f, dist - FarseerPhysics.ConvertUnits.ToDisplayUnits(limbRadius));
if (dist > attack.Range) continue;
if (dist > range) continue; float distFactor = 1.0f - dist / attack.Range;
float distFactor = 1.0f - dist / range;
//solid obstacles between the explosion and the limb reduce the effect of the explosion by 90% //solid obstacles between the explosion and the limb reduce the effect of the explosion by 90%
if (Submarine.CheckVisibility(limb.SimPosition, explosionPos) != null) distFactor *= 0.1f; if (Submarine.CheckVisibility(limb.SimPosition, explosionPos) != null) distFactor *= 0.1f;
c.AddDamage(limb.WorldPosition, DamageType.None, c.AddDamage(limb.WorldPosition, DamageType.None,
damage / c.AnimController.Limbs.Length * distFactor, 0.0f, stun * distFactor, false); attack.GetDamage(1.0f) / c.AnimController.Limbs.Length * distFactor,
attack.GetBleedingDamage(1.0f) / c.AnimController.Limbs.Length * distFactor,
attack.Stun * distFactor,
false);
if (limb.WorldPosition == worldPosition) continue; if (limb.WorldPosition != worldPosition && force > 0.0f)
if (force > 0.0f)
{ {
limb.body.ApplyLinearImpulse(Vector2.Normalize(limb.WorldPosition - worldPosition) * distFactor * force); limb.body.ApplyLinearImpulse(Vector2.Normalize(limb.WorldPosition - worldPosition) * distFactor * force);
} }
} }
if (!wasDead && c.IsDead)
{
foreach (LimbJoint joint in c.AnimController.LimbJoints)
{
if (Rand.Range(0.0f, 1.0f) < attack.SeverLimbsProbability)
{
c.AnimController.SeverLimbJoint(joint);
}
}
}
} }
} }
@@ -109,6 +109,7 @@ namespace Barotrauma
public void AddToRemoveQueue(Entity entity) public void AddToRemoveQueue(Entity entity)
{ {
if (GameMain.Client != null) return; if (GameMain.Client != null) return;
if (removeQueue.Contains(entity) || entity.Removed) return;
removeQueue.Enqueue(entity); removeQueue.Enqueue(entity);
} }
@@ -116,6 +117,7 @@ namespace Barotrauma
public void AddToRemoveQueue(Item item) public void AddToRemoveQueue(Item item)
{ {
if (GameMain.Client != null) return; if (GameMain.Client != null) return;
if (removeQueue.Contains(item) || item.Removed) return;
removeQueue.Enqueue(item); removeQueue.Enqueue(item);
if (item.ContainedItems == null) return; if (item.ContainedItems == null) return;
@@ -217,7 +217,7 @@ namespace Barotrauma
} }
jointList.ClearChildren(); jointList.ClearChildren();
foreach (RevoluteJoint joint in character.AnimController.limbJoints) foreach (RevoluteJoint joint in character.AnimController.LimbJoints)
{ {
Limb limb1 = (Limb)(joint.BodyA.UserData); Limb limb1 = (Limb)(joint.BodyA.UserData);
Limb limb2 = (Limb)(joint.BodyB.UserData); Limb limb2 = (Limb)(joint.BodyB.UserData);
@@ -236,7 +236,7 @@ namespace Barotrauma
private void DrawJoints(SpriteBatch spriteBatch, Limb limb, Vector2 limbBodyPos) private void DrawJoints(SpriteBatch spriteBatch, Limb limb, Vector2 limbBodyPos)
{ {
foreach (var joint in editingCharacter.AnimController.limbJoints) foreach (var joint in editingCharacter.AnimController.LimbJoints)
{ {
Vector2 jointPos = Vector2.Zero; Vector2 jointPos = Vector2.Zero;
@@ -253,24 +253,27 @@ namespace Barotrauma
{ {
continue; continue;
} }
jointPos.Y = -jointPos.Y; Vector2 tformedJointPos = jointPos /= limb.Scale;
jointPos += limbBodyPos; tformedJointPos.Y = -tformedJointPos.Y;
tformedJointPos += limbBodyPos;
if (joint.BodyA == limb.body.FarseerBody) if (joint.BodyA == limb.body.FarseerBody)
{ {
float a1 = joint.UpperLimit - MathHelper.PiOver2; float a1 = joint.UpperLimit - MathHelper.PiOver2;
float a2 = joint.LowerLimit - MathHelper.PiOver2; float a2 = joint.LowerLimit - MathHelper.PiOver2;
float a3 =( a1+a2)/2.0f; float a3 = (a1 + a2) / 2.0f;
GUI.DrawLine(spriteBatch, jointPos, jointPos + new Vector2((float)Math.Cos(a1), -(float)Math.Sin(a1)) * 30.0f, Color.Green); GUI.DrawLine(spriteBatch, tformedJointPos, tformedJointPos + new Vector2((float)Math.Cos(a1), -(float)Math.Sin(a1)) * 30.0f, Color.Green);
GUI.DrawLine(spriteBatch, jointPos, jointPos + new Vector2((float)Math.Cos(a2), -(float)Math.Sin(a2)) * 30.0f, Color.DarkGreen); GUI.DrawLine(spriteBatch, tformedJointPos, tformedJointPos + new Vector2((float)Math.Cos(a2), -(float)Math.Sin(a2)) * 30.0f, Color.DarkGreen);
GUI.DrawLine(spriteBatch, jointPos, jointPos + new Vector2((float)Math.Cos(a3), -(float)Math.Sin(a3)) * 30.0f, Color.LightGray); GUI.DrawLine(spriteBatch, tformedJointPos, tformedJointPos + new Vector2((float)Math.Cos(a3), -(float)Math.Sin(a3)) * 30.0f, Color.LightGray);
} }
GUI.DrawRectangle(spriteBatch, jointPos, new Vector2(5.0f, 5.0f), Color.Red, true); GUI.DrawRectangle(spriteBatch, tformedJointPos, new Vector2(5.0f, 5.0f), Color.Red, true);
if (Vector2.Distance(PlayerInput.MousePosition, jointPos) < 6.0f) if (Vector2.Distance(PlayerInput.MousePosition, tformedJointPos) < 10.0f)
{ {
GUI.DrawRectangle(spriteBatch, jointPos - new Vector2(3.0f, 3.0f), new Vector2(11.0f, 11.0f), Color.Red, false); GUI.DrawString(spriteBatch, tformedJointPos + Vector2.One*10.0f, jointPos.ToString(), Color.White, Color.Black * 0.5f);
GUI.DrawRectangle(spriteBatch, tformedJointPos - new Vector2(3.0f, 3.0f), new Vector2(11.0f, 11.0f), Color.Red, false);
if (PlayerInput.LeftButtonHeld()) if (PlayerInput.LeftButtonHeld())
{ {
Vector2 speed = ConvertUnits.ToSimUnits(PlayerInput.MouseSpeed); Vector2 speed = ConvertUnits.ToSimUnits(PlayerInput.MouseSpeed);
+29
View File
@@ -162,6 +162,35 @@ namespace Barotrauma
return value; return value;
} }
public static float GetAttributeFloat(XElement element, float defaultValue, params string[] matchingAttributeName)
{
if (element == null) return defaultValue;
foreach (string name in matchingAttributeName)
{
if (element.Attribute(name) == null) continue;
float val = defaultValue;
try
{
if (!float.TryParse(element.Attribute(name).Value, NumberStyles.Float, CultureInfo.InvariantCulture, out val))
{
continue;
}
}
catch (Exception e)
{
DebugConsole.ThrowError("Error in "+element+"!", e);
continue;
}
return val;
}
return defaultValue;
}
public static float GetAttributeFloat(XElement element, string name, float defaultValue) public static float GetAttributeFloat(XElement element, string name, float defaultValue)
{ {
if (element == null || element.Attribute(name) == null) return defaultValue; if (element == null || element.Attribute(name) == null) return defaultValue;