diff --git a/.gitignore b/.gitignore index b213ddbdc0..81f44ef553 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,6 @@ - *.suo *.cache -/Source/CombatRealism/_DLLs -/Source/CombatRealism/Combat_Realism.csproj.user -Source/CombatRealism/Combat_Realism.csproj -Source/CombatRealism/obj/Debug/Combat_Realism.csproj.FileListAbsolute.txt +*/Thumbs.db +/Source/CombatExtended/bin/* +/Source/CombatExtended/obj/* +/Source/CombatExtended/CombatExtended.csproj.user diff --git a/About/About.xml b/About/About.xml index 7f1dfb7e6c..81d24bf5dc 100644 --- a/About/About.xml +++ b/About/About.xml @@ -1,11 +1,7 @@  Combat Extended - NoImageAvailable - https://ludeon.com/forums/index.php?topic=27374.0 - 0.16.1386 - Version: 1.0 - - Extends combat mechanics to make it deeper and more tactical. - + CE Team + 0.17.1557 + Version: 1.0\n\nExtends combat mechanics to make them deeper and more tactical. diff --git a/About/Preview.png b/About/Preview.png new file mode 100644 index 0000000000..e498a2dc46 Binary files /dev/null and b/About/Preview.png differ diff --git a/Assemblies/0Harmony.dll b/Assemblies/0Harmony.dll new file mode 100644 index 0000000000..a95b6df8aa Binary files /dev/null and b/Assemblies/0Harmony.dll differ diff --git a/Assemblies/CombatExtended.dll b/Assemblies/CombatExtended.dll index 0f6caf08de..d73fdc4fa7 100644 Binary files a/Assemblies/CombatExtended.dll and b/Assemblies/CombatExtended.dll differ diff --git a/Defs/Ammo/Advanced/12x64mmCharged.xml b/Defs/Ammo/Advanced/12x64mmCharged.xml new file mode 100644 index 0000000000..2be61cbcf6 --- /dev/null +++ b/Defs/Ammo/Advanced/12x64mmCharged.xml @@ -0,0 +1,73 @@ + + + + + Ammo12x64mmCharged + + AmmoAdvanced + + + + + + AmmoSet_12x64mmCharged + + + Bullet_12x64mmCharged + + + + + + + Mechanoid-built high-caliber charged shot ammo used in heavy weapons. + + 0.1 + 0.14 + + +
  • Ammo12x64mmCharged
  • +
    + 200 +
    + + + Ammo_12x64mmCharged + + + Things/Ammo/Charged/Large + Graphic_StackCount + + + 3.09 + + Charged + + + + + + Bullet_12x64mmCharged + + + Things/Projectile/Charge_Small + Graphic_Single + TransparentPostLight + + + Bullet + 25 + 180 + +
  • + Bomb_Secondary + 15 +
  • +
    + 1.2 +
    +
    + + + +
    \ No newline at end of file diff --git a/Defs/Ammo/Advanced/30x64mmFuelCell.xml b/Defs/Ammo/Advanced/30x64mmFuelCell.xml new file mode 100644 index 0000000000..0a0a4058fe --- /dev/null +++ b/Defs/Ammo/Advanced/30x64mmFuelCell.xml @@ -0,0 +1,245 @@ + + + + + Ammo30x64mmFuelCell + + AmmoAdvanced + + + + + + AmmoSet_30x64mmFuel + + + Bullet_30x64mmFuel_Incendiary + Bullet_30x64mmFuel_Thermobaric + Bullet_30x64mmFuel_Foam + + + + + + + Container holding fuel for incendiary shot firearms. + + 0.3 + 0.5 + + +
  • CE_AutoEnableTrade
  • +
  • CE_AutoEnableCrafting
  • +
    + +
  • Ammo30x64mmFuelCell
  • +
    + 75 +
    + + + Ammo_30x64mmFuel_Incendiary + + + Things/Ammo/FuelCell/Incendiary + Graphic_StackCount + + + 1.52 + + IncendiaryFuel + + + + Ammo_30x64mmFuel_Thermobaric + + + Things/Ammo/FuelCell/Thermobaric + Graphic_StackCount + + + 2.16 + + ThermobaricFuel + + + + Ammo_30x64mmFuel_Foam + + + Things/Ammo/FuelCell/Foam + Graphic_StackCount + + + 0.61 + + FoamFuel + false + + + + + + + Things/Projectile/InfernoCannonShot + Graphic_Single + TransparentPostLight + + + 40 + false + + + + + Bullet_30x64mmFuel_Incendiary + CombatExtended.ProjectileCE_Explosive + + + Flame + 15 + 1.5 + FilthFuel + + + + + Bullet_30x64mmFuel_Thermobaric + + + 1.5 + Thermobaric + 25 + MortarBomb_Explode + + +
  • + 25 + Thermobaric + 2.5 + MortarBomb_Explode + true +
  • +
    +
    + + + Bullet_30x64mmFuel_Foam + CombatExtended.ProjectileCE_Explosive + + + Extinguish + 50 + 5.0 + FilthFireFoam + 1 + + + + + + + MakeAmmo_30x64mmFuel_Incendiary + + Craft 50 30x64mm incendiary fuel cells. + Making incendiary fuel cells. + +
  • + + +
  • Steel
  • + + + 12 + +
  • + + +
  • Prometheum
  • + + + 7 + +
    + + +
  • Steel
  • +
  • Prometheum
  • +
    +
    + + 50 + +
    + + + MakeAmmo_30x64mmFuel_Thermobaric + + Craft 50 30x64mm thermobaric fuel cells. + Making thermobaric fuel cells. + +
  • + + +
  • Steel
  • + + + 12 + +
  • + + +
  • FSX
  • + + + 7 + +
    + + +
  • Steel
  • +
  • FSX
  • +
    +
    + + 50 + +
    + + + MakeAmmo_30x64mmFuel_Foam + + Craft 50 30x64mm foam fuel cells. + Making foam fuel cells. + +
  • + + +
  • Steel
  • + + + 12 + +
  • + + +
  • MeatRaw
  • + + + 2 + +
    + + +
  • Steel
  • +
    + +
  • MeatRaw
  • +
    +
    + + 50 + +
    + +
    \ No newline at end of file diff --git a/Defs/Ammo/Advanced/5x35mmCharged.xml b/Defs/Ammo/Advanced/5x35mmCharged.xml new file mode 100644 index 0000000000..947550cb5a --- /dev/null +++ b/Defs/Ammo/Advanced/5x35mmCharged.xml @@ -0,0 +1,73 @@ + + + + + Ammo5x35mmCharged + + AmmoAdvanced + + + + + + AmmoSet_5x35mmCharged + + + Bullet_5x35mmCharged + + + + + + + Mechanoid-built charged shot ammo designed for high-velocity fire and armor penetration. + + 0.012 + 0.01 + + +
  • Ammo5x35mmCharged
  • +
    +
    + + + Ammo_5x35mmCharged + + + Things/Ammo/Charged/Concentrated + Graphic_StackCount + + + 1.28 + + Charged + + + + + + Bullet_5x35mmCharged + + + Things/Projectile/ChargeLanceShot + Graphic_Single + TransparentPostLight + (3,3) + + + Bullet + 10 + 200 + +
  • + Bomb_Secondary + 3 +
  • +
    + 0.95 +
    +
    + + + +
    \ No newline at end of file diff --git a/Defs/Ammo/Advanced/6x24mmCharged.xml b/Defs/Ammo/Advanced/6x24mmCharged.xml new file mode 100644 index 0000000000..607e3c7e72 --- /dev/null +++ b/Defs/Ammo/Advanced/6x24mmCharged.xml @@ -0,0 +1,245 @@ + + + + + Ammo6x24mmCharged + + AmmoAdvanced + + + + + + AmmoSet_6x24mmCharged + + + Bullet_6x24mmCharged + Bullet_6x24mmCharged_AP + Bullet_6x24mmCharged_Ion + + + + + + + Charged shot ammo used by advanced assault rifle designs. + + 0.01 + 0.03 + + +
  • CE_AutoEnableTrade
  • +
  • CE_AutoEnableCrafting
  • +
    + +
  • Ammo6x24mmCharged
  • +
    +
    + + + Ammo_6x24mmCharged + + + Things/Ammo/Charged/Regular + Graphic_StackCount + + + 0.97 + + Charged + + + + Ammo_6x24mmCharged_AP + + + Things/Ammo/Charged/Concentrated + Graphic_StackCount + + + 0.97 + + ChargedAP + + + + Ammo_6x24mmCharged_Ion + + + Things/Ammo/Charged/Ion + Graphic_StackCount + + + 0.97 + + Ionized + false + + + + + + + Things/Projectile/Charge_Small + Graphic_Single + + + Bullet + 170 + + + + + Bullet_6x24mmCharged + + + 11 + +
  • + Bomb_Secondary + 7 +
  • +
    + 0.8 +
    +
    + + + Bullet_6x24mmCharged_AP + + + 11 + +
  • + Bomb_Secondary + 3 +
  • +
    + 0.9 +
    +
    + + + Bullet_6x24mmCharged_Ion + + + 11 + +
  • + Electrical + 3 +
  • +
  • + EMP + 6 +
  • +
    + 0.75 +
    +
    + + + + + MakeAmmo_6x24mmCharged + + Craft 100 6x24mm Charged cartridges. + Making 6x24mm Charged cartridges. + +
  • + + +
  • Plasteel
  • + + + 2 + +
  • + + +
  • Component
  • + + + 2 + +
    + + +
  • Plasteel
  • +
  • Component
  • +
    +
    + + 100 + +
    + + + MakeAmmo_6x24mmCharged_AP + + Craft 100 6x24mm Charged (Conc.) cartridges. + Making 6x24mm Charged (Conc.) cartridges. + +
  • + + +
  • Plasteel
  • + + + 2 + +
  • + + +
  • Component
  • + + + 2 + +
    + + +
  • Plasteel
  • +
  • Component
  • +
    +
    + + 100 + +
    + + + MakeAmmo_6x24mmCharged_Ion + + Craft 100 6x24mm Charged (Ion) cartridges. + Making 6x24mm Charged (Ion) cartridges. + +
  • + + +
  • Plasteel
  • + + + 2 + +
  • + + +
  • Component
  • + + + 2 + +
    + + +
  • Plasteel
  • +
  • Component
  • +
    +
    + + 100 + +
    + +
    \ No newline at end of file diff --git a/Defs/Ammo/Advanced/80x256mmFuelCell.xml b/Defs/Ammo/Advanced/80x256mmFuelCell.xml new file mode 100644 index 0000000000..258e424067 --- /dev/null +++ b/Defs/Ammo/Advanced/80x256mmFuelCell.xml @@ -0,0 +1,85 @@ + + + + + Ammo80x256mmFuelCell + + AmmoAdvanced + + + + + + AmmoSet_80x256mmFuel + + + Bullet_80x256mmFuel_Thermobaric + + + + + + + Large fuel container for incendiary shot cannons. + + 3.0 + 8 + + +
  • Ammo80x256mmFuelCell
  • +
    + 25 +
    + + + Ammo_80x256mmFuel_Thermobaric + + + Things/Ammo/FuelCell/Large + Graphic_StackCount + + + 28.98 + + ThermobaricFuel + +
  • + 100 + Thermobaric + 3.5 + FilthFuel + 0.5 + MortarIncendiary_Explode +
  • +
    +
    + + + + + Bullet_80x256mmFuel_Thermobaric + CombatExtended.ProjectileCE_Explosive + + + Things/Projectile/InfernoCannonShot + Graphic_Single + TransparentPostLight + + + Flame + 100 + 100 + false + 3.5 + FilthFuel + 0.5 + MortarIncendiary_Explode + ArtilleryHitThickRoof + MortarRound_PreImpact + MortarRound_Ambient + + + + + +
    \ No newline at end of file diff --git a/Defs/Ammo/AmmoBases.xml b/Defs/Ammo/AmmoBases.xml new file mode 100644 index 0000000000..55ac8fff39 --- /dev/null +++ b/Defs/Ammo/AmmoBases.xml @@ -0,0 +1,113 @@ + + + + + + + + + CombatExtended.AmmoThing + + Item + Middle + true + + 100 + -5 + 1 + 2 + + true + Item + 500 + Metal_Drop + Metal_Drop + True + True + +
  • + + true + true + false + 15 + +
  • CE_Ammo
  • + + Sellable + Normal + 0.2 + 10 + ShotAssaultRifle + GunTail_Medium +
    + + + true + + 75 + + + + + + + Projectile + Normal + Projectile + CombatExtended.BulletCE + + False + True + + Transparent + + + + + + + true + + + + + + + SmithingSpeed + Cook + Recipe_Machining + true + 10000 + Crafting + 500 + + + + CE_AmmoCrafting + UnfinishedAmmo + + + + SmithingSpeed + Cook + Recipe_Machining + true + 2000 + Crafting + 500 + +
  • ElectricSmithy
  • +
  • FueledSmithy
  • +
    + UnfinishedArrows +
    + + + + +
  • TableMachining
  • +
    +
    + +
    \ No newline at end of file diff --git a/Defs/AmmoCategoryDefs/AmmoCategories_Advanced.xml b/Defs/Ammo/AmmoCategoryDefs/AmmoCategories_Advanced.xml similarity index 71% rename from Defs/AmmoCategoryDefs/AmmoCategories_Advanced.xml rename to Defs/Ammo/AmmoCategoryDefs/AmmoCategories_Advanced.xml index 45e5bc4c8e..a1db934998 100644 --- a/Defs/AmmoCategoryDefs/AmmoCategories_Advanced.xml +++ b/Defs/Ammo/AmmoCategoryDefs/AmmoCategories_Advanced.xml @@ -1,42 +1,44 @@  - + Charged The charged particle coating disrupts armor and tissue in equal measure. - + - + ChargedAP + conc. Focuses charged particles around the tip of the core for improved armor penetration at the cost of stopping power. - + - + Ionized + ion Designed to combat mechanoids, the round creates an electrical current on impact, disrupting electronic systems temporarily. - + - + IncendiaryFuel Filled with incendiary agent that ignites after impact. - + - + ThermobaricFuel Filled with high-explosive aerosol that causes a large explosion and ignites flammable materials. true - + - + FoamFuel Special round designed for civilian fire-fighting purposes. Filled with fire-retardant foam to suppress fires in a large area. true - + \ No newline at end of file diff --git a/Defs/AmmoCategoryDefs/AmmoCategories_General.xml b/Defs/Ammo/AmmoCategoryDefs/AmmoCategories_General.xml similarity index 68% rename from Defs/AmmoCategoryDefs/AmmoCategories_General.xml rename to Defs/Ammo/AmmoCategoryDefs/AmmoCategories_General.xml index 447bc1f1c7..8ba7b3b2f3 100644 --- a/Defs/AmmoCategoryDefs/AmmoCategories_General.xml +++ b/Defs/Ammo/AmmoCategoryDefs/AmmoCategories_General.xml @@ -1,41 +1,47 @@  - + FullMetalJacket + FMJ The soft lead core is encased in a harder metal coating, combining a medium amount of stopping power and armor penetration. - + - + ArmorPiercing + AP Features a hardened steel penetrator core for increased armor penetration. - + - + HollowPoint + HP A hollowed out tip causes the bullet to expand on impact, increasing tissue damage at the cost of armor penetration. - + - + Sabot + Sabot Uses a discarding sabot to fire an undersized projectile at higher muzzle velocities, greatly improving armor penetration. - + - + IncendiaryAP + AP-I Filled with an incendiary compound that ignites on impact, doing additional damage and potentially igniting targets. - + - + ExplosiveAP + AP-HE Filled with high-explosives that detonate on impact for additional damage. true - + \ No newline at end of file diff --git a/Defs/AmmoCategoryDefs/AmmoCategories_Grenades.xml b/Defs/Ammo/AmmoCategoryDefs/AmmoCategories_Grenades.xml similarity index 73% rename from Defs/AmmoCategoryDefs/AmmoCategories_Grenades.xml rename to Defs/Ammo/AmmoCategoryDefs/AmmoCategories_Grenades.xml index 387c2986c1..70d3356f19 100644 --- a/Defs/AmmoCategoryDefs/AmmoCategories_Grenades.xml +++ b/Defs/Ammo/AmmoCategoryDefs/AmmoCategories_Grenades.xml @@ -1,24 +1,25 @@  - + GrenadeHE + HE The high-explosive charge detonates on impact, scattering lethal shell fragments in a large area. - + - + GrenadeEMP Creates an electro-magnetic burst on impact, temporarily disrupting electronic systems and Mechanoids. true - + - + GrenadeIncendiary Filled with incendiary agent. The agent is dispersed on impact, covering the area in flames. true - + \ No newline at end of file diff --git a/Defs/Ammo/AmmoCategoryDefs/AmmoCategories_Neolithic.xml b/Defs/Ammo/AmmoCategoryDefs/AmmoCategories_Neolithic.xml new file mode 100644 index 0000000000..376da3f1aa --- /dev/null +++ b/Defs/Ammo/AmmoCategoryDefs/AmmoCategories_Neolithic.xml @@ -0,0 +1,31 @@ + + + + Javelin + + A heavy steel tip attached to a long wooden pole, packing a very strong punch against scarcely armored targets. + + + + StoneArrow + + stone + A sharpened stone is attached as an arrow head. Cuts exposed tissue fairly well but is ineffective against any kind of armor. + + + + SteelArrow + + steel + The arrow head is made from steel to enhance armor penetration. + true + + + + PlasteelArrow + + plasteel + Fitted with a plasteel head to maximize armor penetration. + true + + \ No newline at end of file diff --git a/Defs/AmmoCategoryDefs/AmmoCategories_Rockets.xml b/Defs/Ammo/AmmoCategoryDefs/AmmoCategories_Rockets.xml similarity index 72% rename from Defs/AmmoCategoryDefs/AmmoCategories_Rockets.xml rename to Defs/Ammo/AmmoCategoryDefs/AmmoCategories_Rockets.xml index 2dcb4015ba..60c13d7678 100644 --- a/Defs/AmmoCategoryDefs/AmmoCategories_Rockets.xml +++ b/Defs/Ammo/AmmoCategoryDefs/AmmoCategories_Rockets.xml @@ -1,23 +1,25 @@  - + RocketHEAT + HEAT Shaped charge warhead. Detonates on impact, creating a super-heated stream of molten metal that punches through enemy armor. - + - + RocketThermobaric Disperses and subsequently ignites a fuel-air explosive mix, creating a powerful explosion and potentially igniting flammable objects. true - + - + RocketFrag + Frag Designed to explode into a cloud of deadly shrapnel, shredding soft targets in a large area. - + \ No newline at end of file diff --git a/Defs/AmmoCategoryDefs/AmmoCategories_Shotgun.xml b/Defs/Ammo/AmmoCategoryDefs/AmmoCategories_Shotgun.xml similarity index 72% rename from Defs/AmmoCategoryDefs/AmmoCategories_Shotgun.xml rename to Defs/Ammo/AmmoCategoryDefs/AmmoCategories_Shotgun.xml index 309ed33a4b..e133855453 100644 --- a/Defs/AmmoCategoryDefs/AmmoCategories_Shotgun.xml +++ b/Defs/Ammo/AmmoCategoryDefs/AmmoCategories_Shotgun.xml @@ -1,35 +1,38 @@  - + BuckShot + buck Filled with several buckshot pellets which spread in a tight pattern. - + - + BirdShot + bird Filled with a large number of very small birdshot pellets which spread over a large area. - + - + Slug The single large projectile offers better damage potential and armor penetration compared to regular shot but is inaccurate over large distances. - + - + Beanbag + bean Non-lethal rubber round originally designed for riot control. Accurate over short ranges only. Designed to temporarily incapacitate a target, it does not cause bleeding or damage to internal organs. - + - + ElectroSlug Designed to combat mechanoids, the projectile is accurate over short range only and delivers an electro-magnetic pulse on impact, temporarily disabling electronics. true - + \ No newline at end of file diff --git a/Defs/Ammo/Grenade/25x40mmGrenade.xml b/Defs/Ammo/Grenade/25x40mmGrenade.xml new file mode 100644 index 0000000000..6aae6764f3 --- /dev/null +++ b/Defs/Ammo/Grenade/25x40mmGrenade.xml @@ -0,0 +1,214 @@ + + + + + Ammo25x40mmGrenades + + AmmoGrenades + + + + + + AmmoSet_25x40mmGrenade + + + Bullet_25x40mmGrenade_HE + Bullet_25x40mmGrenade_EMP + + + + + + + Specialized grenade developed for use in shoulder-fired grenade launchers. + + 0.2 + 0.3 + + +
  • CE_AutoEnableTrade
  • +
  • CE_AutoEnableCrafting
  • +
    + +
  • Ammo25x40mmGrenades
  • +
    + 20 +
    + + + Ammo_25x40mmGrenade_HE + + + Things/Ammo/GrenadeLauncher/HE + Graphic_StackCount + + + 1.38 + + GrenadeHE + +
  • + 15 + Bomb + 1 + + 80 + +
  • +
    +
    + + + Ammo_25x40mmGrenade_EMP + + + Things/Ammo/GrenadeLauncher/EMP + Graphic_StackCount + + + 2.07 + + GrenadeEMP + +
  • + 5 + Bomb + 0.5 + + 10 + +
  • +
    +
    + + + + + CombatExtended.ProjectileCE_Explosive + + Things/Projectile/Bullet_Big + Graphic_Single + + + 84 + + + + + Bullet_25x40mmGrenade_HE + + CombatExtended.ProjectileCE_Explosive + + Bomb + 30 + 1 + + +
  • + + 80 + +
  • +
    +
    + + + Bullet_25x40mmGrenade_EMP + + CombatExtended.ProjectileCE_Explosive + + EMP + 40 + 1 + + +
  • + 10 + Electrical + 2.5 + Explosion_Bomb +
  • +
    +
    + + + + + MakeAmmo_25x40mmGrenade_HE + + Craft 50 25x40mm HE grenades. + Making 25x40mm HE grenades. + +
  • + + +
  • Steel
  • + + + 18 + +
  • + + +
  • FSX
  • + + + 3 + +
  • + + +
  • Component
  • + + + 1 + +
    + + +
  • Steel
  • +
  • FSX
  • +
  • Component
  • +
    +
    + + 50 + +
    + + + MakeAmmo_25x40mmGrenade_EMP + + Craft 50 25x40mm EMP grenades. + Making 25x40mm EMP grenades. + +
  • + + +
  • Steel
  • + + + 15 + +
  • + + +
  • Component
  • + + + 4 + +
    + + +
  • Steel
  • +
  • Component
  • +
    +
    + + 50 + +
    + +
    \ No newline at end of file diff --git a/Defs/Ammo/Grenade/30x29mmGrenade.xml b/Defs/Ammo/Grenade/30x29mmGrenade.xml new file mode 100644 index 0000000000..b4c2c7cf26 --- /dev/null +++ b/Defs/Ammo/Grenade/30x29mmGrenade.xml @@ -0,0 +1,214 @@ + + + + + Ammo30x29mmGrenades + + AmmoGrenades + + + + + + AmmoSet_30x29mmGrenade + + + Bullet_30x29mmGrenade_HE + Bullet_30x29mmGrenade_EMP + + + + + + + Relatively small, low velocity grenade for use in grenade launchers. + + 0.2 + 0.3 + + +
  • CE_AutoEnableTrade
  • +
  • CE_AutoEnableCrafting
  • +
    + +
  • Ammo30x29mmGrenades
  • +
    + 75 + 20 +
    + + + Ammo_30x29mmGrenade_HE + + + Things/Ammo/GrenadeLauncher/HE + Graphic_StackCount + + + 1.73 + + GrenadeHE + +
  • + 20 + Bomb + 1.5 + + 90 + +
  • +
    +
    + + + Ammo_30x29mmGrenade_EMP + + + Things/Ammo/GrenadeLauncher/EMP + Graphic_StackCount + + + 2.07 + + GrenadeEMP + +
  • + 5 + Bomb + 0.5 + + 15 + +
  • +
    +
    + + + + + CombatExtended.ProjectileCE_Explosive + + Things/Projectile/Bullet_Big + Graphic_Single + + + 60 + false + + + + + Bullet_30x29mmGrenade_HE + + + 1.5 + Bomb + 40 + + +
  • + + 90 + +
  • +
    +
    + + + Bullet_30x29mmGrenade_EMP + + + 2.5 + EMP + 40 + + +
  • + 10 + Electrical + 2.5 + Explosion_Bomb +
  • +
    +
    + + + + + MakeAmmo_30x29mmGrenade_HE + + Craft 50 30x29mm HE grenades. + Making 30x29mm HE grenades. + +
  • + + +
  • Steel
  • + + + 15 + +
  • + + +
  • FSX
  • + + + 3 + +
  • + + +
  • Component
  • + + + 1 + +
    + + +
  • Steel
  • +
  • FSX
  • +
  • Component
  • +
    +
    + + 50 + +
    + + + MakeAmmo_30x29mmGrenade_EMP + + Craft 50 30x29mm EMP grenades. + Making 30x29mm EMP grenades. + +
  • + + +
  • Steel
  • + + + 15 + +
  • + + +
  • Component
  • + + + 4 + +
    + + +
  • Steel
  • +
  • Component
  • +
    +
    + + 50 + +
    + +
    \ No newline at end of file diff --git a/Defs/Ammo/Grenade/40x46mmGrenade.xml b/Defs/Ammo/Grenade/40x46mmGrenade.xml new file mode 100644 index 0000000000..25c22b0bef --- /dev/null +++ b/Defs/Ammo/Grenade/40x46mmGrenade.xml @@ -0,0 +1,213 @@ + + + + + Ammo40x46mmGrenades + + AmmoGrenades + + + + + + AmmoSet_40x46mmGrenade + + + Bullet_40x46mmGrenade_HE + Bullet_40x46mmGrenade_EMP + + + + + + + Low velocity grenade fired from handheld grenade launchers. + + 0.3 + 0.4 + + +
  • CE_AutoEnableTrade
  • +
  • CE_AutoEnableCrafting
  • +
    + +
  • Ammo40x46mmGrenades
  • +
    + 75 + 20 +
    + + + Ammo_40x46mmGrenade_HE + + + Things/Ammo/GrenadeLauncher/HE + Graphic_StackCount + + + 2.19 + + GrenadeHE + +
  • + 25 + Bomb + 1.8 + + 120 + +
  • +
    +
    + + + Ammo_40x46mmGrenade_EMP + + + Things/Ammo/GrenadeLauncher/EMP + Graphic_StackCount + + + 2.65 + + GrenadeEMP + +
  • + 5 + Bomb + 0.5 + + 20 + +
  • +
    +
    + + + + + CombatExtended.ProjectileCE_Explosive + + Things/Projectile/Bullet_Big + Graphic_Single + + + 30 + + + + + Bullet_40x46mmGrenade_HE + + + 1.8 + Bomb + 50 + + +
  • + + 120 + +
  • +
    +
    + + + Bullet_40x46mmGrenade_EMP + + + 3.0 + EMP + 60 + + +
  • + 15 + Electrical + 3.0 + Explosion_Bomb +
  • +
    +
    + + + + + MakeAmmo_40x46mmGrenade_HE + + Craft 50 40x46mm HE grenades. + Making 40x46mm HE grenades. + +
  • + + +
  • Steel
  • + + + 20 + +
  • + + +
  • FSX
  • + + + 4 + +
  • + + +
  • Component
  • + + + 1 + +
    + + +
  • Steel
  • +
  • FSX
  • +
  • Component
  • +
    +
    + + 50 + +
    + + + MakeAmmo_40x46mmGrenade_EMP + + Craft 50 40x46mm EMP grenades. + Making 40x46mm EMP grenades. + +
  • + + +
  • Steel
  • + + + 20 + +
  • + + +
  • Component
  • + + + 5 + +
    + + +
  • Steel
  • +
  • Component
  • +
    +
    + + 50 + +
    + +
    \ No newline at end of file diff --git a/Defs/Ammo/HighCaliber/14.5x114mmSoviet.xml b/Defs/Ammo/HighCaliber/14.5x114mmSoviet.xml new file mode 100644 index 0000000000..15a67c795b --- /dev/null +++ b/Defs/Ammo/HighCaliber/14.5x114mmSoviet.xml @@ -0,0 +1,233 @@ + + + + + Ammo145x114mm + + AmmoHighCaliber + + + + + + AmmoSet_145x114mm + + + Bullet_145x114mm_FMJ + Bullet_145x114mm_HE + Bullet_145x114mm_Incendiary + + + + + + + Old-school anti-tank cartridge originally designed for AT rifles, it is also used by a number of heavy machine guns. + + 0.19 + 0.24 + + +
  • CE_AutoEnableTrade
  • +
  • CE_AutoEnableCrafting
  • +
    + +
  • Ammo145x114mm
  • +
    + 200 +
    + + + Ammo_145x114mm_FMJ + + + Things/Ammo/HighCaliber/FMJ + Graphic_StackCount + + + 0.62 + + FullMetalJacket + Bullet_145x114mm_FMJ + + + + Ammo_145x114mm_HE + + + Things/Ammo/HighCaliber/HE + Graphic_StackCount + + + 1.13 + + ExplosiveAP + Bullet_145x114mm_HE + + + + Ammo_145x114mm_Incendiary + + + Things/Ammo/HighCaliber/Incendiary + Graphic_StackCount + + + 0.94 + + IncendiaryAP + Bullet_145x114mm_Incendiary + + + + + + + Things/Projectile/Bullet_Big + Graphic_Single + + + Bullet + 250 + true + + + + + Bullet_145x114mm_FMJ + + + 59 + 1.033 + + + + + Bullet_145x114mm_HE + + + 35 + 1.183 + +
  • + Bomb_Secondary + 24 +
  • +
    +
    +
    + + + Bullet_145x114mm_Incendiary + + + 35 + 1.183 + +
  • + Flame_Secondary + 12 +
  • +
    +
    +
    + + + + + MakeAmmo_145x114mm_FMJ + + Craft 200 14.5x114mm (FMJ) cartridges. + Making 14.5x114mm (FMJ) cartridges. + +
  • + + +
  • Steel
  • + + + 48 + +
    + + +
  • Steel
  • +
    +
    + + 200 + + 7000 +
    + + + MakeAmmo_145x114mm_HE + + Craft 200 14.5x114mm (HE) cartridges. + Making 14.5x114mm (HE) cartridges. + +
  • + + +
  • Steel
  • + + + 44 + +
  • + + +
  • FSX
  • + + + 6 + +
    + + +
  • Steel
  • +
  • FSX
  • +
    +
    + + 200 + + 20500 +
    + + + MakeAmmo_145x114mm_Incendiary + + Craft 200 14.5x114mm (AP-I) cartridges. + Making 14.5x114mm (AP-I) cartridges. + +
  • + + +
  • Steel
  • + + + 42 + +
  • + + +
  • Prometheum
  • + + + 4 + +
    + + +
  • Steel
  • +
  • Prometheum
  • +
    +
    + + 200 + + 18750 +
    + +
    \ No newline at end of file diff --git a/Defs/Ammo/HighCaliber/338LapuaMagnum.xml b/Defs/Ammo/HighCaliber/338LapuaMagnum.xml new file mode 100644 index 0000000000..321711fd55 --- /dev/null +++ b/Defs/Ammo/HighCaliber/338LapuaMagnum.xml @@ -0,0 +1,232 @@ + + + + + Ammo338Lapua + + AmmoHighCaliber + + + + + + AmmoSet_338Lapua + + + Bullet_338Lapua_FMJ + Bullet_338Lapua_HE + Bullet_338Lapua_Incendiary + + + + + + + The .338 Lapua Magnum (8.6×70mm or 8.58×70mm) is a rimless, bottlenecked, centerfire cartridge developed for military long-range sniper rifles. + + 0.04 + 0.08 + + +
  • CE_AutoEnableTrade
  • +
  • CE_AutoEnableCrafting
  • +
    + +
  • Ammo338Lapua
  • +
    +
    + + + Ammo_338Lapua_FMJ + + + Things/Ammo/HighCaliber/FMJ + Graphic_StackCount + + + 0.19 + + FullMetalJacket + Bullet_338Lapua_FMJ + + + + Ammo_338Lapua_HE + + + Things/Ammo/HighCaliber/HE + Graphic_StackCount + + + 0.46 + + ExplosiveAP + Bullet_338Lapua_HE + + + + Ammo_338Lapua_Incendiary + + + Things/Ammo/HighCaliber/Incendiary + Graphic_StackCount + + + 0.28 + + IncendiaryAP + Bullet_338Lapua_Incendiary + + + + + + + Things/Projectile/Bullet_Big + Graphic_Single + + + Bullet + 228 + true + + + + + Bullet_338Lapua_FMJ + + + 25 + 0.731 + + + + + Bullet_338Lapua_HE + + + 35 + 0.975 + +
  • + Bomb_Secondary + 25 +
  • +
    +
    +
    + + + Bullet_338Lapua_Incendiary + + + 15 + 0.881 + +
  • + Flame_Secondary + 5 +
  • +
    +
    +
    + + + + + MakeAmmo_338Lapua_FMJ + + Craft 100 .338 Lapua Magnum (FMJ) cartridges. + Making .338 Lapua Magnum (FMJ) cartridges. + +
  • + + +
  • Steel
  • + + + 24 + +
    + + +
  • Steel
  • +
    +
    + + 200 + + 4250 +
    + + + MakeAmmo_338Lapua_HE + + Craft 100 .338 Lapua Magnum (HE) cartridges. + Making .338 Lapua Magnum (HE) cartridges. + +
  • + + +
  • Steel
  • + + + 24 + +
  • + + +
  • FSX
  • + + + 4 + +
    + + +
  • Steel
  • +
  • FSX
  • +
    +
    + + 200 + + 10250 +
    + + + MakeAmmo_338Lapua_Incendiary + + Craft 100 .338 Lapua Magnum (AP-I) cartridges. + Making .338 Lapua Magnum (AP-I) cartridges. + +
  • + + +
  • Steel
  • + + + 22 + +
  • + + +
  • Prometheum
  • + + + 2 + +
    + + +
  • Steel
  • +
  • Prometheum
  • +
    +
    + + 200 + + 10250 +
    + +
    \ No newline at end of file diff --git a/Defs/Ammo/HighCaliber/50BMG.xml b/Defs/Ammo/HighCaliber/50BMG.xml new file mode 100644 index 0000000000..7b90ee7867 --- /dev/null +++ b/Defs/Ammo/HighCaliber/50BMG.xml @@ -0,0 +1,293 @@ + + + + + Ammo50BMG + + AmmoHighCaliber + + + + + + AmmoSet_50BMG + + + Bullet_50BMG_FMJ + Bullet_50BMG_Sabot + Bullet_50BMG_HE + Bullet_50BMG_Incendiary + + + + + + + Large caliber bullet used by many heavy machine guns and anti-materiel rifles. + + 0.12 + 0.16 + + +
  • CE_AutoEnableTrade
  • +
  • CE_AutoEnableCrafting
  • +
    + +
  • Ammo50BMG
  • +
    + 200 +
    + + + Ammo_50BMG_FMJ + + + Things/Ammo/HighCaliber/FMJ + Graphic_StackCount + + + 0.42 + + FullMetalJacket + Bullet_50BMG_FMJ + + + + Ammo_50BMG_Sabot + + + Things/Ammo/HighCaliber/Sabot + Graphic_StackCount + + + 0.67 + + Sabot + Bullet_50BMG_Sabot + + + + Ammo_50BMG_HE + + + Things/Ammo/HighCaliber/HE + Graphic_StackCount + + + 0.76 + + ExplosiveAP + Bullet_50BMG_HE + + + + Ammo_50BMG_Incendiary + + + Things/Ammo/HighCaliber/Incendiary + Graphic_StackCount + + + 0.62 + + IncendiaryAP + Bullet_50BMG_Incendiary + + + + + + + Things/Projectile/Bullet_Big + Graphic_Single + + + Bullet + 222 + true + + + + + Bullet_50BMG_FMJ + + + 46 + 0.909 + + + + + Bullet_50BMG_Sabot + + + 19 + 1.109 + 250 + + + + + Bullet_50BMG_HE + + + 28 + 1.059 + +
  • + Bomb_Secondary + 18 +
  • +
    +
    +
    + + + Bullet_50BMG_Incendiary + + + 28 + 1.059 + +
  • + Flame_Secondary + 9 +
  • +
    +
    +
    + + + + + MakeAmmo_50BMG_FMJ + + Craft 200 .50 BMG (FMJ) cartridges. + Making .50 BMG (FMJ) cartridges. + +
  • + + +
  • Steel
  • + + + 31 + +
    + + +
  • Steel
  • +
    +
    + + 200 + + 5250 +
    + + + MakeAmmo_50BMG_Sabot + + Craft 200 .50 BMG (Sabot) cartridges. + Making .50 BMG (Sabot) cartridges. + +
  • + + +
  • Steel
  • + + + 26 + +
  • + + +
  • Uranium
  • + + + 4 + +
    + + +
  • Steel
  • +
  • Uranium
  • +
    +
    + + 200 + + 11250 +
    + + + MakeAmmo_50BMG_HE + + Craft 200 .50 BMG (HE) cartridges. + Making .50 BMG (HE) cartridges. + +
  • + + +
  • Steel
  • + + + 27 + +
  • + + +
  • FSX
  • + + + 4 + +
    + + +
  • Steel
  • +
  • FSX
  • +
    +
    + + 200 + + 14500 +
    + + + MakeAmmo_50BMG_Incendiary + + Craft 200 .50 BMG (AP-I) cartridges. + Making .50 BMG (AP-I) cartridges. + +
  • + + +
  • Steel
  • + + + 29 + +
  • + + +
  • Prometheum
  • + + + 2 + +
    + + +
  • Steel
  • +
  • Prometheum
  • +
    +
    + + 200 + + 10250 +
    + +
    \ No newline at end of file diff --git a/Defs/Ammo/Neolithic/Arrows.xml b/Defs/Ammo/Neolithic/Arrows.xml new file mode 100644 index 0000000000..f0671c029a --- /dev/null +++ b/Defs/Ammo/Neolithic/Arrows.xml @@ -0,0 +1,217 @@ + + + + + AmmoArrows + + AmmoNeolithic + + + + + + AmmoSet_Arrow + + + Projectile_Arrow_Stone + Projectile_Arrow_Steel + Projectile_Arrow_Plasteel + + + + + + + Simple arrow design with a cutting head attached to a wooden shaft. + + 0.11 + 0.11 + 1 + + +
  • AmmoArrows
  • +
    + 200 +
    + + + Ammo_Arrow_Stone + + + Things/Ammo/Neolithic/Arrow/Stone + Graphic_StackCount + + + 0.17 + + StoneArrow + + + + Ammo_Arrow_Steel + + + Things/Ammo/Neolithic/Arrow/Steel + Graphic_StackCount + + + 0.38 + + SteelArrow + + + + Ammo_Arrow_Plasteel + + + Things/Ammo/Neolithic/Arrow/Plasteel + Graphic_StackCount + + + 3.32 + + PlasteelArrow + false + + + + + + + Things/Projectile/Arrow_Small + Graphic_Single + + + Arrow + 44 + + + + + Projectile_Arrow_Stone + + + 11 + 0.15 + + + + + Projectile_Arrow_Steel + + + 11 + 0.20 + + + + + Projectile_Arrow_Plasteel + + + 11 + 0.25 + + + + + + + MakeArrow_Stone + + Craft 10 stone arrows. + Making stone arrows. + +
  • + + +
  • WoodLog
  • + + + 1 + +
    + + +
  • WoodLog
  • +
    +
    + + 10 + + +
  • ElectricSmithy
  • +
  • FueledSmithy
  • +
  • CraftingSpot
  • +
    +
    + + + MakeArrow_Steel + + Craft 10 steel arrows. + Making steel arrows. + +
  • + + +
  • WoodLog
  • + + + 1 + +
  • + + +
  • Steel
  • + + + 1 + +
    + + +
  • WoodLog
  • +
  • Steel
  • +
    +
    + + 10 + +
    + + + MakeArrow_Plasteel + + Craft 10 plasteel arrows. + Making plasteel arrows. + +
  • + + +
  • WoodLog
  • + + + 1 + +
  • + + +
  • Plasteel
  • + + + 1 + +
    + + +
  • WoodLog
  • +
  • Plasteel
  • +
    +
    + + 10 + +
    + +
    \ No newline at end of file diff --git a/Defs/Ammo/Neolithic/GreatArrows.xml b/Defs/Ammo/Neolithic/GreatArrows.xml new file mode 100644 index 0000000000..4e0f61ff83 --- /dev/null +++ b/Defs/Ammo/Neolithic/GreatArrows.xml @@ -0,0 +1,217 @@ + + + + + AmmoGreatArrows + + AmmoNeolithic + + + + + + AmmoSet_GreatArrow + + + Projectile_GreatArrow_Stone + Projectile_GreatArrow_Steel + Projectile_GreatArrow_Plasteel + + + + + + + Heavy arrow designed to be fired from a great bow. + + 0.17 + 0.17 + 1 + + +
  • AmmoGreatArrows
  • +
    + 200 +
    + + + Ammo_GreatArrow_Stone + + + Things/Ammo/Neolithic/Arrow/Stone + Graphic_StackCount + + + 0.11 + + StoneArrow + + + + Ammo_GreatArrow_Steel + + + Things/Ammo/Neolithic/Arrow/Steel + Graphic_StackCount + + + 0.52 + + SteelArrow + + + + Ammo_GreatArrow_Plasteel + + + Things/Ammo/Neolithic/Arrow/Plasteel + Graphic_StackCount + + + 3.46 + + PlasteelArrow + false + + + + + + + Things/Projectile/Arrow_Small + Graphic_Single + + + Arrow + 49 + + + + + Projectile_GreatArrow_Stone + + + 15 + 0.2 + + + + + Projectile_GreatArrow_Steel + + + 15 + 0.275 + + + + + Projectile_GreatArrow_Plasteel + + + 15 + 0.35 + + + + + + + MakeGreatArrow_Stone + + Craft 10 stone great arrows. + Making stone great arrows. + +
  • + + +
  • WoodLog
  • + + + 2 + +
    + + +
  • WoodLog
  • +
    +
    + + 10 + + +
  • ElectricSmithy
  • +
  • FueledSmithy
  • +
  • CraftingSpot
  • +
    +
    + + + MakeGreatArrow_Steel + + Craft 10 steel great arrows. + Making steel great arrows. + +
  • + + +
  • WoodLog
  • + + + 2 + +
  • + + +
  • Steel
  • + + + 1 + +
    + + +
  • WoodLog
  • +
  • Steel
  • +
    +
    + + 10 + +
    + + + MakeGreatArrow_Plasteel + + Craft 10 plasteel great arrows. + Making plasteel great arrows. + +
  • + + +
  • WoodLog
  • + + + 2 + +
  • + + +
  • Plasteel
  • + + + 1 + +
    + + +
  • WoodLog
  • +
  • Plasteel
  • +
    +
    + + 10 + +
    + +
    \ No newline at end of file diff --git a/Defs/Ammo/Neolithic/Javelins.xml b/Defs/Ammo/Neolithic/Javelins.xml new file mode 100644 index 0000000000..a7e173ee24 --- /dev/null +++ b/Defs/Ammo/Neolithic/Javelins.xml @@ -0,0 +1,50 @@ + + + + + + + AmmoSet_Javelins + + + Pilum_Fired + + + + + + + + + + Things/Projectile/Pilum + Graphic_Single + + + Stab + + + + + Pilum_Thrown + + + 16 + 26 + 0.3 + + + + + Pilum_Fired + + + 22 + 38 + 0.35 + + + + + + \ No newline at end of file diff --git a/Defs/Ammo/Pistols/22LR.xml b/Defs/Ammo/Pistols/22LR.xml new file mode 100644 index 0000000000..88f7996e49 --- /dev/null +++ b/Defs/Ammo/Pistols/22LR.xml @@ -0,0 +1,150 @@ + + + + + Ammo22LR + + AmmoPistols + + + + + + AmmoSet_22LR + + + Bullet_22LR_FMJ + + + + + + + + Low caliber handgun cartridge massively lacking in stopping power. + + 0.01 + 0.01 + + +
  • CE_AutoEnableTrade
  • +
  • CE_AutoEnableCrafting
  • +
    + +
  • Ammo22LR
  • +
    +
    + + + Ammo_22LR_FMJ + + + Things/Ammo/Pistol/FMJ + Graphic_StackCount + + + 0.03 + + FullMetalJacket + Bullet_22LR_FMJ + + + + + + + + + Things/Projectile/Bullet_Small + Graphic_Single + + + Bullet + 110 + true + + + + + Bullet_22LR_FMJ + + + 4 + 0.189 + + + + + + + + + MakeAmmo_22LR_FMJ + + Craft 500 .22 LR (FMJ) cartridges. + Making .22 LR (FMJ) cartridges. + +
  • + + +
  • Steel
  • + + + 4 + +
    + + +
  • Steel
  • +
    +
    + + 500 + + 1250 +
    + + + +
    \ No newline at end of file diff --git a/Defs/Ammo/Pistols/32ACP.xml b/Defs/Ammo/Pistols/32ACP.xml new file mode 100644 index 0000000000..442e2ead30 --- /dev/null +++ b/Defs/Ammo/Pistols/32ACP.xml @@ -0,0 +1,148 @@ + + + + + Ammo32ACP + + AmmoPistols + + + + + + AmmoSet_32ACP + + + Bullet_32ACP_FMJ + + + + + + + + Low caliber handgun cartridge lacking in stopping power. + + 0.01 + 0.01 + + +
  • CE_AutoEnableTrade
  • +
  • CE_AutoEnableCrafting
  • +
    + +
  • Ammo32ACP
  • +
    +
    + + + Ammo_32ACP_FMJ + + + Things/Ammo/Pistol/FMJ + Graphic_StackCount + + + 0.03 + + FullMetalJacket + Bullet_32ACP_FMJ + + + + + + + + + Things/Projectile/Bullet_Small + Graphic_Single + + + Bullet + 80 + true + + + + + Bullet_32ACP_FMJ + + + 6 + 0.187 + + + + + + + + + MakeAmmo_32ACP_FMJ + + Craft 500 .32 ACP cartridges. + Making .32 ACP cartridges. + +
  • + + +
  • Steel
  • + + + 5 + +
    + + +
  • Steel
  • +
    +
    + + 500 + + 1250 +
    + +
    \ No newline at end of file diff --git a/Defs/Ammo/Pistols/40Rimfire.xml b/Defs/Ammo/Pistols/40Rimfire.xml new file mode 100644 index 0000000000..12b53827d0 --- /dev/null +++ b/Defs/Ammo/Pistols/40Rimfire.xml @@ -0,0 +1,92 @@ + + + + + Ammo40Rimfire + + AmmoPistols + + + + + + AmmoSet_40Rimfire + + + Bullet_40Rimfire + + + + + + + Ammo_40Rimfire + + Ultra-light cartridge for use in derringer pistols. + +
  • CE_AutoEnableTrade
  • +
  • CE_AutoEnableCrafting
  • +
    + +
  • Ammo40Rimfire
  • +
    + + Things/Ammo/Pistol/FMJ + Graphic_StackCount + + + 0.02 + 0.01 + 0.01 + + FullMetalJacket + Bullet_40Rimfire +
    + + + + + Bullet_40Rimfire + + + Things/Projectile/Bullet_Small + Graphic_Single + + + Bullet + 33 + 4 + 0.098 + true + + + + + + + MakeAmmo_40Rimfire + + Craft 500 .40 Rimfire cartridges. + Making .40 Rimfire cartridges. + +
  • + + +
  • Steel
  • + + + 4 + +
    + + +
  • Steel
  • +
    +
    + + 500 + + 1000 +
    + +
    \ No newline at end of file diff --git a/Defs/Ammo/Pistols/45ACP.xml b/Defs/Ammo/Pistols/45ACP.xml new file mode 100644 index 0000000000..aef62d93b2 --- /dev/null +++ b/Defs/Ammo/Pistols/45ACP.xml @@ -0,0 +1,202 @@ + + + + + Ammo45ACP + + AmmoPistols + + + + + + AmmoSet_45ACP + + + Bullet_45ACP_FMJ + Bullet_45ACP_AP + Bullet_45ACP_HP + + + + + + + Pistol cartridge favoured for its above average stopping power. + + 0.02 + 0.02 + + +
  • CE_AutoEnableTrade
  • +
  • CE_AutoEnableCrafting
  • +
    + +
  • Ammo45ACP
  • +
    +
    + + + Ammo_45ACP_FMJ + + + Things/Ammo/Pistol/FMJ + Graphic_StackCount + + + 0.06 + + FullMetalJacket + Bullet_45ACP_FMJ + + + + Ammo_45ACP_AP + + + Things/Ammo/Pistol/AP + Graphic_StackCount + + + 0.08 + + ArmorPiercing + Bullet_45ACP_AP + + + + Ammo_45ACP_HP + + + Things/Ammo/Pistol/HP + Graphic_StackCount + + + 0.08 + + HollowPoint + Bullet_45ACP_HP + + + + + + + Things/Projectile/Bullet_Small + Graphic_Single + + + Bullet + 78 + true + + + + + Bullet_45ACP_FMJ + + + 14 + 0.31 + + + + + Bullet_45ACP_AP + + + 8 + 0.46 + + + + + Bullet_45ACP_HP + + + 20 + 0.16 + + + + + + + MakeAmmo_45ACP_FMJ + + Craft 500 .45 ACP (FMJ) cartridges. + Making .45 ACP (FMJ) cartridges. + +
  • + + +
  • Steel
  • + + + 11 + +
    + + +
  • Steel
  • +
    +
    + + 500 + + 2000 +
    + + + MakeAmmo_45ACP_AP + + Craft 500 .45 ACP (AP) cartridges. + Making .45 ACP (AP) cartridges. + +
  • + + +
  • Steel
  • + + + 14 + +
    + + +
  • Steel
  • +
    +
    + + 500 + + 3000 +
    + + + MakeAmmo_45ACP_HP + + Craft 500 .45 ACP (HP) cartridges. + Making .45 ACP (HP) cartridges. + +
  • + + +
  • Steel
  • + + + 11 + +
    + + +
  • Steel
  • +
    +
    + + 500 + + 4250 +
    + +
    \ No newline at end of file diff --git a/Defs/Ammo/Pistols/45Colt.xml b/Defs/Ammo/Pistols/45Colt.xml new file mode 100644 index 0000000000..68e30bfb7f --- /dev/null +++ b/Defs/Ammo/Pistols/45Colt.xml @@ -0,0 +1,203 @@ + + + + + Ammo45Colt + + AmmoPistols + + + + + + AmmoSet_45Colt + + + Bullet_45Colt_FMJ + Bullet_45Colt_AP + Bullet_45Colt_HP + Bullet_410Bore_Buck + + + + + + + Ancient pistol cartridge originally designed for revolvers. + + 0.02 + 0.03 + + +
  • CE_AutoEnableTrade
  • +
  • CE_AutoEnableCrafting
  • +
    + +
  • Ammo45Colt
  • +
    +
    + + + Ammo_45Colt_FMJ + + + Things/Ammo/Pistol/FMJ + Graphic_StackCount + + + 0.07 + + FullMetalJacket + Bullet_45Colt_FMJ + + + + Ammo_45Colt_AP + + + Things/Ammo/Pistol/AP + Graphic_StackCount + + + 0.1 + + ArmorPiercing + Bullet_45Colt_AP + + + + Ammo_45Colt_HP + + + Things/Ammo/Pistol/HP + Graphic_StackCount + + + 0.09 + + HollowPoint + Bullet_45Colt_HP + + + + + + + Things/Projectile/Bullet_Small + Graphic_Single + + + Bullet + 70 + true + + + + + Bullet_45Colt_FMJ + + + 14 + 0.317 + + + + + Bullet_45Colt_AP + + + 8 + 0.467 + + + + + Bullet_45Colt_HP + + + 20 + 0.167 + + + + + + + MakeAmmo_45Colt_FMJ + + Craft 500 .45 Colt (FMJ) cartridges. + Making .45 Colt (FMJ) cartridges. + +
  • + + +
  • Steel
  • + + + 14 + +
    + + +
  • Steel
  • +
    +
    + + 500 + + 2000 +
    + + + MakeAmmo_45Colt_AP + + Craft 500 .45 Colt (AP) cartridges. + Making .45 Colt (AP) cartridges. + +
  • + + +
  • Steel
  • + + + 18 + +
    + + +
  • Steel
  • +
    +
    + + 500 + + 3000 +
    + + + MakeAmmo_45Colt_HP + + Craft 500 .45 Colt (HP) cartridges. + Making .45 Colt (HP) cartridges. + +
  • + + +
  • Steel
  • + + + 14 + +
    + + +
  • Steel
  • +
    +
    + + 500 + + 4250 +
    + +
    \ No newline at end of file diff --git a/Defs/Ammo/Pistols/500SWMagnum.xml b/Defs/Ammo/Pistols/500SWMagnum.xml new file mode 100644 index 0000000000..9ea5dd12cc --- /dev/null +++ b/Defs/Ammo/Pistols/500SWMagnum.xml @@ -0,0 +1,152 @@ + + + + + Ammo500SWMagnum + + AmmoPistols + + + + + + AmmoSet_500SWMagnum + + + Bullet_500SWMagnum_FMJ + Bullet_500SWMagnum_HP + + + + + + + Designed for big game hunting, this is one of the most powerful handgun cartridges ever designed. + + 0.04 + 0.04 + + +
  • CE_AutoEnableTrade
  • +
  • CE_AutoEnableCrafting
  • +
    + +
  • Ammo500SWMagnum
  • +
    +
    + + + Ammo_500SWMagnum_FMJ + + + Things/Ammo/Pistol/FMJ + Graphic_StackCount + + + 0.12 + + FullMetalJacket + Bullet_500SWMagnum_FMJ + + + + Ammo_500SWMagnum_HP + + + Things/Ammo/Pistol/HP + Graphic_StackCount + + + 0.18 + + HollowPoint + Bullet_500SWMagnum_HP + + + + + + + Things/Projectile/Bullet_Big + Graphic_Single + + + Bullet + 122 + true + + + + + Bullet_500SWMagnum_FMJ + + + 28 + 0.563 + + + + + Bullet_500SWMagnum_HP + + + 39 + 0.413 + + + + + + + MakeAmmo_500SWMagnum_FMJ + + Craft 200 .500 S&W Magnum cartridges. + Making .500 S&W Magnum cartridges. + +
  • + + +
  • Steel
  • + + + 21 + +
    + + +
  • Steel
  • +
    +
    + + 500 + + 5000 +
    + + + MakeAmmo_500SWMagnum_HP + + Craft 200 .500 S&W Magnum cartridges. + Making .500 S&W Magnum cartridges. + +
  • + + +
  • Steel
  • + + + 21 + +
    + + +
  • Steel
  • +
    +
    + + 500 + + 12500 +
    + +
    \ No newline at end of file diff --git a/Defs/Ammo/Pistols/50AE.xml b/Defs/Ammo/Pistols/50AE.xml new file mode 100644 index 0000000000..fc7846b3f5 --- /dev/null +++ b/Defs/Ammo/Pistols/50AE.xml @@ -0,0 +1,151 @@ + + + + + Ammo50AE + + AmmoPistols + + + + + + AmmoSet_50AE + + + Bullet_50AE_FMJ + Bullet_50AE_HP + + + + + + + This high-powered cartridge is one of the largest calibers found in handguns. + + 0.03 + 0.03 + + +
  • CE_AutoEnableTrade
  • +
  • CE_AutoEnableCrafting
  • +
    + +
  • Ammo50AE
  • +
    +
    + + + Ammo_50AE_FMJ + + + Things/Ammo/Pistol/FMJ + Graphic_StackCount + + + 0.1 + + FullMetalJacket + Bullet_50AE_FMJ + + + + Ammo_50AE_HP + + + Things/Ammo/Pistol/HP + Graphic_StackCount + + + 0.15 + + HollowPoint + Bullet_50AE_HP + + + + + + + Things/Projectile/Bullet_Big + Graphic_Single + + + Bullet + 113 + + + + + Bullet_50AE_FMJ + + + 25 + 0.505 + + + + + Bullet_50AE_HP + + + 35 + 0.355 + + + + + + + MakeAmmo_50AE_HP + + Craft 200 .50 AE HP cartridges. + Making .50 AE HP cartridges. + +
  • + + +
  • Steel
  • + + + 16 + +
    + + +
  • Steel
  • +
    +
    + + 500 + + 10250 +
    + + + MakeAmmo_50AE_FMJ + + Craft 200 .50 AE FMJ cartridges. + Making .50 AE FMJ cartridges. + +
  • + + +
  • Steel
  • + + + 16 + +
    + + +
  • Steel
  • +
    +
    + + 500 + + 4250 +
    + +
    \ No newline at end of file diff --git a/Defs/Ammo/Pistols/762x25mmTokarev.xml b/Defs/Ammo/Pistols/762x25mmTokarev.xml new file mode 100644 index 0000000000..e27d93b2ef --- /dev/null +++ b/Defs/Ammo/Pistols/762x25mmTokarev.xml @@ -0,0 +1,202 @@ + + + + + Ammo762x25mmTokarev + + AmmoPistols + + + + + + AmmoSet_762x25mmTokarev + + + Bullet_762x25mmTokarev_FMJ + Bullet_762x25mmTokarev_AP + Bullet_762x25mmTokarev_HP + + + + + + + Common pistol cartridge used by a variety of handguns and SMGs. + + 0.01 + 0.02 + + +
  • CE_AutoEnableTrade
  • +
  • CE_AutoEnableCrafting
  • +
    + +
  • Ammo762x25mmTokarev
  • +
    +
    + + + Ammo_762x25mmTokarev_FMJ + + + Things/Ammo/Pistol/FMJ + Graphic_StackCount + + + 0.05 + + FullMetalJacket + Bullet_762x25mmTokarev_FMJ + + + + Ammo_762x25mmTokarev_AP + + + Things/Ammo/Pistol/AP + Graphic_StackCount + + + 0.07 + + ArmorPiercing + Bullet_762x25mmTokarev_AP + + + + Ammo_762x25mmTokarev_HP + + + Things/Ammo/Pistol/HP + Graphic_StackCount + + + 0.07 + + HollowPoint + Bullet_762x25mmTokarev_HP + + + + + + + Things/Projectile/Bullet_Small + Graphic_Single + + + Bullet + 131 + true + + + + + Bullet_762x25mmTokarev_FMJ + + + 11 + 0.357 + + + + + Bullet_762x25mmTokarev_AP + + + 7 + 0.507 + + + + + Bullet_762x25mmTokarev_HP + + + 15 + 0.207 + + + + + + + MakeAmmo_762x25mmTokarev_FMJ + + Craft 500 7.62x25mm Tokarev (FMJ) cartridges. + Making 7.62x25mm Tokarev (FMJ) cartridges. + +
  • + + +
  • Steel
  • + + + 9 + +
    + + +
  • Steel
  • +
    +
    + + 500 + + 2000 +
    + + + MakeAmmo_762x25mmTokarev_AP + + Craft 500 7.62x25mm Tokarev (AP) cartridges. + Making 7.62x25mm Tokarev (AP) cartridges. + +
  • + + +
  • Steel
  • + + + 11 + +
    + + +
  • Steel
  • +
    +
    + + 500 + + 2750 +
    + + + MakeAmmo_762x25mmTokarev_HP + + Craft 500 7.62x25mm Tokarev (HP) cartridges. + Making 7.62x25mm Tokarev (HP) cartridges. + +
  • + + +
  • Steel
  • + + + 9 + +
    + + +
  • Steel
  • +
    +
    + + 500 + + 3750 +
    + +
    \ No newline at end of file diff --git a/Defs/Ammo/Pistols/9x19mmPara.xml b/Defs/Ammo/Pistols/9x19mmPara.xml new file mode 100644 index 0000000000..8c48ab98d0 --- /dev/null +++ b/Defs/Ammo/Pistols/9x19mmPara.xml @@ -0,0 +1,202 @@ + + + + + Ammo9x19mmPara + + AmmoPistols + + + + + + AmmoSet_9x19mmPara + + + Bullet_9x19mmPara_FMJ + Bullet_9x19mmPara_AP + Bullet_9x19mmPara_HP + + + + + + + Common pistol cartridge used by a variety of handguns and SMGs. + + 0.01 + 0.02 + + +
  • CE_AutoEnableTrade
  • +
  • CE_AutoEnableCrafting
  • +
    + +
  • Ammo9x19mmPara
  • +
    +
    + + + Ammo_9x19mmPara_FMJ + + + Things/Ammo/Pistol/FMJ + Graphic_StackCount + + + 0.06 + + FullMetalJacket + Bullet_9x19mmPara_FMJ + + + + Ammo_9x19mmPara_AP + + + Things/Ammo/Pistol/AP + Graphic_StackCount + + + 0.07 + + ArmorPiercing + Bullet_9x19mmPara_AP + + + + Ammo_9x19mmPara_HP + + + Things/Ammo/Pistol/HP + Graphic_StackCount + + + 0.07 + + HollowPoint + Bullet_9x19mmPara_HP + + + + + + + Things/Projectile/Bullet_Small + Graphic_Single + + + Bullet + 95 + true + + + + + Bullet_9x19mmPara_FMJ + + + 11 + 0.31 + + + + + Bullet_9x19mmPara_AP + + + 7 + 0.46 + + + + + Bullet_9x19mmPara_HP + + + 15 + 0.16 + + + + + + + MakeAmmo_9x19mmPara_FMJ + + Craft 500 9x19mm Parabellum (FMJ) cartridges. + Making 9x19mm Parabellum (FMJ) cartridges. + +
  • + + +
  • Steel
  • + + + 9 + +
    + + +
  • Steel
  • +
    +
    + + 500 + + 1750 +
    + + + MakeAmmo_9x19mmPara_AP + + Craft 500 9x19mm Parabellum (AP) cartridges. + Making 9x19mm Parabellum (AP) cartridges. + +
  • + + +
  • Steel
  • + + + 11 + +
    + + +
  • Steel
  • +
    +
    + + 500 + + 2500 +
    + + + MakeAmmo_9x19mmPara_HP + + Craft 500 9x19mm Parabellum (HP) cartridges. + Making 9x19mm Parabellum (HP) cartridges. + +
  • + + +
  • Steel
  • + + + 9 + +
    + + +
  • Steel
  • +
    +
    + + 500 + + 3500 +
    + +
    \ No newline at end of file diff --git a/Defs/Ammo/Pistols/FN57x28mm.xml b/Defs/Ammo/Pistols/FN57x28mm.xml new file mode 100644 index 0000000000..7cadc1ce3f --- /dev/null +++ b/Defs/Ammo/Pistols/FN57x28mm.xml @@ -0,0 +1,202 @@ + + + + + AmmoFN57x28mm + + AmmoPistols + + + + + + AmmoSet_FN57x28mm + + + Bullet_FN57x28mm_FMJ + Bullet_FN57x28mm_AP + Bullet_FN57x28mm_HP + + + + + + + This high-velocity handgun cartridge was specifically designed for military personnel to defeat body armor. + + 0.01 + 0.02 + + +
  • CE_AutoEnableTrade
  • +
  • CE_AutoEnableCrafting
  • +
    + +
  • AmmoFN57x28mm
  • +
    +
    + + + Ammo_FN57x28mm_FMJ + + + Things/Ammo/Pistol/FMJ + Graphic_StackCount + + + 0.04 + + FullMetalJacket + Bullet_FN57x28mm_FMJ + + + + Ammo_FN57x28mm_AP + + + Things/Ammo/Pistol/AP + Graphic_StackCount + + + 0.05 + + ArmorPiercing + Bullet_FN57x28mm_AP + + + + Ammo_FN57x28mm_HP + + + Things/Ammo/Pistol/HP + Graphic_StackCount + + + 0.05 + + HollowPoint + Bullet_FN57x28mm_HP + + + + + + + Things/Projectile/Bullet_Small + Graphic_Single + + + Bullet + 163 + true + + + + + Bullet_FN57x28mm_FMJ + + + 7 + 0.312 + + + + + Bullet_FN57x28mm_AP + + + 4 + 0.462 + + + + + Bullet_FN57x28mm_HP + + + 10 + 0.162 + + + + + + + MakeAmmo_FN57x28mm_FMJ + + Craft 250 FN 5.7x28mm (FMJ) cartridges. + Making FN 5.7x28mm (FMJ) cartridges. + +
  • + + +
  • Steel
  • + + + 8 + +
    + + +
  • Steel
  • +
    +
    + + 500 + + 1500 +
    + + + MakeAmmo_FN57x28mm_AP + + Craft 250 FN 5.7x28mm (AP) cartridges. + Making FN 5.7x28mm (AP) cartridges. + +
  • + + +
  • Steel
  • + + + 9 + +
    + + +
  • Steel
  • +
    +
    + + 500 + + 2000 +
    + + + MakeAmmo_FN57x28mm_HP + + Craft 250 FN 5.7x28mm (HP) cartridges. + Making FN 5.7x28mm (HP) cartridges. + +
  • + + +
  • Steel
  • + + + 8 + +
    + + +
  • Steel
  • +
    +
    + + 500 + + 2500 +
    + +
    \ No newline at end of file diff --git a/Defs/Ammo/Projectiles_Fragments.xml b/Defs/Ammo/Projectiles_Fragments.xml new file mode 100644 index 0000000000..72753863b1 --- /dev/null +++ b/Defs/Ammo/Projectiles_Fragments.xml @@ -0,0 +1,58 @@ + + + + + + + Fragment_Shell + + + Things/Projectile/Fragments/Fragment_Medium + Graphic_Single + + + Fragment + 18 + 50 + 0.25 + 10 + + + + + + + Fragment_GrenadeFrag + + + Things/Projectile/Fragments/Fragment_Medium + Graphic_Single + + + Fragment + 12 + 30 + 0.25 + 10 + + + + + + + Fragment_RocketFrag + + + Things/Projectile/Fragments/Fragment_Small + Graphic_Single + + + Fragment + 14 + 40 + 0.25 + 10 + + + + \ No newline at end of file diff --git a/Defs/RecipeDefs_Ammo/Recipes_HandGrenades.xml b/Defs/Ammo/Recipes_HandGrenades.xml similarity index 54% rename from Defs/RecipeDefs_Ammo/Recipes_HandGrenades.xml rename to Defs/Ammo/Recipes_HandGrenades.xml index a851116344..1e0376cbb5 100644 --- a/Defs/RecipeDefs_Ammo/Recipes_HandGrenades.xml +++ b/Defs/Ammo/Recipes_HandGrenades.xml @@ -1,12 +1,6 @@  - - -
  • TableMachining
  • -
    -
    - MakeFragGrenade @@ -161,4 +155,140 @@ + + MakeStickBomb + + Craft 10 stick bombs. + Making stick bombs. + +
  • ElectricSmithy
  • +
  • FueledSmithy
  • +
  • CraftingSpot
  • +
    + +
  • + + +
  • WoodLog
  • + + + 5 + +
  • + + +
  • FSX
  • + + + 1 + +
  • + + +
  • Cloth
  • + + + 5 + +
    + + +
  • WoodLog
  • +
  • FSX
  • +
  • Cloth
  • +
    +
    + + 10 + +
    + + + MakeSmokeGrenade + + Craft 10 smoke grenades. + Making smoke grenades. + +
  • + + +
  • Steel
  • + + + 10 + +
  • + + +
  • Chemfuel
  • + + + 1 + +
  • + + +
  • Component
  • + + + 1 + +
    + + +
  • Steel
  • +
  • Chemfuel
  • +
  • Component
  • +
    +
    + + 10 + +
    + + + MakeFirefoamGrenade + + Craft 10 firefoam grenades. + Making firefoam grenades. + +
  • + + +
  • Steel
  • + + + 10 + +
  • + + +
  • MeatRaw
  • + + + 2 + +
  • + + +
  • Component
  • + + + 1 + +
    + + +
  • Steel
  • +
  • Component
  • +
    + +
  • MeatRaw
  • +
    +
    + + 10 + +
    +
    diff --git a/Defs/Ammo/Rifle/303British.xml b/Defs/Ammo/Rifle/303British.xml new file mode 100644 index 0000000000..f320b3d4d0 --- /dev/null +++ b/Defs/Ammo/Rifle/303British.xml @@ -0,0 +1,202 @@ + + + + + Ammo303British + + AmmoRifles + + + + + + AmmoSet_303British + + + Bullet_303British_FMJ + Bullet_303British_AP + Bullet_303British_HP + + + + + + + Large rifle bullet found mostly in outdated bolt-action firearms. + + 0.03 + 0.05 + + +
  • CE_AutoEnableTrade
  • +
  • CE_AutoEnableCrafting
  • +
    + +
  • Ammo303British
  • +
    +
    + + + Ammo_303British_FMJ + + + Things/Ammo/Rifle/FMJ + Graphic_StackCount + + + 0.11 + + FullMetalJacket + Bullet_303British_FMJ + + + + Ammo_303British_AP + + + Things/Ammo/Rifle/AP + Graphic_StackCount + + + 0.15 + + ArmorPiercing + Bullet_303British_AP + + + + Ammo_303British_HP + + + Things/Ammo/Rifle/HP + Graphic_StackCount + + + 0.15 + + HollowPoint + Bullet_303British_HP + + + + + + + Things/Projectile/Bullet_Small + Graphic_Single + + + Bullet + 186 + true + + + + + Bullet_303British_FMJ + + + 18 + 0.589 + + + + + Bullet_303British_AP + + + 11 + 0.739 + + + + + Bullet_303British_HP + + + 25 + 0.439 + + + + + + + MakeAmmo_303British_FMJ + + Craft 500 .303 British (FMJ) cartridges. + Making .303 British (FMJ) cartridges. + +
  • + + +
  • Steel
  • + + + 21 + +
    + + +
  • Steel
  • +
    +
    + + 500 + + 3750 +
    + + + MakeAmmo_303British_AP + + Craft 500 .303 British (AP) cartridges. + Making .303 British (AP) cartridges. + +
  • + + +
  • Steel
  • + + + 26 + +
    + + +
  • Steel
  • +
    +
    + + 500 + + 6000 +
    + + + MakeAmmo_303British_HP + + Craft 500 .303 British (HP) cartridges. + Making .303 British (HP) cartridges. + +
  • + + +
  • Steel
  • + + + 21 + +
    + + +
  • Steel
  • +
    +
    + + 500 + + 8750 +
    + +
    \ No newline at end of file diff --git a/Defs/Ammo/Rifle/545x39mmSoviet.xml b/Defs/Ammo/Rifle/545x39mmSoviet.xml new file mode 100644 index 0000000000..0b9d3d4f64 --- /dev/null +++ b/Defs/Ammo/Rifle/545x39mmSoviet.xml @@ -0,0 +1,202 @@ + + + + + Ammo545x39mmSoviet + + AmmoRifles + + + + + + AmmoSet_545x39mmSoviet + + + Bullet_545x39mmSoviet_FMJ + Bullet_545x39mmSoviet_AP + Bullet_545x39mmSoviet_HP + + + + + + + Small, high-velocity rifle bullet used in a variety of assault rifles. + + 0.01 + 0.03 + + +
  • CE_AutoEnableTrade
  • +
  • CE_AutoEnableCrafting
  • +
    + +
  • Ammo545x39mmSoviet
  • +
    +
    + + + Ammo_545x39mmSoviet_FMJ + + + Things/Ammo/Rifle/FMJ + Graphic_StackCount + + + 0.07 + + FullMetalJacket + Bullet_545x39mmSoviet_FMJ + + + + Ammo_545x39mmSoviet_AP + + + Things/Ammo/Rifle/AP + Graphic_StackCount + + + 0.08 + + ArmorPiercing + Bullet_545x39mmSoviet_AP + + + + Ammo_545x39mmSoviet_HP + + + Things/Ammo/Rifle/HP + Graphic_StackCount + + + 0.08 + + HollowPoint + Bullet_545x39mmSoviet_HP + + + + + + + Things/Projectile/Bullet_Small + Graphic_Single + + + Bullet + 220 + true + + + + + Bullet_545x39mmSoviet_FMJ + + + 10 + 0.453 + + + + + Bullet_545x39mmSoviet_AP + + + 6 + 0.603 + + + + + Bullet_545x39mmSoviet_HP + + + 14 + 0.303 + + + + + + + MakeAmmo_545x39mmSoviet_FMJ + + Craft 500 5.45x39mm Soviet (FMJ) cartridges. + Making 5.45x39mm Soviet (FMJ) cartridges. + +
  • + + +
  • Steel
  • + + + 12 + +
    + + +
  • Steel
  • +
    +
    + + 500 + + 2250 +
    + + + MakeAmmo_545x39mmSoviet_AP + + Craft 500 5.45x39mm Soviet (AP) cartridges. + Making 5.45x39mm Soviet (AP) cartridges. + +
  • + + +
  • Steel
  • + + + 14 + +
    + + +
  • Steel
  • +
    +
    + + 500 + + 3250 +
    + + + MakeAmmo_545x39mmSoviet_HP + + Craft 500 5.45x39mm Soviet (HP) cartridges. + Making 5.45x39mm Soviet (HP) cartridges. + +
  • + + +
  • Steel
  • + + + 12 + +
    + + +
  • Steel
  • +
    +
    + + 500 + + 4250 +
    + +
    \ No newline at end of file diff --git a/Defs/Ammo/Rifle/556x45mmNATO.xml b/Defs/Ammo/Rifle/556x45mmNATO.xml new file mode 100644 index 0000000000..4a4c9bc36b --- /dev/null +++ b/Defs/Ammo/Rifle/556x45mmNATO.xml @@ -0,0 +1,203 @@ + + + + + Ammo556x45mmNATO + + AmmoRifles + + + + + + AmmoSet_556x45mmNATO + + + Bullet_556x45mmNATO_FMJ + Bullet_556x45mmNATO_AP + Bullet_556x45mmNATO_HP + + + + + + + Small, high-velocity rifle bullet used in a variety of assault rifles. + + 0.012 + 0.03 + + +
  • CE_AutoEnableTrade
  • +
  • CE_AutoEnableCrafting
  • +
    + +
  • Ammo556x45mmNATO
  • +
    +
    + + + Ammo_556x45mmNATO_FMJ + + + Things/Ammo/Rifle/FMJ + Graphic_StackCount + + + 0.07 + + FullMetalJacket + Bullet_556x45mmNATO_FMJ + + + + Ammo_556x45mmNATO_AP + + + Things/Ammo/Rifle/AP + Graphic_StackCount + + + 0.09 + + ArmorPiercing + Bullet_556x45mmNATO_AP + + + + Ammo_556x45mmNATO_HP + + + Things/Ammo/Rifle/HP + Graphic_StackCount + + + 0.09 + + HollowPoint + Bullet_556x45mmNATO_HP + + + + + + + Things/Projectile/Bullet_Small + Graphic_Single + + + Bullet + 231 + true + + + + + + Bullet_556x45mmNATO_FMJ + + + 11 + 0.485 + + + + + Bullet_556x45mmNATO_AP + + + 7 + 0.635 + + + + + Bullet_556x45mmNATO_HP + + + 15 + 0.335 + + + + + + + MakeAmmo_556x45mmNATO_FMJ + + Craft 500 5.56x45mm NATO (FMJ) cartridges. + Making 5.56x45mm NATO (FMJ) cartridges. + +
  • + + +
  • Steel
  • + + + 12 + +
    + + +
  • Steel
  • +
    +
    + + 500 + + 2250 +
    + + + MakeAmmo_556x45mmNATO_AP + + Craft 500 5.56x45mm NATO (AP) cartridges. + Making 5.56x45mm NATO (AP) cartridges. + +
  • + + +
  • Steel
  • + + + 14 + +
    + + +
  • Steel
  • +
    +
    + + 500 + + 3500 +
    + + + MakeAmmo_556x45mmNATO_HP + + Craft 500 5.56x45mm NATO (HP) cartridges. + Making 5.56x45mm NATO (HP) cartridges. + +
  • + + +
  • Steel
  • + + + 14 + +
    + + +
  • Steel
  • +
    +
    + + 500 + + 5000 +
    + +
    \ No newline at end of file diff --git a/Defs/Ammo/Rifle/56-56Spencer.xml b/Defs/Ammo/Rifle/56-56Spencer.xml new file mode 100644 index 0000000000..c734aff841 --- /dev/null +++ b/Defs/Ammo/Rifle/56-56Spencer.xml @@ -0,0 +1,92 @@ + + + + + Ammo5656Spencer + + AmmoRifles + + + + + + AmmoSet_5656Spencer + + + Bullet_5656Spencer + + + + + + + Ammo_5656SpencerRimfire + + Ancient cartridge for use in the Spencer repeating rifle. + +
  • CR_AutoEnableTrade
  • +
  • CR_AutoEnableCrafting
  • +
    + +
  • Ammo5656Spencer
  • +
    + + Things/Ammo/Rifle/FMJ + Graphic_StackCount + + + 0.08 + 0.01 + 0.03 + + FullMetalJacket + Bullet_5656Spencer +
    + + + + + Bullet_5656Spencer + + + Things/Projectile/Bullet_Small + Graphic_Single + + + Bullet + 25 + 0.466 + 92 + true + + + + + + + MakeAmmo_5656SpencerRimfire + + Craft 500 .56-56 Spencer rimfire cartridges. + Making .56-56 Spencer rimfire cartridges. + +
  • + + +
  • Steel
  • + + + 8 + +
    + + +
  • Steel
  • +
    +
    + + 500 + + 3000 +
    + +
    \ No newline at end of file diff --git a/Defs/Ammo/Rifle/762x39mmSoviet.xml b/Defs/Ammo/Rifle/762x39mmSoviet.xml new file mode 100644 index 0000000000..8383d78ab5 --- /dev/null +++ b/Defs/Ammo/Rifle/762x39mmSoviet.xml @@ -0,0 +1,214 @@ + + + + + Ammo762x39mmSoviet + + AmmoRifles + + + + + + AmmoSet_762x39mmSoviet + + + Bullet_762x39mmSoviet_FMJ + Bullet_762x39mmSoviet_AP + Bullet_762x39mmSoviet_HP + + + + + + + Intermediate rifle cartridge used by certain older assault rifles. + + 0.02 + 0.04 + + +
  • CE_AutoEnableTrade
  • +
  • CE_AutoEnableCrafting
  • +
    + +
  • Ammo762x39mmSoviet
  • +
    +
    + + + Ammo_762x39mmSoviet_FMJ + + + Things/Ammo/Rifle/FMJ + Graphic_StackCount + + + 0.09 + + FullMetalJacket + Bullet_762x39mmSoviet_FMJ + + + + Ammo_762x39mmSoviet_AP + + + Things/Ammo/Rifle/AP + Graphic_StackCount + + + 0.12 + + ArmorPiercing + Bullet_762x39mmSoviet_AP + + + + Ammo_762x39mmSoviet_HP + + + Things/Ammo/Rifle/HP + Graphic_StackCount + + + 0.12 + + HollowPoint + Bullet_762x39mmSoviet_HP + + + + + + + Things/Projectile/Bullet_Small + Graphic_Single + + + Bullet + 180 + true + + + + + Bullet_762x39mmSoviet_FMJ + + + Things/Projectile/Bullet_Small + Graphic_Single + + + 16 + 0.516 + + + + + Bullet_762x39mmSoviet_AP + + + Things/Projectile/Bullet_Small + Graphic_Single + + + 10 + 0.666 + + + + + Bullet_762x39mmSoviet_HP + + + Things/Projectile/Bullet_Small + Graphic_Single + + + 22 + 0.366 + + + + + + + MakeAmmo_762x39mmSoviet_FMJ + + Craft 500 7.62x39mm Soviet (FMJ) cartridges. + Making 7.62x39mm Soviet (FMJ) cartridges. + +
  • + + +
  • Steel
  • + + + 16 + +
    + + +
  • Steel
  • +
    +
    + + 500 + + 3000 +
    + + + MakeAmmo_762x39mmSoviet_AP + + Craft 500 7.62x39mm Soviet (AP) cartridges. + Making 7.62x39mm Soviet (AP) cartridges. + +
  • + + +
  • Steel
  • + + + 19 + +
    + + +
  • Steel
  • +
    +
    + + 500 + + 5000 +
    + + + MakeAmmo_762x39mmSoviet_HP + + Craft 500 7.62x39mm Soviet (HP) cartridges. + Making 7.62x39mm Soviet (HP) cartridges. + +
  • + + +
  • Steel
  • + + + 16 + +
    + + +
  • Steel
  • +
    +
    + + 500 + + 7000 +
    + +
    \ No newline at end of file diff --git a/Defs/Ammo/Rifle/762x51mmNATO.xml b/Defs/Ammo/Rifle/762x51mmNATO.xml new file mode 100644 index 0000000000..0119d69094 --- /dev/null +++ b/Defs/Ammo/Rifle/762x51mmNATO.xml @@ -0,0 +1,199 @@ + + + + + Ammo762x51mmNATO + + AmmoRifles + + + + + + AmmoSet_762x51mmNATO + + + Bullet_762x51mmNATO_FMJ + Bullet_762x51mmNATO_AP + Bullet_762x51mmNATO_HP + + + + + + + Large rifle bullet used in machine guns, sniper rifles and the occasional assault rifle. + + 0.02 + 0.05 + + +
  • CE_AutoEnableTrade
  • +
  • CE_AutoEnableCrafting
  • +
    + +
  • Ammo762x51mmNATO
  • +
    +
    + + + Ammo_762x51mmNATO_FMJ + + + Things/Ammo/Rifle/FMJ + Graphic_StackCount + + + 0.11 + + FullMetalJacket + Bullet_762x51mmNATO_FMJ + + + + Ammo_762x51mmNATO_AP + + + Things/Ammo/Rifle/AP + Graphic_StackCount + + + 0.15 + + ArmorPiercing + Bullet_762x51mmNATO_AP + + + + Ammo_762x51mmNATO_HP + + + Things/Ammo/Rifle/HP + Graphic_StackCount + + + 0.11 + + HollowPoint + Bullet_762x51mmNATO_HP + + + + + + + Things/Projectile/Bullet_Small + Graphic_Single + + + Bullet + 210 + true + + + + + Bullet_762x51mmNATO_FMJ + + + 18 + 0.601 + + + + + Bullet_762x51mmNATO_AP + + + 11 + 0.751 + + + + + Bullet_762x51mmNATO_HP + + + 25 + 0.451 + + + + + + + MakeAmmo_762x51mmNATO_FMJ + + Craft 500 7.62x51mm NATO (FMJ) cartridges. + Making 7.62x51mm NATO (FMJ) cartridges. + +
  • + + +
  • Steel
  • + + + 21 + +
    + + +
  • Steel
  • +
    +
    + + 500 + +
    + + + MakeAmmo_762x51mmNATO_AP + + Craft 500 7.62x51mm NATO (AP) cartridges. + Making 7.62x51mm NATO (AP) cartridges. + +
  • + + +
  • Steel
  • + + + 26 + +
    + + +
  • Steel
  • +
    +
    + + 500 + +
    + + + MakeAmmo_762x51mmNATO_HP + + Craft 500 7.62x51mm NATO (HP) cartridges. + Making 7.62x51mm NATO (HP) cartridges. + +
  • + + +
  • Steel
  • + + + 21 + +
    + + +
  • Steel
  • +
    +
    + + 500 + +
    + +
    \ No newline at end of file diff --git a/Defs/Ammo/Rifle/762x54mmR.xml b/Defs/Ammo/Rifle/762x54mmR.xml new file mode 100644 index 0000000000..24e45f9edb --- /dev/null +++ b/Defs/Ammo/Rifle/762x54mmR.xml @@ -0,0 +1,202 @@ + + + + + Ammo762x54mmR + + AmmoRifles + + + + + + AmmoSet_762x54mmR + + + Bullet_762x54mmR_FMJ + Bullet_762x54mmR_AP + Bullet_762x54mmR_HP + + + + + + + Rimmed rifle cartridge used by many machine guns, bolt-action and sniper rifles. + + 0.03 + 0.05 + + +
  • CE_AutoEnableTrade
  • +
  • CE_AutoEnableCrafting
  • +
    + +
  • Ammo762x54mmR
  • +
    +
    + + + Ammo_762x54mmR_FMJ + + + Things/Ammo/Rifle/FMJ + Graphic_StackCount + + + 0.11 + + FullMetalJacket + Bullet_762x54mmR_FMJ + + + + Ammo_762x54mmR_AP + + + Things/Ammo/Rifle/AP + Graphic_StackCount + + + 0.16 + + ArmorPiercing + Bullet_762x54mmR_AP + + + + Ammo_762x54mmR_HP + + + Things/Ammo/Rifle/HP + Graphic_StackCount + + + 0.16 + + HollowPoint + Bullet_762x54mmR_HP + + + + + + + Things/Projectile/Bullet_Small + Graphic_Single + + + Bullet + 207 + true + + + + + Bullet_762x54mmR_FMJ + + + 19 + 0.602 + + + + + Bullet_762x54mmR_AP + + + 11 + 0.752 + + + + + Bullet_762x54mmR_HP + + + 27 + 0.452 + + + + + + + MakeAmmo_762x54mmR_FMJ + + Craft 500 7.62x54mmR (FMJ) cartridges. + Making 7.62x54mmR (FMJ) cartridges. + +
  • + + +
  • Steel
  • + + + 21 + +
    + + +
  • Steel
  • +
    +
    + + 500 + + 3750 +
    + + + MakeAmmo_762x54mmR_AP + + Craft 500 7.62x54mmR (AP) cartridges. + Making 7.62x54mmR (AP) cartridges. + +
  • + + +
  • Steel
  • + + + 26 + +
    + + +
  • Steel
  • +
    +
    + + 500 + + 6500 +
    + + + MakeAmmo_762x54mmR_HP + + Craft 500 7.62x54mmR (HP) cartridges. + Making 7.62x54mmR (HP) cartridges. + +
  • + + +
  • Steel
  • + + + 21 + +
    + + +
  • Steel
  • +
    +
    + + 500 + + 9250 +
    + +
    \ No newline at end of file diff --git a/Defs/Ammo/Rocket/M72LAW.xml b/Defs/Ammo/Rocket/M72LAW.xml new file mode 100644 index 0000000000..4e3c41f949 --- /dev/null +++ b/Defs/Ammo/Rocket/M72LAW.xml @@ -0,0 +1,34 @@ + + + + + + + Bullet_M72LAW + + + Things/Projectile/RPG/HEAT + Graphic_Single + TransparentPostLight + + + Bullet + 100 + 2.1 + 40 + RocketPropelledLoop_Small + + +
  • + 20 + Bomb + 1 + + 20 + + MortarBomb_Explode +
  • +
    +
    + +
    \ No newline at end of file diff --git a/Defs/Ammo/Rocket/RPG7.xml b/Defs/Ammo/Rocket/RPG7.xml new file mode 100644 index 0000000000..2734db2db3 --- /dev/null +++ b/Defs/Ammo/Rocket/RPG7.xml @@ -0,0 +1,336 @@ + + + + + AmmoRPG7Grenades + + AmmoRockets + + + + + + AmmoSet_RPG7Grenade + + + Bullet_RPG7Grenade_HEAT + Bullet_RPG7Grenade_Thermobaric + Bullet_RPG7Grenade_Frag + + + + + + + Rocket-propelled grenade designed for the RPG-7 launcher. After being fired a rocket motor kicks in to propel the grenade further. + + 150 + + +
  • CE_AutoEnableTrade
  • +
  • CE_AutoEnableCrafting
  • +
    + +
  • AmmoRPG7Grenades
  • +
    + 25 + 40 + MortarBomb_Explode +
    + + + Ammo_RPG7Grenade_HEAT + + + Things/Ammo/RPG/HEAT + Graphic_StackCount + + + 23.23 + 2.6 + 4 + + RocketHEAT + +
  • + 30 + Bomb + 1 + 6 + + 30 + + MortarBomb_Explode +
  • +
    +
    + + + Ammo_RPG7Grenade_Thermobaric + + + Things/Ammo/RPG/Thermobaric + Graphic_StackCount + + + 37.03 + 4.5 + 6 + + RocketThermobaric + +
  • + 40 + Thermobaric + 4.0 + true + MortarBomb_Explode +
  • +
    +
    + + + Ammo_RPG7Grenade_Frag + + + Things/Ammo/RPG/Frag + Graphic_StackCount + + + 18.17 + 2 + 6 + + RocketFrag + +
  • + 30 + Bomb + 1 + + 300 + + MortarBomb_Explode +
  • +
    +
    + + + + + + TransparentPostLight + + + 65 + RocketPropelledLoop_Small + + + + + Bullet_RPG7Grenade_HEAT + + + Things/Projectile/RPG/HEAT + Graphic_Single + + + Bullet + 150 + 3.0 + + +
  • + 30 + Bomb + 1 + + 30 + + MortarBomb_Explode +
  • +
    +
    + + + Bullet_RPG7Grenade_Thermobaric + + + Things/Projectile/RPG/Thermobaric + Graphic_Single + + + 1.7 + Thermobaric + 50 + + +
  • + 40 + Thermobaric + 4.0 + true + MortarBomb_Explode +
  • +
    +
    + + + Bullet_RPG7Grenade_Frag + CombatExtended.ProjectileCE_Explosive + + + Things/Projectile/RPG/Frag + Graphic_Single + + + 1.7 + Bomb + 50 + + +
  • + 9 + + 300 + + MortarBomb_Explode +
  • +
    +
    + + + + + MakeAmmo_RPG7Grenade_HEAT + + Craft 5 RPG-7 HEAT grenades. + Making RPG-7 HEAT grenades. + 15000 + +
  • + + +
  • Steel
  • + + + 13 + +
  • + + +
  • FSX
  • + + + 3 + +
  • + + +
  • Component
  • + + + 3 + +
    + + +
  • Steel
  • +
  • FSX
  • +
  • Component
  • +
    +
    + + 5 + +
    + + + MakeAmmo_RPG7Grenade_Thermobaric + + Craft 5 RPG-7 thermobaric grenades. + Making RPG-7 thermobaric grenades. + 15000 + +
  • + + +
  • Steel
  • + + + 13 + +
  • + + +
  • FSX
  • + + + 9 + +
  • + + +
  • Component
  • + + + 3 + +
    + + +
  • Steel
  • +
  • FSX
  • +
  • Component
  • +
    +
    + + 5 + +
    + + + MakeAmmo_RPG7Grenade_Frag + + Craft 5 RPG-7 frag grenades. + Making RPG-7 frag grenades. + 15000 + +
  • + + +
  • Steel
  • + + + 7 + +
  • + + +
  • FSX
  • + + + 2 + +
  • + + +
  • Component
  • + + + 3 + +
    + + +
  • Steel
  • +
  • FSX
  • +
  • Component
  • +
    +
    + + 5 + +
    + +
    \ No newline at end of file diff --git a/Defs/Ammo/Shell/81mmMortar.xml b/Defs/Ammo/Shell/81mmMortar.xml new file mode 100644 index 0000000000..28406b9aef --- /dev/null +++ b/Defs/Ammo/Shell/81mmMortar.xml @@ -0,0 +1,325 @@ + + + + + Ammo81mmMortarShells + + AmmoShells + + + + + + AmmoSet_81mmMortarShell + + + + Bullet_81mmMortarShell_HE + Bullet_81mmMortarShell_Incendiary + Bullet_81mmMortarShell_EMP + + + + + + + Low-velocity shell designed to be fired from a mortar. + + 200 + + +
  • Ammo81mmMortarShells
  • +
    + +
  • CE_AutoEnableTrade
  • +
  • CE_AutoEnableCrafting
  • +
    + 25 + 30 + MortarBomb_Explode +
    + + + + MortarShell + + + Things/Ammo/Mortar/HE + Graphic_Single + + + 28.52 + 4.24 + 5 + + GrenadeHE + +
  • + 50 + Bomb + 2.5 + + 300 + +
  • +
    +
    + + + Ammo_81mmMortarShell_Incendiary + + + Things/Ammo/Mortar/Incendiary + Graphic_Single + + + 23.92 + 4.1 + 5.5 + + GrenadeIncendiary + +
  • + Flame + 50 + 3.5 + FilthFuel + 0.5 + MortarIncendiary_Explode + + 20 + +
  • +
    +
    + + + Ammo_81mmMortarShell_EMP + + + Things/Ammo/Mortar/EMP + Graphic_Single + + + 19.78 + 4.5 + 6 + + GrenadeEMP + +
  • + 10 + Bomb + 1 + + 20 + +
  • +
    +
    + + + + + CombatExtended.ProjectileCE_Explosive + + TransparentPostLight + + + 100 + ArtilleryHitThickRoof + MortarRound_PreImpact + MortarRound_Ambient + true + true + Mote_BigShell + + + + + Bullet_81mmMortarShell_HE + + + Things/Projectile/Mortar/HE + Graphic_Single + + + Bomb + 150 + 1 + MortarBomb_Explode + + +
  • + 100 + Bomb + 2.5 + + 300 + +
  • +
    +
    + + + Bullet_81mmMortarShell_Incendiary + + + Things/Projectile/Mortar/Incendiary + Graphic_Single + + + Flame + 50 + 3.5 + FilthFuel + 0.5 + MortarIncendiary_Explode + + + + + Bullet_81mmMortarShell_EMP + + + Things/Projectile/Mortar/EMP + Graphic_Single + + + EMP + 80 + 5 + MortarBomb_Explode + + +
  • + 20 + Electrical + 5 +
  • +
    +
    + + + + + MakeMortarShell + + Craft 5 81mm HE mortar shells. + Making 81mm HE mortar shells. + +
  • + + +
  • Steel
  • + + + 22 + +
  • + + +
  • FSX
  • + + + 5 + +
  • + + +
  • Component
  • + + + 2 + +
    + + +
  • Steel
  • +
  • FSX
  • +
  • Component
  • +
    +
    + + 5 + +
    + + + MakeAmmo_81mmMortarShell_Incendiary + + Craft 5 81mm incendiary mortar shells. + Making 81mm incendiary mortar shells. + +
  • + + +
  • Steel
  • + + + 22 + +
  • + + +
  • Prometheum
  • + + + 5 + +
  • + + +
  • Component
  • + + + 2 + +
    + + +
  • Steel
  • +
  • Prometheum
  • +
  • Component
  • +
    +
    + + 5 + +
    + + + MakeAmmo_81mmMortarShell_EMP + + Craft 5 81mm EMP mortar shells. + Making 81mm EMP mortar shells. + +
  • + + +
  • Steel
  • + + + 22 + +
  • + + +
  • Component
  • + + + 7 + +
    + + +
  • Steel
  • +
  • Component
  • +
    +
    + + 5 + +
    + +
    \ No newline at end of file diff --git a/Defs/Ammo/Shell/90mmCannon.xml b/Defs/Ammo/Shell/90mmCannon.xml new file mode 100644 index 0000000000..535ecb3a04 --- /dev/null +++ b/Defs/Ammo/Shell/90mmCannon.xml @@ -0,0 +1,326 @@ + + + + + Ammo90mmCannonShells + + AmmoShells + + + + + + AmmoSet_90mmCannonShell + + + Bullet_90mmCannonShell_HEAT + Bullet_90mmCannonShell_HE + Bullet_90mmCannonShell_EMP + + + + + + + Relatively small cannon shell. + +
  • Ammo90mmCannonShells
  • +
    + 25 + +
  • CE_AutoEnableTrade
  • +
  • CE_AutoEnableCrafting
  • +
    + + 200 + 10 + 7 + + 30 + MortarBomb_Explode +
    + + + Ammo_90mmCannonShell_HEAT + + + Things/Ammo/Cannon/HEAT + Graphic_Single + + + 27.83 + + RocketHEAT + +
  • + 25 + Bomb + 1.5 + + 100 + +
  • +
    +
    + + + Ammo_90mmCannonShell_HE + + + Things/Ammo/Cannon/HE + Graphic_Single + + + 28.98 + + GrenadeHE + +
  • + 50 + Bomb + 2.5 + + 300 + + 10 +
  • +
    +
    + + + Ammo_90mmCannonShell_EMP + + + Things/Ammo/Cannon/EMP + Graphic_Single + + + 34.73 + + GrenadeEMP + +
  • + 15 + Bomb + 1.5 + + 30 + +
  • +
    +
    + + + + + + TransparentPostLight + + + 155 + MortarBomb_Explode + false + true + Mote_BigShell + + + + + Bullet_90mmCannonShell_HEAT + + + Things/Projectile/Cannon/HEAT + Graphic_Single + + + Bullet + 200 + MortarBomb_Explode + 5.0 + + +
  • + 50 + Bomb + 1.5 + + 100 + + 7.5 +
  • +
    +
    + + + Bullet_90mmCannonShell_HE + + CombatExtended.ProjectileCE_Explosive + + Things/Projectile/Cannon/HE + Graphic_Single + + + Bomb + 150 + 1.7 + MortarBomb_Explode + + +
  • + 100 + Bomb + 2.5 + + 300 + + 10 +
  • +
    +
    + + + Bullet_90mmCannonShell_EMP + + CombatExtended.ProjectileCE_Explosive + + Things/Projectile/Cannon/EMP + Graphic_Single + + + EMP + 80 + 5 + Explosion_Bomb + + +
  • + 20 + Electrical + 5 +
  • +
    +
    + + + + + MakeAmmo_90mmCannonShell_HEAT + + Craft 5 90mm HEAT cannon shells. + Making 90mm HEAT cannon shells. + +
  • + + +
  • Steel
  • + + + 23 + +
  • + + +
  • FSX
  • + + + 3 + +
  • + + +
  • Component
  • + + + 3 + +
    + + +
  • Steel
  • +
  • FSX
  • +
  • Component
  • +
    +
    + + 5 + +
    + + + MakeAmmo_90mmCannonShell_HE + + Craft 5 90mm HE cannon shells. + Making 90mm HE cannon shells. + +
  • + + +
  • Steel
  • + + + 23 + +
  • + + +
  • FSX
  • + + + 5 + +
  • + + +
  • Component
  • + + + 2 + +
    + + +
  • Steel
  • +
  • FSX
  • +
  • Component
  • +
    +
    + + 5 + +
    + + + MakeAmmo_90mmCannonShell_EMP + + Craft 5 90mm EMP cannon shells. + Making 90mm EMP cannon shells. + +
  • + + +
  • Steel
  • + + + 23 + +
  • + + +
  • Component
  • + + + 7 + +
    + + +
  • Steel
  • +
  • Component
  • +
    +
    + + 5 + +
    + +
    \ No newline at end of file diff --git a/Defs/Ammo/Shotgun/12Gauge.xml b/Defs/Ammo/Shotgun/12Gauge.xml new file mode 100644 index 0000000000..27a5db511c --- /dev/null +++ b/Defs/Ammo/Shotgun/12Gauge.xml @@ -0,0 +1,353 @@ + + + + + Ammo12Gauge + + AmmoShotguns + + + + + + AmmoSet_12Gauge + + + Bullet_12Gauge_Buck + Bullet_12Gauge_Bird + Bullet_12Gauge_Slug + Bullet_12Gauge_Beanbag + Bullet_12Gauge_ElectroSlug + + + + + + + Extremely common shotgun caliber used in almost every application, from hunting over riot control to military firearms. + + 0.05 + 0.07 + + +
  • CE_AutoEnableTrade
  • +
  • CE_AutoEnableCrafting
  • +
    + +
  • Ammo12Gauge
  • +
    + 350 +
    + + + Ammo_12Gauge_Buck + + + Things/Ammo/Shotgun/Shot + Graphic_StackCount + + + 0.15 + + BuckShot + Bullet_12Gauge_Buck + + + + Ammo_12Gauge_Bird + + + Things/Ammo/Shotgun/Shot + Graphic_StackCount + + + 0.15 + + BirdShot + Bullet_12Gauge_Bird + + + + Ammo_12Gauge_Slug + + + Things/Ammo/Shotgun/Slug + Graphic_StackCount + + + 0.1 + 0.15 + + Slug + Bullet_12Gauge_Slug + + + + Ammo_12Gauge_Beanbag + + false + + Things/Ammo/Shotgun/Beanbag + Graphic_StackCount + + + 0.18 + + Beanbag + Bullet_12Gauge_Beanbag + + + + Ammo_12Gauge_ElectroSlug + + + Things/Ammo/Shotgun/EMP + Graphic_StackCount + + + 0.43 + + ElectroSlug + Bullet_12Gauge_ElectroSlug + + + + + + + Bullet + 101 + true + Mote_ShotgunShell + + + + + Bullet_12Gauge_Buck + + + Things/Projectile/Shotgun_Pellet + Graphic_Single + + + 7 + 9 + 0.227 + 17.8 + + + + + Bullet_12Gauge_Bird + + + Things/Projectile/Shotgun_Pellet + Graphic_Single + + + 1 + 50 + 71.4 + 0.089 + + + + + Bullet_12Gauge_Slug + + + Things/Projectile/Bullet_big + Graphic_Single + + + 103 + 37 + 0.45 + + + + + Bullet_12Gauge_Beanbag + + + Things/Projectile/Bullet_big + Graphic_Single + + + Beanbag + 6 + 0.151 + 2 + + + + + Bullet_12Gauge_ElectroSlug + + + Things/Projectile/Bullet_big + Graphic_Single + + + EMP + 25 + +
  • + Electrical + 7 +
  • +
    +
    +
    + + + + + MakeAmmo_12Gauge_Buck + + Craft 200 12 gauge (Buck) shells. + Making 12 gauge (Buck) shells. + +
  • + + +
  • Steel
  • + + + 17 + +
    + + +
  • Steel
  • +
    +
    + + 200 + + 5000 +
    + + + MakeAmmo_12Gauge_Bird + + Craft 200 12 gauge (Bird) shells. + Making 12 gauge (Bird) shells. + +
  • + + +
  • Steel
  • + + + 17 + +
    + + +
  • Steel
  • +
    +
    + + 200 + + 5000 +
    + + + MakeAmmo_12Gauge_Slug + + Craft 200 12 gauge (Slug) shells. + Making 12 gauge (Slug) shells. + +
  • + + +
  • Steel
  • + + + 17 + +
    + + +
  • Steel
  • +
    +
    + + 200 + + 4500 +
    + + + MakeAmmo_12Gauge_Beanbag + + Craft 200 12 gauge (Beanbag) shells. + Making 12 gauge (Beanbag) shells. + +
  • + + +
  • Steel
  • + + + 18 + +
  • + + +
  • Cloth
  • + + + 3 + +
    + + +
  • Steel
  • +
  • Cloth
  • +
    +
    + + 200 + + 4250 +
    + + + MakeAmmo_12Gauge_ElectroSlug + + Craft 200 12 gauge (EMP) shells. + Making 12 gauge (EMP) shells. + +
  • + + +
  • Steel
  • + + + 18 + +
  • + + +
  • Component
  • + + + 4 + +
    + + +
  • Steel
  • +
  • Component
  • +
    +
    + + 200 + + 7250 +
    + +
    \ No newline at end of file diff --git a/Defs/Ammo/Shotgun/410Bore.xml b/Defs/Ammo/Shotgun/410Bore.xml new file mode 100644 index 0000000000..16910f4eeb --- /dev/null +++ b/Defs/Ammo/Shotgun/410Bore.xml @@ -0,0 +1,98 @@ + + + + + Ammo410Bore + + AmmoShotguns + + + + + + + + Low caliber shotgun shell. Its small diameter allows it to be fired from many of the same firearms as the .45 Colt cartridge. + + 0.06 + 0.11 + + +
  • CE_AutoEnableTrade
  • +
  • CE_AutoEnableCrafting
  • +
    + +
  • Ammo410Bore
  • +
    + 200 +
    + + + Ammo_410Bore_Buck + + + Things/Ammo/Shotgun/Shot + Graphic_StackCount + + + 0.14 + + BuckShot + Bullet_410Bore_Buck + + + + + + + Bullet + 70 + true + Mote_ShotgunShell + + + + + Bullet_410Bore_Buck + + + Things/Projectile/Shotgun_Pellet + Graphic_Single + + + 10 + 5 + 0.25 + 17.8 + + + + + + + MakeAmmo_410Bore_Buck + + Craft 200 .410 Bore (Buck) shells. + Making .410 Bore (Buck) shells. + +
  • + + +
  • Steel
  • + + + 12 + +
    + + +
  • Steel
  • +
    +
    + + 200 + + 4500 +
    + +
    \ No newline at end of file diff --git a/Defs/Ammo/ThingCategories.xml b/Defs/Ammo/ThingCategories.xml new file mode 100644 index 0000000000..aec522a59f --- /dev/null +++ b/Defs/Ammo/ThingCategories.xml @@ -0,0 +1,64 @@ + + + + + Ammo + + Weapons + + + + AmmoAdvanced + + Ammo + + + + AmmoGrenades + + Ammo + + + + AmmoHighCaliber + + Ammo + + + + AmmoPistols + + Ammo + + + + AmmoRifles + + Ammo + + + + AmmoShotguns + + Ammo + + + + AmmoRockets + + Ammo + + + + AmmoShells + + Ammo + + + + AmmoNeolithic + + Ammo + + + \ No newline at end of file diff --git a/Defs/AmmoCategoryDefs/AmmoCategories_Neolithic.xml b/Defs/AmmoCategoryDefs/AmmoCategories_Neolithic.xml deleted file mode 100644 index f4bf21ba22..0000000000 --- a/Defs/AmmoCategoryDefs/AmmoCategories_Neolithic.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - StoneArrow - - A sharpened stone is attached as an arrow head. Cuts exposed tissue fairly well but is ineffective against any kind of armor. - - - - SteelArrow - - The arrow head is made from steel to enhance armor penetration. - true - - - - PlasteelArrow - - Fitted with a plasteel head to maximize armor penetration. - true - - - \ No newline at end of file diff --git a/Defs/AmmoSetDefs/AmmoSets_Advanced.xml b/Defs/AmmoSetDefs/AmmoSets_Advanced.xml deleted file mode 100644 index 8d9e3c6e6c..0000000000 --- a/Defs/AmmoSetDefs/AmmoSets_Advanced.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - AmmoSet_30x64mmFuel - - -
  • Ammo_30x64mmFuel_Incendiary
  • -
  • Ammo_30x64mmFuel_Thermobaric
  • -
  • Ammo_30x64mmFuel_Foam
  • -
    -
    - - - - - AmmoSet_80x256mmFuel - - -
  • Ammo_80x256mmFuel_Thermobaric
  • -
    -
    - - - - - AmmoSet_6x24mmCharged - - -
  • Ammo_6x24mmCharged
  • -
  • Ammo_6x24mmCharged_AP
  • -
  • Ammo_6x24mmCharged_Ion
  • -
    -
    - - - - - AmmoSet_5x35mmCharged - - -
  • Ammo_5x35mmCharged
  • -
    -
    - - - - - AmmoSet_12x64mmCharged - - -
  • Ammo_12x64mmCharged
  • -
    -
    - -
    \ No newline at end of file diff --git a/Defs/AmmoSetDefs/AmmoSets_Grenades.xml b/Defs/AmmoSetDefs/AmmoSets_Grenades.xml deleted file mode 100644 index a98b717625..0000000000 --- a/Defs/AmmoSetDefs/AmmoSets_Grenades.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - AmmoSet_30x29mmGrenade - - -
  • Ammo_30x29mmGrenade_HE
  • -
  • Ammo_30x29mmGrenade_EMP
  • -
    -
    - - - - - AmmoSet_40x46mmGrenade - - -
  • Ammo_40x46mmGrenade_HE
  • -
  • Ammo_40x46mmGrenade_EMP
  • -
    -
    - -
    \ No newline at end of file diff --git a/Defs/AmmoSetDefs/AmmoSets_HighCaliber.xml b/Defs/AmmoSetDefs/AmmoSets_HighCaliber.xml deleted file mode 100644 index a426657048..0000000000 --- a/Defs/AmmoSetDefs/AmmoSets_HighCaliber.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - AmmoSet_50BMG - - -
  • Ammo_50BMG_FMJ
  • -
  • Ammo_50BMG_AP
  • -
  • Ammo_50BMG_HE
  • -
  • Ammo_50BMG_Incendiary
  • -
    -
    - - - - - AmmoSet_145x114mm - - -
  • Ammo_145x114mm_FMJ
  • -
  • Ammo_145x114mm_HE
  • -
  • Ammo_145x114mm_Incendiary
  • -
    -
    - -
    \ No newline at end of file diff --git a/Defs/AmmoSetDefs/AmmoSets_Neolithic.xml b/Defs/AmmoSetDefs/AmmoSets_Neolithic.xml deleted file mode 100644 index c20391856b..0000000000 --- a/Defs/AmmoSetDefs/AmmoSets_Neolithic.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - AmmoSet_Arrow - - -
  • Ammo_Arrow_Stone
  • -
  • Ammo_Arrow_Steel
  • -
  • Ammo_Arrow_Plasteel
  • -
    -
    - - - - - AmmoSet_GreatArrow - - -
  • Ammo_GreatArrow_Stone
  • -
  • Ammo_GreatArrow_Steel
  • -
  • Ammo_GreatArrow_Plasteel
  • -
    -
    - -
    \ No newline at end of file diff --git a/Defs/AmmoSetDefs/AmmoSets_Pistols.xml b/Defs/AmmoSetDefs/AmmoSets_Pistols.xml deleted file mode 100644 index f37ee2fa18..0000000000 --- a/Defs/AmmoSetDefs/AmmoSets_Pistols.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - AmmoSet_40Rimfire - - -
  • Ammo_40Rimfire
  • -
    -
    - - - - - AmmoSet_32ACP - - -
  • Ammo_32ACP_FMJ
  • - -
    -
    - - - - - AmmoSet_762x25mmTokarev - - -
  • Ammo_762x25mmTokarev_FMJ
  • -
  • Ammo_762x25mmTokarev_AP
  • -
  • Ammo_762x25mmTokarev_HP
  • -
    -
    - - - - - AmmoSet_9x19mmPara - - -
  • Ammo_9x19mmPara_FMJ
  • -
  • Ammo_9x19mmPara_AP
  • -
  • Ammo_9x19mmPara_HP
  • -
    -
    - - - - - AmmoSet_45ACP - - -
  • Ammo_45ACP_FMJ
  • -
  • Ammo_45ACP_AP
  • -
  • Ammo_45ACP_HP
  • -
    -
    - - - - - AmmoSet_45Colt - - -
  • Ammo_45Colt_FMJ
  • -
  • Ammo_45Colt_AP
  • -
  • Ammo_45Colt_HP
  • -
  • Ammo_410Bore_Buck
  • -
    -
    - -
    \ No newline at end of file diff --git a/Defs/AmmoSetDefs/AmmoSets_Rifles.xml b/Defs/AmmoSetDefs/AmmoSets_Rifles.xml deleted file mode 100644 index f1993b9c68..0000000000 --- a/Defs/AmmoSetDefs/AmmoSets_Rifles.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - AmmoSet_556x45mmNATO - - -
  • Ammo_556x45mmNATO_FMJ
  • -
  • Ammo_556x45mmNATO_AP
  • -
  • Ammo_556x45mmNATO_HP
  • -
    -
    - - - - - AmmoSet_762x39mmSoviet - - -
  • Ammo_762x39mmSoviet_FMJ
  • -
  • Ammo_762x39mmSoviet_AP
  • -
  • Ammo_762x39mmSoviet_HP
  • -
    -
    - - - - - AmmoSet_303British - - -
  • Ammo_303British_FMJ
  • -
  • Ammo_303British_AP
  • -
  • Ammo_303British_HP
  • -
    -
    - - - - - AmmoSet_762x51mmNATO - - -
  • Ammo_762x51mmNATO_FMJ
  • -
  • Ammo_762x51mmNATO_AP
  • -
  • Ammo_762x51mmNATO_HP
  • -
    -
    - - - - - AmmoSet_762x54mmR - - -
  • Ammo_762x54mmR_FMJ
  • -
  • Ammo_762x54mmR_AP
  • -
  • Ammo_762x54mmR_HP
  • -
    -
    - -
    \ No newline at end of file diff --git a/Defs/AmmoSetDefs/AmmoSets_Rockets.xml b/Defs/AmmoSetDefs/AmmoSets_Rockets.xml deleted file mode 100644 index efad027b67..0000000000 --- a/Defs/AmmoSetDefs/AmmoSets_Rockets.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - AmmoSet_RPG7Grenade - - -
  • Ammo_RPG7Grenade_HEAT
  • -
  • Ammo_RPG7Grenade_Thermobaric
  • -
  • Ammo_RPG7Grenade_Frag
  • -
    -
    - -
    \ No newline at end of file diff --git a/Defs/AmmoSetDefs/AmmoSets_Shells.xml b/Defs/AmmoSetDefs/AmmoSets_Shells.xml deleted file mode 100644 index 91bb78488a..0000000000 --- a/Defs/AmmoSetDefs/AmmoSets_Shells.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - AmmoSet_81mmMortarShell - - -
  • MortarShell
  • -
  • Ammo_81mmMortarShell_Incendiary
  • -
  • Ammo_81mmMortarShell_EMP
  • -
    -
    - - - - - AmmoSet_90mmCannonShell - - -
  • Ammo_90mmCannonShell_HEAT
  • -
  • Ammo_90mmCannonShell_HE
  • -
  • Ammo_90mmCannonShell_EMP
  • -
    -
    - -
    diff --git a/Defs/AmmoSetDefs/AmmoSets_Shotgun.xml b/Defs/AmmoSetDefs/AmmoSets_Shotgun.xml deleted file mode 100644 index 22d173c2e8..0000000000 --- a/Defs/AmmoSetDefs/AmmoSets_Shotgun.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - AmmoSet_12Gauge - - -
  • Ammo_12Gauge_Buck
  • -
  • Ammo_12Gauge_Bird
  • -
  • Ammo_12Gauge_Slug
  • -
  • Ammo_12Gauge_Beanbag
  • -
  • Ammo_12Gauge_ElectroSlug
  • -
    -
    - -
    \ No newline at end of file diff --git a/Defs/Bodies/Bodies_Animal_Insect.xml b/Defs/Bodies/Bodies_Animal_Insect.xml deleted file mode 100644 index 4c7decd9d6..0000000000 --- a/Defs/Bodies/Bodies_Animal_Insect.xml +++ /dev/null @@ -1,257 +0,0 @@ - - - - - BeetleLike - - - Shell - Middle - Outside - -
  • CoveredByNaturalArmor
  • -
    - -
  • - LeftElytra - 0.05 - -
  • CoveredByNaturalArmor
  • - - -
  • - RightElytra - 0.05 - -
  • CoveredByNaturalArmor
  • - - -
  • - Stomach - 0.05 - Inside - -
  • CoveredByNaturalArmor
  • - - -
  • - InsectHeart - 0.03 - Inside - -
  • CoveredByNaturalArmor
  • - - -
  • - Pronotum - 0.08 - Top - -
  • CoveredByNaturalArmor
  • - - -
  • - InsectHead - 0.65 - -
  • - Brain - 0.2 - Inside -
  • -
  • - LeftEye - 0.15 -
  • -
  • - RightEye - 0.15 -
  • -
  • - LeftAntenna - 0.05 -
  • -
  • - RightAntenna - 0.05 -
  • -
  • - InsectNostril - 0.1 -
  • -
  • - InsectMouth - 0.05 - -
  • Mouth
  • - - -
    - -
    - -
  • - FrontLeftInsectLeg - 0.06 - Bottom -
  • -
  • - FrontRightInsectLeg - 0.06 - Bottom -
  • -
  • - MiddleLeftInsectLeg - 0.06 - Bottom -
  • -
  • - MiddleRightInsectLeg - 0.06 - Bottom -
  • -
  • - RearLeftInsectLeg - 0.06 - Bottom -
  • -
  • - RearRightInsectLeg - 0.06 - Bottom -
  • - -
    -
    - - - BeetleLikeWithClaw - - - Shell - Middle - Outside - -
  • CoveredByNaturalArmor
  • -
    - -
  • - LeftElytra - 0.05 - -
  • CoveredByNaturalArmor
  • - - -
  • - RightElytra - 0.05 - -
  • CoveredByNaturalArmor
  • - - -
  • - Stomach - 0.05 - Inside - -
  • CoveredByNaturalArmor
  • - - -
  • - InsectHeart - 0.03 - Inside - -
  • CoveredByNaturalArmor
  • - - -
  • - Pronotum - 0.08 - Top - -
  • CoveredByNaturalArmor
  • - - -
  • - InsectHead - 0.65 - -
  • - Brain - 0.2 - Inside -
  • -
  • - LeftEye - 0.15 -
  • -
  • - RightEye - 0.15 -
  • -
  • - LeftAntenna - 0.05 -
  • -
  • - RightAntenna - 0.05 -
  • -
  • - InsectNostril - 0.1 -
  • -
  • - InsectMouth - 0.05 - -
  • Mouth
  • - - -
  • - HeadClaw - 0.05 - -
  • HeadClaw
  • - - -
    - -
    - -
  • - FrontLeftInsectLeg - 0.06 - Bottom -
  • -
  • - FrontRightInsectLeg - 0.06 - Bottom -
  • -
  • - MiddleLeftInsectLeg - 0.06 - Bottom -
  • -
  • - MiddleRightInsectLeg - 0.06 - Bottom -
  • -
  • - RearLeftInsectLeg - 0.06 - Bottom -
  • -
  • - RearRightInsectLeg - 0.06 - Bottom -
  • - -
    -
    - -
    \ No newline at end of file diff --git a/Defs/Bodies/Bodies_Humanlike.xml b/Defs/Bodies/Bodies_Humanlike.xml deleted file mode 100644 index 854c1b5ec9..0000000000 --- a/Defs/Bodies/Bodies_Humanlike.xml +++ /dev/null @@ -1,609 +0,0 @@ - - - - - - Human - - - Torso - Middle - Outside - -
  • Torso
  • -
    - -
  • - LeftClavicle - 0.005 - Top - Inside - -
  • Torso
  • - - -
  • - RightClavicle - 0.005 - Top - Inside - -
  • Torso
  • - - -
  • - Sternum - 0.005 - Inside - -
  • Torso
  • - - -
  • - Rib - 0.01 - Inside - -
  • Torso
  • - - -
  • - Rib - 0.01 - Inside - -
  • Torso
  • - - -
  • - Rib - 0.01 - Inside - -
  • Torso
  • - - -
  • - Rib - 0.01 - Inside - -
  • Torso
  • - - -
  • - Rib - 0.01 - Inside - -
  • Torso
  • - - -
  • - Rib - 0.01 - Inside - -
  • Torso
  • - - -
  • - Rib - 0.01 - Inside - -
  • Torso
  • - - -
  • - Rib - 0.01 - Inside - -
  • Torso
  • - - -
  • - Rib - 0.01 - Inside - -
  • Torso
  • - - -
  • - Rib - 0.01 - Inside - -
  • Torso
  • - - -
  • - Rib - 0.01 - Inside - -
  • Torso
  • - - -
  • - Rib - 0.01 - Inside - -
  • Torso
  • - - -
  • - Pelvis - 0.05 - Bottom - Inside - -
  • Torso
  • - - -
  • - Spine - 0.02 - Inside - -
  • Torso
  • - - -
  • - Stomach - 0.05 - Inside - -
  • Torso
  • - - -
  • - Heart - 0.04 - Inside - -
  • Torso
  • - - -
  • - LeftLung - 0.055 - Inside - -
  • Torso
  • - - -
  • - RightLung - 0.055 - Inside - -
  • Torso
  • - - -
  • - LeftKidney - 0.03 - Inside - -
  • Torso
  • - - -
  • - RightKidney - 0.03 - Inside - -
  • Torso
  • - - -
  • - Liver - 0.06 - Inside - -
  • Torso
  • - - -
  • - Neck - 0.055 - Top - -
  • Torso
  • - - -
  • - Head - 0.72 - -
  • UpperHead
  • -
  • FullHead
  • - - -
  • - Skull - 0.18 - Inside - -
  • UpperHead
  • -
  • FullHead
  • - - -
  • - Brain - 0.8 - -
  • UpperHead
  • -
  • FullHead
  • - - -
    - -
  • - LeftEye - 0.05 - -
  • FullHead
  • -
  • Eyes
  • - - -
  • - RightEye - 0.05 - -
  • FullHead
  • -
  • Eyes
  • - - -
  • - LeftEar - 0.05 - -
  • UpperHead
  • -
  • FullHead
  • - - -
  • - RightEar - 0.05 - -
  • UpperHead
  • -
  • FullHead
  • - - -
  • - Nose - 0.08 - -
  • FullHead
  • - - -
  • - Jaw - 0.15 - -
  • Teeth
  • -
  • FullHead
  • - - -
    - -
    - -
  • - LeftShoulder - 0.08 - -
  • Shoulders
  • - - -
  • - LeftArm - 0.95 - -
  • Arms
  • - - -
  • - LeftHumerus - 0.1 - Inside - -
  • Arms
  • - - -
  • - LeftRadius - 0.1 - Inside - -
  • Arms
  • - - -
  • - LeftHand - 0.2 - Bottom - -
  • Hands
  • - - -
  • - LeftHandPinky - 0.05 - -
  • Hands
  • -
  • LeftHand
  • - - -
  • - LeftHandRingFinger - 0.05 - -
  • Hands
  • -
  • LeftHand
  • - - -
  • - LeftHandMiddleFinger - 0.05 - -
  • Hands
  • -
  • LeftHand
  • - - -
  • - LeftHandIndexFinger - 0.05 - -
  • Hands
  • -
  • LeftHand
  • - - -
  • - LeftHandThumb - 0.05 - -
  • Hands
  • -
  • LeftHand
  • - - -
    - -
    - -
    - -
  • - RightShoulder - 0.08 - -
  • Shoulders
  • - - -
  • - RightArm - 0.95 - -
  • Arms
  • - - -
  • - RightHumerus - 0.1 - Inside - -
  • Arms
  • - - -
  • - RightRadius - 0.1 - Inside - -
  • Arms
  • - - -
  • - RightHand - 0.2 - Bottom - -
  • Hands
  • - - -
  • - RightHandPinky - 0.05 - -
  • Hands
  • -
  • RightHand
  • - - -
  • - RightHandRingFinger - 0.05 - -
  • Hands
  • -
  • RightHand
  • - - -
  • - RightHandMiddleFinger - 0.05 - -
  • Hands
  • -
  • RightHand
  • - - -
  • - RightHandIndexFinger - 0.05 - -
  • Hands
  • -
  • RightHand
  • - - -
  • - RightHandThumb - 0.05 - -
  • Hands
  • -
  • RightHand
  • - - -
    - -
    - -
    - -
  • - LeftLeg - 0.1 - Bottom - -
  • Legs
  • - - -
  • - LeftFemur - 0.1 - Inside - -
  • Legs
  • - - -
  • - LeftTibia - 0.1 - Inside - -
  • Legs
  • - - -
  • - LeftFoot - 0.2 - -
  • Feet
  • - - -
  • - LeftFootLittleToe - 0.05 - -
  • Feet
  • - - -
  • - LeftFootFourthToe - 0.05 - -
  • Feet
  • - - -
  • - LeftFootMiddleToe - 0.05 - -
  • Feet
  • - - -
  • - LeftFootSecondToe - 0.05 - -
  • Feet
  • - - -
  • - LeftFootBigToe - 0.05 - -
  • Feet
  • - - -
    - -
    - -
  • - RightLeg - 0.1 - Bottom - -
  • Legs
  • - - -
  • - RightFemur - 0.1 - Inside - -
  • Legs
  • - - -
  • - RightTibia - 0.1 - Inside - -
  • Legs
  • - - -
  • - RightFoot - 0.2 - -
  • Feet
  • - - -
  • - RightFootLittleToe - 0.05 - -
  • Feet
  • - - -
  • - RightFootFourthToe - 0.05 - -
  • Feet
  • - - -
  • - RightFootMiddleToe - 0.05 - -
  • Feet
  • - - -
  • - RightFootSecondToe - 0.05 - -
  • Feet
  • - - -
  • - RightFootBigToe - 0.05 - -
  • Feet
  • - - -
    - -
    - -
    -
    -
    - -
    \ No newline at end of file diff --git a/Defs/Bodies/Bodies_Mechanoid.xml b/Defs/Bodies/Bodies_Mechanoid.xml deleted file mode 100644 index c43a585423..0000000000 --- a/Defs/Bodies/Bodies_Mechanoid.xml +++ /dev/null @@ -1,459 +0,0 @@ - - - - - - MechanicalCentipede - - - MechanicalCentipedeBodyFirstRing - Middle - Outside - -
  • CoveredByNaturalArmor
  • -
    - -
  • - MechanicalPrimaryCapacitor - 0.0875 - Inside -
  • -
  • - MechanicalHead - 0.08 - Top - -
  • HeadAttackTool
  • -
  • CoveredByNaturalArmor
  • - - -
  • - ArtificialBrain - 0.2 - Inside - -
  • CoveredByNaturalArmor
  • - - -
  • - LeftSightSensor - 0.15 -
  • -
  • - RightSightSensor - 0.15 -
  • -
  • - LeftHearingSensor - 0.05 -
  • -
  • - RightHearingSensor - 0.05 -
  • -
  • - SmellSensor - 0.1 -
  • -
    - -
  • - MechanicalCentipedeBodySecondRing - 0.75 - -
  • CoveredByNaturalArmor
  • - - -
  • - MechanicalWeaponActuator - 0.05 - Inside -
  • -
  • - MechanicalSecondaryCapacitor - 0.07 - Inside -
  • -
  • - MechanicalCentipedeBodyThirdRing - 0.8 - -
  • CoveredByNaturalArmor
  • - - -
  • - MechanicalPrimaryPowerCore - 0.125 - Inside -
  • -
  • - MechanicalCoolantTank - 0.06 - Inside -
  • -
  • - MechanicalCentipedeBodyFourthRing - 0.75 - -
  • CoveredByNaturalArmor
  • - - -
  • - MechanicalCoolantPump - 0.04 - Inside -
  • -
  • - MechanicalLeftHeatSink - 0.068 - Inside -
  • -
  • - MechanicalRightHeatSink - 0.068 - Inside -
  • -
  • - MechanicalCentipedeBodyFifthRing - 0.66 - -
  • CoveredByNaturalArmor
  • - - -
  • - MechanicalAuxiliaryPowerCore - 0.25 - Inside -
  • -
  • - MechanicalTertiaryCapacitor - 0.175 - Inside -
  • -
  • - MechanicalCentipedeBodySixthRing - 0.5 - -
  • CoveredByNaturalArmor
  • - - -
    - -
    - -
    - -
    - -
    -
    -
    - - - Scyther - - - MechanicalThorax - Middle - Outside - -
  • CoveredByNaturalArmor
  • -
    - -
  • - MechanicalPrimaryPowerCore - 0.12 - Inside -
  • -
  • - MechanicalPrimaryCapacitor - 0.020 - Inside -
  • -
  • - MechanicalSecondaryCapacitor - 0.020 - Inside -
  • -
  • - MechanicalLeftHeatSink - 0.03 - Inside -
  • -
  • - MechanicalRightHeatSink - 0.03 - Inside -
  • -
  • - MechanicalCoolantPump - 0.01 - Inside -
  • -
  • - MechanicalCoolantTank - 0.06 - Inside -
  • -
  • - MechanicalHydraulicsControl - 0.04 - Inside -
  • -
  • - MechanicalRollerBearing - 0.06 - Inside -
  • -
  • - MechanicalNeck - 0.08 - Top - -
  • CoveredByNaturalArmor
  • - - -
  • - MechanicalHead - 0.75 - -
  • CoveredByNaturalArmor
  • - - -
  • - ArtificialBrain - 0.15 - Inside - -
  • CoveredByNaturalArmor
  • - - -
  • - LeftSightSensor - 0.15 -
  • -
  • - RightSightSensor - 0.15 -
  • -
  • - LeftHearingSensor - 0.05 -
  • -
  • - RightHearingSensor - 0.05 -
  • -
  • - SmellSensor - 0.1 -
  • -
    - -
    - -
  • - LeftMechanicalShoulder - 0.15 - -
  • CoveredByNaturalArmor
  • - - -
  • - LeftMechanicalArm - 0.95 - -
  • CoveredByNaturalArmor
  • - - -
  • - MechanicalLeftUpperActuator - 0.15 - Inside -
  • -
  • - MechanicalLeftUpperPiston - 0.25 - Inside -
  • -
  • - LeftBlade - 0.3 - -
  • LeftBlade
  • - - -
  • - LeftMechanicalHand - 0.2 - Bottom - -
  • CoveredByNaturalArmor
  • - - -
  • - LeftHandMechanicalPinky - 0.05 - -
  • LeftHand
  • - - -
  • - LeftHandMechanicalMiddleFinger - 0.05 - -
  • LeftHand
  • - - -
  • - LeftHandMechanicalIndexFinger - 0.05 - -
  • LeftHand
  • - - -
  • - LeftHandMechanicalThumb - 0.05 - -
  • LeftHand
  • - - -
    - -
    - -
    - -
  • - RightMechanicalShoulder - 0.15 - -
  • CoveredByNaturalArmor
  • - - -
  • - RightMechanicalArm - 0.95 - -
  • CoveredByNaturalArmor
  • - - -
  • - MechanicalRightUpperActuator - 0.15 - Inside -
  • -
  • - MechanicalRightUpperPiston - 0.25 - Inside -
  • -
  • - RightBlade - 0.3 - -
  • RightBlade
  • - - -
  • - RightMechanicalHand - 0.2 - Bottom - -
  • CoveredByNaturalArmor
  • - - -
  • - RightHandMechanicalPinky - 0.05 - -
  • RightHand
  • - - -
  • - RightHandMechanicalMiddleFinger - 0.05 - -
  • RightHand
  • - - -
  • - RightHandMechanicalIndexFinger - 0.05 - -
  • RightHand
  • - - -
  • - RightHandMechanicalThumb - 0.05 - -
  • RightHand
  • - - -
    - -
    - -
    - -
  • - LeftMechanicalLeg - 0.1 - Bottom - -
  • CoveredByNaturalArmor
  • - - -
  • - MechanicalLeftLowerPiston - 0.3 - Inside -
  • -
  • - MechanicalLeftLowerActuator - 0.2 - Inside -
  • -
  • - LeftMechanicalFoot - 0.2 - -
  • CoveredByNaturalArmor
  • - - -
    - -
  • - RightMechanicalLeg - 0.1 - Bottom - -
  • CoveredByNaturalArmor
  • - - -
  • - MechanicalRightLowerPiston - 0.3 - Inside -
  • -
  • - MechanicalRightLowerActuator - 0.2 - Inside -
  • -
  • - RightMechanicalFoot - 0.2 - -
  • CoveredByNaturalArmor
  • - - -
    - -
    -
    -
    - -
    \ No newline at end of file diff --git a/Defs/Bodies/Bodies_Turtle.xml b/Defs/Bodies/Bodies_Turtle.xml deleted file mode 100644 index 262d59f651..0000000000 --- a/Defs/Bodies/Bodies_Turtle.xml +++ /dev/null @@ -1,120 +0,0 @@ - - - - - TurtleLike - - - TurtleShell - Middle - Outside - -
  • CoveredByNaturalArmor
  • -
    - -
  • - Plastron - 0.05 - Bottom - -
  • CoveredByNaturalArmor
  • - - -
  • - Tail - 0.05 -
  • -
  • - Spine - 0.02 - Inside -
  • -
  • - Stomach - 0.05 - Inside -
  • -
  • - Heart - 0.03 - Inside -
  • -
  • - LeftLung - 0.03 - Inside -
  • -
  • - RightLung - 0.03 - Inside -
  • -
  • - LeftKidney - 0.03 - Inside -
  • -
  • - RightKidney - 0.03 - Inside -
  • -
  • - Liver - 0.05 - Inside -
  • -
  • - Head - 0.15 - -
  • - Brain - 0.2 - Inside -
  • -
  • - LeftEye - 0.15 -
  • -
  • - RightEye - 0.15 -
  • -
  • - Nose - 0.1 -
  • -
  • - TurtleBeak - 0.05 - -
  • TurtleBeakAttackTool
  • - - -
    - -
  • - FrontLeftLeg - 0.07 - Bottom -
  • -
  • - FrontRightLeg - 0.07 - Bottom -
  • -
  • - RearLeftLeg - 0.07 - Bottom -
  • -
  • - RearRightLeg - 0.07 - Bottom -
  • - -
    -
    -
    \ No newline at end of file diff --git a/Defs/BodyPartGroupDefs/BodyPartGroups.xml b/Defs/Bodies/BodyPartGroups.xml similarity index 100% rename from Defs/BodyPartGroupDefs/BodyPartGroups.xml rename to Defs/Bodies/BodyPartGroups.xml diff --git a/Defs/BodyPartDefs/BodyParts_Mechanoid_Internal.xml b/Defs/Bodies/BodyParts_Mechanoid_Internal.xml similarity index 77% rename from Defs/BodyPartDefs/BodyParts_Mechanoid_Internal.xml rename to Defs/Bodies/BodyParts_Mechanoid_Internal.xml index 5119f8f728..b9c8d841a8 100644 --- a/Defs/BodyPartDefs/BodyParts_Mechanoid_Internal.xml +++ b/Defs/Bodies/BodyParts_Mechanoid_Internal.xml @@ -10,10 +10,9 @@ 0 false true - -
  • Consciousness_reactor
  • -
  • Moving_reactor
  • -
    + +
  • MetabolismSource
  • +
    @@ -23,10 +22,9 @@ 0 false true - -
  • Consciousness_reactor
  • -
  • Moving_reactor
  • -
    + +
  • MetabolismSource
  • +
    @@ -38,10 +36,9 @@ 0 false true - -
  • Consciousness_capacitor
  • -
  • Moving_capacitor
  • -
    + +
  • BloodFiltrationSource
  • +
    @@ -51,10 +48,9 @@ 0 false true - -
  • Consciousness_capacitor
  • -
  • Moving_capacitor
  • -
    + +
  • BloodFiltrationSource
  • +
    @@ -64,10 +60,9 @@ 0 false true - -
  • Consciousness_capacitor
  • -
  • Moving_capacitor
  • -
    + +
  • BloodFiltrationSource
  • +
    @@ -79,10 +74,9 @@ 0 false true - -
  • Consciousness_heatsink
  • -
  • Moving_heatsink
  • -
    + +
  • BreathingSource
  • +
    @@ -92,14 +86,14 @@ 0 false true - -
  • Consciousness_heatsink
  • -
  • Moving_heatsink
  • -
    + +
  • BreathingSource
  • +
    + MechanicalCoolantTank @@ -120,10 +114,9 @@ 0 false true - -
  • Consciousness_coolant2
  • -
  • Moving_coolant2
  • -
    + +
  • BloodPumpingSource
  • +
    @@ -135,11 +128,12 @@ 0 false true - -
  • Manipulation_actuator0
  • -
    + +
  • ManipulationLimbCore
  • +
    + + MechanicalLeftUpperActuator @@ -171,9 +168,9 @@ 0 false true - -
  • Manipulation_actuator1
  • -
    + +
  • ManipulationLimbSegment
  • +
    @@ -183,9 +180,9 @@ 0 false true - -
  • Manipulation_actuator1
  • -
    + +
  • ManipulationLimbSegment
  • +
    @@ -195,9 +192,9 @@ 0 false true - -
  • Manipulation_piston1
  • -
    + +
  • ManipulationLimbSegment
  • +
    @@ -207,9 +204,9 @@ 0 false true - -
  • Manipulation_piston1
  • -
    + +
  • ManipulationLimbSegment
  • +
    @@ -219,9 +216,9 @@ 0 false true - -
  • Moving_actuator1
  • -
    + +
  • MovingLimbSegment
  • +
    @@ -231,9 +228,9 @@ 0 false true - -
  • Moving_actuator1
  • -
    + +
  • MovingLimbSegment
  • +
    @@ -243,9 +240,9 @@ 0 false true - -
  • Moving_piston1
  • -
    + +
  • MovingLimbSegment
  • +
    @@ -255,9 +252,9 @@ 0 false true - -
  • Moving_piston1
  • -
    + +
  • MovingLimbSegment
  • +
    @@ -267,9 +264,9 @@ 0 false true - -
  • Moving_bearing
  • -
    + +
  • Pelvis
  • +
    \ No newline at end of file diff --git a/Defs/Bodies/BodyShapes.xml b/Defs/Bodies/BodyShapes.xml new file mode 100644 index 0000000000..6cb43784c6 --- /dev/null +++ b/Defs/Bodies/BodyShapes.xml @@ -0,0 +1,48 @@ + + + + + Invalid + + + + Humanoid + 0.25 + 0.5 + 1 + 0.3 + + + + Quadruped + 0.5 + 0.5 + 0.5 + 0.25 + + + + QuadrupedLow + 0.5 + 0.5 + 0.25 + 0.25 + + + + Serpentine + 0.5 + 0.5 + 0.125 + 0.125 + + + + Birdlike + 0.5 + 0.5 + 0.75 + 0.5 + + + \ No newline at end of file diff --git a/Defs/BodyPartDefs/BodyParts_General.xml b/Defs/BodyPartDefs/BodyParts_General.xml deleted file mode 100644 index df64903073..0000000000 --- a/Defs/BodyPartDefs/BodyParts_General.xml +++ /dev/null @@ -1,103 +0,0 @@ - - - - - - - - Brain - - 20 - 1 - false - -
  • Consciousness_brain
  • -
  • Sight_brain
  • -
  • Hearing_brain
  • -
  • Moving_brain
  • -
  • Manipulation_brain
  • -
  • Talking_brain
  • -
    - true -
    - - - Spine - - 20 - 0.5 - false - true - -
  • Moving_spine
  • -
  • Manipulation_spine
  • -
    -
    - - - Rib - - 13 - 0 - false - true - - - - LeftLeg - - 40 - 0.08 - true - -
  • Moving_leftWay1
  • -
    -
    - - - LeftFoot - - 26 - 0.5 - 0.08 - true - -
  • Moving_way2
  • -
    -
    - - - RightLeg - - 40 - 0.08 - true - -
  • Moving_rightWay1
  • -
    -
    - - - RightFoot - - 26 - 0.5 - 0.08 - true - -
  • Moving_way2
  • -
    -
    - -
    \ No newline at end of file diff --git a/Defs/BodyPartDefs/BodyParts_Mechanoid.xml b/Defs/BodyPartDefs/BodyParts_Mechanoid.xml deleted file mode 100644 index badd788c7e..0000000000 --- a/Defs/BodyPartDefs/BodyParts_Mechanoid.xml +++ /dev/null @@ -1,86 +0,0 @@ - - - - - MechanicalThorax - - 50 - 0 - false - true - false - - - - LeftBlade - - 32 - 5 - 0 - false - true - ScytherBlade - - - - RightBlade - - 32 - 5 - 0 - false - true - ScytherBlade - - - - LeftMechanicalLeg - - 40 - 0 - false - true - -
  • Moving_leftWay1
  • -
    -
    - - - LeftMechanicalFoot - - 26 - 2 - 0 - false - true - -
  • Moving_way2
  • -
    -
    - - - RightMechanicalLeg - - 40 - 0 - false - true - -
  • Moving_rightWay1
  • -
    -
    - - - RightMechanicalFoot - - 26 - 2 - 0 - false - true - -
  • Moving_way2
  • -
    -
    - -
    \ No newline at end of file diff --git a/Defs/BodyPartDefs/BodyParts_Organs.xml b/Defs/BodyPartDefs/BodyParts_Organs.xml deleted file mode 100644 index d188d39988..0000000000 --- a/Defs/BodyPartDefs/BodyParts_Organs.xml +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - Heart - - 20 - 0.32 - 6.75 - false - -
  • BloodPumping
  • -
    - Heart - true -
    - - - LeftLung - - 20 - 0.32 - 3.9 - false - -
  • Breathing_main
  • -
    - Lung -
    - - - RightLung - - 20 - 0.32 - 3.9 - false - -
  • Breathing_main
  • -
    - Lung -
    - - - LeftKidney - - 20 - 0.32 - 3.9 - false - -
  • BloodFiltration_kidney
  • -
    - Kidney -
    - - - RightKidney - - 20 - 0.32 - 3.9 - false - -
  • BloodFiltration_kidney
  • -
    - Kidney -
    - - - Liver - - 20 - 0.32 - 5.85 - false - -
  • Metabolism
  • -
  • BloodFiltration_liver
  • -
    - Liver - true -
    - -
    \ No newline at end of file diff --git a/Defs/DamageDefs/Damages_LocalInjury.xml b/Defs/DamageDefs/Damages_LocalInjury.xml index f72b505e5e..3c2efd4777 100644 --- a/Defs/DamageDefs/Damages_LocalInjury.xml +++ b/Defs/DamageDefs/Damages_LocalInjury.xml @@ -1,55 +1,7 @@ - - Combat_Realism.DamageWorker_AddInjuryCE - - - - Cut - - true - {0} has been cut to death. - Cut - Cut - Crack - true - Slice - Sharp - true - - - - Crush - - true - {0} has been crushed to death. - Crush - Cut - Crack - true - Blunt - Blunt - true - - - - Blunt - - true - true - {0} has been beaten to death. - Crush - Bruise - Crack - true - true - Blunt - Blunt - true - - - + Beanbag {0} has been shot to death. @@ -59,172 +11,51 @@ 0.07 - Blunt - - - - Stab - - true - true - {0} has been stabbed to death. - Stab - Crack - true - Slice - Sharp - true - - Bullet - - true - true - {0} has been shot to death. - Gunshot - true - Bullet - Sharp - true - - - + Fragment {0} has been shredded to death. Shredded Crack - false - - - - Arrow - - true - true - {0} has been shot to death. - Cut - Crack - true - Bullet - Sharp - true + true - + + - Scratch - + Slash + true - true {0} has been torn to death. Scratch Crack true Slice Sharp - true - true - true - - - - Bite - - true - true - {0} has been bitten to death. - Bite - Crack - true - Slice - Sharp - true - - - - ToxicBite - - -
  • - ToxicBuildup - 0.001 + +
  • + true
  • -
    - true - true +
    - - Bomb - - true - true - true - {0} has died in an explosion. - Blast - Crack - true - Blunt - Blunt - true - 50 - 2 - false - 5 - Mote_BlastDry - Explosion_Bomb - - - + Bomb_Secondary false false - true - + Thermobaric - Combat_Realism.DamageWorker_FlameCE - - - - Flame - Combat_Realism.DamageWorker_FlameCE - - false - false - 1.5 - false - true - {0} has burned to death. - Burn - Heat - true - 10 - 15 - Mote_BlastFlame - Explosion_Flame - true + CombatExtended.DamageWorker_FlameCE - + Flame_Secondary false false - true - - - - Frostbite - - false - false - {0} has succumbed to frostbite. - Frostbite - true - Heat @@ -232,7 +63,6 @@ false false - 1.5 true {0} has been electrocuted. ElectricalBurn diff --git a/Defs/DamageDefs/Damages_Misc.xml b/Defs/DamageDefs/Damages_Misc.xml deleted file mode 100644 index 17a66a9628..0000000000 --- a/Defs/DamageDefs/Damages_Misc.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - false - false - - - - Stun - - true - {0} has been stunned to death. - Electric - 35 - 0 - Mote_BlastEMP - Explosion_Stun - - - diff --git a/Defs/Effects/Effecter_Misc.xml b/Defs/Effects/Effecter_Misc.xml deleted file mode 100644 index cbfd595c75..0000000000 --- a/Defs/Effects/Effecter_Misc.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - Pee - -
  • - SubEffecter_SprayerContinuous - - 0.1 - 0.25 - - 5 - 0.35 - 0.4 - Mote_VomitBit -
  • -
    -
    - -
    \ No newline at end of file diff --git a/Defs/Effects/Motes_CR.xml b/Defs/Effects/Motes_CR.xml index 45b5cc3940..aaa8a9e0f7 100644 --- a/Defs/Effects/Motes_CR.xml +++ b/Defs/Effects/Motes_CR.xml @@ -1,91 +1,128 @@  + + + + Mote_SuppressIcon + + Things/Mote/Mote_SuppressIcon + + MoteThrownAttached + MetaOverlays + + 0.25 + 1 + 1.4 + (0.45, 0, 0.45) + + + + + Mote_HunkerIcon + + Things/Mote/Mote_HunkerDownIcon + + MoteThrownAttached + MetaOverlays + + 0.25 + 1 + 1.4 + (0.45, 0, 0.45) + + + + - - Mote_EmptyCasing - - Things/Mote/Mote_BulletCasing - - MoteOverhead - - 1.0 - 0.2 - C_Impact_BulletCasing - true - - + + Mote_EmptyCasing + + Things/Mote/Mote_BulletCasing + + MoteOverhead + + 1.0 + 0.2 + C_Impact_BulletCasing + true + + - - Mote_ShotgunShell - - Things/Mote/Mote_ShotgunShell - (0.5,0.5) - - MoteOverhead - - 1.0 - 0.2 - C_Impact_ShotgunCasingImpact - true - - + + Mote_ShotgunShell + + Things/Mote/Mote_ShotgunShell + (0.5,0.5) + + MoteOverhead + + 1.0 + 0.2 + C_Impact_ShotgunCasingImpact + true + + - - Mote_BigShell - - Things/Mote/Mote_BigShell - (0.5,0.5) - - MoteOverhead - - 1.0 - 0.2 - C_Impact_ShotgunCasingImpact - true - - + + Mote_BigShell + + Things/Mote/Mote_BigShell + (0.5,0.5) + + MoteOverhead + + 1.0 + 0.2 + C_Impact_ShotgunCasingImpact + true + + - - Mote_GrenadePin - - Things/Mote/Mote_GrenadePin - - MoteOverhead - - 1.0 - 0.2 - C_Impact_BulletCasing - true - - + + Mote_GrenadePin + + Things/Mote/Mote_GrenadePin + + MoteOverhead + + 1.0 + 0.2 + C_Impact_BulletCasing + true + + - - Mote_BigExplode - - Things/Mote/BigExplode - - MoteOverhead - - 0.05 - 0.4 - 0.45 - 15 - - + + Mote_BigExplode + + Things/Mote/BigExplode + + MoteOverhead + + 0.05 + 0.4 + 0.45 + 15 + + - - Mote_Firetrail - - Things/Mote/Mote_FireSmoked - - MoteOverhead - - 0.083 - 0.083 - 1 - 0.035 - - + + Mote_Firetrail + + Things/Mote/Mote_FireSmoked + + MoteOverhead + + 0.083 + 0.083 + 1 + 0.035 + + \ No newline at end of file diff --git a/Defs/FactionDefs/Factions_Hidden.xml b/Defs/FactionDefs/Factions_Hidden.xml deleted file mode 100644 index 39331bbb06..0000000000 --- a/Defs/FactionDefs/Factions_Hidden.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - Mechanoid - - A hive of ancient self-replicating machines. - mechanoids - 1 - a mechanoid hive - 37 - false - true - false - false - Ultra - 45 - - -100 - -100 - - true - - -100 - -100 - - -
  • - Normal - - 100 - 100 - -
  • -
    - World/WorldObjects/DefaultFactionBase - - -100 - 200 - -
    - -
    diff --git a/Defs/FactionDefs/Factions_Misc.xml b/Defs/FactionDefs/Factions_Misc.xml deleted file mode 100644 index 2ee28f7b79..0000000000 --- a/Defs/FactionDefs/Factions_Misc.xml +++ /dev/null @@ -1,266 +0,0 @@ - - - - - Outlander - - A small community of survivors.\n\nThese people have lived here for decades or centuries, and have lost most of the technology that brought them to this world. They usually work with simple mechanical tools and defend themselves with advanced gunpowder weapons.\n\nThey are concerned with the practical matters of trade, trust, and survival. - outlanders - 1 - 1 - true - 100 - true - true - mayor - World/WorldObjects/Expanding/Town - -
  • (0.64, 0.42, 0.36)
  • -
  • (0.47, 0.5, 0.91)
  • -
    - - -40 - 40 - - NamerFactionOutlander - NamerFactionBaseOutlander - Industrial - Civil - -
  • Rural
  • -
    - - -60 - 0 - - -
  • Caravan_Outlander_BulkGoods
  • -
  • Caravan_Outlander_CombatSupplier
  • -
  • Caravan_Outlander_Exotic
  • -
  • Caravan_Outlander_PirateMerchant
  • -
    - -
  • Visitor_Outlander_Standard
  • -
    - -
  • FactionBase_Outlander_Standard
  • -
    - - -40 - 45 - - -
  • - Normal - - 50 - 250 - 250 - 100 - 100 - -
  • -
  • - Trader - - 1 - - - 1 - 1 - - - 250 - 100 - 100 - -
  • -
  • - FactionBase - - 50 - 250 - 250 - 100 - 100 - -
  • -
    - World/WorldObjects/DefaultFactionBase -
    - - - - Tribe - - These people have been here a very long time. Maybe their ancestors crashed here a thousand years ago. Maybe they survived some cataclysm that destroyed a technological civilization here. In any case, the tribals are mostly nomadic people who live off the land using primitive tools and weapons.\n\nSome tribes are more aggressive than others; many are open to trade and alliances, even with strange peoples like yourselves. Close cooperation or recruitment will be very difficult because of the vast sociotechnological and linguistic gap between the tribals and yourselves.\n\nDespite their apparent technological weakness, the tribals can be dangerous enemies and valuable friends because of their skill with low-tech warfare, their numbers, and their hardiness. - tribespeople - 1 - 1 - true - 100 - true - World/WorldObjects/Expanding/Village - -
  • (0.4, 0.92, 0.35)
  • -
  • (0.89, 0.89, 0.7)
  • -
  • (1, 1, 0.1)
  • -
    - - 10 - 30 - - true - NamerFactionTribal - NamerFactionBaseTribal - NamerPersonTribal - Neolithic - Tribal - chief - -
  • Tribal
  • -
    - - -100 - 10 - - -
  • Caravan_Neolithic_BulkGoods
  • -
  • Caravan_Neolithic_CombatSupplier
  • -
  • Caravan_Neolithic_Slaver
  • -
    - -
  • Visitor_Neolithic_Standard
  • -
    - -
  • FactionBase_Neolithic_Standard
  • -
    - - -40 - 45 - - -
  • - Normal - - 60 - 100 - 70 - -
  • -
  • - Trader - - 1 - - - 1 - 1 - - - 60 - 100 - -
  • -
  • - FactionBase - - 60 - 100 - 70 - -
  • -
    - World/WorldObjects/TribalFactionBase -
    - - - - Pirate - - A gang of bandits.\n\nPirates don't sow, they don't build, and they rarely trade. They enrich themselves mostly by raiding and robbing the more productive groups in the area.\n\nTheir technology level depends mostly on who they've managed to steal from recently. Mostly they carry gunpowder weapons, though the luckier ones may have advanced energy weapons, and some may just like to stab people at close range. - pirates - 1 - 1 - 2 - true - 100 - true - true - false - boss - World/WorldObjects/Expanding/PirateOutpost - -
  • (0.45, 0.03, 0.02)
  • -
  • (0.8, 0.08, 0.18)
  • -
  • (0.92, 0.62, 0.06)
  • -
    - - -100 - -90 - - true - NamerFactionPirate - NamerFactionBasePirate - Spacer - Raider - -
  • Punk
  • -
    - - -100 - -80 - - - -40 - 45 - - -
  • - Normal - 100 - - 5 - 70 - 100 - 150 - 500 - 150 - 90 - 90 - 90 - 60 - 60 - -
  • -
  • - Normal - 50 - -
  • Siege
  • - - - 200 - - -
  • - FactionBase - - 5 - 70 - 100 - 150 - 500 - 150 - 90 - 90 - 90 - 60 - 60 - -
  • -
    - World/WorldObjects/DefaultFactionBase -
    - -
    diff --git a/Defs/HediffDefs/Hediffs_GlobalMisc.xml b/Defs/HediffDefs/Hediffs_CE.xml similarity index 61% rename from Defs/HediffDefs/Hediffs_GlobalMisc.xml rename to Defs/HediffDefs/Hediffs_CE.xml index 78350454e3..776ecdda2e 100644 --- a/Defs/HediffDefs/Hediffs_GlobalMisc.xml +++ b/Defs/HediffDefs/Hediffs_CE.xml @@ -1,5 +1,5 @@  - + MuscleSpasms @@ -76,5 +76,40 @@ - - \ No newline at end of file + + + + + ElectricalBurn + + + + + Blast + + +
  • + bandaged + sutured + set +
  • +
  • + 0.08 +
  • +
  • + 2 + old blast injury + permanent blast injury +
  • +
    + + 0.03 + 0.00625 + 0.035 + false + Torn off + Torn out + +
    + + diff --git a/Defs/HediffDefs/Hediffs_Injuries.xml b/Defs/HediffDefs/Hediffs_Injuries.xml deleted file mode 100644 index d43d55bc37..0000000000 --- a/Defs/HediffDefs/Hediffs_Injuries.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - Hediff_Injury - true - true - - - - - - ElectricalBurn - - -
  • - bandaged - sutured - set -
  • -
  • - burn scar -
  • -
  • - 0.05 -
  • -
    - - 0.028125 - 0.00625 - 0 - true - Burned off - Burned out - -
    - - - Blast - - -
  • - bandaged - sutured - set -
  • -
  • - 0.50 -
  • -
  • - scar -
  • -
    - - 0.03 - 0.00625 - 0.035 - true - Torn off - Torn out - -
    - -
    diff --git a/Defs/JobDefs/Jobs_CE.xml b/Defs/JobDefs/Jobs_CE.xml new file mode 100644 index 0000000000..d3f3408262 --- /dev/null +++ b/Defs/JobDefs/Jobs_CE.xml @@ -0,0 +1,77 @@ + + + + + + + ReloadWeapon + CombatExtended.JobDriver_Reload + Reloading FlagSource TargetB with AmmoType. + +
  • + true +
  • +
    +
    + + + RunForCover + JobDriver_Goto + Running for cover. + false + false + true + false + + + + HunkerDown + CombatExtended.JobDriver_HunkerDown + Hunkering down. + false + false + true + false + + + + WaitKnockdown + CombatExtended.JobDriver_WaitKnockdown + Knocked down. + false + false + true + false + Never + + + + ReloadTurret + CombatExtended.JobDriver_ReloadTurret + Reloading TurretType TargetA with TargetB. + +
  • + true +
  • +
    +
    + + + Stabilize + CombatExtended.JobDriver_Stabilize + Stabilizing. + false + +
  • + true +
  • +
    +
    + + + TakeFromOther + CombatExtended.JobDriver_TakeFromOther + FlagC TargetA from TargetB. + + +
    diff --git a/Defs/JobDefs/Jobs_CR.xml b/Defs/JobDefs/Jobs_CR.xml deleted file mode 100644 index d64f371ae0..0000000000 --- a/Defs/JobDefs/Jobs_CR.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - ReloadWeapon - Combat_Realism.JobDriver_Reload - Reloading weapon. - - - - RunForCover - JobDriver_Goto - Running for cover. - false - false - true - false - - - - HunkerDown - Combat_Realism.JobDriver_HunkerDown - Hunkering down. - false - false - true - false - - - - ReloadTurret - Combat_Realism.JobDriver_ReloadTurret - Reloading turret. - - - diff --git a/Defs/MainTabDefs/OutfitsAndLoadouts.xml b/Defs/MainTabDefs/OutfitsAndLoadouts.xml deleted file mode 100644 index 88bd3bed44..0000000000 --- a/Defs/MainTabDefs/OutfitsAndLoadouts.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - Assign - - Configure what each colonist is allowed to wear, how they react to danger and what they carry into battle - Combat_Realism.MainTabWindow_OutfitsAndLoadouts - 30 - F3 - - - \ No newline at end of file diff --git a/Defs/Misc/PawnColumnDefs/PawnColumns_CE.xml b/Defs/Misc/PawnColumnDefs/PawnColumns_CE.xml new file mode 100644 index 0000000000..d5e53c33f7 --- /dev/null +++ b/Defs/Misc/PawnColumnDefs/PawnColumns_CE.xml @@ -0,0 +1,25 @@ + + + + + Loadout + + CombatExtended.PawnColumnWorker_Loadout + true + + + + CEMass + + CombatExtended.PawnColumnWorker_MassBulkBar + true + + + + CEBulk + + CombatExtended.PawnColumnWorker_MassBulkBar + true + + + \ No newline at end of file diff --git a/Defs/PawnKindDefs/PawnKinds_Mechanoid.xml b/Defs/PawnKindDefs/PawnKinds_Mechanoid.xml deleted file mode 100644 index bc8e3c1222..0000000000 --- a/Defs/PawnKindDefs/PawnKinds_Mechanoid.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - Cutout - - - Cutout - - - - - Centipede - - Mechanoid_Centipede - 870 - Mechanoid - true - -
  • - - Things/Pawn/Mechanoid/Centipede - Graphic_Multi - 3 - - (0.6, 0.8, 0.6) - - -
  • -
    - - 8000 - 8000 - - -
  • MechanoidGunHeavy
  • -
    - - 1 - -
    - - - Scyther - - Mechanoid_Scyther - 160 - Mechanoid - false - -
  • - - Things/Pawn/Mechanoid/Scyther - Graphic_Multi - 1.5 - - (0.4, 0.8, 0.4) - - -
  • -
    - - 5000 - 5000 - - -
  • MechanoidGunMedium
  • -
    - - 1 - -
    - -
    diff --git a/Defs/PawnKindDefs/PawnKinds_Mercenary.xml b/Defs/PawnKindDefs/PawnKinds_Mercenary.xml index 9db4dbf9f9..c78121fbcd 100644 --- a/Defs/PawnKindDefs/PawnKinds_Mercenary.xml +++ b/Defs/PawnKindDefs/PawnKinds_Mercenary.xml @@ -4,7 +4,7 @@ Human Pirate - 0.80 + 0.70 Raider 0.1 2.55 @@ -14,133 +14,9 @@ - MercenaryGunner - - 80 - - 0.7 - 2.3 - - -
  • Outlander
  • -
  • Military
  • -
    - - 1500 - 2800 - - 0.5 - - 300 - 1000 - - -
  • Gun
  • -
    - - 1000 - 1500 - - - 0 - 2 - - -
  • Advanced
  • -
    - 0.003 - - 1 - 1 - - - 0.8 - -
  • - Silver - - 50 - 200 - -
  • -
  • - Medicine - - 1 - 1 - -
  • -
    -
    -
    - - - MercenarySniper - - 90 - - 0.7 - 2.3 - - -
  • Outlander
  • -
  • Military
  • -
    - - 1500 - 2500 - - 0.5 - - 1200 - 1800 - - -
  • SniperRifle
  • -
    - - 1000 - 1500 - - - 0 - 2 - - -
  • Advanced
  • -
    - 0.003 - - 1 - 1 - 1 - 1 - - - 0.8 - -
  • - Silver - - 50 - 200 - -
  • -
  • - Medicine - - 1 - 1 - -
  • -
    -
    -
    - - - MercenarySlasher - - 135 + MercenaryShieldBearer + + 140 0.5 2.3 @@ -150,7 +26,7 @@
  • Military
  • -
  • Apparel_PersonalShield
  • +
  • Apparel_BallisticShield
  • 1000 @@ -195,36 +71,38 @@ + + 1 +
    - MercenaryHeavy - - heavy mercenaries - 185 + MercenaryMachineGunner + + 95 - 0.5 - 1.4 + 0.7 + 2.3
  • Outlander
  • Military
  • - 200 - 350 + 1500 + 2500 0.5 - 1600 - 2000 + 1200 + 1800 -
  • GunHeavy
  • +
  • CE_MachineGun
  • - 2000 - 3000 + 1000 + 1500 0 @@ -233,118 +111,26 @@
  • Advanced
  • - 0.08 - - 1 - 1 - 1 - -
    - - - 0.70 - 220 - 45 - - 0.8 - 3.5 - - -
  • Outlander
  • -
  • Military
  • -
  • Spacer
  • -
    - - 2500 - 4200 - - 0.9 - - 1600 - 2000 - - - 2000 - 3000 - - - 1 - 2 - - 0.1 - -
  • Advanced
  • -
    - 0.08 + 0.003 0.8
  • Silver - 120 - 480 + 50 + 200
  • Medicine 1 - 2 + 1
  • -
    - - - PirateBoss - - 520 - bosses - true - -
  • AdvancedGun
  • -
    - - 10000 - 16800 - - - 1 - 1 - 1 - 1 - -
    - - - MercenaryElite - - 260 - elite mercenaries - -
  • AdvancedGun
  • -
    - - 1 - 1 - 1 - 1 - -
    - - - MercenaryMachineGunner - - 220 - -
  • CE_MachineGun
  • -
    - - 1200 - 2000 - 1 1 diff --git a/Defs/PawnKindDefs/PawnKinds_Outlander.xml b/Defs/PawnKindDefs/PawnKinds_Outlander.xml deleted file mode 100644 index 158c077442..0000000000 --- a/Defs/PawnKindDefs/PawnKinds_Outlander.xml +++ /dev/null @@ -1,137 +0,0 @@ - - - - - Outlander - 0.045 - 0.60 - 0.04 - Civil - -
  • Outlander
  • -
    -
    - - - Villager - - Human - 25 - Poor - false - - 0.2 - 2.0 - - - 300 - 900 - - 0.4 - - 0 - 250 - - -
  • Gun
  • -
  • Melee
  • -
    - - 200 - 300 - - -
  • Simple
  • -
    - 0.001 - 2.55 - - 0.75 - -
  • - 90 - Silver - - 25 - 70 - -
  • -
  • - 10 - Silver - - 700 - 1000 - -
  • -
    -
    - - 1 - 1 - 1 - -
    - - - TownCouncilman - - town councilmen - true - 40 - 100 - - - - TownTrader - - true - - - - TownGuard - - Human - 50 - 65 - - 0.5 - 1.8 - - - 300 - 900 - - 0.4 - - 200 - 600 - - -
  • Gun
  • -
    - - 200 - 300 - - -
  • Simple
  • -
    - 0.001 - 2.55 - - 0.95 - Silver - - 30 - 100 - - - - 1 - 1 - 1 - -
    - -
    diff --git a/Defs/PawnKindDefs/PawnKinds_Pirate.xml b/Defs/PawnKindDefs/PawnKinds_Pirate.xml deleted file mode 100644 index c0b8f2e4ff..0000000000 --- a/Defs/PawnKindDefs/PawnKinds_Pirate.xml +++ /dev/null @@ -1,243 +0,0 @@ - - - - - Human - Pirate - Raider - 0.65 - 0.10 - 0.1 - 2.55 - -
  • Outlander
  • -
    -
    - - - Drifter - - 25 - 0 - - 0.2 - 0.6 - - Shoddy - - 90 - 280 - - 0.2 - - 60 - 100 - - -
  • Gun
  • -
  • Melee
  • -
    - - 0 - 35 - - -
  • Poor
  • -
    - 0.1 - - 0.9 - -
  • - Silver - - 30 - 70 - -
  • -
  • - Medicine - - 1 - 1 - -
  • -
    -
    - - 1 - -
    - - - Scavenger - - 38 - - 0.2 - 0.9 - - Poor - 0.1 - - 300 - 500 - - 0.3 - - 250 - 450 - - -
  • Gun
  • -
    - - 0 - 35 - - -
  • Poor
  • -
    - 0.1 - - 0.9 - -
  • - Silver - - 25 - 50 - -
  • -
  • - Medicine - - 1 - 1 - -
  • -
    -
    - - 1 - -
    - - - Thrasher - - Human - 36 - Poor - 0.2 - 48 - true - - 0.4 - 1.1 - - - 300 - 800 - - -
  • PersonalShield
  • -
  • Outlander
  • -
    - 0.8 - - 60 - 150 - - -
  • Melee
  • -
    - - 0 - 35 - - -
  • Poor
  • -
    - 0.1 - - 0.9 - -
  • - Silver - - 25 - 50 - -
  • -
  • - Medicine - - 1 - 1 - -
  • -
    -
    -
    - - - Pirate - - Human - 56 - 50 - true - - 0.4 - 1.5 - - - 500 - 1100 - - -
  • Outlander
  • -
    - 0.7 - - 450 - 600 - - -
  • Gun
  • -
    - - 0 - 35 - - -
  • Poor
  • -
    - 0.1 - - 0.8 - -
  • - Silver - - 40 - 80 - -
  • -
  • - Medicine - - 1 - 1 - -
  • -
    -
    - - 1 - 1 - -
    - -
    diff --git a/Defs/PawnKindDefs/PawnKinds_Spacer.xml b/Defs/PawnKindDefs/PawnKinds_Spacer.xml deleted file mode 100644 index 71914cdd6b..0000000000 --- a/Defs/PawnKindDefs/PawnKinds_Spacer.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - SpaceSoldier - - Human - 100 - 0.30 - Civil - SpacerHostile - 1 - 58 - Good - 0.08 - - 0 - 4000 - - -
  • Spacer
  • -
    - true - 0.5 - - 300 - 900 - - -
  • Gun
  • -
    - - 1000 - 5000 - - - 0 - 2 - - -
  • Advanced
  • -
    - 0.3 - - 1 - 1 - 1 - 1 - -
    - -
    diff --git a/Defs/PawnKindDefs/PawnKinds_Tribal.xml b/Defs/PawnKindDefs/PawnKinds_Tribal.xml deleted file mode 100644 index f5a8450992..0000000000 --- a/Defs/PawnKindDefs/PawnKinds_Tribal.xml +++ /dev/null @@ -1,107 +0,0 @@ - - - - - Human - Tribe - Tribal - 0.65 - 0.05 - 2.55 - Pemmican - - - - TribalWarrior - - 38 - 40 - - 0.5 - 1.8 - - - 180 - 350 - - -
  • Tribal
  • -
    - - 90 - 400 - - -
  • NeolithicMelee
  • -
    -
    - - - TribalTrader - - true - - - - TribalArcher - - 48 - 40 - - 0.5 - 1.8 - - - 180 - 350 - - -
  • Tribal
  • -
    - - 400 - 400 - - -
  • CE_Bow
  • -
    - - 1 - 1 - -
    - - - TribalChief - - 70 - 0.90 - Superior - 35 - true - - 0.7 - 3.0 - - - 600 - 1600 - - -
  • Tribal
  • -
    - - 800 - 1000 - - -
  • NeolithicRanged
  • -
    - - 1 - 1 - 1 - -
    - -
    diff --git a/Defs/RecipeDefs/Recipes_Production.xml b/Defs/RecipeDefs/Recipes_Production.xml deleted file mode 100644 index fc592849ac..0000000000 --- a/Defs/RecipeDefs/Recipes_Production.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - - - SmeltWeapon - - Use heat and strong electromagnets to break down weapons into useful resources. - Smelting weapon. - 1600 - SmeltingSpeed - Smelt - Recipe_Smelt - -
  • Smelted
  • -
    - -
  • - - -
  • Weapons
  • - - - 1 - -
    - - -
  • WeaponsRanged
  • -
  • WeaponsMelee
  • -
    - -
  • AllowNonSmeltableWeapons
  • -
    -
    - -
  • AllowSmeltable
  • -
    -
    - - - MakeComponent - - Make a component. - Making component. - SmithingSpeed - Cook - Recipe_Machining - 10000 - -
  • - - -
  • Steel
  • - - - 6 - -
    - - -
  • Steel
  • -
    -
    - - 1 - - -
  • - Crafting - 10 -
  • -
    - Crafting -
    - - - - -
    \ No newline at end of file diff --git a/Defs/RecipeDefs/Recipes_Turrets.xml b/Defs/RecipeDefs/Recipes_Turrets.xml deleted file mode 100644 index 79b91c4b9f..0000000000 --- a/Defs/RecipeDefs/Recipes_Turrets.xml +++ /dev/null @@ -1,115 +0,0 @@ - - - - - MakeTurret_Blaster - - Make a charge blaster auto-turret. - Making charge blaster auto-turret. - SmithingSpeed - Cook - Recipe_Machining - 34000 - -
  • - - -
  • Steel
  • - - - 100 - -
  • - - -
  • Plasteel
  • - - - 100 - -
  • - - -
  • Component
  • - - - 20 - -
    - - -
  • Steel
  • -
  • Plasteel
  • -
  • Component
  • -
    -
    - - 1 - - -
  • - Crafting - 10 -
  • -
    - Crafting -
    - - - MakeTurret_Heavy - - Make a heavy auto-turret. - Making heavy auto-turret. - SmithingSpeed - Cook - Recipe_Machining - 37500 - -
  • - - -
  • Steel
  • - - - 250 - -
  • - - -
  • Plasteel
  • - - - 50 - -
  • - - -
  • Component
  • - - - 10 - -
    - - -
  • Steel
  • -
  • Plasteel
  • -
  • Component
  • -
    -
    - - 1 - - -
  • - Crafting - 10 -
  • -
    - Crafting -
    - - - - -
    \ No newline at end of file diff --git a/Defs/RecipeDefs_Ammo/Recipes_AmmoAdvanced.xml b/Defs/RecipeDefs_Ammo/Recipes_AmmoAdvanced.xml deleted file mode 100644 index 677c97d362..0000000000 --- a/Defs/RecipeDefs_Ammo/Recipes_AmmoAdvanced.xml +++ /dev/null @@ -1,227 +0,0 @@ - - - - - SmithingSpeed - Cook - Recipe_Machining - true - 10000 - Crafting - 500 - - - - - - - - - MakeAmmo_30x64mmFuel_Incendiary - - Craft 50 30x64mm incendiary fuel cells. - Making incendiary fuel cells. - -
  • - - -
  • Steel
  • - - - 12 - -
  • - - -
  • Prometheum
  • - - - 7 - -
    - - -
  • Steel
  • -
  • Prometheum
  • -
    -
    - - 50 - -
    - - - MakeAmmo_30x64mmFuel_Thermobaric - - Craft 50 30x64mm thermobaric fuel cells. - Making thermobaric fuel cells. - -
  • - - -
  • Steel
  • - - - 12 - -
  • - - -
  • FSX
  • - - - 7 - -
    - - -
  • Steel
  • -
  • FSX
  • -
    -
    - - 50 - -
    - - - MakeAmmo_30x64mmFuel_Foam - - Craft 50 30x64mm foam fuel cells. - Making foam fuel cells. - -
  • - - -
  • Steel
  • - - - 12 - -
  • - - -
  • MeatRaw
  • - - - 2 - -
    - - -
  • Steel
  • -
    - -
  • MeatRaw
  • -
    -
    - - 50 - -
    - - - - - MakeAmmo_6x24mmCharged - - Craft 100 6x24mm Charged cartridges. - Making 6x24mm Charged cartridges. - -
  • - - -
  • Plasteel
  • - - - 2 - -
  • - - -
  • Component
  • - - - 2 - -
    - - -
  • Plasteel
  • -
  • Component
  • -
    -
    - - 100 - -
    - - - MakeAmmo_6x24mmCharged_AP - - Craft 100 6x24mm Charged (Conc.) cartridges. - Making 6x24mm Charged (Conc.) cartridges. - -
  • - - -
  • Plasteel
  • - - - 2 - -
  • - - -
  • Component
  • - - - 2 - -
    - - -
  • Plasteel
  • -
  • Component
  • -
    -
    - - 100 - -
    - - - MakeAmmo_6x24mmCharged_Ion - - Craft 100 6x24mm Charged (Ion) cartridges. - Making 6x24mm Charged (Ion) cartridges. - -
  • - - -
  • Plasteel
  • - - - 2 - -
  • - - -
  • Component
  • - - - 2 - -
    - - -
  • Plasteel
  • -
  • Component
  • -
    -
    - - 100 - -
    - -
    \ No newline at end of file diff --git a/Defs/RecipeDefs_Ammo/Recipes_AmmoHighCaliber.xml b/Defs/RecipeDefs_Ammo/Recipes_AmmoHighCaliber.xml deleted file mode 100644 index 3b0c2f5270..0000000000 --- a/Defs/RecipeDefs_Ammo/Recipes_AmmoHighCaliber.xml +++ /dev/null @@ -1,228 +0,0 @@ - - - - - - - MakeAmmo_50BMG_FMJ - - Craft 200 .50 BMG (FMJ) cartridges. - Making .50 BMG (FMJ) cartridges. - -
  • - - -
  • Steel
  • - - - 44 - -
    - - -
  • Steel
  • -
    -
    - - 200 - -
    - - - MakeAmmo_50BMG_AP - - Craft 200 .50 BMG (Sabot) cartridges. - Making .50 BMG (Sabot) cartridges. - -
  • - - -
  • Steel
  • - - - 32 - -
  • - - -
  • Uranium
  • - - - 4 - -
    - - -
  • Steel
  • -
  • Uranium
  • -
    -
    - - 200 - -
    - - - MakeAmmo_50BMG_HE - - Craft 200 .50 BMG (HE) cartridges. - Making .50 BMG (HE) cartridges. - -
  • - - -
  • Steel
  • - - - 32 - -
  • - - -
  • FSX
  • - - - 6 - -
    - - -
  • Steel
  • -
  • FSX
  • -
    -
    - - 200 - -
    - - - MakeAmmo_50BMG_Incendiary - - Craft 200 .50 BMG (AP-I) cartridges. - Making .50 BMG (AP-I) cartridges. - -
  • - - -
  • Steel
  • - - - 40 - -
  • - - -
  • Prometheum
  • - - - 6 - -
    - - -
  • Steel
  • -
  • Prometheum
  • -
    -
    - - 200 - -
    - - - - - MakeAmmo_145x114mm_FMJ - - Craft 200 14.5x114mm (FMJ) cartridges. - Making 14.5x114mm (FMJ) cartridges. - -
  • - - -
  • Steel
  • - - - 80 - -
    - - -
  • Steel
  • -
    -
    - - 200 - -
    - - - MakeAmmo_145x114mm_HE - - Craft 200 14.5x114mm (HE) cartridges. - Making 14.5x114mm (HE) cartridges. - -
  • - - -
  • Steel
  • - - - 58 - -
  • - - -
  • FSX
  • - - - 8 - -
    - - -
  • Steel
  • -
  • FSX
  • -
    -
    - - 200 - -
    - - - MakeAmmo_145x114mm_Incendiary - - Craft 200 14.5x114mm (AP-I) cartridges. - Making 14.5x114mm (AP-I) cartridges. - -
  • - - -
  • Steel
  • - - - 68 - -
  • - - -
  • Prometheum
  • - - - 8 - -
    - - -
  • Steel
  • -
  • Prometheum
  • -
    -
    - - 200 - -
    - -
    \ No newline at end of file diff --git a/Defs/RecipeDefs_Ammo/Recipes_AmmoNeolithic.xml b/Defs/RecipeDefs_Ammo/Recipes_AmmoNeolithic.xml deleted file mode 100644 index 7f3f44238b..0000000000 --- a/Defs/RecipeDefs_Ammo/Recipes_AmmoNeolithic.xml +++ /dev/null @@ -1,218 +0,0 @@ - - - - - SmithingSpeed - Cook - Recipe_Machining - true - 2000 - Crafting - 500 - -
  • ElectricSmithy
  • -
  • FueledSmithy
  • -
    -
    - - - - - MakeArrow_Stone - - Craft 10 stone arrows. - Making stone arrows. - -
  • - - -
  • WoodLog
  • - - - 1 - -
    - - -
  • WoodLog
  • -
    -
    - - 10 - - -
  • ElectricSmithy
  • -
  • FueledSmithy
  • -
  • CraftingSpot
  • -
    -
    - - - MakeArrow_Steel - - Craft 10 steel arrows. - Making steel arrows. - -
  • - - -
  • WoodLog
  • - - - 1 - -
  • - - -
  • Steel
  • - - - 1 - -
    - - -
  • WoodLog
  • -
  • Steel
  • -
    -
    - - 10 - -
    - - - MakeArrow_Plasteel - - Craft 10 plasteel arrows. - Making plasteel arrows. - -
  • - - -
  • WoodLog
  • - - - 1 - -
  • - - -
  • Plasteel
  • - - - 1 - -
    - - -
  • WoodLog
  • -
  • Plasteel
  • -
    -
    - - 10 - -
    - - - - - MakeGreatArrow_Stone - - Craft 10 stone great arrows. - Making stone great arrows. - -
  • - - -
  • WoodLog
  • - - - 2 - -
    - - -
  • WoodLog
  • -
    -
    - - 10 - - -
  • ElectricSmithy
  • -
  • FueledSmithy
  • -
  • CraftingSpot
  • -
    -
    - - - MakeGreatArrow_Steel - - Craft 10 steel great arrows. - Making steel great arrows. - -
  • - - -
  • WoodLog
  • - - - 2 - -
  • - - -
  • Steel
  • - - - 1 - -
    - - -
  • WoodLog
  • -
  • Steel
  • -
    -
    - - 10 - -
    - - - MakeGreatArrow_Plasteel - - Craft 10 plasteel great arrows. - Making plasteel great arrows. - -
  • - - -
  • WoodLog
  • - - - 2 - -
  • - - -
  • Plasteel
  • - - - 1 - -
    - - -
  • WoodLog
  • -
  • Plasteel
  • -
    -
    - - 10 - -
    - -
    \ No newline at end of file diff --git a/Defs/RecipeDefs_Ammo/Recipes_AmmoPistols.xml b/Defs/RecipeDefs_Ammo/Recipes_AmmoPistols.xml deleted file mode 100644 index c5f2b12d8a..0000000000 --- a/Defs/RecipeDefs_Ammo/Recipes_AmmoPistols.xml +++ /dev/null @@ -1,366 +0,0 @@ - - - - - - - MakeAmmo_40Rimfire - - Craft 500 .40 Rimfire cartridges. - Making .40 Rimfire cartridges. - -
  • - - -
  • Steel
  • - - - 5 - -
    - - -
  • Steel
  • -
    -
    - - 500 - -
    - - - - - MakeAmmo_32ACP_FMJ - - Craft 500 .32 ACP cartridges. - Making .32 ACP cartridges. - -
  • - - -
  • Steel
  • - - - 10 - -
    - - -
  • Steel
  • -
    -
    - - 500 - -
    - - - - - MakeAmmo_762x25mmTokarev_FMJ - - Craft 500 7.62x25mm Tokarev (FMJ) cartridges. - Making 7.62x25mm Tokarev (FMJ) cartridges. - -
  • - - -
  • Steel
  • - - - 10 - -
    - - -
  • Steel
  • -
    -
    - - 500 - -
    - - - MakeAmmo_762x25mmTokarev_AP - - Craft 500 7.62x25mm Tokarev (AP) cartridges. - Making 7.62x25mm Tokarev (AP) cartridges. - -
  • - - -
  • Steel
  • - - - 12 - -
    - - -
  • Steel
  • -
    -
    - - 500 - -
    - - - MakeAmmo_762x25mmTokarev_HP - - Craft 500 7.62x25mm Tokarev (HP) cartridges. - Making 7.62x25mm Tokarev (HP) cartridges. - -
  • - - -
  • Steel
  • - - - 12 - -
    - - -
  • Steel
  • -
    -
    - - 500 - -
    - - - - - MakeAmmo_9x19mmPara_FMJ - - Craft 500 9x19mm Parabellum (FMJ) cartridges. - Making 9x19mm Parabellum (FMJ) cartridges. - -
  • - - -
  • Steel
  • - - - 12 - -
    - - -
  • Steel
  • -
    -
    - - 500 - -
    - - - MakeAmmo_9x19mmPara_AP - - Craft 500 9x19mm Parabellum (AP) cartridges. - Making 9x19mm Parabellum (AP) cartridges. - -
  • - - -
  • Steel
  • - - - 14 - -
    - - -
  • Steel
  • -
    -
    - - 500 - -
    - - - MakeAmmo_9x19mmPara_HP - - Craft 500 9x19mm Parabellum (HP) cartridges. - Making 9x19mm Parabellum (HP) cartridges. - -
  • - - -
  • Steel
  • - - - 14 - -
    - - -
  • Steel
  • -
    -
    - - 500 - -
    - - - - - MakeAmmo_45ACP_FMJ - - Craft 500 .45 ACP (FMJ) cartridges. - Making .45 ACP (FMJ) cartridges. - -
  • - - -
  • Steel
  • - - - 20 - -
    - - -
  • Steel
  • -
    -
    - - 500 - -
    - - - MakeAmmo_45ACP_AP - - Craft 500 .45 ACP (AP) cartridges. - Making .45 ACP (AP) cartridges. - -
  • - - -
  • Steel
  • - - - 22 - -
    - - -
  • Steel
  • -
    -
    - - 500 - -
    - - - MakeAmmo_45ACP_HP - - Craft 500 .45 ACP (HP) cartridges. - Making .45 ACP (HP) cartridges. - -
  • - - -
  • Steel
  • - - - 22 - -
    - - -
  • Steel
  • -
    -
    - - 500 - -
    - - - - - MakeAmmo_45Colt_FMJ - - Craft 500 .45 Colt (FMJ) cartridges. - Making .45 Colt (FMJ) cartridges. - -
  • - - -
  • Steel
  • - - - 20 - -
    - - -
  • Steel
  • -
    -
    - - 500 - -
    - - - MakeAmmo_45Colt_AP - - Craft 500 .45 Colt (AP) cartridges. - Making .45 Colt (AP) cartridges. - -
  • - - -
  • Steel
  • - - - 22 - -
    - - -
  • Steel
  • -
    -
    - - 500 - -
    - - - MakeAmmo_45Colt_HP - - Craft 500 .45 Colt (HP) cartridges. - Making .45 Colt (HP) cartridges. - -
  • - - -
  • Steel
  • - - - 22 - -
    - - -
  • Steel
  • -
    -
    - - 500 - -
    - -
    \ No newline at end of file diff --git a/Defs/RecipeDefs_Ammo/Recipes_AmmoRifles.xml b/Defs/RecipeDefs_Ammo/Recipes_AmmoRifles.xml deleted file mode 100644 index 0f2962f3d9..0000000000 --- a/Defs/RecipeDefs_Ammo/Recipes_AmmoRifles.xml +++ /dev/null @@ -1,389 +0,0 @@ - - - - - - - MakeAmmo_556x45mmNATO_FMJ - - Craft 500 5.56x45mm NATO (FMJ) cartridges. - Making 5.56x45mm NATO (FMJ) cartridges. - -
  • - - -
  • Steel
  • - - - 12 - -
    - - -
  • Steel
  • -
    -
    - - 500 - -
    - - - MakeAmmo_556x45mmNATO_AP - - Craft 500 5.56x45mm NATO (AP) cartridges. - Making 5.56x45mm NATO (AP) cartridges. - -
  • - - -
  • Steel
  • - - - 14 - -
    - - -
  • Steel
  • -
    -
    - - 500 - -
    - - - MakeAmmo_556x45mmNATO_HP - - Craft 500 5.56x45mm NATO (HP) cartridges. - Making 5.56x45mm NATO (HP) cartridges. - -
  • - - -
  • Steel
  • - - - 14 - -
    - - -
  • Steel
  • -
    -
    - - 500 - -
    - - - - - MakeAmmo_762x39mmSoviet_FMJ - - Craft 500 7.62x39mm Soviet (FMJ) cartridges. - Making 7.62x39mm Soviet (FMJ) cartridges. - -
  • - - -
  • Steel
  • - - - 16 - -
    - - -
  • Steel
  • -
    -
    - - 500 - -
    - - - MakeAmmo_762x39mmSoviet_AP - - Craft 500 7.62x39mm Soviet (AP) cartridges. - Making 7.62x39mm Soviet (AP) cartridges. - -
  • - - -
  • Steel
  • - - - 18 - -
    - - -
  • Steel
  • -
    -
    - - 500 - -
    - - - MakeAmmo_762x39mmSoviet_HP - - Craft 500 7.62x39mm Soviet (HP) cartridges. - Making 7.62x39mm Soviet (HP) cartridges. - -
  • - - -
  • Steel
  • - - - 18 - -
    - - -
  • Steel
  • -
    -
    - - 500 - -
    - - - - - MakeAmmo_303British_FMJ - - Craft 500 .303 British (FMJ) cartridges. - Making .303 British (FMJ) cartridges. - -
  • - - -
  • Steel
  • - - - 22 - -
    - - -
  • Steel
  • -
    -
    - - 500 - -
    - - - MakeAmmo_303British_AP - - Craft 500 .303 British (AP) cartridges. - Making .303 British (AP) cartridges. - -
  • - - -
  • Steel
  • - - - 24 - -
    - - -
  • Steel
  • -
    -
    - - 500 - -
    - - - MakeAmmo_303British_HP - - Craft 500 .303 British (HP) cartridges. - Making .303 British (HP) cartridges. - -
  • - - -
  • Steel
  • - - - 24 - -
    - - -
  • Steel
  • -
    -
    - - 500 - -
    - - - - - MakeAmmo_762x51mmNATO_FMJ - - Craft 500 7.62x51mm NATO (FMJ) cartridges. - Making 7.62x51mm NATO (FMJ) cartridges. - -
  • - - -
  • Steel
  • - - - 25 - -
    - - -
  • Steel
  • -
    -
    - - 500 - -
    - - - MakeAmmo_762x51mmNATO_AP - - Craft 500 7.62x51mm NATO (AP) cartridges. - Making 7.62x51mm NATO (AP) cartridges. - -
  • - - -
  • Steel
  • - - - 27 - -
    - - -
  • Steel
  • -
    -
    - - 500 - -
    - - - MakeAmmo_762x51mmNATO_HP - - Craft 500 7.62x51mm NATO (HP) cartridges. - Making 7.62x51mm NATO (HP) cartridges. - -
  • - - -
  • Steel
  • - - - 27 - -
    - - -
  • Steel
  • -
    -
    - - 500 - -
    - - - - - MakeAmmo_762x54mmR_FMJ - - Craft 500 7.62x54mmR (FMJ) cartridges. - Making 7.62x54mmR (FMJ) cartridges. - -
  • - - -
  • Steel
  • - - - 22 - -
    - - -
  • Steel
  • -
    -
    - - 500 - -
    - - - MakeAmmo_762x54mmR_AP - - Craft 500 7.62x54mmR (AP) cartridges. - Making 7.62x54mmR (AP) cartridges. - -
  • - - -
  • Steel
  • - - - 24 - -
    - - -
  • Steel
  • -
    -
    - - 500 - -
    - - - MakeAmmo_762x54mmR_HP - - Craft 500 7.62x54mmR (HP) cartridges. - Making 7.62x54mmR (HP) cartridges. - -
  • - - -
  • Steel
  • - - - 24 - -
    - - -
  • Steel
  • -
    -
    - - 500 - -
    - -
    \ No newline at end of file diff --git a/Defs/RecipeDefs_Ammo/Recipes_AmmoShotgun.xml b/Defs/RecipeDefs_Ammo/Recipes_AmmoShotgun.xml deleted file mode 100644 index 1cc2dd97df..0000000000 --- a/Defs/RecipeDefs_Ammo/Recipes_AmmoShotgun.xml +++ /dev/null @@ -1,176 +0,0 @@ - - - - - - - MakeAmmo_410Bore_Buck - - Craft 200 .410 Bore (Buck) shells. - Making .410 Bore (Buck) shells. - -
  • - - -
  • Steel
  • - - - 12 - -
    - - -
  • Steel
  • -
    -
    - - 200 - -
    - - - - - MakeAmmo_12Gauge_Buck - - Craft 200 12 gauge (Buck) shells. - Making 12 gauge (Buck) shells. - -
  • - - -
  • Steel
  • - - - 20 - -
    - - -
  • Steel
  • -
    -
    - - 200 - -
    - - - MakeAmmo_12Gauge_Bird - - Craft 200 12 gauge (Bird) shells. - Making 12 gauge (Bird) shells. - -
  • - - -
  • Steel
  • - - - 20 - -
    - - -
  • Steel
  • -
    -
    - - 200 - -
    - - - MakeAmmo_12Gauge_Slug - - Craft 200 12 gauge (Slug) shells. - Making 12 gauge (Slug) shells. - -
  • - - -
  • Steel
  • - - - 26 - -
    - - -
  • Steel
  • -
    -
    - - 200 - -
    - - - MakeAmmo_12Gauge_Beanbag - - Craft 200 12 gauge (Beanbag) shells. - Making 12 gauge (Beanbag) shells. - -
  • - - -
  • Steel
  • - - - 12 - -
  • - - -
  • Cloth
  • - - - 6 - -
    - - -
  • Steel
  • -
  • Cloth
  • -
    -
    - - 200 - -
    - - - MakeAmmo_12Gauge_ElectroSlug - - Craft 200 12 gauge (EMP) shells. - Making 12 gauge (EMP) shells. - -
  • - - -
  • Steel
  • - - - 12 - -
  • - - -
  • Component
  • - - - 4 - -
    - - -
  • Steel
  • -
  • Component
  • -
    -
    - - 200 - -
    - -
    \ No newline at end of file diff --git a/Defs/RecipeDefs_Ammo/Recipes_Grenades.xml b/Defs/RecipeDefs_Ammo/Recipes_Grenades.xml deleted file mode 100644 index 692291a0dd..0000000000 --- a/Defs/RecipeDefs_Ammo/Recipes_Grenades.xml +++ /dev/null @@ -1,162 +0,0 @@ - - - - - - - MakeAmmo_30x29mmGrenade_HE - - Craft 50 30x29mm HE grenades. - Making 30x29mm HE grenades. - -
  • - - -
  • Steel
  • - - - 15 - -
  • - - -
  • FSX
  • - - - 3 - -
  • - - -
  • Component
  • - - - 1 - -
    - - -
  • Steel
  • -
  • FSX
  • -
  • Component
  • -
    -
    - - 50 - -
    - - - MakeAmmo_30x29mmGrenade_EMP - - Craft 50 30x29mm EMP grenades. - Making 30x29mm EMP grenades. - -
  • - - -
  • Steel
  • - - - 15 - -
  • - - -
  • Component
  • - - - 4 - -
    - - -
  • Steel
  • -
  • Component
  • -
    -
    - - 50 - -
    - - - - - MakeAmmo_40x46mmGrenade_HE - - Craft 50 40x46mm HE grenades. - Making 40x46mm HE grenades. - -
  • - - -
  • Steel
  • - - - 20 - -
  • - - -
  • FSX
  • - - - 4 - -
  • - - -
  • Component
  • - - - 1 - -
    - - -
  • Steel
  • -
  • FSX
  • -
  • Component
  • -
    -
    - - 50 - -
    - - - MakeAmmo_40x46mmGrenade_EMP - - Craft 50 40x46mm EMP grenades. - Making 40x46mm EMP grenades. - -
  • - - -
  • Steel
  • - - - 20 - -
  • - - -
  • Component
  • - - - 5 - -
    - - -
  • Steel
  • -
  • Component
  • -
    -
    - - 50 - -
    - -
    \ No newline at end of file diff --git a/Defs/RecipeDefs_Ammo/Recipes_Rockets.xml b/Defs/RecipeDefs_Ammo/Recipes_Rockets.xml deleted file mode 100644 index 074a0315d4..0000000000 --- a/Defs/RecipeDefs_Ammo/Recipes_Rockets.xml +++ /dev/null @@ -1,138 +0,0 @@ - - - - - - - MakeAmmo_RPG7Grenade_HEAT - - Craft 5 RPG-7 HEAT grenades. - Making RPG-7 HEAT grenades. - 15000 - -
  • - - -
  • Steel
  • - - - 13 - -
  • - - -
  • FSX
  • - - - 3 - -
  • - - -
  • Component
  • - - - 3 - -
    - - -
  • Steel
  • -
  • FSX
  • -
  • Component
  • -
    -
    - - 5 - -
    - - - MakeAmmo_RPG7Grenade_Thermobaric - - Craft 5 RPG-7 thermobaric grenades. - Making RPG-7 thermobaric grenades. - 15000 - -
  • - - -
  • Steel
  • - - - 13 - -
  • - - -
  • FSX
  • - - - 9 - -
  • - - -
  • Component
  • - - - 3 - -
    - - -
  • Steel
  • -
  • FSX
  • -
  • Component
  • -
    -
    - - 5 - -
    - - - MakeAmmo_RPG7Grenade_Frag - - Craft 5 RPG-7 frag grenades. - Making RPG-7 frag grenades. - 15000 - -
  • - - -
  • Steel
  • - - - 7 - -
  • - - -
  • FSX
  • - - - 2 - -
  • - - -
  • Component
  • - - - 3 - -
    - - -
  • Steel
  • -
  • FSX
  • -
  • Component
  • -
    -
    - - 5 - -
    - -
    \ No newline at end of file diff --git a/Defs/RecipeDefs_Ammo/Recipes_Shells.xml b/Defs/RecipeDefs_Ammo/Recipes_Shells.xml deleted file mode 100644 index f70fb302fd..0000000000 --- a/Defs/RecipeDefs_Ammo/Recipes_Shells.xml +++ /dev/null @@ -1,248 +0,0 @@ - - - - - - - MakeMortarShell - - Craft 5 81mm HE mortar shells. - Making 81mm HE mortar shells. - -
  • - - -
  • Steel
  • - - - 22 - -
  • - - -
  • FSX
  • - - - 5 - -
  • - - -
  • Component
  • - - - 2 - -
    - - -
  • Steel
  • -
  • FSX
  • -
  • Component
  • -
    -
    - - 5 - -
    - - - MakeAmmo_81mmMortarShell_Incendiary - - Craft 5 81mm incendiary mortar shells. - Making 81mm incendiary mortar shells. - -
  • - - -
  • Steel
  • - - - 22 - -
  • - - -
  • Prometheum
  • - - - 5 - -
  • - - -
  • Component
  • - - - 2 - -
    - - -
  • Steel
  • -
  • Prometheum
  • -
  • Component
  • -
    -
    - - 5 - -
    - - - MakeAmmo_81mmMortarShell_EMP - - Craft 5 81mm EMP mortar shells. - Making 81mm EMP mortar shells. - -
  • - - -
  • Steel
  • - - - 22 - -
  • - - -
  • Component
  • - - - 7 - -
    - - -
  • Steel
  • -
  • Component
  • -
    -
    - - 5 - -
    - - - - - MakeAmmo_90mmCannonShell_HEAT - - Craft 5 90mm HEAT cannon shells. - Making 90mm HEAT cannon shells. - -
  • - - -
  • Steel
  • - - - 23 - -
  • - - -
  • FSX
  • - - - 3 - -
  • - - -
  • Component
  • - - - 3 - -
    - - -
  • Steel
  • -
  • FSX
  • -
  • Component
  • -
    -
    - - 5 - -
    - - - MakeAmmo_90mmCannonShell_HE - - Craft 5 90mm HE cannon shells. - Making 90mm HE cannon shells. - -
  • - - -
  • Steel
  • - - - 23 - -
  • - - -
  • FSX
  • - - - 5 - -
  • - - -
  • Component
  • - - - 2 - -
    - - -
  • Steel
  • -
  • FSX
  • -
  • Component
  • -
    -
    - - 5 - -
    - - - MakeAmmo_90mmCannonShell_EMP - - Craft 5 90mm EMP cannon shells. - Making 90mm EMP cannon shells. - -
  • - - -
  • Steel
  • - - - 23 - -
  • - - -
  • Component
  • - - - 7 - -
    - - -
  • Steel
  • -
  • Component
  • -
    -
    - - 5 - -
    - -
    diff --git a/Defs/ResearchProjectDefs/ResearchProjects_Tier2_Misc.xml b/Defs/ResearchProjectDefs/ResearchProjects_Tier4_Misc.xml similarity index 54% rename from Defs/ResearchProjectDefs/ResearchProjects_Tier2_Misc.xml rename to Defs/ResearchProjectDefs/ResearchProjects_Tier4_Misc.xml index a83094d0c1..8c4e3bf36f 100644 --- a/Defs/ResearchProjectDefs/ResearchProjects_Tier2_Misc.xml +++ b/Defs/ResearchProjectDefs/ResearchProjects_Tier4_Misc.xml @@ -14,22 +14,8 @@
  • MultiAnalyzer
  • - - - - CE_TurretAI - - Learn to construct and program basic auto-turrets. - 3000 - Industrial - -
  • Machining
  • -
  • MicroelectronicsBasics
  • -
    - HiTechResearchBench - -
  • MultiAnalyzer
  • -
    + 9 + 3
    \ No newline at end of file diff --git a/Defs/ResearchProjectDefs/ResearchProjects_Turrets.xml b/Defs/ResearchProjectDefs/ResearchProjects_Turrets.xml index 2c43350176..695a9b9b83 100644 --- a/Defs/ResearchProjectDefs/ResearchProjects_Turrets.xml +++ b/Defs/ResearchProjectDefs/ResearchProjects_Turrets.xml @@ -1,16 +1,78 @@  - + + + + CE_Turrets + + CE_TurretHeavyWeapons Allows you to assemble high-caliber weapons such as the KPV machine gun. + 1000 + Industrial + +
  • Machining
  • +
    + 0 + 1 + CE_Turrets +
    + + + + + CE_ChargeTurret + + Learn to construct charge blaster turrets. + 500 + Spacer + +
  • GunTurrets
  • +
  • ChargedShot
  • +
    + HiTechResearchBench + +
  • MultiAnalyzer
  • +
    + 2 + 0 + CE_Turrets +
    + + + CE_HeavyTurret + + Learn to construct heavy auto-turrets. + 500 + Industrial + +
  • GunTurrets
  • +
  • CE_TurretHeavyWeapons
  • + HiTechResearchBench + +
  • MultiAnalyzer
  • +
    + 2 + 1 + CE_Turrets
    -
    \ No newline at end of file + \ No newline at end of file diff --git a/Defs/Scenarios/Scenarios_Classic.xml b/Defs/Scenarios/Scenarios_Classic.xml deleted file mode 100644 index e725db68fe..0000000000 --- a/Defs/Scenarios/Scenarios_Classic.xml +++ /dev/null @@ -1,133 +0,0 @@ - - - - - Crashlanded - - The three of you awake in your cryptosleep sarcophagi to the sound of sirens and ripping metal. You barely get to the escape pods before the ship is torn apart. Some time later, you land on this unknown rimworld. - - Three crashlanded survivors - the classic RimWorld experience. - - PlayerFaction - PlayerColony - - - - -
  • - ConfigPage_ConfigureStartingPawns - 3 -
  • - - -
  • - PlayerPawnsArriveMethod - DropPods - false -
  • - - -
  • - ForcedHediff - false - PlayerStarter - 0.5 - CryptosleepSickness - true - - 1 - 1 - -
  • - - -
  • - StartingThing_Defined - Silver - 800 -
  • -
  • - StartingThing_Defined - MealSurvivalPack - 30 -
  • -
  • - StartingThing_Defined - Medicine - 24 -
  • -
  • - StartingThing_Defined - Component - 30 -
  • -
  • - StartingThing_Defined - Gun_SurvivalRifle -
  • -
  • - StartingThing_Defined - Gun_Pistol -
  • -
  • - StartingThing_Defined - MeleeWeapon_Knife - Plasteel -
  • -
  • - StartingThing_Defined - Ammo_45ACP_FMJ - 150 -
  • -
  • - StartingThing_Defined - Ammo_303British_FMJ - 200 -
  • -
  • - StartingAnimal - 1 - 1.0 -
  • - - -
  • - ScatterThingsNearPlayerStart - Steel - 450 -
  • -
  • - ScatterThingsNearPlayerStart - WoodLog - 300 -
  • - - -
  • - ScatterThingsAnywhere - ShipChunk - 3 -
  • -
  • - ScatterThingsAnywhere - Steel - 720 -
  • -
  • - ScatterThingsAnywhere - MealSurvivalPack - 7 -
  • - - -
  • - GameStartDialog - GameStartDialog - GameStartSting -
  • - -
    -
    -
    - -
    diff --git a/Defs/Scenarios/Scenarios_Special.xml b/Defs/Scenarios/Scenarios_Special.xml deleted file mode 100644 index 47a6032174..0000000000 --- a/Defs/Scenarios/Scenarios_Special.xml +++ /dev/null @@ -1,216 +0,0 @@ - - - - - TheRichExplorer - - People called you crazy for leaving your glitterworld home, but you always yearned to explore the stars - outside the neurosimulator. Now you're at the end of your long journey in cryptosleep, landing on an unknown rimworld to see what it's like. - - One rich explorer out to experience the universe. - - PlayerFaction - PlayerColony - - - - -
  • - ConfigPage_ConfigureStartingPawns - 1 -
  • - - -
  • - PlayerPawnsArriveMethod - false - DropPods -
  • - - -
  • - StartingResearch - GunTurrets -
  • - - -
  • - StartingThing_Defined - Silver - 2000 -
  • -
  • - StartingThing_Defined - Gold - 30 -
  • -
  • - StartingThing_Defined - MealSurvivalPack - 40 -
  • -
  • - StartingThing_Defined - GlitterworldMedicine - 40 -
  • -
  • - StartingThing_Defined - Component - 30 -
  • -
  • - StartingThing_Defined - Gun_ChargeRifle -
  • -
  • - StartingThing_Defined - Ammo_6x24mmCharged - 400 -
  • -
  • - StartingAnimal - 1 - 1.0 -
  • - - -
  • - ScatterThingsNearPlayerStart - Steel - 450 -
  • -
  • - ScatterThingsNearPlayerStart - WoodLog - 300 -
  • - - -
  • - GameStartDialog - The neurosimulations, holo-games, and free-orgies were never enough for you. You wanted more - the grit and consequence of real life, like they talk about in the history books. You wanted to know what real challenge and consequence feel like.\n\nNow, after a journey of decades in cryptosleep, you're landing on this unknown rimworld. Real consequences await you. - GameStartSting -
  • - -
    -
    -
    - - - - - - LostTribe - - Your tribe was destroyed by the great blood machines sent by the gods. Five of you managed to escape. Now, it's time to build up a new home. - - Five lost tribespeople attempt to rebuild. - - PlayerFaction - PlayerTribe - - - - -
  • - ConfigPage_ConfigureStartingPawns - 5 -
  • - - -
  • - PlayerPawnsArriveMethod - Standing -
  • - - -
  • - ForcedHediff - false - PlayerStarter - 0.5 - Malnutrition - - 0.2 - 0.4 - -
  • -
  • - SetNeedLevel - false - PlayerStarter - 1.0 - Food - - 0 - 0.1 - -
  • - - -
  • - StartingThing_Defined - Silver - 200 -
  • -
  • - StartingThing_Defined - Pemmican - 220 -
  • -
  • - StartingThing_Defined - HerbalMedicine - 12 -
  • -
  • - StartingThing_Defined - MeleeWeapon_Club - WoodLog -
  • -
  • - StartingThing_Defined - MeleeWeapon_Spear - WoodLog -
  • -
  • - StartingThing_Defined - MeleeWeapon_Knife - Jade -
  • -
  • - StartingThing_Defined - Bow_Short - 2 -
  • -
  • - StartingThing_Defined - Pila -
  • -
  • - StartingAnimal - 3 - 1.0 -
  • - - -
  • - ScatterThingsNearPlayerStart - WoodLog - 500 -
  • - - -
  • - GameStartDialog - The gods were very angry. The blood machines came at night. They swept through your village, cutting and burning your people with their blades and devil-fire.\n\nOnly a few of you escaped. Now, after a harrowing journey on foot, with no close friends to turn to, you must build a new home in the wilderness, like your ancestors did. - GameStartSting -
  • - -
    -
    -
    - - - -
    diff --git a/Defs/Stats/Stats_Apparel.xml b/Defs/Stats/Stats_Apparel.xml index 8961dd171a..691dd4b9ab 100644 --- a/Defs/Stats/Stats_Apparel.xml +++ b/Defs/Stats/Stats_Apparel.xml @@ -1,16 +1,6 @@ - - WornWeight - - The effective weight of clothing when worn. - Apparel - 0 - 0 - 0 - - WornBulk @@ -19,59 +9,7 @@ 0 0 0 - - - - Apparel - 0 - 0 - 0 - PercentOne - -
  • - 0.7 - 0.8 - 0.9 - 1 - 1.06 - 1.12 - 1.18 - 1.24 - 1.3 -
  • -
  • - - -
  • (0,0.25)
  • -
  • (0.70,1)
  • - - - -
    -
    - - - ArmorRating_Blunt - - Armor against blunt damage like club attacks, rock falls, and explosions. - - - - ArmorRating_Sharp - - Armor against sharp damage like bullets, knife stabs, and animal bites. - - - - ArmorRating_Heat - - Armor against temperature-related damage like burns. - - - - ArmorRating_Electric - - Armor against electric damage like EMP pulses. + false
    diff --git a/Defs/Stats/Stats_Basics_Inventory.xml b/Defs/Stats/Stats_Basics_Inventory.xml index 7c2d8a7786..251bc24f1f 100644 --- a/Defs/Stats/Stats_Basics_Inventory.xml +++ b/Defs/Stats/Stats_Basics_Inventory.xml @@ -1,22 +1,6 @@ - - Mass - - The physical mass of an object. - Basics - 1 - 0 - FloatTwo - {0} kg - -
  • -
  • -
  • - - - Bulk diff --git a/Defs/Stats/Stats_Pawns_Combat.xml b/Defs/Stats/Stats_Pawns_Combat.xml index 26ff46335f..f8527c1c3f 100644 --- a/Defs/Stats/Stats_Pawns_Combat.xml +++ b/Defs/Stats/Stats_Pawns_Combat.xml @@ -1,57 +1,7 @@ - - ShootingAccuracy - - How well a shooter can hold a gun steady when aiming and compensate for recoil.\n\nThe total sway is calculated as:\n(4.5 - shooting accuracy) * weapon sway factor\n\nThe recoil per shot is determined by multiplying this value against the weapon's inherent recoil amount and increases after every shot in a burst. - PawnCombat - 50 - 1 - 0.0 - 4.5 - PercentTwo - false - -
  • - Shooting - true - -
  • 1.0
  • -
  • 1.2
  • -
  • 1.4
  • -
  • 1.6
  • -
  • 1.8
  • -
  • 2.0
  • -
  • 2.1
  • -
  • 2.2
  • -
  • 2.3
  • -
  • 2.4
  • -
  • 2.5
  • -
  • 2.56
  • -
  • 2.62
  • -
  • 2.68
  • -
  • 2.74
  • -
  • 2.8
  • -
  • 2.84
  • -
  • 2.88
  • -
  • 2.92
  • -
  • 2.96
  • -
  • 3.0
  • - - - - -
  • - Consciousness - 1 -
  • -
  • - Manipulation - 1 -
  • -
    -
    + AimingAccuracy @@ -115,17 +65,183 @@ 0.001 PercentZero false + true + +
  • + Consciousness + 1 +
  • +
  • + Manipulation + 1 +
  • +
    +
    + + + Suppressability + + How susceptible this person is to suppression. Loss of conciousness and certain drugs can lower this value, making it harder to suppress this person. + PawnCombat + 60 + 1 + 0 + PercentZero + false false + +
  • + Consciousness + 0.5 +
  • +
    +
    + + + + + + MeleeArmorPenetration + CombatExtended.StatWorker_MeleeArmorPenetration + + Average armor penetration in melee. Determines how much damage is lost to enemy armor. + PawnCombat + 99 + 0 + 0 + FloatTwo + + + + MeleeCritChance + + Base chance to critically hit a target in melee.\n\nThe final chance depends on the opponent's critical skill and equal opponents will always have a 10% chance to crit. + PawnCombat + 99 + 1 + true + 0.0 + 3.2 + PercentZero + +
  • + Melee + 0.1 + 0.01 +
  • +
    + +
  • + Consciousness + 1 +
  • +
  • + Sight + 0.7 + 1 +
  • +
  • + Manipulation + 1 +
  • +
    + + +
  • (0.0, 0.0)
  • +
  • (0.3, 0.3)
  • +
  • (0.6, 0.45)
  • +
  • (1.2, 0.6)
  • +
  • (2.4, 0.75)
  • +
  • (3.2, 0.8)
  • +
    +
    +
    + + + MeleeDodgeChance + + Chance to dodge a melee attack that would've otherwise hit. Characters will not dodge while aiming or firing a ranged weapon. + PawnCombat + CombatExtended.StatWorker_MoveSpeed + 99 + 1 + 0 + 3.2 + PercentZero + +
  • + Melee + 0.1 + 0.015 +
  • +
    + +
  • + Moving + 1 +
  • +
  • + Sight + 0.7 + 1 +
  • +
    + + +
  • (0.0, 0.0)
  • +
  • (0.3, 0.3)
  • +
  • (0.6, 0.45)
  • +
  • (1.2, 0.6)
  • +
  • (2.4, 0.75)
  • +
  • (3.2, 0.8)
  • +
    +
    +
    + + + MeleeParryChance + + Base chance to parry a melee attack. When a parry is performed the equipped weapon or shield will take damage instead of the wielder. If the parrying pawn passes a critical chance check they will automatically riposte their attacker.\n\nThe final chance depends on the opponent's parry skill and equal opponents will always have a 20% chance to crit. + PawnCombat + 99 + 1 + true + 0.0 + 3.2 + PercentZero + 0 + +
  • + Melee + 0.2 + 0.005 +
  • +
  • Consciousness 1
  • +
  • + Sight + 0.7 + 1 +
  • Manipulation 1
  • + + +
  • (0.0, 0.0)
  • +
  • (0.3, 0.3)
  • +
  • (0.6, 0.45)
  • +
  • (1.2, 0.6)
  • +
  • (2.4, 0.75)
  • +
  • (3.2, 0.8)
  • +
    +
    diff --git a/Defs/Stats/Stats_Pawns_General.xml b/Defs/Stats/Stats_Pawns_General.xml deleted file mode 100644 index 461b40474a..0000000000 --- a/Defs/Stats/Stats_Pawns_General.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - MoveSpeed - - Speed of movement through the world in cells per second. - Combat_Realism.StatWorker_MoveSpeed - BasicsPawn - 2.8 - FloatTwo - {0} c/s - 90 - -
  • - Moving - 1 -
  • -
    -
    - -
    diff --git a/Defs/Stats/Stats_Pawns_Inventory.xml b/Defs/Stats/Stats_Pawns_Inventory.xml index d080553180..46ff3289cf 100644 --- a/Defs/Stats/Stats_Pawns_Inventory.xml +++ b/Defs/Stats/Stats_Pawns_Inventory.xml @@ -3,11 +3,10 @@ CarryWeight - Combat_Realism.StatWorker_CarryWeight The amount of weight this creature can carry in pockets, bags or otherwise attached to its body. BasicsPawn - 0 + 40 {0} kg
  • @@ -19,18 +18,15 @@
  • 10 - false
    CarryBulk - Combat_Realism.StatWorker_CarryBulk The volume of items this creature can carry in pockets, bags or otherwise attached to its body. BasicsPawn - 0 + 20 10 - false
  • diff --git a/Defs/Stats/Stats_Pawns_WorkGeneral.xml b/Defs/Stats/Stats_Pawns_WorkGeneral.xml deleted file mode 100644 index 56979d1754..0000000000 --- a/Defs/Stats/Stats_Pawns_WorkGeneral.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - WorkSpeedGlobal - - A multiplier on someone's speed at doing any work. - Combat_Realism.StatWorker_WorkSpeedGlobal - PawnWork - 100 - 1 - PercentZero - -
  • - - -
  • (0,0.75)
  • -
  • (0.45,1.00)
  • -
  • (0.55,1.00)
  • -
  • (1.00,1.25)
  • - - - -
    -
    - - diff --git a/Defs/Stats/Stats_Weapons_Melee.xml b/Defs/Stats/Stats_Weapons_Melee.xml index ac49223b1a..41b4051025 100644 --- a/Defs/Stats/Stats_Weapons_Melee.xml +++ b/Defs/Stats/Stats_Weapons_Melee.xml @@ -2,12 +2,12 @@ - ArmorPenetration - - Capability to penetrate armor on a strike. + MeleeWeapon_Penetration + + Capability to penetrate armor on a melee strike. Weapon 0 - PercentTwo + FloatTwo false
  • diff --git a/Defs/Stats/Stats_Weapons_Ranged.xml b/Defs/Stats/Stats_Weapons_Ranged.xml index d5c9dda9e4..10b163993e 100644 --- a/Defs/Stats/Stats_Weapons_Ranged.xml +++ b/Defs/Stats/Stats_Weapons_Ranged.xml @@ -2,13 +2,12 @@ - AimEfficiency - - How efficient the weapon is at leading and range-finding. This is multiplied against the aiming accuracy of the shooter to calculate the amount of range and lead error.\n\nThe final modifier is calculated via this formula:\n(1.5 - aiming accuracy) / aiming efficiency\n\nLead error is calculated by multiplying this factor against total lead distance in cells. Range error is calculated by multiplying it against the total distance to the target divided by 4. + SightsEfficiency + + How good the sights on this weapon are. Quality sights reduce range errors and improve target leading. This is multiplied against the aiming accuracy of the shooter to calculate the amount of range and lead error.\n\nThe final modifier is calculated via this formula:\n(1.5 - aiming accuracy) / aiming efficiency\n\nLead error is calculated by multiplying this factor against total lead distance in cells. Range error is calculated by multiplying it against the total distance to the target divided by 4. Weapon 1 0.01 - 2 PercentZero false @@ -17,11 +16,11 @@ 0.8 0.9 1 - 1.1 - 1.2 - 1.3 - 1.4 - 1.5 + 1.05 + 1.1 + 1.15 + 1.2 + 1.25
  • diff --git a/Defs/TaleDefs/Tales_SinglePawn.xml b/Defs/TaleDefs/Tales_SinglePawn.xml deleted file mode 100644 index 83c9531dbf..0000000000 --- a/Defs/TaleDefs/Tales_SinglePawn.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - WetHimself - - Tale_SinglePawn - Volatile - 0.3 - 0.5 - - -
  • tale_noun->[pawn_nameShortDef]'s peeing
  • -
  • image->[pawn_nameFull] spills pee onto the ground [circumstance_group]
  • -
  • image->[pawn_nameFull] looking disgusted while lying in a pool of pee [circumstance_group]
  • -
  • image->[pawn_nameFull] doubled over and retching onto the floor [circumstance_group]
  • -
  • image->[pawn_nameFull] on [pawn_possessive] knees, wetting the pants [circumstance_group]
  • -
  • circumstance_phrase->while looking pained
  • -
  • circumstance_phrase->with great shame
  • -
  • circumstance_phrase->as others look on
  • -
  • desc_sentence->[pawn_pronoun] seems totally unaware of what is around [pawn_objective].
  • -
  • desc_sentence->[pawn_possessive] face itself seems to be swelling.
  • -
  • desc_sentence->[pawn_pronoun] is highly aware, [pawn_possessive] fluid drooling, pants wetting.
  • -
  • desc_sentence->[pawn_pronoun] is convulsing violently.
  • -
  • desc_sentence->[pawn_pronoun] looks ashamed and smells bad.
  • -
  • desc_sentence->[pawn_pronoun] seems to be trying to laugh, despite the circumstances.
  • -
  • desc_sentence->[pawn_pronoun] looks almost deflated, as though totally emptied by the intense peeing.
  • -
  • desc_sentence->[pawn_pronoun] is surrounded by an artistically rendered halo of pee.
  • -
  • desc_sentence->A [animal] is licking from the trail of pee in the background.
  • - - - - -
    \ No newline at end of file diff --git a/Defs/ThingCategoryDefs/ThingCategories.xml b/Defs/ThingCategoryDefs/ThingCategories.xml index d77fd7ad2d..b7614b50b6 100644 --- a/Defs/ThingCategoryDefs/ThingCategories.xml +++ b/Defs/ThingCategoryDefs/ThingCategories.xml @@ -1,22 +1,16 @@  - + - WeaponsTurrets - - Weapons + Loadout + + Apparel - Ammo - + WeaponsTurrets + Weapons - - - Loadout - - Apparel - \ No newline at end of file diff --git a/Defs/ThingCategoryDefs/ThingCategories_Advanced.xml b/Defs/ThingCategoryDefs/ThingCategories_Advanced.xml deleted file mode 100644 index bdb9b24fb1..0000000000 --- a/Defs/ThingCategoryDefs/ThingCategories_Advanced.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - AmmoAdvanced - - Ammo - - - - Ammo30x64mmFuelCell - - AmmoAdvanced - - - - Ammo80x128mmFuelCell - - AmmoAdvanced - - - - Ammo6x24mmCharged - - AmmoAdvanced - - - - Ammo5x35mmCharged - - AmmoAdvanced - - - - Ammo12x64mmCharged - - AmmoAdvanced - - - \ No newline at end of file diff --git a/Defs/ThingCategoryDefs/ThingCategories_Grenades.xml b/Defs/ThingCategoryDefs/ThingCategories_Grenades.xml deleted file mode 100644 index 446b92afed..0000000000 --- a/Defs/ThingCategoryDefs/ThingCategories_Grenades.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - AmmoGrenades - - Ammo - - - - Ammo30x29mmGrenades - - AmmoGrenades - - - - Ammo40x46mmGrenades - - AmmoGrenades - - - \ No newline at end of file diff --git a/Defs/ThingCategoryDefs/ThingCategories_HighCaliber.xml b/Defs/ThingCategoryDefs/ThingCategories_HighCaliber.xml deleted file mode 100644 index ed41395244..0000000000 --- a/Defs/ThingCategoryDefs/ThingCategories_HighCaliber.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - AmmoHighCaliber - - Ammo - - - - Ammo50BMG - - AmmoHighCaliber - - - - Ammo145x114mm - - AmmoHighCaliber - - - \ No newline at end of file diff --git a/Defs/ThingCategoryDefs/ThingCategories_Neolithic.xml b/Defs/ThingCategoryDefs/ThingCategories_Neolithic.xml deleted file mode 100644 index e9b7f49ef0..0000000000 --- a/Defs/ThingCategoryDefs/ThingCategories_Neolithic.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - AmmoNeolithic - - Ammo - - - - AmmoArrows - - AmmoNeolithic - - - - AmmoGreatArrows - - AmmoNeolithic - - - \ No newline at end of file diff --git a/Defs/ThingCategoryDefs/ThingCategories_Pistols.xml b/Defs/ThingCategoryDefs/ThingCategories_Pistols.xml deleted file mode 100644 index 33987a9449..0000000000 --- a/Defs/ThingCategoryDefs/ThingCategories_Pistols.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - AmmoPistols - - Ammo - - - - Ammo40Rimfire - - AmmoPistols - - - - Ammo32ACP - - AmmoPistols - - - - Ammo762x25mmTokarev - - AmmoPistols - - - - Ammo9x19mmPara - - AmmoPistols - - - - Ammo45ACP - - AmmoPistols - - - - Ammo45Colt - - AmmoPistols - - - \ No newline at end of file diff --git a/Defs/ThingCategoryDefs/ThingCategories_Rifles.xml b/Defs/ThingCategoryDefs/ThingCategories_Rifles.xml deleted file mode 100644 index b7339b0010..0000000000 --- a/Defs/ThingCategoryDefs/ThingCategories_Rifles.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - AmmoRifles - - Ammo - - - - Ammo556x45mmNATO - - AmmoRifles - - - - Ammo762x39mmSoviet - - AmmoRifles - - - - Ammo303British - - AmmoRifles - - - - Ammo762x51mmNATO - - AmmoRifles - - - - Ammo762x54mmR - - AmmoRifles - - - \ No newline at end of file diff --git a/Defs/ThingCategoryDefs/ThingCategories_Rockets.xml b/Defs/ThingCategoryDefs/ThingCategories_Rockets.xml deleted file mode 100644 index 9a5d76b29b..0000000000 --- a/Defs/ThingCategoryDefs/ThingCategories_Rockets.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - AmmoRockets - - Ammo - - - - AmmoRPG7Grenades - - AmmoRockets - - - \ No newline at end of file diff --git a/Defs/ThingCategoryDefs/ThingCategories_SK.xml b/Defs/ThingCategoryDefs/ThingCategories_SK.xml deleted file mode 100644 index 7d7d3220ca..0000000000 --- a/Defs/ThingCategoryDefs/ThingCategories_SK.xml +++ /dev/null @@ -1,106 +0,0 @@ - - - - - AmmoBolts - - AmmoNeolithic - - - - Ammo44MAG - - AmmoPistols - - - - Ammo50AE - - AmmoPistols - - - - Ammo9x39mmSoviet - - AmmoRifles - - - - Ammo545x39mmR - - AmmoRifles - - - - Ammo20x102mm - - AmmoShells - - - - Ammo30x173mm - - AmmoShells - - - - Ammo35x228mm - - AmmoShells - - - - Ammo120mmCannonShells - - AmmoShells - - - - Ammo155mmCannonShells - - AmmoShells - - - - AmmoM72LAW - - AmmoRockets - - - - AmmoFGMJ - - AmmoRockets - - - - Ammo130mmRocketMissiles - - AmmoRockets - - - - AmmoPlasmaBolt - - AmmoAdvanced - - - - AmmoDualPlasmaBolt - - AmmoAdvanced - - - - AmmoRailRay - - AmmoAdvanced - - - - AmmoLaser - - AmmoAdvanced - - - \ No newline at end of file diff --git a/Defs/ThingCategoryDefs/ThingCategories_Shells.xml b/Defs/ThingCategoryDefs/ThingCategories_Shells.xml deleted file mode 100644 index fcf29491ee..0000000000 --- a/Defs/ThingCategoryDefs/ThingCategories_Shells.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - AmmoShells - - Ammo - - - - Ammo81mmMortarShells - - AmmoShells - - - - Ammo90mmCannonShells - - AmmoShells - - - \ No newline at end of file diff --git a/Defs/ThingCategoryDefs/ThingCategories_Shotgun.xml b/Defs/ThingCategoryDefs/ThingCategories_Shotgun.xml deleted file mode 100644 index 8f97f11490..0000000000 --- a/Defs/ThingCategoryDefs/ThingCategories_Shotgun.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - AmmoShotguns - - Ammo - - - - Ammo410Bore - - AmmoShotguns - - - - Ammo12Gauge - - AmmoShotguns - - - \ No newline at end of file diff --git a/Defs/ThingDefs_Ammo/Ammo_Advanced.xml b/Defs/ThingDefs_Ammo/Ammo_Advanced.xml deleted file mode 100644 index b97000e5b0..0000000000 --- a/Defs/ThingDefs_Ammo/Ammo_Advanced.xml +++ /dev/null @@ -1,208 +0,0 @@ - - - - - - - Container holding fuel for incendiary shot firearms. - - 0.3 - 0.5 - - -
  • CE_AutoEnableTrade
  • -
  • CE_AutoEnableCrafting
  • -
    - -
  • Ammo30x64mmFuelCell
  • -
    - 75 -
    - - - Ammo_30x64mmFuel_Incendiary - - - Things/Ammo/FuelCell/Incendiary - Graphic_StackCount - - - 1.52 - - Bullet_30x64mmFuel_Incendiary - IncendiaryFuel - - - - Ammo_30x64mmFuel_Thermobaric - - - Things/Ammo/FuelCell/Thermobaric - Graphic_StackCount - - - 2.16 - - Bullet_30x64mmFuel_Thermobaric - ThermobaricFuel - - - - Ammo_30x64mmFuel_Foam - - - Things/Ammo/FuelCell/Foam - Graphic_StackCount - - - 0.61 - - Bullet_30x64mmFuel_Foam - FoamFuel - false - - - - - - Large fuel container for incendiary shot cannons. - - 3.0 - 8 - - -
  • Ammo80x128mmFuelCell
  • -
    - 25 -
    - - - Ammo_80x256mmFuel_Thermobaric - - - Things/Ammo/FuelCell/Large - Graphic_StackCount - - - 28.98 - - Bullet_80x256mmFuel_Thermobaric - ThermobaricFuel - - - - - - Charged shot ammo used by advanced assault rifle designs. - - 0.01 - 0.03 - - -
  • CE_AutoEnableTrade
  • -
  • CE_AutoEnableCrafting
  • -
    - -
  • Ammo6x24mmCharged
  • -
    -
    - - - Ammo_6x24mmCharged - - - Things/Ammo/Charged/Regular - Graphic_StackCount - - - 0.97 - - Bullet_6x24mmCharged - Charged - - - - Ammo_6x24mmCharged_AP - - - Things/Ammo/Charged/Concentrated - Graphic_StackCount - - - 0.97 - - Bullet_6x24mmCharged_AP - ChargedAP - - - - Ammo_6x24mmCharged_Ion - - - Things/Ammo/Charged/Ion - Graphic_StackCount - - - 0.97 - - Bullet_6x24mmCharged_Ion - Ionized - false - - - - - - Mechanoid-built charged shot ammo designed for high-velocity fire and armor penetration. - - 0.012 - 0.01 - - -
  • Ammo5x35mmCharged
  • -
    -
    - - - Ammo_5x35mmCharged - - - Things/Ammo/Charged/Concentrated - Graphic_StackCount - - - 1.28 - - Bullet_5x35mmCharged - Charged - - - - - - Mechanoid-built high-caliber charged shot ammo used in heavy weapons. - - 0.1 - 0.14 - - -
  • Ammo12x64mmCharged
  • -
    - 200 -
    - - - Ammo_12x64mmCharged - - - Things/Ammo/Charged/Large - Graphic_StackCount - - - 3.09 - - Bullet_12x64mmCharged - Charged - - -
    \ No newline at end of file diff --git a/Defs/ThingDefs_Ammo/Ammo_Base.xml b/Defs/ThingDefs_Ammo/Ammo_Base.xml deleted file mode 100644 index 59ebb9c660..0000000000 --- a/Defs/ThingDefs_Ammo/Ammo_Base.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - Combat_Realism.AmmoThing - - Item - Middle - true - true - Item - 500 - Metal_Drop - Metal_Drop - -
  • - - true - true - false - 15 - -
  • CE_Ammo
  • - - Sellable -
    - - - true - - -
    \ No newline at end of file diff --git a/Defs/ThingDefs_Ammo/Ammo_Grenades.xml b/Defs/ThingDefs_Ammo/Ammo_Grenades.xml deleted file mode 100644 index 0058697f30..0000000000 --- a/Defs/ThingDefs_Ammo/Ammo_Grenades.xml +++ /dev/null @@ -1,96 +0,0 @@ - - - - - - - Relatively small, low velocity grenade for use in grenade launchers. - - 0.2 - 0.3 - - -
  • CE_AutoEnableTrade
  • -
  • CE_AutoEnableCrafting
  • -
    - -
  • Ammo30x29mmGrenades
  • -
    - 75 -
    - - - Ammo_30x29mmGrenade_HE - - - Things/Ammo/GrenadeLauncher/HE - Graphic_StackCount - - - 1.73 - - Bullet_30x29mmGrenade_HE - GrenadeHE - - - - Ammo_30x29mmGrenade_EMP - - - Things/Ammo/GrenadeLauncher/EMP - Graphic_StackCount - - - 2.07 - - Bullet_30x29mmGrenade_EMP - GrenadeEMP - - - - - - Low velocity grenade fired from handheld grenade launchers. - - 0.3 - 0.4 - - -
  • CE_AutoEnableTrade
  • -
  • CE_AutoEnableCrafting
  • -
    - -
  • Ammo40x46mmGrenades
  • -
    - 75 -
    - - - Ammo_40x46mmGrenade_HE - - - Things/Ammo/GrenadeLauncher/HE - Graphic_StackCount - - - 2.19 - - Bullet_40x46mmGrenade_HE - GrenadeHE - - - - Ammo_40x46mmGrenade_EMP - - - Things/Ammo/GrenadeLauncher/EMP - Graphic_StackCount - - - 2.65 - - Bullet_40x46mmGrenade_EMP - GrenadeEMP - - -
    \ No newline at end of file diff --git a/Defs/ThingDefs_Ammo/Ammo_HighCaliber.xml b/Defs/ThingDefs_Ammo/Ammo_HighCaliber.xml deleted file mode 100644 index d77d3d33b4..0000000000 --- a/Defs/ThingDefs_Ammo/Ammo_HighCaliber.xml +++ /dev/null @@ -1,138 +0,0 @@ - - - - - - - Large caliber bullet used by many heavy machine guns and anti-materiel rifles. - - 0.11 - 0.15 - - -
  • CE_AutoEnableTrade
  • -
  • CE_AutoEnableCrafting
  • -
    - -
  • Ammo50BMG
  • -
    - 200 -
    - - - Ammo_50BMG_FMJ - - - Things/Ammo/HighCaliber/FMJ - Graphic_StackCount - - - 0.51 - - Bullet_50BMG_FMJ - FullMetalJacket - - - - Ammo_50BMG_AP - - - Things/Ammo/HighCaliber/Sabot - Graphic_StackCount - - - 0.48 - - Bullet_50BMG_Sabot - Sabot - - - - Ammo_50BMG_HE - - - Things/Ammo/HighCaliber/HE - Graphic_StackCount - - - 0.71 - - Bullet_50BMG_HE - ExplosiveAP - - - - Ammo_50BMG_Incendiary - - - Things/Ammo/HighCaliber/Incendiary - Graphic_StackCount - - - 0.67 - - Bullet_50BMG_Incendiary - IncendiaryAP - - - - - - Old-school anti-tank cartridge originally designed for AT rifles, it is also used by a number of heavy machine guns. - - 0.2 - 0.25 - - -
  • CE_AutoEnableTrade
  • -
  • CE_AutoEnableCrafting
  • -
    - -
  • Ammo145x114mm
  • -
    - 200 -
    - - - Ammo_145x114mm_FMJ - - - Things/Ammo/HighCaliber/FMJ - Graphic_StackCount - - - 0.92 - - Bullet_145x114mm_FMJ - FullMetalJacket - - - - Ammo_145x114mm_HE - - - Things/Ammo/HighCaliber/HE - Graphic_StackCount - - - 1.13 - - Bullet_145x114mm_HE - ExplosiveAP - - - - Ammo_145x114mm_Incendiary - - - Things/Ammo/HighCaliber/Incendiary - Graphic_StackCount - - - 1.06 - - Bullet_145x114mm_Incendiary - IncendiaryAP - - -
    \ No newline at end of file diff --git a/Defs/ThingDefs_Ammo/Ammo_Neolithic.xml b/Defs/ThingDefs_Ammo/Ammo_Neolithic.xml deleted file mode 100644 index c93182b4ee..0000000000 --- a/Defs/ThingDefs_Ammo/Ammo_Neolithic.xml +++ /dev/null @@ -1,118 +0,0 @@ - - - - - - - Simple arrow design with a cutting head attached to a wooden shaft. - - 0.11 - 0.11 - - -
  • AmmoArrows
  • -
    - 200 -
    - - - Ammo_Arrow_Stone - - - Things/Ammo/Neolithic/Arrow/Stone - Graphic_StackCount - - - 0.17 - - Projectile_Arrow_Stone - StoneArrow - - - - Ammo_Arrow_Steel - - - Things/Ammo/Neolithic/Arrow/Steel - Graphic_StackCount - - - 0.38 - - Projectile_Arrow_Steel - SteelArrow - - - - Ammo_Arrow_Plasteel - - - Things/Ammo/Neolithic/Arrow/Plasteel - Graphic_StackCount - - - 3.32 - - Projectile_Arrow_Plasteel - PlasteelArrow - false - - - - - - Heavy arrow designed to be fired from a great bow. - - 0.17 - 0.17 - - -
  • AmmoGreatArrows
  • -
    - 200 -
    - - - Ammo_GreatArrow_Stone - - - Things/Ammo/Neolithic/Arrow/Stone - Graphic_StackCount - - - 0.11 - - Projectile_GreatArrow_Stone - StoneArrow - - - - Ammo_GreatArrow_Steel - - - Things/Ammo/Neolithic/Arrow/Steel - Graphic_StackCount - - - 0.52 - - Projectile_GreatArrow_Steel - SteelArrow - - - - Ammo_GreatArrow_Plasteel - - - Things/Ammo/Neolithic/Arrow/Plasteel - Graphic_StackCount - - - 3.46 - - Projectile_GreatArrow_Plasteel - PlasteelArrow - false - - -
    \ No newline at end of file diff --git a/Defs/ThingDefs_Ammo/Ammo_Pistols.xml b/Defs/ThingDefs_Ammo/Ammo_Pistols.xml deleted file mode 100644 index ba29126f24..0000000000 --- a/Defs/ThingDefs_Ammo/Ammo_Pistols.xml +++ /dev/null @@ -1,325 +0,0 @@ - - - - - - - Ammo_40Rimfire - - Ultra-light cartridge for use in derringer pistols. - -
  • CE_AutoEnableTrade
  • -
  • CE_AutoEnableCrafting
  • -
    - -
  • Ammo40Rimfire
  • -
    - - Things/Ammo/Pistol/FMJ - Graphic_StackCount - - - 0.02 - 0.012 - 0.01 - - Bullet_40Rimfire - FullMetalJacket -
    - - - - - Low caliber handgun cartridge lacking in stopping power. - - 0.01 - 0.02 - - -
  • CE_AutoEnableTrade
  • -
  • CE_AutoEnableCrafting
  • -
    - -
  • Ammo32ACP
  • -
    -
    - - - Ammo_32ACP_FMJ - - - Things/Ammo/Pistol/FMJ - Graphic_StackCount - - - 0.05 - - Bullet_32ACP_FMJ - FullMetalJacket - - - - - - - - Common pistol cartridge used by a variety of handguns and SMGs. - - 0.01 - 0.02 - - -
  • CE_AutoEnableTrade
  • -
  • CE_AutoEnableCrafting
  • -
    - -
  • Ammo762x25mmTokarev
  • -
    -
    - - - Ammo_762x25mmTokarev_FMJ - - - Things/Ammo/Pistol/FMJ - Graphic_StackCount - - - 0.05 - - Bullet_762x25mmTokarev_FMJ - FullMetalJacket - - - - Ammo_762x25mmTokarev_AP - - - Things/Ammo/Pistol/AP - Graphic_StackCount - - - 0.06 - - Bullet_762x25mmTokarev_AP - ArmorPiercing - - - - Ammo_762x25mmTokarev_HP - - - Things/Ammo/Pistol/HP - Graphic_StackCount - - - 0.06 - - Bullet_762x25mmTokarev_HP - HollowPoint - - - - - - Common pistol cartridge used by a variety of handguns and SMGs. - - 0.012 - 0.02 - - -
  • CE_AutoEnableTrade
  • -
  • CE_AutoEnableCrafting
  • -
    - -
  • Ammo9x19mmPara
  • -
    -
    - - - Ammo_9x19mmPara_FMJ - - - Things/Ammo/Pistol/FMJ - Graphic_StackCount - - - 0.06 - - Bullet_9x19mmPara_FMJ - FullMetalJacket - - - - Ammo_9x19mmPara_AP - - - Things/Ammo/Pistol/AP - Graphic_StackCount - - - 0.07 - - Bullet_9x19mmPara_AP - ArmorPiercing - - - - Ammo_9x19mmPara_HP - - - Things/Ammo/Pistol/HP - Graphic_StackCount - - - 0.07 - - Bullet_9x19mmPara_HP - HollowPoint - - - - - - Pistol cartridge favoured for its above average stopping power. - - 0.02 - 0.03 - - -
  • CE_AutoEnableTrade
  • -
  • CE_AutoEnableCrafting
  • -
    - -
  • Ammo45ACP
  • -
    -
    - - - Ammo_45ACP_FMJ - - - Things/Ammo/Pistol/FMJ - Graphic_StackCount - - - 0.09 - - Bullet_45ACP_FMJ - FullMetalJacket - - - - Ammo_45ACP_AP - - - Things/Ammo/Pistol/AP - Graphic_StackCount - - - 0.10 - - Bullet_45ACP_AP - ArmorPiercing - - - - Ammo_45ACP_HP - - - Things/Ammo/Pistol/HP - Graphic_StackCount - - - 0.10 - - Bullet_45ACP_HP - HollowPoint - - - - - - Ancient pistol cartridge originally designed for revolvers. - - 0.02 - 0.03 - - -
  • CE_AutoEnableTrade
  • -
  • CE_AutoEnableCrafting
  • -
    - -
  • Ammo45Colt
  • -
    -
    - - - Ammo_45Colt_FMJ - - - Things/Ammo/Pistol/FMJ - Graphic_StackCount - - - 0.09 - - Bullet_45Colt_FMJ - FullMetalJacket - - - - Ammo_45Colt_AP - - - Things/Ammo/Pistol/AP - Graphic_StackCount - - - 0.10 - - Bullet_45Colt_AP - ArmorPiercing - - - - Ammo_45Colt_HP - - - Things/Ammo/Pistol/HP - Graphic_StackCount - - - 0.10 - - Bullet_45Colt_HP - HollowPoint - - -
    \ No newline at end of file diff --git a/Defs/ThingDefs_Ammo/Ammo_Rifles.xml b/Defs/ThingDefs_Ammo/Ammo_Rifles.xml deleted file mode 100644 index d9df91775d..0000000000 --- a/Defs/ThingDefs_Ammo/Ammo_Rifles.xml +++ /dev/null @@ -1,299 +0,0 @@ - - - - - - - Small, high-velocity rifle bullet used in a variety of assault rifles. - - 0.012 - 0.03 - - -
  • CE_AutoEnableTrade
  • -
  • CE_AutoEnableCrafting
  • -
    - -
  • Ammo556x45mmNATO
  • -
    -
    - - - Ammo_556x45mmNATO_FMJ - - - Things/Ammo/Rifle/FMJ - Graphic_StackCount - - - 0.06 - - Bullet_556x45mmNATO_FMJ - FullMetalJacket - - - - Ammo_556x45mmNATO_AP - - - Things/Ammo/Rifle/AP - Graphic_StackCount - - - 0.07 - - Bullet_556x45mmNATO_AP - ArmorPiercing - - - - Ammo_556x45mmNATO_HP - - - Things/Ammo/Rifle/HP - Graphic_StackCount - - - 0.07 - - Bullet_556x45mmNATO_HP - HollowPoint - - - - - - Intermediate rifle cartridge used by certain older assault rifles. - - 0.016 - 0.04 - - -
  • CE_AutoEnableTrade
  • -
  • CE_AutoEnableCrafting
  • -
    - -
  • Ammo762x39mmSoviet
  • -
    -
    - - - Ammo_762x39mmSoviet_FMJ - - - Things/Ammo/Rifle/FMJ - Graphic_StackCount - - - 0.07 - - Bullet_762x39mmSoviet_FMJ - FullMetalJacket - - - - Ammo_762x39mmSoviet_AP - - - Things/Ammo/Rifle/AP - Graphic_StackCount - - - 0.08 - - Bullet_762x39mmSoviet_AP - ArmorPiercing - - - - Ammo_762x39mmSoviet_HP - - - Things/Ammo/Rifle/HP - Graphic_StackCount - - - 0.08 - - Bullet_762x39mmSoviet_HP - HollowPoint - - - - - - Large rifle bullet found mostly in outdated bolt-action firearms. - - 0.022 - 0.05 - - -
  • CE_AutoEnableTrade
  • -
  • CE_AutoEnableCrafting
  • -
    - -
  • Ammo303British
  • -
    -
    - - - Ammo_303British_FMJ - - - Things/Ammo/Rifle/FMJ - Graphic_StackCount - - - 0.10 - - Bullet_303British_FMJ - FullMetalJacket - - - - Ammo_303British_AP - - - Things/Ammo/Rifle/AP - Graphic_StackCount - - - 0.11 - - Bullet_303British_AP - ArmorPiercing - - - - Ammo_303British_HP - - - Things/Ammo/Rifle/HP - Graphic_StackCount - - - 0.11 - - Bullet_303British_HP - HollowPoint - - - - - - Large rifle bullet used in machine guns, sniper rifles and the occasional assault rifle. - - 0.025 - 0.05 - - -
  • CE_AutoEnableTrade
  • -
  • CE_AutoEnableCrafting
  • -
    - -
  • Ammo762x51mmNATO
  • -
    -
    - - - Ammo_762x51mmNATO_FMJ - - - Things/Ammo/Rifle/FMJ - Graphic_StackCount - - - 0.12 - - Bullet_762x51mmNATO_FMJ - FullMetalJacket - - - - Ammo_762x51mmNATO_AP - - - Things/Ammo/Rifle/AP - Graphic_StackCount - - - 0.13 - - Bullet_762x51mmNATO_AP - ArmorPiercing - - - - Ammo_762x51mmNATO_HP - - - Things/Ammo/Rifle/HP - Graphic_StackCount - - - 0.13 - - Bullet_762x51mmNATO_HP - HollowPoint - - - - - - Rimmed rifle cartridge used by many machine guns, bolt-action and sniper rifles. - - 0.022 - 0.05 - - -
  • CE_AutoEnableTrade
  • -
  • CE_AutoEnableCrafting
  • -
    - -
  • Ammo762x54mmR
  • -
    -
    - - - Ammo_762x54mmR_FMJ - - - Things/Ammo/Rifle/FMJ - Graphic_StackCount - - - 0.10 - - Bullet_762x54mmR_FMJ - FullMetalJacket - - - - Ammo_762x54mmR_AP - - - Things/Ammo/Rifle/AP - Graphic_StackCount - - - 0.11 - - Bullet_762x54mmR_AP - ArmorPiercing - - - - Ammo_762x54mmR_HP - - - Things/Ammo/Rifle/HP - Graphic_StackCount - - - 0.11 - - Bullet_762x54mmR_HP - HollowPoint - - -
    \ No newline at end of file diff --git a/Defs/ThingDefs_Ammo/Ammo_Rockets.xml b/Defs/ThingDefs_Ammo/Ammo_Rockets.xml deleted file mode 100644 index 6d73d4dec1..0000000000 --- a/Defs/ThingDefs_Ammo/Ammo_Rockets.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - Rocket-propelled grenade designed for the RPG-7 launcher. After being fired a rocket motor kicks in to propel the grenade further. - -
  • CE_AutoEnableTrade
  • -
  • CE_AutoEnableCrafting
  • -
    - -
  • AmmoRPG7Grenades
  • -
    - 25 -
    - - - Ammo_RPG7Grenade_HEAT - - - Things/Ammo/RPG/HEAT - Graphic_StackCount - - - 23.23 - 2.6 - 4 - - Bullet_RPG7Grenade_HEAT - RocketHEAT - - - - Ammo_RPG7Grenade_Thermobaric - - - Things/Ammo/RPG/Thermobaric - Graphic_StackCount - - - 37.03 - 4.5 - 6 - - Bullet_RPG7Grenade_Thermobaric - RocketThermobaric - - - - Ammo_RPG7Grenade_Frag - - - Things/Ammo/RPG/Frag - Graphic_StackCount - - - 18.17 - 4.5 - 6 - - Bullet_RPG7Grenade_Frag - RocketFrag - - -
    \ No newline at end of file diff --git a/Defs/ThingDefs_Ammo/Ammo_Shells.xml b/Defs/ThingDefs_Ammo/Ammo_Shells.xml deleted file mode 100644 index b4a32734cf..0000000000 --- a/Defs/ThingDefs_Ammo/Ammo_Shells.xml +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - Low-velocity shell designed to be fired from a mortar. - -
  • Ammo81mmMortarShells
  • -
    - 25 - Stockable -
    - - - MortarShell - - - Things/Ammo/Mortar/HE - Graphic_Single - - - 28.52 - 4.24 - 5 - - Bullet_81mmMortarShell_HE - GrenadeHE - - - - Ammo_81mmMortarShell_Incendiary - - - Things/Ammo/Mortar/Incendiary - Graphic_Single - - - 23.92 - 4.1 - 5.5 - - Bullet_81mmMortarShell_Incendiary - GrenadeIncendiary - - - - Ammo_81mmMortarShell_EMP - - - Things/Ammo/Mortar/EMP - Graphic_Single - - - 19.78 - 4.5 - 6 - - Bullet_81mmMortarShell_EMP - GrenadeEMP - - - - - - Relatively small cannon shell. - -
  • Ammo90mmCannonShells
  • -
    - 25 - -
  • CE_AutoEnableTrade
  • -
  • CE_AutoEnableCrafting
  • -
    - - 4.6 - 7 - -
    - - - Ammo_90mmCannonShell_HEAT - - - Things/Ammo/Cannon/HEAT - Graphic_Single - - - 27.83 - - Bullet_90mmCannonShell_HEAT - RocketHEAT - - - - Ammo_90mmCannonShell_HE - - - Things/Ammo/Cannon/HE - Graphic_Single - - - 28.98 - - Bullet_90mmCannonShell_HE - GrenadeHE - - - - Ammo_90mmCannonShell_EMP - - - Things/Ammo/Cannon/EMP - Graphic_Single - - - 34.73 - - Bullet_90mmCannonShell_EMP - GrenadeEMP - - -
    diff --git a/Defs/ThingDefs_Ammo/Ammo_Shotgun.xml b/Defs/ThingDefs_Ammo/Ammo_Shotgun.xml deleted file mode 100644 index de5a014c3c..0000000000 --- a/Defs/ThingDefs_Ammo/Ammo_Shotgun.xml +++ /dev/null @@ -1,126 +0,0 @@ - - - - - - - Low caliber shotgun shell. Its small diameter allows it to be fired from many of the same firearms as the .45 Colt cartridge. - - 0.06 - 0.11 - - -
  • CE_AutoEnableTrade
  • -
  • CE_AutoEnableCrafting
  • -
    - -
  • Ammo410Bore
  • -
    - 200 -
    - - - Ammo_410Bore_Buck - - - Things/Ammo/Shotgun/Shot - Graphic_StackCount - - - 0.14 - - Bullet_410Bore_Buck - BuckShot - - - - - - Extremely common shotgun caliber used in almost every application, from hunting over riot control to military firearms. - - 0.08 - 0.15 - - -
  • CE_AutoEnableTrade
  • -
  • CE_AutoEnableCrafting
  • -
    - -
  • Ammo12Gauge
  • -
    - 200 -
    - - - Ammo_12Gauge_Buck - - - Things/Ammo/Shotgun/Shot - Graphic_StackCount - - - 0.23 - - Bullet_12Gauge_Buck - BuckShot - - - - Ammo_12Gauge_Bird - - - Things/Ammo/Shotgun/Shot - Graphic_StackCount - - - 0.23 - - Bullet_12Gauge_Bird - BirdShot - - - - Ammo_12Gauge_Slug - - - Things/Ammo/Shotgun/Slug - Graphic_StackCount - - - 0.1 - 0.30 - - Bullet_12Gauge_Slug - Slug - - - - Ammo_12Gauge_Beanbag - - false - - Things/Ammo/Shotgun/Beanbag - Graphic_StackCount - - - 0.18 - - Bullet_12Gauge_Beanbag - Beanbag - - - - Ammo_12Gauge_ElectroSlug - - - Things/Ammo/Shotgun/EMP - Graphic_StackCount - - - 0.48 - - Bullet_12Gauge_ElectroSlug - ElectroSlug - - -
    \ No newline at end of file diff --git a/Defs/ThingDefs_Ammo/Projectiles_Advanced.xml b/Defs/ThingDefs_Ammo/Projectiles_Advanced.xml deleted file mode 100644 index 9a6b738619..0000000000 --- a/Defs/ThingDefs_Ammo/Projectiles_Advanced.xml +++ /dev/null @@ -1,202 +0,0 @@ - - - - - - - - Things/Projectile/InfernoCannonShot - Graphic_Single - TransparentPostLight - - - 60 - false - - - - - Bullet_30x64mmFuel_Incendiary - Combat_Realism.ProjectileCE_Explosive - - - Flame - 50 - 2.0 - Napalm_Fuel - - - - - Bullet_30x64mmFuel_Thermobaric - - - 1.5 - Thermobaric - 30 - MortarBomb_Explode - - -
  • - 50 - Thermobaric - 2.0 - MortarBomb_Explode - true -
  • -
    -
    - - - Bullet_30x64mmFuel_Foam - Combat_Realism.ProjectileCE_Explosive - - - Extinguish - 50 - 5.0 - FilthFireFoam - 1 - - - - - - - Bullet_80x256mmFuel_Thermobaric - Combat_Realism.ProjectileCE_Explosive - - - Things/Projectile/InfernoCannonShot - Graphic_Single - TransparentPostLight - - - Flame - 40 - 60 - false - 3.5 - Napalm_Fuel - 0.5 - MortarIncendiary_Explode - ArtilleryHitThickRoof - MortarRound_PreImpact - MortarRound_Ambient - - - - - - - - - - Things/Projectile/Charge_Small - Graphic_Single - - - Bullet - 170 - - - - - Bullet_6x24mmCharged - - - 11 - -
  • - Bomb_Secondary - 7 -
  • -
    - 0.65 -
    -
    - - - Bullet_6x24mmCharged_AP - - - 11 - -
  • - Bomb_Secondary - 3 -
  • -
    - 0.7 -
    -
    - - - Bullet_6x24mmCharged_Ion - - - 11 - -
  • - Electrical - 3 -
  • -
  • - EMP - 6 -
  • -
    - 0.65 -
    -
    - - - - - Bullet_5x35mmCharged - - - Things/Projectile/ChargeLanceShot - Graphic_Single - TransparentPostLight - (3,3) - - - Bullet - 10 - 170 - -
  • - Bomb_Secondary - 3 -
  • -
    - 0.75 -
    -
    - - - - - Bullet_12x64mmCharged - - - Things/Projectile/Charge_Small - Graphic_Single - TransparentPostLight - - - Bullet - 25 - 180 - -
  • - Bomb_Secondary - 15 -
  • -
    - 0.8 -
    -
    - -
    \ No newline at end of file diff --git a/Defs/ThingDefs_Ammo/Projectiles_Base.xml b/Defs/ThingDefs_Ammo/Projectiles_Base.xml deleted file mode 100644 index 28ec4990a9..0000000000 --- a/Defs/ThingDefs_Ammo/Projectiles_Base.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - Projectile - Normal - Projectile - Combat_Realism.BulletCE - - False - True - - Transparent - - - - \ No newline at end of file diff --git a/Defs/ThingDefs_Ammo/Projectiles_Fragments.xml b/Defs/ThingDefs_Ammo/Projectiles_Fragments.xml deleted file mode 100644 index 39b7017879..0000000000 --- a/Defs/ThingDefs_Ammo/Projectiles_Fragments.xml +++ /dev/null @@ -1,120 +0,0 @@ - - - - - Projectile - Normal - Projectile - Combat_Realism.BulletCE - - False - True - - Transparent - - - - - - - true - - - - - - - Fragment_MortarSmall - - - Things/Projectile/Fragments/Fragment_Small - Graphic_Single - - - Fragment - 12 - 160 - 0.3 - - - - - Fragment_MortarMedium - - - Things/Projectile/Fragments/Fragment_Medium - Graphic_Single - - - Fragment - 18 - 140 - 0.25 - - - - - Fragment_MortarLarge - - - Things/Projectile/Fragments/Fragment_Large - Graphic_Single - - - false - Fragment - 27 - 120 - 0.25 - - - - - - - Fragment_GrenadeFragSmall - - - Things/Projectile/Fragments/Fragment_Small - Graphic_Single - - - Fragment - 6 - 160 - 0.25 - - - - - Fragment_GrenadeFragMedium - - - Things/Projectile/Fragments/Fragment_Medium - Graphic_Single - - - Fragment - 8 - 140 - 0.25 - - - - - Fragment_GrenadeFragLarge - - - Things/Projectile/Fragments/Fragment_Large - Graphic_Single - - - false - Fragment - 10 - 120 - 0.2 - - - - \ No newline at end of file diff --git a/Defs/ThingDefs_Ammo/Projectiles_Grenades.xml b/Defs/ThingDefs_Ammo/Projectiles_Grenades.xml deleted file mode 100644 index 808b06f158..0000000000 --- a/Defs/ThingDefs_Ammo/Projectiles_Grenades.xml +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - - Combat_Realism.ProjectileCE_Explosive - - Things/Projectile/Bullet_Big - Graphic_Single - - - 60 - false - - - - - Bullet_30x29mmGrenade_HE - - - 2.0 - Bomb - 40 - - -
  • - 2.5 - - 120 - 90 - 24 - -
  • -
    -
    - - - Bullet_30x29mmGrenade_EMP - - - 2.5 - EMP - 40 - - -
  • - 10 - Electrical - 2.5 - Explosion_Bomb -
  • -
    -
    - - - - - Combat_Realism.ProjectileCE_Explosive - - Things/Projectile/Bullet_Big - Graphic_Single - - - 30 - - - - - Bullet_40x46mmGrenade_HE - - - 1.8 - Bomb - 50 - - -
  • - 3 - - 140 - 105 - 30 - -
  • -
    -
    - - - Bullet_40x46mmGrenade_EMP - - - 3.0 - EMP - 60 - - -
  • - 15 - Electrical - 3.0 - Explosion_Bomb -
  • -
    -
    - -
    \ No newline at end of file diff --git a/Defs/ThingDefs_Ammo/Projectiles_HighCaliber.xml b/Defs/ThingDefs_Ammo/Projectiles_HighCaliber.xml deleted file mode 100644 index d7b235165a..0000000000 --- a/Defs/ThingDefs_Ammo/Projectiles_HighCaliber.xml +++ /dev/null @@ -1,124 +0,0 @@ - - - - - - - - - - Things/Projectile/Bullet_Big - Graphic_Single - - - Bullet - 186 - true - - - - - Bullet_50BMG_FMJ - - - 40 - 0.9 - - - - - Bullet_50BMG_Sabot - - - 25 - 1.1 - 244 - - - - - Bullet_50BMG_HE - - - 25 - 0.9 - -
  • - Bomb_Secondary - 25 -
  • -
    -
    -
    - - - Bullet_50BMG_Incendiary - - - 35 - 1.1 - -
  • - Flame_Secondary - 5 -
  • -
    -
    -
    - - - - - - - Things/Projectile/Bullet_Big - Graphic_Single - - - Bullet - 186 - true - - - - - Bullet_145x114mm_FMJ - - - 50 - 1.1 - - - - - Bullet_145x114mm_HE - - - 30 - 1.1 - -
  • - Bomb_Secondary - 30 -
  • -
    -
    -
    - - - Bullet_145x114mm_Incendiary - - - 45 - 1.3 - -
  • - Flame_Secondary - 5 -
  • -
    -
    -
    - - -
    diff --git a/Defs/ThingDefs_Ammo/Projectiles_Neolithic.xml b/Defs/ThingDefs_Ammo/Projectiles_Neolithic.xml deleted file mode 100644 index 93ce085da1..0000000000 --- a/Defs/ThingDefs_Ammo/Projectiles_Neolithic.xml +++ /dev/null @@ -1,102 +0,0 @@ - - - - - - - - Things/Projectile/Arrow_Small - Graphic_Single - - - Arrow - 44 - - - - - Projectile_Arrow_Stone - - - 11 - 0.15 - - - - - Projectile_Arrow_Steel - - - 11 - 0.20 - - - - - Projectile_Arrow_Plasteel - - - 11 - 0.25 - - - - - - - - Things/Projectile/Arrow_Small - Graphic_Single - - - Arrow - 49 - - - - - Projectile_GreatArrow_Stone - - - 15 - 0.2 - - - - - Projectile_GreatArrow_Steel - - - 15 - 0.275 - - - - - Projectile_GreatArrow_Plasteel - - - 15 - 0.35 - - - - - - - Pilum_Thrown - - - Things/Projectile/Pilum - Graphic_Single - - - Stab - 16 - 26 - 0.3 - - - - - diff --git a/Defs/ThingDefs_Ammo/Projectiles_Pistols.xml b/Defs/ThingDefs_Ammo/Projectiles_Pistols.xml deleted file mode 100644 index 02f71671af..0000000000 --- a/Defs/ThingDefs_Ammo/Projectiles_Pistols.xml +++ /dev/null @@ -1,228 +0,0 @@ - - - - - - - Bullet_40Rimfire - - - Things/Projectile/Bullet_Small - Graphic_Single - - - Bullet - 71 - 6 - 0.1 - true - - - - - - - - Things/Projectile/Bullet_Small - Graphic_Single - - - Bullet - 62 - true - - - - - Bullet_32ACP_FMJ - - - 8 - 0.25 - - - - - Bullet_32ACP_AP - - - 6 - 0.3 - - - - - Bullet_32ACP_HP - - - 11 - 0.2 - - - - - - - - Things/Projectile/Bullet_Small - Graphic_Single - - - Bullet - 82 - true - - - - - Bullet_762x25mmTokarev_FMJ - - - 11 - 0.35 - - - - - Bullet_762x25mmTokarev_AP - - - 8 - 0.45 - - - - - Bullet_762x25mmTokarev_HP - - - 14 - 0.275 - - - - - - - - Things/Projectile/Bullet_Small - Graphic_Single - - - Bullet - 78 - true - - - - - Bullet_9x19mmPara_FMJ - - - 12 - 0.325 - - - - - Bullet_9x19mmPara_AP - - - 9 - 0.425 - - - - - Bullet_9x19mmPara_HP - - - 15 - 0.25 - - - - - - - - Things/Projectile/Bullet_Small - Graphic_Single - - - Bullet - 67 - true - - - - - Bullet_45ACP_FMJ - - - 14 - 0.3 - - - - - Bullet_45ACP_AP - - - 11 - 0.4 - - - - - Bullet_45ACP_HP - - - 17 - 0.225 - - - - - - - - Things/Projectile/Bullet_Small - Graphic_Single - - - Bullet - 50 - true - - - - - Bullet_45Colt_FMJ - - - 14 - 0.3 - - - - - Bullet_45Colt_AP - - - 11 - 0.4 - - - - - Bullet_45Colt_HP - - - 17 - 0.225 - - - - - diff --git a/Defs/ThingDefs_Ammo/Projectiles_Rifles.xml b/Defs/ThingDefs_Ammo/Projectiles_Rifles.xml deleted file mode 100644 index 6203ec3a84..0000000000 --- a/Defs/ThingDefs_Ammo/Projectiles_Rifles.xml +++ /dev/null @@ -1,226 +0,0 @@ - - - - - - - - - - Things/Projectile/Bullet_Small - Graphic_Single - - - Bullet - 188 - true - - - - - - Bullet_556x45mmNATO_FMJ - - - 14 - 0.525 - - - - - Bullet_556x45mmNATO_AP - - - 11 - 0.625 - - - - - Bullet_556x45mmNATO_HP - - - 17 - 0.375 - - - - - - - - - Things/Projectile/Bullet_Small - Graphic_Single - - - Bullet - 146 - true - - - - - Bullet_762x39mmSoviet_FMJ - - - Things/Projectile/Bullet_Small - Graphic_Single - - - 16 - 0.55 - - - - - Bullet_762x39mmSoviet_AP - - - Things/Projectile/Bullet_Small - Graphic_Single - - - 13 - 0.65 - - - - - Bullet_762x39mmSoviet_HP - - - Things/Projectile/Bullet_Small - Graphic_Single - - - 19 - 0.4 - - - - - - - - Things/Projectile/Bullet_Small - Graphic_Single - - - Bullet - 169 - true - - - - - Bullet_303British_FMJ - - - 18 - 0.6 - - - - - Bullet_303British_AP - - - 15 - 0.7 - - - - - Bullet_303British_HP - - - 21 - 0.45 - - - - - - - - Things/Projectile/Bullet_Small - Graphic_Single - - - Bullet - 167 - true - - - - - Bullet_762x51mmNATO_FMJ - - - 18 - 0.6 - - - - - Bullet_762x51mmNATO_AP - - - 15 - 0.7 - - - - - Bullet_762x51mmNATO_HP - - - 21 - 0.45 - - - - - - - - Things/Projectile/Bullet_Small - Graphic_Single - - - Bullet - 157 - true - - - - - Bullet_762x54mmR_FMJ - - - 18 - 0.6 - - - - - Bullet_762x54mmR_AP - - - 15 - 0.7 - - - - - Bullet_762x54mmR_HP - - - 21 - 0.45 - - - - - diff --git a/Defs/ThingDefs_Ammo/Projectiles_Rockets.xml b/Defs/ThingDefs_Ammo/Projectiles_Rockets.xml deleted file mode 100644 index a7c1395921..0000000000 --- a/Defs/ThingDefs_Ammo/Projectiles_Rockets.xml +++ /dev/null @@ -1,103 +0,0 @@ - - - - - - - Combat_Realism.ProjectileCE_Explosive_RL - - TransparentPostLight - - - 65 - ArtilleryHitThickRoof - MortarRound_PreImpact - RocketPropelledLoop_Small - false - - - - - Bullet_RPG7Grenade_HEAT - - - Things/Projectile/RPG/HEAT - Graphic_Single - - - Bullet - 150 - 3.0 - - -
  • - 30 - Bomb - 1 - 6 - - 40 - 16 - 6 - - MortarBomb_Explode -
  • -
    -
    - - - Bullet_RPG7Grenade_Thermobaric - - - Things/Projectile/RPG/Thermobaric - Graphic_Single - - - 1.7 - Thermobaric - 50 - - -
  • - 40 - Thermobaric - 4.0 - true - 6 - - 30 - 12 - 4 - - MortarBomb_Explode -
  • -
    -
    - - - Bullet_RPG7Grenade_Frag - Combat_Realism.ProjectileCE_Explosive - - - Things/Projectile/RPG/Frag - Graphic_Single - - - 1.7 - Bomb - 50 - - -
  • - 9 - - 120 - 60 - 20 - - MortarBomb_Explode -
  • -
    -
    - -
    diff --git a/Defs/ThingDefs_Ammo/Projectiles_Shells.xml b/Defs/ThingDefs_Ammo/Projectiles_Shells.xml deleted file mode 100644 index 9e13ef25eb..0000000000 --- a/Defs/ThingDefs_Ammo/Projectiles_Shells.xml +++ /dev/null @@ -1,184 +0,0 @@ - - - - - - - Combat_Realism.ProjectileCE_Explosive - - TransparentPostLight - - - 70 - ArtilleryHitThickRoof - MortarRound_PreImpact - MortarRound_Ambient - true - true - Mote_BigShell - - - - - Bullet_81mmMortarShell_HE - - - Things/Projectile/Mortar/HE - Graphic_Single - - - Bomb - 150 - 1 - MortarBomb_Explode - - -
  • - 100 - Bomb - 2.5 - - 200 - 100 - 40 - - 10 -
  • -
    -
    - - - Bullet_81mmMortarShell_Incendiary - - - Things/Projectile/Mortar/Incendiary - Graphic_Single - - - Flame - 50 - 3.5 - Napalm_Fuel - 0.5 - MortarIncendiary_Explode - - - - - Bullet_81mmMortarShell_EMP - - - Things/Projectile/Mortar/EMP - Graphic_Single - - - EMP - 80 - 5 - MortarBomb_Explode - - -
  • - 20 - Electrical - 5 -
  • -
    -
    - - - - - TransparentPostLight - - - 155 - MortarBomb_Explode - false - true - Mote_BigShell - - - - - Bullet_90mmCannonShell_HEAT - - - Things/Projectile/Cannon/HEAT - Graphic_Single - - - Bullet - 200 - MortarBomb_Explode - 5.0 - - -
  • - 50 - Bomb - 1.5 - - 30 - 16 - 7 - - 7.5 -
  • -
    -
    - - - Bullet_90mmCannonShell_HE - - Combat_Realism.ProjectileCE_Explosive - - Things/Projectile/Cannon/HE - Graphic_Single - - - Bomb - 150 - 1.7 - MortarBomb_Explode - - -
  • - 100 - Bomb - 2.5 - - 240 - 120 - 45 - - 10 -
  • -
    -
    - - - Bullet_90mmCannonShell_EMP - - Combat_Realism.ProjectileCE_Explosive - - Things/Projectile/Cannon/EMP - Graphic_Single - - - EMP - 80 - 5 - Explosion_Bomb - - -
  • - 20 - Electrical - 5 -
  • -
    -
    - -
    - diff --git a/Defs/ThingDefs_Ammo/Projectiles_Shotgun.xml b/Defs/ThingDefs_Ammo/Projectiles_Shotgun.xml deleted file mode 100644 index 1499b02efe..0000000000 --- a/Defs/ThingDefs_Ammo/Projectiles_Shotgun.xml +++ /dev/null @@ -1,118 +0,0 @@ - - - - - - - - Bullet - 70 - true - Mote_ShotgunShell - - - - - Bullet_410Bore_Buck - - - Things/Projectile/Shotgun_Pellet - Graphic_Single - - - 12 - 5 - 0.3 - 8.5 - - - - - - - - Bullet - 70 - true - Mote_ShotgunShell - - - - - Bullet_12Gauge_Buck - - - Things/Projectile/Shotgun_Pellet - Graphic_Single - - - 10 - 8 - 0.3 - 5 - - - - - Bullet_12Gauge_Bird - - - Things/Projectile/Shotgun_Pellet - Graphic_Single - - - 3 - 40 - 10 - 0.1 - - - - - Bullet_12Gauge_Slug - - - Things/Projectile/Bullet_big - Graphic_Single - - - 110 - 30 - 0.3 - - - - - Bullet_12Gauge_Beanbag - - - Things/Projectile/Bullet_big - Graphic_Single - - - Beanbag - 6 - 0.15 - - - - - Bullet_12Gauge_ElectroSlug - - - Things/Projectile/Bullet_big - Graphic_Single - - - EMP - 20 - -
  • - Electrical - 5 -
  • -
    -
    -
    - -
    diff --git a/Defs/ThingDefs_Buildings/Buildings_Defenses.xml b/Defs/ThingDefs_Buildings/Buildings_Defenses.xml index 1382640227..7f73dfa6f2 100644 --- a/Defs/ThingDefs_Buildings/Buildings_Defenses.xml +++ b/Defs/ThingDefs_Buildings/Buildings_Defenses.xml @@ -1,6 +1,6 @@ - + Building Building @@ -11,32 +11,9 @@ Repair true BuildingRubble - -
  • - Bomb - 2.5 -
  • -
  • - Thermobaric - 2.5 -
  • -
  • - Bullet - 0.2 -
  • -
  • - Fragment - 0.1 -
  • -
  • - Arrow - 0.05 -
  • -
  • - Electrical - 0.2 -
  • -
    + + 0.70 +
    @@ -130,7 +107,7 @@ Building Impassable true - 0.73 + 0.7 true 1 Never diff --git a/Defs/ThingDefs_Buildings/Buildings_Exotic.xml b/Defs/ThingDefs_Buildings/Buildings_Exotic.xml deleted file mode 100644 index 2de4e968f5..0000000000 --- a/Defs/ThingDefs_Buildings/Buildings_Exotic.xml +++ /dev/null @@ -1,70 +0,0 @@ - - - - - Building - 150 - true - Impassable - 1.0 - (6,3) - - 1200 - 0 - -100 - - Normal - false - true - true - true - Light - BulletImpactMetal - MapMeshOnly - ConstructMetal - false - 1.0 - true - - false - CrashedShipPart_Ambience - 0.2 - - - - - CrashedPsychicEmanatorShipPart - - A mysterious crashed piece of a spaceship. It may contain exotic materials, computers, even AI personas. This kind of technology can be dangerous. - Building_PsychicEmanator - - Things/Building/Exotic/CrashedShipPart - Graphic_Single - (6,3) - - - 1 - 280 - 140 - 2 - - - - - CrashedPoisonShipPart - - A mysterious crashed piece of a spaceship. It may contain exotic materials, computers, even AI personas. This one seems to be poisoning the ground around it. - Building_PoisonShipPart - - Things/Building/Exotic/CrashedPoisonShipPart - Graphic_Single - (6,3) - - - 230 - 120 - 2 - - - - \ No newline at end of file diff --git a/Defs/ThingDefs_Buildings/Buildings_Natural.xml b/Defs/ThingDefs_Buildings/Buildings_Natural.xml deleted file mode 100644 index 7f14d82240..0000000000 --- a/Defs/ThingDefs_Buildings/Buildings_Natural.xml +++ /dev/null @@ -1,366 +0,0 @@ - - - - - Building - true - MapMeshOnly - RockRubble - false - -
  • - Bomb - 2.5 -
  • -
  • - Thermobaric - 2.5 -
  • -
  • - Bullet - 0.05 -
  • -
  • - Fragment - 0.05 -
  • -
  • - Electrical - 0.0 -
  • -
    -
    - - - Mineable - - Things/Building/Linked/Rock_Atlas - Graphic_Single - CornerFiller - -
  • Rock
  • -
  • MapEdge
  • -
    -
    - Building - Impassable - true - true - 1 - true - true - false - true - true - 1.0 - true - true - - 0 - - - true - true - false - false - -
    - - - - - CollapsedRocks - - - Things/Building/Natural/CollapsedRocks - Graphic_Single - None - (3,3) - - - 500 - - Collapsed rocks, packed tightly enough to hold up a roof. - true - - false - false - - - - - - - MineableSteel - - - Things/Building/Linked/RockFlecked_Atlas - Graphic_Single - CutoutComplex - (114,92,83) - (155,133,107) - - - 1500 - - The remains of some ancient, collapsed structure. Rich in steel. - - true - Steel - 35 - 1 - - 20 - 40 - - - - - - MineableSilver - - - Things/Building/Linked/RockFlecked_Atlas - Graphic_Single - CutoutComplex - (89,83,68) - (147,144,134) - - - 1500 - - Rock containing bits of silver. - - true - Silver - 35 - 0.10 - - 4 - 12 - - - - - - MineableGold - - - Things/Building/Linked/RockFlecked_Atlas - Graphic_Single - CutoutComplex - (89,83,68) - (187,173,25) - - - 1500 - - Rock containing bits of gold. - - true - Gold - 35 - 0.07 - - 1 - 6 - - - - - - MineableUranium - - - Things/Building/Linked/RockFlecked_Atlas - Graphic_Single - CutoutComplex - (114,114,114) - (70,70,70) - - - 4000 - - Rock containing bits of uranium. - - true - Uranium - 35 - 0.07 - - 1 - 6 - - - - - - MineablePlasteel - - - Things/Building/Linked/RockFlecked_Atlas - Graphic_Single - CutoutComplex - (110,118,118) - (134,166,166) - - - 10000 - - Ancient compacted rubble rich in plasteel. - - true - Plasteel - 35 - 0.05 - - 10 - 50 - - - - - - MineableJade - - - Things/Building/Linked/RockFlecked_Atlas - Graphic_Single - CutoutComplex - (68,83,68) - (30,173,25) - - - 1500 - - Rock containing bits of jade. - - true - Jade - 35 - 0.065 - - 1 - 6 - - - - - - MineableComponents - - - Things/Building/Linked/CompactedMachinery_Atlas - Graphic_Single - CutoutComplex - - - 2000 - - Ancient machinery, compacted over time. Can be mined for useful components. - - true - Component - 2 - 1.00 - - 3 - 6 - - - - - - SteamGeyser - Building_SteamGeyser - - - Things/Building/Natural/SteamGeyser - Graphic_Single - Transparent - (4,4) - - Floor - false - false - false - Normal - true - Natural steam source. - (2,2) - true - true - - false - false - false - - - - - Hive - - A hive of giant insects. Will spawn additional insects and hives over time. - Hive - - Things/Building/Natural/Hive - Graphic_Single - 1.6 - - Building - false - - 300 - 1.0 - - 10 - true - Rare - PassThroughOnly - -
  • -
  • - InsectJelly - 20 - - 26000 - 30000 - - 40 - true -
  • -
  • - GlowPod - 1 - - 30000 - 60000 - - 1 -
  • -
  • - 7 - 38 -
  • -
  • - - -20 - 9999 - - 8 -
  • -
  • - FilthSlime - 10 - 4 - 5 -
  • -
  • - 60000 - 40000 - 10 -
  • -
    -
    - -
    diff --git a/Defs/ThingDefs_Buildings/Buildings_Production.xml b/Defs/ThingDefs_Buildings/Buildings_Production.xml index 0a25590576..45e70e2fb8 100644 --- a/Defs/ThingDefs_Buildings/Buildings_Production.xml +++ b/Defs/ThingDefs_Buildings/Buildings_Production.xml @@ -6,6 +6,7 @@ true 0.20 + false true true @@ -81,75 +82,4 @@ - - TableMachining - - Building_WorkTable - A work station for assembling and disassembling machinery such as guns or mechanoid corpses. - - Things/Building/Production/TableMachining - Graphic_Multi - (3.5,1.5) - - Damage/Corner - Damage/Corner - Damage/Corner - Damage/Corner - - - - 150 - 5 - - Building - 0.5 - True - - 3000 - 180 - 1.0 - -2 - - (3,1) - Production - PassThroughOnly - 70 - True - (0,0,-1) - Item - -
  • ButcherCorpseMechanoid
  • -
    - -
  • ITab_Bills
  • -
    - -
  • - CompPowerTrader - true - 350 -
  • -
  • -
  • - 5 - (73,123,138,0) -
  • -
  • - -
  • ToolCabinet
  • - - -
  • - - - BillsTab - - ConstructMetal -
  • Machining
  • - Misc7 - -
  • PlaceWorker_ShowFacilitiesConnections
  • -
    -
    - diff --git a/Defs/ThingDefs_Buildings/Buildings_Security.xml b/Defs/ThingDefs_Buildings/Buildings_Security.xml deleted file mode 100644 index 31eb40af50..0000000000 --- a/Defs/ThingDefs_Buildings/Buildings_Security.xml +++ /dev/null @@ -1,521 +0,0 @@ - - - - - Sandbags - - Building - Building - - Things/Building/Linked/Sandbags_Atlas - Graphic_Single - Basic - -
  • Sandbags
  • -
    -
    - - Things/Building/Linked/Sandbags_Blueprint_Atlas - - Things/Building/Linked/Sandbags_MenuIcon - Building - 40 - true - PassThroughOnly - true - 0.65 - - 450 - -10 - 180 - 0 - - - false - true - - Cover from gunfire. - 1 - - 6 - - SandbagRubble - false - true - true - Light - Security - 0.20 - ConstructDirt - ConstructDirt - Misc1 -
    - - - - Item - ThingWithComps - - Primary - - Things/Item/Equipment/WeaponRanged/ChargeRifle - Graphic_Single - - Never - Industrial - True - True - Never - ArtilleryShellLoaded - -
  • - CompEquippable -
  • -
  • - -
  • (29,85)
  • -
  • (72,300)
  • -
  • (92,660)
  • - - -
  • - 1 - 150 - true - AmmoSet_81mmMortarShell -
  • -
    -
    - - - - - TurretGun - - Combat_Realism.Building_TurretGunCE - - Things/Building/Security/TurretImprovised - Graphic_Single - (3,3) - - (0.2,0.2,0.6,0.6) - - - MinifiedFurniture - Building - false - false - - 100 - 1.0 - 2500 - 100 - -60 - - Normal - -
  • -
  • - 3.9 - Bomb - 0.5 -
  • -
  • -
  • - CompPowerTrader - 350 -
  • -
  • -
  • - - An improvised turret that automatically fires at nearby enemies. Explodes when damaged. Its hacked-together AI brain isn't very smart, and can't be directly controlled, so beware of friendly fire. - PassThroughOnly - 50 - 0.85 - true - true - -
  • Steeled
  • - - 75 - - 100 - 10 - - - SmithingSpeed - Crafting - Smith - Recipe_Smith - -
  • TableMachining
  • -
    - UnfinishedTurretGun - CE_TurretAI - -
  • - Crafting - 10 -
  • -
    -
    - Light - Security - 27 - - true - Gun_TurretImprovised - 1.1 - Things/Building/Security/TurretImprovised_Top - - Misc2 - -
  • CE_Turret
  • -
    - -
  • GunTurrets
  • -
    -
    - - - - - - A mortar that launches explosive shells. Must be manned. - Combat_Realism.Building_TurretGunCE - - Things/Building/Security/TurretMortarBase - Graphic_Single - (4,4) - - (0.38,0.2,0.56375,0.8) - Damage/Corner - - - MinifiedFurniture - Building - True - (0,0,-1) - false - - 180 - 1.0 - 2700 - -60 - 200 - - Normal - -
  • -
  • - Violent -
  • -
    - (2,2) - PassThroughOnly - 50 - 0.4 - true - -
  • Metallic
  • -
    - 100 - - 150 - - Light - - Artillery_MortarBomb - MortarShell - 4.5 - 20.0 - Things/Building/Security/TurretMortarBomb_Top - - -
  • PlaceWorker_NotUnderRoof
  • -
    -
  • Mortars
  • -
    - - - - - Turret_MortarBomb - -
  • - 4.9 - Bomb -
  • -
    - - -
  • Artillery
  • -
  • Artillery_BaseDestroyer
  • -
    -
    - Security - Misc3 -
    - - - Artillery_MortarBomb - - Lobs mortar shells on a high arc. Very inaccurate but long-ranged and capable of indirect fire. - Spacer - - 0.5 - - -
  • Artillery
  • -
  • Artillery_BaseDestroyer
  • -
    - -
  • - Combat_Realism.Verb_ShootMortarCE - false - true - Bullet_81mmMortarShell_HE - 5.5 - 32 - 700 - 1 - Mortar_LaunchA - 16 - 0.2 - - true - -
  • -
    -
    - - - - - Turret_MortarIncendiary - - Artillery_MortarBomb - -
  • Artillery
  • -
  • Artillery_BaseDestroyer
  • -
    -
    - true -
    - - - Artillery_MortarIncendiary - - Incendiary mortar launcher. Lobs fire-starting bombs over walls. Very inaccurate but long-ranged. - Spacer - - 0.5 - - -
  • Artillery
  • -
  • Artillery_BaseDestroyer
  • -
    - -
  • - Combat_Realism.Verb_ShootMortarCE - false - true - Bullet_81mmMortarShell_Incendiary - 10 - true - 5.5 - 32 - 700 - 1 - Mortar_LaunchA - 16 - 0.2 - - true - -
  • -
    -
    - - - - - Turret_MortarEMP - - Artillery_MortarBomb - -
  • Artillery
  • -
    -
    - true -
    - - - Artillery_MortarEMP - - Mortar launcher. Lobs EMP bombs over walls. Very inaccurate but long-ranged. - Spacer - - 0.5 - - -
  • Artillery
  • -
    - -
  • - Combat_Realism.Verb_ShootMortarCE - false - true - Bullet_81mmMortarShell_EMP - 10 - 5.5 - 32 - 700 - 1 - Mortar_LaunchA - 16 - - true - -
  • -
    -
    - - - - - TrapDeadfall - - Building_TrapRearmable - - Things/Building/Security/DeadfallArmed - Graphic_Single - - (0,0,1,0.15) - - - Building - RealtimeOnly - false - Normal - false - - 40 - 2000 - -4 - 60 - 0.8 - - A suspended spiked weight held up by a delicate trigger. When the victim disturbs the trigger, the weight is released and falls on his head or torso. - -
  • Metallic
  • -
  • Woody
  • -
  • Stony
  • -
    - 70 - Security - Misc6 - - true - Sharp - - Things/Building/Security/DeadfallUnarmed - Graphic_Single - Cutout - - -
    - - - TrapIEDBomb - - Building_TrapExplosive - - Things/Building/Security/IEDBomb - Graphic_Single - - (0.1,0,0.8,0.3) - - - Building - RealtimeOnly - false - Normal - false - - 40 - 2000 - -4 - 0.8 - - An artillery shell connected to a homemade trigger. When someone disturbs the trigger, the shell explodes. The improvised trigger has a random delay that might allow a nimble enemy to escape. - - 1 - 1 - - Security - Misc7 - - true - - -
  • - 2.9 - Bomb - 0.2 - - 15 - 70 - -
  • -
    -
  • IEDBomb
  • -
    - - - TrapIEDIncendiary - - Building_TrapExplosive - - Things/Building/Security/IEDIncendiary - Graphic_Single - - (0.1,0,0.8,0.3) - - - Building - RealtimeOnly - false - Normal - false - - 40 - 2000 - -4 - 0.8 - - Explosives mixed into an incendiary paste with a chemical trigger for dispersal. Its chemical trigger is simple and reliable. - - 1 - 1 - - Security - Misc8 - - true - - -
  • - 2.9 - Flame - 0.2 - - 10 - 50 - -
  • -
    -
  • IEDIncendiary
  • -
    - -
    diff --git a/Defs/ThingDefs_Buildings/Buildings_Structure.xml b/Defs/ThingDefs_Buildings/Buildings_Structure.xml deleted file mode 100644 index 01654408bc..0000000000 --- a/Defs/ThingDefs_Buildings/Buildings_Structure.xml +++ /dev/null @@ -1,171 +0,0 @@ - - - - - - - Building_Door - Blueprint_Door - Building - - Things/Building/Door/Door_Blueprint - - DoorMoveable - 1 - true - -
  • Metallic
  • -
  • Woody
  • -
  • Stony
  • -
    - - 250 - 1.0 - - false - true - Normal - false - BulletImpactMetal - Light - Structure - true - 1.0 - true - RealtimeOnly - - DoorOpenPowered - DoorClosePowered - DoorOpenManual - DoorCloseManual - true - true - - -
  • - - - - - Door - - Divides rooms. Must be manually opened and closed, which slows people down. - - 850 - - - Things/Building/Door/DoorSimple_Mover - Graphic_Single - - - false - - - Things/Building/Door/DoorSimple_MenuIcon - 25 - Misc1 - - - - Autodoor - - Divides rooms. Powered operation allows people to move through the door without slowing down. - - 1100 - - - Things/Building/Door/Autodoor_Mover - Graphic_Single - - - false - - - Things/Building/Door/Autodoor_MenuIcon - - 40 - 2 - - 25 - -
  • - CompPowerTrader - 50 -
  • -
  • - - Misc2 - -
  • Autodoors
  • - -
    - - - - - Wall - - Building - Building - An impassable wall. Capable of holding up a roof. - - Things/Building/Linked/Wall - Graphic_Appearances - CornerFiller - -
  • Wall
  • -
  • Rock
  • -
    - - Damage/Corner - Damage/Corner - Damage/Corner - Damage/Corner - Damage/Edge - Damage/Edge - Damage/Edge - Damage/Edge - -
    - - Things/Building/Linked/Wall_Blueprint_Atlas - - Things/Building/Linked/WallSmooth_MenuIcon - - 350 - 150 - 1.0 - - 5 - false - Building - Impassable - true - true - 1 - true - 1 - Never - false - true - true - Heavy - true - Structure - 1.0 - true - -
  • Metallic
  • -
  • Woody
  • -
  • Stony
  • -
    - - true - true - - Misc3 -
    - -
    diff --git a/Defs/ThingDefs_Buildings/Buildings_Turrets.xml b/Defs/ThingDefs_Buildings/Buildings_Turrets.xml index 70334b238d..3c6edd1c94 100644 --- a/Defs/ThingDefs_Buildings/Buildings_Turrets.xml +++ b/Defs/ThingDefs_Buildings/Buildings_Turrets.xml @@ -2,7 +2,7 @@ - Combat_Realism.Building_TurretGunCE + CombatExtended.Building_TurretGunCE Graphic_Single @@ -20,7 +20,6 @@ -60 -
  • Normal @@ -39,6 +38,14 @@ + + Security + +
  • +
  • + + + True (0,0,-1) @@ -59,17 +66,30 @@ + + + SmithingSpeed + Crafting + Smith + Recipe_Smith + +
  • TableMachining
  • + + UnfinishedTurretGun + +
    + - + Turret_Blaster Things/Building/Turrets/MachineGunBase + 48000 140 - 3335 20 25 @@ -79,35 +99,46 @@ CompPowerTrader 950 -
  • -
  • Automatic turret equipped with a charge blaster. + + 65 + 30 + 12 + Gun_BlasterTurret Things/Building/Turrets/BlasterTurret_Top + +
  • CE_ChargeTurret
  • + 40 MinifiedTurret_Blaster
    - + Turret_Heavy Things/Building/Turrets/MachineGunBase + 80000 2150 - 250 + 550 0.05 80 100 Spacer Plated automatic turret with large caliber machine gun. Very resistant to damage. + + 275 + 8 + Gun_HeavyTurret Things/Building/Turrets/HeavyTurret_Top @@ -118,15 +149,16 @@ CompPowerTrader 700 -
  • -
  • MinifiedTurret_Heavy + +
  • CE_ChargeTurret
  • +
    - + Turret_M240B @@ -134,13 +166,13 @@ 1.0 - 25000 + 31500 16.5 20 M240B medium machine gun mounted on a tripod. - 200 + 125 4 @@ -152,7 +184,7 @@ - + Turret_KPV @@ -160,14 +192,14 @@ 150 - 30000 + 50500 88 100 KPV heavy machine gun mounted on a tripod. - 400 - 6 + 275 + 4 Gun_KPV @@ -179,64 +211,65 @@ MinifiedTurret_KPV - + - - Turret_Flak - + + Turret_AGSThirty + - Things/Building/Turrets/FlakTurret_Base + Things/Building/Turrets/AGS30Base - 250 - 50000 - 1000 - 1000 + 33500 + 16 + 20 - Old school anti-aircraft cannon. Ineffective against modern aviation but still popular on rimworlds for use against entrenched enemies and vehicles. + Lightweight automatic grenade launcher. - 1000 - 15 + 115 + 5 - 16 + 8 - Gun_FlakTurret - Things/Building/Turrets/FlakTurret_Top + Gun_AGSThirty + Things/Building/Turrets/TurretGun_AGS30 - (2,2) CE_TurretHeavyWeapons - MinifiedTurret_Flak + MinifiedTurret_AGSThirty - + - Turret_AGSThirty - + Turret_Flak + - Things/Building/Turrets/AGS30Base + Things/Building/Turrets/FlakTurret_Base - 25000 - 16 - 20 + 500 + 79500 + 1000 + 1000 - Lightweight automatic grenade launcher. + Old school anti-aircraft cannon. Ineffective against modern aviation but still popular on rimworlds for use against entrenched enemies and vehicles. - 400 - 6 + 495 + 5 - 8 + 16 - Gun_AGSThirty - Things/Building/Turrets/TurretGun_AGS30 + Gun_FlakTurret + Things/Building/Turrets/FlakTurret_Top - - CE_TurretHeavyWeapons - - MinifiedTurret_AGSThirty + (2,2) + MinifiedTurret_Flak + +
  • CE_TurretHeavyWeapons
  • +
    + Security
    diff --git a/Defs/ThingDefs_Items/Items_Food.xml b/Defs/ThingDefs_Items/Items_Food.xml deleted file mode 100644 index f8ebd23aa5..0000000000 --- a/Defs/ThingDefs_Items/Items_Food.xml +++ /dev/null @@ -1,218 +0,0 @@ - - - - - ThingWithComps - Item - true - true - - 50 - 1.0 - -6 - 0.5 - 1 - - Item - 10 - Rare - true - -
  • FoodMeals
  • -
    - true - -
  • -
  • -
  • - - 15 - Last - true - - Meal - 1 - 16 - - - - - -
  • - 4 - true -
  • -
    -
    - - - MealSurvivalPack - - A high-quality packaged meal, manufactured for use in survival situations. - - Things/Item/Meal/SurvivalPack - Graphic_Single - - - 0.5 - 30 - 0.4 - - - MealFine - AteFineMeal - 0.90 - EatVegetarian - Meal_Eat - - - - - MealNutrientPaste - - A synthetic mixture of protein, carbohydrates, and vitamins, amino acids and minerals. Everything the body needs, and absolutely disgusting. - - Things/Item/Meal/NutrientPaste - Graphic_Single - - - 20 - 15 - - - MealAwful - AteAwfulMeal - 0.90 - EatVegetarian - Meal_Eat - - - - - MealSimple - - A simple meal quickly cooked from a few ingredients. - - Things/Item/Meal/Simple - Graphic_Single - - - 20 - 25 - 300 - - - MealSimple - 0.85 - EatVegetarian - Meal_Eat - - - - - MealFine - - A complex dish assembled with care from a wide selection of ingredients. - - Things/Item/Meal/Fine - Graphic_Single - - - 20 - 28 - 450 - - - MealFine - AteFineMeal - 0.90 - EatVegetarian - Meal_Eat - - - - - MealLavish - - A masterpiece of the culinary arts, this meal nourishes the body, mind, and soul. - - Things/Item/Meal/Lavish - Graphic_Single - - - 20 - 40 - 800 - - - MealLavish - AteLavishMeal - 1.00 - EatVegetarian - Meal_Eat - - - - - Kibble - - -
  • Foods
  • -
    - Kibble animal feed made from mixed meat and plant sources. Humans can eat it, but they really, really don't like it. - - Things/Item/Resource/Kibble - - - 1.3 - 0.015 - 0.2 - - - Kibble - RawBad - AteKibble - -30 - 0.05 - EatVegetarian - RawVegetable_Eat - -
    - - - Pemmican - - ThingWithComps - -
  • Foods
  • -
    - A preserved mashed mixture of fat and plant food. Tastes bland, but not offensive. It lasts a very long time without refrigeration. - - Things/Item/Resource/Pemmican - Graphic_Single - - - 3.0 - 0.018 - 700 - 0.036 - - - Meal - MealSimple - 0.05 - EatVegetarian - Meal_Eat - - -
  • - 80 - true -
  • -
  • -
  • - - 150 - - - diff --git a/Defs/ThingDefs_Items/Items_Resource_Ammo.xml b/Defs/ThingDefs_Items/Items_Resource_Ammo.xml new file mode 100644 index 0000000000..d0f6755041 --- /dev/null +++ b/Defs/ThingDefs_Items/Items_Resource_Ammo.xml @@ -0,0 +1,52 @@ + + + + + + + Prometheum + + Military-grade incendiary agent, ignites on contact with oxygen. The raw resource is used to craft incendiary ammo of all kinds. + + Things/Resources/Prometheum + Graphic_StackCount + + Metal_Drop + Standard_Drop + 25 + + 70 + 6 + 1.0 + 1.5 + 5 + + +
  • ResourcesRaw
  • + +
    + + + FSX + + High-explosive chemical extracted from Boomalope sacks, it is used in a variety of industrial and military applications. + + Things/Resources/FSX + Graphic_StackCount + + Metal_Drop + Standard_Drop + 25 + + 70 + 10 + 1.0 + 2 + 5 + + +
  • ResourcesRaw
  • +
    +
    + + diff --git a/Defs/ThingDefs_Items/Items_Resource_Manufactured.xml b/Defs/ThingDefs_Items/Items_Resource_Manufactured.xml deleted file mode 100644 index f64f4b86fd..0000000000 --- a/Defs/ThingDefs_Items/Items_Resource_Manufactured.xml +++ /dev/null @@ -1,229 +0,0 @@ - - - - - - - HerbalMedicine - - A pack of herbal concoctions typically extracted from the healroot plant. Less potent than industrial pharmaceuticals, but much better than nothing. - Medicine - - Things/Item/Resource/MedicineHerbal - Graphic_Single - - Standard_Drop - Standard_Drop - - 100 - 12 - 0.35 - 1.0 - 1.0 - 0.40 - 10 - - -
  • Medicine
  • -
    - Rare - -
  • - 150 - true -
  • -
    -
    - - - Medicine - - Medical staff use these supplies to heal the wounded. - Medicine - - Things/Item/Resource/Medicine - Graphic_Single - - Standard_Drop - Standard_Drop - - 100 - 18 - 0.5 - 1.0 - 1.0 - 0.70 - 2 - 700 - - -
  • Medicine
  • -
    - - 1 - 1 - 3 - - - DrugProductionSpeed - Medicine - -
  • DrugLab
  • -
    - MedicineProduction - -
  • - Medicine - 6 -
  • -
  • - Crafting - 3 -
  • -
    -
    -
    - - - GlitterworldMedicine - - Advanced medical supplies from a high-tech glitterworld. - Medicine - - Things/Item/Resource/MedicineGlitterworld - Graphic_Single - - Standard_Drop - Standard_Drop - - 100 - 0.5 - 1.0 - 1.0 - 1.6 - 2.0 - - -
  • Medicine
  • -
    - -
  • Exotic
  • -
    -
    - - - - - - - - - Prometheum - - Military-grade incendiary agent, ignites on contact with oxygen. The raw resource is used to craft incendiary ammo of all kinds. - - Things/Resources/Prometheum - Graphic_StackCount - - Metal_Drop - Standard_Drop - 25 - - 70 - 6 - 1.0 - 1.5 - 5 - - -
  • Manufactured
  • -
    -
    - - - FSX - - High-explosive chemical extracted from Boomalope sacks, it is used in a variety of industrial and military applications. - - Things/Resources/FSX - Graphic_StackCount - - Metal_Drop - Standard_Drop - 25 - - 70 - 10 - 1.0 - 2 - 5 - - -
  • Manufactured
  • -
    -
    - - - - - Component - - Miscellaneous gears, capacitors, circuit boards, tubes, wheels, sensors, wires, chips, processors, and other electronic and industrial parts. Necessary for assembling complex machines or electronics. - - Things/Item/Resource/Component - Graphic_Single - - Metal_Drop - Standard_Drop - 50 - - 70 - 21 - 0.6 - 1.0 - 1.0 - - true - -
  • Manufactured
  • -
    -
    - -
    diff --git a/Defs/ThingDefs_Items/Items_Resource_RawPlant.xml b/Defs/ThingDefs_Items/Items_Resource_RawPlant.xml deleted file mode 100644 index ffc1a081f3..0000000000 --- a/Defs/ThingDefs_Items/Items_Resource_RawPlant.xml +++ /dev/null @@ -1,244 +0,0 @@ - - - - - - Graphic_Single - - true - - 100 - 1.0 - 10 - 0.03 - 0.5 - - Rare - - - - - RawBad - AteRawFood - 0.05 - EatVegetarian - RawVegetable_Eat - - -
  • PlantFoodRaw
  • -
    - -
  • - - - - - RawPotatoes - - Raw potatoes. - - Things/Item/Resource/PlantFoodRaw/Potatoes - - - 2 - - - VegetableOrFruit - - -
  • - 30 - true -
  • -
    -
    - - - RawRice - - Raw rice. - Grain_Drop - Grain_Drop - - Things/Item/Resource/PlantFoodRaw/Rice - - - 2 - - - Seed - - -
  • - 40 - true -
  • -
    -
    - - - RawAgave - - Raw agave fruit. - - Things/Item/Resource/PlantFoodRaw/AgaveFruit - - - 2 - - - VegetableOrFruit - - -
  • - 25 - true -
  • -
    -
    - - - RawCorn - - Raw corn. - Grain_Drop - Grain_Drop - - Things/Item/Resource/PlantFoodRaw/Corn - - - 2 - - - VegetableOrFruit - - -
  • - 60 - true -
  • -
    -
    - - - RawBerries - - Assorted berries. Nice to eat, even when raw. - - Things/Item/Resource/PlantFoodRaw/Berries - - - 2.5 - 0.027 - - -
  • - 14 - true -
  • -
    - - RawTasty - - VegetableOrFruit - -
    - - - - - - Plant - RawBad - 0.05 - - - - - Hay - - Nutrient-rich grasses and shoots, harvested and compacted for storage. Hay is good animal feed, but inedible for humans. - 200 - - Things/Item/Resource/PlantFoodRaw/Hay - Graphic_StackCount - - - 1.2 - 0.014 - - -
  • - 60 - true -
  • -
    - -
  • Foods
  • -
    -
    - - - RawHops - - Raw hops. A flavoring and preserving agent that is necessary for making beer. - - Things/Item/Resource/PlantFoodRaw/Hops - - - 2 - - -
  • - 30 - true -
  • -
    - -
  • PlantMatter
  • -
    -
    - - - PsychoidLeaves - - Raw cut leaves of a psychoid plant. - - Things/Item/Resource/PlantFoodRaw/PsychoidLeaves - - - 2.4 - - -
  • - 30 - true -
  • -
    - -
  • PlantMatter
  • -
    -
    - - - SmokeleafLeaves - - Raw cut leaves of a smokeleaf plant. Can be rolled into smokeable joint at a crafting spot. - - Things/Item/Resource/PlantFoodRaw/SmokeleafLeaves - - - 2.4 - - -
  • - 30 - true -
  • -
    - -
  • PlantMatter
  • -
    -
    - -
    diff --git a/Defs/ThingDefs_Items/Items_Resource_Stuff.xml b/Defs/ThingDefs_Items/Items_Resource_Stuff.xml deleted file mode 100644 index ebd2b6724c..0000000000 --- a/Defs/ThingDefs_Items/Items_Resource_Stuff.xml +++ /dev/null @@ -1,500 +0,0 @@ - - - - - - - Silver - - This metal is mostly used as a commodity currency. It can also be used for making attractive decorations. - - Things/Item/Resource/Silver - Graphic_Single - - First - Silver_Drop - Silver_Drop - false - true - - 1 - 0.01 - 0.01 - 0.5 - 1.1 - - -
  • ResourcesRaw
  • -
    - 500 - true - 1 - - -
  • Metallic
  • -
    - (180,173,150) - 0.05 - ConstructMetal - BulletImpactMetal - MeleeHit_Metal_Sharp - MeleeHit_Metal_Blunt - - 6 - - - 0.7 - 0.2 - 3 - 1 - - true -
    -
    - - - Gold - - The most seductive metal of them all. Millions have died in attempting to feed the endless human thirst for gold. This soft metal is little use on its own, but is strikingly beautiful and very rare. - - Things/Item/Resource/Gold - Graphic_Single - - Silver_Drop - Silver_Drop - false - - 10 - 0.05 - 0.01 - 0.3 - 1.15 - - -
  • ResourcesRaw
  • -
    - 500 - true - 0.5 - - golden - -
  • Metallic
  • -
    - 0.02 - (255,235,122) - ConstructMetal - BulletImpactMetal - MeleeHit_Metal_Sharp - MeleeHit_Metal_Blunt - - 18 - - - 0.6 - 0.2 - 6 - 0.9 - 0.9 - 1.1 - - true -
    -
    - - - Steel - - An iron-carbon metal alloy used for building structures, tools, and weapons. - - Things/Item/Resource/Metal - Graphic_Random - (255,255,255) - - Metal_Drop - Metal_Drop - - 2.0 - 0.5 - 0.3 - 1 - 1 - - false - ChunkSlagSteel - -
  • ResourcesRaw
  • -
    - 4 - - -
  • Metallic_Weapon
  • -
  • Metallic
  • -
  • Steeled
  • -
    - 1.00 - ConstructMetal - (102,102,105) - BulletImpactMetal - MeleeHit_Metal_Sharp - MeleeHit_Metal_Blunt - - 1 - 1 - 0.2 - 1 - - true -
    -
    - - - Plasteel - - Advanced spacer tech structural material. Plasteel is extremely strong due to its unique molecular structure. - - Things/Item/Resource/Plasteel - Graphic_Single - - Metal_Drop - Metal_Drop - false - - 14 - 0.5 - 0.3 - 1.0 - - -
  • ResourcesRaw
  • -
    - 1 - - -
  • Metallic_Weapon
  • -
  • Metallic
  • -
  • Steeled
  • -
    - 0.25 - ConstructMetal - (160,178,181) - BulletImpactMetal - MeleeHit_Metal_Sharp - MeleeHit_Metal_Blunt - - 0.0 - 0.18 - 0 - 0.0 - - - 2.8 - 1.2 - 0.1 - 2.2 - 2.2 - 0.8 - 0.8 - 0.8 - 1.0 - 1.15 - 1.3 - - true -
    -
    - - - WoodLog - - Wood from trees or other fibrous plants. Useful for building structures, weapons, and even simple prosthetics. A raw stick of wood can be used as a weapon in a pinch. - - Things/Item/Resource/WoodLog - Graphic_StackCount - - -20 - Wood_Drop - Wood_Drop - - 1.4 - 150 - 0.4 - 0.3 - 1.0 - 2 - 8 - 2.2 - 0.3 - - - wooden - -
  • Woody
  • -
    - 1.00 - (133,97,67) - ConstructWood - Planks - BulletImpactWood - MeleeHit_Wood - MeleeHit_Wood - - 2 - - - 0.4 - 1.25 - 1 - 0.7 - 0.7 - 1.2 - 0.9 - 0.1 - 0.3 - -
    - true - -
  • ResourcesRaw
  • -
    - -
  • Poor
  • -
    - -
  • - Verb_MeleeAttack - true - Blunt -
  • -
    -
    - - - Uranium - - An extremely hard, dense metal. While it is best known for its use powering nuclear reactors, its physical properties also make it excellent in some roles as a tool, weapon, or armor. - - Things/Item/Resource/Uranium - Graphic_Single - - false - Metal_Drop - Metal_Drop - - 6 - 0.1 - 0.3 - 1.4 - - -
  • ResourcesRaw
  • -
    - 500 - true - 0.5 - - -
  • Metallic_Weapon
  • -
  • Metallic
  • -
    - 0.05 - (100,100,100) - ConstructMetal - BulletImpactMetal - MeleeHit_Metal_Sharp - MeleeHit_Metal_Blunt - - 2.5 - 1.9 - 1.9 - 0.4 - 0.0 - 0.9 - 1.35 - 1.4 - 2.5 - - true -
    -
    - - - Jade - - A hard, green stone. Because of its beauty and rarity, jade is often used for ornaments and decorations. It's hardness and density also makes it a good material for blunt weapons. - - Things/Item/Resource/Jade - Graphic_Single - - false - ChunkRock_Drop - ChunkRock_Drop - - 5 - 0.06 - 0.3 - 0.8 - 1.5 - - -
  • ResourcesRaw
  • -
    - 500 - true - 0.5 - - -
  • Stony
  • -
    - 0.05 - (85,118,69) - ConstructMetal - BulletImpactMetal - MeleeHit_Stone - MeleeHit_Stone - - 9 - - - 0.5 - 1.4 - 5.0 - 3 - 0.2 - 1.3 - 1.3 - - false -
    -
    - - - - - DevilstrandCloth - - Fabric spun from microfibers extracted from silk-producing Devilstrand mushrooms. Very tough, but insulates no better than cloth. - - Things/Item/Resource/Cloth - Graphic_Single - (180,60,60) - - - 100 - 10 - 0.032 - 0.3 - 1.0 - 3 - - - -
  • Fabric
  • -
    - 0.35 - (180,60,60) - - 0.05 - 0.05 - 0 - 0.05 - 0.5 - 0.5 - 0.5 - - - 1.3 - 1.3 - 1.8 - 1 - 3 - 1.5 - 1.5 - 1.5 - -
    - -
  • Textiles
  • -
    - -
  • - CompColorable -
  • -
    -
    - - - Hyperweave - - High-tech nano-fibers woven into sheets. It is somewhat heavy, but is incredibly difficult to break. The secrets of its production are known only to the most advanced glitterworld cultures. - - Things/Item/Resource/Hyperweave - Graphic_Single - - - 16 - 0.038 - 0.3 - 1.0 - 1.0 - - - -
  • Fabric
  • -
    - 0.18 - (0,106,126) - - 0.03 - 0.03 - 0.03 - 0.75 - 0.75 - 0.5 - - - 1.8 - 1.6 - 4.0 - 2.0 - 0 - 1.1 - 1.1 - 1.8 - 1.8 - 1.8 - -
    - -
  • Textiles
  • -
    -
    - - - MegaslothWool - - While somewhat coarse, megasloth wool's long fibers make it very strong. It is very warm. - - (189,161,116) - - - 0.3 - 0.3 - - - (189,161,116) - 0.15 - - 0.08 - 0.02 - - - 1.3 - 2.2 - 3.1 - 3.1 - - - - -
    diff --git a/Defs/ThingDefs_Items/Items_Unfinished.xml b/Defs/ThingDefs_Items/Items_Unfinished.xml index ace8342f29..6a8122975a 100644 --- a/Defs/ThingDefs_Items/Items_Unfinished.xml +++ b/Defs/ThingDefs_Items/Items_Unfinished.xml @@ -20,7 +20,8 @@ 50 2.0 - -6 + -4 + 1
  • @@ -39,80 +40,34 @@ - UnfinishedSculpture - + UnfinishedAmmo + - Things/Item/Unfinished/UnfinishedSculpture - Graphic_Single - - -
  • Metallic
  • -
  • Woody
  • -
  • Stony
  • - - - - - UnfinishedGun - - - Things/Item/Unfinished/UnfinishedGun + Things/Item/Unfinished/UnfinishedComponent Graphic_Single - UnfinishedWeapon - - - Things/Item/Unfinished/UnfinishedWeapon - Graphic_Single - - -
  • Metallic
  • -
  • Woody
  • -
  • Stony
  • -
    -
    - - - UnfinishedTechArmor - + UnfinishedArrows + - Things/Item/Unfinished/UnfinishedTechArmor + Things/Item/Unfinished/UnfinishedGun Graphic_Single - - UnfinishedApparel - + UnfinishedTurretGun + - Things/Item/Unfinished/UnfinishedApparel + Things/Item/Unfinished/UnfinishedGun Graphic_Single -
  • Fabric
  • -
  • Leathery
  • Metallic
  • - -
  • - CompColorable -
  • -
    -
    - - - UnfinishedComponent - - - Things/Item/Unfinished/UnfinishedComponent - Graphic_Single - - @@ -134,38 +89,6 @@ 15 - - MinifiedSculpture - - -
  • Art
  • -
    - -
  • ITab_Art
  • -
    -
    - - - MinifiedFurniture - - -
  • Furniture
  • -
    - -
  • ITab_Art
  • -
    -
    - - - MinifiedTurretGun @@ -178,16 +101,4 @@ - - UnfinishedTurretGun - - - Things/Item/Unfinished/UnfinishedGun - Graphic_Single - - -
  • Metallic
  • -
    -
    - diff --git a/Defs/ThingDefs_LoadoutGen/LoadoutGen_Mechanoid.xml b/Defs/ThingDefs_LoadoutGen/LoadoutGen_Mechanoid.xml index bdb4fbce56..a998516e74 100644 --- a/Defs/ThingDefs_LoadoutGen/LoadoutGen_Mechanoid.xml +++ b/Defs/ThingDefs_LoadoutGen/LoadoutGen_Mechanoid.xml @@ -1,8 +1,8 @@  - - Combat_Realism.LoadoutGeneratorThing + + CombatExtended.LoadoutGeneratorThing Loadout creation dummy. If you're seeing this, it means something probably went horribly wrong. Item false @@ -25,7 +25,7 @@ LoadoutGen_MechanoidAmmo - + 0 10000 10000 diff --git a/Defs/ThingDefs_LoadoutGen/LoadoutGen_Mercenary.xml b/Defs/ThingDefs_LoadoutGen/LoadoutGen_Mercenary.xml index 9418bc7a46..fd34ce0b29 100644 --- a/Defs/ThingDefs_LoadoutGen/LoadoutGen_Mercenary.xml +++ b/Defs/ThingDefs_LoadoutGen/LoadoutGen_Mercenary.xml @@ -4,10 +4,10 @@ LoadoutGen_MercAmmoPrimary - + 0 60 - 120 + 90 0 @@ -15,10 +15,10 @@ LoadoutGen_MercAmmoPrimaryDouble - + 0 - 120 - 240 + 100 + 200 0 @@ -26,10 +26,10 @@ LoadoutGen_MercHeavyAmmoPrimary - + 0 6 - 24 + 18 40 @@ -37,7 +37,7 @@ LoadoutGen_MercSidearmMelee - + 0.5 CE_Sidearm_Melee @@ -53,7 +53,7 @@ LoadoutGen_MercSidearm - + 0.5 CE_Sidearm @@ -69,7 +69,7 @@ LoadoutGen_MercSidearmSMG - + 0.0 CE_SMG @@ -85,10 +85,10 @@ LoadoutGen_MercSidearmAmmo - + 0 - 15 - 30 + 7 + 15 20 @@ -96,13 +96,25 @@ LoadoutGen_MercSidearmSMGAmmo - + 0 50 100 20 + + + LoadoutGen_MercSapperGrenades + + + 0 + Weapon_GrenadeFrag + 15 + 30 + + 10 + \ No newline at end of file diff --git a/Defs/ThingDefs_LoadoutGen/LoadoutGen_Outlander.xml b/Defs/ThingDefs_LoadoutGen/LoadoutGen_Outlander.xml index 0cc1182526..ecafbac838 100644 --- a/Defs/ThingDefs_LoadoutGen/LoadoutGen_Outlander.xml +++ b/Defs/ThingDefs_LoadoutGen/LoadoutGen_Outlander.xml @@ -4,7 +4,7 @@ LoadoutGen_OutlanderAmmoPrimary - + 0 20 40 @@ -15,7 +15,7 @@ LoadoutGen_OutlanderSidearmMelee - + 0.75 CE_Sidearm_Melee @@ -31,7 +31,7 @@ LoadoutGen_OutlanderSilver - + 0.75 Silver 30 diff --git a/Defs/ThingDefs_LoadoutGen/LoadoutGen_Pirate.xml b/Defs/ThingDefs_LoadoutGen/LoadoutGen_Pirate.xml index 5fb22ae0bf..7430d397af 100644 --- a/Defs/ThingDefs_LoadoutGen/LoadoutGen_Pirate.xml +++ b/Defs/ThingDefs_LoadoutGen/LoadoutGen_Pirate.xml @@ -4,10 +4,10 @@ LoadoutGen_PirateAmmoPrimary - + 0 - 30 - 60 + 15 + 30 0 diff --git a/Defs/ThingDefs_LoadoutGen/LoadoutGen_Tribal.xml b/Defs/ThingDefs_LoadoutGen/LoadoutGen_Tribal.xml index 2cb3eb15b3..48bb36bc95 100644 --- a/Defs/ThingDefs_LoadoutGen/LoadoutGen_Tribal.xml +++ b/Defs/ThingDefs_LoadoutGen/LoadoutGen_Tribal.xml @@ -4,7 +4,7 @@ LoadoutGen_TribalAmmo - + 0 30 100 @@ -15,7 +15,7 @@ LoadoutGen_TribalPila - + 0 Pila 1 @@ -27,7 +27,7 @@ LoadoutGen_TribalSidearm - + 0 CE_Sidearm_Tribal diff --git a/Defs/ThingDefs_Misc/Apparel_Carrying.xml b/Defs/ThingDefs_Misc/Apparel_Carrying.xml index da65bc2c20..3a87935d52 100644 --- a/Defs/ThingDefs_Misc/Apparel_Carrying.xml +++ b/Defs/ThingDefs_Misc/Apparel_Carrying.xml @@ -23,11 +23,6 @@ Never
  • - TailoringSpeed @@ -43,6 +38,7 @@
  • Loadout
  • + 0.67
    @@ -50,7 +46,7 @@ Apparel_TacVest - Combat_Realism.Apparel_TacVest + CombatExtended.Apparel_VisibleAccessory A loadbearing vest with a number of pouches to store magazines and other equipment.\n\nSpeeds up reloading but is quite bulky to wear. Things/Apparel/TacRigging/TacRigging @@ -62,7 +58,6 @@ 8000 2 10 - 2 8 @@ -73,37 +68,31 @@ 60 + false
  • Shoulders
  • -
  • Middle
  • +
  • Belt
  • - 1 -
  • Outlander
  • Military
  • Soldier
  • - + +
  • + 1 +
  • +
    Apparel_Backpack - Combat_Realism.Apparel_Backpack + CombatExtended.Apparel_VisibleAccessory A comfortable and spacious backpack for storing all kinds of items. Things/Apparel/Backpack/Milpack @@ -115,58 +104,6 @@ 8000 1 3 - 0 - - - 30 - - - 60 - - - -
  • Shoulders
  • -
    - -
  • Accessory
  • -
    - 1 - -
  • Outlander
  • -
  • Military
  • -
    - -
  • Soldier
  • -
    -
    - -
    - - - Apparel_BackpackRegular - - Combat_Realism.Apparel_Backpack - A backpack is a bag with straps that go over your shoulders, so that you can carry things on your back when you are walking or climbing. - - Things/Apparel/BackpackReg/BackpackReg - Graphic_Single - - - 100 - 125 - 8000 - 1 - 3 - 0 30 @@ -175,13 +112,13 @@ 60 + false -
  • Shoulders
  • +
  • Torso
  • -
  • Accessory
  • +
  • Belt
  • - 1
  • Outlander
  • Military
  • @@ -190,16 +127,11 @@
  • Soldier
  • - + +
  • + 2 +
  • +
    diff --git a/Defs/ThingDefs_Misc/Apparel_Hats.xml b/Defs/ThingDefs_Misc/Apparel_Hats.xml deleted file mode 100644 index d840958b7d..0000000000 --- a/Defs/ThingDefs_Misc/Apparel_Hats.xml +++ /dev/null @@ -1,201 +0,0 @@ - - - - - -
  • Headgear
  • -
    -
    - - - -
  • Headgear
  • -
    -
    - - - Apparel_PowerArmorHelmet - - A part of power armor set, mostly used by heavy infantry.\n\nIntegrated servo-motors assist the wearer's muscles in holding the weight of the helmet while the integrated combat HUD improves weapon accuracy. - Spacer - - UnfinishedTechArmor - PoweredArmor - - - Things/Pawn/Humanlike/Apparel/PowerArmorHelmet/PowerArmorHelmet - Graphic_Single - - - 22000 - 180 - 2000 - 0.35 - 0.6 - 0.5 - 0 - -3 - 3 - 4 - 5 - 0 - 1 - - - -0.15 - 1.15 - - - 7 - 50 - 20 - - - -
  • FullHead
  • -
    - Things/Pawn/Humanlike/Apparel/PowerArmorHelmet/PowerArmorHelmet - -
  • Overhead
  • -
    - 0.5 - -
  • Military
  • -
    - -
  • Soldier
  • -
    -
    - - -
  • - 10 - RGBA(0.33,0.33,0.33,1) -
  • -
  • - 10 - RGBA(0.65,0.65,0.65,1) -
  • -
  • - 6 - RGBA(0.3,0.3,0.3,1) - RGBA(0.5,0.5,0.5,1) -
  • -
  • - 10 - RGBA(0.9,0.9,0.9,1) -
  • -
    -
    -
    - - - Apparel_KevlarHelmet - - A lightweight combat helmet. - Industrial - - UnfinishedTechArmor - - - Things/Pawn/Humanlike/Apparel/KevlarHelmet/KevlarHelmet - Graphic_Single - - - 8000 - 130 - 260 - 0.15 - 0.45 - 1.4 - 4 - 1.4 - 0 - - - 20 - 15 - - - -
  • UpperHead
  • -
    - Things/Pawn/Humanlike/Apparel/KevlarHelmet/KevlarHelmet - -
  • Overhead
  • -
    - 2 - -
  • Military
  • -
    - -
  • Soldier
  • -
    - - -
  • - 10 - RGBA(0.33,0.33,0.33,1) -
  • -
  • - 10 - RGBA(0.65,0.65,0.65,1) -
  • -
  • - 6 - RGBA(0.3,0.3,0.3,1) - RGBA(0.5,0.5,0.5,1) -
  • -
  • - 10 - RGBA(0.9,0.9,0.9,1) -
  • -
    -
    -
    - - - Apparel_MilitaryHelmet - - Old-looking and heavy, but effective. Protects against low-velocity projectiles, shrapnel, falling debris, and cuts to the head. - Industrial - - Things/Pawn/Humanlike/Apparel/MilitaryHelmet/MilitaryHelmet - Graphic_Single - - 40 - -
  • Steeled
  • -
    - - 7000 - 100 - 0.1 - 0.30 - 2 - 4 - 2 - 0 - - - -0.10 - - - -
  • UpperHead
  • -
    - Things/Pawn/Humanlike/Apparel/MilitaryHelmet/MilitaryHelmet - -
  • Overhead
  • -
    - 2 - -
  • Military
  • -
    - -
  • Soldier
  • -
    -
    -
    - -
    diff --git a/Defs/ThingDefs_Misc/Apparel_Shield.xml b/Defs/ThingDefs_Misc/Apparel_Shield.xml index a2ef094de1..3fa7b89c66 100644 --- a/Defs/ThingDefs_Misc/Apparel_Shield.xml +++ b/Defs/ThingDefs_Misc/Apparel_Shield.xml @@ -1,62 +1,134 @@ - - - - - PersonalShield - Apparel_PersonalShield - - A single-person energy shield device. It will attempt to stop any rapidly-moving projectile or energy attack that comes from a distance. It does nothing against melee attacks or shots from point-blank range. It also prevents firing past touch range. - - Things/Pawn/Humanlike/Apparel/PersonalShield/PersonalShield - Graphic_Single - - Spacer - Normal - - 1200 - 0.15 - 1.5 - 5 - 10 - 5 - 4 - - -
  • Apparel
  • -
    - - -
  • Torso
  • -
    - -
  • Accessory
  • -
    - 1 - -
  • PersonalShield
  • -
    -
    - - -
  • - 10 - RGBA(0.33,0.33,0.33,1) -
  • -
  • - 10 - RGBA(0.65,0.65,0.65,1) -
  • -
  • - 6 - RGBA(0.3,0.3,0.3,1) - RGBA(0.5,0.5,0.5,1) -
  • -
  • - 10 - RGBA(0.9,0.9,0.9,1) -
  • -
    -
    -
    - -
    + + + + + CombatExtended.Apparel_Shield + +
  • Apparel
  • +
    + + false + +
  • LeftHand
  • +
    + +
  • Belt
  • +
    +
    + CE_Shields +
    + + + Apparel_MeleeShield + + Simple shield that can block simple projectiles and hits with melee weapons. + Industrial + + Things/Apparel/Shield/Shield + Graphic_Single + Cutout + + 60 + +
  • Steeled
  • +
  • Woody
  • + +
    + + + +
  • FueledSmithy
  • +
  • ElectricSmithy
  • +
    +
    + + 9500 + 125 + 0.15 + 0.2 + 7 + 8 + 8 + + + -0.05 + -0.05 + -0.05 + -0.05 + -0.25 + -0.05 + 1.0 + + + +
  • TribalShield
  • +
    +
    + +
  • + +
  • Hands
  • +
  • Arms
  • +
  • Shoulders
  • +
  • Torso
  • +
  • Neck
  • + + +
    +
    + + + Apparel_BallisticShield + + A heavy shield designed to protect against gunfire. It can cover most of the wearer's body but restricts use of two-handed weapons. Its heavy weight and bulk make it unwieldy in combat. + Industrial + + Things/Apparel/BallisticShield/BallisticShield + Graphic_Single + + 90 + +
  • Steeled
  • +
    + + 9500 + 125 + 0.30 + 0.75 + 13 + 15 + 15 + + + -0.2 + -0.2 + -0.2 + -0.2 + -0.5 + -0.2 + 1.0 + + + +
  • OutlanderShield
  • +
    +
    + +
  • + +
  • Hands
  • +
  • Arms
  • +
  • Shoulders
  • +
  • Torso
  • +
  • Neck
  • +
  • FullHead
  • + + +
  • Legs
  • +
    + true + +
    +
    + +
    diff --git a/Defs/ThingDefs_Misc/Apparel_Various.xml b/Defs/ThingDefs_Misc/Apparel_Various.xml index 78dfdaca97..a983c6cc19 100644 --- a/Defs/ThingDefs_Misc/Apparel_Various.xml +++ b/Defs/ThingDefs_Misc/Apparel_Various.xml @@ -7,6 +7,7 @@ True 10 True + Medieval 35 @@ -15,7 +16,8 @@ 100 1.0 2 - -6 + -4 + 0.70 Item True @@ -30,21 +32,7 @@ - - - - TailoringSpeed - Crafting - Tailor - Recipe_Tailor - -
  • ElectricTailoringBench
  • -
  • HandTailoringBench
  • -
    - UnfinishedApparel -
    -
    - + SmithingSpeed @@ -58,107 +46,30 @@ - - - Apparel_Parka - - A thick parka for staying warm in even the coldest of temperatures. - - Things/Pawn/Humanlike/Apparel/Parka/Parka - Graphic_Single - - 120 - -
  • Fabric
  • -
  • Leathery
  • -
    - -
  • Apparel
  • -
    - - 200 - 22000 - 0.03 - 0.03 - -40 - -3 - 1 - 10 - 1 - 3 - - - -
  • Torso
  • -
  • Shoulders
  • -
  • Arms
  • -
    - Things/Pawn/Humanlike/Apparel/Parka/Parka - -
  • Shell
  • -
    - 1 - -
  • Outlander
  • -
  • Tribal
  • -
    - -
  • Worker
  • -
  • Soldier
  • -
    -
    - - -
  • - 10 - RGBA(0.33,0.33,0.33,1) -
  • -
  • - 10 - RGBA(0.65,0.65,0.65,1) -
  • -
  • - 10 - RGBA(0.4,0.3,0.15,1) -
  • -
  • - 15 - RGBA(0.3,0.3,0.3,1) - RGBA(0.5,0.5,0.5,1) -
  • -
  • - 6 - RGBA(0.5,0.5,0.5,1) - RGBA(1,1,1,1) -
  • -
    -
    -
    - - + - Apparel_VestPlate - - A vest with armor plates inserted on the chest and back. Protects against gunfire. + Apparel_FlakVest + + Padded vest made from bullet-resistant materials. Provides limited protection against shrapnel and gunfire at relatively low weight. Industrial - Things/Pawn/Humanlike/Apparel/VestPlate/VestPlate + Things/Apparel/FlakVest/FlakVest Graphic_Single 80 -
  • Steeled
  • +
  • Fabric
  • + 0.33 - 9500 - 200 - 0.20 - 0.55 - 13 - 5 - 13 - 5 + 5000 + 125 + 0.10 + 0.15 + 4 + 5 + 2.5
  • Apparel
  • @@ -166,12 +77,12 @@
  • Torso
  • +
  • Shoulders
  • - Things/Pawn/Humanlike/Apparel/VestPlate/VestPlate + Things/Apparel/FlakVest/FlakVest
  • Middle
  • - 1
  • Outlander
  • Military
  • @@ -185,7 +96,7 @@ Apparel_CompositeVest - A vest with armor plates inserted on the chest and back. Composite plating offers superior protection against gunfire compared to regular vests. + A vest with armor plates inserted on the chest and back. The composite ceramics offer better protection than steel but aren't as durable. Industrial UnfinishedTechArmor @@ -196,13 +107,11 @@ 9500 - 150 - 430 + 75 0.3 0.7 12 5 - 12 5 @@ -212,98 +121,18 @@ 60 20 - - -
  • Torso
  • -
    - Things/Pawn/Humanlike/Apparel/VestPlate/VestPlate - -
  • Middle
  • -
    - 0.7 - -
  • Outlander
  • -
  • Military
  • -
    - -
  • Soldier
  • -
    -
    - - -
  • - 10 - RGBA(0.33,0.33,0.33,1) -
  • -
  • - 10 - RGBA(0.65,0.65,0.65,1) -
  • -
  • - 6 - RGBA(0.3,0.3,0.3,1) - RGBA(0.5,0.5,0.5,1) -
  • -
    -
    -
    - - - - Apparel_PowerArmor - - Powered armor usually used by assault troops from advanced glitterworld planets.\n\nBulky and heavy, but the advanced servo-motors greatly increase the wearer's load bearing capacity and assist in weapon-handling. - Spacer - - UnfinishedTechArmor - PoweredArmor - - - Things/Pawn/Humanlike/Apparel/PowerArmor/PowerArmor - Graphic_Single - - - 40000 - 400 - 4500 - 0.35 - 0.80 - 0.30 - -45 - 25 - 60 - 100 - 60 - 15 - - - 80 - 10 - 1.15 - - -
  • Apparel
  • -
    - - 18 - 135 - + 0.67
  • Torso
  • Shoulders
  • -
  • Arms
  • -
  • Legs
  • - Things/Pawn/Humanlike/Apparel/PowerArmor/PowerArmor + Things/Pawn/Humanlike/Apparel/VestPlate/VestPlate
  • Middle
  • -
  • Shell
  • - 2
  • Outlander
  • -
  • Spacer
  • Military
  • @@ -325,15 +154,8 @@ RGBA(0.3,0.3,0.3,1) RGBA(0.5,0.5,0.5,1) -
  • - 10 - RGBA(0.9,0.9,0.9,1) -
  • - - - diff --git a/Defs/ThingDefs_Misc/Filth_Various.xml b/Defs/ThingDefs_Misc/Filth_Various.xml deleted file mode 100644 index 1aaaa22c15..0000000000 --- a/Defs/ThingDefs_Misc/Filth_Various.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - - - Filth - Filth - Filth - false - MapMeshOnly - - Transparent - Graphic_Cluster - - - -15 - -5 - - - - - - - Napalm_Fuel - - Burns on the ground. - Combat_Realism.IncendiaryFuel - true - Normal - - -10 - -15 - 75 - 5.0 - - - Things/Filth/LiquidFuel - Transparent - - - false - 70 - true - 1 - - - - - - FilthPee - - - -30 - -15 - - - Things/Filth/Spatter - (180, 140, 100, 140) - - - true - 70 - true - - - - \ No newline at end of file diff --git a/Defs/ThingDefs_Misc/Things_Special.xml b/Defs/ThingDefs_Misc/Things_Special.xml index 1d3de142d7..d07796192a 100644 --- a/Defs/ThingDefs_Misc/Things_Special.xml +++ b/Defs/ThingDefs_Misc/Things_Special.xml @@ -4,7 +4,7 @@ ArtilleryMarker - Combat_Realism.ArtilleryMarker + CombatExtended.ArtilleryMarker Attachment Normal diff --git a/Defs/ThingDefs_Misc/Various_Stone.xml b/Defs/ThingDefs_Misc/Various_Stone.xml deleted file mode 100644 index ae750b6869..0000000000 --- a/Defs/ThingDefs_Misc/Various_Stone.xml +++ /dev/null @@ -1,431 +0,0 @@ - - - - - - - Item - Thing - Item - PassThroughOnly - 0.4 - - 300 - 0 - -20 - -2 - - true - 55 - true - MapMeshOnly - true - true - true - 1 - Never - -
  • - Bomb - 2 -
  • -
  • - Bullet - 0.05 -
  • -
  • - Fragment - 0.05 -
  • -
    -
    - - - Blocks of stone. Mostly useful for building long-lasting, simple structures. - - Things/Item/Resource/StoneBlocks - Graphic_Single - - Stone_Drop - Stone_Drop - false - - 1.9 - 0.6 - 1.6 - -12 - 4.0 - 1.0 - - -
  • StoneBlocks
  • -
    - - -
  • Stony
  • -
    - 0.20 - Bricks - - 140 - 2 - - - 1.2 - 0.4 - 2.4 - 0 - 6.0 - 1.3 - 0.45 - 0.9 - 1.35 - 2.0 - -
    -
    - - - - 0 - -2 - - - - - - - ChunkSlagSteel - - - Things/Item/Chunk/ChunkSlag - Graphic_Random - - - 5 - - ChunkSlag_Drop - -
  • Chunks
  • -
    - - 10 - -
    - - - - Sandstone - - A sedimentary rock composed of sand particles compressed together. - - (126,104,94) - - - 400 - - - ChunkSandstone - 0.25 - - - - - ChunkSandstone - - - Things/Item/Chunk/ChunkStone - Graphic_Random - (126,104,94) - - - 20 - - ChunkRock_Drop - -
  • StoneChunks
  • -
    - - 20 - -
    - - - BlocksSandstone - - Blocks of solid sandstone. Sandstone is a relatively soft rock and chips easily. - - (126,104,94) - - - 1.9 - 1 - 0.5 - - - (126,104,94) - BulletImpactGround - MeleeHit_Stone - MeleeHit_Stone - sandstone - - 1.1 - 0.4 - 1.4 - 5.0 - 1.1 - - - - - - - Granite - - A very hard igneous rock. - - (105,95,97) - - - 900 - - - ChunkGranite - 0.25 - - - - - ChunkGranite - - - Things/Item/Chunk/ChunkStone - Graphic_Random - (105,95,97) - - - 25 - - ChunkRock_Drop - -
  • StoneChunks
  • -
    - - 20 - -
    - - - BlocksGranite - - Blocks of solid granite. Granite is a very hard stone. - - (105,95,97) - - - 2.1 - 1.25 - 0.65 - - - (105,95,97) - BulletImpactGround - MeleeHit_Stone - MeleeHit_Stone - granite - - 0.5 - 1.7 - - - - - - - Limestone - - A sedimentary rock formed from the compacted remains of ancient seashells. - - (158,153,135) - - - 700 - - - ChunkLimestone - 0.25 - - - - - ChunkLimestone - - - Things/Item/Chunk/ChunkStone - Graphic_Random - (158,153,135) - - - 22 - - ChunkRock_Drop - -
  • StoneChunks
  • -
    - - 20 - -
    - - - BlocksLimestone - - Blocks of solid limestone. - - (158,153,135) - - - 1.9 - 1.1 - - - (158,153,135) - BulletImpactGround - MeleeHit_Stone - MeleeHit_Stone - limestone - - 0.4 - 1.55 - - - - - - - Slate - - A dark-colored metamorphic rock. Its fine layers are emblematic of slaty cleavage. - - (70,70,70) - - - 500 - - - ChunkSlate - 0.25 - - - - - ChunkSlate - - - Things/Item/Chunk/ChunkStone - Graphic_Random - (90,90,90) - - - 18 - - ChunkRock_Drop - -
  • StoneChunks
  • -
    - - 20 - -
    - - - BlocksSlate - - Blocks of solid slate. A dull-looking rock that chips easily. - - (70,70,70) - - - 1.9 - 0.9 - - - (70,70,70) - BulletImpactGround - MeleeHit_Stone - MeleeHit_Stone - slate - - 1.1 - 0.38 - 1.3 - - - - - - - Marble - - A soft metamorphic rock. - - (132,135,132) - - - 450 - -1 - - - ChunkMarble - 0.25 - - - - - ChunkMarble - - - Things/Item/Chunk/ChunkStone - Graphic_Random - (132,135,132) - - - 25 - - ChunkRock_Drop - -
  • StoneChunks
  • -
    - - 20 - -
    - - - BlocksMarble - - Blocks of solid marble. Marble is a soft, beautiful stone, known for being easy to sculpt. - - (132,135,132) - - - 1.9 - 1.25 - - - (132,135,132) - BulletImpactGround - MeleeHit_Stone - MeleeHit_Stone - marble - - 1.35 - 0.45 - 1.2 - 5.5 - 1.15 - - - - -
    diff --git a/Defs/ThingDefs_Misc/Weapons_Grenades.xml b/Defs/ThingDefs_Misc/Weapons_Grenades.xml index f45ca34b3c..75d3227f0e 100644 --- a/Defs/ThingDefs_Misc/Weapons_Grenades.xml +++ b/Defs/ThingDefs_Misc/Weapons_Grenades.xml @@ -29,14 +29,21 @@ Never
    - + + CombatExtended.AmmoThing 75 + +
  • CE_AI_Grenade
  • +
  • CE_OneHandedWeapon
  • +
    + Normal + First
    Projectile Projectile - Combat_Realism.ProjectileCE_Explosive + CombatExtended.ProjectileCE_Explosive Normal False @@ -44,198 +51,196 @@ Transparent - + 24 false - - + - Proj_GrenadeFrag - + Proj_GrenadeFlashbang + - Things/Projectile/Grenades/Frag + Things/Projectile/Grenades/Flashbang Graphic_Single - 1.5 - Bomb - 80 - 60 + 3.5 + Stun + 50 + 30 + Explosion_Stun true Mote_GrenadePin - -
  • - 4.0 - - 225 - 150 - 45 - -
  • -
    - Weapon_GrenadeFrag + Weapon_GrenadeFlashbang Primary - - Old-school fragmentation grenade. + + Pyrotechnic charge designed to produce a blinding flash of light and loud noise, temporarily blinding and disorienting anyone nearby. - Things/Ammo/HandGrenades/Frag + Things/Ammo/HandGrenades/Flashbang Graphic_StackCount InteractGrenade Industrial - 5.25 - 0.15 + 4.85 + 0.15 1 -
  • GrenadeDestructive
  • +
  • CE_GrenadeFlashbang
  • +
  • CE_AI_Nonlethal
  • Grenades
  • -
  • - - Combat_Realism.Verb_ShootCEOneUse +
  • + + CombatExtended.Verb_ShootCEOneUse true - 10.0 + 10 0.8 4 - true + false ThrowGrenade true - Proj_GrenadeFrag + Proj_GrenadeFlashbang true
  • + +
  • + 25 + Stun + 3.5 + Explosion_Stun +
  • +
    - - + - Proj_GrenadeMolotov - - Combat_Realism.Projectile_FireTrail + Proj_GrenadeStickBomb + - Things/Projectile/Grenades/Molotov + Things/Projectile/Grenades/StickBomb Graphic_Single - 1.5 - Flame - 30 - Napalm_Fuel + 1.5 + Bomb + 50 + 90 - Weapon_GrenadeMolotov + Weapon_GrenadeStickBomb Primary - - Glass bottle filled with flammable liquid, with a burning cloth in the neck. A favorite weapon of hooligans and desperate warriors from rim to rim. + + Primitive fuse-lit explosive. A favorite of tribals who use these to fight technologically advanced enemies with heavy armor. - Things/Ammo/HandGrenades/Molotov + Things/Ammo/HandGrenades/StickBomb Graphic_StackCount - InteractMolotovCocktail + InteractGrenade Industrial - 2.10 - 0.15 + 5.25 + 0.15 1
  • GrenadeDestructive
  • +
  • Neolithic
  • Grenades
  • -
  • - - Combat_Realism.Verb_ShootCEOneUse +
  • + + CombatExtended.Verb_ShootCEOneUse true - 10 + 10.0 0.8 4 true - true - ThrowMolotovCocktail + ThrowGrenade true - Proj_GrenadeMolotov + Proj_GrenadeStickBomb true
  • + +
  • + 25 + Bomb + 1.5 +
  • +
    - + - Proj_GrenadeEMP - + Proj_GrenadeSmoke + - Things/Projectile/Grenades/EMP + Things/Projectile/Grenades/Smoke Graphic_Single - 3 - EMP - 40 - 60 + 4 + Smoke + 30 true Mote_GrenadePin + Gas_Smoke + 1 - -
  • - 10 - Electrical - 4 - Explosion_Bomb -
  • -
    - Weapon_GrenadeEMP + Weapon_GrenadeSmoke Primary - - Electromagnetic pulse grenade damaging to electronic equipment. + + Releases a large cloud of defensive smoke, providing concealment against gunfire. - Things/Ammo/HandGrenades/EMP + Things/Ammo/HandGrenades/Smoke Graphic_StackCount InteractGrenade Industrial - 7.65 - 0.15 + 4.85 + 0.15 1 -
  • GrenadeEMP
  • +
  • CE_GrenadeSmoke
  • +
  • CE_AI_Nonlethal
  • Grenades
  • -
  • - - Combat_Realism.Verb_ShootCEOneUse +
  • + + CombatExtended.Verb_ShootCEOneUse true 10 0.8 @@ -245,58 +250,67 @@ true - Proj_GrenadeEMP + Proj_GrenadeSmoke true
  • + +
  • + Smoke + 3.5 + Gas_Smoke + 1 +
  • +
    - + - Proj_GrenadeFlashbang - + Proj_GrenadeFirefoam + - Things/Projectile/Grenades/Flashbang + Things/Projectile/Grenades/Firefoam Graphic_Single - 3.5 - Stun + 4 50 - 60 - Explosion_Stun + Extinguish + 30 true Mote_GrenadePin + FilthFireFoam + 1 - Weapon_GrenadeFlashbang + Weapon_GrenadeFirefoam Primary - - Pyrotechnic charge designed to produce a blinding flash of light and loud noise, temporarily blinding and disorienting anyone nearby. + + Special firefighting grenade. Releases a cloud of firefoam upon impact. - Things/Ammo/HandGrenades/Flashbang + Things/Ammo/HandGrenades/Firefoam Graphic_StackCount InteractGrenade Industrial 4.85 - 0.15 + 0.15 1 -
  • CE_GrenadeFlashbang
  • +
  • CE_AI_Nonlethal
  • Grenades
  • -
  • - - Combat_Realism.Verb_ShootCEOneUse +
  • + + CombatExtended.Verb_ShootCEOneUse true 10 0.8 @@ -306,10 +320,18 @@ true - Proj_GrenadeFlashbang + Proj_GrenadeFirefoam true
  • + +
  • + Extinguish + 4 + FilthFireFoam + 1 +
  • +
    diff --git a/Defs/ThingDefs_Misc/Weapons_Guns.xml b/Defs/ThingDefs_Misc/Weapons_Guns.xml deleted file mode 100644 index 5dee3bdc5f..0000000000 --- a/Defs/ThingDefs_Misc/Weapons_Guns.xml +++ /dev/null @@ -1,1063 +0,0 @@ - - - - - - Item - ThingWithComps - Primary - 10 - True - True - - 35 - - true - - 100 - 1.0 - 2 - 0.5 - - Item - True - Never - Industrial - true - -
  • WeaponsRanged
  • -
    - -
  • ITab_Art
  • -
    - -
  • -
  • - CompEquippable -
  • -
  • - CompQuality -
  • -
  • - ArtName_WeaponGun - ArtDescription_WeaponGun - Excellent -
  • -
    -
    - - - - SmithingSpeed - Crafting - Smith - Recipe_Smith - -
  • TableMachining
  • -
    - UnfinishedGun -
    -
    - - - -
  • Gun
  • -
    -
    - - - -
  • Gun
  • -
    -
    - - - - - - Gun_Pistol - - Ancient pattern automatic pistol. Weak and short range, but quick. - - Things/Item/Equipment/WeaponRanged/Pistol - Graphic_Single - - InteractPistol - - 6000 - 200 - 0.35 - 0.16 - 1.55 - 0.25 - 2.10 - 1.00 - - - 30 - 2 - - -
  • CE_Sidearm
  • -
    - -
  • - Combat_Realism.Verb_ShootCE - true - Bullet_45ACP_FMJ - 0.3 - 10 - ShotPistol - GunTail_Light - 9 -
  • -
    - -
  • - 7 - 180 - AmmoSet_45ACP -
  • -
  • - FALSE - FALSE -
  • -
    -
    - - - - - Gun_PumpShotgun - - Ancient design. Deadly, but short range. - - Things/Item/Equipment/WeaponRanged/Shotgun - Graphic_Single - - InteractShotgun - - 7500 - 400 - 0.5 - 1.54 - 8.10 - 3.00 - 1.5 - - - 90 - 3 - - -
  • - Combat_Realism.Verb_ShootCE - true - Bullet_12Gauge_Buck - 0.5 - 15 - ShotShotgun - GunTail_Heavy - 9 -
  • -
    - -
  • - 5 - 240 - AmmoSet_12Gauge -
  • -
  • - FALSE - FALSE -
  • -
    -
    - - - - - Gun_SurvivalRifle - - Ancient bolt-action rifle. Good range, Good power, low rate of fire. - - Things/Item/Equipment/WeaponRanged/SurvivalRifle - Graphic_Single - - InteractRifle - - 8000 - 400 - 0.50 - 0.08 - 1.42 - 9.50 - 4.00 - 1.2 - - - 90 - 3 - - -
  • - Combat_Realism.Verb_ShootCE - true - Bullet_303British_FMJ - 1.1 - 67 - ShotSurvivalRifle - GunTail_Heavy - 9 -
  • -
    - -
  • - 10 - 180 - AmmoSet_303British -
  • -
  • - FALSE - TRUE -
  • -
    -
    - - - - - Gun_AssaultRifle - - A general-purpose military weapon for field or urban combat. It fires a three-round burst. Good range, low power, high rate of fire. - - Things/Item/Equipment/WeaponRanged/AssaultRifle - Graphic_Single - - InteractRifle - - 10500 - 650 - 0.50 - 0.08 - 1.28 - 10.03 - 3.40 - 0.4 - - - 100 - 4 - - -
  • - Regular - 0.96 - Combat_Realism.Verb_ShootCE - true - Bullet_556x45mmNATO_FMJ - 0.8 - 73 - 6 - 4 - ShotAssaultRifle - GunTail_Medium - 9 -
  • -
    - -
  • - 30 - 300 - AmmoSet_556x45mmNATO -
  • -
  • - 3 - TRUE - TRUE -
  • -
    -
    - - - - - Gun_SniperRifle - - Ancient pattern military sniper rifle. Bolt action. Long range, great accuracy and power. - - Things/Item/Equipment/WeaponRanged/SniperRifle - Graphic_Single - - InteractRifle - - 13000 - 850 - 1.25 - 0.04 - 2.09 - 10.92 - 7.30 - 0.5 - - - 100 - 6 - - -
  • - Combat_Realism.Verb_ShootCE - true - Bullet_762x51mmNATO_FMJ - 1.6 - 107 - ShotSniperRifle - GunTail_Heavy - 9 -
  • -
    - -
  • - 5 - 300 - AmmoSet_762x51mmNATO -
  • -
  • - FALSE - TRUE -
  • -
    - -
  • SniperRifle
  • -
    -
    - - - - - Gun_MachinePistol - - A micro-submachine gun. Short range, low power, high rate of fire. Very quick to aim and fire. - - Things/Item/Equipment/WeaponRanged/MachinePistol - Graphic_Single - - InteractSMG - - 9000 - 550 - 0.50 - 0.12 - 0.98 - 5.44 - 3.50 - 0.33 - - - 90 - 3 - - -
  • - Regular - 0.19 - Combat_Realism.Verb_ShootCE - true - Bullet_9x19mmPara_FMJ - 0.8 - 20 - 6 - 6 - ShotMachinePistol - GunTail_Light - 9 -
  • -
    - -
  • - 32 - 240 - AmmoSet_9x19mmPara -
  • -
  • - 3 - FALSE - FALSE -
  • -
    - -
  • CE_SMG
  • -
    -
    - - - - - Gun_HeavySMG - - A compact, wide-caliber slug-thrower. Very short range, but it packs a punch and handles quite well. - - Things/Item/Equipment/WeaponRanged/HeavySMG - Graphic_Single - - InteractSMG - - 10500 - 600 - 0.35 - 0.12 - 0.66 - 5.00 - 1.40 - 0.33 - - - 130 - 4 - - -
  • - Regular - 0.47 - Combat_Realism.Verb_ShootCE - true - Bullet_45ACP_FMJ - 0.9 - 14 - 6 - 7 - ShotHeavySMG - GunTail_Heavy - 9 -
  • -
    - -
  • - 20 - 240 - AmmoSet_45ACP -
  • -
  • - 3 - FALSE - FALSE -
  • -
    - -
  • CE_SMG
  • -
    -
    - - - - - Gun_IncendiaryLauncher - - Incendiary bolt launcher. Starts fires. - - Things/Item/Equipment/WeaponRanged/IncendiaryLauncher - Graphic_Single - - InteractRifle - - 13000 - 630 - 0.50 - 0.17 - 1.26 - 11.25 - 4.20 - 0.4 - - - 140 - 4 - - -
  • - Combat_Realism.Verb_ShootCE - true - Bullet_30x64mmFuel_Incendiary - true - 1.8 - 53 - 1 - ShotIncendiaryLauncher - GunTail_Medium - 14 - - true - -
  • -
    - -
  • - 5 - 300 - AmmoSet_30x64mmFuel -
  • -
  • - FALSE - TRUE -
  • -
    -
    - - - - - Gun_LMG - - A light machine gun. - - Things/Item/Equipment/WeaponRanged/LMG - Graphic_Single - - InteractRifle - - 18000 - 1200 - 0.50 - 0.08 - 3.42 - 13.97 - 9.12 - 1 - - - 150 - 4 - - -
  • CE_MachineGun
  • -
    - -
  • - Mounted - 0.36 - Combat_Realism.Verb_ShootCE - true - Bullet_762x54mmR_FMJ - 2.2 - 113 - 7 - 10 - ShotMinigun - GunTail_Medium - 9 - - true - -
  • -
    - -
  • - 47 - 420 - AmmoSet_762x54mmR -
  • -
  • - 5 - FALSE - FALSE -
  • -
    -
    - - - - - Gun_ChargeRifle - - Charged-shot energy/projectile rifle. - - Things/Item/Equipment/WeaponRanged/ChargeRifle - Graphic_Single - - InteractChargeRifle - - 24000 - 1600 - 0.50 - 0.05 - 1.40 - 11.00 - 3.50 - 0.4 - - - ChargedShot - - - 120 - 30 - 6 - - Spacer - -
  • AdvancedGun
  • -
    - -
  • - Regular - 0.59 - Combat_Realism.Verb_ShootCE - true - Bullet_6x24mmCharged - 0.8 - 73 - 5 - 6 - ShotChargeRifle - GunTail_Medium - 9 -
  • -
    - -
  • - 60 - 300 - AmmoSet_6x24mmCharged -
  • -
  • - 3 - TRUE - TRUE -
  • -
    -
    - - - - - Gun_TurretImprovised - - - Things/Item/Equipment/WeaponRanged/ChargeRifle - Graphic_Single - - true - Jury-rigged gun attached to a turret. - InteractRifle - false - Never - - 0.35 - 0.08 - 1.20 - 7.00 - 3.00 - 0.4 - - -
  • TurretGun
  • -
    - -
  • - Mounted - 0.72 - Combat_Realism.Verb_ShootCE - true - Bullet_556x45mmNATO_FMJ - 0.9 - 27 - 5 - 10 - GunShotA - GunTail_Light - 9 -
  • -
    - -
  • - 300 - 300 - true - AmmoSet_556x45mmNATO -
  • -
  • - TRUE - TRUE - true - true -
  • -
    -
    - - - - - Gun_Minigun - - A multi-barrel machine gun with an extremely high rate of fire. Mechanoid-built. - - Things/Item/Equipment/WeaponRanged/Minigun - Graphic_Single - - InteractRifle - - 30000 - 2200 - 1.25 - 0.08 - 3.70 - 16.00 - 20.00 - 1.5 - - Never - True - True - Spacer - -
  • MechanoidGunHeavy
  • -
    - -
  • - Mounted - 0.90 - Combat_Realism.Verb_ShootCE - true - Bullet_762x51mmNATO_FMJ - 2.4 - 2.2 - 107 - 300 - 1 - ShotMinigun - GunTail_Medium - 9 -
  • -
    - -
  • - 600 - 300 - AmmoSet_762x51mmNATO -
  • -
  • - FALSE - TRUE -
  • -
    -
    - - - Bullet_DoomsdayRocket - - - Things/Projectile/Rocket_Big - Graphic_Single - TransparentPostLight - - Combat_Realism.ProjectileCE_Explosive - - Bomb - 250 - 7.8 - 100 - - - - - Gun_DoomsdayRocket - - A single-use rocket launcher for quick retribution. - - Things/Item/Equipment/WeaponRanged/DoomsdayLauncher - Graphic_Single - - - 18000 - 2000 - 1.25 - 0.2 - 3.90 - 17.50 - 11.00 - 1.5 - - - LargeRockets - - - 170 - 15 - 5 - - Spacer - false - -
  • Gun
  • -
  • GunHeavy
  • -
    - -
  • Exotic
  • -
    - -
  • - Combat_Realism.Verb_ShootCEOneUse - true - Bullet_DoomsdayRocket - 0.0 - 2.6 - 80 - 1 - InfernoCannon_Fire - GunTail_Heavy - true - - true - - 14 -
  • -
    - -
  • - FALSE - TRUE -
  • -
    -
    - - - Bullet_Rocket - - - Things/Projectile/Rocket_Big - Graphic_Single - TransparentPostLight - - Combat_Realism.ProjectileCE_Explosive - - Bomb - 180 - 3.0 - 100 - - - - - Gun_TripleRocket - - A single-use rocket launcher that fires 3 projectiles in quick succession. - - Things/Item/Equipment/WeaponRanged/RocketLauncher - Graphic_Single - - - 15000 - 1000 - 1.25 - 0.2 - 3.50 - 17.50 - 9.00 - 1.5 - - - LargeRockets - - - 120 - 8 - 3 - - Spacer - false - -
  • Gun
  • -
  • GunHeavy
  • -
    - -
  • Exotic
  • -
    - -
  • - Combat_Realism.Verb_ShootCEOneUse - true - Bullet_Rocket - 2.0 - 2.9 - 80 - 20 - 3 - InfernoCannon_Fire - GunTail_Heavy - true - false - - true - - 14 -
  • -
    - -
  • - 1 - FALSE - TRUE - true -
  • -
    -
    - - - - - Gun_ChargeBlasterHeavy - - Charged-shot blaster for area suppressive fire. Mechanoid-built. - - Things/Item/Equipment/WeaponRanged/ChargeBlasterHeavy - Graphic_Single - - - 2400 - 1.25 - 0.04 - 4.50 - 24.00 - 25.00 - 1.5 - - Never - Spacer - True - True - -
  • MechanoidGunHeavy
  • -
    - -
  • - Mounted - 0.54 - Combat_Realism.Verb_ShootCE - true - Bullet_12x64mmCharged - 2.9 - 1.7 - 93 - 5 - 20 - ShotChargeBlaster - GunTail_Heavy - 9 -
  • -
    - -
  • - 100 - 300 - AmmoSet_12x64mmCharged -
  • -
  • - 10 - FALSE - TRUE -
  • -
    -
    - - - Gun_InfernoCannon - - Incendiary-shot mini-artillery device. Mechanoid-built. - - Things/Item/Equipment/WeaponRanged/InfernoCannon - Graphic_Single - - - 2400 - 1.25 - 0.1 - 3.50 - 37.50 - 10.00 - 2 - - Never - Spacer - True - True - -
  • MechanoidGunHeavy
  • -
    - -
  • - Combat_Realism.Verb_ShootCE - true - Bullet_80x256mmFuel_Thermobaric - 3.5 - true - 2.3 - 80 - 1 - InfernoCannon_Fire - GunTail_Light - 14 -
  • -
    - -
  • - 1 - 270 - AmmoSet_80x256mmFuel -
  • -
  • - FALSE - TRUE -
  • -
    -
    - - - Gun_ChargeLance - - Charged-shot rail-assisted lance weapon. Fires a single charged shot at high velocity. - - Things/Item/Equipment/WeaponRanged/ChargeLance - Graphic_Single - - - 2000 - 1.25 - 0.017 - 4.10 - 18.00 - 7.00 - 0.5 - - Never - Spacer - True - True - -
  • MechanoidGunMedium
  • -
    - -
  • - Combat_Realism.Verb_ShootCE - true - Bullet_5x35mmCharged - 1.3 - 120 - 1 - ChargeLance_Fire - GunTail_Heavy - 9 -
  • -
    - -
  • - 0 - AmmoSet_5x35mmCharged -
  • -
  • - FALSE - TRUE -
  • -
    -
    - -
    diff --git a/Defs/ThingDefs_Misc/Weapons_Melee.xml b/Defs/ThingDefs_Misc/Weapons_Melee.xml deleted file mode 100644 index 19e2679a24..0000000000 --- a/Defs/ThingDefs_Misc/Weapons_Melee.xml +++ /dev/null @@ -1,344 +0,0 @@ - - - - - Item - ThingWithComps - Primary - 10 - True - True - - 35 - - true - - 100 - 1.0 - 1 - 0.5 - - Item - True - Never - Industrial - true - -
  • Melee
  • -
    - -
  • WeaponsMelee
  • -
    - -
  • -
  • - CompEquippable -
  • -
  • - CompQuality -
  • -
  • - ArtName_WeaponMelee - ArtDescription_WeaponMelee - Excellent -
  • -
    - - SmithingSpeed - Crafting - Smith - Recipe_Smith - -
  • ElectricSmithy
  • -
  • FueledSmithy
  • -
    - UnfinishedWeapon -
    - -
  • ITab_Art
  • -
    -
    - - - - - -
  • Root
  • -
    - -
  • Silver
  • -
  • Gold
  • -
  • WoodLog
  • -
    -
    -
    -
    - - - - - -
  • Root
  • -
    - -
  • Silver
  • -
  • Gold
  • -
    -
    -
    -
    - - - - - MeleeWeapon_Gladius - - A short sword of ancient design. Good for stabbing or slashing. - - Things/Item/Equipment/WeaponMelee/Gladius - Graphic_Single - - InteractPistol - 50 - - 20000 - 14 - 0.975 - 0.2 - 3.5 - 1 - - -65 - -
  • Metallic_Weapon
  • -
  • Woody
  • -
    - -
  • - Verb_MeleeAttack - true - Cut -
  • -
    -
    - - - MeleeWeapon_LongSword - - The ancient weapon of kings, the longsword can be used for slashing or stabbing and is deadly in the right hands. - - Things/Item/Equipment/WeaponMelee/LongSword - Graphic_Single - - InteractPistol - 120 - - 40000 - 16 - 1.25 - 0.225 - 8 - 1.6 - - -65 - -
  • Metallic_Weapon
  • -
  • Woody
  • -
    - -
  • - Verb_MeleeAttack - true - Cut -
  • -
    -
    - - - MeleeWeapon_Knife - - One of humankind's oldest tools, the knife is both an everyday tool and a deadly weapon. - - Things/Item/Equipment/WeaponMelee/Knife - Graphic_Single - - -
  • CE_Sidearm_Melee
  • -
    - InteractPistol - 40 - - 6000 - 12 - 0.83 - 0.175 - 1 - 0.3 - - -65 - -
  • Metallic_Weapon
  • -
    - -
  • - Verb_MeleeAttack - true - Cut -
  • -
    -
    - - - MeleeWeapon_Shiv - - An improvised knife-like weapon. - - Things/Item/Equipment/WeaponMelee/Shiv - Graphic_Single - - -
  • CE_Sidearm_Melee
  • -
    - InteractPistol - Sellable - 10 - - 300 - 10 - 0.5 - 0.83 - 0.125 - 1 - 0.3 - - -65 - -
  • Metallic_Weapon
  • -
  • Woody
  • -
  • Stony
  • -
    - - -
  • ElectricSmithy
  • -
  • FueledSmithy
  • -
  • CraftingSpot
  • -
    -
    - -
  • - Verb_MeleeAttack - true - Cut -
  • -
    -
    - - - MeleeWeapon_Spear - - A polearm tipped with a sharp point for stabbing opponents in melee combat. - - Things/Item/Equipment/WeaponMelee/Spear - Graphic_Single - - Neolithic - -
  • Neolithic
  • -
  • NeolithicMelee
  • -
    - 90 - - 25000 - 18 - 1.15 - 0.275 - 10 - 2.5 - - -25 - -
  • Metallic_Weapon
  • -
  • Woody
  • -
    - -
  • - Verb_MeleeAttack - true - Stab -
  • -
    -
    - - - MeleeWeapon_Mace - - A refined club, engineered for efficient swinging and deadly impacts. - - Things/Item/Equipment/WeaponMelee/Mace - Graphic_Single - - 75 - - 15000 - 16 - 1.05 - - -65 - -
  • Metallic_Weapon
  • -
  • Woody
  • -
    - -
  • - Verb_MeleeAttack - true - Blunt -
  • -
    -
    - - - MeleeWeapon_Club - - The oldest human weapon - a shaped piece of wood for bashing enemies to death. Primitive but effective. - - Things/Item/Equipment/WeaponMelee/Club - Graphic_Single - - Neolithic - -
  • Neolithic
  • -
  • NeolithicMelee
  • -
  • CE_Sidearm_Tribal
  • -
    - Sellable - 40 - - 500 - 13 - 0.5 - 1.35 - - -65 - -
  • Metallic_Weapon
  • -
  • Woody
  • -
  • Stony
  • -
    - - -
  • ElectricSmithy
  • -
  • FueledSmithy
  • -
  • CraftingSpot
  • -
    -
    - -
  • - Verb_MeleeAttack - true - Blunt -
  • -
    -
    - -
    diff --git a/Defs/ThingDefs_Misc/Weapons_RangedNeolithic.xml b/Defs/ThingDefs_Misc/Weapons_RangedNeolithic.xml index 4f8af4ea29..169fb7e59e 100644 --- a/Defs/ThingDefs_Misc/Weapons_RangedNeolithic.xml +++ b/Defs/ThingDefs_Misc/Weapons_RangedNeolithic.xml @@ -1,219 +1,154 @@ - - Item - ThingWithComps - Primary - 10 - True - True - - 35 - - true - - 100 - 1.0 - 2 - 0.5 - - Item - True - Never - Neolithic - -
  • Neolithic
  • -
    - -
  • WeaponsRanged
  • -
    - -
  • -
  • - CompEquippable -
  • -
  • - CompQuality -
  • -
    - - SmithingSpeed - Crafting - -
  • ElectricSmithy
  • -
  • FueledSmithy
  • -
    - Smelt - UnfinishedWeapon -
    -
    + + Item + ThingWithComps + Primary + 10 + True + True + + 35 + + true + + 100 + 1.0 + 2 + 0.5 + + Item + True + Never + Neolithic + +
  • Neolithic
  • +
    + +
  • WeaponsRanged
  • +
    + +
  • +
  • + CompEquippable +
  • +
  • + CompQuality +
  • +
    + + SmithingSpeed + Crafting + +
  • ElectricSmithy
  • +
  • FueledSmithy
  • +
    + Smelt + UnfinishedWeapon +
    +
    - - -
  • - CompQuality -
  • -
    -
    + + Projectile + Normal + Projectile + CombatExtended.BulletCE + + False + True + + Transparent + + + - - Projectile - Normal - Projectile - Combat_Realism.BulletCE - - False - True - - Transparent - - - + + + Primary + 10 + + 35 + + + 100 + 1.0 + 2 + 0.5 + + Neolithic + False + False + +
  • Neolithic
  • +
    + +
  • WeaponsRanged
  • +
    + +
  • + CompEquippable +
  • +
    + + SmithingSpeed + Crafting + +
  • ElectricSmithy
  • +
  • FueledSmithy
  • +
    + Smelt + UnfinishedWeapon +
    +
    - + - - Bow_Short - - A simple short bow, made with skill, but using only the most primitive technologies. - - Things/Item/Equipment/WeaponRanged/BowShort - Graphic_Single - - BowSmall - - 40 - - - 1200 - 60 - 0.35 - 1 - 2 - 3.00 - 2.00 - 1 - - -
  • NeolithicRanged
  • -
  • CE_Bow
  • -
    - - -
  • ElectricSmithy
  • -
  • FueledSmithy
  • -
  • CraftingSpot
  • -
    -
    - -
  • - Combat_Realism.Verb_ShootCE - true - Projectile_Arrow_Stone - 0.8 - 23 - BowSmall -
  • -
    - -
  • - AmmoSet_Arrow -
  • -
  • - false - false -
  • -
    -
    - - - Pila - - A non-reusable throwing spear. - - Things/Ammo/Neolithic/Pilum - Graphic_StackCount - 0 - - Interact_BeatFire - - 1 - 1 - - - 1400 - 3.7 - 0.25 - 2.5 - 2 - 4.00 - 3.00 - 1 - - 30 - 75 - -
  • NeolithicRanged
  • -
  • CE_Pila
  • -
    - -
  • - Combat_Realism.Verb_ShootCEOneUse - true - Pilum_Thrown - 1.0 - 6 - -
  • -
    -
    - - - Bow_Great - - A powerful greatbow. Fires a heavy arrow long distances. - - Things/Item/Equipment/WeaponRanged/BowGreat - Graphic_Single - - BowLarge - - 180 - - - 1700 - 110 - 0.35 - 1 - 2 - 5.00 - 2.00 - 1 - - -
  • NeolithicRanged
  • -
  • CE_Bow
  • -
    - -
  • - Combat_Realism.Verb_ShootCE - true - Projectile_GreatArrow_Stone - 0.9 - 30 - BowLarge -
  • -
    - -
  • - AmmoSet_GreatArrow -
  • -
  • - false - false -
  • -
    -
    + + Pila + + A non-reusable throwing spear which may be thrown on its own or using an atlatl. + + Things/Ammo/Neolithic/Pilum + Graphic_StackCount + 0 + + Interact_BeatFire + + 1 + 1 + + + 1400 + 3.7 + 0.25 + 1.5 + 2.5 + 5.00 + 3.00 + 1 + + 30 + 75 + +
  • NeolithicRanged
  • +
  • CR_Pila
  • +
  • CE_AI_Rifle
  • +
    + +
  • CR_AutoEnableTrade
  • +
    + +
  • + CombatExtended.Verb_ShootCEOneUse + true + Pilum_Thrown + 1.5 + 9 + +
  • +
    + Javelin +
    diff --git a/Defs/ThingDefs_Misc/Weapons_Spotting.xml b/Defs/ThingDefs_Misc/Weapons_Spotting.xml index f25fc3050f..7a97064d70 100644 --- a/Defs/ThingDefs_Misc/Weapons_Spotting.xml +++ b/Defs/ThingDefs_Misc/Weapons_Spotting.xml @@ -29,7 +29,7 @@ 10500 650 - 1.25 + 1.6 0.5 1.5 3.00 @@ -39,12 +39,12 @@ 4 -
  • - Combat_Realism.Verb_MarkForArtillery +
  • + CombatExtended.Verb_MarkForArtillery true Bullet_Dummy 5.8 - 107 + 75 0 true diff --git a/Defs/ThingDefs_Misc/Weapons_Turrets.xml b/Defs/ThingDefs_Misc/Weapons_Turrets.xml index ff970d4f12..93a0b5d485 100644 --- a/Defs/ThingDefs_Misc/Weapons_Turrets.xml +++ b/Defs/ThingDefs_Misc/Weapons_Turrets.xml @@ -1,4 +1,4 @@ - + @@ -16,9 +16,9 @@ -
  • +
  • FALSE - TRUE + AimedShot true true
  • @@ -38,32 +38,32 @@ InteractChargeRifle 2000 - 1.25 + 0.5 0.08 - 1.80 - 1.5 + 1.4 + 0.36 -
  • - Mounted - 0.41 - Combat_Realism.Verb_ShootCE +
  • + 0.53 + CombatExtended.Verb_ShootCE true Bullet_6x24mmCharged 1.1 - 40 + 55 5 10 ShotChargeBlaster GunTail_Heavy 9 + Mounted
  • -
  • - 300 - 600 - true +
  • + 100 + 7.8 + false AmmoSet_6x24mmCharged
  • @@ -81,32 +81,32 @@ Large caliber gun on a turret mount. 2000 - 1.25 - 0.08 - 2.35 - 1.5 + 0.5 + 0.01 + 7.70 + 0.36 -
  • - Mounted - 0.78 - Combat_Realism.Verb_ShootCE +
  • + 0.95 + CombatExtended.Verb_ShootCE true Bullet_145x114mm_FMJ - 1.4 - 40 + 1.1 + 55 6 10 HeavyMG GunTail_Heavy 16 + Mounted
  • -
  • - 100 - 600 - true +
  • + 40 + 7.8 + false AmmoSet_145x114mm
  • @@ -124,36 +124,37 @@ Heavy machine gun for use against light vehicles. 2000 - 0.35 - 0.08 - 2.35 - 2.5 + 0.5 + 0.01 + 6.88 + 0.36 -
  • - Mounted - 0.79 - Combat_Realism.Verb_ShootCE +
  • + 1.08 + CombatExtended.Verb_ShootCE true Bullet_145x114mm_FMJ - 1.5 - 133 + 1.1 + 86 6 10 HeavyMG GunTail_Heavy 16 + Mounted
  • -
  • - 50 - 600 - true +
  • + 40 + 7.8 + false AmmoSet_145x114mm
  • -
  • +
  • 5 + SuppressFire
  • @@ -169,37 +170,38 @@ M240B machine gun mounted on a tripod. - 200 - 0.5 - 0.08 - 0.43 - 1.5 + 2000 + 0.50 + 0.04 + 2.51 + 0.36 -
  • - Mounted - 0.43 - Combat_Realism.Verb_ShootCE +
  • + 0.60 + CombatExtended.Verb_ShootCE true Bullet_762x51mmNATO_FMJ - 0.9 - 107 - 5 - 20 + 1.1 + 75 + 6 + 10 MediumMG GunTail_Medium 10 + Mounted
  • -
  • +
  • 100 - 510 - true + 7.8 + false AmmoSet_762x51mmNATO
  • -
  • +
  • 5 + SuppressFire
  • @@ -217,34 +219,40 @@ ArtilleryShellLoaded 2000 - 1.25 - 0.1 - 3 - 2 + 0.6 + 0.01 + 2.99 + 2.57 -
  • - Combat_Realism.Verb_ShootCE +
  • + CombatExtended.Verb_ShootCE true Bullet_90mmCannonShell_HEAT true - 2.2 + 4 16 - 133 - 1 + 86 + 120mm GunTail_Heavy 20 + + true + + Mounted
  • -
  • +
  • 1 - 750 - true + 9.8 + false AmmoSet_90mmCannonShell
  • -
  • +
  • + AimedShot +
  • @@ -259,40 +267,43 @@ AGS-30 attached to a tripod. - 2500 - 1.25 - 0.08 - 0.25 - 1.33 + 2000 + 1.16 + 0.15 + 2.19 + 0.40 -
  • - Mounted - 0.8 - Combat_Realism.Verb_ShootCE +
  • + 4.90 + CombatExtended.Verb_ShootCE true Bullet_30x29mmGrenade_HE true - 1.0 + 1.37 8 - 107 + 75 9 6 AGS GunTail_Heavy 14 + + true + + Mounted
  • -
  • +
  • 30 - 600 - true + 7.8 + false AmmoSet_30x29mmGrenade
  • -
  • - true - TRUE +
  • + FALSE + SuppressFire 3
  • diff --git a/Defs/ThingDefs_Plants/Plants_Bases.xml b/Defs/ThingDefs_Plants/Plants_Bases.xml index b0810f3046..1256f01f43 100644 --- a/Defs/ThingDefs_Plants/Plants_Bases.xml +++ b/Defs/ThingDefs_Plants/Plants_Bases.xml @@ -1,7 +1,7 @@ - + Plant Plant LowPlant @@ -24,7 +24,6 @@ 0.5 1.0 - true Harvest_Standard Harvest_Standard_Finish 190 diff --git a/Defs/ThingDefs_Plants/Plants_Cultivated_Farm.xml b/Defs/ThingDefs_Plants/Plants_Cultivated_Farm.xml index 80dadeb457..8bb8cecb9a 100644 --- a/Defs/ThingDefs_Plants/Plants_Cultivated_Farm.xml +++ b/Defs/ThingDefs_Plants/Plants_Cultivated_Farm.xml @@ -1,14 +1,14 @@ - + PlantBlazebulb - Combat_Realism.Plant_Blazebulb + CombatExtended.Plant_Blazebulb - Genetically engineered plant designed to yield pyrophoric compounds for use in incendiary weapons.\n\nGreat care must be taken in cultivating these as the incendiary compounds inside the bulbs can self-ignite at room temperature, requiring constant cooling to maintain optimal growth temperatures. + Genetically engineered plant designed to yield pyrophoric compounds for use in incendiary weapons.\n\nGreat care must be taken in cultivating these as the incendiary compounds inside the bulbs can self-ignite at temperatures above 28°C/82F, requiring constant cooling to maintain optimal growth temperatures. 65 - 1 + -1 1 @@ -27,7 +27,6 @@ Standard false Prometheum - true 5
  • Ground
  • diff --git a/Defs/ThingDefs_Races/Races_Animal_Insect.xml b/Defs/ThingDefs_Races/Races_Animal_Insect.xml deleted file mode 100644 index 542db2fac4..0000000000 --- a/Defs/ThingDefs_Races/Races_Animal_Insect.xml +++ /dev/null @@ -1,220 +0,0 @@ - - - - - - - - Spelopede - - A medium-sized bioengineered bug the size of a sheep. The spelopede is the middle caste of a hive, taking care of most work tasks as well as fighting with its claws. - - 2.5 - -25 - 450 - 0 - 0.2 - 0.2 - - -
  • - Verb_MeleeAttack - 1.9 - 9 - Cut - HeadClaw -
  • -
    - - BeetleLikeWithClaw - 0.25 - 0.8 - 1.7 - 10 - Megaspider - 0.95 - 6 - -
  • - EusocialInsectLarva - 0 -
  • -
  • - EusocialInsectJuvenile - 0.03 -
  • -
  • - EusocialInsectAdult - 0.2 - Pawn_Spelopede_Pain - Pawn_Spelopede_Death - Pawn_Spelopede_Call - Pawn_Spelopede_Angry -
  • -
    - Pawn_Melee_SmallScratch_HitPawn - Pawn_Melee_SmallScratch_HitBuilding - Pawn_Melee_SmallScratch_Miss -
    - -
  • Insectoid
  • -
    -
    - - - Spelopede - - Spelopede - 65 - 0.2 - true - -
  • - - Things/Pawn/Animal/Spelopede/Spelopede - 1 - (156,148,125) - - - Things/Pawn/Animal/Dessicated/CritterDessicatedSmall - 1 - -
  • -
  • - - Things/Pawn/Animal/Spelopede/Spelopede - 1.25 - (156,148,125) - - - Things/Pawn/Animal/Dessicated/CritterDessicatedSmall - 1.25 - -
  • -
  • - - Things/Pawn/Animal/Spelopede/Spelopede - 1.65 - (156,148,125) - - (0.4, 0.5, 0.37) - (0,0,-0.15) - - - - Things/Pawn/Animal/Dessicated/CritterDessicatedSmall - 1.65 - -
  • -
    -
    - - - - - Megaspider - - Not actually a spider, the megaspider is a genetically-engineered giant insectoid the size of a bear. Designed for heavy work and combat, its thick chitinous armor makes it hard to kill, while its long deadly ripper-blades make it deadly. - - 3.85 - -40 - 700 - 0 - 0.3 - 0.5 - - -
  • - Verb_MeleeAttack - 1.9 - 13 - Cut - HeadClaw -
  • -
    - - BeetleLikeWithClaw - 0.35 - 1.2 - 2.5 - 10 - insect meat - 0.95 - 6 - -
  • - EusocialInsectLarva - 0 -
  • -
  • - EusocialInsectJuvenile - 0.03 -
  • -
  • - EusocialInsectAdult - 0.2 - Pawn_BigInsect_Pain - Pawn_BigInsect_Death - Pawn_BigInsect_Call - Pawn_BigInsect_Angry -
  • -
    - Pawn_Melee_BigBash_HitPawn - Pawn_Melee_BigBash_HitBuilding - Pawn_Melee_BigBash_Miss -
    - -
  • Insectoid
  • -
    -
    - - - Megaspider - - Megaspider - 150 - 0.2 - true - -
  • - - Things/Pawn/Animal/Megaspider/Megaspider - 1.2 - (154,125,94) - - - Things/Pawn/Animal/Dessicated/CritterDessicatedMedium - 1.2 - -
  • -
  • - - Things/Pawn/Animal/Megaspider/Megaspider - 1.6 - (154,125,94) - - - Things/Pawn/Animal/Dessicated/CritterDessicatedMedium - 1.6 - -
  • -
  • - - Things/Pawn/Animal/Megaspider/Megaspider - 2.5 - (154,125,94) - - (0.5, 0.7, 0.43) - (0,0,-0.1) - - - - Things/Pawn/Animal/Dessicated/CritterDessicatedMedium - 2.5 - -
  • -
    -
    - - -
    \ No newline at end of file diff --git a/Defs/ThingDefs_Races/Races_Animal_Rodentlike.xml b/Defs/ThingDefs_Races/Races_Animal_Rodentlike.xml deleted file mode 100644 index e2df245379..0000000000 --- a/Defs/ThingDefs_Races/Races_Animal_Rodentlike.xml +++ /dev/null @@ -1,97 +0,0 @@ - - - - - Boomrat - - Either by deliberate genetic weaponization, or as an unusual defense mechanism, these rodent-like creatures create a powerful fire-starting explosion when killed. - - 5.5 - -30 - 130 - - -
  • - Combat_Realism.CompShearableRenameable - Chemical fullness - 5 - 1 - FSX -
  • -
    - -
  • - Verb_MeleeAttack - 1.65 - 6 - Scratch - FrontLeftPaw -
  • -
  • - Verb_MeleeAttack - 1.65 - 6 - Scratch - FrontRightPaw -
  • -
  • - Verb_MeleeAttack - 1.65 - 4 - Bite - Teeth -
  • -
    - - QuadrupedAnimalWithPaws - DeathActionWorker_SmallExplosion - 0.2 - 0.35 - 0.4 - OmnivoreRoughAnimal - (115,37,28) - 0.7 - 4 - 0.75 - 4 - 120 - false - 12.5 - - -
  • (0.5, 0)
  • -
  • (1, 1)
  • -
  • (5, 1)
  • -
  • (5.5, 0)
  • -
    -
    - 8 - -
  • - AnimalBaby - 0 -
  • -
  • - AnimalJuvenile - 0.1 -
  • -
  • - AnimalAdult - 0.35 - Pawn_Boomrat_Wounded - Pawn_Boomrat_Death - Pawn_Boomrat_Call - Pawn_Boomrat_Angry -
  • -
    - Pawn_Melee_SmallScratch_HitPawn - Pawn_Melee_SmallScratch_HitBuilding - Pawn_Melee_SmallScratch_Miss -
    - -
  • StandardAnimal
  • -
  • BadassAnimal
  • -
    -
    - -
    diff --git a/Defs/ThingDefs_Races/Races_Animal_Tropical.xml b/Defs/ThingDefs_Races/Races_Animal_Tropical.xml deleted file mode 100644 index fd3ea4e20c..0000000000 --- a/Defs/ThingDefs_Races/Races_Animal_Tropical.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - Boomalope - - Engineered for chemicals production, the boomalope grows a large sac of volatile chemicals on its back. Though it is weak and fragile for its size, other animals have learned to avoid it because of the huge explosion it produces when it dies. - - 2.15 - -15 - 290 - - -
  • - Combat_Realism.CompShearableRenameable - Chemical fullness - 5 - 5 - FSX -
  • -
    - -
  • - Verb_MeleeAttack - 1.65 - 9 - Blunt - HeadAttackTool -
  • -
    - - QuadrupedAnimalWithHoovesAndHump - DeathActionWorker_BigExplosion - 6 - true - 1.5 - 1 - 0.65 - VegetarianRoughAnimal - (176,150,106) - 0.9 - 0.6 - false - 30 - 15 - -
  • - AnimalBaby - 0 -
  • -
  • - AnimalJuvenile - 0.25 -
  • -
  • - AnimalAdult - 1 - Pawn_Muffalo_Wounded - Pawn_Muffalo_Death - Pawn_Muffalo_Call - Pawn_Muffalo_Angry -
  • -
    - Pawn_Melee_BigBash_HitPawn - Pawn_Melee_BigBash_HitBuilding - Pawn_Melee_BigBash_Miss -
    - -
  • StandardAnimal
  • -
  • BadassAnimal
  • -
    -
    - -
    diff --git a/Defs/ThingDefs_Races/Races_Humanlike.xml b/Defs/ThingDefs_Races/Races_Humanlike.xml deleted file mode 100644 index 1151b40525..0000000000 --- a/Defs/ThingDefs_Races/Races_Humanlike.xml +++ /dev/null @@ -1,123 +0,0 @@ - - - - - Human - - A baseline human, mostly unmodified by gene engineering and mostly unchanged by evolutionary pressures on non-Earth planets. - - 1750 - 4.61 - 1.0 - 12 - 32 - 25 - - -
  • - Verb_MeleeAttack - 1.85 - 6 - Blunt - LeftHand -
  • -
  • - Verb_MeleeAttack - 1.85 - 6 - Blunt - RightHand -
  • -
    - - Humanlike - HumanlikeConstant - Humanlike - true - 80 - (211,194,143) - 0.01 - 0.70 - 3 - HumanStandard - Human - 1 - 1 - OmnivoreHuman - 45 - - -
  • (0.5, 0)
  • -
  • (1, 1)
  • -
  • (1.01, 0.02)
  • -
  • (3.5, 0)
  • -
    -
    - -
  • - HumanlikeBaby - 0 -
  • -
  • - HumanlikeToddler - 1.2 -
  • -
  • - HumanlikeChild - 4 -
  • -
  • - HumanlikeTeenager - 13 -
  • -
  • - HumanlikeAdult - 18 -
  • -
    - Pawn_Melee_Punch_HitPawn - Pawn_Melee_Punch_HitBuilding - Pawn_Melee_Punch_Miss - - (0.3, 0.8, 0.4) - (0,0,-0.3) - - - -
  • (14,0)
  • -
  • (16,100)
  • -
  • (50,100)
  • -
  • (60,30)
  • -
  • (70,18)
  • -
  • (80,10)
  • -
  • (90,3)
  • -
  • (100,0)
  • -
    -
    - -
  • OrganicStandard
  • -
    -
    - -
  • InstallPowerClaw
  • -
  • InstallScytherBlade
  • -
  • InstallBionicEye
  • -
  • InstallBionicArm
  • -
  • InstallBionicLeg
  • -
  • InstallSimpleProstheticArm
  • -
  • InstallSimpleProstheticLeg
  • -
  • InstallPegLeg
  • -
  • InstallDenture
  • -
  • InstallJoywire
  • -
  • InstallPainstopper
  • -
  • InstallNaturalHeart
  • -
  • InstallNaturalLung
  • -
  • InstallNaturalKidney
  • -
  • InstallNaturalLiver
  • -
  • ExciseCarcinoma
  • -
  • RemoveBodyPart
  • -
  • Euthanize
  • -
    -
    - -
    diff --git a/Defs/ThingDefs_Races/Races_Mechanoid.xml b/Defs/ThingDefs_Races/Races_Mechanoid.xml deleted file mode 100644 index 9708287b4a..0000000000 --- a/Defs/ThingDefs_Races/Races_Mechanoid.xml +++ /dev/null @@ -1,183 +0,0 @@ - - - - - Pawn - Pawn - true - Normal - Pawn - false - true - BulletImpactFlesh - - 70 - - -
  • ITab_Pawn_Health
  • -
  • ITab_Pawn_Needs
  • -
  • ITab_Pawn_Character
  • -
  • ITab_Pawn_Training
  • -
  • Combat_Realism.ITab_Inventory
  • -
  • ITab_Pawn_Guest
  • -
  • ITab_Pawn_Prisoner
  • -
  • ITab_Pawn_Social
  • -
    - -
  • - CompAttachBase -
  • -
  • - Combat_Realism.CompPawnGizmo -
  • -
  • - Combat_Realism.CompSuppressable -
  • -
  • - Combat_Realism.CompInventory -
  • -
    - true -
    - - - - - BulletImpactMetal - - 0 - 0 - 0 - -100 - 250 - - - Mechanoid - false - false - None - - - - - - Mechanoid_Centipede - - Heavy combat mechanoids that glide on dozens of tiny legs. Their heavy armor and firepower makes them very effective against bunched-up static defenders. They are somewhat vulnerable to mobile hit-and-run tactics. - - 1.33 - 0.40 - 0.95 - 0 - 130 - 40 - 0.9 - - -
  • - Verb_MeleeAttack - 2.0 - 35 - Blunt - HeadAttackTool -
  • -
    - - ToolUser - Mechanoid - MechanicalCentipede - 2.0 - 2.0 - -
  • - MechanoidFullyFormed - 0 - Pawn_Mech_Centipede_Wounded - Pawn_Mech_Centipede_Death - Pawn_Mech_Centipede_Call -
  • -
    - - 1000 - 2000 - - Pawn_Melee_MechanoidBash_HitPawn - Pawn_Melee_MechanoidBash_HitBuilding - Pawn_Melee_MechanoidBash_Miss -
    - -
  • ShutDownMechanoid
  • -
    - - 80 - 50 - 2 - -
    - - - - - Mechanoid_Scyther - - Fast, spindly, human-sized combat mechanoids. They usually carry one primary ranged weapon, and their bodies are adorned with two articulated blades to make them deadly in melee combat. Best handled by concentrated, overwhelming force. - - 6.6 - 0.2 - 0.45 - 30 - 15 - 0 - 0.9 - - -
  • - Verb_MeleeAttack - 1.65 - 24 - Cut - LeftBlade -
  • -
  • - Verb_MeleeAttack - 1.65 - 24 - Cut - RightBlade -
  • -
    - - ToolUser - Mechanoid - Scyther - 1.0 - 1.0 - -
  • - MechanoidFullyFormed - 0 - Pawn_Mech_Scyther_Wounded - Pawn_Mech_Scyther_Death - Pawn_Mech_Scyther_Call -
  • -
    - - 1000 - 2000 - - Pawn_Melee_MechanoidSlash_HitPawn - Pawn_Melee_MechanoidSlash_HitBuilding - Pawn_Melee_MechanoidSlash_Miss -
    - -
  • RemoveMechanoidBodyPart
  • -
  • ShutDownMechanoid
  • -
    - - 40 - 25 - 1 - -
    - -
    diff --git a/Defs/ThinkTreeDefs/Humanlike.xml b/Defs/ThinkTreeDefs/Humanlike.xml deleted file mode 100644 index b584d5a140..0000000000 --- a/Defs/ThinkTreeDefs/Humanlike.xml +++ /dev/null @@ -1,331 +0,0 @@ - - - - - Humanlike - - - -
  • - -
  • - -
  • - -
  • -
    - - - -
  • - - -
  • - - -
  • - -
  • - -
  • - Downed -
  • -
  • - BurningResponse -
  • -
  • - MentalStateCritical -
  • - - -
  • - - -
  • - MentalStateNonCritical -
  • - - -
  • - Humanlike_PostMentalState -
  • - - -
  • - -
  • - -
  • - - -
  • - HighPriority - -
  • - LordDuty -
  • - - - - -
  • - Humanlike_PostDuty -
  • - - -
  • - true - - -
  • - true - - -
  • - Deadly -
  • - - -
  • - -
  • - -
  • -
  • -
  • - -
  • -
  • -
  • -
  • - -
  • - -
  • - - -
  • - -
  • - Walk -
  • - - - - -
  • - - -
  • - - -
  • - true -
  • - - - -
  • - - -
  • - Jog - Deadly -
  • - - - -
  • - true - -
  • - -
  • - -
  • - Deadly -
  • - - - -
  • - Deadly -
  • -
  • - -
  • - - -
  • - - -
  • - true -
  • - - -
  • - - -
  • - - -
  • - - -
  • - -
  • - true -
  • - - - - -
  • - true - true -
  • - - -
  • - MediumPriority - -
  • - LordDuty -
  • - - - - -
  • - true -
  • - - -
  • - - - -
  • - - -
  • - - -
  • - Humanlike_PreMain -
  • - - -
  • - -
  • - true - -
  • -
  • -
  • -
  • -
  • - -
  • -
  • - -
  • -
  • -
  • - -
  • - - - - -
  • - Humanlike_PostMain -
  • - - -
  • - -
  • - Idle - - -
  • - Joy - 0.9 - true - -
  • - -
  • - - -
  • - None -
  • - - - - - - -
  • - true - -
  • - -
  • -
  • - Walk -
  • - - - - - - -
  • - true - -
  • - Walk -
  • - - - - -
  • - Deadly -
  • - -
  • - - - - - - HumanlikeConstant - - -
  • - - -
  • -
  • - -
  • - - -
  • - LordDutyConstant -
  • - - - -
    -
    - -
    \ No newline at end of file diff --git a/Defs/ThinkTreeDefs/SubTrees_CR.xml b/Defs/ThinkTreeDefs/SubTrees_CR.xml deleted file mode 100644 index c7d84a7565..0000000000 --- a/Defs/ThinkTreeDefs/SubTrees_CR.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - SuppressionResponse - Humanlike_PostMentalState - 100 - - -
  • - -
  • -
  • - -
  • - -
  • - -
  • -
    - - - - -
    -
    - - - - - -
    diff --git a/Defs/ThoughtDefs/Thoughts_CR.xml b/Defs/ThoughtDefs/Thoughts_CR.xml index 7f0ece2f1a..78ffaa5500 100644 --- a/Defs/ThoughtDefs/Thoughts_CR.xml +++ b/Defs/ThoughtDefs/Thoughts_CR.xml @@ -4,7 +4,7 @@ Suppressed - Combat_Realism.ThoughtWorker_Suppressed + CombatExtended.ThoughtWorker_Suppressed
  • diff --git a/Defs/TraderKindDefs/TraderKinds_Caravan_Outlander.xml b/Defs/TraderKindDefs/TraderKinds_Caravan_Outlander.xml deleted file mode 100644 index e6f6910161..0000000000 --- a/Defs/TraderKindDefs/TraderKinds_Caravan_Outlander.xml +++ /dev/null @@ -1,646 +0,0 @@ - - - - - Caravan_Outlander_BulkGoods - - -
  • - Silver - - 1200 - 2000 - -
  • -
  • - Component - - 3 - 15 - -
  • -
  • - Steel - - 100 - 350 - -
  • -
  • - WoodLog - - 100 - 350 - -
  • -
  • - Plasteel - - 50 - 160 - -
  • -
  • - Cloth - - -70 - 120 - -
  • -
  • - Gold - - -40 - 120 - -
  • -
  • - Textiles - - 1 - 2 - - - 400 - 800 - -
  • -
  • - ResourcesRaw - - 2 - 4 - - - 150 - 320 - -
  • -
  • - FoodRaw - - 2 - 4 - - - 150 - 600 - -
  • -
  • - FoodMeals - - 1 - 2 - - - 200 - 1000 - -
  • -
  • - Neutroamine - - 30 - 150 - -
  • -
  • - Chemfuel - - 0 - 150 - -
  • -
  • - Chocolate - - -150 - 200 - -
  • -
  • - Beer - - -150 - 200 - -
  • -
  • - Medicine - Expensive - - 3 - 8 - -
  • -
  • - Furniture - - 0 - 2 - - - -1 - 2 - -
  • -
  • - true - 0.70 - -
  • StandardAnimal
  • - - - 2 - 4 - - - 4 - 12 - - -
  • - - 4 - 10 - -
  • -
  • - Drugs - - 2 - 3 - - - 1500 - 2500 - -
  • -
  • -
  • - -
  • Chocolate
  • -
  • Kibble
  • -
  • Pemmican
  • - - - -
  • - FSX - Normal - - -120 - 70 - -
  • -
  • - Prometheum - Normal - - -120 - 70 - -
  • - - - - - Caravan_Outlander_CombatSupplier - - -
  • - Silver - - 1200 - 2000 - -
  • -
  • - Component - Expensive - - -2 - 7 - -
  • -
  • - - 3 - 4 - -
  • -
  • - WeaponsMelee - - 3 - 4 - - - 300 - 800 - -
  • -
  • - - 2 - 3 - -
  • -
  • - Medicine - - 4 - 8 - -
  • -
  • - BodyPartOrImplant - - -3 - 3 - - - 1 - 2 - -
  • -
  • - MortarShell - - 4 - 10 - -
  • -
  • - - 1 - 4 - -
  • -
  • -
  • - CE_Ammo - - 200 - 1000 - - Cheap - - 2 - 5 - -
  • -
  • - Ammo - - 0 - 0 - -
  • -
  • - CE_Turret - - -4 - 2 - - - 1 - 1 - -
  • -
  • - WeaponsTurrets - - 0 - 0 - -
  • -
    -
    - - - Caravan_Outlander_Exotic - - -
  • - Silver - - 1500 - 3500 - -
  • -
  • - Component - - 6 - 20 - -
  • -
  • - Plasteel - - 50 - 150 - -
  • -
  • - Gold - - 100 - 200 - -
  • -
  • - Neutroamine - - 25 - 100 - -
  • -
  • - Chemfuel - - 50 - 250 - -
  • -
  • - GlitterworldMedicine - - -5 - 4 - -
  • -
  • - Exotic - - 2 - 4 - - - 1 - 2 - -
  • -
  • - BodyPartOrImplant - - 2 - 4 - - - 1 - 2 - -
  • -
  • - Drugs - - 2 - 4 - - - 400 - 1200 - -
  • -
  • - Artifact - - 1 - 2 - - - 1 - 1 - -
  • -
  • - Apparel - - 1 - 2 - - - 400 - 1500 - - - 1 - 2 - -
  • -
  • - - 1 - 2 - -
  • -
  • - Television - - 1 - 2 - - - -2 - 2 - -
  • -
  • - Telescope - - -2 - 2 - -
  • -
  • - Furniture - - 0 - 3 - - - -1 - 2 - -
  • -
  • - true - -
  • StandardAnimal
  • - - 0.60 - - 1 - 3 - - - 2 - 6 - - -
  • -
  • - - - - - Caravan_Outlander_PirateMerchant - - -
  • - Silver - - 1000 - 1800 - -
  • -
  • - Component - Expensive - - -2 - 4 - -
  • -
  • - Gold - - -40 - 120 - -
  • -
  • - Neutroamine - Expensive - - -50 - 50 - -
  • -
  • - Chemfuel - Expensive - - -50 - 80 - -
  • -
  • - Drugs - - 2 - 4 - - - 1500 - 3000 - -
  • -
  • - - 2 - 3 - -
  • -
  • - - -1 - 1 - -
  • -
  • - - -2 - 1 - -
  • -
  • - Beer - - -100 - 100 - -
  • -
  • - Medicine - Expensive - - 2 - 5 - -
  • -
  • - BodyPartOrImplant - - -3 - 3 - - - 1 - 2 - -
  • -
  • - Artifact - - -4 - 1 - - - 1 - 1 - -
  • -
  • - MortarShell - - -4 - 7 - -
  • -
  • - true - -
  • BadassAnimal
  • - - - 1 - 2 - - - 2 - 6 - - -
  • - - 1 - 5 - -
  • -
  • -
  • - CE_Ammo - - 50 - 100 - - - -1 - 2 - -
  • -
  • - Ammo - - 0 - 0 - -
  • -
    -
    - - diff --git a/Defs/TraderKindDefs/TraderKinds_Orbital_Misc.xml b/Defs/TraderKindDefs/TraderKinds_Orbital_Misc.xml deleted file mode 100644 index 2422b76220..0000000000 --- a/Defs/TraderKindDefs/TraderKinds_Orbital_Misc.xml +++ /dev/null @@ -1,642 +0,0 @@ - - - - - Orbital_BulkGoods - - true - -
  • - Silver - - 4000 - 6000 - -
  • -
  • - Component - - 5 - 30 - -
  • -
  • - Steel - - 800 - 1500 - -
  • -
  • - WoodLog - - 800 - 1500 - -
  • -
  • - Plasteel - - 300 - 700 - -
  • -
  • - Cloth - - -200 - 600 - -
  • -
  • - Gold - - 500 - 2000 - -
  • -
  • - Textiles - - 1 - 2 - - - 2200 - 4000 - -
  • -
  • - ResourcesRaw - - 2 - 4 - - - 1500 - 3000 - -
  • -
  • - FoodRaw - - 2 - 8 - - - 1600 - 5000 - -
  • -
  • - FoodMeals - - 1 - 2 - - - 500 - 1500 - -
  • -
  • - Neutroamine - - 400 - 800 - -
  • -
  • - Chemfuel - - 200 - 600 - -
  • -
  • - Chocolate - - -700 - 2000 - -
  • -
  • - Beer - - -700 - 2000 - -
  • -
  • - Medicine - Expensive - - 10 - 30 - -
  • -
  • - Furniture - - 0 - 3 - - - -1 - 2 - -
  • -
  • - 0.70 - -
  • StandardAnimal
  • - - - 2 - 4 - - - 10 - 20 - - -
  • - - 10 - 20 - -
  • -
  • - Drugs - - 2 - 4 - - - 4000 - 8000 - -
  • -
  • -
  • - -
  • Kibble
  • -
  • Chocolate
  • -
  • Pemmican
  • - - -
  • - CE_Ammo - - 200 - 5000 - - - -1 - 4 - -
  • -
  • - Ammo - - 0 - 0 - -
  • -
    -
    - - - Orbital_CombatSupplier - - true - -
  • - Silver - - 4000 - 6000 - -
  • -
  • - Component - Expensive - - -1 - 10 - -
  • -
  • - - 8 - 15 - -
  • -
  • - WeaponsMelee - - 3 - 5 - - - 500 - 1400 - -
  • -
  • - - 2 - 4 - -
  • -
  • - - 4 - 8 - -
  • -
  • - Medicine - - 30 - 50 - -
  • -
  • - BodyPartOrImplant - - 0 - 5 - - - 1 - 1 - -
  • -
  • - MortarShell - - 30 - 60 - -
  • -
  • - Drugs -
  • -
  • -
  • - CE_Ammo - - 500 - 2000 - - Cheap - - 3 - 9 - -
  • -
  • - Ammo - - 0 - 0 - -
  • -
  • - CE_Turret - - -2 - 4 - - - 1 - 2 - -
  • -
  • - WeaponsTurrets - - 0 - 0 - -
  • -
    -
    - - - Orbital_Exotic - - true - -
  • - Silver - - 8000 - 10000 - -
  • -
  • - Component - Expensive - - 10 - 70 - -
  • -
  • - Gold - - 100 - 2000 - -
  • -
  • - Plasteel - - 100 - 800 - -
  • -
  • - GlitterworldMedicine - - -30 - 20 - -
  • -
  • - Neutroamine - - 300 - 700 - -
  • -
  • - Chemfuel - - 200 - 600 - -
  • -
  • - Drugs - - 3 - 4 - - - 4000 - 8000 - -
  • -
  • - Exotic - - 3 - 5 - - - 1 - 2 - -
  • -
  • - BodyPartOrImplant - - 2 - 5 - - - 1 - 1 - -
  • -
  • - Artifact - - 1 - 4 - - - 1 - 1 - -
  • -
  • - Apparel - - 3 - 6 - - - 1500 - 10000 - - - 1 - 10 - -
  • -
  • - - 5 - 10 - -
  • -
  • - Television - - 2 - 3 - - - -2 - 7 - -
  • -
  • - Telescope - - -5 - 20 - -
  • -
  • - Furniture - - 1 - 4 - - - -1 - 2 - -
  • -
  • - -
  • StandardAnimal
  • - - 0.60 - - 1 - 2 - - - 2 - 3 - - -
  • -
  • -
  • - -
  • Chocolate
  • - - -
    -
    - - - Orbital_PirateMerchant - - true - -
  • - Silver - - 4000 - 6000 - -
  • -
  • - Component - Expensive - - -1 - 8 - -
  • -
  • - - 2 - 3 - -
  • -
  • - - -1 - 2 - -
  • -
  • - - -2 - 2 - -
  • -
  • - Beer - - -300 - 300 - -
  • -
  • - Medicine - Expensive - - 5 - 15 - -
  • -
  • - Neutroamine - Expensive - - 100 - 400 - -
  • -
  • - Chemfuel - Expensive - - 50 - 200 - -
  • -
  • - BodyPartOrImplant - - -4 - 5 - - - 1 - 1 - -
  • -
  • - Artifact - - -5 - 1 - - - 1 - 1 - -
  • -
  • - MortarShell - - -10 - 40 - -
  • -
  • - - 3 - 8 - -
  • -
  • - Drugs - - 5 - 6 - - - 4000 - 8000 - -
  • -
  • -
  • - -
  • Chocolate
  • - - -
  • - CE_Ammo - - 200 - 5000 - - - -1 - 4 - -
  • -
  • - Ammo - - 0 - 0 - -
  • -
    -
    - -
    diff --git a/Defs/TraderKindDefs/TraderKinds_Visitor_Outlander.xml b/Defs/TraderKindDefs/TraderKinds_Visitor_Outlander.xml deleted file mode 100644 index 50e8f177bd..0000000000 --- a/Defs/TraderKindDefs/TraderKinds_Visitor_Outlander.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - - Visitor_Outlander_Standard - - -
  • - Silver - - 50 - 300 - -
  • -
  • - Component - Expensive - - -2 - 5 - -
  • -
  • - FoodMeals - - 1 - 2 - - - 0 - 3 - -
  • -
  • - Medicine - - 0 - 6 - -
  • -
  • - - 0 - 2 - -
  • -
  • - Drugs - Expensive - - -1 - 2 - - - 300 - 500 - -
  • -
  • - - 0 - 2 - -
  • -
  • -
  • - -
  • Cloth
  • -
  • Chocolate
  • - - -
    -
    - -
    \ No newline at end of file diff --git a/Defs/TraitDefs/Traits_Spectrum.xml b/Defs/TraitDefs/Traits_Spectrum.xml new file mode 100644 index 0000000000..e4e7e6d104 --- /dev/null +++ b/Defs/TraitDefs/Traits_Spectrum.xml @@ -0,0 +1,35 @@ + + + + + Bravery + 1 + +
  • + + NAME always shies away from danger. HECAP is usually the first to flee from battle. + -1 + + 0.25 + +
  • +
  • + + Few things scare NAME. In battle HE stands unfazed where others panic and flee. + 1 + + -0.50 + +
  • +
  • + + NAME laughs in the face of danger. Some ascribe it to bravery, others to stupidity. Either way, NAME seems to lack any sense of self-preservation and will never flee from a threatening situation. + 2 + + -1.0 + +
  • +
    +
    + +
    \ No newline at end of file diff --git a/Defs/Tutor/Concepts_NotedOpportunistic.xml b/Defs/Tutor/Concepts_NotedOpportunistic.xml new file mode 100644 index 0000000000..bbc67c3980 --- /dev/null +++ b/Defs/Tutor/Concepts_NotedOpportunistic.xml @@ -0,0 +1,141 @@ + + + + + + + + CE_Reload + + 50 + True + Guns have limited magazine capacity and display their current ammo amount when selecting the gun or its wielder. Once a magazine is empty your colonist needs to spend time reloading. This can take quite a long time for some weapons and consumes ammo from the shooter's inventory.\n\nIn addition to the magazine count guns display their currently loaded ammo type. Different types of ammo can have significantly different performance. It's important to select the appropriate ammo for the enemy you're fighting.\n\nYou can manually order a reload or change the selected ammo type by selecting a colonist and clicking the RELOAD button. This will bring up a menu with a reload command and a list of ammo types in the colonist's inventory.\n\nThe 'Unload' command can be used to dump the currently loaded ammo into the inventory. Ordering a reload with a partially filled magazine will do this automatically. + +
  • CE_Reload
  • +
    +
    + + + CE_ReloadNoMag + + 50 + True + Some weapons such as bows have no magazine that can be loaded. They instead consume ammo directly from their wielder's inventory.\n\nYou can select a pawn and use the RELOAD button to select which of the currently carried ammo-types to use. + +
  • CE_ReloadNoMag
  • +
    +
    + + + CE_ReloadAuto + + 50 + True + Auto-turrets have a limited ammo capacity and no means of reloading themselves. Colonists assigned to the 'Haul' worktype will automatically refill auto-turrets' magazines once they haven't fired for a while.\n\nYou can also order a manual reload by selecting a hauler and right-clicking the turret.\n\nTo select which ammo type your colonists should load, select the turret and click the RELOAD button to bring up a list of all possible ammo types. + +
  • CE_ReloadAuto
  • +
    +
    + + + CE_ReloadManned + + 50 + True + Manned turrets require reloading just like regular guns. Whenever there is a pawn manning them they will automatically use ammo from their inventory to reload or fetch ammo from a nearby stockpile if they're not carrying any.\n\nYou can select a turret and use the RELOAD button to order a manual reload or change the ammo type for that turret. You can also use the 'Unload' command to dump the currently loaded ammo out.\n\nNote that the turret needs to have someone manning it to execute reload commands. + +
  • CE_ReloadManned
  • +
    +
    + + + CE_FireModes + + 50 + True + Fully-automatic weapons can be fired in multiple ways. You can choose between single, burst and full-auto fire. Longer bursts have increased damage and can suppress more easily but the longer the burst, the more accuracy is lost to recoil. They also deplete magazines much more quickly.\n\nUse lower shot counts for far-away enemies you want to hit and longer bursts for suppression, close range and clumped up enemies.\n\nTo change a colonist's fire mode select him, then click the FIRE MODE button to cycle through the available modes. The button also displays the currently selected mode. + +
  • CE_FireModeToggle
  • +
    +
    + + + CE_AimModes + + 50 + True + Your colonists can use two different aim modes when shooting: snapshot and aimed shot. Snapshot requires a short warmup period before firing. Aimed shot reduces weapon sway but requires an additional aiming period after warmup, with the exact time depending on the distance to the target. The further away a target is, the longer the shooter has to aim.\n\nThe bonus provided by aimed shot depends on the shooter's aiming accuracy. A skilled sharpshooter can eliminate nearly all sway by using aimed shot whereas a low-skilled shooter gains only very little benefit.\n\nTo cycle between the fire modes select a colonist and click the AIM MODE button. The button will change to display the currently selected mode.\n\nPawns affected by suppression cannot use aimed shot, regardless of what setting is selected. Mechanoids and auto-turrets on the other hand always use aimed shot. + +
  • CE_AimModeToggle
  • +
    +
    + + + CE_Spotting + + 50 + True + You can have colonists act as spotters for artillery. To do this, equip a pair of binoculars, then order your colonist to target an enemy or a spot on the ground.\n\nAfter a while the target will be marked with a red 'x'. Now select your mortar and order it to fire at the marked target.\n\nThis not only removes indirect fire penalties, it will also use the spotter's aiming accuracy instead of the mortar operator's. Use skilled spotters with sharp eyes to direct artillery directly onto your enemies. + + + + CE_MortarDirectFire + + 50 + True + Mortars are much more accurate when firing at targets they can see. If your mortar operator is within sniper rifle range of the target and has direct line of sight to it they will be able to direct fire directly.\n\nWhen firing at targets they can't see mortars need spotters or they suffer hefty accuracy penalties. You can check your hit chances by selecting the mortar and hovering over a target. + + + + CE_AimingSystem + + 50 + True + Combat Extended uses a new physics-based projectile system. Projectiles follow a ballistic flight path and use hitboxes for collision detection. Several factors determine how close a bullet will fly near it's target:\n\n-Visibility: Darkness, bad weather and smoke make it harder to see the target.\n-Movement: shooter has to lead a moving target. Lead error means the shooter might aim too far forward or back in the direction of movement.\n-Range: shooter needs to correctly estimate how far away the target is. Range error means the shooter will aim as if target was x cells closer/further than it actually is.\n-Sway: Weapons will sway in the hands of the shooter. Reduced by aimed shot mode (reduction depends on skill and sights efficiency).\n-Recoil: Shots within a burst gradually become less accurate\n-Weapon spread: Bullets randomly deviate in a cone (e.g. shotgun pellets).\n-Cover height: Cover obscures parts of the target's hitbox. Can block line of sight for smaller targets (e.g. squirrels behind sandbags).\n-Body size\n-Stance: Downed or hunkering pawns are harder to hit.\n\nYou can get a detailed breakdown by selecting a shooter and hovering the mouse over a target. Given measurements are the maximum deviation in cells/degrees and target/cover hitbox dimensions in cells. + + + + CE_Stabilizing + + 50 + True + When a living creature is downed its wounds can be stabilized using medicine. This will temporarily reduce the amount of blood loss but does nothing to actually treat the wound.\n\nSelect a colonist with medicine in his inventory and right-click the creature you want to stabilize, then click the 'Stabilize' option.\n\nThe amount of bleed reduction depends on medicine skill and medicine used. Internal injuries are harder to treat than external ones and missing body parts can't be stabilized at all. + + + + CE_Shields + + 50 + True + Shields can provide protection against projectiles and melee attacks at the cost of being unable to use two-handed weapons. They are divided into two categories: regular shields and ballistic shields.\n\nRegular shields will deflect projectiles impacting the torso and have a chance to deflect melee attacks depending on the attacker's and defender's melee skills.\n\nBallistic shields are large and cumbersome, inflicting penalties to melee and ranged combat but they also cover the entire head area and can be crouched behind to protect most of the legs.\n\nShields don't make you invincible however, taking offensive actions will expose the weapon arm while high-penetration rounds will punch through or damage the shield. Don't expect a wooden shield to deflect gunfire! + + + + CE_ArmorSystem + + 50 + Combat Extended replaces the vanilla armor system with a penetration-based model. Blunt and sharp type weapons have armor penetration values which determine how much their damage is reduced by armor.\n\nA weapon hitting armor equal to its penetration will do 50% damage. If armor is twice the penetration it will do no damage, if it is half the penetration the full damage goes through.\n\nSharp damage additionally needs to check against deflection. If penetration is equal to armor there is a 50% chance for deflection. Deflected attacks are converted into blunt damage, preventing bleeding and internal organ damage.\n\nEnvironmental damage such as fire/electricity has no penetration and is simply reduced by the % of armor against that type. + + + + CE_SuppressionReaction + + 50 + All humans have a suppression meter, based on their mental break threshold and current mood. Any time gunfire passes by them, it will add to the meter based on projectile power and (lack of) worn armor. \n\nWhen someone's suppression threshold is reached they will panic, run for the nearest cover and become incapable of using aimed shot mode, making it a good tool to break up melee charges or reduce sniper accuracy. It will also impart a mood penalty, making them easier to suppress in the future.\n\nYou can recognize suppressed pawns by the yellow downwards arrow they're emitting. + + + + CE_Hunkering + + 50 + If someone's suppression meter maxes out they will hunker in panic. This causes them to run for the nearest cover and lie down, unable to shoot back or take any action until their suppression ticks down, essentially removing them from the fight.\n\nHunkering pawns are marked by an orange downwards arrow. + + + + CE_WornBulk + + 50 + Certain clothing items are very bulky and will hinder your colonists in their daily tasks, lowering work speed when worn. These items include things like armor and regular clothing made from certain materials such as hyperweave.\n\nYou can check the info-menu of a particular apparel to see its 'worn bulk' stat to see how much bulk it adds when equipped on a colonist. + + +
    \ No newline at end of file diff --git a/Defs/Tutor/Concepts_NotedSelfshow.xml b/Defs/Tutor/Concepts_NotedSelfshow.xml new file mode 100644 index 0000000000..e0b39a3e89 --- /dev/null +++ b/Defs/Tutor/Concepts_NotedSelfshow.xml @@ -0,0 +1,58 @@ + + + + + + + CE_InventoryWeightBulk + + 19 + You can order your colonists to pick up items and store them in their inventory. They are limited in this by their carry weight and bulk capacity.\n\nCarry weight is determined by movement capacity and the more weight a colonist is carrying, the slower they are.\n\nBulk represents the space in your colonists' pockets and can be increased by equipping loadbearing gear like backpacks and tactical vests. The more stuffed their pockets are, the slower they'll work, so only pick up things you actually need.\n\nYou can check a colonist's load by selecting them, clicking the INVENTORY button and hovering over the displayed bars.\n\nTo order a colonist to pick something up, select him, right-click an item and select the 'Pick up' option. + +
  • ITab-Gear-Closed
  • +
    +
    + + + CE_Loadouts + + 18 + Colonists can be told to automatically pick up certain items to avoid inventory micromanagement. For example you can tell them to keep ammo for their primary weapon and they will stock up after a firefight.\n\nOpen the ASSIGN tab and press the 'Manage loadouts' button. Create a new loadout and set the items and quantity you want your colonists to keep. Then you can assign that loadout to your colonists and they will automatically manage their inventories. + +
  • MainTab-Assign-Closed
  • +
  • CE_ManageLoadouts
  • +
    +
    + + + CE_AmmoCrafting + + 8 + Ensuring your colonists are supplied with quality ammo is vital to surviving on a Rimworld. Simple stone arrows can be obtained from the crafting but perform very poorly against opponents with advanced armor and clothing.\n\nSteel and plasteel arrows offer better penetration and can be made at the smithing bench once smithing is researched.\n\nResearch machining to unlock the loading bench, where you can craft ammo for most firearms. Artillery shells and grenades are made at the machining table.\n\nWhile most conventional ammo types can be made from simple raw materials, advanced ammo requires more exotic ingredients such as components, FSX or Prometheum. + + + + CE_ObtainingFSX + + 3 + FSX is the main ingredient for explosives such as frag grenades and mortar shells. You can obtain it either through traders or by taming boomrats and boomalopes, then harvesting the volatile chemicals they produce.\n\nOnce tamed they will produce a steady stream of FSX that your colonists will automatically harvest similar to other animal resources like wool and milk.\n\nYou can see your animal's current chemical fullness by selecting it and checking the readout in the lower-left corner. + + + + CE_ObtainingPrometheum + + 2 + Prometheum is used in most incendiary weapons such as incendiary mortar shells, AP-I rounds and molotovs. It is a highly flammable liquid that is harvested from the blazebulb plant.\n\nTo grow blazebulb, simply select a growing zone and set it to plant blazebulb.\n\nWarning: Blazebulbs are highly sensitive and have a chance to ignite if the surrounding temperature exceeds 28°C/82F. They will also leak puddles of Prometheum when damaged, which ignite on contact with air.\n\nMake sure your plantation has good climate control and is fire-proofed, otherwise it might quickly turn into a blazing inferno! + +
  • GrowingZoneSetPlant
  • +
    +
    + + + CE_CentipedeArmor + + 1 + Warning: It is only a matter of time before Mechanoids take notice of your arrival and start attacking. The larger models have heavy armor that is impervious to small-arms fire.\n\nFighting them requires powerful weapons such as heavy machine guns or explosives. You should keep a healthy stockpile of these weapons if you hope to survive for long. + + +
    \ No newline at end of file diff --git a/Defs/Tutor/Concepts_TriggeredModal.xml b/Defs/Tutor/Concepts_TriggeredModal.xml new file mode 100644 index 0000000000..469038e3b4 --- /dev/null +++ b/Defs/Tutor/Concepts_TriggeredModal.xml @@ -0,0 +1,20 @@ + + + + + + + CE_AmmoSettings + + -1000 + WARNING: You have changed the ammo settings. It is highly recommended you start a new colony with these settings.\n\nChanging the ammo settings on an existing colony is not supported and might result in game-breaking bugs, do so at your own risk. + + + + + \ No newline at end of file diff --git a/Defs/WorkGiverDefs/WorkGivers.xml b/Defs/WorkGiverDefs/WorkGivers.xml index 1398431c82..c40661741f 100644 --- a/Defs/WorkGiverDefs/WorkGivers.xml +++ b/Defs/WorkGiverDefs/WorkGivers.xml @@ -1,16 +1,14 @@  - - ReloadTurrets - Combat_Realism.WorkGiver_ReloadTurret + CombatExtended.WorkGiver_ReloadTurret Hauling reload reloading - 500 + 105
  • Manipulation
  • diff --git a/Languages/ChineseSimplified/DefInjected/StatDef/Stats_Weapons_Ranged.xml b/Languages/ChineseSimplified/DefInjected/StatDef/Stats_Weapons_Ranged.xml index c6383dbc64..baf3eac7bd 100644 --- a/Languages/ChineseSimplified/DefInjected/StatDef/Stats_Weapons_Ranged.xml +++ b/Languages/ChineseSimplified/DefInjected/StatDef/Stats_Weapons_Ranged.xml @@ -1,9 +1,9 @@ - 瞄准效率 + 瞄准效率 - 武器预判和测距的效率。射手的瞄准精确度除以本系数来计算范围和预判误差。\n\n最终判定数值根据以下公式计算:\n(1.5 - 瞄准精确度) / 瞄准效率\n\n预判误差:预判距离格数除以判定数值。\n射程误差:与目标的总距离除以4再除以判定数值。 + 武器预判和测距的效率。射手的瞄准精确度除以本系数来计算范围和预判误差。\n\n最终判定数值根据以下公式计算:\n(1.5 - 瞄准精确度) / 瞄准效率\n\n预判误差:预判距离格数除以判定数值。\n射程误差:与目标的总距离除以4再除以判定数值。 误差 diff --git a/Languages/ChineseSimplified/DefInjected/ThingDef/Filth_Various.xml b/Languages/ChineseSimplified/DefInjected/ThingDef/Filth_Various.xml deleted file mode 100644 index 202786dbb4..0000000000 --- a/Languages/ChineseSimplified/DefInjected/ThingDef/Filth_Various.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - 凝固汽油坑 - - 在地上燃烧。 - - 尿液 - - \ No newline at end of file diff --git a/Languages/English/Keyed/BulkAndWeight.xml b/Languages/English/Keyed/BulkAndWeight.xml index 2af2d601bc..f9d9a6d872 100644 --- a/Languages/English/Keyed/BulkAndWeight.xml +++ b/Languages/English/Keyed/BulkAndWeight.xml @@ -3,6 +3,7 @@ Outfits Edit {0} + Manage loadouts Current loadout Loadouts Mass @@ -15,14 +16,18 @@ Current weight: {1}\nBase capacity: {0}\n\nMove speed factor: {2}\nEncumbrance penalty: {3} Current bulk: {1}\nBase capacity: {0}\n\nWork speed factor: {2} Nothing + No Loadouts Select loadout... New loadout Delete loadout... + Copy loadout No loadout selected Loadout Select ranged weapons Select melee weapons Select ammo + Select minified + Select generic Select all Filter selection Drag handle to reorder diff --git a/Languages/English/Keyed/Keys.xml b/Languages/English/Keyed/Keys.xml index 382e57f923..2a0df5cb23 100644 --- a/Languages/English/Keyed/Keys.xml +++ b/Languages/English/Keyed/Keys.xml @@ -1,16 +1,11 @@ - Reload - Reloads this gun. - - Reloading! - Reloaded! - + Suppressed! Hunkering! - Reloading + Auto Burst Single @@ -21,9 +16,11 @@ Toggle fire mode. Toggle aim mode. + Marked for artillery, expires in Visibility error + Smoke Lead error Range error Sway @@ -34,6 +31,23 @@ Target height Target width + + equipped + stored + ammo + Reloading {0}! + Reloading turret {0}. + manned turret + auto-turret + Unload + Reload + Reloads this gun. + Reloading + + + Equipping + Taking + Carried weight Carried bulk Encumbered @@ -42,15 +56,32 @@ Pick up Pick up half Cannot pick up - Magazine size - Reload time - Caliber - Fire modes - Burst shot count Out of ammo Put away {0} can't do taming job because of a full inventory. Drop and haul Consume + Stop Holding + Forced Holding + + + Stabilize {0} + Cannot stabilize + no medicine + + + Magazine size + Reload time + Caliber + Fire modes + Burst shot count + Used by + + + Colonist has shield and two-handed weapon + One of your colonists is carrying a shield and has a two-handed weapon equipped. They won't be able to attack unless they remove the shield or switch to another weapon. + + + diff --git a/Languages/English/Keyed/LoadoutGeneric.xml b/Languages/English/Keyed/LoadoutGeneric.xml new file mode 100644 index 0000000000..a05a512717 --- /dev/null +++ b/Languages/English/Keyed/LoadoutGeneric.xml @@ -0,0 +1,12 @@ + + + Any Meal + + Any Raw Food + + Any Drugs + + Any Ammo for {0} + + / + diff --git a/Languages/English/Keyed/ModMenu.xml b/Languages/English/Keyed/ModMenu.xml new file mode 100644 index 0000000000..0958e4f8ba --- /dev/null +++ b/Languages/English/Keyed/ModMenu.xml @@ -0,0 +1,37 @@ + + + + + + General + Ammunition + + + + Show shell casings + Firing weapons will display a dropped casing effect. Disable to improve performance. + + Show combat taunts + Pawns will display text-based taunts during combat. + + Allow hunting with melee weapons + Hunters will still be allowed to hunt if they have a melee weapon equipped. + + + + Enable ammunition system + Weapons require ammunition to reload and can use various specialized ammo types.\n\nWARNING: Changing this setting on an existing colony may cause bugs and instability, do so at your own risk. + + Right-click ammo selection + Right-clicking the reload button brings up the ammo selection menu. + + Auto-reload on ammo select + Pawns will automatically reload when a new ammo type is selected. + + Auto-equip ammo + Pawns without loadouts assigned will automatically pick up ammo for their equipped weapon. + + Display weapon caliber + Ammunition-using weapons will have their caliber appended behind their name. + + diff --git a/Languages/English/Keyed/Text.xml b/Languages/English/Keyed/Text.xml deleted file mode 100644 index 91f1edd213..0000000000 --- a/Languages/English/Keyed/Text.xml +++ /dev/null @@ -1,77 +0,0 @@ - - - - (OFF) - Press Shift-Return for configuration - - Achtung! Mod - - Active - This mod can be turned on/off without restarting RimWorld - - Force draft - To draft an undrafted colonist while right-clicking, hold the selected key - - Ignore context menu - To ignore the context menu while positioning colonists, hold the selected key key while right-clicking - - Move colonists relative - To move selected colonists relative to their current position, hold the selected key while right-click-dragging - - Disabled - Alt - Ctrl - Shift - Win/Cmd - - Mental break level for jobs - Set the break level at which a colonist stop a given Achtung job - Ignore - Minor - Major - Almost extreme - Extreme - - Health status for jobs - Set the health status at which a colonist stop a given Achtung job - Ignore - Should be tended now - Medical care - Needs medical rest - In pain shock - - Show Auto Combat positions - If enabled will show auto combat positioning for selected colonists - - {0} was cancelled - {0} is facing an imminent breakdown - {0} is in bad shape - - Clean this room - Cleaning room thoroughly - Clean a room until it is completely clean - Cleaning{0}: {1} - - Fight fire - Fighting a fire - Fights a fire (even outside home zone) - Fighting fire: {0} - - Sow this zone/room - Sowing zone/room - Sow a growing zone or room until it is completely sowed - Sowing{0}: {1} - - Auto combat {0} - Fighting automatically - Fight an enemy or target automatically - Auto combat: {0} - Advancing to {0} - Positioning ({0}) - Shooting at {0} - Hitting {0} - Aiming at {0} - - (Job #{0}) - - \ No newline at end of file diff --git a/Languages/English/Keyed/TextMotes.xml b/Languages/English/Keyed/TextMotes.xml new file mode 100644 index 0000000000..fb99e761d8 --- /dev/null +++ b/Languages/English/Keyed/TextMotes.xml @@ -0,0 +1,9 @@ + + + + Riposted! + Parried! + Knockdown! + Critical hit! + + \ No newline at end of file diff --git a/Languages/English/Strings/NameBanks/SwearLibrary.txt b/Languages/English/Strings/NameBanks/SwearLibrary.txt index 5120877615..fa5fae9ddd 100644 --- a/Languages/English/Strings/NameBanks/SwearLibrary.txt +++ b/Languages/English/Strings/NameBanks/SwearLibrary.txt @@ -3,18 +3,15 @@ Yeehaw, Partytime! Eat dirt! No one will ever find your grave! Shut up and eat my bullets! -You just hung vacancy signs on your asses and my foots looking for a room! -Die, you scum! +You just hung vacancy signs on your asses and my foot's looking for a room! +Die, scum! I will dance on your grave! Usually I am a pacifist, but you asked for it! -I will rip off your leg, and beat you to death with it! -You asshole! +I will rip off your leg and beat you to death with it! I will rip out your entrails! -Don't worry about your widow, I'll comfort her! I'm here to kick ass! Look who's here! Not even your mom will recognize your face! -Hungry? How about a knuckle-sandwich! I will smoke your ass! There can be only one! Are you scared already? @@ -32,23 +29,16 @@ Your number is up! I'm not racist, I kill all kinds of people! Playtime is over! You cry like a sissy! -I will give you some lovin'..up your ass! -I will kill you, resurrect you, and kill you again! Kill them ALL! -Take this, you pig! -You will not survive this , you scum! -Eat shit you apes! -One, two, cheeki breeki! +Take this, pig! +You will not survive this, scum! Don't you dare die yet! I need your skin alive! -Our colony policy is to destroy ALL enemies! Are you bulletproof?! Die already! You can't handle our badassery! -Come out, come out, wherever you are! Pick a direction, and run little piggy! Promise, you'll die quick and painless! I'll smoke you like a chimney! You get a bullet and you get a bullet, everybody gets a bullet! -All your base are belong to us! No one will find your corpse! Yippee Ki Yay motherfucker! We will slice you in little pieces! @@ -63,17 +53,9 @@ I will spill your blood till it rains down from the skies! You know how I said I'll kill you last? I lied. I will show you REAL pain! I'll make it slow..and very painful! -I hope you will all drop dead! -Just a small sacrifice for the greater good! -Justice will be served! Run, little piggy, run! I'm gonna take you to the bank. To the blood bank! I will make you suffer! Barbeque, huh? How do you like your ribs? -Your actions are illogical. All possible outcomes have been calculated. -Have you realized the foolishnes of your actions? -You call that a knife? This is a knife! -Die, you cockroach! Prepare to die! -He laughs best that shoots first! -this is SPARTA! \ No newline at end of file +He laughs best that shoots first! \ No newline at end of file diff --git a/Languages/English/Strings/NameBanks/SwearLibrarySuppressed.txt b/Languages/English/Strings/NameBanks/SwearLibrarySuppressed.txt index ce31292f27..927c1856fe 100644 --- a/Languages/English/Strings/NameBanks/SwearLibrarySuppressed.txt +++ b/Languages/English/Strings/NameBanks/SwearLibrarySuppressed.txt @@ -1,87 +1,21 @@ -Suckers! No regard for human life! -I'm gonna get my ass kicked! -Line up you fools! -Allah-Akbar! -We will never surrender! -And mommy told me there were no monsters! -This is gonna hurt! -That's not what I signed up for! -I'll shove my foot so far up your ass, you gon' choke on my laces! +This is not what I signed up for! I should have stayed home! -I am so mad! A little more lead and I'll turn into a statue! -That was my favourite eye! -Just wait and I will be dancing on your grave! -Aren't YOU a piece of cake? Let me stick a fork in you! -Oh boy! He actually hit me! -I might have lost a lung.... I'm cool! Don't hit me! -You broke my wank-hand you bastard! -Don't kick me! -Can't you train on someone else first? -I_am_fucked.exe initiated... I need a change of underwear! One, two, three...am I still alive? Four, five I hope that's not my spleen there on the floor -Some one get a first aid kit! Or a joint -This is screwed up! -Screw you asshole! -Get your filthy paws off of me! -Well, fuck me! -Bitch you just bought a ticket to hell! -Oh! Look how much blood....I had. -My eye! My precious eye! +This is messed up! Dammit! -Just you wait, I'll give it to you smooth and hard! It's time to study the enemy from afar! -You're gonna pay..oh how you're gonna pay! -They are CRAZY! Its easier to be brave from a distance! -My sheesh, my sheesh! -Have they lost their minds?! -Oh, you scum! -And then? And then I died..haha. My favourite joke! -Come to the door...and you gonna pick your bones off the floor! -Hello to you too! -If you can't listen , you're gonna have to feel! -He that will not hear must feel. -Ey..guys, hurry! -Step on up ladies and gents! -Dont anger the angry white people! Do you even know who I am?! Don't hit me, I'm a certified idiot! People aren't afraid of dying but of loosing their life! -Please don't think I'm just to lazy to carry you myself! -What's that smell?! Oh..that's us. -We swear we're fun guys! -Do I look like I'm greenpeace you vermin? Better to get a bit wet than get a lot dead. -Don't touch me! -Did I explain to you already, what crazy means? This ain't at all like taking candy from a baby! -You're to late! The beer is already all gone! -I was an adventurer..then I took an arrow to the knee Aaaahhhhhh-aaaaaaaahhhh! -We fight or we die! -No retreat, no surrender! -Kill or be killed! -Don't forget: the pin, you pull and the grenade is what you throw! -Does he even realize he's off his meds?! -Stupid bastards! Just went ahead and burned my farm! -Where will my blood spill? -Stay back you vile scum! Oh pleasant fear, oh sweet despair! I hope you all croak! I'm not afraid of anything! Aaaahhh! -Madness will consume you! -This. Is. SPARTAAAA! -I'm still kicking! -All is not lost yet! -Maybe we will die, but at least we have our freedom! -I will rip out your guts, you bastards! -The real war will start tomorrow, with a hangover! -But we used to get along so well! -I hate inept raiders -Mrrrmrrrgml! -Mrgl mrrrgll? -Arrggghhhh! Arrgh aaahhhhh! \ No newline at end of file +I'm still kicking! \ No newline at end of file diff --git a/Languages/Russian/defInjected/StatDefs/Stats_Weapons_Ranged.xml b/Languages/Russian/defInjected/StatDefs/Stats_Weapons_Ranged.xml index 319ae0c220..1c11e1686f 100644 --- a/Languages/Russian/defInjected/StatDefs/Stats_Weapons_Ranged.xml +++ b/Languages/Russian/defInjected/StatDefs/Stats_Weapons_Ranged.xml @@ -1,8 +1,8 @@  - эффективность прицеливания - How efficient the weapon is at leading and range-finding. This is multiplied against the aiming accuracy of the shooter to calculate the amount of range and lead error.\n\nThe final modifier is calculated via this formula:\n(1.5 - aiming accuracy) / aiming efficiency\n\nLead error is calculated by multiplying this factor against total lead distance in cells. Range error is calculated by multiplying it against the total distance to the target divided by 4. + эффективность прицеливания + How efficient the weapon is at leading and range-finding. This is multiplied against the aiming accuracy of the shooter to calculate the amount of range and lead error.\n\nThe final modifier is calculated via this formula:\n(1.5 - aiming accuracy) / aiming efficiency\n\nLead error is calculated by multiplying this factor against total lead distance in cells. Range error is calculated by multiplying it against the total distance to the target divided by 4. разброс Разброс - это присущая оружию неточность, при котором пули имеют некоторое случайное коническое отклонение, которое не зависит от мастерства. diff --git a/Patches/Core/Bodies/Bodies_Animal_Bird/Bodies_Animal_Bird.xml b/Patches/Core/Bodies/Bodies_Animal_Bird/Bodies_Animal_Bird.xml new file mode 100644 index 0000000000..38afd2681e --- /dev/null +++ b/Patches/Core/Bodies/Bodies_Animal_Bird/Bodies_Animal_Bird.xml @@ -0,0 +1,124 @@ + + + + + /Defs/BodyDef[defName = "Bird"]/corePart/parts/li[def = "Tail"]/coverage + + 0.03 + + + + + /Defs/BodyDef[defName = "Bird"]/corePart/parts/li[def = "Stomach"]/coverage + + 0.08 + + + + + /Defs/BodyDef[defName = "Bird"]/corePart/parts/li[def = "LeftLung"]/coverage + + 0.1 + + + + + /Defs/BodyDef[defName = "Bird"]/corePart/parts/li[def = "RightLung"]/coverage + + 0.1 + + + + + /Defs/BodyDef[defName = "Bird"]/corePart/parts/li[def = "LeftKidney"]/coverage + + 0.02 + + + + + /Defs/BodyDef[defName = "Bird"]/corePart/parts/li[def = "RightKidney"]/coverage + + 0.02 + + + + + /Defs/BodyDef[defName = "Bird"]/corePart/parts/li[def = "Neck"]/coverage + + 0.1 + + + + + /Defs/BodyDef[defName = "Bird"]/corePart/parts/li[def = "Neck"]/parts/li[def = "Head"]/coverage + + 0.25 + + + + + /Defs/BodyDef[defName = "Bird"]/corePart/parts/li[def = "Neck"]/parts/li[def = "Head"]/parts/li[def = "Skull"]/coverage + + 0.25 + + + + + /Defs/BodyDef[defName = "Bird"]/corePart/parts/li[def = "Neck"]/parts/li[def = "Head"]/parts/li[def = "Skull"]/parts/li[def = "Brain"]/coverage + + 0.9 + + + + + /Defs/BodyDef[defName = "Bird"]/corePart/parts/li[def = "Neck"]/parts/li[def = "Head"]/parts/li[def = "LeftEye"]/coverage + + 0.1 + + + + + /Defs/BodyDef[defName = "Bird"]/corePart/parts/li[def = "Neck"]/parts/li[def = "Head"]/parts/li[def = "RightEye"]/coverage + + 0.1 + + + + + /Defs/BodyDef[defName = "Bird"]/corePart/parts/li[def = "Neck"]/parts/li[def = "Head"]/parts/li[def = "Beak"]/coverage + + 0.4 + + + + + /Defs/BodyDef[defName = "Bird"]/corePart/parts/li[def = "LeftLeg"]/coverage + + 0.17 + + + + + /Defs/BodyDef[defName = "Bird"]/corePart/parts/li[def = "LeftLeg"]/parts/li[def = "LeftFoot"]/coverage + + 0.1 + + + + + /Defs/BodyDef[defName = "Bird"]/corePart/parts/li[def = "RightLeg"]/coverage + + 0.17 + + + + + /Defs/BodyDef[defName = "Bird"]/corePart/parts/li[def = "RightLeg"]/parts/li[def = "RightFoot"]/coverage + + 0.1 + + + + + diff --git a/Patches/Core/Bodies/Bodies_Animal_Insect/Beetlelike.xml b/Patches/Core/Bodies/Bodies_Animal_Insect/Beetlelike.xml new file mode 100644 index 0000000000..ff024d7141 --- /dev/null +++ b/Patches/Core/Bodies/Bodies_Animal_Insect/Beetlelike.xml @@ -0,0 +1,239 @@ + + + + + + + + Always + +
  • + /Defs/BodyDef[defName="BeetleLike"]/corePart/groups + Invert +
  • +
  • + /Defs/BodyDef[defName="BeetleLike"]/corePart + + + +
  • +
    +
    + + + + /Defs/BodyDef[defName="BeetleLike"]/corePart/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + Always + +
  • + /Defs/BodyDef[defName="BeetleLike"]/corePart/parts/li[def = "LeftElytra"]/groups + Invert +
  • +
  • + /Defs/BodyDef[defName="BeetleLike"]/corePart/parts/li[def = "LeftElytra"] + + + +
  • +
    +
    + + + /Defs/BodyDef[defName="BeetleLike"]/corePart/parts/li[def = "LeftElytra"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + Always + +
  • + /Defs/BodyDef[defName="BeetleLike"]/corePart/parts/li[def = "RightElytra"]/groups + Invert +
  • +
  • + /Defs/BodyDef[defName="BeetleLike"]/corePart/parts/li[def = "RightElytra"] + + + +
  • +
    +
    + + + /Defs/BodyDef[defName="BeetleLike"]/corePart/parts/li[def = "RightElytra"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + Always + +
  • + /Defs/BodyDef[defName="BeetleLike"]/corePart/parts/li[def = "Pronotum"]/groups + Invert +
  • +
  • + /Defs/BodyDef[defName="BeetleLike"]/corePart/parts/li[def = "Pronotum"] + + + +
  • +
    +
    + + + /Defs/BodyDef[defName="BeetleLike"]/corePart/parts/li[def = "Pronotum"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /Defs/BodyDef[defName="BeetleLike"]/corePart/parts/li[def = "Pronotum"]/parts/li[def="InsectHead"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + + + Always + +
  • + /Defs/BodyDef[defName = "BeetleLikeWithClaw"]/corePart/groups + Invert +
  • +
  • + /Defs/BodyDef[defName = "BeetleLikeWithClaw"]/corePart + + + +
  • +
    +
    + + + /Defs/BodyDef[defName = "BeetleLikeWithClaw"]/corePart/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + Always + +
  • + /Defs/BodyDef[defName = "BeetleLikeWithClaw"]/corePart/parts/li[def = "LeftElytra"]/groups + Invert +
  • +
  • + /Defs/BodyDef[defName = "BeetleLikeWithClaw"]/corePart/parts/li[def = "LeftElytra"] + + + +
  • +
    +
    + + + /Defs/BodyDef[defName = "BeetleLikeWithClaw"]/corePart/parts/li[def = "LeftElytra"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + Always + +
  • + /Defs/BodyDef[defName = "BeetleLikeWithClaw"]/corePart/parts/li[def = "RightElytra"]/groups + Invert +
  • +
  • + /Defs/BodyDef[defName = "BeetleLikeWithClaw"]/corePart/parts/li[def = "RightElytra"] + + + +
  • +
    +
    + + + /Defs/BodyDef[defName = "BeetleLikeWithClaw"]/corePart/parts/li[def = "RightElytra"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + Always + +
  • + /Defs/BodyDef[defName = "BeetleLikeWithClaw"]/corePart/parts/li[def = "Pronotum"]/groups + Invert +
  • +
  • + /Defs/BodyDef[defName = "BeetleLikeWithClaw"]/corePart/parts/li[def = "Pronotum"] + + + +
  • +
    +
    + + + /Defs/BodyDef[defName = "BeetleLikeWithClaw"]/corePart/parts/li[def = "Pronotum"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + + + /Defs/BodyDef[defName="BeetleLike" or defName="BeetleLikeWithClaw"]/corePart/parts/li[def = "Pronotum"]/coverage + + 0.3 + + + + + /Defs/BodyDef[defName="BeetleLike" or defName="BeetleLikeWithClaw"]/corePart/parts/li[def = "Pronotum"]/parts/li[def="InsectHead"]/parts/li[def = "LeftAntenna"]/coverage + + 0.05 + + + + + /Defs/BodyDef[defName="BeetleLike" or defName="BeetleLikeWithClaw"]/corePart/parts/li[def = "Pronotum"]/parts/li[def="InsectHead"]/parts/li[def = "RightAntenna"]/coverage + + 0.05 + + + + + /Defs/BodyDef[defName="BeetleLike" or defName="BeetleLikeWithClaw"]/corePart/parts/li[def = "Pronotum"]/parts/li[def="InsectHead"]/parts/li[def = "InsectNostril"]/coverage + + 0.1 + + + + + /Defs/BodyDef[defName="BeetleLike" or defName="BeetleLikeWithClaw"]/corePart/parts/li[def = "Pronotum"]/parts/li[def="InsectHead"]/parts/li[def = "InsectMouth"]/coverage + + 0.05 + + + +
    + diff --git a/Patches/Core/Bodies/Bodies_Animal_Quadruped/Monkey.xml b/Patches/Core/Bodies/Bodies_Animal_Quadruped/Monkey.xml new file mode 100644 index 0000000000..89c7c7c5ea --- /dev/null +++ b/Patches/Core/Bodies/Bodies_Animal_Quadruped/Monkey.xml @@ -0,0 +1,101 @@ + + + + + + + + + /BodyDefs/BodyDef[defName = "Monkey"]/corePart/parts/li[def = "LeftClavicle"]/coverage + + 0.005 + + + + + /BodyDefs/BodyDef[defName = "Monkey"]/corePart/parts/li[def = "RightClavicle"]/coverage + + 0.005 + + + + + /BodyDefs/BodyDef[defName = "Monkey"]/corePart/parts/li[def = "Rib"]/coverage + + 0.001 + + + + + /BodyDefs/BodyDef[defName = "Monkey"]/corePart/parts/li[def = "Pelvis"]/coverage + + 0.005 + + + + + /BodyDefs/BodyDef[defName = "Monkey"]/corePart/parts/li[def = "Spine"]/coverage + + 0.02 + + + + + /BodyDefs/BodyDef[defName = "Monkey"]/corePart/parts/li[def = "Stomach"]/coverage + + 0.05 + + + + + /BodyDefs/BodyDef[defName = "Monkey"]/corePart/parts/li[def = "LeftLung"]/coverage + + 0.06 + + + + + /BodyDefs/BodyDef[defName = "Monkey"]/corePart/parts/li[def = "RightLung"]/coverage + + 0.06 + + + + + /BodyDefs/BodyDef[defName = "Monkey"]/corePart/parts/li[def = "LeftKidney"]/coverage + + 0.02 + + + + + /BodyDefs/BodyDef[defName = "Monkey"]/corePart/parts/li[def = "RightKidney"]/coverage + + 0.02 + + + + + /BodyDefs/BodyDef[defName = "Monkey"]/corePart/parts/li[def = "Liver"]/coverage + + 0.05 + + + + + /BodyDefs/BodyDef[defName = "Monkey"]/corePart/parts/li[def = "Neck"]/coverage + + 0.12 + + + + + /BodyDefs/BodyDef[defName = "Monkey"]/corePart/parts/li[def="Neck"]/parts/li[def="Head"]/parts/li[def="Skull"]/parts/li[def = "Brain"]/coverage + + 0.9 + + + + + + diff --git a/Patches/Core/Bodies/Bodies_Animal_Quadruped/QuadrupedAnimalWithClawsTailAndJowl.xml b/Patches/Core/Bodies/Bodies_Animal_Quadruped/QuadrupedAnimalWithClawsTailAndJowl.xml new file mode 100644 index 0000000000..a4c84d77af --- /dev/null +++ b/Patches/Core/Bodies/Bodies_Animal_Quadruped/QuadrupedAnimalWithClawsTailAndJowl.xml @@ -0,0 +1,404 @@ + + + + + + + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def = "Tail"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def = "Tail"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def = "Neck"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def = "Neck"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="Skull"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="Skull"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="AnimalJaw"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="AnimalJaw"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def = "FrontLeftLeg"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def = "FrontLeftLeg"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def = "FrontRightLeg"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def = "FrontRightLeg"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def = "RearLeftLeg"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def = "RearLeftLeg"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def = "RearRightLeg"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def = "RearRightLeg"] + + + +
  • +
    +
    + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def = "Tail"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def = "Neck"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="Skull"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="AnimalJaw"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def = "FrontLeftLeg"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def = "FrontRightLeg"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def = "RearLeftLeg"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def = "RearRightLeg"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def = "Tail"]/coverage + + 0.01 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def = "Spine"]/coverage + + 0.02 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def = "Stomach"]/coverage + + 0.06 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def = "Heart"]/coverage + + 0.04 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def = "LeftLung"]/coverage + + 0.06 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def = "RightLung"]/coverage + + 0.06 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def = "LeftKidney"]/coverage + + 0.015 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def = "RightKidney"]/coverage + + 0.015 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def = "Liver"]/coverage + + 0.05 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def = "Neck"]/coverage + + 0.12 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/coverage + + 0.75 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="Skull"]/coverage + + 0.25 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="Skull"]/parts/li[def = "Brain"]/coverage + + 0.9 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def = "LeftEye"]/coverage + + 0.1 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def = "RightEye"]/coverage + + 0.1 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def = "LeftEar"]/coverage + + 0.05 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def = "RightEar"]/coverage + + 0.05 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="AnimalJaw"]/coverage + + 0.2 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def = "Jowl"]/coverage + + 0.14 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def = "FrontLeftLeg"]/coverage + + 0.1 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def = "FrontRightLeg"]/coverage + + 0.1 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def = "RearLeftLeg"]/coverage + + 0.1 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithClawsTailAndJowl"]/corePart/parts/li[def = "RearRightLeg"]/coverage + + 0.1 + + + +
    + diff --git a/Patches/Core/Bodies/Bodies_Animal_Quadruped/QuadrupedAnimalWithHooves.xml b/Patches/Core/Bodies/Bodies_Animal_Quadruped/QuadrupedAnimalWithHooves.xml new file mode 100644 index 0000000000..86e169b97a --- /dev/null +++ b/Patches/Core/Bodies/Bodies_Animal_Quadruped/QuadrupedAnimalWithHooves.xml @@ -0,0 +1,445 @@ + + + + + + + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def = "Neck"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def = "Neck"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="Skull"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="Skull"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="AnimalJaw"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="AnimalJaw"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def = "FrontLeftLeg"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def = "FrontLeftLeg"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def = "FrontLeftLeg"]/parts/li[def = "FrontLeftHoof"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def = "FrontLeftLeg"]/parts/li[def = "FrontLeftHoof"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def = "FrontRightLeg"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def = "FrontRightLeg"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def = "FrontRightLeg"]/parts/li[def = "FrontRightHoof"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def = "FrontRightLeg"]/parts/li[def = "FrontRightHoof"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def = "RearLeftLeg"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def = "RearLeftLeg"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def = "RearLeftLeg"]/parts/li[def = "RearLeftHoof"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def = "RearLeftLeg"]/parts/li[def = "RearLeftHoof"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def = "RearRightLeg"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def = "RearRightLeg"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def = "RearRightLeg"]/parts/li[def = "RearRightHoof"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def = "RearRightLeg"]/parts/li[def = "RearRightHoof"] + + + +
  • +
    +
    + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def = "Neck"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="Skull"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="AnimalJaw"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def = "FrontLeftLeg"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def = "FrontLeftLeg"]/parts/li[def = "FrontLeftHoof"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def = "FrontRightLeg"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def = "FrontRightLeg"]/parts/li[def = "FrontRightHoof"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def = "RearLeftLeg"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def = "RearLeftLeg"]/parts/li[def = "RearLeftHoof"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def = "RearRightLeg"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def = "RearRightLeg"]/parts/li[def = "RearRightHoof"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def = "Spine"]/coverage + + 0.02 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def = "Stomach"]/coverage + + 0.08 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def = "LeftLung"]/coverage + + 0.08 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def = "RightLung"]/coverage + + 0.08 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def = "LeftKidney"]/coverage + + 0.025 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def = "RightKidney"]/coverage + + 0.025 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def = "Liver"]/coverage + + 0.07 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def = "Neck"]/coverage + + 0.12 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="Skull"]/coverage + + 0.3 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="Skull"]/parts/li[def = "Brain"]/coverage + + 0.9 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def = "LeftEye"]/coverage + + 0.08 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def = "RightEye"]/coverage + + 0.08 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def = "LeftEar"]/coverage + + 0.12 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def = "RightEar"]/coverage + + 0.12 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="AnimalJaw"]/coverage + + 0.2 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def = "FrontLeftLeg"]/parts/li[def = "FrontLeftHoof"]/coverage + + 0.1 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def = "FrontRightLeg"]/parts/li[def = "FrontRightHoof"]/coverage + + 0.1 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def = "RearLeftLeg"]/parts/li[def = "RearLeftHoof"]/coverage + + 0.1 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHooves"]/corePart/parts/li[def = "RearRightLeg"]/parts/li[def = "RearRightHoof"]/coverage + + 0.1 + + + +
    + diff --git a/Patches/Core/Bodies/Bodies_Animal_Quadruped/QuadrupedAnimalWithHoovesAndHorn.xml b/Patches/Core/Bodies/Bodies_Animal_Quadruped/QuadrupedAnimalWithHoovesAndHorn.xml new file mode 100644 index 0000000000..c0b8bf43f9 --- /dev/null +++ b/Patches/Core/Bodies/Bodies_Animal_Quadruped/QuadrupedAnimalWithHoovesAndHorn.xml @@ -0,0 +1,482 @@ + + + + + + + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def = "Neck"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def = "Neck"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="Skull"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="Skull"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="Nose"]/parts/li[def = "Heart"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="Nose"]/parts/li[def = "Heart"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="AnimalJaw"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="AnimalJaw"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def = "FrontLeftLeg"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def = "FrontLeftLeg"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def = "FrontLeftLeg"]/parts/li[def = "FrontLeftHoof"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def = "FrontLeftLeg"]/parts/li[def = "FrontLeftHoof"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def = "FrontRightLeg"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def = "FrontRightLeg"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def = "FrontRightLeg"]/parts/li[def = "FrontRightHoof"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def = "FrontRightLeg"]/parts/li[def = "FrontRightHoof"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def = "RearLeftLeg"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def = "RearLeftLeg"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def = "RearLeftLeg"]/parts/li[def = "RearLeftHoof"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def = "RearLeftLeg"]/parts/li[def = "RearLeftHoof"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def = "RearRightLeg"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def = "RearRightLeg"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def = "RearRightLeg"]/parts/li[def = "RearRightHoof"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def = "RearRightLeg"]/parts/li[def = "RearRightHoof"] + + + +
  • +
    +
    + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def = "Neck"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="Skull"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="Nose"]/parts/li[def = "Horn"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="AnimalJaw"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def = "FrontLeftLeg"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def = "FrontLeftLeg"]/parts/li[def = "FrontLeftHoof"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def = "FrontRightLeg"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def = "FrontRightLeg"]/parts/li[def = "FrontRightHoof"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def = "RearLeftLeg"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def = "RearLeftLeg"]/parts/li[def = "RearLeftHoof"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def = "RearRightLeg"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def = "RearRightLeg"]/parts/li[def = "RearRightHoof"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def = "Spine"]/coverage + + 0.02 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def = "Stomach"]/coverage + + 0.08 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def = "LeftLung"]/coverage + + 0.08 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def = "RightLung"]/coverage + + 0.08 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def = "LeftKidney"]/coverage + + 0.025 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def = "RightKidney"]/coverage + + 0.025 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def = "Liver"]/coverage + + 0.07 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def = "Neck"]/coverage + + 0.12 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/coverage + + 0.75 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="Skull"]/coverage + + 0.3 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="Skull"]/parts/li[def = "Brain"]/coverage + + 0.9 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def = "LeftEye"]/coverage + + 0.05 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def = "RightEye"]/coverage + + 0.05 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def = "LeftEar"]/coverage + + 0.05 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def = "RightEar"]/coverage + + 0.05 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def = "Nose"]/coverage + + 0.29 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="AnimalJaw"]/coverage + + 0.2 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def = "FrontLeftLeg"]/parts/li[def = "FrontLeftHoof"]/coverage + + 0.1 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def = "FrontRightLeg"]/parts/li[def = "FrontRightHoof"]/coverage + + 0.1 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def = "RearLeftLeg"]/parts/li[def = "RearLeftHoof"]/coverage + + 0.1 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHorn"]/corePart/parts/li[def = "RearRightLeg"]/parts/li[def = "RearRightHoof"]/coverage + + 0.1 + + + +
    + diff --git a/Patches/Core/Bodies/Bodies_Animal_Quadruped/QuadrupedAnimalWithHoovesAndHump.xml b/Patches/Core/Bodies/Bodies_Animal_Quadruped/QuadrupedAnimalWithHoovesAndHump.xml new file mode 100644 index 0000000000..936abc368c --- /dev/null +++ b/Patches/Core/Bodies/Bodies_Animal_Quadruped/QuadrupedAnimalWithHoovesAndHump.xml @@ -0,0 +1,461 @@ + + + + + + + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def = "Hump"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def = "Hump"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def = "Neck"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def = "Neck"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="Skull"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="Skull"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="AnimalJaw"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="AnimalJaw"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def = "FrontLeftLeg"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def = "FrontLeftLeg"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def = "FrontLeftLeg"]/parts/li[def = "FrontLeftHoof"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def = "FrontLeftLeg"]/parts/li[def = "FrontLeftHoof"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def = "FrontRightLeg"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def = "FrontRightLeg"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def = "FrontRightLeg"]/parts/li[def = "FrontRightHoof"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def = "FrontRightLeg"]/parts/li[def = "FrontRightHoof"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def = "RearLeftLeg"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def = "RearLeftLeg"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def = "RearLeftLeg"]/parts/li[def = "RearLeftHoof"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def = "RearLeftLeg"]/parts/li[def = "RearLeftHoof"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def = "RearRightLeg"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def = "RearRightLeg"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def = "RearRightLeg"]/parts/li[def = "RearRightHoof"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def = "RearRightLeg"]/parts/li[def = "RearRightHoof"] + + + +
  • +
    +
    + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def = "Hump"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def = "Neck"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="Skull"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="AnimalJaw"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def = "FrontLeftLeg"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def = "FrontLeftLeg"]/parts/li[def = "FrontLeftHoof"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def = "FrontRightLeg"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def = "FrontRightLeg"]/parts/li[def = "FrontRightHoof"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def = "RearLeftLeg"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def = "RearLeftLeg"]/parts/li[def = "RearLeftHoof"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def = "RearRightLeg"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def = "RearRightLeg"]/parts/li[def = "RearRightHoof"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def = "Spine"]/coverage + + 0.02 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def = "Stomach"]/coverage + + 0.07 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def = "LeftLung"]/coverage + + 0.07 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def = "RightLung"]/coverage + + 0.07 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def = "LeftKidney"]/coverage + + 0.02 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def = "RightKidney"]/coverage + + 0.02 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def = "Liver"]/coverage + + 0.07 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def = "Neck"]/coverage + + 0.12 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="Skull"]/coverage + + 0.3 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="Skull"]/parts/li[def = "Brain"]/coverage + + 0.9 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def = "LeftEye"]/coverage + + 0.08 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def = "RightEye"]/coverage + + 0.08 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def = "LeftEar"]/coverage + + 0.12 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def = "RightEar"]/coverage + + 0.12 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def = "FrontLeftLeg"]/parts/li[def = "FrontLeftHoof"]/coverage + + 0.1 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def = "FrontRightLeg"]/parts/li[def = "FrontRightHoof"]/coverage + + 0.1 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def = "RearLeftLeg"]/parts/li[def = "RearLeftHoof"]/coverage + + 0.1 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndHump"]/corePart/parts/li[def = "RearRightLeg"]/parts/li[def = "RearRightHoof"]/coverage + + 0.1 + + + +
    + diff --git a/Patches/Core/Bodies/Bodies_Animal_Quadruped/QuadrupedAnimalWithHoovesAndTusks.xml b/Patches/Core/Bodies/Bodies_Animal_Quadruped/QuadrupedAnimalWithHoovesAndTusks.xml new file mode 100644 index 0000000000..e56740d721 --- /dev/null +++ b/Patches/Core/Bodies/Bodies_Animal_Quadruped/QuadrupedAnimalWithHoovesAndTusks.xml @@ -0,0 +1,459 @@ + + + + + + + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def = "Neck"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def = "Neck"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="Skull"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="Skull"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="AnimalJaw"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="AnimalJaw"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def = "FrontLeftLeg"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def = "FrontLeftLeg"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def = "FrontLeftLeg"]/parts/li[def = "FrontLeftHoof"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def = "FrontLeftLeg"]/parts/li[def = "FrontLeftHoof"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def = "FrontRightLeg"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def = "FrontRightLeg"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def = "FrontRightLeg"]/parts/li[def = "FrontRightHoof"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def = "FrontRightLeg"]/parts/li[def = "FrontRightHoof"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def = "RearLeftLeg"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def = "RearLeftLeg"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def = "RearLeftLeg"]/parts/li[def = "RearLeftHoof"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def = "RearLeftLeg"]/parts/li[def = "RearLeftHoof"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def = "RearRightLeg"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def = "RearRightLeg"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def = "RearRightLeg"]/parts/li[def = "RearRightHoof"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def = "RearRightLeg"]/parts/li[def = "RearRightHoof"] + + + +
  • +
    +
    + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def = "Neck"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="Skull"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="AnimalJaw"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def = "FrontLeftLeg"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def = "FrontLeftLeg"]/parts/li[def = "FrontLeftHoof"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def = "FrontRightLeg"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def = "FrontRightLeg"]/parts/li[def = "FrontRightHoof"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def = "RearLeftLeg"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def = "RearLeftLeg"]/parts/li[def = "RearLeftHoof"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def = "RearRightLeg"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def = "RearRightLeg"]/parts/li[def = "RearRightHoof"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def = "Spine"]/coverage + + 0.02 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def = "Stomach"]/coverage + + 0.08 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def = "LeftLung"]/coverage + + 0.08 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def = "RightLung"]/coverage + + 0.08 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def = "LeftKidney"]/coverage + + 0.025 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def = "RightKidney"]/coverage + + 0.025 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def = "Liver"]/coverage + + 0.07 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def = "Neck"]/coverage + + 0.12 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="Skull"]/coverage + + 0.3 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="Skull"]/parts/li[def = "Brain"]/coverage + + 0.9 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def = "LeftEye"]/coverage + + 0.08 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def = "RightEye"]/coverage + + 0.08 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def = "LeftEar"]/coverage + + 0.1 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def = "RightEar"]/coverage + + 0.1 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="AnimalJaw"]/coverage + + 0.24 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="AnimalJaw"]/parts/li[def = "LeftTusk"]/coverage + + 0.25 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="AnimalJaw"]/parts/li[def = "RightTusk"]/coverage + + 0.25 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def = "FrontLeftLeg"]/parts/li[def = "FrontLeftHoof"]/coverage + + 0.1 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def = "FrontRightLeg"]/parts/li[def = "FrontRightHoof"]/coverage + + 0.1 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def = "RearLeftLeg"]/parts/li[def = "RearLeftHoof"]/coverage + + 0.1 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesAndTusks"]/corePart/parts/li[def = "RearRightLeg"]/parts/li[def = "RearRightHoof"]/coverage + + 0.1 + + + +
    + diff --git a/Patches/Core/Bodies/Bodies_Animal_Quadruped/QuadrupedAnimalWithHoovesTusksAndTrunk.xml b/Patches/Core/Bodies/Bodies_Animal_Quadruped/QuadrupedAnimalWithHoovesTusksAndTrunk.xml new file mode 100644 index 0000000000..7b2f699d84 --- /dev/null +++ b/Patches/Core/Bodies/Bodies_Animal_Quadruped/QuadrupedAnimalWithHoovesTusksAndTrunk.xml @@ -0,0 +1,473 @@ + + + + + + + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def = "Neck"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def = "Neck"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="Skull"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="Skull"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="AnimalJaw"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="AnimalJaw"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def = "FrontLeftLeg"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def = "FrontLeftLeg"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def = "FrontLeftLeg"]/parts/li[def = "FrontLeftHoof"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def = "FrontLeftLeg"]/parts/li[def = "FrontLeftHoof"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def = "FrontRightLeg"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def = "FrontRightLeg"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def = "FrontRightLeg"]/parts/li[def = "FrontRightHoof"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def = "FrontRightLeg"]/parts/li[def = "FrontRightHoof"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def = "RearLeftLeg"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def = "RearLeftLeg"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def = "RearLeftLeg"]/parts/li[def = "RearLeftHoof"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def = "RearLeftLeg"]/parts/li[def = "RearLeftHoof"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def = "RearRightLeg"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def = "RearRightLeg"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def = "RearRightLeg"]/parts/li[def = "RearRightHoof"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def = "RearRightLeg"]/parts/li[def = "RearRightHoof"] + + + +
  • +
    +
    + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def = "Neck"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="Skull"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="AnimalJaw"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def = "FrontLeftLeg"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def = "FrontLeftLeg"]/parts/li[def = "FrontLeftHoof"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def = "FrontRightLeg"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def = "FrontRightLeg"]/parts/li[def = "FrontRightHoof"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def = "RearLeftLeg"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def = "RearLeftLeg"]/parts/li[def = "RearLeftHoof"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def = "RearRightLeg"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def = "RearRightLeg"]/parts/li[def = "RearRightHoof"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def = "Spine"]/coverage + + 0.02 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def = "Stomach"]/coverage + + 0.08 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def = "LeftLung"]/coverage + + 0.08 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def = "RightLung"]/coverage + + 0.08 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def = "LeftKidney"]/coverage + + 0.025 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def = "RightKidney"]/coverage + + 0.025 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def = "Liver"]/coverage + + 0.07 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def = "Neck"]/coverage + + 0.12 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/coverage + + 0.75 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="Skull"]/coverage + + 0.25 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="Skull"]/parts/li[def = "Brain"]/coverage + + 0.9 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def = "LeftEye"]/coverage + + 0.05 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def = "RightEye"]/coverage + + 0.05 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def = "LeftEar"]/coverage + + 0.15 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def = "RightEar"]/coverage + + 0.15 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def = "Trunk"]/coverage + + 0.14 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="AnimalJaw"]/coverage + + 0.2 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="AnimalJaw"]/parts/li[def = "LeftTusk"]/coverage + + 0.25 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="AnimalJaw"]/parts/li[def = "RightTusk"]/coverage + + 0.25 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def = "FrontLeftLeg"]/parts/li[def = "FrontLeftHoof"]/coverage + + 0.1 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def = "FrontRightLeg"]/parts/li[def = "FrontRightHoof"]/coverage + + 0.1 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def = "RearLeftLeg"]/parts/li[def = "RearLeftHoof"]/coverage + + 0.1 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithHoovesTusksAndTrunk"]/corePart/parts/li[def = "RearRightLeg"]/parts/li[def = "RearRightHoof"]/coverage + + 0.1 + + + +
    + diff --git a/Patches/Core/Bodies/Bodies_Animal_Quadruped/QuadrupedAnimalWithPaws.xml b/Patches/Core/Bodies/Bodies_Animal_Quadruped/QuadrupedAnimalWithPaws.xml new file mode 100644 index 0000000000..56dae81de1 --- /dev/null +++ b/Patches/Core/Bodies/Bodies_Animal_Quadruped/QuadrupedAnimalWithPaws.xml @@ -0,0 +1,445 @@ + + + + + + + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def = "Neck"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def = "Neck"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="Skull"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="Skull"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="AnimalJaw"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="AnimalJaw"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def = "FrontLeftLeg"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def = "FrontLeftLeg"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def = "FrontLeftLeg"]/parts/li[def = "FrontLeftPaw"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def = "FrontLeftLeg"]/parts/li[def = "FrontLeftPaw"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def = "FrontRightLeg"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def = "FrontRightLeg"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def = "FrontRightLeg"]/parts/li[def = "FrontRightPaw"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def = "FrontRightLeg"]/parts/li[def = "FrontRightPaw"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def = "RearLeftLeg"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def = "RearLeftLeg"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def = "RearLeftLeg"]/parts/li[def = "RearLeftPaw"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def = "RearLeftLeg"]/parts/li[def = "RearLeftPaw"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def = "RearRightLeg"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def = "RearRightLeg"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def = "RearRightLeg"]/parts/li[def = "RearRightPaw"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def = "RearRightLeg"]/parts/li[def = "RearRightPaw"] + + + +
  • +
    +
    + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def = "Neck"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="Skull"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="AnimalJaw"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def = "FrontLeftLeg"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def = "FrontLeftLeg"]/parts/li[def = "FrontLeftPaw"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def = "FrontRightLeg"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def = "FrontRightLeg"]/parts/li[def = "FrontRightPaw"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def = "RearLeftLeg"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def = "RearLeftLeg"]/parts/li[def = "RearLeftPaw"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def = "RearRightLeg"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def = "RearRightLeg"]/parts/li[def = "RearRightPaw"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def = "Spine"]/coverage + + 0.02 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def = "Stomach"]/coverage + + 0.08 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def = "LeftLung"]/coverage + + 0.08 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def = "RightLung"]/coverage + + 0.08 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def = "LeftKidney"]/coverage + + 0.025 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def = "RightKidney"]/coverage + + 0.025 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def = "Liver"]/coverage + + 0.07 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def = "Neck"]/coverage + + 0.12 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="Skull"]/coverage + + 0.3 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="Skull"]/parts/li[def = "Brain"]/coverage + + 0.9 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def = "LeftEye"]/coverage + + 0.08 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def = "RightEye"]/coverage + + 0.08 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def = "LeftEar"]/coverage + + 0.12 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def = "RightEar"]/coverage + + 0.12 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="AnimalJaw"]/coverage + + 0.2 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def = "FrontLeftLeg"]/parts/li[def = "FrontLeftPaw"]/coverage + + 0.1 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def = "FrontRightLeg"]/parts/li[def = "FrontRightPaw"]/coverage + + 0.1 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def = "RearLeftLeg"]/parts/li[def = "RearLeftPaw"]/coverage + + 0.1 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPaws"]/corePart/parts/li[def = "RearRightLeg"]/parts/li[def = "RearRightPaw"]/coverage + + 0.1 + + + +
    + diff --git a/Patches/Core/Bodies/Bodies_Animal_Quadruped/QuadrupedAnimalWithPawsAndTail.xml b/Patches/Core/Bodies/Bodies_Animal_Quadruped/QuadrupedAnimalWithPawsAndTail.xml new file mode 100644 index 0000000000..fd04775fc4 --- /dev/null +++ b/Patches/Core/Bodies/Bodies_Animal_Quadruped/QuadrupedAnimalWithPawsAndTail.xml @@ -0,0 +1,452 @@ + + + + + + + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def = "Neck"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def = "Neck"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="Skull"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="Skull"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="AnimalJaw"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="AnimalJaw"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def = "FrontLeftLeg"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def = "FrontLeftLeg"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def = "FrontLeftLeg"]/parts/li[def = "FrontLeftPaw"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def = "FrontLeftLeg"]/parts/li[def = "FrontLeftPaw"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def = "FrontRightLeg"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def = "FrontRightLeg"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def = "FrontRightLeg"]/parts/li[def = "FrontRightPaw"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def = "FrontRightLeg"]/parts/li[def = "FrontRightPaw"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def = "RearLeftLeg"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def = "RearLeftLeg"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def = "RearLeftLeg"]/parts/li[def = "RearLeftPaw"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def = "RearLeftLeg"]/parts/li[def = "RearLeftPaw"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def = "RearRightLeg"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def = "RearRightLeg"] + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def = "RearRightLeg"]/parts/li[def = "RearRightPaw"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def = "RearRightLeg"]/parts/li[def = "RearRightPaw"] + + + +
  • +
    +
    + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def = "Neck"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="Skull"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="AnimalJaw"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def = "FrontLeftLeg"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def = "FrontLeftLeg"]/parts/li[def = "FrontLeftPaw"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def = "FrontRightLeg"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def = "FrontRightLeg"]/parts/li[def = "FrontRightPaw"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def = "RearLeftLeg"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def = "RearLeftLeg"]/parts/li[def = "RearLeftPaw"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def = "RearRightLeg"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def = "RearRightLeg"]/parts/li[def = "RearRightPaw"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def = "Tail"]/coverage + + 0.02 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def = "Spine"]/coverage + + 0.02 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def = "Stomach"]/coverage + + 0.08 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def = "LeftLung"]/coverage + + 0.08 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def = "RightLung"]/coverage + + 0.08 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def = "LeftKidney"]/coverage + + 0.025 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def = "RightKidney"]/coverage + + 0.025 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def = "Liver"]/coverage + + 0.07 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def = "Neck"]/coverage + + 0.12 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="Skull"]/coverage + + 0.3 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="Skull"]/parts/li[def = "Brain"]/coverage + + 0.9 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def = "LeftEye"]/coverage + + 0.08 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def = "RightEye"]/coverage + + 0.08 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def = "LeftEar"]/coverage + + 0.12 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def = "RightEar"]/coverage + + 0.12 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def="Neck"]/parts/li[def = "Head"]/parts/li[def="AnimalJaw"]/coverage + + 0.2 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def = "FrontLeftLeg"]/parts/li[def = "FrontLeftPaw"]/coverage + + 0.1 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def = "FrontRightLeg"]/parts/li[def = "FrontRightPaw"]/coverage + + 0.1 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def = "RearLeftLeg"]/parts/li[def = "RearLeftPaw"]/coverage + + 0.1 + + + + + /BodyDefs/BodyDef[defName = "QuadrupedAnimalWithPawsAndTail"]/corePart/parts/li[def = "RearRightLeg"]/parts/li[def = "RearRightPaw"]/coverage + + 0.1 + + + +
    + diff --git a/Patches/Core/Bodies/Bodies_Animal_Quadruped/TurtleLike.xml b/Patches/Core/Bodies/Bodies_Animal_Quadruped/TurtleLike.xml new file mode 100644 index 0000000000..a799830a61 --- /dev/null +++ b/Patches/Core/Bodies/Bodies_Animal_Quadruped/TurtleLike.xml @@ -0,0 +1,122 @@ + + + + + + + + + Always + +
  • + /BodyDefs/BodyDef[defName = "TurtleLike"]/corePart/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "TurtleLike"]/corePart + + + +
  • +
    +
    + + + Always + +
  • + /BodyDefs/BodyDef[defName = "TurtleLike"]/corePart/parts/li[def = "Plastron"]/groups + Invert +
  • +
  • + /BodyDefs/BodyDef[defName = "TurtleLike"]/corePart/parts/li[def = "Plastron"] + + + +
  • +
    +
    + + + + + /BodyDefs/BodyDef[defName = "TurtleLike"]/corePart/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /BodyDefs/BodyDef[defName = "TurtleLike"]/corePart/parts/li[def = "Plastron"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + + + /BodyDefs/BodyDef[defName = "TurtleLike"]/corePart/parts/li[def = "Plastron"]/coverage + + 0.05 + + + + + /BodyDefs/BodyDef[defName = "TurtleLike"]/corePart/parts/li[def = "Spine"]/coverage + + 0.03 + + + + + /BodyDefs/BodyDef[defName = "TurtleLike"]/corePart/parts/li[def = "Stomach"]/coverage + + 0.08 + + + + + /BodyDefs/BodyDef[defName = "TurtleLike"]/corePart/parts/li[def = "LeftLung"]/coverage + + 0.1 + + + + + /BodyDefs/BodyDef[defName = "TurtleLike"]/corePart/parts/li[def = "RightLung"]/coverage + + 0.1 + + + + + /BodyDefs/BodyDef[defName = "TurtleLike"]/corePart/parts/li[def = "LeftKidney"]/coverage + + 0.06 + + + + + /BodyDefs/BodyDef[defName = "TurtleLike"]/corePart/parts/li[def = "RightKidney"]/coverage + + 0.06 + + + + + /BodyDefs/BodyDef[defName = "TurtleLike"]/corePart/parts/li[def = "Liver"]/coverage + + 0.06 + + + + + /BodyDefs/BodyDef[defName = "TurtleLike"]/corePart/parts/li[def = "Head"]/coverage + + 0.07 + + + +
    + diff --git a/Patches/Core/Bodies/Bodies_Humanlike/Human.xml b/Patches/Core/Bodies/Bodies_Humanlike/Human.xml new file mode 100644 index 0000000000..6ba92c268e --- /dev/null +++ b/Patches/Core/Bodies/Bodies_Humanlike/Human.xml @@ -0,0 +1,234 @@ + + + + + + + + + /Defs/BodyDef[defName = "Human"]/corePart/parts/li[def = "Rib"]/coverage + + 0.001 + + + + + /Defs/BodyDef[defName = "Human"]/corePart/parts/li[def = "Pelvis"]/coverage + + 0.05 + + + + + /Defs/BodyDef[defName = "Human"]/corePart/parts/li[def = "Stomach"]/coverage + + 0.05 + + + + + /Defs/BodyDef[defName = "Human"]/corePart/parts/li[def = "Heart"]/coverage + + 0.04 + + + + + /Defs/BodyDef[defName = "Human"]/corePart/parts/li[def = "LeftLung"]/coverage + + 0.055 + + + + + /Defs/BodyDef[defName = "Human"]/corePart/parts/li[def = "RightLung"]/coverage + + 0.055 + + + + + /Defs/BodyDef[defName = "Human"]/corePart/parts/li[def = "LeftKidney"]/coverage + + 0.03 + + + + + /Defs/BodyDef[defName = "Human"]/corePart/parts/li[def = "RightKidney"]/coverage + + 0.03 + + + + + /Defs/BodyDef[defName = "Human"]/corePart/parts/li[def = "Liver"]/coverage + + 0.06 + + + + + /Defs/BodyDef[defName = "Human"]/corePart/parts/li[def = "Neck"]/coverage + + 0.055 + + + + + /Defs/BodyDef[defName = "Human"]/corePart/parts/li[def="Neck"]/parts/li[def="Head"]/parts/li[def="Skull"]/parts/li[def = "Brain"]/coverage + + 0.9 + + + + + /Defs/BodyDef[defName = "Human"]/corePart/parts/li[def="Neck"]/parts/li[def="Head"]/parts/li[def = "LeftEye"]/coverage + + 0.05 + + + + + /Defs/BodyDef[defName = "Human"]/corePart/parts/li[def="Neck"]/parts/li[def="Head"]/parts/li[def = "RightEye"]/coverage + + 0.05 + + + + + /Defs/BodyDef[defName = "Human"]/corePart/parts/li[def="Neck"]/parts/li[def="Head"]/parts/li[def = "LeftEar"]/coverage + + 0.05 + + + + + /Defs/BodyDef[defName = "Human"]/corePart/parts/li[def="Neck"]/parts/li[def="Head"]/parts/li[def = "RightEar"]/coverage + + 0.05 + + + + + /Defs/BodyDef[defName = "Human"]/corePart/parts/li[def="Neck"]/parts/li[def="Head"]/parts/li[def = "Nose"]/coverage + + 0.08 + + + + + /Defs/BodyDef[defName = "Human"]/corePart/parts/li[def = "LeftShoulder"]/coverage + + 0.085 + + + + + /Defs/BodyDef[defName = "Human"]/corePart/parts/li[def="LeftShoulder"]/parts/li[def = "LeftClavicle"]/coverage + + 0.06 + + + + + /Defs/BodyDef[defName = "Human"]/corePart/parts/li[def="LeftShoulder"]/parts/li[def = "LeftArm"]/parts/li[def="LeftHumerus"]/coverage + + 0.15 + + + + + /Defs/BodyDef[defName = "Human"]/corePart/parts/li[def="LeftShoulder"]/parts/li[def = "LeftArm"]/parts/li[def="LeftRadius"]/coverage + + 0.15 + + + + + /Defs/BodyDef[defName = "Human"]/corePart/parts/li[def = "RightShoulder"]/coverage + + 0.085 + + + + + /Defs/BodyDef[defName = "Human"]/corePart/parts/li[def="RightShoulder"]/parts/li[def = "RightClavicle"]/coverage + + 0.06 + + + + + /Defs/BodyDef[defName = "Human"]/corePart/parts/li[def="RightShoulder"]/parts/li[def = "RightArm"]/parts/li[def="RightHumerus"]/coverage + + 0.15 + + + + + /Defs/BodyDef[defName = "Human"]/corePart/parts/li[def="RightShoulder"]/parts/li[def = "RightArm"]/parts/li[def="RightRadius"]/coverage + + 0.15 + + + + + /Defs/BodyDef[defName = "Human"]/corePart/parts/li[def = "LeftLeg"]/coverage + + 0.1 + + + + + /Defs/BodyDef[defName = "Human"]/corePart/parts/li[def = "LeftLeg"]/parts/li[def="LeftFemur"]/coverage + + 0.15 + + + + + /Defs/BodyDef[defName = "Human"]/corePart/parts/li[def = "LeftLeg"]/parts/li[def="LeftTibia"]/coverage + + 0.15 + + + + + /Defs/BodyDef[defName = "Human"]/corePart/parts/li[def = "LeftLeg"]/parts/li[def="LeftFoot"]/coverage + + 0.1 + + + + + /Defs/BodyDef[defName = "Human"]/corePart/parts/li[def = "RightLeg"]/coverage + + 0.1 + + + + + /Defs/BodyDef[defName = "Human"]/corePart/parts/li[def = "RightLeg"]/parts/li[def="RightFemur"]/coverage + + 0.15 + + + + + /Defs/BodyDef[defName = "Human"]/corePart/parts/li[def = "RightLeg"]/parts/li[def="RightTibia"]/coverage + + 0.15 + + + + + /Defs/BodyDef[defName = "Human"]/corePart/parts/li[def = "RightLeg"]/parts/li[def="RightFoot"]/coverage + + 0.1 + + + + + + diff --git a/Patches/Core/Bodies/Bodies_Mechanoid/MechanicalCentipede.xml b/Patches/Core/Bodies/Bodies_Mechanoid/MechanicalCentipede.xml new file mode 100644 index 0000000000..b6e8e43979 --- /dev/null +++ b/Patches/Core/Bodies/Bodies_Mechanoid/MechanicalCentipede.xml @@ -0,0 +1,317 @@ + + + + + + + + + Always + +
  • + /Defs/BodyDef[defName = "MechanicalCentipede"]/corePart/groups + Invert +
  • +
  • + /Defs/BodyDef[defName = "MechanicalCentipede"]/corePart + + + +
  • +
    +
    + + + Always + +
  • + /Defs/BodyDef[defName = "MechanicalCentipede"]/corePart/parts/li[def = "MechanicalHead"]/groups + Invert +
  • +
  • + /Defs/BodyDef[defName = "MechanicalCentipede"]/corePart/parts/li[def = "MechanicalHead"] + + + +
  • +
    +
    + + + Always + +
  • + /Defs/BodyDef[defName = "MechanicalCentipede"]/corePart/parts/li[def = "MechanicalCentipedeBodySecondRing"]/groups + Invert +
  • +
  • + /Defs/BodyDef[defName = "MechanicalCentipede"]/corePart/parts/li[def = "MechanicalCentipedeBodySecondRing"] + + + +
  • +
    +
    + + + Always + +
  • + /Defs/BodyDef[defName = "MechanicalCentipede"]/corePart/parts/li[def="MechanicalCentipedeBodySecondRing"]/parts/li[def = "MechanicalCentipedeBodyThirdRing"]/groups + Invert +
  • +
  • + /Defs/BodyDef[defName = "MechanicalCentipede"]/corePart/parts/li[def="MechanicalCentipedeBodySecondRing"]/parts/li[def = "MechanicalCentipedeBodyThirdRing"] + + + +
  • +
    +
    + + + Always + +
  • + /Defs/BodyDef[defName = "MechanicalCentipede"]/corePart/parts/li[def="MechanicalCentipedeBodySecondRing"]/parts/li[def = "MechanicalCentipedeBodyThirdRing"]/parts/li[def = "MechanicalCentipedeBodyFourthRing"]/groups + Invert +
  • +
  • + /Defs/BodyDef[defName = "MechanicalCentipede"]/corePart/parts/li[def="MechanicalCentipedeBodySecondRing"]/parts/li[def = "MechanicalCentipedeBodyThirdRing"]/parts/li[def = "MechanicalCentipedeBodyFourthRing"] + + + +
  • +
    +
    + + + Always + +
  • + /Defs/BodyDef[defName = "MechanicalCentipede"]/corePart/parts/li[def="MechanicalCentipedeBodySecondRing"]/parts/li[def = "MechanicalCentipedeBodyThirdRing"]/parts/li[def = "MechanicalCentipedeBodyFourthRing"]/parts/li[def = "MechanicalCentipedeBodyFifthRing"]/groups + Invert +
  • +
  • + /Defs/BodyDef[defName = "MechanicalCentipede"]/corePart/parts/li[def="MechanicalCentipedeBodySecondRing"]/parts/li[def = "MechanicalCentipedeBodyThirdRing"]/parts/li[def = "MechanicalCentipedeBodyFourthRing"]/parts/li[def = "MechanicalCentipedeBodyFifthRing"] + + + +
  • +
    +
    + + + Always + +
  • + /Defs/BodyDef[defName = "MechanicalCentipede"]/corePart/parts/li[def="MechanicalCentipedeBodySecondRing"]/parts/li[def = "MechanicalCentipedeBodyThirdRing"]/parts/li[def = "MechanicalCentipedeBodyFourthRing"]/parts/li[def = "MechanicalCentipedeBodyFifthRing"]/parts/li[def = "MechanicalCentipedeBodySixthRing"]/groups + Invert +
  • +
  • + /Defs/BodyDef[defName = "MechanicalCentipede"]/corePart/parts/li[def="MechanicalCentipedeBodySecondRing"]/parts/li[def = "MechanicalCentipedeBodyThirdRing"]/parts/li[def = "MechanicalCentipedeBodyFourthRing"]/parts/li[def = "MechanicalCentipedeBodyFifthRing"]/parts/li[def = "MechanicalCentipedeBodySixthRing"] + + + +
  • +
    +
    + + + + + /Defs/BodyDef[defName = "MechanicalCentipede"]/corePart/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /Defs/BodyDef[defName = "MechanicalCentipede"]/corePart/parts/li[def = "MechanicalHead"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /Defs/BodyDef[defName = "MechanicalCentipede"]/corePart/parts/li[def = "MechanicalCentipedeBodySecondRing"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /Defs/BodyDef[defName = "MechanicalCentipede"]/corePart/parts/li[def="MechanicalCentipedeBodySecondRing"]/parts/li[def = "MechanicalCentipedeBodyThirdRing"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /Defs/BodyDef[defName = "MechanicalCentipede"]/corePart/parts/li[def="MechanicalCentipedeBodySecondRing"]/parts/li[def = "MechanicalCentipedeBodyThirdRing"]/parts/li[def = "MechanicalCentipedeBodyFourthRing"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /Defs/BodyDef[defName = "MechanicalCentipede"]/corePart/parts/li[def="MechanicalCentipedeBodySecondRing"]/parts/li[def = "MechanicalCentipedeBodyThirdRing"]/parts/li[def = "MechanicalCentipedeBodyFourthRing"]/parts/li[def = "MechanicalCentipedeBodyFifthRing"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /Defs/BodyDef[defName = "MechanicalCentipede"]/corePart/parts/li[def="MechanicalCentipedeBodySecondRing"]/parts/li[def = "MechanicalCentipedeBodyThirdRing"]/parts/li[def = "MechanicalCentipedeBodyFourthRing"]/parts/li[def = "MechanicalCentipedeBodyFifthRing"]/parts/li[def = "MechanicalCentipedeBodySixthRing"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + + + /Defs/BodyDef[defName = "MechanicalCentipede"]/corePart/parts/li[def = "MechanicalHead"]/coverage + + 0.08 + + + + + /Defs/BodyDef[defName = "MechanicalCentipede"]/corePart/parts/li[def = "MechanicalHead"]/parts/li[def = "LeftSightSensor"]/coverage + + 0.15 + + + + + /Defs/BodyDef[defName = "MechanicalCentipede"]/corePart/parts/li[def = "MechanicalHead"]/parts/li[def = "RightSightSensor"]/coverage + + 0.15 + + + + + /Defs/BodyDef[defName = "MechanicalCentipede"]/corePart/parts/li[def = "MechanicalHead"]/parts/li[def = "LeftHearingSensor"]/coverage + + 0.05 + + + + + /Defs/BodyDef[defName = "MechanicalCentipede"]/corePart/parts/li[def = "MechanicalHead"]/parts/li[def = "RightHearingSensor"]/coverage + + 0.05 + + + + + /Defs/BodyDef[defName = "MechanicalCentipede"]/corePart/parts/li[def = "MechanicalHead"]/parts/li[def = "SmellSensor"]/coverage + + 0.05 + + + + + + + /Defs/BodyDef[defName = "MechanicalCentipede"]/corePart/parts + +
  • + MechanicalPrimaryCapacitor + 0.0875 + Inside +
  • +
    +
    + + + /Defs/BodyDef[defName = "MechanicalCentipede"]/corePart/parts/li[def = "MechanicalCentipedeBodySecondRing"]/parts + +
  • + MechanicalWeaponActuator + 0.05 + Inside +
  • +
    +
    + + + /Defs/BodyDef[defName = "MechanicalCentipede"]/corePart/parts/li[def = "MechanicalCentipedeBodySecondRing"]/parts + +
  • + MechanicalSecondaryCapacitor + 0.07 + Inside +
  • +
    +
    + + + /Defs/BodyDef[defName = "MechanicalCentipede"]/corePart/parts/li[def="MechanicalCentipedeBodySecondRing"]/parts/li[def = "MechanicalCentipedeBodyThirdRing"]/parts + +
  • + MechanicalPrimaryPowerCore + 0.125 + Inside +
  • +
    +
    + + + /Defs/BodyDef[defName = "MechanicalCentipede"]/corePart/parts/li[def="MechanicalCentipedeBodySecondRing"]/parts/li[def = "MechanicalCentipedeBodyThirdRing"]/parts + +
  • + MechanicalCoolantTank + 0.09 + Inside +
  • +
    +
    + + + /Defs/BodyDef[defName = "MechanicalCentipede"]/corePart/parts/li[def="MechanicalCentipedeBodySecondRing"]/parts/li[def = "MechanicalCentipedeBodyThirdRing"]/parts/li[def = "MechanicalCentipedeBodyFourthRing"]/parts + +
  • + MechanicalLeftHeatSink + 0.068 + Inside +
  • +
    +
    + + + /Defs/BodyDef[defName = "MechanicalCentipede"]/corePart/parts/li[def="MechanicalCentipedeBodySecondRing"]/parts/li[def = "MechanicalCentipedeBodyThirdRing"]/parts/li[def = "MechanicalCentipedeBodyFourthRing"]/parts + +
  • + MechanicalRightHeatSink + 0.068 + Inside +
  • +
    +
    + + + /Defs/BodyDef[defName = "MechanicalCentipede"]/corePart/parts/li[def="MechanicalCentipedeBodySecondRing"]/parts/li[def = "MechanicalCentipedeBodyThirdRing"]/parts/li[def = "MechanicalCentipedeBodyFourthRing"]/parts/li[def = "MechanicalCentipedeBodyFifthRing"]/parts + +
  • + MechanicalAuxiliaryPowerCore + 0.25 + Inside +
  • +
    +
    + + + /Defs/BodyDef[defName = "MechanicalCentipede"]/corePart/parts/li[def="MechanicalCentipedeBodySecondRing"]/parts/li[def = "MechanicalCentipedeBodyThirdRing"]/parts/li[def = "MechanicalCentipedeBodyFourthRing"]/parts/li[def = "MechanicalCentipedeBodyFifthRing"]/parts + +
  • + MechanicalTertiaryCapacitor + 0.175 + Inside +
  • +
    +
    + +
    + diff --git a/Patches/Core/Bodies/Bodies_Mechanoid/Scyther.xml b/Patches/Core/Bodies/Bodies_Mechanoid/Scyther.xml new file mode 100644 index 0000000000..6afad3a3b0 --- /dev/null +++ b/Patches/Core/Bodies/Bodies_Mechanoid/Scyther.xml @@ -0,0 +1,563 @@ + + + + + + + + + Always + +
  • + /Defs/BodyDef[defName = "Scyther"]/corePart/groups + Invert +
  • +
  • + /Defs/BodyDef[defName = "Scyther"]/corePart + + + +
  • +
    +
    + + + Always + +
  • + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "MechanicalNeck"]/groups + Invert +
  • +
  • + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "MechanicalNeck"] + + + +
  • +
    +
    + + + Always + +
  • + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "MechanicalNeck"]/parts/li[def = "MechanicalHead"]/groups + Invert +
  • +
  • + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "MechanicalNeck"]/parts/li[def = "MechanicalHead"] + + + +
  • +
    +
    + + + Always + +
  • + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "LeftMechanicalShoulder"]/groups + Invert +
  • +
  • + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "LeftMechanicalShoulder"] + + + +
  • +
    +
    + + + Always + +
  • + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "LeftMechanicalShoulder"]/parts/li[def = "LeftMechanicalArm"]/groups + Invert +
  • +
  • + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "LeftMechanicalShoulder"]/parts/li[def = "LeftMechanicalArm"] + + + +
  • +
    +
    + + + Always + +
  • + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "LeftMechanicalShoulder"]/parts/li[def = "LeftMechanicalArm"]/parts/li[def = "LeftMechanicalHand"]/groups + Invert +
  • +
  • + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "LeftMechanicalShoulder"]/parts/li[def = "LeftMechanicalArm"]/parts/li[def = "LeftMechanicalHand"] + + + +
  • +
    +
    + + + Always + +
  • + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "RightMechanicalShoulder"]/groups + Invert +
  • +
  • + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "RightMechanicalShoulder"] + + + +
  • +
    +
    + + + Always + +
  • + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "RightMechanicalShoulder"]/parts/li[def = "RightMechanicalArm"]/groups + Invert +
  • +
  • + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "RightMechanicalShoulder"]/parts/li[def = "RightMechanicalArm"] + + + +
  • +
    +
    + + + Always + +
  • + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "RightMechanicalShoulder"]/parts/li[def = "RightMechanicalArm"]/parts/li[def = "RightMechanicalHand"]/groups + Invert +
  • +
  • + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "RightMechanicalShoulder"]/parts/li[def = "RightMechanicalArm"]/parts/li[def = "RightMechanicalHand"] + + + +
  • +
    +
    + + + Always + +
  • + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "LeftMechanicalLeg"]/groups + Invert +
  • +
  • + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "LeftMechanicalLeg"] + + + +
  • +
    +
    + + + Always + +
  • + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "LeftMechanicalLeg"]/parts/li[def = "LeftMechanicalFoot"]/groups + Invert +
  • +
  • + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "LeftMechanicalLeg"]/parts/li[def = "LeftMechanicalFoot"] + + + +
  • +
    +
    + + + Always + +
  • + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "RightMechanicalLeg"]/groups + Invert +
  • +
  • + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "RightMechanicalLeg"] + + + +
  • +
    +
    + + + Always + +
  • + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "RightMechanicalLeg"]/parts/li[def = "RightMechanicalFoot"]/groups + Invert +
  • +
  • + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "RightMechanicalLeg"]/parts/li[def = "RightMechanicalFoot"] + + + +
  • +
    +
    + + + + + /Defs/BodyDef[defName = "Scyther"]/corePart/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "MechanicalNeck"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "MechanicalNeck"]/parts/li[def="MechanicalHead"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "LeftMechanicalShoulder"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "LeftMechanicalShoulder"]/parts/li[def = "LeftMechanicalArm"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "LeftMechanicalShoulder"]/parts/li[def = "LeftMechanicalArm"]/parts/li[def = "LeftMechanicalHand"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "RightMechanicalShoulder"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "RightMechanicalShoulder"]/parts/li[def = "RightMechanicalArm"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "RightMechanicalShoulder"]/parts/li[def = "RightMechanicalArm"]/parts/li[def = "RightMechanicalHand"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "LeftMechanicalLeg"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "LeftMechanicalLeg"]/parts/li[def = "LeftMechanicalFoot"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "RightMechanicalLeg"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "RightMechanicalLeg"]/parts/li[def = "RightMechanicalFoot"]/groups + +
  • CoveredByNaturalArmor
  • +
    +
    + + + + + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "MechanicalNeck"]/coverage + + 0.08 + + + + + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "MechanicalNeck"]/parts/li[def="MechanicalHead"]/coverage + + 0.75 + + + + + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "MechanicalNeck"]/parts/li[def="MechanicalHead"]/parts/li[def = "ArtificialBrain"]/coverage + + 0.15 + + + + + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "MechanicalNeck"]/parts/li[def="MechanicalHead"]/parts/li[def = "LeftSightSensor"]/coverage + + 0.15 + + + + + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "MechanicalNeck"]/parts/li[def="MechanicalHead"]/parts/li[def = "RightSightSensor"]/coverage + + 0.15 + + + + + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "MechanicalNeck"]/parts/li[def="MechanicalHead"]/parts/li[def = "LeftHearingSensor"]/coverage + + 0.05 + + + + + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "MechanicalNeck"]/parts/li[def="MechanicalHead"]/parts/li[def = "RightHearingSensor"]/coverage + + 0.05 + + + + + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "MechanicalNeck"]/parts/li[def="MechanicalHead"]/parts/li[def = "SmellSensor"]/coverage + + 0.05 + + + + + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "LeftMechanicalShoulder"]/coverage + + 0.15 + + + + + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "RightMechanicalShoulder"]/coverage + + 0.15 + + + + + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "LeftMechanicalLeg"]/coverage + + 0.1 + + + + + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "RightMechanicalLeg"]/coverage + + 0.1 + + + + + + + /Defs/BodyDef[defName = "Scyther"]/corePart/parts + +
  • + MechanicalPrimaryPowerCore + 0.12 + Inside +
  • +
    +
    + + + /Defs/BodyDef[defName = "Scyther"]/corePart/parts + +
  • + MechanicalPrimaryCapacitor + 0.02 + Inside +
  • +
    +
    + + + /Defs/BodyDef[defName = "Scyther"]/corePart/parts + +
  • + MechanicalSecondaryCapacitor + 0.02 + Inside +
  • +
    +
    + + + /Defs/BodyDef[defName = "Scyther"]/corePart/parts + +
  • + MechanicalLeftHeatSink + 0.03 + Inside +
  • +
    +
    + + + /Defs/BodyDef[defName = "Scyther"]/corePart/parts + +
  • + MechanicalRightHeatSink + 0.03 + Inside +
  • +
    +
    + + + /Defs/BodyDef[defName = "Scyther"]/corePart/parts + +
  • + MechanicalCoolantTank + 0.06 + Inside +
  • +
    +
    + + + /Defs/BodyDef[defName = "Scyther"]/corePart/parts + +
  • + MechanicalRollerBearing + 0.06 + Inside +
  • +
    +
    + + + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "LeftMechanicalShoulder"]/parts/li[def = "LeftMechanicalArm"]/parts + +
  • + MechanicalLeftUpperActuator + 0.15 + Inside +
  • +
    +
    + + + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "LeftMechanicalShoulder"]/parts/li[def = "LeftMechanicalArm"]/parts + +
  • + MechanicalLeftUpperPiston + 0.25 + Inside +
  • +
    +
    + + + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "RightMechanicalShoulder"]/parts/li[def = "RightMechanicalArm"]/parts + +
  • + MechanicalRightUpperActuator + 0.15 + Inside +
  • +
    +
    + + + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "RightMechanicalShoulder"]/parts/li[def = "RightMechanicalArm"]/parts + +
  • + MechanicalRightUpperPiston + 0.25 + Inside +
  • +
    +
    + + + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "LeftMechanicalLeg"]/parts + +
  • + MechanicalLeftLowerActuator + 0.15 + Inside +
  • +
    +
    + + + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "LeftMechanicalLeg"]/parts + +
  • + MechanicalLeftLowerPiston + 0.25 + Inside +
  • +
    +
    + + + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "RightMechanicalLeg"]/parts + +
  • + MechanicalRightLowerActuator + 0.15 + Inside +
  • +
    +
    + + + /Defs/BodyDef[defName = "Scyther"]/corePart/parts/li[def = "RightMechanicalLeg"]/parts + +
  • + MechanicalRightLowerPiston + 0.25 + Inside +
  • +
    +
    + +
    + diff --git a/Patches/Core/Bodies/BodyParts_General.xml b/Patches/Core/Bodies/BodyParts_General.xml new file mode 100644 index 0000000000..eb882c9353 --- /dev/null +++ b/Patches/Core/Bodies/BodyParts_General.xml @@ -0,0 +1,47 @@ + + + + + */BodyPartDef[defName="Brain"]/hitPoints + + 15 + + + + + */BodyPartDef[defName="Rib"]/hitPoints + + 13 + + + + + */BodyPartDef[defName="LeftLeg"]/hitPoints + + 40 + + + + + */BodyPartDef[defName="LeftFoot"]/hitPoints + + 26 + + + + + */BodyPartDef[defName="RightLeg"]/hitPoints + + 40 + + + + + */BodyPartDef[defName="RightFoot"]/hitPoints + + 26 + + + + + diff --git a/Patches/Core/Bodies/BodyParts_Humanoid.xml b/Patches/Core/Bodies/BodyParts_Humanoid.xml new file mode 100644 index 0000000000..9fa0017605 --- /dev/null +++ b/Patches/Core/Bodies/BodyParts_Humanoid.xml @@ -0,0 +1,12 @@ + + + + + */BodyPartDef[defName="Torso"]/hitPoints + + 50 + + + + + diff --git a/Patches/Core/Bodies/BodyParts_Mechanoid.xml b/Patches/Core/Bodies/BodyParts_Mechanoid.xml new file mode 100644 index 0000000000..ebd3af6fda --- /dev/null +++ b/Patches/Core/Bodies/BodyParts_Mechanoid.xml @@ -0,0 +1,53 @@ + + + + + */BodyPartDef[defName="MechanicalThorax"]/hitPoints + + 50 + + + + + */BodyPartDef[defName="LeftBlade"]/hitPoints + + 26 + + + + + */BodyPartDef[defName="RightBlade"]/hitPoints + + 26 + + + + + */BodyPartDef[defName="LeftMechanicalLeg"]/hitPoints + + 40 + + + + + */BodyPartDef[defName="LeftMechanicalFoot"]/hitPoints + + 26 + + + + + */BodyPartDef[defName="RightMechanicalLeg"]/hitPoints + + 40 + + + + + */BodyPartDef[defName="RightMechanicalFoot"]/hitPoints + + 26 + + + + \ No newline at end of file diff --git a/Patches/Core/Bodies/BodyParts_Organs.xml b/Patches/Core/Bodies/BodyParts_Organs.xml new file mode 100644 index 0000000000..a79623c770 --- /dev/null +++ b/Patches/Core/Bodies/BodyParts_Organs.xml @@ -0,0 +1,68 @@ + + + + + */BodyPartDef[defName="Heart"]/bleedingRateMultiplier + + 12.5 + + + + + */BodyPartDef[defName="LeftLung"] + + 7.25 + + + + + */BodyPartDef[defName="RightLung"] + + 7.25 + + + + + */BodyPartDef[defName="LeftKidney"]/hitPoints + + 15 + + + + + */BodyPartDef[defName="LeftKidney"] + + 4.5 + + + + + */BodyPartDef[defName="RightKidney"]/hitPoints + + 15 + + + + + */BodyPartDef[defName="RightKidney"] + + 4.5 + + + + + */BodyPartDef[defName="Liver"] + + 9.75 + + + + + */BodyPartDef[defName="Stomach"] + + 3.0 + + + + + diff --git a/Patches/Core/DamageDefs/Damages_LocalInjury.xml b/Patches/Core/DamageDefs/Damages_LocalInjury.xml new file mode 100644 index 0000000000..d5d79cd038 --- /dev/null +++ b/Patches/Core/DamageDefs/Damages_LocalInjury.xml @@ -0,0 +1,115 @@ + + + + + + + */DamageDef[workerClass = "DamageWorker_AddInjury"]/workerClass + + CombatExtended.DamageWorker_AddInjuryCE + + + + + */DamageDef[workerClass = "DamageWorker_Flame"]/workerClass + + CombatExtended.DamageWorker_FlameCE + + + + + + + */DamageDef[defName="Crush"] + +
  • + true +
  • +
    +
    + + + */DamageDef[defName="Blunt"] + +
  • + true +
  • +
    +
    + + + */DamageDef[defName="Scratch"] + +
  • + true + true +
  • +
    +
    + + + */DamageDef[defName="Bite"] + +
  • + true +
  • +
    +
    + + + */DamageDef[defName="Flame"] + +
  • + true + true +
  • +
    +
    + + + */DamageDef[defName="Frostbite"] + +
  • + true + true +
  • +
    +
    + + + + + */DamageDef[defName="Blunt"] + Name + BluntDamage + + + + */DamageDef[defName="Bullet"] + Name + BulletDamage + + + + */DamageDef[defName="Bomb"] + Name + BombDamage + + + + */DamageDef[defName="Burn"] + Name + BurnDamage + + + + + + */DamageDef[defName="Bomb"]/hediff + + Blast + + + +
    + diff --git a/Patches/Core/DamageDefs/Damages_Stun.xml b/Patches/Core/DamageDefs/Damages_Stun.xml new file mode 100644 index 0000000000..910bb94080 --- /dev/null +++ b/Patches/Core/DamageDefs/Damages_Stun.xml @@ -0,0 +1,12 @@ + + + + + */DamageDef[defName="Stun"]/armorCategory + + + + + + + diff --git a/Patches/Core/Drugs/Drugs.xml b/Patches/Core/Drugs/Drugs.xml new file mode 100644 index 0000000000..8906c094e8 --- /dev/null +++ b/Patches/Core/Drugs/Drugs.xml @@ -0,0 +1,25 @@ + + + + + + + /GoJuice/HediffDef[defName="GoJuiceHigh"]/stages/li[1] + + + -0.75 + + + + + + /Yayo/HediffDef[defName="YayoHigh"]/stages/li[1] + + + -0.5 + + + + + + diff --git a/Patches/Core/FactionDefs/Factions_Misc.xml b/Patches/Core/FactionDefs/Factions_Misc.xml new file mode 100644 index 0000000000..5058697bf0 --- /dev/null +++ b/Patches/Core/FactionDefs/Factions_Misc.xml @@ -0,0 +1,118 @@ + + + + + + + */FactionDef[defName="Mechanoid"]/earliestRaidDays + + 60 + + + + + */FactionDef[defName="Mechanoid"]/pawnGroupMakers/li[1]/options/Centipede + + 50 + + + + + + + + + /FactionDefs/FactionDef[defName="Outlander" or defName="Pirate"]/pawnGroupMakers/li/*/GrenadierEMP + + + + + + + /FactionDefs/FactionDef[defName="Outlander"]/pawnGroupMakers/li[1]/options + + 100 + + + + + /FactionDefs/FactionDef[defName="Outlander"]/pawnGroupMakers/li[2]/guards + + 70 + + + + + /FactionDefs/FactionDef[defName="Outlander"]/pawnGroupMakers/li[3]/options + + 70 + + + + + + /FactionDefs/FactionDef[defName="Pirate"]/pawnGroupMakers/li[1]/options + + 70 + + + + + /FactionDefs/FactionDef[defName="Pirate"]/pawnGroupMakers/li[2]/options + + 100 + + + + + /FactionDefs/FactionDef[defName="Pirate"]/pawnGroupMakers/li[3]/options + + 70 + + + + + + + + /FactionDefs/FactionDef[defName="Outlander"]/pawnGroupMakers/li[1]/options + + 70 + + + + + /FactionDefs/FactionDef[defName="Outlander"]/pawnGroupMakers/li[2]/guards + + 50 + + + + + /FactionDefs/FactionDef[defName="Outlander"]/pawnGroupMakers/li[3]/options + + 50 + + + + + + /FactionDefs/FactionDef[defName="Pirate"]/pawnGroupMakers/li[1]/options + + 80 + + + + + /FactionDefs/FactionDef[defName="Pirate"]/pawnGroupMakers/li[3]/options + + 80 + + + + + diff --git a/Patches/Core/HediffDefs/BloodLoss.xml b/Patches/Core/HediffDefs/BloodLoss.xml new file mode 100644 index 0000000000..f570da82d1 --- /dev/null +++ b/Patches/Core/HediffDefs/BloodLoss.xml @@ -0,0 +1,67 @@ + + + + */HediffDef[defName="BloodLoss"]/stages + + +
  • + + false +
  • +
  • + 0.1 + + +
  • + Consciousness + -0.05 +
  • + + +
  • + 0.2 + + +
  • + Consciousness + -0.25 +
  • + + +
  • + 0.4 + + +
  • + Consciousness + -0.5 +
  • + + +
  • + 0.6 + + true + +
  • + Consciousness + 0.25 +
  • + + +
  • + 0.8 + + true + +
  • + Consciousness + 0.1 +
  • + + +
    +
    +
    +
    + diff --git a/Patches/Core/HediffDefs/Hediffs_Local_AddedParts.xml b/Patches/Core/HediffDefs/Hediffs_Local_AddedParts.xml new file mode 100644 index 0000000000..a82a1c0144 --- /dev/null +++ b/Patches/Core/HediffDefs/Hediffs_Local_AddedParts.xml @@ -0,0 +1,48 @@ + + + + */HediffDef[defName="BionicArm"]/comps/li[@Class="HediffCompProperties_VerbGiver"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 9 + Blunt + 0.15 +
  • +
    +
    +
    + + + */HediffDef[defName="PowerClaw"]/comps/li[@Class="HediffCompProperties_VerbGiver"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.2 + 15 + Scratch + 0.3 +
  • +
    +
    +
    + + + */HediffDef[defName="ScytherBlade"]/comps/li[@Class="HediffCompProperties_VerbGiver"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.0 + 20 + Cut + 0.4 +
  • +
    +
    +
    +
    + diff --git a/Patches/Core/HediffDefs/Hediffs_Local_Injuries.xml b/Patches/Core/HediffDefs/Hediffs_Local_Injuries.xml new file mode 100644 index 0000000000..ed29d639e4 --- /dev/null +++ b/Patches/Core/HediffDefs/Hediffs_Local_Injuries.xml @@ -0,0 +1,219 @@ + + + + + + + /HediffDefs/HediffDef[defName = "MissingBodyPart"]/comps + +
  • + + + + + /HediffDefs/HediffDef[@Name="InjuryBase"] + + +
  • + + + + + + + + /HediffDefs/HediffDef[defName="MissingBodyPart"]/injuryProps/bleedRate + + 0.08 + + + + + /HediffDefs/HediffDef[defName="MissingBodyPart"]/injuryProps/painPerSeverity + + 0.04 + + + + + + + /HediffDefs/HediffDef[defName="Burn"]/injuryProps/painPerSeverity + + 0.025 + + + + + /HediffDefs/HediffDef[defName="Burn"]/comps/li[@Class = "HediffCompProperties_Infecter"] + +
  • + 0.07 +
  • +
    +
    + + + /HediffDefs/HediffDef[defName="Burn"]/comps/li[@Class = "HediffCompProperties_GetsOld"] + + 1.5 + + + + + /HediffDefs/HediffDef[defName="Burn"] + Name + Burn + + + + + + /HediffDefs/HediffDef[defName="Crush"]/injuryProps/bleedRate + + 0.015 + + + + + /HediffDefs/HediffDef[defName="Crush"]/injuryProps/painPerSeverity + + 0.0125 + + + + + /HediffDefs/HediffDef[defName="Crush"]/comps/li[@Class = "HediffCompProperties_Infecter"] + +
  • + 0.04 +
  • +
    +
    + + + + + /HediffDefs/HediffDef[defName="Crack"]/injuryProps/painPerSeverity + + 0.0175 + + + + + + + /HediffDefs/HediffDef[defName="Cut"]/comps/li[@Class = "HediffCompProperties_Infecter"] + +
  • + 0.015 +
  • +
    +
    + + + /HediffDefs/HediffDef[defName="Cut"]/comps/li[@Class = "HediffCompProperties_GetsOld"] + + 0.75 + + + + + + + /HediffDefs/HediffDef[defName="Scratch"]/comps/li[@Class = "HediffCompProperties_Infecter"] + +
  • + 0.015 +
  • +
    +
    + + + /HediffDefs/HediffDef[defName="Scratch"]/comps/li[@Class = "HediffCompProperties_GetsOld"] + + 0.5 + + + + + + + /HediffDefs/HediffDef[defName="Bite"]/comps/li[@Class = "HediffCompProperties_Infecter"] + +
  • + 0.06 +
  • +
    +
    + + + + + /HediffDefs/HediffDef[defName="Stab"]/injuryProps/painPerSeverity + + 0.0175 + + + + + /HediffDefs/HediffDef[defName="Stab"]/comps/li[@Class = "HediffCompProperties_Infecter"] + +
  • + 0.03 +
  • +
    +
    + + + + + /HediffDefs/HediffDef[defName="Gunshot"]/injuryProps/painPerSeverity + + 0.0175 + + + + + /HediffDefs/HediffDef[defName="Gunshot"]/comps/li[@Class = "HediffCompProperties_Infecter"] + +
  • + 0.03 +
  • +
    +
    + + + + + /HediffDefs/HediffDef[defName="Shredded"]/injuryProps/bleedRate + + 0.015 + + + + + /HediffDefs/HediffDef[defName="Shredded"]/injuryProps/painPerSeverity + + 0.0175 + + + + + /HediffDefs/HediffDef[defName="Shredded"]/comps/li[@Class = "HediffCompProperties_Infecter"] + +
  • + 0.05 +
  • +
    +
    + + + /HediffDefs/HediffDef[defName="Shredded"]/comps/li[@Class = "HediffCompProperties_GetsOld"]/oldLabel + + shrapnel scar + + + +
    + diff --git a/Patches/Core/JobDefs/Jobs.xml b/Patches/Core/JobDefs/Jobs.xml new file mode 100644 index 0000000000..bcd2e14fff --- /dev/null +++ b/Patches/Core/JobDefs/Jobs.xml @@ -0,0 +1,28 @@ + + + + /JobDefs/JobDef[defName="UnloadYourInventory"]/driverClass + + CombatExtended.JobDriver_UnloadYourInventory + + + + + */JobDef[defName="Hunt"]/driverClass + + CombatExtended.JobDriver_Hunt + + + + + + + */JobDef[defName="AttackStatic" or defName="WaitCombat" or defName="ManTurret"] + +
  • + true +
  • +
    +
    +
    + diff --git a/Patches/Core/Misc/PawnTables/PawnTables.xml b/Patches/Core/Misc/PawnTables/PawnTables.xml new file mode 100644 index 0000000000..5110824cb1 --- /dev/null +++ b/Patches/Core/Misc/PawnTables/PawnTables.xml @@ -0,0 +1,18 @@ + + + + + */PawnTableDef[defName="Assign"]/columns/li[last()] + +
  • GapSmall
  • +
  • Loadout
  • +
  • GapSmall
  • +
  • CEMass
  • +
  • GapSmall
  • +
  • CEBulk
  • +
  • RemainingSpace
  • +
    +
    + +
    + diff --git a/Patches/Core/PawnCapacityDefs/PawnCapacities.xml b/Patches/Core/PawnCapacityDefs/PawnCapacities.xml new file mode 100644 index 0000000000..1795d2e1c9 --- /dev/null +++ b/Patches/Core/PawnCapacityDefs/PawnCapacities.xml @@ -0,0 +1,41 @@ + + + + + /PawnCapacityDefs/PawnCapacityDef[defName="BloodFiltration"] + + capacitance + true + + + + + /PawnCapacityDefs/PawnCapacityDef[defName="BloodPumping"] + + coolant pumping + true + + + + + /PawnCapacityDefs/PawnCapacityDef[defName="Breathing"] + + heat exchange + true + + + + + /PawnCapacityDefs/PawnCapacityDef[defName="Metabolism"] + + power generation + true + + + + + /PawnCapacityDefs/PawnCapacityDef[defName="BloodFiltration" or defName="BloodPumping" or defName="Breathing" or defName="Metabolism"]/showOnMechanoids + + + + diff --git a/Patches/Core/PawnKindDefs_Humanlike/PawnKinds.xml b/Patches/Core/PawnKindDefs_Humanlike/PawnKinds.xml new file mode 100644 index 0000000000..b675da44f0 --- /dev/null +++ b/Patches/Core/PawnKindDefs_Humanlike/PawnKinds.xml @@ -0,0 +1,171 @@ + + + + + + + /PawnKindDefs/PawnKindDef[defName="Scyther"]/aiAvoidCover + + + + /PawnKindDefs/PawnKindDef[defName="Centipede"]/combatPower + + 580 + + + + + /PawnKindDefs/PawnKindDef[defName="Scyther" or defName="Centipede"] + + + 1 + + + + + + + + /PawnKindDefs/PawnKindDef[defName="GrenadierDestructive"] + + + 1 + + + + + + /PawnKindDefs/PawnKindDef[defName="MercenaryGunner"] + + + 1 + 1 + + + + + + /PawnKindDefs/PawnKindDef[defName="MercenarySniper"] + + + 1 + 1 + 1 + 1 + + + + + + /PawnKindDefs/PawnKindDef[defName="MercenaryHeavy"] + + + 1 + 1 + 1 + + + + + + /PawnKindDefs/PawnKindDef[@Name = "EliteBase"] + + + 1 + 1 + 1 + 1 + + + + + + + + /PawnKindDefs/PawnKindDef[defName="Villager"] + + + 1 + 1 + + + + + + /PawnKindDefs/PawnKindDef[defName="TownGuard"] + + + 1 + 1 + 1 + + + + + + + + /PawnKindDefs/PawnKindDef[defName="Drifter" or defName="Scavenger"] + + + 1 + + + + + + /PawnKindDefs/PawnKindDef[defName="Pirate"] + + + 1 + 1 + + + + + + + + /PawnKindDefs/PawnKindDef[defName="SpaceSoldier"] + + + 1 + 1 + 1 + 1 + + + + + + + + /PawnKindDefs/PawnKindDef[defName="TribalWarrior"]/weaponMoney/min + + 80 + + + + + /PawnKindDefs/PawnKindDef[defName="TribalArcher"] + + + 1 + 1 + + + + + + /PawnKindDefs/PawnKindDef[defName="TribalChief"] + + + 1 + 1 + 1 + + + + + + diff --git a/Patches/Core/RecipeDefs/Recipes_Production.xml b/Patches/Core/RecipeDefs/Recipes_Production.xml new file mode 100644 index 0000000000..b3a00fd206 --- /dev/null +++ b/Patches/Core/RecipeDefs/Recipes_Production.xml @@ -0,0 +1,15 @@ + + + + + /RecipeDefs/RecipeDef[defName="SmeltWeapon"]/fixedIngredientFilter + + +
  • Ammo
  • +
  • WeaponsTurrets
  • +
    +
    +
    + +
    + diff --git a/Patches/Core/ResearchProjectDefs/ResearchProjects.xml b/Patches/Core/ResearchProjectDefs/ResearchProjects.xml new file mode 100644 index 0000000000..e1ca9be1c2 --- /dev/null +++ b/Patches/Core/ResearchProjectDefs/ResearchProjects.xml @@ -0,0 +1,32 @@ + + + + + + */ResearchProjectDef[defName="MultibarrelWeapons"] + + + + + /ResearchProjectDefs/ResearchProjectDef[defName="GunTurrets"] + + CE_Turrets + + + + + /ResearchProjectDefs/ResearchProjectDef[defName="GunTurrets"]/researchViewX + + 1 + + + + + /ResearchProjectDefs/ResearchProjectDef[defName="GunTurrets"]/researchViewY + + 0 + + + + + diff --git a/Patches/Core/Scenarios/Scenarios.xml b/Patches/Core/Scenarios/Scenarios.xml new file mode 100644 index 0000000000..2d187aa4de --- /dev/null +++ b/Patches/Core/Scenarios/Scenarios.xml @@ -0,0 +1,41 @@ + + + + */ScenarioDef[defName="Crashlanded"]/scenario/parts + +
  • + StartingThing_Defined + Ammo_303British_FMJ + 100 +
  • +
  • + StartingThing_Defined + Ammo_45ACP_FMJ + 70 +
  • +
    +
    + + + */ScenarioDef[defName="TheRichExplorer"]/scenario/parts + +
  • + StartingThing_Defined + Ammo_6x24mmCharged + 300 +
  • +
    +
    + + + */ScenarioDef[defName="LostTribe"]/scenario/parts + +
  • + StartingThing_Defined + Ammo_Arrow_Stone + 100 +
  • +
    +
    +
    + diff --git a/Patches/Core/Stats/Stats.xml b/Patches/Core/Stats/Stats.xml new file mode 100644 index 0000000000..196b97996f --- /dev/null +++ b/Patches/Core/Stats/Stats.xml @@ -0,0 +1,127 @@ + + + + + + + + + */StatDef[@Name = "ArmorRatingBase"]/parts/li[@Class = "StatPart_Quality"] + +
  • + 0.7 + 0.8 + 0.9 + 1 + 1.06 + 1.12 + 1.18 + 1.24 + 1.3 +
  • +
    +
    + + + */StatDef[defName="ArmorRating_Blunt" or defName="ArmorRating_Sharp"] + + FloatTwo + + + + + + + + + */StatDef[defName="ShootingAccuracy"]/label + + + + + + + */StatDef[defName="ShootingAccuracy"]/description + + How well a shooter can hold a gun steady when aiming and compensate for recoil.\n\nThe total sway is calculated as:\n(4.5 - shooting accuracy) * weapon sway factor\n\nThe recoil per shot is determined by multiplying this value against the weapon's inherent recoil amount and increases after every shot in a burst. + + + + + */StatDef[defName="ShootingAccuracy"]/minValue + + 0 + + + + + */StatDef[defName="ShootingAccuracy"]/maxValue + + 4.5 + + + + + */StatDef[defName="ShootingAccuracy"]/skillNeedFactors/li[@Class = "SkillNeed_BaseBonus"] + +
  • + Shooting + true + +
  • 1.0
  • +
  • 1.2
  • +
  • 1.4
  • +
  • 1.6
  • +
  • 1.8
  • +
  • 2.0
  • +
  • 2.1
  • +
  • 2.2
  • +
  • 2.3
  • +
  • 2.4
  • +
  • 2.5
  • +
  • 2.56
  • +
  • 2.62
  • +
  • 2.68
  • +
  • 2.74
  • +
  • 2.8
  • +
  • 2.84
  • +
  • 2.88
  • +
  • 2.92
  • +
  • 2.96
  • +
  • 3.0
  • + + +
    +
    + + + */StatDef[defName="ShootingAccuracy"]/capacityFactors/li[capacity = "Manipulation"]/weight + + 1 + + + + + */StatDef[defName="ShootingAccuracy"]/postProcessCurve + + + + + + /StatDefs/StatDef[defName="MoveSpeed"] + + CombatExtended.StatWorker_MoveSpeed + + + + + + + */StatDef[defName="WorkSpeedGlobal"] + + CombatExtended.StatWorker_WorkSpeedGlobal + + + +
    + diff --git a/Patches/Core/Storyteller/Incidents_Map_Threats.xml b/Patches/Core/Storyteller/Incidents_Map_Threats.xml new file mode 100644 index 0000000000..c3a837db6c --- /dev/null +++ b/Patches/Core/Storyteller/Incidents_Map_Threats.xml @@ -0,0 +1,14 @@ + + + + + + + */IncidentDef[defName="PsychicEmanatorShipPartCrash" or defName="PoisonShipPartCrash"] + + 60 + + + + + diff --git a/Patches/Core/ThingDefs_Buildings/Buildings_Base.xml b/Patches/Core/ThingDefs_Buildings/Buildings_Base.xml new file mode 100644 index 0000000000..8625119878 --- /dev/null +++ b/Patches/Core/ThingDefs_Buildings/Buildings_Base.xml @@ -0,0 +1,167 @@ + + + + + + + */ThingDef[DefName="TableMachining"]/recipes/li[.="MakeMortarShell"] + + + + + + + + /Buildings/ThingDef[defName="Wall"]/damageMultipliers + + + + */ThingDef[@Name="BuildingBase"] + + +
  • + Bomb + 1.2 +
  • +
  • + Thermobaric + 1.5 +
  • +
  • + Bullet + 0.25 +
  • +
  • + Fragment + 0.125 +
  • +
  • + Arrow + 0.05 +
  • +
  • + Electrical + 0.25 +
  • +
    +
    +
    + + + + + + + + + */ThingDef[@Name="BuildingNaturalBase"] + + +
  • + Bomb + 2 +
  • +
  • + Thermobaric + 2.5 +
  • +
  • + Bullet + 0.05 +
  • +
  • + Fragment + 0.025 +
  • +
  • + Arrow + 0.0 +
  • +
  • + Electrical + 0.0 +
  • +
    +
    +
    + + + */ThingDef[@Name="ChunkBase"] + + +
  • + Bomb + 2 +
  • +
  • + Thermobaric + 2.5 +
  • +
  • + Bullet + 0.05 +
  • +
  • + Fragment + 0.025 +
  • +
  • + Arrow + 0.0 +
  • +
  • + Electrical + 0.0 +
  • +
    +
    +
    + +
    + diff --git a/Patches/Core/ThingDefs_Buildings/Buildings_Security.xml b/Patches/Core/ThingDefs_Buildings/Buildings_Security.xml new file mode 100644 index 0000000000..b135e5eb4a --- /dev/null +++ b/Patches/Core/ThingDefs_Buildings/Buildings_Security.xml @@ -0,0 +1,293 @@ + + + + + + + */ThingDef[defName="Sandbags"]/costList/Steel + + 2 + + + + + */ThingDef[defName="Sandbags"]/fillPercent + + 0.6 + + + + + + + */ThingDef[defName="TurretGun"]/thingClass + + CombatExtended.Building_TurretGunCE + + + + + */ThingDef[defName="TurretGun"]/label + + + + + + + */ThingDef[defName="TurretGun"]/comps/li[@Class = "CompProperties_Explosive"] + + + + */ThingDef[defName="TurretGun"]/fillPercent + + 0.85 + + + + + */ThingDef[defName="TurretGun"]/specialDisplayRadius + + 27 + + + + + */ThingDef[defName="TurretGun"]/building/turretBurstCooldownTime + + 1.1 + + + + + + + Always + +
  • + */ThingDef[defName="TurretGun"]/tradeTags + Invert +
  • +
  • + */ThingDef[defName="TurretGun"] + + + +
  • +
    +
    + + + */ThingDef[defName="TurretGun"]/tradeTags + +
  • CE_Turret
  • +
    +
    + + + + + */ThingDef[defName="TurretGun"]/costList/Steel + + 175 + + + + + */ThingDef[defName="TurretGun"]/costList/Component + + 8 + + + + + */ThingDef[defName="TurretGun"]/stuffCategories + + + + */ThingDef[defName="TurretGun"]/costStuffCount + + + + + + + + */ThingDef[defName = "Artillery_MortarBomb"] + + + 0.5 + + +
  • + +
  • (30,80)
  • +
  • (50,220)
  • +
  • (70,440)
  • +
  • (90,730)
  • + + +
  • + 1 + 5 + true + AmmoSet_81mmMortarShell +
  • +
    +
    +
    + + + */ThingDef[defName = "Artillery_MortarBomb"]/weaponTags + +
  • TurretGun
  • +
    +
    + + + */ThingDef[defName = "Artillery_MortarBomb"]/verbs + + +
  • + CombatExtended.Verb_ShootMortarCE + false + true + Bullet_81mmMortarShell_HE + 5.5 + 32 + 700 + 1 + Mortar_LaunchA + 16 + 1 + 0.2 + + true + +
  • +
    +
    +
    + + + + + */ThingDef[@Name = "BaseArtilleryBuilding"]/thingClass + + CombatExtended.Building_TurretGunCE + + + + + */ThingDef[@Name = "BaseArtilleryBuilding"]/building/turretBurstCooldownTime + + 2 + + + + + */ThingDef[@Name = "BaseArtilleryBuilding"]/building + + CE_MortarDirectFire + + + + + + + + + Always + +
  • + */ThingDef[@Name = "BaseArtilleryBuilding"]/tradeTags + Invert +
  • +
  • + */ThingDef[@Name = "BaseArtilleryBuilding"] + + + +
  • +
    +
    + + + */ThingDef[@Name = "BaseArtilleryBuilding"]/tradeTags + +
  • CE_Turret
  • +
    +
    + + + + + */ThingDef[@Name = "BaseArtilleryBuilding"]/costList/Steel + + 200 + + + + + */ThingDef[@Name = "BaseArtilleryBuilding"]/stuffCategories + + + + */ThingDef[@Name = "BaseArtilleryBuilding"]/costStuffCount + + + + + + */ThingDef[@Name = "BaseArtilleryBuilding"]/designationCategory + + + + + + */ThingDef[defName="Turret_MortarBomb"]/label + + + + + + + */ThingDef[defName="Turret_MortarBomb"]/comps + + + + */ThingDef[defName="Turret_MortarBomb"] + + Security + + + + + + + */ThingDef[defName="Turret_MortarIncendiary"] + + + + + + */ThingDef[defName="Turret_MortarEMP"] + + true + + + + + + + */ThingDef[defName="TrapIEDIncendiary"]/costList/Chemfuel + + 1 + + + +
    + diff --git a/Patches/Core/ThingDefs_Items/Items.xml b/Patches/Core/ThingDefs_Items/Items.xml new file mode 100644 index 0000000000..4f4821766a --- /dev/null +++ b/Patches/Core/ThingDefs_Items/Items.xml @@ -0,0 +1,296 @@ + + + + + + + */ThingDef[@Name="OrganicProductBase"]/statBases + + 0.2 + + + + + + + + + */ThingDef[defName="ThrumboHorn"]/statBases/MeleeWeapon_DamageAmount + + 19 + + + + + */ThingDef[defName="ThrumboHorn"]/statBases + + 0.3 + 10 + + + + + */ThingDef[defName="ThrumboHorn"] + + + 1 + 0.75 + + + + + + */ThingDef[defName="ThrumboHorn"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + true + Stab +
  • +
    +
    +
    + + + + + */ThingDef[defName="ElephantTusk"]/statBases/MeleeWeapon_DamageAmount + + 19 + + + + + */ThingDef[defName="ElephantTusk"]/statBases + + 0.175 + 10 + + + + + */ThingDef[defName="ElephantTusk"] + + + 0.25 + 0.5 + + + + + + */ThingDef[defName="ElephantTusk"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + true + Stab +
  • +
    +
    +
    + + + + + */ThingDef[defName="Silver"]/statBases + + 0.007 + + + + + */ThingDef[defName="Gold"]/statBases + + 0.01 + + + + + + + */ThingDef[defName="Steel"]/statBases + + 0.03 + + + + + */ThingDef[defName="Steel"]/stuffProps/categories + +
  • Metallic_Weapon
  • +
  • Steeled
  • +
    +
    + + + + + */ThingDef[defName="Plasteel"]/statBases + + 0.03 + + + + + */ThingDef[defName="Plasteel"]/stuffProps/categories + +
  • Metallic_Weapon
  • +
  • Steeled
  • +
    +
    + + + */ThingDef[defName="Plasteel"]/stuffProps + + + 0.0 + 0.18 + 0 + 0.0 + + + + + + */ThingDef[defName="Plasteel"]/stuffProps/statFactors + + 0.8 + 1.0 + 1.15 + 1.3 + + + + + + + */ThingDef[defName="WoodLog"]/statBases + + 0.07 + + + + + */ThingDef[defName="WoodLog"]/statBases/SharpDamageMultiplier + + 0.7 + + + + + */ThingDef[defName="WoodLog"]/statBases/BluntDamageMultiplier + + 0.5 + + + + + */ThingDef[defName="WoodLog"]/stuffProps/statFactors + + 0.3 + 0.3 + + + + + */ThingDef[defName="WoodLog"]/verbs/li[1]/verbClass + + CombatExtended.Verb_MeleeAttackCE + + + + + + + */ThingDef[defName="Uranium"]/statBases + + 0.05 + + + + + */ThingDef[defName="Uranium"]/stuffProps/categories + +
  • Metallic_Weapon
  • +
    +
    + + + */ThingDef[defName="Uranium"]/stuffProps/statFactors + + 2 + 1.4 + + + + + + + */ThingDef[defName="Jade"]/statBases + + 0.3 + + + + + */ThingDef[defName="Jade"]/stuffProps/statFactors + + 1.3 + + + + + + + */ThingDef[defName="DevilstrandCloth"]/statBases + + 0.3 + + + + + */ThingDef[defName="DevilstrandCloth"]/stuffProps/statOffsets + + 0.5 + 0.5 + + + + + */ThingDef[defName="DevilstrandCloth"]/stuffProps/statFactors + + 1.5 + 1.5 + + + + + + + */ThingDef[defName="Hyperweave"]/statBases + + 0.3 + + + + + */ThingDef[defName="Hyperweave"]/stuffProps/statOffsets + + 0.75 + 0.5 + + + + + */ThingDef[defName="Hyperweave"]/stuffProps/statFactors + + 1.8 + 1.8 + + + +
    + diff --git a/Patches/Core/ThingDefs_Misc/Apparel_Belts.xml b/Patches/Core/ThingDefs_Misc/Apparel_Belts.xml new file mode 100644 index 0000000000..6bf9a295c4 --- /dev/null +++ b/Patches/Core/ThingDefs_Misc/Apparel_Belts.xml @@ -0,0 +1,39 @@ + + + + + + + */ThingDef[defName="Apparel_ShieldBelt"]/statBases + + 4 + 2 + + + + + */ThingDef[defName="Apparel_ShieldBelt"]/statBases/EnergyShieldRechargeRate + + 0.195 + + + + + */ThingDef[defName="Apparel_ShieldBelt"]/statBases/EnergyShieldEnergyMax + + 1.65 + + + + + + + */ThingDef[defName="Apparel_SmokepopBelt"]/statBases + + 3 + 1 + + + + + diff --git a/Patches/Core/ThingDefs_Misc/Apparel_Hats.xml b/Patches/Core/ThingDefs_Misc/Apparel_Hats.xml new file mode 100644 index 0000000000..6d697a0d68 --- /dev/null +++ b/Patches/Core/ThingDefs_Misc/Apparel_Hats.xml @@ -0,0 +1,117 @@ + + + + + + + */ThingDef[defName="Apparel_SimpleHelmet"]/statBases + + 4 + + + + + */ThingDef[defName="Apparel_SimpleHelmet"]/statBases/ArmorRating_Blunt + + 0.15 + + + + + */ThingDef[defName="Apparel_SimpleHelmet"]/statBases/ArmorRating_Sharp + + 0.40 + + + + + */ThingDef[defName="Apparel_SimpleHelmet"]/stuffCategories/li[.="Metallic"] + +
  • Steeled
  • +
    +
    + + + */ThingDef[defName="Apparel_SimpleHelmet"]/equippedStatOffsets/MoveSpeed + + + + */ThingDef[defName="Apparel_SimpleHelmet"]/costStuffCount + + 50 + + + + + + + */ThingDef[defName="Apparel_AdvancedHelmet"]/statBases + + 4 + + + + + */ThingDef[defName="Apparel_AdvancedHelmet"]/statBases/ArmorRating_Blunt + + 0.2 + + + + + */ThingDef[defName="Apparel_AdvancedHelmet"]/statBases/ArmorRating_Sharp + + 0.55 + + + + + */ThingDef[defName="Apparel_AdvancedHelmet"]/stuffCategories/li[.="Metallic"] + +
  • Steeled
  • +
    +
    + + + */ThingDef[defName="Apparel_AdvancedHelmet"]/equippedStatOffsets/MoveSpeed + + + + */ThingDef[defName="Apparel_AdvancedHelmet"]/costStuffCount + + 50 + + + + + + + */ThingDef[defName="Apparel_PowerArmorHelmet"]/description + + A part of power armor set, mostly used by heavy infantry.\n\nIntegrated servo-motors assist the wearer's muscles in holding the weight of the helmet while the integrated combat HUD improves weapon accuracy. + + + + + */ThingDef[defName="Apparel_PowerArmorHelmet"]/statBases + + 5 + 1 + + + + + */ThingDef[defName="Apparel_PowerArmorHelmet"]/equippedStatOffsets/MoveSpeed + + + + */ThingDef[defName="Apparel_PowerArmorHelmet"]/equippedStatOffsets + + -0.2 + 0.15 + -0.50 + + + +
    + diff --git a/Patches/Core/ThingDefs_Misc/Apparel_Various.xml b/Patches/Core/ThingDefs_Misc/Apparel_Various.xml new file mode 100644 index 0000000000..80834357bd --- /dev/null +++ b/Patches/Core/ThingDefs_Misc/Apparel_Various.xml @@ -0,0 +1,184 @@ + + + + + + + */ThingDef[defName="Apparel_Parka"]/statBases + + 10 + 5 + + + + + */ThingDef[defName="Apparel_Parka"]/equippedStatOffsets/WorkSpeedGlobal + + + + */ThingDef[defName="Apparel_Parka"]/equippedStatOffsets/MoveSpeed + + + + + + */ThingDef[defName="Apparel_Duster"]/statBases + + 7.5 + 1 + + + + + */ThingDef[defName="Apparel_Duster"]/equippedStatOffsets/MoveSpeed + + + + + + */ThingDef[defName="Apparel_Jacket"]/statBases + + 5 + 1 + + + + + */ThingDef[defName="Apparel_Jacket"]/equippedStatOffsets/MoveSpeed + + + + + + */ThingDef[defName="Apparel_VestPlate"]/statBases + + 5 + 1 + + + + + */ThingDef[defName="Apparel_VestPlate"]/statBases/MaxHitPoints + + 125 + + + + + */ThingDef[defName="Apparel_VestPlate"]/statBases/Mass + + 13 + + + + + */ThingDef[defName="Apparel_VestPlate"]/statBases/ArmorRating_Sharp + + 0.6 + + + + + */ThingDef[defName="Apparel_VestPlate"]/equippedStatOffsets/MoveSpeed + + + + */ThingDef[defName="Apparel_VestPlate"]/apparel/bodyPartGroups + +
  • Shoulders
  • +
    +
    + + + + + */ThingDef[defName="Apparel_VestPlate"] + + 90 + + + + + */ThingDef[defName="Apparel_VestPlate"] + + +
  • Steeled
  • +
    +
    +
    + + + */ThingDef[defName="Apparel_VestPlate"]/recipeMaker/unfinishedThingDef + + + + */ThingDef[defName="Apparel_VestPlate"]/costList/Steel + + + + */ThingDef[defName="Apparel_VestPlate"]/costList/Component + + + + */ThingDef[defName="Apparel_VestPlate"]/colorGenerator + + + + + + */ThingDef[defName="Apparel_PowerArmor"]/statBases + + 100 + 15 + + + + + */ThingDef[defName="Apparel_PowerArmor"]/description + + Powered armor usually used by assault troops from advanced glitterworld planets.\n\nBulky and heavy, but the advanced servo-motors greatly increase the wearer's load bearing capacity and assist in weapon-handling. + + + + + */ThingDef[defName="Apparel_PowerArmor"]/statBases/Mass + + 50 + + + + + */ThingDef[defName="Apparel_PowerArmor"]/statBases/ArmorRating_Sharp + + 0.8 + + + + + */ThingDef[defName="Apparel_PowerArmor"]/equippedStatOffsets/MoveSpeed + + + + */ThingDef[defName="Apparel_PowerArmor"]/equippedStatOffsets/WorkSpeedGlobal + + + + */ThingDef[defName="Apparel_PowerArmor"]/equippedStatOffsets + + 80 + 10 + 0.15 + -0.50 + + + + + */ThingDef[defName="Apparel_PowerArmor"]/apparel/bodyPartGroups + +
  • Hands
  • +
  • Feet
  • +
    +
    + +
    + diff --git a/Patches/Core/ThingDefs_Misc/Filth_Various.xml b/Patches/Core/ThingDefs_Misc/Filth_Various.xml new file mode 100644 index 0000000000..fc535c21fa --- /dev/null +++ b/Patches/Core/ThingDefs_Misc/Filth_Various.xml @@ -0,0 +1,30 @@ + + + + + */ThingDef[defName="FilthFuel"]/thingClass + + CombatExtended.IncendiaryFuel + + + + + */ThingDef[defName="FilthFuel"]/statBases/MaxHitPoints + + 75 + + + + + */ThingDef[defName="FilthFuel"]/statBases/Flammability + + 5 + + + + + */ThingDef[defName="FilthFuel"]/filth/rainWashes + + + + diff --git a/Patches/Core/ThingDefs_Misc/Weapons_Grenades.xml b/Patches/Core/ThingDefs_Misc/Weapons_Grenades.xml new file mode 100644 index 0000000000..f9cf76f040 --- /dev/null +++ b/Patches/Core/ThingDefs_Misc/Weapons_Grenades.xml @@ -0,0 +1,509 @@ + + + + + + + */ThingDef[@Name="BaseGrenadeProjectile"]/thingClass + + CombatExtended.ProjectileCE_Explosive + + + + + */ThingDef[@Name="BaseGrenadeProjectile"]/projectile + Class + CombatExtended.ProjectilePropertiesCE + + + + */ThingDef[@Name="BaseGrenadeProjectile"]/projectile/speed + + 24 + + + + + + + + + */ThingDef[defName="Proj_GrenadeFrag"]/thingClass + + CombatExtended.ProjectileCE_Explosive + + + + + */ThingDef[defName="Proj_GrenadeFrag"]/graphicData/texPath + + Things/Projectile/Grenades/Frag + + + + + */ThingDef[defName="Proj_GrenadeFrag"]/projectile + + + 1.5 + Bomb + 50 + 60 + true + Mote_GrenadePin + + + + + + Always + +
  • + */ThingDef[defName="Proj_GrenadeFrag"]/comps + Invert +
  • +
  • + */ThingDef[defName="Proj_GrenadeFrag"] + + + +
  • +
    +
    + + + */ThingDef[defName="Proj_GrenadeFrag"]/comps + +
  • + + 250 + +
  • +
    +
    + + + + + */ThingDef[defName="Weapon_GrenadeFrag"]/label + + + + + + + */ThingDef[defName="Weapon_GrenadeFrag"]/graphicData + + + Things/Ammo/HandGrenades/Frag + Graphic_StackCount + 0 + + + + + + */ThingDef[defName="Weapon_GrenadeFrag"] + + CombatExtended.AmmoThing + 75 + Normal + First + + + + + */ThingDef[defName="Weapon_GrenadeFrag"] + Class + CombatExtended.AmmoDef + + + + */ThingDef[defName="Weapon_GrenadeFrag"]/weaponTags + +
  • CE_AI_Grenade
  • +
  • CE_OneHandedWeapon
  • +
    +
    + + + */ThingDef[defName="Weapon_GrenadeFrag"]/statBases/MarketValue + + 5.25 + + + + + */ThingDef[defName="Weapon_GrenadeFrag"]/statBases/RangedWeapon_Cooldown + + 1 + + + + + */ThingDef[defName="Weapon_GrenadeFrag"]/statBases + + 0.15 + + + + + */ThingDef[defName="Weapon_GrenadeFrag"]/verbs + + +
  • + + CombatExtended.Verb_ShootCEOneUse + true + 10.0 + 0.8 + 4 + true + ThrowGrenade + + true + + Proj_GrenadeFrag + true +
  • +
    +
    +
    + + + */ThingDef[defName="Weapon_GrenadeFrag"]/smeltProducts + + + + Always + +
  • + */ThingDef[defName="Weapon_GrenadeFrag"]/comps + Invert +
  • +
  • + */ThingDef[defName="Weapon_GrenadeFrag"] + + + +
  • +
    +
    + + + */ThingDef[defName="Weapon_GrenadeFrag"]/comps + +
  • + 40 + Bomb + 1.5 + + 250 + +
  • +
    +
    + + + + + + + */ThingDef[defName="Proj_GrenadeMolotov"]/graphicData/texPath + + Things/Projectile/Grenades/Molotov + + + + + */ThingDef[defName="Proj_GrenadeMolotov"]/projectile + + + 1.5 + Flame + 30 + FilthFuel + 1 + + + + + + */ThingDef[defName="Proj_GrenadeMolotov"] + + CombatExtended.Projectile_FireTrail + + + + + + + */ThingDef[defName="Weapon_GrenadeMolotov"]/label + + + + + + + */ThingDef[defName="Weapon_GrenadeMolotov"]/graphicData + + + Things/Ammo/HandGrenades/Molotov + Graphic_StackCount + 0 + + + + + + */ThingDef[defName="Weapon_GrenadeMolotov"] + + CombatExtended.AmmoThing + 75 + Normal + First + + + + + */ThingDef[defName="Weapon_GrenadeMolotov"] + Class + CombatExtended.AmmoDef + + + + */ThingDef[defName="Weapon_GrenadeMolotov"]/weaponTags + +
  • CE_AI_Grenade
  • +
  • CE_OneHandedWeapon
  • +
    +
    + + + */ThingDef[defName="Weapon_GrenadeMolotov"]/statBases/MarketValue + + 2.10 + + + + + */ThingDef[defName="Weapon_GrenadeMolotov"]/statBases/RangedWeapon_Cooldown + + 1 + + + + + */ThingDef[defName="Weapon_GrenadeMolotov"]/statBases + + 0.15 + + + + + */ThingDef[defName="Weapon_GrenadeMolotov"]/verbs + + +
  • + + CombatExtended.Verb_ShootCEOneUse + true + 10 + 0.8 + 4 + true + true + ThrowMolotovCocktail + + true + + Proj_GrenadeMolotov + true +
  • +
    +
    +
    + + + Always + +
  • + */ThingDef[defName="Weapon_GrenadeMolotov"]/comps + Invert +
  • +
  • + */ThingDef[defName="Weapon_GrenadeMolotov"] + + + +
  • +
    +
    + + + */ThingDef[defName="Weapon_GrenadeMolotov"]/comps + +
  • + 1 + Flame + 0.5 + FilthFuel + 1 +
  • +
    +
    + + + + + + + */ThingDef[defName="Proj_GrenadeEMP"]/thingClass + + CombatExtended.ProjectileCE_Explosive + + + + + */ThingDef[defName="Proj_GrenadeEMP"]/graphicData/texPath + + Things/Projectile/Grenades/EMP + + + + + */ThingDef[defName="Proj_GrenadeEMP"]/projectile + + + 3 + EMP + 40 + 60 + true + Mote_GrenadePin + + + + + + Always + +
  • + */ThingDef[defName="Proj_GrenadeEMP"]/comps + Invert +
  • +
  • + */ThingDef[defName="Proj_GrenadeEMP"] + + + +
  • +
    +
    + + + */ThingDef[defName="Proj_GrenadeEMP"]/comps + +
  • + 10 + Electrical + 4 + Explosion_Bomb +
  • +
    +
    + + + + + */ThingDef[defName="Weapon_GrenadeEMP"]/label + + + + + + + */ThingDef[defName="Weapon_GrenadeEMP"]/graphicData + + + Things/Ammo/HandGrenades/EMP + Graphic_StackCount + 0 + + + + + + */ThingDef[defName="Weapon_GrenadeEMP"] + + CombatExtended.AmmoThing + 75 + Normal + First + + + + + */ThingDef[defName="Weapon_GrenadeEMP"] + Class + CombatExtended.AmmoDef + + + + */ThingDef[defName="Weapon_GrenadeEMP"]/weaponTags + +
  • CE_AI_Grenade
  • +
  • CE_OneHandedWeapon
  • +
    +
    + + + */ThingDef[defName="Weapon_GrenadeEMP"]/statBases/MarketValue + + 7.65 + + + + + */ThingDef[defName="Weapon_GrenadeEMP"]/statBases/RangedWeapon_Cooldown + + 1 + + + + + */ThingDef[defName="Weapon_GrenadeEMP"]/statBases + + 0.15 + + + + + */ThingDef[defName="Weapon_GrenadeEMP"]/verbs + + +
  • + + CombatExtended.Verb_ShootCEOneUse + true + 10 + 0.8 + 4 + false + ThrowGrenade + + true + + Proj_GrenadeEMP + true +
  • +
    +
    +
    + + + */ThingDef[defName="Weapon_GrenadeEMP"]/smeltProducts + + +
    + diff --git a/Patches/Core/ThingDefs_Misc/Weapons_Guns.xml b/Patches/Core/ThingDefs_Misc/Weapons_Guns.xml new file mode 100644 index 0000000000..8bfd530bee --- /dev/null +++ b/Patches/Core/ThingDefs_Misc/Weapons_Guns.xml @@ -0,0 +1,2293 @@ + + + + + + + */ThingDef[@ParentName="BaseGun" or @ParentName="BaseHumanMakeableGun" or @ParentName="BaseWeaponNeolithic"]/statBases/AccuracyTouch + + + + */ThingDef[@ParentName="BaseGun" or @ParentName="BaseHumanMakeableGun" or @ParentName="BaseWeaponNeolithic"]/statBases/AccuracyShort + + + + */ThingDef[@ParentName="BaseGun" or @ParentName="BaseHumanMakeableGun" or @ParentName="BaseWeaponNeolithic"]/statBases/AccuracyMedium + + + + */ThingDef[@ParentName="BaseGun" or @ParentName="BaseHumanMakeableGun" or @ParentName="BaseWeaponNeolithic"]/statBases/AccuracyLong + + + + + + + + */ThingDef[defName="Gun_Pistol"]/statBases/Mass + + 1.11 + + + + + */ThingDef[defName="Gun_Pistol"]/statBases/RangedWeapon_Cooldown + + 0.38 + + + + + */ThingDef[defName="Gun_Pistol"]/statBases + + 0.35 + 0.17 + 1.32 + 2.10 + + + + + */ThingDef[defName="Gun_Pistol"]/verbs + + +
  • + CombatExtended.Verb_ShootCE + true + Bullet_45ACP_FMJ + 0.6 + 12 + ShotPistol + GunTail_Light + 9 +
  • +
    +
    +
    + + + + + Always + +
  • + */ThingDef[defName="Gun_Pistol"]/comps + Invert +
  • +
  • + */ThingDef[defName="Gun_Pistol"] + + + +
  • +
    +
    + + + */ThingDef[defName="Gun_Pistol"]/comps + +
  • + 7 + 4 + AmmoSet_45ACP +
  • +
  • + FALSE +
  • +
    +
    + + + + + Always + +
  • + */ThingDef[defName="Gun_Pistol"]/weaponTags + Invert +
  • +
  • + */ThingDef[defName="Gun_Pistol"] + + + +
  • +
    +
    + + + */ThingDef[defName="Gun_Pistol"]/weaponTags + +
  • CE_Sidearm
  • +
  • CE_AI_Pistol
  • +
  • CE_OneHandedWeapon
  • +
    +
    + + + + + */ThingDef[defName="Gun_Pistol"]/statBases/WorkToMake + + 5000 + + + + + */ThingDef[defName="Gun_Pistol"]/costList + + + 25 + 2 + + + + + + + + + + */ThingDef[defName="Gun_PumpShotgun"]/statBases/Mass + + 3.00 + + + + + */ThingDef[defName="Gun_PumpShotgun"]/statBases/RangedWeapon_Cooldown + + 1.0 + + + + + */ThingDef[defName="Gun_PumpShotgun"]/statBases + + 0.14 + 1.20 + 9.0 + 0.5 + + + + + */ThingDef[defName="Gun_PumpShotgun"]/verbs + + +
  • + CombatExtended.Verb_ShootCE + true + Bullet_12Gauge_Buck + 0.6 + 16 + ShotShotgun + GunTail_Heavy + 9 +
  • +
    +
    +
    + + + + + Always + +
  • + */ThingDef[defName="Gun_PumpShotgun"]/comps + Invert +
  • +
  • + */ThingDef[defName="Gun_PumpShotgun"] + + + +
  • +
    +
    + + + */ThingDef[defName="Gun_PumpShotgun"]/comps + +
  • + 5 + 4.25 + AmmoSet_12Gauge +
  • +
  • + + + + + + + Always + +
  • + */ThingDef[defName="Gun_PumpShotgun"]/weaponTags + Invert +
  • +
  • + */ThingDef[defName="Gun_PumpShotgun"] + + + +
  • + +
    + + + */ThingDef[defName="Gun_PumpShotgun"]/weaponTags + +
  • CE_AI_AssaultWeapon
  • +
    +
    + + + + + */ThingDef[defName="Gun_PumpShotgun"]/statBases/WorkToMake + + 8500 + + + + + */ThingDef[defName="Gun_PumpShotgun"]/costList + + + 40 + 10 + 1 + + + + + + + + + + */ThingDef[defName="Gun_ChainShotgun"]/statBases/Mass + + 3.50 + + + + + */ThingDef[defName="Gun_ChainShotgun"]/statBases/RangedWeapon_Cooldown + + 0.39 + + + + + */ThingDef[defName="Gun_ChainShotgun"]/statBases + + 0.15 + 1.26 + 6.7 + 0.5 + + + + + */ThingDef[defName="Gun_ChainShotgun"]/verbs + + +
  • + CombatExtended.Verb_ShootCE + true + Bullet_12Gauge_Buck + 0.6 + 16 + ShotShotgun + GunTail_Heavy + 9 + 15 + 4.34 +
  • +
    +
    +
    + + + + + Always + +
  • + */ThingDef[defName="Gun_ChainShotgun"]/comps + Invert +
  • +
  • + */ThingDef[defName="Gun_ChainShotgun"] + + + +
  • +
    +
    + + + */ThingDef[defName="Gun_ChainShotgun"]/comps + +
  • + 8 + 4 + AmmoSet_12Gauge +
  • +
  • + + + + + + + Always + +
  • + */ThingDef[defName="Gun_ChainShotgun"]/weaponTags + Invert +
  • +
  • + */ThingDef[defName="Gun_ChainShotgun"] + + + +
  • + +
    + + + */ThingDef[defName="Gun_ChainShotgun"]/weaponTags + +
  • CE_AI_AssaultWeapon
  • +
    +
    + + + + + */ThingDef[defName="Gun_ChainShotgun"]/statBases/WorkToMake + + 13500 + + + + + */ThingDef[defName="Gun_ChainShotgun"]/costList + + + 40 + 2 + + + + + + + + + + */ThingDef[defName="Gun_BoltActionRifle"]/statBases/Mass + + 4.19 + + + + + */ThingDef[defName="Gun_BoltActionRifle"]/statBases/RangedWeapon_Cooldown + + 1.17 + + + + + */ThingDef[defName="Gun_BoltActionRifle"]/statBases + + 0.50 + 0.02 + 1.68 + 12.60 + + + + + */ThingDef[defName="Gun_BoltActionRifle"]/verbs + + +
  • + CombatExtended.Verb_ShootCE + true + Bullet_303British_FMJ + 1.4 + 55 + ShotBoltActionRifle + GunTail_Heavy + 9 +
  • +
    +
    +
    + + + + + Always + +
  • + */ThingDef[defName="Gun_BoltActionRifle"]/comps + Invert +
  • +
  • + */ThingDef[defName="Gun_BoltActionRifle"] + + + +
  • +
    +
    + + + */ThingDef[defName="Gun_BoltActionRifle"]/comps + +
  • + 10 + 4.3 + AmmoSet_303British +
  • +
  • + AimedShot +
  • +
    +
    + + + + + Always + +
  • + */ThingDef[defName="Gun_BoltActionRifle"]/weaponTags + Invert +
  • +
  • + */ThingDef[defName="Gun_BoltActionRifle"] + + + +
  • +
    +
    + + + */ThingDef[defName="Gun_BoltActionRifle"]/weaponTags + +
  • CE_AI_Rifle
  • +
    +
    + + + + + */ThingDef[defName="Gun_BoltActionRifle"]/statBases/WorkToMake + + 10500 + + + + + */ThingDef[defName="Gun_BoltActionRifle"]/costList + + + 50 + 15 + 1 + + + + + + + + + + */ThingDef[defName="Gun_AssaultRifle"]/statBases/Mass + + 3.26 + + + + + */ThingDef[defName="Gun_AssaultRifle"]/statBases/RangedWeapon_Cooldown + + 0.36 + + + + + */ThingDef[defName="Gun_AssaultRifle"]/statBases + + 0.50 + 0.07 + 1.33 + 10.03 + + + + + */ThingDef[defName="Gun_AssaultRifle"]/verbs + + +
  • + 1.18 + CombatExtended.Verb_ShootCE + true + Bullet_556x45mmNATO_FMJ + 1.1 + 55 + 6 + 4 + ShotAssaultRifle + GunTail_Medium + 9 +
  • +
    +
    +
    + + + + + Always + +
  • + */ThingDef[defName="Gun_AssaultRifle"]/comps + Invert +
  • +
  • + */ThingDef[defName="Gun_AssaultRifle"] + + + +
  • +
    +
    + + + */ThingDef[defName="Gun_AssaultRifle"]/comps + +
  • + 30 + 4 + AmmoSet_556x45mmNATO +
  • +
  • + 3 + TRUE + AimedShot +
  • +
    +
    + + + + + Always + +
  • + */ThingDef[defName="Gun_AssaultRifle"]/weaponTags + Invert +
  • +
  • + */ThingDef[defName="Gun_AssaultRifle"] + + + +
  • +
    +
    + + + */ThingDef[defName="Gun_AssaultRifle"]/weaponTags + +
  • CE_AI_Rifle
  • +
    +
    + + + + + */ThingDef[defName="Gun_AssaultRifle"]/statBases/WorkToMake + + 23500 + + + + + */ThingDef[defName="Gun_AssaultRifle"]/costList + + + 60 + 4 + + + + + + + + + + */ThingDef[defName="Gun_SniperRifle"]/statBases/Mass + + 7.30 + + + + + */ThingDef[defName="Gun_SniperRifle"]/statBases/RangedWeapon_Cooldown + + 1.16 + + + + + */ThingDef[defName="Gun_SniperRifle"]/statBases + + 1.6 + 0.05 + 1.92 + 10.92 + + + + + */ThingDef[defName="Gun_SniperRifle"]/verbs + + +
  • + CombatExtended.Verb_ShootCE + true + Bullet_762x51mmNATO_FMJ + 2.1 + 75 + ShotSniperRifle + GunTail_Heavy + 9 +
  • +
    +
    +
    + + + + + Always + +
  • + */ThingDef[defName="Gun_SniperRifle"]/comps + Invert +
  • +
  • + */ThingDef[defName="Gun_SniperRifle"] + + + +
  • +
    +
    + + + */ThingDef[defName="Gun_SniperRifle"]/comps + +
  • + 5 + 4 + AmmoSet_762x51mmNATO +
  • +
  • + AimedShot +
  • +
    +
    + + + + + Always + +
  • + */ThingDef[defName="Gun_SniperRifle"]/weaponTags + Invert +
  • +
  • + */ThingDef[defName="Gun_SniperRifle"] + + + +
  • +
    +
    + + + */ThingDef[defName="Gun_SniperRifle"]/weaponTags + +
  • CE_AI_Rifle
  • +
    +
    + + + + + */ThingDef[defName="Gun_SniperRifle"]/statBases/WorkToMake + + 22500 + + + + + */ThingDef[defName="Gun_SniperRifle"]/costList + + + 75 + 4 + + + + + + + + + + */ThingDef[defName="Gun_MachinePistol"]/statBases/Mass + + 3.50 + + + + + */ThingDef[defName="Gun_MachinePistol"]/statBases/RangedWeapon_Cooldown + + 0.36 + + + + + */ThingDef[defName="Gun_MachinePistol"]/statBases + + 0.50 + 0.12 + 0.99 + 4.7 + + + + + */ThingDef[defName="Gun_MachinePistol"]/verbs + + +
  • + 0.91 + CombatExtended.Verb_ShootCE + true + Bullet_9x19mmPara_FMJ + 0.6 + 20 + 6 + 6 + ShotMachinePistol + GunTail_Light + 9 +
  • +
    +
    +
    + + + + + Always + +
  • + */ThingDef[defName="Gun_MachinePistol"]/comps + Invert +
  • +
  • + */ThingDef[defName="Gun_MachinePistol"] + + + +
  • +
    +
    + + + */ThingDef[defName="Gun_MachinePistol"]/comps + +
  • + 32 + 4 + AmmoSet_9x19mmPara +
  • +
  • + 3 + FALSE +
  • +
    +
    + + + + + Always + +
  • + */ThingDef[defName="Gun_MachinePistol"]/weaponTags + Invert +
  • +
  • + */ThingDef[defName="Gun_MachinePistol"] + + + +
  • +
    +
    + + + */ThingDef[defName="Gun_MachinePistol"]/weaponTags + +
  • CE_SMG
  • +
  • CE_AI_AssaultWeapon
  • +
  • CE_OneHandedWeapon
  • +
    +
    + + + + + */ThingDef[defName="Gun_MachinePistol"]/statBases/WorkToMake + + 21500 + + + + + */ThingDef[defName="Gun_MachinePistol"]/costList + + + 45 + 4 + + + + + + + + + + */ThingDef[defName="Gun_HeavySMG"]/statBases/Mass + + 1.40 + + + + + */ThingDef[defName="Gun_HeavySMG"]/statBases/RangedWeapon_Cooldown + + 0.37 + + + + + */ThingDef[defName="Gun_HeavySMG"]/statBases + + 0.35 + 0.17 + 1.46 + 3.17 + + + + + */ThingDef[defName="Gun_HeavySMG"]/verbs + + +
  • + 2.16 + CombatExtended.Verb_ShootCE + true + Bullet_45ACP_FMJ + 0.6 + 16 + 6 + 9 + ShotHeavySMG + GunTail_Heavy + 9 +
  • +
    +
    +
    + + + + + Always + +
  • + */ThingDef[defName="Gun_HeavySMG"]/comps + Invert +
  • +
  • + */ThingDef[defName="Gun_HeavySMG"] + + + +
  • +
    +
    + + + */ThingDef[defName="Gun_HeavySMG"]/comps + +
  • + 20 + 4 + AmmoSet_9x19mmPara +
  • +
  • + 3 + FALSE +
  • +
    +
    + + + + + Always + +
  • + */ThingDef[defName="Gun_HeavySMG"]/weaponTags + Invert +
  • +
  • + */ThingDef[defName="Gun_HeavySMG"] + + + +
  • +
    +
    + + + */ThingDef[defName="Gun_HeavySMG"]/weaponTags + +
  • CE_SMG
  • +
  • CE_AI_AssaultWeapon
  • +
  • CE_OneHandedWeapon
  • +
    +
    + + + + + */ThingDef[defName="Gun_HeavySMG"]/statBases/WorkToMake + + 20000 + + + + + */ThingDef[defName="Gun_HeavySMG"]/costList + + + 45 + 4 + + + + + + + + + + */ThingDef[defName="Gun_IncendiaryLauncher"]/statBases/Mass + + 8 + + + + + */ThingDef[defName="Gun_IncendiaryLauncher"]/statBases/RangedWeapon_Cooldown + + 0.43 + + + + + */ThingDef[defName="Gun_IncendiaryLauncher"]/statBases + + 0.50 + 0.15 + 1.8 + 10 + + + + + */ThingDef[defName="Gun_IncendiaryLauncher"]/verbs + + +
  • + CombatExtended.Verb_ShootCE + true + Bullet_30x64mmFuel_Incendiary + true + 1.1 + 40 + 0 + ShotIncendiaryLauncher + GunTail_Medium + 14 + + true + +
  • +
    +
    +
    + + + + + Always + +
  • + */ThingDef[defName="Gun_IncendiaryLauncher"]/comps + Invert +
  • +
  • + */ThingDef[defName="Gun_IncendiaryLauncher"] + + + +
  • +
    +
    + + + */ThingDef[defName="Gun_IncendiaryLauncher"]/comps + +
  • + 5 + 4 + AmmoSet_30x64mmFuel +
  • +
  • + FALSE + SuppressFire +
  • +
    +
    + + + + + Always + +
  • + */ThingDef[defName="Gun_IncendiaryLauncher"]/weaponTags + Invert +
  • +
  • + */ThingDef[defName="Gun_IncendiaryLauncher"] + + + +
  • +
    +
    + + + */ThingDef[defName="Gun_IncendiaryLauncher"]/weaponTags + +
  • CE_AI_Rifle
  • +
  • CE_AI_Launcher
  • +
    +
    + + + + + */ThingDef[defName="Gun_IncendiaryLauncher"]/statBases/WorkToMake + + 33000 + + + + + */ThingDef[defName="Gun_IncendiaryLauncher"]/costList + + + 75 + 30 + 6 + + + + + + + + + + */ThingDef[defName="Gun_LMG"]/statBases/Mass + + 9.12 + + + + + */ThingDef[defName="Gun_LMG"]/statBases/RangedWeapon_Cooldown + + 0.56 + + + + + */ThingDef[defName="Gun_LMG"]/statBases + + 0.50 + 0.05 + 1.53 + 13.7 + + + + + */ThingDef[defName="Gun_LMG"]/verbs + + +
  • + 0.82 + CombatExtended.Verb_ShootCE + true + Bullet_762x54mmR_FMJ + 1.25 + 75 + 7 + 10 + ShotMinigun + GunTail_Medium + 9 + + true + + Mounted +
  • +
    +
    +
    + + + + + Always + +
  • + */ThingDef[defName="Gun_LMG"]/comps + Invert +
  • +
  • + */ThingDef[defName="Gun_LMG"] + + + +
  • +
    +
    + + + */ThingDef[defName="Gun_LMG"]/comps + +
  • + 47 + 4.9 + AmmoSet_762x54mmR +
  • +
  • + 5 + FALSE + SuppressFire +
  • +
    +
    + + + + + Always + +
  • + */ThingDef[defName="Gun_LMG"]/weaponTags + Invert +
  • +
  • + */ThingDef[defName="Gun_LMG"] + + + +
  • +
    +
    + + + */ThingDef[defName="Gun_LMG"]/weaponTags + +
  • CE_MachineGun
  • +
  • CE_AI_Suppressive
  • +
    +
    + + + + + */ThingDef[defName="Gun_LMG"]/statBases/WorkToMake + + 27000 + + + + + */ThingDef[defName="Gun_LMG"]/costList + + + 80 + 10 + 4 + + + + + + + + + + */ThingDef[defName="Gun_ChargeRifle"]/statBases/Mass + + 3.0 + + + + + */ThingDef[defName="Gun_ChargeRifle"]/statBases/RangedWeapon_Cooldown + + 0.36 + + + + + */ThingDef[defName="Gun_ChargeRifle"]/statBases + + 0.60 + 0.08 + 1.20 + 9.00 + + + + + */ThingDef[defName="Gun_ChargeRifle"]/verbs + + +
  • + 1.13 + CombatExtended.Verb_ShootCE + true + Bullet_6x24mmCharged + 1.0 + 55 + 5 + 6 + ShotChargeRifle + GunTail_Medium + 9 +
  • +
    +
    +
    + + + + + Always + +
  • + */ThingDef[defName="Gun_ChargeRifle"]/comps + Invert +
  • +
  • + */ThingDef[defName="Gun_ChargeRifle"] + + + +
  • +
    +
    + + + */ThingDef[defName="Gun_ChargeRifle"]/comps + +
  • + 30 + 4 + AmmoSet_6x24mmCharged +
  • +
  • + 3 + TRUE + AimedShot +
  • +
    +
    + + + + + Always + +
  • + */ThingDef[defName="Gun_ChargeRifle"]/weaponTags + Invert +
  • +
  • + */ThingDef[defName="Gun_ChargeRifle"] + + + +
  • +
    +
    + + + */ThingDef[defName="Gun_ChargeRifle"]/weaponTags + +
  • CE_AI_Rifle
  • +
    +
    + + + + + */ThingDef[defName="Gun_ChargeRifle"]/statBases/WorkToMake + + 42500 + + + + + */ThingDef[defName="Gun_ChargeRifle"]/costList + + + 55 + 25 + 9 + + + + + + + + + + */ThingDef[defName="Gun_TurretImprovised"]/statBases/RangedWeapon_Cooldown + + 0.35 + + + + + */ThingDef[defName="Gun_TurretImprovised"]/statBases + + 0.5 + 0.07 + 1.80 + 8.00 + + + + + */ThingDef[defName="Gun_TurretImprovised"]/verbs + + +
  • + 0.22 + CombatExtended.Verb_ShootCE + true + Bullet_556x45mmNATO_FMJ + 1.1 + 48 + 5 + 10 + GunShotA + GunTail_Light + 9 + Mounted +
  • +
    +
    +
    + + + + + Always + +
  • + */ThingDef[defName="Gun_TurretImprovised"]/comps + Invert +
  • +
  • + */ThingDef[defName="Gun_TurretImprovised"] + + + +
  • +
    +
    + + + */ThingDef[defName="Gun_TurretImprovised"]/comps + +
  • + 200 + 7.8 + false + AmmoSet_556x45mmNATO +
  • +
  • + AimedShot + true + true +
  • +
    +
    + + + + + + + */ThingDef[defName="Gun_Minigun"]/statBases/Mass + + 39.00 + + + + + */ThingDef[defName="Gun_Minigun"]/statBases/RangedWeapon_Cooldown + + 0.35 + + + + + */ThingDef[defName="Gun_Minigun"]/statBases + + 50 + 0.06 + 4.70 + 8.02 + + + + + */ThingDef[defName="Gun_Minigun"]/verbs + + +
  • + 0.09 + CombatExtended.Verb_ShootCE + true + Bullet_762x51mmNATO_FMJ + 1.1 + 75 + 300 + 1 + ShotMinigun + GunTail_Medium + 9 +
  • +
    +
    +
    + + + + + Always + +
  • + */ThingDef[defName="Gun_Minigun"]/comps + Invert +
  • +
  • + */ThingDef[defName="Gun_Minigun"] + + + +
  • +
    +
    + + + */ThingDef[defName="Gun_Minigun"]/comps + +
  • + 600 + 9.2 + AmmoSet_762x51mmNATO +
  • +
  • + AimedShot +
  • +
    +
    + + + + + Always + +
  • + */ThingDef[defName="Gun_Minigun"]/weaponTags + Invert +
  • +
  • + */ThingDef[defName="Gun_Minigun"] + + + +
  • +
    +
    + + + */ThingDef[defName="Gun_Minigun"]/weaponTags + +
  • CE_AI_Suppressive
  • +
    +
    + + + + + */ThingDef[defName="Gun_Minigun"] + ParentName + BaseGun + + + + */ThingDef[defName="Gun_Minigun"]/costList + + + + */ThingDef[defName="Gun_Minigun"]/recipeMaker + + + + */ThingDef[defName="Gun_Minigun"]/statBases + + 2200 + + + + + */ThingDef[defName="Gun_Minigun"] + + Never + True + True + + + + + + + + + */ThingDef[defName="Bullet_DoomsdayRocket"]/thingClass + + CombatExtended.ProjectileCE_Explosive + + + + + */ThingDef[defName="Bullet_DoomsdayRocket"]/projectile + + + Bomb + 250 + 7.8 + 100 + + + + + + Always + +
  • + */ThingDef[defName="Bullet_DoomsdayRocket"]/comps + Invert +
  • +
  • + */ThingDef[defName="Bullet_DoomsdayRocket"] + + + +
  • +
    +
    + + + */ThingDef[defName="Bullet_DoomsdayRocket"]/comps + +
  • + 1 + + 400 + +
  • +
    +
    + + + + + */ThingDef[defName="Gun_DoomsdayRocket"]/statBases/Mass + + 20.00 + + + + + */ThingDef[defName="Gun_DoomsdayRocket"]/statBases/RangedWeapon_Cooldown + + 1.5 + + + + + */ThingDef[defName="Gun_DoomsdayRocket"]/statBases + + 1.24 + 0.2 + 3.24 + 13.0 + + + + + */ThingDef[defName="Gun_DoomsdayRocket"]/verbs + + +
  • + CombatExtended.Verb_ShootCEOneUse + true + Bullet_DoomsdayRocket + 0.0 + 2.3 + 48 + 1 + InfernoCannon_Fire + GunTail_Heavy + true + + true + + 14 +
  • +
    +
    +
    + + + + + Always + +
  • + */ThingDef[defName="Gun_DoomsdayRocket"]/comps + Invert +
  • +
  • + */ThingDef[defName="Gun_DoomsdayRocket"] + + + +
  • +
    +
    + + + */ThingDef[defName="Gun_DoomsdayRocket"]/comps + +
  • + AimedShot +
  • +
    +
    + + + + + Always + +
  • + */ThingDef[defName="Gun_DoomsdayRocket"]/weaponTags + Invert +
  • +
  • + */ThingDef[defName="Gun_DoomsdayRocket"] + + + +
  • +
    +
    + + + */ThingDef[defName="Gun_DoomsdayRocket"]/weaponTags + +
  • CE_AI_Launcher
  • +
    +
    + + + + + */ThingDef[defName="Gun_DoomsdayRocket"]/statBases/MarketValue + + + + */ThingDef[defName="Gun_DoomsdayRocket"] + + + LargeRockets + + + 125 + 7 + 5 + + + + + + + + + + */ThingDef[defName="Bullet_Rocket"]/thingClass + + CombatExtended.ProjectileCE_Explosive + + + + + */ThingDef[defName="Bullet_Rocket"]/projectile + + + Bomb + 180 + 3.0 + 100 + + + + + + Always + +
  • + */ThingDef[defName="Bullet_Rocket"]/comps + Invert +
  • +
  • + */ThingDef[defName="Bullet_Rocket"] + + + +
  • +
    +
    + + + */ThingDef[defName="Bullet_Rocket"]/comps + +
  • + 1 + + 150 + +
  • +
    +
    + + + + + */ThingDef[defName="Gun_TripleRocket"]/statBases/Mass + + 12.00 + + + + + */ThingDef[defName="Gun_TripleRocket"]/statBases/RangedWeapon_Cooldown + + 1.5 + + + + + */ThingDef[defName="Gun_TripleRocket"]/statBases + + 0.5 + 0.2 + 2.20 + 13.00 + + + + + */ThingDef[defName="Gun_TripleRocket"]/verbs + + +
  • + CombatExtended.Verb_ShootCEOneUse + true + Bullet_Rocket + 2.0 + 1.9 + 40 + 20 + 3 + InfernoCannon_Fire + GunTail_Heavy + true + false + + true + + 14 +
  • +
    +
    +
    + + + + + Always + +
  • + */ThingDef[defName="Gun_TripleRocket"]/comps + Invert +
  • +
  • + */ThingDef[defName="Gun_TripleRocket"] + + + +
  • +
    +
    + + + */ThingDef[defName="Gun_TripleRocket"]/comps + +
  • + FALSE + AimedShot + true +
  • +
    +
    + + + + + Always + +
  • + */ThingDef[defName="Gun_TripleRocket"]/weaponTags + Invert +
  • +
  • + */ThingDef[defName="Gun_TripleRocket"] + + + +
  • +
    +
    + + + */ThingDef[defName="Gun_TripleRocket"]/weaponTags + +
  • CE_AI_Launcher
  • +
    +
    + + + + + */ThingDef[defName="Gun_TripleRocket"]/statBases/MarketValue + + + + */ThingDef[defName="Gun_TripleRocket"] + + + LargeRockets + + + 90 + 6 + 3 + + + + + + + + + + */ThingDef[defName="Gun_ChargeBlasterHeavy"]/statBases/Mass + + 35.00 + + + + + */ThingDef[defName="Gun_ChargeBlasterHeavy"]/statBases/RangedWeapon_Cooldown + + 0.36 + + + + + */ThingDef[defName="Gun_ChargeBlasterHeavy"]/statBases + + 0.5 + 0.01 + 4.80 + 13.00 + + + + + */ThingDef[defName="Gun_ChargeBlasterHeavy"]/verbs + + +
  • + 0.75 + CombatExtended.Verb_ShootCE + true + Bullet_12x64mmCharged + 2.9 + 1.1 + 86 + 6 + 20 + ShotChargeBlaster + GunTail_Heavy + 9 + Mounted +
  • +
    +
    +
    + + + + + Always + +
  • + */ThingDef[defName="Gun_ChargeBlasterHeavy"]/comps + Invert +
  • +
  • + */ThingDef[defName="Gun_ChargeBlasterHeavy"] + + + +
  • +
    +
    + + + */ThingDef[defName="Gun_ChargeBlasterHeavy"]/comps + +
  • + 100 + 9.2 + AmmoSet_12x64mmCharged +
  • +
  • + 5 + AimedShot +
  • +
    +
    + + + + + Always + +
  • + */ThingDef[defName="Gun_ChargeBlasterHeavy"]/weaponTags + Invert +
  • +
  • + */ThingDef[defName="Gun_ChargeBlasterHeavy"] + + + +
  • +
    +
    + + + */ThingDef[defName="Gun_ChargeBlasterHeavy"]/weaponTags + +
  • CE_AI_Suppressive
  • +
    +
    + + + + + + + */ThingDef[defName="Gun_InfernoCannon"]/statBases/Mass + + 300.00 + + + + + */ThingDef[defName="Gun_InfernoCannon"]/statBases/RangedWeapon_Cooldown + + 2.53 + + + + + */ThingDef[defName="Gun_InfernoCannon"]/statBases + + 0.5 + 0.01 + 0.82 + 20.00 + + + + + */ThingDef[defName="Gun_InfernoCannon"]/verbs + + +
  • + CombatExtended.Verb_ShootCE + true + Bullet_80x256mmFuel_Thermobaric + true + 4.1 + 86 + 1 + InfernoCannon_Fire + GunTail_Light + 14 +
  • +
    +
    +
    + + + + + Always + +
  • + */ThingDef[defName="Gun_InfernoCannon"]/comps + Invert +
  • +
  • + */ThingDef[defName="Gun_InfernoCannon"] + + + +
  • +
    +
    + + + */ThingDef[defName="Gun_InfernoCannon"]/comps + +
  • + 1 + 9.8 + AmmoSet_80x256mmFuel +
  • +
  • + AimedShot +
  • +
    +
    + + + + + Always + +
  • + */ThingDef[defName="Gun_InfernoCannon"]/weaponTags + Invert +
  • +
  • + */ThingDef[defName="Gun_InfernoCannon"] + + + +
  • +
    +
    + + + */ThingDef[defName="Gun_InfernoCannon"]/weaponTags + +
  • CE_AI_Launcher
  • +
    +
    + + + + + + + */ThingDef[defName="Gun_ChargeLance"]/statBases/Mass + + 8.00 + + + + + */ThingDef[defName="Gun_ChargeLance"]/statBases/RangedWeapon_Cooldown + + 0.35 + + + + + */ThingDef[defName="Gun_ChargeLance"]/statBases + + 0.5 + 0.01 + 2.10 + 13.00 + + + + + */ThingDef[defName="Gun_ChargeLance"]/verbs + + +
  • + CombatExtended.Verb_ShootCE + true + Bullet_5x35mmCharged + 1.1 + 62 + 1 + ChargeLance_Fire + GunTail_Heavy + 9 +
  • +
    +
    +
    + + + + + Always + +
  • + */ThingDef[defName="Gun_ChargeLance"]/comps + Invert +
  • +
  • + */ThingDef[defName="Gun_ChargeLance"] + + + +
  • +
    +
    + + + */ThingDef[defName="Gun_ChargeLance"]/comps + +
  • + 1 + 1.6 + AmmoSet_5x35mmCharged +
  • +
  • + AimedShot +
  • +
    +
    + + + + + Always + +
  • + */ThingDef[defName="Gun_ChargeLance"]/weaponTags + Invert +
  • +
  • + */ThingDef[defName="Gun_ChargeLance"] + + + +
  • +
    +
    + + + */ThingDef[defName="Gun_ChargeLance"]/weaponTags + +
  • CE_AI_Rifle
  • +
    +
    + +
    + diff --git a/Patches/Core/ThingDefs_Misc/Weapons_Melee.xml b/Patches/Core/ThingDefs_Misc/Weapons_Melee.xml new file mode 100644 index 0000000000..baa9c21b26 --- /dev/null +++ b/Patches/Core/ThingDefs_Misc/Weapons_Melee.xml @@ -0,0 +1,486 @@ + + + + + + + */ThingDef[@ParentName="BaseMeleeWeapon_Sharp" or @ParentName="BaseMeleeWeapon_Blunt"]/stuffCategories/li[.="Metallic"] + +
  • Metallic_Weapon
  • +
    +
    + + + + + + + */ThingDef[defName="MeleeWeapon_Shiv"]/statBases/MeleeWeapon_DamageAmount + + 10 + + + + + */ThingDef[defName="MeleeWeapon_Shiv"]/statBases/MeleeWeapon_Cooldown + + 0.83 + + + + + */ThingDef[defName="MeleeWeapon_Shiv"]/statBases + + 0.125 + 1 + + + + + */ThingDef[defName="MeleeWeapon_Shiv"] + + + 0.1 + 0.1 + + + + + + */ThingDef[defName="MeleeWeapon_Shiv"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + true + Stab +
  • +
    +
    +
    + + + + + Always + +
  • + */ThingDef[defName="MeleeWeapon_Shiv"]/weaponTags + Invert +
  • +
  • + */ThingDef[defName="MeleeWeapon_Shiv"] + + + +
  • +
    +
    + + + */ThingDef[defName="MeleeWeapon_Shiv"]/weaponTags + +
  • CE_Sidearm_Melee
  • +
  • CE_OneHandedWeapon
  • +
    +
    + + + + + + + */ThingDef[defName="MeleeWeapon_Knife"]/statBases/MeleeWeapon_DamageAmount + + 12 + + + + + */ThingDef[defName="MeleeWeapon_Knife"]/statBases/MeleeWeapon_Cooldown + + 0.83 + + + + + */ThingDef[defName="MeleeWeapon_Knife"]/statBases + + 0.175 + 1 + + + + + */ThingDef[defName="MeleeWeapon_Knife"] + + + 0.25 + 0.25 + + + + + + */ThingDef[defName="MeleeWeapon_Knife"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + true + Stab +
  • +
    +
    +
    + + + + + Always + +
  • + */ThingDef[defName="MeleeWeapon_Knife"]/weaponTags + Invert +
  • +
  • + */ThingDef[defName="MeleeWeapon_Knife"] + + + +
  • +
    +
    + + + */ThingDef[defName="MeleeWeapon_Knife"]/weaponTags + +
  • CE_Sidearm_Melee
  • +
  • CE_OneHandedWeapon
  • +
    +
    + + + + + + + */ThingDef[defName="MeleeWeapon_Club"]/statBases/MeleeWeapon_DamageAmount + + 13 + + + + + */ThingDef[defName="MeleeWeapon_Club"]/statBases/MeleeWeapon_Cooldown + + 1.35 + + + + + */ThingDef[defName="MeleeWeapon_Club"]/statBases + + 0.13 + 4 + + + + + */ThingDef[defName="MeleeWeapon_Club"] + + + 0.5 + 0.25 + + + + + + */ThingDef[defName="MeleeWeapon_Club"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + true + Blunt +
  • +
    +
    +
    + + + + + Always + +
  • + */ThingDef[defName="MeleeWeapon_Club"]/weaponTags + Invert +
  • +
  • + */ThingDef[defName="MeleeWeapon_Club"] + + + +
  • +
    +
    + + + */ThingDef[defName="MeleeWeapon_Club"]/weaponTags + +
  • CE_Sidearm_Tribal
  • +
  • CE_OneHandedWeapon
  • +
    +
    + + + + + + + */ThingDef[defName="MeleeWeapon_Mace"]/statBases/MeleeWeapon_DamageAmount + + 16 + + + + + */ThingDef[defName="MeleeWeapon_Mace"]/statBases/MeleeWeapon_Cooldown + + 1.05 + + + + + */ThingDef[defName="MeleeWeapon_Mace"]/statBases + + 0.16 + 3.5 + + + + + */ThingDef[defName="MeleeWeapon_Mace"] + + + 0.65 + 0.4 + + + + + + */ThingDef[defName="MeleeWeapon_Mace"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + true + Blunt +
  • +
    +
    +
    + + + + + Always + +
  • + */ThingDef[defName="MeleeWeapon_Mace"]/weaponTags + Invert +
  • +
  • + */ThingDef[defName="MeleeWeapon_Mace"] + + + +
  • +
    +
    + + + */ThingDef[defName="MeleeWeapon_Mace"]/weaponTags + +
  • CE_OneHandedWeapon
  • +
    +
    + + + + + + + */ThingDef[defName="MeleeWeapon_Gladius"]/statBases/MeleeWeapon_DamageAmount + + 14 + + + + + */ThingDef[defName="MeleeWeapon_Gladius"]/statBases/MeleeWeapon_Cooldown + + 0.975 + + + + + */ThingDef[defName="MeleeWeapon_Gladius"]/statBases + + 0.2 + 3.5 + + + + + */ThingDef[defName="MeleeWeapon_Gladius"] + + + 0.5 + 0.65 + + + + + + */ThingDef[defName="MeleeWeapon_Gladius"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + true + Stab +
  • +
    +
    +
    + + + + + Always + +
  • + */ThingDef[defName="MeleeWeapon_Gladius"]/weaponTags + Invert +
  • +
  • + */ThingDef[defName="MeleeWeapon_Gladius"] + + + +
  • +
    +
    + + + */ThingDef[defName="MeleeWeapon_Gladius"]/weaponTags + +
  • CE_OneHandedWeapon
  • +
    +
    + + + + + + + */ThingDef[defName="MeleeWeapon_Spear"]/statBases/MeleeWeapon_DamageAmount + + 18 + + + + + */ThingDef[defName="MeleeWeapon_Spear"]/statBases/MeleeWeapon_Cooldown + + 1.15 + + + + + */ThingDef[defName="MeleeWeapon_Spear"]/statBases + + 0.275 + 10 + + + + + */ThingDef[defName="MeleeWeapon_Spear"] + + + 0.5 + 0.5 + 0.25 + + + + + + */ThingDef[defName="MeleeWeapon_Spear"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + true + Stab +
  • +
    +
    +
    + + + + + + + */ThingDef[defName="MeleeWeapon_LongSword"]/statBases/MeleeWeapon_DamageAmount + + 16 + + + + + */ThingDef[defName="MeleeWeapon_LongSword"]/statBases/MeleeWeapon_Cooldown + + 1.25 + + + + + */ThingDef[defName="MeleeWeapon_LongSword"] + + + 1 + 0.75 + + + + + + */ThingDef[defName="MeleeWeapon_LongSword"]/statBases + + 0.225 + 8 + + + + + */ThingDef[defName="MeleeWeapon_LongSword"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + true + Stab +
  • +
    +
    +
    + +
    + diff --git a/Patches/Core/ThingDefs_Misc/Weapons_RangedNeolithic.xml b/Patches/Core/ThingDefs_Misc/Weapons_RangedNeolithic.xml new file mode 100644 index 0000000000..e740e655fc --- /dev/null +++ b/Patches/Core/ThingDefs_Misc/Weapons_RangedNeolithic.xml @@ -0,0 +1,153 @@ + + + + + + + + + */ThingDef[defName="Bow_Short"]/statBases/RangedWeapon_Cooldown + + 1 + + + + + */ThingDef[defName="Bow_Short"]/statBases + + 0.35 + 1 + 2 + 3.00 + + + + + */ThingDef[defName="Bow_Short"]/verbs + + +
  • + CombatExtended.Verb_ShootCE + true + Projectile_Arrow_Stone + 1 + 28 + BowSmall +
  • +
    +
    +
    + + + + + Always + +
  • + */ThingDef[defName="Bow_Short"]/comps + Invert +
  • +
  • + */ThingDef[defName="Bow_Short"] + + + +
  • +
    +
    + + + */ThingDef[defName="Bow_Short"]/comps + +
  • + AmmoSet_Arrow +
  • +
  • + + + + + + + */ThingDef[defName="Bow_Short"]/weaponTags + +
  • CE_Bow
  • +
    +
    + + + + + + + */ThingDef[defName="Bow_Great"]/statBases/RangedWeapon_Cooldown + + 1 + + + + + */ThingDef[defName="Bow_Great"]/statBases + + 0.35 + 1 + 2 + 5.00 + + + + + */ThingDef[defName="Bow_Great"]/verbs + + +
  • + CombatExtended.Verb_ShootCE + true + Projectile_GreatArrow_Stone + 1.3 + 33 + BowLarge +
  • +
    +
    +
    + + + + + Always + +
  • + */ThingDef[defName="Bow_Great"]/comps + Invert +
  • +
  • + */ThingDef[defName="Bow_Great"] + + + +
  • +
    +
    + + + */ThingDef[defName="Bow_Great"]/comps + +
  • + AmmoSet_GreatArrow +
  • +
  • + + + + + + + */ThingDef[defName="Bow_Great"]/weaponTags + +
  • CE_Bow
  • +
    +
    + +
    + diff --git a/Patches/Core/ThingDefs_Races/Races_Animal_Arid.xml b/Patches/Core/ThingDefs_Races/Races_Animal_Arid.xml new file mode 100644 index 0000000000..b080ccf553 --- /dev/null +++ b/Patches/Core/ThingDefs_Races/Races_Animal_Arid.xml @@ -0,0 +1,303 @@ + + + + + + + */ThingDef[defName="Muffalo"]/statBases/MoveSpeed + + 5 + 0.12 + 0.27 + + + + + */ThingDef[defName="Muffalo"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 20 + Blunt + HeadAttackTool + 0.13 +
  • +
    +
    +
    + + + */ThingDef[defName="Muffalo"]/race/baseBodySize + + 2 + + + + + */ThingDef[defName="Muffalo"] + +
  • + Quadruped +
  • +
    +
    + + + + + */ThingDef[defName="Gazelle"]/statBases/MoveSpeed + + 6.2 + 0.21 + 0.10 + + + + + */ThingDef[defName="Gazelle"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 6 + Blunt + FrontLeftLeg + 0.1 +
  • +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 6 + Blunt + FrontRightLeg + 0.1 +
  • +
    +
    +
    + + + */ThingDef[defName="Gazelle"]/race/baseBodySize + + 0.5 + + + + + */ThingDef[defName="Gazelle"]/race/baseHealthScale + + 0.5 + + + + + */ThingDef[defName="Gazelle"] + +
  • + Quadruped +
  • +
    +
    + + + + + */ThingDef[defName="Iguana"]/statBases + + 0.14 + 0.02 + + + + + */ThingDef[defName="Iguana"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 0.9 + 6 + Scratch + FrontLeftClaws + 0.02 +
  • +
  • + CombatExtended.Verb_MeleeAttackCE + 0.9 + 6 + Scratch + FrontRightClaws + 0.02 +
  • +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 6 + Bite + Teeth + 0.12 +
  • +
    +
    +
    + + + */ThingDef[defName="Iguana"]/race/baseBodySize + + 0.28 + + + + + */ThingDef[defName="Iguana"]/race/baseHealthScale + + 0.3 + + + + + */ThingDef[defName="Iguana"] + +
  • + Serpentine +
  • +
    +
    + + + + + */ThingDef[defName="Rhinoceros"]/statBases/MoveSpeed + + 5.5 + 0.1 + 0.52 + 0.13 + 0.15 + + + + + */ThingDef[defName="Rhinoceros"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 20 + Stab + HornAttackTool + 0.35 +
  • +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 24 + Blunt + HornAttackTool + 0.2 + 0.5 +
  • +
    +
    +
    + + + */ThingDef[defName="Rhinoceros"]/race/baseBodySize + + 2.1 + + + + + */ThingDef[defName="Rhinoceros"]/race/baseHealthScale + + 2.3 + + + + + */ThingDef[defName="Rhinoceros"]/race/leatherStatFactors/ArmorRating_Blunt + + 1.2 + + + + + */ThingDef[defName="Rhinoceros"]/race/leatherStatFactors/ArmorRating_Sharp + + 1.5 + + + + + */ThingDef[defName="Rhinoceros"] + +
  • + Quadruped +
  • +
    +
    + + + + + */ThingDef[defName="Dromedary"]/statBases + + 0.08 + 0.13 + + + + + */ThingDef[defName="Dromedary"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 11 + Blunt + FrontLeftLeg + 0.1 +
  • +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 11 + Blunt + FrontRightLeg + 0.1 +
  • +
    +
    +
    + + + */ThingDef[defName="Dromedary"]/race/baseBodySize + + 1.1 + + + + + */ThingDef[defName="Dromedary"]/race/baseHealthScale + + 1 + + + + + */ThingDef[defName="Dromedary"] + +
  • + Quadruped +
  • +
    +
    + +
    + diff --git a/Patches/Core/ThingDefs_Races/Races_Animal_Base.xml b/Patches/Core/ThingDefs_Races/Races_Animal_Base.xml new file mode 100644 index 0000000000..a09c1f7f58 --- /dev/null +++ b/Patches/Core/ThingDefs_Races/Races_Animal_Base.xml @@ -0,0 +1,19 @@ + + + + + */ThingDef[@Name="BasePawn"]/inspectorTabs/li[.="ITab_Pawn_Gear"] + +
  • CombatExtended.ITab_Inventory
  • +
    +
    + + + */ThingDef[@Name="BasePawn"]/comps + +
  • + + + + + diff --git a/Patches/Core/ThingDefs_Races/Races_Animal_Bears.xml b/Patches/Core/ThingDefs_Races/Races_Animal_Bears.xml new file mode 100644 index 0000000000..37f44fd58d --- /dev/null +++ b/Patches/Core/ThingDefs_Races/Races_Animal_Bears.xml @@ -0,0 +1,128 @@ + + + + + + + */ThingDef[@Name="BaseBear"] + +
  • + Quadruped +
  • +
    +
    + + + */ThingDef[@Name="BaseBear"]/statBases/MoveSpeed + + 5.6 + + + + + */ThingDef[@Name="BaseBear"]/statBases + + 0.13 + 0.15 + 0.15 + 0.19 + + + + + */ThingDef[@Name="BaseBear"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 2.0 + 25 + Slash + FrontLeftPaw + 0.18 + + +
  • + Stun + 21 +
  • + + + +
  • + CombatExtended.Verb_MeleeAttackCE + 2.0 + 25 + Slash + FrontRightPaw + 0.18 + + +
  • + Stun + 21 +
  • + + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 30 + Bite + Teeth + 0.22 + + +
  • + Stun + 21 +
  • + + + +
    +
    +
    + + + */ThingDef[@Name="BaseBear"]/race/baseBodySize + + 1.15 + + + + + */ThingDef[@Name="BaseBear"]/race/baseHealthScale + + 1.3 + + + + + + + */ThingDef[defName="PolarBear"]/statBases + + 4.0 + 0.09 + 0.18 + + + + + */ThingDef[defName="PolarBear"]/race + + 1.55 + + + + + */ThingDef[defName="PolarBear"]/race + + 1.75 + + + +
    + diff --git a/Patches/Core/ThingDefs_Races/Races_Animal_BigCat.xml b/Patches/Core/ThingDefs_Races/Races_Animal_BigCat.xml new file mode 100644 index 0000000000..dc5f23b771 --- /dev/null +++ b/Patches/Core/ThingDefs_Races/Races_Animal_BigCat.xml @@ -0,0 +1,180 @@ + + + + + + + */ThingDef[@Name="BigCatThingBase"] + +
  • + Quadruped +
  • +
    +
    + + + */ThingDef[@Name="BigCatThingBase"]/statBases + + 0.23 + 0.12 + + + + + */ThingDef[@Name="BigCatThingBase"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.5 + 11 + Slash + FrontLeftPaw + 0.15 + + +
  • + Stun + 20 +
  • + + + 0.25 + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.5 + 11 + Slash + FrontRightPaw + 0.15 + + +
  • + Stun + 20 +
  • + + + 0.25 + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.85 + 20 + Bite + Teeth + 0.2 + + +
  • + Stun + 20 +
  • + + + +
    +
    +
    + + + */ThingDef[@Name="BigCatThingBase"]/race/baseBodySize + + 0.85 + + + + + */ThingDef[@Name="BigCatThingBase"]/race/baseHealthScale + + 0.8 + + + + + + + */ThingDef[defName="Lynx"] + +
  • + Quadruped +
  • +
    +
    + + + */ThingDef[defName="Lynx"]/statBases + + 0.29 + 0.07 + + + + + */ThingDef[defName="Lynx"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.5 + 9 + Scratch + FrontLeftPaw + 0.1 + + +
  • + Stun + 20 +
  • + + + 0.25 + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.5 + 9 + Scratch + FrontRightPaw + 0.1 + + +
  • + Stun + 20 +
  • + + + 0.25 + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.85 + 11 + Bite + Teeth + 0.2 + + +
  • + Stun + 20 +
  • + + + +
    +
    +
    + + + */ThingDef[defName="Lynx"]/race/baseHealthScale + + 0.75 + + + +
    + diff --git a/Patches/Core/ThingDefs_Races/Races_Animal_Birds.xml b/Patches/Core/ThingDefs_Races/Races_Animal_Birds.xml new file mode 100644 index 0000000000..2a55a60f37 --- /dev/null +++ b/Patches/Core/ThingDefs_Races/Races_Animal_Birds.xml @@ -0,0 +1,277 @@ + + + + + + + */ThingDef[@Name="BigBirdThingBase"] + +
  • + Birdlike +
  • +
    +
    + + + + + */ThingDef[defName="Cassowary"]/statBases/MoveSpeed + + 5 + 0.17 + 0.09 + + + + + */ThingDef[defName="Cassowary"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 15 + Cut + Feet + 0.15 + + +
  • + Stun + 20 +
  • + + + +
  • + CombatExtended.Verb_MeleeAttackCE + 0.6 + 5 + Bite + Beak + 0.05 + + +
  • + Stun + 20 +
  • + + + 0.1 + +
    +
    +
    + + + */ThingDef[defName="Cassowary"]/race/baseBodySize + + 0.9 + + + + + */ThingDef[defName="Cassowary"]/race/baseHealthScale + + 0.7 + + + + + + + */ThingDef[defName="Emu"]/statBases/MoveSpeed + + 4.8 + 0.20 + 0.06 + + + + + */ThingDef[defName="Emu"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 19 + Cut + Feet + 0.15 + + +
  • + Stun + 20 +
  • + + + +
  • + CombatExtended.Verb_MeleeAttackCE + 0.6 + 6 + Bite + Beak + 0.05 + + +
  • + Stun + 20 +
  • + + + 0.1 + +
    +
    +
    + + + */ThingDef[defName="Emu"]/race/baseBodySize + + 1 + + + + + */ThingDef[defName="Emu"]/race/baseHealthScale + + 0.8 + + + + + + + */ThingDef[defName="Ostrich"]/statBases + + 0.19 + 0.16 + + + + + */ThingDef[defName="Ostrich"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 19 + Cut + Feet + 0.15 + + +
  • + Stun + 20 +
  • + + + +
  • + CombatExtended.Verb_MeleeAttackCE + 0.6 + 6 + Bite + Beak + 0.05 + + +
  • + Stun + 20 +
  • + + + 0.1 + +
    +
    +
    + + + */ThingDef[defName="Ostrich"]/race/baseBodySize + + 1.2 + + + + + */ThingDef[defName="Ostrich"]/race/baseHealthScale + + 0.95 + + + + + + + */ThingDef[defName="Turkey"]/statBases + + 0.2 + 0.02 + + + + + */ThingDef[defName="Turkey"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 6 + Scratch + Feet + 0.06 + + +
  • + Stun + 20 +
  • + + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.85 + 5 + Bite + Beak + 0.04 + + +
  • + Stun + 20 +
  • + + + +
    +
    +
    + + + */ThingDef[defName="Turkey"]/race/baseBodySize + + 0.6 + + + + + */ThingDef[defName="Turkey"]/race/baseHealthScale + + 0.5 + + + +
    + diff --git a/Patches/Core/ThingDefs_Races/Races_Animal_Farm.xml b/Patches/Core/ThingDefs_Races/Races_Animal_Farm.xml new file mode 100644 index 0000000000..1dc21ff58e --- /dev/null +++ b/Patches/Core/ThingDefs_Races/Races_Animal_Farm.xml @@ -0,0 +1,182 @@ + + + + + + + */ThingDef[defName="Chicken"]/statBases + + 0.15 + 0.0 + + + + + */ThingDef[defName="Chicken"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 3 + Bite + Beak + 0.02 +
  • +
    +
    +
    + + + */ThingDef[defName="Chicken"]/race/baseBodySize + + 0.25 + + + + + */ThingDef[defName="Chicken"]/race/baseHealthScale + + 0.2 + + + + + */ThingDef[defName="Chicken"] + +
  • + Birdlike +
  • +
    +
    + + + + + */ThingDef[defName="Pig"]/statBases/MoveSpeed + + 2.6 + 0.07 + 0.06 + + + + + */ThingDef[defName="Pig"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 7 + Bite + Teeth + 0.1 +
  • +
    +
    +
    + + + */ThingDef[defName="Pig"]/race/baseHealthScale + + 0.85 + + + + + */ThingDef[defName="Pig"] + +
  • + Quadruped +
  • +
    +
    + + + + + */ThingDef[defName="Cow"]/statBases + + 0.15 + 0.13 + + + + + */ThingDef[defName="Cow"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 13 + Blunt + HeadAttackTool + 0.1 +
  • +
    +
    +
    + + + */ThingDef[defName="Cow"]/race/baseBodySize + + 1.8 + + + + + */ThingDef[defName="Cow"] + +
  • + Quadruped +
  • +
    +
    + + + + + */ThingDef[defName="Alpaca"]/statBases + + 0.14 + 0.06 + + + + + */ThingDef[defName="Alpaca"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 7 + Blunt + FrontLeftLeg + 0.06 +
  • +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 7 + Blunt + FrontRightLeg + 0.06 +
  • +
    +
    +
    + + + */ThingDef[defName="Alpaca"] + +
  • + Quadruped +
  • +
    +
    + +
    + diff --git a/Patches/Core/ThingDefs_Races/Races_Animal_Giant.xml b/Patches/Core/ThingDefs_Races/Races_Animal_Giant.xml new file mode 100644 index 0000000000..7988d2fbd4 --- /dev/null +++ b/Patches/Core/ThingDefs_Races/Races_Animal_Giant.xml @@ -0,0 +1,131 @@ + + + + + + + */ThingDef[defName="Elephant"]/statBases/MoveSpeed + + 5 + 0.08 + 0.79 + 0.10 + 0.125 + + + + + */ThingDef[defName="Elephant"]/statBases + + + + + + */ThingDef[defName="Elephant"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 2.0 + 35 + Stab + TuskAttackTool + 0.3 +
  • +
    +
    +
    + + + */ThingDef[defName="Elephant"] + +
  • + Quadruped +
  • +
    +
    + + + + + */ThingDef[defName="Megasloth"]/statBases + + 0.06 + 0.41 + 0.10 + 0.125 + + + + + */ThingDef[defName="Megasloth"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 2.3 + 22 + Slash + LeftHand + 0.25 +
  • +
  • + CombatExtended.Verb_MeleeAttackCE + 2.3 + 22 + Slash + RightHand + 0.25 +
  • +
    +
    +
    + + + */ThingDef[defName="Megasloth"] + +
  • + Quadruped +
  • +
    +
    + + + + + */ThingDef[defName="Thrumbo"]/statBases + + 0.09 + 0.76 + 0.2 + 0.3 + + + + + */ThingDef[defName="Thrumbo"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.85 + 40 + Cut + HornAttackTool + 0.4 +
  • +
    +
    +
    + + + */ThingDef[defName="Thrumbo"] + +
  • + Birdlike +
  • +
    +
    + +
    + diff --git a/Patches/Core/ThingDefs_Races/Races_Animal_Hares.xml b/Patches/Core/ThingDefs_Races/Races_Animal_Hares.xml new file mode 100644 index 0000000000..11d85cd9f8 --- /dev/null +++ b/Patches/Core/ThingDefs_Races/Races_Animal_Hares.xml @@ -0,0 +1,48 @@ + + + + + + + */ThingDef[@Name="BaseHare"]/statBases/MoveSpeed + + 4.8 + 0.24 + 0.02 + + + + + */ThingDef[@Name="BaseHare"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 3 + Bite + Teeth + 0.02 +
  • +
    +
    +
    + + + */ThingDef[@Name="BaseHare"]/race/baseHealthScale + + 0.15 + + + + + */ThingDef[@Name="BaseHare"] + +
  • + QuadrupedLow +
  • +
    +
    + +
    + diff --git a/Patches/Core/ThingDefs_Races/Races_Animal_Insect.xml b/Patches/Core/ThingDefs_Races/Races_Animal_Insect.xml new file mode 100644 index 0000000000..eb746407c1 --- /dev/null +++ b/Patches/Core/ThingDefs_Races/Races_Animal_Insect.xml @@ -0,0 +1,160 @@ + + + + + + + */ThingDef[@Name="BaseInsect"] + +
  • + QuadrupedLow +
  • +
    +
    + + + + + */ThingDef[defName="Megascarab"]/statBases/MoveSpeed + + 3.7 + 0.14 + 0.02 + + + + + */ThingDef[defName="Megascarab"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.85 + 7 + Bite + Mouth + 0.12 +
  • +
    +
    +
    + + + */ThingDef[defName="Megascarab"]/statBases/ArmorRating_Blunt + + 0.05 + + + + + */ThingDef[defName="Megascarab"]/statBases/ArmorRating_Sharp + + 0.05 + + + + + */ThingDef[defName="Megascarab"]/race/baseHealthScale + + 0.3 + + + + + + + */ThingDef[defName="Spelopede"]/statBases/MoveSpeed + + 3.7 + 0.08 + 0.12 + + + + + */ThingDef[defName="Spelopede"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.9 + 18 + Cut + HeadClaw + 0.25 +
  • +
    +
    +
    + + + */ThingDef[defName="Spelopede"]/statBases/ArmorRating_Blunt + + 0.2 + + + + + */ThingDef[defName="Spelopede"]/statBases/ArmorRating_Sharp + + 0.2 + + + + + */ThingDef[defName="Spelopede"]/race/baseHealthScale + + 1.2 + + + + + + + */ThingDef[defName="Megaspider"]/statBases/MoveSpeed + + 4 + 0.07 + 0.25 + + + + + */ThingDef[defName="Megaspider"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.9 + 30 + Cut + HeadClaw + 0.35 +
  • +
    +
    +
    + + + */ThingDef[defName="Megaspider"]/statBases/ArmorRating_Blunt + + 0.3 + + + + + */ThingDef[defName="Megaspider"]/statBases/ArmorRating_Sharp + + 0.3 + + + + + */ThingDef[defName="Megaspider"]/race/baseHealthScale + + 1.8 + + + +
    + diff --git a/Patches/Core/ThingDefs_Races/Races_Animal_Pet.xml b/Patches/Core/ThingDefs_Races/Races_Animal_Pet.xml new file mode 100644 index 0000000000..4c729abe40 --- /dev/null +++ b/Patches/Core/ThingDefs_Races/Races_Animal_Pet.xml @@ -0,0 +1,275 @@ + + + + + + + */ThingDef[defName="YorkshireTerrier"]/statBases + + 0.17 + 0.01 + + + + + */ThingDef[defName="YorkshireTerrier"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 3 + Scratch + FrontLeftPaw + 0.05 +
  • +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 3 + Scratch + FrontRightPaw + 0.05 +
  • +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 6 + Bite + Teeth + 0.08 +
  • +
    +
    +
    + + + */ThingDef[defName="YorkshireTerrier"]/race/baseHealthScale + + 0.3 + + + + + */ThingDef[defName="YorkshireTerrier"] + +
  • + Quadruped +
  • +
    +
    + + + + + */ThingDef[defName="Husky"]/statBases + + 0.22 + 0.05 + + + + + */ThingDef[defName="Husky"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 6 + Scratch + FrontLeftPaw + 0.08 +
  • +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 6 + Scratch + FrontRightPaw + 0.08 +
  • +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 16 + Bite + Teeth + 0.15 +
  • +
    +
    +
    + + + */ThingDef[defName="Husky"]/race/baseBodySize + + 0.65 + + + + + */ThingDef[defName="Husky"]/race/baseHealthScale + + 0.65 + + + + + */ThingDef[defName="Husky"] + +
  • + Quadruped +
  • +
    +
    + + + + + */ThingDef[defName="LabradorRetriever"]/statBases + + 0.19 + 0.06 + + + + + */ThingDef[defName="LabradorRetriever"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 5 + Scratch + FrontLeftPaw + 0.08 +
  • +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 5 + Scratch + FrontRightPaw + 0.08 +
  • +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 14 + Bite + Teeth + 0.15 +
  • +
    +
    +
    + + + */ThingDef[defName="LabradorRetriever"]/race/baseBodySize + + 0.65 + + + + + */ThingDef[defName="LabradorRetriever"]/race/baseHealthScale + + 0.65 + + + + + */ThingDef[defName="LabradorRetriever"] + +
  • + Quadruped +
  • +
    +
    + + + + + */ThingDef[defName="Cat"]/statBases + + 0.23 + 0.02 + + + + + */ThingDef[defName="Cat"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.0 + 6 + Scratch + FrontLeftPaw + 0.1 + + +
  • + Stun + 20 +
  • + + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.0 + 6 + Scratch + FrontRightPaw + 0.1 + + +
  • + Stun + 20 +
  • + + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 6 + Bite + Teeth + 0.15 + + +
  • + Stun + 20 +
  • + + + +
    +
    +
    + + + */ThingDef[defName="Cat"]/race/baseHealthScale + + 0.23 + + + + + */ThingDef[defName="Cat"] + +
  • + Quadruped +
  • +
    +
    + +
    + diff --git a/Patches/Core/ThingDefs_Races/Races_Animal_Rodentlike.xml b/Patches/Core/ThingDefs_Races/Races_Animal_Rodentlike.xml new file mode 100644 index 0000000000..53709d21e8 --- /dev/null +++ b/Patches/Core/ThingDefs_Races/Races_Animal_Rodentlike.xml @@ -0,0 +1,457 @@ + + + + + + + */ThingDef[defName="Squirrel"] + +
  • + QuadrupedLow +
  • +
    +
    + + + */ThingDef[defName="Squirrel"]/statBases/MoveSpeed + + 2.4 + 0.18 + 0.0 + + + + + */ThingDef[defName="Squirrel"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.85 + 3 + Scratch + FrontLeftPaw + 0.05 +
  • +
  • + CombatExtended.Verb_MeleeAttackCE + 1.85 + 3 + Scratch + FrontRightPaw + 0.05 +
  • +
  • + CombatExtended.Verb_MeleeAttackCE + 2.0 + 4 + Bite + Teeth + 0.06 +
  • +
    +
    +
    + + + */ThingDef[defName="Squirrel"]/race/baseHealthScale + + 0.12 + + + + + + + */ThingDef[defName="Alphabeaver"] + +
  • + QuadrupedLow +
  • +
    +
    + + + */ThingDef[defName="Alphabeaver"]/statBases/MoveSpeed + + 5 + 0.12 + 0.05 + + + + + */ThingDef[defName="Alphabeaver"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 6 + Scratch + FrontLeftPaw + 0.08 +
  • +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 6 + Scratch + FrontRightPaw + 0.08 +
  • +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 10 + Bite + Teeth + 0.15 +
  • +
    +
    +
    + + + + + */ThingDef[defName="Capybara"] + +
  • + Quadruped +
  • +
    +
    + + + */ThingDef[defName="Capybara"]/statBases + + 0.12 + 0.05 + + + + + */ThingDef[defName="Capybara"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 7 + Scratch + FrontLeftPaw + 0.1 +
  • +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 7 + Scratch + FrontRightPaw + 0.1 +
  • +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 8 + Bite + Teeth + 0.13 +
  • +
    +
    +
    + + + */ThingDef[defName="Capybara"]/race/baseBodySize + + 0.7 + + + + + + + */ThingDef[defName="Chinchilla"] + +
  • + QuadrupedLow +
  • +
    +
    + + + */ThingDef[defName="Chinchilla"]/statBases/MoveSpeed + + 2.84 + 0.23 + 0.0 + + + + + */ThingDef[defName="Chinchilla"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 2 + Scratch + FrontLeftPaw +
  • +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 2 + Scratch + FrontRightPaw +
  • +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 3 + Bite + Teeth +
  • +
    +
    +
    + + + */ThingDef[defName="Chinchilla"]/race/baseBodySize + + 0.17 + + + + + */ThingDef[defName="Chinchilla"]/race/baseHealthScale + + 0.12 + + + + + + + */ThingDef[defName="Boomrat"] + +
  • + QuadrupedLow +
  • +
    +
    + + + */ThingDef[defName="Boomrat"]/statBases/MoveSpeed + + 3.0 + 0.2 + 0.01 + + + + + */ThingDef[defName="Boomrat"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 3 + Scratch + FrontLeftPaw + 0.03 +
  • +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 3 + Scratch + FrontRightPaw + 0.03 +
  • +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 4 + Bite + Teeth + 0.05 +
  • +
    +
    +
    + + + */ThingDef[defName="Boomrat"]/race/baseHealthScale + + 0.2 + + + + + Always + +
  • + */ThingDef[defName="Boomrat"]/comps + Invert +
  • +
  • + */ThingDef[defName="Boomrat"] + + + +
  • +
    +
    + + + */ThingDef[defName="Boomrat"]/comps + +
  • + CombatExtended.CompShearableRenameable + Chemical fullness + 5 + 1 + FSX +
  • +
    +
    + + + + + */ThingDef[defName="Raccoon"] + +
  • + QuadrupedLow +
  • +
    +
    + + + */ThingDef[defName="Raccoon"]/statBases/MoveSpeed + + 3 + 0.15 + 0.01 + + + + + */ThingDef[defName="Raccoon"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 5 + Scratch + FrontLeftPaw + 0.05 +
  • +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 5 + Scratch + FrontRightPaw + 0.05 +
  • +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 10 + Bite + Teeth + 0.07 +
  • +
    +
    +
    + + + */ThingDef[defName="Raccoon"]/race/baseBodySize + + 0.35 + + + + + */ThingDef[defName="Raccoon"]/race/baseHealthScale + + 0.35 + + + + + + + */ThingDef[defName="Rat"] + +
  • + QuadrupedLow +
  • +
    +
    + + + */ThingDef[defName="Rat"]/statBases/MoveSpeed + + 2.3 + 0.18 + 0.0 + + + + + */ThingDef[defName="Rat"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 4 + Scratch + FrontLeftPaw + 0.05 +
  • +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 4 + Scratch + FrontRightPaw + 0.05 +
  • +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 5 + Bite + Teeth + 0.06 +
  • +
    +
    +
    + + + */ThingDef[defName="Rat"]/race/baseBodySize + + 0.2 + + + + + */ThingDef[defName="Rat"]/race/baseHealthScale + + 0.2 + + + +
    + diff --git a/Patches/Core/ThingDefs_Races/Races_Animal_Temperate.xml b/Patches/Core/ThingDefs_Races/Races_Animal_Temperate.xml new file mode 100644 index 0000000000..48cf1a0c38 --- /dev/null +++ b/Patches/Core/ThingDefs_Races/Races_Animal_Temperate.xml @@ -0,0 +1,377 @@ + + + + + + + */ThingDef[defName="Deer"] + +
  • + Quadruped +
  • +
    +
    + + + */ThingDef[defName="Deer"]/statBases/MoveSpeed + + 7 + 0.26 + 0.14 + + + + + */ThingDef[defName="Deer"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 7 + Blunt + FrontLeftLeg + 0.1 + 0.1 +
  • +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 7 + Blunt + FrontRightLeg + 0.1 + 0.1 +
  • +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 16 + Blunt + HeadAttackTool + 0.13 +
  • +
    +
    +
    + + + */ThingDef[defName="Deer"]/race/baseBodySize + + 1.15 + + + + + */ThingDef[defName="Deer"]/race/baseHealthScale + + 1.15 + + + + + + + */ThingDef[defName="Ibex"] + +
  • + Quadruped +
  • +
    +
    + + + */ThingDef[defName="Ibex"]/statBases/MoveSpeed + + 4.4 + 0.15 + 0.08 + + + + + */ThingDef[defName="Ibex"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 7 + Blunt + FrontLeftLeg + 0.1 + 0.1 +
  • +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 7 + Blunt + FrontRightLeg + 0.1 + 0.1 +
  • +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 16 + Blunt + HeadAttackTool + 0.13 +
  • +
    +
    +
    + + + */ThingDef[defName="Ibex"]/race/baseBodySize + + 0.9 + + + + + */ThingDef[defName="Ibex"]/race/baseHealthScale + + 0.9 + + + + + + + */ThingDef[defName="Elk"] + +
  • + Quadruped +
  • +
    +
    + + + */ThingDef[defName="Elk"]/statBases/MoveSpeed + + 7.24 + 0.2 + 0.34 + + + + + */ThingDef[defName="Elk"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.85 + 16 + Blunt + FrontLeftLeg + 0.13 + 0.1 +
  • +
  • + CombatExtended.Verb_MeleeAttackCE + 1.85 + 16 + Blunt + FrontRightLeg + 0.13 + 0.1 +
  • +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 23 + Blunt + HeadAttackTool + 0.2 +
  • +
    +
    +
    + + + */ThingDef[defName="Elk"]/race/baseBodySize + + 1.9 + + + + + */ThingDef[defName="Elk"]/race/baseHealthScale + + 1.9 + + + + + + + */ThingDef[defName="Caribou"] + +
  • + Quadruped +
  • +
    +
    + + + */ThingDef[defName="Caribou"]/statBases/MoveSpeed + + 7.84 + 0.29 + 0.22 + + + + + */ThingDef[defName="Caribou"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.85 + 16 + Blunt + FrontLeftLeg + 0.15 + 0.1 +
  • +
  • + CombatExtended.Verb_MeleeAttackCE + 1.85 + 16 + Blunt + FrontRightLeg + 0.15 + 0.1 +
  • +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 23 + Blunt + HeadAttackTool + 0.2 +
  • +
    +
    +
    + + + */ThingDef[defName="Caribou"]/race/baseBodySize + + 1.9 + + + + + */ThingDef[defName="Caribou"]/race/baseHealthScale + + 1.9 + + + + + + + */ThingDef[defName="WildBoar"] + +
  • + Quadruped +
  • +
    +
    + + + */ThingDef[defName="WildBoar"]/statBases/MoveSpeed + + 4.0 + 0.12 + 0.08 + + + + + */ThingDef[defName="WildBoar"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 9 + Scratch + TuskAttackTool + 0.2 +
  • +
    +
    +
    + + + */ThingDef[defName="WildBoar"]/race/baseBodySize + + 0.85 + + + + + */ThingDef[defName="WildBoar"]/race/baseHealthScale + + 0.85 + + + + + + + */ThingDef[defName="Tortoise"] + +
  • + QuadrupedLow +
  • +
    +
    + + + */ThingDef[defName="Tortoise"]/statBases/MoveSpeed + + 1.0 + 0.02 + 0.01 + + + + + */ThingDef[defName="Tortoise"]/statBases/ArmorRating_Blunt + + 0.2 + + + + + */ThingDef[defName="Tortoise"]/statBases/ArmorRating_Sharp + + 0.3 + + + + + */ThingDef[defName="Tortoise"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 3.1 + 15 + Bite + TurtleBeakAttackTool + 0.3 +
  • +
    +
    +
    + +
    + diff --git a/Patches/Core/ThingDefs_Races/Races_Animal_Tropical.xml b/Patches/Core/ThingDefs_Races/Races_Animal_Tropical.xml new file mode 100644 index 0000000000..34c566149b --- /dev/null +++ b/Patches/Core/ThingDefs_Races/Races_Animal_Tropical.xml @@ -0,0 +1,164 @@ + + + + + + + */ThingDef[defName="Cobra"] + +
  • + Serpentine +
  • +
    +
    + + + */ThingDef[defName="Cobra"]/statBases/MoveSpeed + + 3.84 + 0.17 + 0.02 + + + + + */ThingDef[defName="Cobra"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 10 + ToxicBite + Mouth + 0.12 + + +
  • + Stun + 20 +
  • + + + +
    +
    +
    + + + + + */ThingDef[defName="Monkey"] + +
  • + Humanoid +
  • +
    +
    + + + */ThingDef[defName="Monkey"]/statBases/MoveSpeed + + 5 + 0.24 + 0.03 + + + + + */ThingDef[defName="Monkey"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.3 + 4 + Blunt + LeftHand + 0.02 +
  • +
  • + CombatExtended.Verb_MeleeAttackCE + 1.3 + 4 + Blunt + RightHand + 0.02 +
  • +
    +
    +
    + + + */ThingDef[defName="Monkey"]/race/baseHealthScale + + 0.35 + + + + + + + */ThingDef[defName="Boomalope"] + +
  • + Quadruped +
  • +
    +
    + + + */ThingDef[defName="Boomalope"]/statBases + + 0.05 + 0.07 + + + + + */ThingDef[defName="Boomalope"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 20 + Blunt + HeadAttackTool + 0.13 +
  • +
    +
    +
    + + + Always + +
  • + */ThingDef[defName="Boomalope"]/comps + Invert +
  • +
  • + */ThingDef[defName="Boomalope"] + + + +
  • +
    +
    + + + */ThingDef[defName="Boomalope"]/comps + +
  • + CombatExtended.CompShearableRenameable + Chemical fullness + 20 + 20 + FSX +
  • +
    +
    + +
    + diff --git a/Patches/Core/ThingDefs_Races/Races_Animal_WildCanines.xml b/Patches/Core/ThingDefs_Races/Races_Animal_WildCanines.xml new file mode 100644 index 0000000000..c06f538f92 --- /dev/null +++ b/Patches/Core/ThingDefs_Races/Races_Animal_WildCanines.xml @@ -0,0 +1,273 @@ + + + + + + + */ThingDef[defName="Warg"] + +
  • + Quadruped +
  • +
    +
    + + + */ThingDef[defName="Warg"]/statBases/MoveSpeed + + 7 + + + + + */ThingDef[defName="Warg"]/statBases + + 0.075 + 0.125 + 0.21 + 0.20 + + + + + */ThingDef[defName="Warg"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.2 + 16 + Slash + FrontLeftPaw + 0.2 + + +
  • + Stun + 20 +
  • + + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.2 + 16 + Slash + FrontRightPaw + 0.2 + + +
  • + Stun + 20 +
  • + + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.8 + 30 + Bite + Teeth + 0.225 + + +
  • + Stun + 20 +
  • + + + 2 + +
    +
    +
    + + + */ThingDef[defName="Warg"]/race/baseHealthScale + + 1.25 + + + + + + + */ThingDef[@Name="ThingBaseWolf"] + +
  • + Quadruped +
  • +
    +
    + + + */ThingDef[@Name="ThingBaseWolf"]/statBases/MoveSpeed + + 6.25 + 0.26 + 0.09 + + + + + */ThingDef[@Name="ThingBaseWolf"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.5 + 9 + Scratch + FrontLeftPaw + 0.08 + + +
  • + Stun + 20 +
  • + + + 0.1 + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.5 + 9 + Scratch + FrontRightPaw + 0.08 + + +
  • + Stun + 20 +
  • + + + 0.1 + +
  • + CombatExtended.Verb_MeleeAttackCE + 2.0 + 18 + Bite + Teeth + 0.18 + + +
  • + Stun + 20 +
  • + + + +
    +
    +
    + + + */ThingDef[@Name="ThingBaseWolf"]/race/baseHealthScale + + 0.85 + + + + + + + */ThingDef[@Name="ThingBaseFox"] + +
  • + Quadruped +
  • +
    +
    + + + */ThingDef[@Name="ThingBaseFox"]/statBases + + 0.27 + 0.02 + + + + + */ThingDef[@Name="ThingBaseFox"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 7 + Scratch + FrontLeftPaw + 0.08 + + +
  • + Stun + 20 +
  • + + + 0.2 + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 6 + Scratch + FrontRightPaw + 0.08 + + +
  • + Stun + 20 +
  • + + + 0.2 + +
  • + CombatExtended.Verb_MeleeAttackCE + 2.1 + 10 + Bite + Teeth + 0.12 + + +
  • + Stun + 20 +
  • + + + +
    +
    +
    + + + */ThingDef[@Name="ThingBaseFox"]/race/baseBodySize + + 0.35 + + + + + */ThingDef[@Name="ThingBaseFox"]/race/baseHealthScale + + 0.35 + + + +
    + diff --git a/Patches/Core/ThingDefs_Races/Races_Humanlike.xml b/Patches/Core/ThingDefs_Races/Races_Humanlike.xml new file mode 100644 index 0000000000..6110fad083 --- /dev/null +++ b/Patches/Core/ThingDefs_Races/Races_Humanlike.xml @@ -0,0 +1,64 @@ + + + + + */ThingDef[defName="Human"] + +
  • + Humanoid +
  • +
    +
    + + + */ThingDef[defName="Human"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.85 + 6 + Blunt + LeftHand + 0.08 +
  • +
  • + CombatExtended.Verb_MeleeAttackCE + 1.85 + 6 + Blunt + RightHand + 0.08 +
  • +
    +
    +
    + + + Always + +
  • + */ThingDef[defName="Human"]/comps + Invert +
  • +
  • + */ThingDef[defName="Human"] + + + +
  • +
    +
    + + + */ThingDef[defName="Human"]/comps + +
  • + CombatExtended.CompPawnGizmo +
  • +
  • + + + + + diff --git a/Patches/Core/ThingDefs_Races/Races_Mechanoid.xml b/Patches/Core/ThingDefs_Races/Races_Mechanoid.xml new file mode 100644 index 0000000000..4add5e6489 --- /dev/null +++ b/Patches/Core/ThingDefs_Races/Races_Mechanoid.xml @@ -0,0 +1,158 @@ + + + + + + + */ThingDef[@Name="BaseMechanoid"]/statBases + + 1 + + + + + Always + +
  • + */ThingDef[@Name="BaseMechanoid"]/comps + Invert +
  • +
  • + */ThingDef[@Name="BaseMechanoid"] + + + +
  • + +
    + + + */ThingDef[@Name="BaseMechanoid"]/comps + +
  • + CombatExtended.CompPawnGizmo +
  • +
    +
    + + + + + */ThingDef[defName="Mechanoid_Centipede"] + +
  • + Quadruped +
  • +
    +
    + + + */ThingDef[defName="Mechanoid_Centipede"]/statBases + + 400 + 80 + 0.9 + 0.02 + 0.15 + + + + + */ThingDef[defName="Mechanoid_Centipede"]/statBases/ArmorRating_Blunt + + 0.4 + + + + + */ThingDef[defName="Mechanoid_Centipede"]/statBases/ArmorRating_Sharp + + 1 + + + + + */ThingDef[defName="Mechanoid_Centipede"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 2.0 + 50 + Blunt + HeadAttackTool + 0.3 +
  • +
    +
    +
    + + + */ThingDef[defName="Mechanoid_Centipede"]/race/baseHealthScale + + 2 + + + + + + + */ThingDef[defName="Mechanoid_Scyther"] + +
  • + Humanoid +
  • +
    +
    + + + */ThingDef[defName="Mechanoid_Scyther"]/statBases + + 50 + 20 + 0.9 + 0.19 + 0.22 + + + + + */ThingDef[defName="Mechanoid_Scyther"]/statBases/ArmorRating_Blunt + + 0.2 + + + + + */ThingDef[defName="Mechanoid_Scyther"]/statBases/ArmorRating_Sharp + + 0.45 + + + + + */ThingDef[defName="Mechanoid_Scyther"]/verbs + + +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 24 + Cut + LeftBlade + 0.4 +
  • +
  • + CombatExtended.Verb_MeleeAttackCE + 1.65 + 24 + Cut + RightBlade + 0.4 +
  • +
    +
    +
    + +
    + diff --git a/Patches/Core/ThinkTreeDefs/Humanlike.xml b/Patches/Core/ThinkTreeDefs/Humanlike.xml new file mode 100644 index 0000000000..d171bca076 --- /dev/null +++ b/Patches/Core/ThinkTreeDefs/Humanlike.xml @@ -0,0 +1,36 @@ + + + + + + + /ThinkTrees/ThinkTreeDef[defName="Humanlike"]/thinkRoot/subNodes/li[@Class="ThinkNode_ConditionalColonist"]/subNodes/li[subNodes/li[@Class="JobGiver_PackFood"]] + + + + + + /ThinkTrees/ThinkTreeDef[defName="Humanlike"]/thinkRoot/subNodes/li[@Class="ThinkNode_ConditionalColonist"]/subNodes/li[@Class="JobGiver_Work"] + +
  • +
  • + + + + + + + /ThinkTrees/ThinkTreeDef[defName="HumanlikeConstant"]/thinkRoot/subNodes/li[@Class="ThinkNode_ConditionalCanDoConstantThinkTreeJobNow"]/subNodes/li[@Class="JobGiver_FleeExplosion"] + +
  • + + + + + /ThinkTrees/ThinkTreeDef[defName="HumanlikeConstant"]/thinkRoot/subNodes/li[@Class="ThinkNode_ConditionalCanDoConstantThinkTreeJobNow"]/subNodes/li[@Class="JobGiver_ConfigurableHostilityResponse"] + Class + CombatExtended.JobGiver_ConfigurableHostilityResponse + + + + diff --git a/Patches/Core/TraderKindDefs/TraderKinds.xml b/Patches/Core/TraderKindDefs/TraderKinds.xml new file mode 100644 index 0000000000..61b4a4f48b --- /dev/null +++ b/Patches/Core/TraderKindDefs/TraderKinds.xml @@ -0,0 +1,203 @@ + + + + + + + + + /DefPackage-TraderKindDef/TraderKindDef/stockGenerators/li[thingDef="MortarShell"] + + + + + + /DefPackage-TraderKindDef/TraderKindDef[defName="Base_Outlander_Standard"]/stockGenerators + +
  • + CE_Ammo + + 500 + 2000 + + + 5 + 9 + +
  • +
  • + Ammo + + 0 + 0 + +
  • +
  • + CE_Turret + + -2 + 4 + + + 1 + 2 + +
  • +
  • + WeaponsTurrets + + 0 + 0 + +
  • +
    +
    + + + + + + + /DefPackage-TraderKindDef/TraderKindDef[defName="Caravan_Outlander_BulkGoods" or defName="Caravan_Outlander_PirateMerchant" or defName="Caravan_Outlander_Exotic"]/stockGenerators + +
  • + CE_Ammo + + 200 + 400 + + + 1 + 4 + +
  • +
  • + Ammo + + 0 + 0 + +
  • +
    +
    + + + + + /DefPackage-TraderKindDef/TraderKindDef[defName="Caravan_Outlander_CombatSupplier"]/stockGenerators + +
  • + CE_Ammo + + 400 + 1000 + + Cheap + + 3 + 8 + +
  • +
  • + Ammo + + 0 + 0 + +
  • +
  • + CE_Turret + + -4 + 2 + + + 1 + 1 + +
  • +
  • + WeaponsTurrets + + 0 + 0 + +
  • +
    +
    + + + + + + + /DefPackage-TraderKindDef/TraderKindDef[defName="Orbital_BulkGoods" or defName="Orbital_PirateMerchant" or defName="Orbital_Exotic"]/stockGenerators + +
  • + CE_Ammo + + 400 + 1000 + + + 1 + 4 + +
  • +
  • + Ammo + + 0 + 0 + +
  • +
    +
    + + + + + /DefPackage-TraderKindDef/TraderKindDef[defName="Orbital_CombatSupplier"]/stockGenerators + +
  • + CE_Ammo + + 1000 + 3000 + + Cheap + + 5 + 12 + +
  • +
  • + Ammo + + 0 + 0 + +
  • +
  • + CE_Turret + + -2 + 4 + + + 1 + 2 + +
  • +
  • + WeaponsTurrets + + 0 + 0 + +
  • +
    +
    + +
    + diff --git a/Patches/Core/WorkGiverDefs/WorkGivers.xml b/Patches/Core/WorkGiverDefs/WorkGivers.xml new file mode 100644 index 0000000000..2562a26ced --- /dev/null +++ b/Patches/Core/WorkGiverDefs/WorkGivers.xml @@ -0,0 +1,10 @@ + + + + /WorkGivers/WorkGiverDef[defName="HunterHunt"]/giverClass + + CombatExtended.WorkGiver_HunterHuntCE + + + + diff --git a/Source/CombatExtended.sln b/Source/CombatExtended.sln index 2187c2f658..b4ddc9dbac 100644 --- a/Source/CombatExtended.sln +++ b/Source/CombatExtended.sln @@ -3,16 +3,19 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 VisualStudioVersion = 14.0.25420.1 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CombatExtended", "CombatRealism\CombatExtended.csproj", "{AABEDCF4-2B5E-450E-B855-89595E67DC8D}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CombatExtended", "CombatExtended\CombatExtended.csproj", "{AABEDCF4-2B5E-450E-B855-89595E67DC8D}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU + Debugger|Any CPU = Debugger|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {AABEDCF4-2B5E-450E-B855-89595E67DC8D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {AABEDCF4-2B5E-450E-B855-89595E67DC8D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AABEDCF4-2B5E-450E-B855-89595E67DC8D}.Debug|Any CPU.ActiveCfg = Release|Any CPU + {AABEDCF4-2B5E-450E-B855-89595E67DC8D}.Debug|Any CPU.Build.0 = Release|Any CPU + {AABEDCF4-2B5E-450E-B855-89595E67DC8D}.Debugger|Any CPU.ActiveCfg = Debugger|Any CPU + {AABEDCF4-2B5E-450E-B855-89595E67DC8D}.Debugger|Any CPU.Build.0 = Debugger|Any CPU {AABEDCF4-2B5E-450E-B855-89595E67DC8D}.Release|Any CPU.ActiveCfg = Release|Any CPU {AABEDCF4-2B5E-450E-B855-89595E67DC8D}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection diff --git a/Source/CombatExtended/AI/CombatRole.cs b/Source/CombatExtended/AI/CombatRole.cs new file mode 100644 index 0000000000..53876b1cba --- /dev/null +++ b/Source/CombatExtended/AI/CombatRole.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using UnityEngine; + +namespace CombatExtended.AI +{ + public enum CombatRole : byte + { + Undefined, + Melee, + Assault, + Sniper, + Suppressor, + Grenadier, + Rocketeer + } +} diff --git a/Source/CombatExtended/AI/CombatRoleUtility.cs b/Source/CombatExtended/AI/CombatRoleUtility.cs new file mode 100644 index 0000000000..f5dbb84ebf --- /dev/null +++ b/Source/CombatExtended/AI/CombatRoleUtility.cs @@ -0,0 +1,206 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using UnityEngine; + +namespace CombatExtended.AI +{ + public static class CombatRoleUtility + { + #region Constants + + public const string AssaultTag = "CE_AI_AssaultWeapon"; + public const string PistolTag = "CE_AI_Pistol"; + public const string RifleTag = "CE_AI_Rifle"; + public const string SuppressTag = "CE_AI_Suppressive"; + public const string GrenadeTag = "CE_AI_Grenade"; + public const string NonlethalTag = "CE_AI_Nonlethal"; + public const string LauncherTag = "CE_AI_Launcher"; + + #endregion + + #region Methods + + #region Role Selection + + public static bool CanDoRole(this Pawn pawn, CombatRole role) + { + CompInventory comp = pawn.TryGetComp(); + if (comp == null) return false; + switch (role) + { + default: + return false; + case CombatRole.Melee: + return CanBeMelee(pawn, comp); + case CombatRole.Assault: + return CanBeAssault(pawn, comp); + case CombatRole.Sniper: + return CanBeSniper(pawn, comp); + case CombatRole.Suppressor: + return CanBeSuppressor(pawn, comp); + case CombatRole.Grenadier: + return CanBeGrenadier(pawn, comp); + case CombatRole.Rocketeer: + return CanBeRocketeer(pawn, comp); + } + } + + /// + /// Determines whether a pawn is elligible to be used as a melee combatant by its squad + /// + /// True if the pawn has a melee weapon and no ranged weapons with ammo, false otherwise + private static bool CanBeMelee(Pawn pawn, CompInventory comp) + { + bool hasMelee = !comp.meleeWeaponList.NullOrEmpty(); + bool hasRanged = comp.rangedWeaponList.Any(w => w.HasAmmo()); + return hasMelee && !hasRanged; + } + + /// + /// Determines whether a pawn is elligible to be used as a charging flanker unit by its squad + /// + /// True if the pawn has a gun tagged as assault weapon (e.g. SMG or shotgun) or their only ranged weapon is a pistol (with ammo), false otherwise + private static bool CanBeAssault(Pawn pawn, CompInventory comp) + { + if (comp.rangedWeaponList.NullOrEmpty()) return false; + bool hasPistol = false; + bool hasNonPistol = false; + foreach (ThingWithComps gun in comp.rangedWeaponList) + { + if (gun.def.IsAssaultGun() && gun.HasAmmo()) return true; + if (gun.def.IsPistol()) hasPistol = hasPistol || gun.HasAmmo(); + else hasNonPistol = hasNonPistol || gun.HasAmmo(); + } + return hasPistol && !hasNonPistol; + } + + /// + /// Determines whether a pawn is elligible to be used as a sniper, going for kills on high value targets + /// + /// True if pawn has a weapon tagged as rifle with ammo available, false otherwise + private static bool CanBeSniper(Pawn pawn, CompInventory comp) + { + return comp.rangedWeaponList.Any(w => w.def.IsRifle() && w.HasAmmo()); + } + + /// + /// Determines whether a pawn can be used to suppress targets + /// + /// True if the pawn has a weapon tagged for suppression and ammo available, false otherwise + private static bool CanBeSuppressor(Pawn pawn, CompInventory comp) + { + return comp.rangedWeaponList.Any(w => w.def.IsSuppressive() && w.HasAmmo()); + } + + /// + /// Determines whether a pawn has grenades they can use against a target + /// + /// True if the pawn has at least one destructive grenade in their inventory, false otherwise + private static bool CanBeGrenadier(Pawn pawn, CompInventory comp) + { + return comp.rangedWeaponList.Any(w => w.def.IsGrenade() && w.def.IsLethal()); + } + + /// + /// Determines whether a pawn can use a rocket/grenade launcher against fortified targets + /// + /// True if the pawn has a rocket/grenade launcher with ammo in their inventory, false otherwise + private static bool CanBeRocketeer(Pawn pawn, CompInventory comp) + { + return comp.rangedWeaponList.Any(w => w.def.IsLauncher() && w.HasAmmo()); + } + + #endregion + + #region Gun Extension Methods + + public static bool IsPistol(this ThingDef def) + { + return def.weaponTags.Contains(PistolTag); + } + + public static bool IsAssaultGun(this ThingDef def) + { + return def.weaponTags.Contains(AssaultTag); + } + + public static bool IsRifle(this ThingDef def) + { + return def.weaponTags.Contains(RifleTag); + } + + public static bool IsSuppressive(this ThingDef def) + { + return def.weaponTags.Contains(SuppressTag); + } + + public static bool IsGrenade(this ThingDef def) + { + return def.weaponTags.Contains(GrenadeTag); + } + + public static bool IsLauncher(this ThingDef def) + { + return def.weaponTags.Contains(LauncherTag); + } + + public static bool IsLethal(this ThingDef def) + { + return !def.weaponTags.Contains(NonlethalTag); + } + + #endregion + + /// + /// Finds the most damaging gun and grenade in a pawn's inventory for a given minimum range + /// + /// The Pawn whose inventory to search through + /// The minimum range the returned weapons must have, set to negative for unlimited + /// Pair where First is the highest DPS gun and Second is the highest damage/radius grenade in inventory, Pair with null values if no gun/grenade with the given range could be found or the Pawn has no CompInventory + internal static Pair GetBestGunAndGrenadeFor(Pawn pawn, int range = -1) + { + CompInventory inventory = pawn.TryGetComp(); + if (inventory == null) + { + Log.Error("CE tried calculating best gun and grenade for " + pawn.ToString() + " without CompInventory"); + return new Pair(); + } + ThingWithComps bestGun = null; + ThingWithComps bestGrenade = null; + float maxGunScore = 0f; + float maxGrenadeScore = 0f; + foreach (ThingWithComps curWeapon in inventory.rangedWeaponList) + { + CompEquippable compEq = curWeapon.TryGetComp(); + if (compEq.PrimaryVerb.verbProps.range > range && curWeapon.def.IsLethal()) + { + float score = 0f; + bool isGrenade = curWeapon.def.IsGrenade(); + if (isGrenade) + { + // Score the grenade based on damage and explosion radius and compare against stored max + ThingDef grenade = compEq.PrimaryVerb.verbProps.projectileDef; + score = grenade.projectile.damageAmountBase * grenade.projectile.explosionRadius * (grenade.HasComp(typeof(CompExplosiveCE)) ? 2 : 1); + if (score > maxGrenadeScore) bestGrenade = curWeapon; + } + else + { + // Score the gun based on DPS and compare against stored max + Verb verb = compEq.PrimaryVerb; + ThingDef bullet = verb as Verb_LaunchProjectileCE == null ? verb.verbProps.projectileDef : (verb as Verb_LaunchProjectileCE).ProjectileDef; + float secPerBurst = verb.verbProps.warmupTime + curWeapon.GetStatValue(StatDefOf.RangedWeapon_Cooldown) + (verb.verbProps.ticksBetweenBurstShots * verb.verbProps.burstShotCount); // Overall time for one burst + score = bullet.projectile.damageAmountBase * verb.verbProps.burstShotCount / secPerBurst; + if (score > maxGunScore) bestGun = curWeapon; + } + } + } + return new Pair(bestGun, bestGrenade); + } + + #endregion + } +} diff --git a/Source/CombatExtended/AI/Defs/RaidGoalDef.cs b/Source/CombatExtended/AI/Defs/RaidGoalDef.cs new file mode 100755 index 0000000000..9c04cf3980 --- /dev/null +++ b/Source/CombatExtended/AI/Defs/RaidGoalDef.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using UnityEngine; + +namespace CombatExtended.AI +{ + public class RaidGoalDef : Def + { + //RaidGoalFinder finderClass; + } +} diff --git a/Source/CombatExtended/AI/FactionBrain/FactionBrain.cs b/Source/CombatExtended/AI/FactionBrain/FactionBrain.cs new file mode 100644 index 0000000000..73465de6be --- /dev/null +++ b/Source/CombatExtended/AI/FactionBrain/FactionBrain.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Verse; +using RimWorld; +using UnityEngine; + +namespace CombatExtended.AI +{ + public class FactionBrain : IExposable + { + public FactionBrainManager manager; + private Faction faction; + + private SquadBrain brain; + + public Map Map => manager.map; + internal bool ShouldDelete => Map.mapPawns.SpawnedPawnsInFaction(faction).NullOrEmpty(); + internal int TickInterval { get { return 10; } } // TODO this should return the amount of ticks between running BrainTick() + + public FactionBrain() + { + } + + public FactionBrain(FactionBrainManager manager, Faction faction) + { + this.manager = manager; + this.faction = faction; + //LongEventHandler.ExecuteWhenFinished(InitBrain); + } + + private void InitBrain() + { + try + { + List list = new List(manager.map.mapPawns.FreeHumanlikesSpawnedOfFaction(faction)); + brain = new SquadBrain(list + , faction + , manager.map); + + foreach (Pawn p in list) + { + CompSquadBrain comp = p.TryGetComp(); + if (comp != null) comp.squad = brain; + } + } + catch (Exception er) + { + Log.Message(er.Message); + } + } + + public void BrainTick() + { + if (brain == null) InitBrain(); + + foreach (Pawn p in manager.map.mapPawns.FreeHumanlikesSpawnedOfFaction(faction)) + { + CompSquadBrain comp = p.TryGetComp(); + if (comp != null && comp.squad == null) + { + comp.squad = brain; + } + } + + + } + + public void ExposeData() + { + Scribe_Values.Look(ref faction, "faction", Faction.OfPlayer); + } + } +} diff --git a/Source/CombatExtended/AI/FactionBrain/FactionBrainManager.cs b/Source/CombatExtended/AI/FactionBrain/FactionBrainManager.cs new file mode 100644 index 0000000000..af6543e7ef --- /dev/null +++ b/Source/CombatExtended/AI/FactionBrain/FactionBrainManager.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Verse; +using RimWorld; +using UnityEngine; + +namespace CombatExtended.AI +{ + public class FactionBrainManager : MapComponent + { + private List brains = new List(); + + public FactionBrainManager(Map map) : base(map) + { + } + + public override void ExposeData() + { + base.ExposeData(); + Scribe_Collections.Look(ref brains, "brains", LookMode.Deep); + Action action = delegate + { + foreach (var brain in brains) + { + brain.manager = this; + } + }; + LongEventHandler.ExecuteWhenFinished(action); + } + + public override void MapComponentTick() + { + foreach(var brain in brains) + { + brain.BrainTick(); + } + } + } +} diff --git a/Source/CombatExtended/AI/Objectives/RaidGoalFinder.cs b/Source/CombatExtended/AI/Objectives/RaidGoalFinder.cs new file mode 100644 index 0000000000..2e306ecdcb --- /dev/null +++ b/Source/CombatExtended/AI/Objectives/RaidGoalFinder.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; + +namespace CombatExtended.AI +{ + public abstract class RaidGoalFinder + { + + } +} diff --git a/Source/CombatExtended/AI/Objectives/RaidGoalFinder_Targets.cs b/Source/CombatExtended/AI/Objectives/RaidGoalFinder_Targets.cs new file mode 100644 index 0000000000..cf63383f0b --- /dev/null +++ b/Source/CombatExtended/AI/Objectives/RaidGoalFinder_Targets.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using UnityEngine; + +namespace CombatExtended.AI +{ + public class RaidGoalFinder_HostilePawns + { + + } +} diff --git a/Source/CombatExtended/AI/Objectives/SquadObjective.cs b/Source/CombatExtended/AI/Objectives/SquadObjective.cs new file mode 100755 index 0000000000..70e31c5939 --- /dev/null +++ b/Source/CombatExtended/AI/Objectives/SquadObjective.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace CombatExtended.AI +{ + internal class SquadObjective + { + } +} diff --git a/Source/CombatExtended/AI/PathFinding/SquadPath.cs b/Source/CombatExtended/AI/PathFinding/SquadPath.cs new file mode 100755 index 0000000000..b445396fb3 --- /dev/null +++ b/Source/CombatExtended/AI/PathFinding/SquadPath.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using UnityEngine; + +namespace CombatExtended.AI +{ + public class SquadPath + { + public float fortificationStrength = 0; + public float defenderStrength = 0; + public List nodes = new List(); + } +} diff --git a/Source/CombatExtended/AI/PathFinding/SquadPathBrainPlus.cs b/Source/CombatExtended/AI/PathFinding/SquadPathBrainPlus.cs new file mode 100644 index 0000000000..9ec034d09e --- /dev/null +++ b/Source/CombatExtended/AI/PathFinding/SquadPathBrainPlus.cs @@ -0,0 +1,234 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using Verse.AI; +using UnityEngine; + +namespace CombatExtended.AI +{ + public class SquadBrainPlus + { + private readonly Map map; + private readonly Faction fac; + + private long tick_count; + + private List squadPawns; + + private Dictionary targets; + + private SquadPath path; + + private Region target; + + private enum states{ + moving = 1,ideal = 2,findingPath = 3 + } + + private states state = + states.ideal; + + public SquadBrainPlus(Map map, Faction fac) + { + this.map + = map; + this.tick_count + = 0; + this.fac + = fac; + + this.squadPawns + = map.mapPawns + .AllPawnsSpawned.FindAll((obj) => obj.Faction == Faction.OfPlayer); + this.targets + = new Dictionary(); + + Log.Message("Pawn number is " + squadPawns.Count); + } + + public void Tick() + { + if (tick_count % 100 == 0) + { + Log.Message("state number is " + state); + } + + if(tick_count++ % 10 == 0) + this.SearchForTarget(); + + if (state == states.findingPath) + { + this.FindPath(); + + this.state + = states.moving; + } + + if (tick_count % 6 == 0) + { + + } + + if (tick_count % 5 != 0) + return; + + if (state == states.ideal) + { + this.Ideal(); + } + + if (state == states.moving) + { + this.Move(); + } + } + + private void SearchForTarget() + { + var targetbed = map.listerThings + .AllThings + .Find( + (obj) => + obj.def.IsBed + ); + + this.target + = targetbed.GetRegion(); + + if (path == null) + { + this.state + = states.findingPath; + + return; + } + + if (path.nodes.Count == 0) + { + this.state + = states.findingPath; + } + + if (this.target == targetbed.GetRegion()) + return; + } + + private void Move() + { + if (path.nodes.Count == 0) + { + this.state + = states.ideal; + + return; + } + + if (path.nodes[0] == null) + { + path.nodes.RemoveAt(0); + return; + } + + foreach (Pawn pawn in squadPawns) + { + try + { + if (pawn.Position.GetRegion(map) != path.nodes[0]) + { + if (pawn.CurJob == null) + { + var region = path.nodes[0]; + + var targetCell = + region.RandomCell; + + while (!targetCell.Walkable(map)) + targetCell = region.AnyCell; + + pawn.jobs.StartJob( + new Job(JobDefOf.Goto, targetCell) + ); + } + else if (pawn.CurJob.def != JobDefOf.Goto || + pawn.CurJob.targetA.Cell.GetRegion(map) != path.nodes[0]) + { + + var region = path.nodes[0]; + + var targetCell = + region.RandomCell; + + while (!targetCell.Walkable(map)) + targetCell = region.RandomCell; + + pawn.jobs.StartJob( + new Job(JobDefOf.Goto, targetCell) + ); + + } + } + } + catch (Exception er) + { + Log.Message(er.ToString()); + } + } + + foreach (Pawn pawn in squadPawns) + { + if (pawn.Position.GetRegion(map) != path.nodes[0]) + return; + } + + path.nodes.RemoveAt(0); + } + + private void Ideal() + { + + } + + private void FindPath() + { + + this.squadPawns + = map.mapPawns + .AllPawnsSpawned.FindAll((obj) => obj.Faction == Faction.OfPlayer); + + Log.Message("Starting PathFinding"); + + SquadPather pather = + new SquadPather(map); + + + Log.Message("Starting PathFinding" + squadPawns[0] + .Position.GetRegion(map) + .Equals(this.target) + ); + + this.path = pather.GetSquadPathFromTo( + squadPawns[0].Position.GetRegion(map), + this.target, + this.fac, + 100 + ); + + Log.Message("nodes Counts " + this.path.nodes.Count); + } + + private void AssignJobToPawn(Job job,Pawn pawn) + { + if (pawn.drafter != null) + { + pawn.jobs.TryTakeOrderedJob(job); + } + else + { + ExternalPawnDrafter.TakeOrderedJob(pawn, job); + } + } + } +} diff --git a/Source/CombatExtended/AI/PathFinding/SquadPathBrainPlus.cs~ b/Source/CombatExtended/AI/PathFinding/SquadPathBrainPlus.cs~ new file mode 100644 index 0000000000..9ec034d09e --- /dev/null +++ b/Source/CombatExtended/AI/PathFinding/SquadPathBrainPlus.cs~ @@ -0,0 +1,234 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using Verse.AI; +using UnityEngine; + +namespace CombatExtended.AI +{ + public class SquadBrainPlus + { + private readonly Map map; + private readonly Faction fac; + + private long tick_count; + + private List squadPawns; + + private Dictionary targets; + + private SquadPath path; + + private Region target; + + private enum states{ + moving = 1,ideal = 2,findingPath = 3 + } + + private states state = + states.ideal; + + public SquadBrainPlus(Map map, Faction fac) + { + this.map + = map; + this.tick_count + = 0; + this.fac + = fac; + + this.squadPawns + = map.mapPawns + .AllPawnsSpawned.FindAll((obj) => obj.Faction == Faction.OfPlayer); + this.targets + = new Dictionary(); + + Log.Message("Pawn number is " + squadPawns.Count); + } + + public void Tick() + { + if (tick_count % 100 == 0) + { + Log.Message("state number is " + state); + } + + if(tick_count++ % 10 == 0) + this.SearchForTarget(); + + if (state == states.findingPath) + { + this.FindPath(); + + this.state + = states.moving; + } + + if (tick_count % 6 == 0) + { + + } + + if (tick_count % 5 != 0) + return; + + if (state == states.ideal) + { + this.Ideal(); + } + + if (state == states.moving) + { + this.Move(); + } + } + + private void SearchForTarget() + { + var targetbed = map.listerThings + .AllThings + .Find( + (obj) => + obj.def.IsBed + ); + + this.target + = targetbed.GetRegion(); + + if (path == null) + { + this.state + = states.findingPath; + + return; + } + + if (path.nodes.Count == 0) + { + this.state + = states.findingPath; + } + + if (this.target == targetbed.GetRegion()) + return; + } + + private void Move() + { + if (path.nodes.Count == 0) + { + this.state + = states.ideal; + + return; + } + + if (path.nodes[0] == null) + { + path.nodes.RemoveAt(0); + return; + } + + foreach (Pawn pawn in squadPawns) + { + try + { + if (pawn.Position.GetRegion(map) != path.nodes[0]) + { + if (pawn.CurJob == null) + { + var region = path.nodes[0]; + + var targetCell = + region.RandomCell; + + while (!targetCell.Walkable(map)) + targetCell = region.AnyCell; + + pawn.jobs.StartJob( + new Job(JobDefOf.Goto, targetCell) + ); + } + else if (pawn.CurJob.def != JobDefOf.Goto || + pawn.CurJob.targetA.Cell.GetRegion(map) != path.nodes[0]) + { + + var region = path.nodes[0]; + + var targetCell = + region.RandomCell; + + while (!targetCell.Walkable(map)) + targetCell = region.RandomCell; + + pawn.jobs.StartJob( + new Job(JobDefOf.Goto, targetCell) + ); + + } + } + } + catch (Exception er) + { + Log.Message(er.ToString()); + } + } + + foreach (Pawn pawn in squadPawns) + { + if (pawn.Position.GetRegion(map) != path.nodes[0]) + return; + } + + path.nodes.RemoveAt(0); + } + + private void Ideal() + { + + } + + private void FindPath() + { + + this.squadPawns + = map.mapPawns + .AllPawnsSpawned.FindAll((obj) => obj.Faction == Faction.OfPlayer); + + Log.Message("Starting PathFinding"); + + SquadPather pather = + new SquadPather(map); + + + Log.Message("Starting PathFinding" + squadPawns[0] + .Position.GetRegion(map) + .Equals(this.target) + ); + + this.path = pather.GetSquadPathFromTo( + squadPawns[0].Position.GetRegion(map), + this.target, + this.fac, + 100 + ); + + Log.Message("nodes Counts " + this.path.nodes.Count); + } + + private void AssignJobToPawn(Job job,Pawn pawn) + { + if (pawn.drafter != null) + { + pawn.jobs.TryTakeOrderedJob(job); + } + else + { + ExternalPawnDrafter.TakeOrderedJob(pawn, job); + } + } + } +} diff --git a/Source/CombatExtended/AI/PathFinding/SquadPathKMBetterPQueue.cs b/Source/CombatExtended/AI/PathFinding/SquadPathKMBetterPQueue.cs new file mode 100644 index 0000000000..f82956a3f5 --- /dev/null +++ b/Source/CombatExtended/AI/PathFinding/SquadPathKMBetterPQueue.cs @@ -0,0 +1,281 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using UnityEngine; +using System.Collections; + +namespace CombatExtended.AI +{ + public class BetterPQueue + { + //private readonly SortedDictionary Heap; + + private MinHeap heap; + + public BetterPQueue(){ + //this.Heap = new + // SortedDictionary(); + heap = new MinHeap(); + } + + public void Push(T item,float Score) + { + var NewKey = + new HeapKey(Guid.NewGuid(),Score, item); + + this.heap.Add(NewKey); + } + + public T getMin() + { + var minValue = + this.heap.GetMin(); + + this.heap.ExtractDominating(); + + return minValue.ObjPointer; + } + + public Boolean isEmpty() + { + return this.heap.Count == 0; + } + + private class HeapKey : IComparable + { + public HeapKey(Guid id, float value,T objPointer) + { + Id = id; + Value = value; + ObjPointer = objPointer; + } + + public Guid Id { get; private set; } + public float Value { get; private set; } + + //This is the Pointer to The Real Node + public T ObjPointer; + + public int CompareTo(HeapKey other) + { + if (other == null) + { + throw new ArgumentNullException("other"); + } + + var result = Value.CompareTo(other.Value); + + return result == 0 ? Id.CompareTo(other.Id) : result; + } + } + } + + public abstract class Heap : IEnumerable + { + private const int InitialCapacity = 0; + private const int GrowFactor = 2; + private const int MinGrow = 1; + + private int _capacity = InitialCapacity; + private T[] _heap = new T[InitialCapacity]; + private int _tail = 0; + + public int Count { get { return _tail; } } + public int Capacity { get { return _capacity; } } + + protected Comparer Comparer { get; private set; } + protected abstract bool Dominates(T x, T y); + + protected Heap() : this(Comparer.Default) + { + } + + protected Heap(Comparer comparer) : this(Enumerable.Empty(), comparer) + { + + } + + protected Heap(IEnumerable collection) + : this(collection, Comparer.Default) + { + } + + protected Heap(IEnumerable collection, Comparer comparer) + { + if (collection == null) throw new ArgumentNullException("collection"); + if (comparer == null) throw new ArgumentNullException("comparer"); + + Comparer = comparer; + + foreach (var item in collection) + { + if (Count == Capacity) + Grow(); + + _heap[_tail++] = item; + } + + for (int i = Parent(_tail - 1); i >= 0; i--) + BubbleDown(i); + } + + public void Add(T item) + { + if (Count == Capacity) + Grow(); + + _heap[_tail++] = item; + BubbleUp(_tail - 1); + } + + private void BubbleUp(int i) + { + if (i == 0 || Dominates(_heap[Parent(i)], _heap[i])) + return; //correct domination (or root) + + Swap(i, Parent(i)); + BubbleUp(Parent(i)); + } + + public T GetMin() + { + if (Count == 0) throw new InvalidOperationException("Heap is empty"); + return _heap[0]; + } + + public T ExtractDominating() + { + if (Count == 0) throw new InvalidOperationException("Heap is empty"); + T ret = _heap[0]; + _tail--; + Swap(_tail, 0); + BubbleDown(0); + return ret; + } + + private void BubbleDown(int i) + { + int dominatingNode = Dominating(i); + if (dominatingNode == i) return; + Swap(i, dominatingNode); + BubbleDown(dominatingNode); + } + + private int Dominating(int i) + { + int dominatingNode = i; + dominatingNode = GetDominating(YoungChild(i), dominatingNode); + dominatingNode = GetDominating(OldChild(i), dominatingNode); + + return dominatingNode; + } + + private int GetDominating(int newNode, int dominatingNode) + { + if (newNode < _tail && !Dominates(_heap[dominatingNode], _heap[newNode])) + return newNode; + else + return dominatingNode; + } + + private void Swap(int i, int j) + { + T tmp = _heap[i]; + _heap[i] = _heap[j]; + _heap[j] = tmp; + } + + private static int Parent(int i) + { + return (i + 1) / 2 - 1; + } + + private static int YoungChild(int i) + { + return (i + 1) * 2 - 1; + } + + private static int OldChild(int i) + { + return YoungChild(i) + 1; + } + + private void Grow() + { + int newCapacity = _capacity * GrowFactor + MinGrow; + var newHeap = new T[newCapacity]; + Array.Copy(_heap, newHeap, _capacity); + _heap = newHeap; + _capacity = newCapacity; + } + + public IEnumerator GetEnumerator() + { + return _heap.Take(Count).GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + } + + public class MaxHeap : Heap + { + public MaxHeap() + : this(Comparer.Default) + { + } + + public MaxHeap(Comparer comparer) + : base(comparer) + { + } + + public MaxHeap(IEnumerable collection, Comparer comparer) + : base(collection, comparer) + { + } + + public MaxHeap(IEnumerable collection) : base(collection) + { + } + + protected override bool Dominates(T x, T y) + { + return Comparer.Compare(x, y) >= 0; + } + } + + public class MinHeap : Heap + { + public MinHeap() + : this(Comparer.Default) + { + } + + public MinHeap(Comparer comparer) + : base(comparer) + { + } + + public MinHeap(IEnumerable collection) : base(collection) + { + } + + public MinHeap(IEnumerable collection, Comparer comparer) + : base(collection, comparer) + { + } + + protected override bool Dominates(T x, T y) + { + return Comparer.Compare(x, y) <= 0; + } + } + + +} diff --git a/Source/CombatExtended/AI/PathFinding/SquadPathMover.cs b/Source/CombatExtended/AI/PathFinding/SquadPathMover.cs new file mode 100644 index 0000000000..4cafe5190c --- /dev/null +++ b/Source/CombatExtended/AI/PathFinding/SquadPathMover.cs @@ -0,0 +1,448 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using Verse.AI; +//using Reloader; +using UnityEngine; +using System.Reflection; + +namespace CombatExtended.AI +{ + public class SquadPathMover + { + private enum states + { + moving = 1, ideal = 2, findingPath = 3 + } + + private readonly Map map; + + private IntVec3 target; + private Region targetRegion; + + private List PathOfSquad; + + private List enemyPawns; + + private readonly Dictionary squadTargets; + + private List squadPawns; + + private readonly Faction fac; + + private states state = + states.ideal; + + public SquadPathMover(Map map, Faction fac) + { + this.map + = map; + + this.fac + = fac; + + this.squadPawns + = new List(); + } + + public void RegisterTarget(IntVec3 target) + { + this.target + = target; + + this.targetRegion + = target.GetRegion(map); + + this.OnTargetSet(); + + this.state = + states.findingPath; + } + + public void addPawn(Pawn pawn) + { + this.squadPawns + .Add(pawn); + } + + public void removePawn(Pawn pawn) + { + if (!squadPawns.Contains(pawn)) + throw new NullReferenceException(); + + this.squadPawns.Remove(pawn); + + this.squadTargets.Remove(pawn); + } + + private long tick_counts = 0; + + public void TickPather () + { + switch (tick_counts++ % 30) + { + case 0: + this.CheckPathSafty(); + break; + case 1: + this.CheckForEnemyPawns(); + break; + default: + break; + } + + if (tick_counts % 100 == 0) + { + Log.Message("state number is " + state); + } + + if (state == states.findingPath) + { + this.FindPathSafe(); + + this.state + = states.moving; + } + + if (tick_counts % 5 != 0) + return; + + if (state == states.moving) + { + this.Move(); + } + } + + private void Move() + { + if (PathOfSquad.Count == 0) + { + this.state + = states.ideal; + + return; + } + + if (PathOfSquad[0] == null) + { + squadPawns.RemoveAt(0); + return; + } + + foreach (Pawn pawn in squadPawns) + { + try + { + if (pawn.Position.GetRegion(map) != PathOfSquad[0]) + { + if (pawn.CurJob == null) + { + var region = PathOfSquad[0]; + + var targetCell = + region.RandomCell; + + while (!targetCell.Walkable(map)) + targetCell = region.AnyCell; + + pawn.jobs.StartJob( + new Job(JobDefOf.Goto, targetCell) + ); + } + else if (pawn.CurJob.def != JobDefOf.Goto || + pawn.CurJob.targetA.Cell.GetRegion(map) != PathOfSquad[0]) + { + + var region = PathOfSquad[0]; + + var targetCell = + region.RandomCell; + + while (!targetCell.Walkable(map)) + targetCell = region.RandomCell; + + pawn.jobs.StartJob( + new Job(JobDefOf.Goto, targetCell) + ); + + } + } + } + catch (Exception er) + { + Log.Message(er.ToString()); + } + } + + foreach (Pawn pawn in squadPawns) + { + if (pawn.Position.GetRegion(map) != PathOfSquad[0]) + return; + } + + PathOfSquad.RemoveAt(0); + } + + + + //TODO FINISH EVENT SYSTEM................................................................................. + + #region END EVENTS----------------------------------------------------------------------------------------- + + public virtual void OnEnemyNearPawns(Pawn pawn,Pawn enemy) + { + + } + + public virtual void OnEnemyNearPath(Region region) + { + + } + + public virtual void OnMove() + { + + } + + public virtual void OnTargetSet() + { + + } + + public virtual void OnPawnInjured() + { + + } + + public virtual void OnDistenatinReached() + { + + } + + #endregion // END EVENTS----------------------------------------------------------------------------------- + + //TODO FINISH EVENT SYSTEM................................................................................. + + private void FindPathSafe () + { + if(!this.target.IsValid) + throw new NullReferenceException(); + + SquadPather pather = + new SquadPather(map); + + this.PathOfSquad = pather.GetSquadPathFromTo(squadPawns[0].Position.GetRegion(map) + , targetRegion + , fac, 0f).nodes; + } + + private void CheckForEnemyPawns() + { + this.enemyPawns = map.mapPawns + .AllPawnsSpawned + .FindAll(t => fac.HostileTo(t.Faction)); + + foreach (Pawn pawn in squadPawns) + { + foreach (Pawn enemy in enemyPawns) + { + if (Math.Sqrt(Math.Pow(pawn.Position.x + enemy.Position.x, 2) + Math.Pow(pawn.Position.y + enemy.Position.y, 2)) < 35f + && + GenSight.LineOfSight(pawn.Position, enemy.Position, map, true)) + { + this.OnEnemyNearPawns(pawn, enemy); + } + } + } + } + + private void CheckPathSafty() + { + if (PathOfSquad == null) + return; + + if (PathOfSquad.Count == 0) + return; + + //TODO Tweaking Don't Forget About this + + if (PathOfSquad.Count <= 2) + return; + + Region region = + this.PathOfSquad[2]; + + if (region == null) + return; + + var safety = + this.StudyWeaponSights(region); + + if (safety < 10) + return; + + this.OnEnemyNearPath(region); + } + + //[Reloader.ReloadMethod("SquadPathMover", "StudyWeaponSights", new Type[1] { typeof(Region)})] + private float StudyWeaponSights(Region startRegion) + { + + //avg value of cost.. + var sum = 0f; + + var count = 0; + + foreach (Pawn pawn in map.mapPawns.AllPawnsSpawned.FindAll(t => fac.HostileTo(t.Faction))) + { + try + { + if (pawn.Faction == null) + { + + + continue; + } + + if (!pawn.Faction.HostileTo(fac)) + { + + + continue; + } + + if (pawn.equipment == null) + { + + + continue; + } + + if (!pawn.equipment.HasAnything()) + { + + + continue; + } + + if (pawn.equipment.PrimaryEq == null) + { + + + continue; + } + + if (pawn.equipment.PrimaryEq.PrimaryVerb == null) + { + + + continue; + } + + if (pawn.equipment.PrimaryEq.PrimaryVerb.verbProps == null) + { + + + continue; + } + + } + catch (Exception er) + { + Log.Message(er.ToString()); + + continue; + } + + if (count > squadPawns.Count / 2 && squadPawns.Count > 1) + { + break; + } + + Region targetReg = + pawn.Position.GetRegion(pawn.Map); + + if (Math.Sqrt( + Math.Pow(targetReg.Cells.First().x - startRegion.Cells.First().x, 2) + + + Math.Pow(targetReg.Cells.First().y - startRegion.Cells.First().y, 2) - 10f + ) <= pawn.equipment.PrimaryEq.PrimaryVerb.verbProps.range) + + { + for (int i = 0, j = 0; i < 4 + 1 && j < 4; i++) + { + IntVec3 targetPoint = + startRegion.RandomCell; + + IntVec3 startPoint = + targetReg.RandomCell; + + //TODO Implment Range of weapons + + if (GenSight.LineOfSight(startPoint + , targetPoint + , map + , true)) + { + sum += 100f; + + j++; + + count++; + + break; + } + } + } + + if (pawn.equipment.PrimaryEq.PrimaryVerb.verbProps.range * 2f + > Math.Sqrt( + Math.Pow(targetReg.Cells.First().x - startRegion.Cells.First().x, 2) + + + Math.Pow(targetReg.Cells.First().y - startRegion.Cells.First().y, 2) + ) + ) + { + var temp = ( + pawn.equipment.PrimaryEq.PrimaryVerb.verbProps.range * 2f - + (float)Math.Sqrt( + Math.Pow(targetReg.Cells.First().x - startRegion.Cells.First().x, 2) + + + Math.Pow(targetReg.Cells.First().y - startRegion.Cells.First().y, 2) + ) + ); + + for (int i = 0, j = 0; i < 4 + 1 && j < 4; i++) + { + IntVec3 targetPoint = + startRegion.RandomCell; + + IntVec3 startPoint = + targetReg.RandomCell; + + //TODO Implment Range of weapons + + if (GenSight.LineOfSight(startPoint + , targetPoint + , map + , true)) + { + sum += (float)temp; + + j++; + + count++; + + break; + } + } + } + } + + return sum; + } + } +} diff --git a/Source/CombatExtended/AI/PathFinding/SquadPathMover.cs~ b/Source/CombatExtended/AI/PathFinding/SquadPathMover.cs~ new file mode 100644 index 0000000000..1d9da7c847 --- /dev/null +++ b/Source/CombatExtended/AI/PathFinding/SquadPathMover.cs~ @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using Verse.AI; +using UnityEngine; + +namespace CombatExtended.AI +{ + public abstract class SquadPathMover + { + public enum Events + { + go_Job, + set_Up, + squad_Changed, + canceled_Job, + } + + public enum JobTicks + { + moving + ideal, + finding_Path, + new_job, + free + } + + public enum JobTactics + { + move, + avoid, + attack, + hold_postion, + hold_fire, + findCover, + free + } + + private long TICK_COUNTER = 0; + + private Region Target; + + private readonly Map map; + + private readonly SquadBrain context; + + public SquadPathMover(Map map,SquadBrain context){ + this.map = map; + this.context = context; + } + + public virtual void TickAction(Events states) + { + switch (states) + { + case Events.go_Job: + + break; + case Events.set_Up: + + break; + case Events.canceled_Job: + + break; + case Events.squad_Changed: + + break; + } + } + + + + } +} diff --git a/Source/CombatExtended/AI/PathFinding/SquadPathRegionAStar.cs b/Source/CombatExtended/AI/PathFinding/SquadPathRegionAStar.cs new file mode 100644 index 0000000000..c017fee3b6 --- /dev/null +++ b/Source/CombatExtended/AI/PathFinding/SquadPathRegionAStar.cs @@ -0,0 +1,537 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using UnityEngine; + +namespace CombatExtended.AI +{ + public sealed partial class SquadPather + { + //this is used to mark the number of passes over certin region + + private Dictionary DoneRegion; + + //This is the destination Region TODO Rename it + public readonly Region des; + + private Faction fac; + + private List pawns; + + private const int TEST_CELL_CONST = 4; + + private SquadPath GetPathFromTo(Region startRegion, Region targetRegion, Faction fac, float fortLimit) + { + + //TODO get the list of all pawn in the map + //TODO (Filter Pawns that are Hostiles to the faction TODO Optimize) + + this.fac = fac; + + this.pawns = + map.mapPawns. + AllPawnsSpawned + .FindAll((obj) => obj.Faction.HostileTo(fac)) + .ToList(); + + List RemoverList = + new List(); + + foreach (Pawn pawn in pawns) + { + try + { + if (pawn.Faction == null) + { + RemoverList.Add(pawn); + + continue; + } + + if (!pawn.Faction.HostileTo(fac)) + { + RemoverList.Add(pawn); + + continue; + } + + if (pawn.equipment == null) + { + RemoverList.Add(pawn); + + continue; + } + + if (!pawn.equipment.HasAnything()) + { + RemoverList.Add(pawn); + + continue; + } + + if (pawn.equipment.PrimaryEq == null) + { + RemoverList.Add(pawn); + + continue; + } + + if (pawn.equipment.PrimaryEq.PrimaryVerb == null) + { + RemoverList.Add(pawn); + + continue; + } + + if (pawn.equipment.PrimaryEq.PrimaryVerb.verbProps == null) + { + RemoverList.Add(pawn); + + continue; + } + + } + catch (Exception) + { + RemoverList.Add(pawn); + + continue; + } + } + + foreach (Pawn pawn in RemoverList) + pawns.Remove(pawn); + + RemoverList.Clear(); + + List Path = + GetPathAStar(startRegion + , targetRegion + , fac + , fortLimit).ToList(); + + Path.Reverse(); + + //Smooth Down the Path TODO Need Rework + if (Path.Count != 0) + { + List temp = + new List(); + + for (int i = 0; i < Path.Count - 2; i += 2) + temp.Add(i); + + temp.Reverse(); + + foreach (int i in temp) + Path.RemoveAt(i); + + temp.Clear(); + } + + var squadPath = + new SquadPath(); + + + Log.Message("nodes num " + Path.Count); + + squadPath.nodes = Path; + + return squadPath; + } + + private float StudyRegion(Region region, Faction fac, float fortLimit) + { + //TODO NOW ..... LOL + + var temp = StudyWeaponSights(region) + (float)fac.TacticalMemory + .TrapMemories() + .FindAll( + t => t.loc.GetRegion(t.map).Equals(region) + ).Count; + + var density = + StudyObjectsCount(region); + + if (Math.Abs(temp) <= 5) + return density; + + var speed = + +StudyWalkSpeedRegion(region); + + if (temp > 50f) + { + temp -= density + + speed; + } + + return temp; + } + + private float StudyWalkSpeedRegion(Region region) + { + return (float)(region.Cells.Count() - region.ListerThings.AllThings.Count); + } + + private float StudyObjectsCount(Region region) + { + return region.ListerThings.AllThings.Count; + } + + private float StudyWeaponSights(Region startRegion) + { + + //avg value of cost.. + var sum = 0f; + + var count = 0; + + foreach (Pawn pawn in pawns) + { + if (count > pawns.Count / 2 && pawns.Count > 1) + { + break; + } + + Region targetRegion = + pawn.Position.GetRegion(pawn.Map); + + if (Math.Sqrt( + Math.Pow(targetRegion.Cells.First().x - startRegion.Cells.First().x, 2) + + + Math.Pow(targetRegion.Cells.First().y - startRegion.Cells.First().y, 2) - 10f + ) <= pawn.equipment.PrimaryEq.PrimaryVerb.verbProps.range) + + { + for (int i = 0, j = 0; i < TEST_CELL_CONST + 1 && j < 4; i++) + { + IntVec3 targetPoint = + startRegion.RandomCell; + + IntVec3 startPoint = + targetRegion.RandomCell; + + //TODO Implment Range of weapons + + if (GenSight.LineOfSight(startPoint + , targetPoint + , map + , true)) + { + sum += 12; + + j++; + + count++; + + break; + } + } + } + + if (pawn.equipment.PrimaryEq.PrimaryVerb.verbProps.range * 2f + > Math.Sqrt( + Math.Pow(targetRegion.Cells.First().x - startRegion.Cells.First().x, 2) + + + Math.Pow(targetRegion.Cells.First().y - startRegion.Cells.First().y, 2) + ) + ) + { + var temp = ( + pawn.equipment.PrimaryEq.PrimaryVerb.verbProps.range * 2f - + (float)Math.Sqrt( + Math.Pow(targetRegion.Cells.First().x - startRegion.Cells.First().x, 2) + + + Math.Pow(targetRegion.Cells.First().y - startRegion.Cells.First().y, 2) + ) + ); + + for (int i = 0, j = 0; i < TEST_CELL_CONST + 1 && j < 4; i++) + { + IntVec3 targetPoint = + startRegion.RandomCell; + + IntVec3 startPoint = + targetRegion.RandomCell; + + //TODO Implment Range of weapons + + if (GenSight.LineOfSight(startPoint + , targetPoint + , map + , true)) + { + sum += (float)temp; + + j++; + + count++; + } + } + } + } + + return sum; + } + + private IEnumerable GetPathAStar(Region startRegion, Region targetRegion, Faction fac, float fortLimit) + { + this.DoneRegion = + new Dictionary(); + + BetterPQueue Queue = + new BetterPQueue(); + + var startnode = + RegionNode.CreateNode(startRegion, 0f, null); + + Queue.Push(startnode, startnode.Score); + + var breaK = false; + + while (!Queue.isEmpty()) + { + var node = + Queue.getMin(); + + if (node.CurrentRegion.Equals(targetRegion)) + { + + Queue.Push(node, node.Score); + + while (node != null) + { + yield return node.CurrentRegion; + + node = node.Parent; + } + + break; + } + + if (!DoneRegion.ContainsKey(node.CurrentRegion.id)) + { + this.DoneRegion.Add(node.CurrentRegion.id, 1); + } + + if (node.CurrentRegion.links.Count == 2) + { + List temp = + new List(); + + var region = node.CurrentRegion; + + DoneRegion.Remove(region.id); + + while (region.links.Count == 2) + { + if (region.id == targetRegion.id) + { + while (temp.Count != 0) + { + yield return temp.Last(); + temp.RemoveLast(); + } + + while (node != null) + { + yield return node.CurrentRegion; + + node = node.Parent; + } + + breaK = true; + + break; + } + + if (breaK) + break; + + if (DoneRegion.ContainsKey(region.id)) + { + break; + } + + DoneRegion.Add(region.id, 1); + + if (!DoneRegion.ContainsKey(GetRegionLink(region, region.links.ToList()[0]).id)) + { + temp.Add(GetRegionLink(region, region.links.First())); + region = GetRegionLink(region, region.links.First()); + } + else if (!DoneRegion.ContainsKey(GetRegionLink(region, region.links.ToList()[1]).id)) + { + temp.Add(GetRegionLink(region, region.links.First())); + region = GetRegionLink(region, region.links.First()); + } + else + { + break; + } + } + + if (!breaK) + { + if (region.links.Count > 2) + { + var sumSight = (float)pawns.FindAll((obj) => temp.Contains(obj.GetRegion())).Count * 100; + + foreach (Region r in temp) + { + sumSight += StudyObjectsCount(r) + StudyWalkSpeedRegion(r); + } + + var Rtemp = RegionNode.CreateNode(temp[0], + sumSight + + (float)GetOclicdianDistanceRegionAtoB(temp[0], targetRegion) + + (float)GetOclicdianDistanceRegionAtoB(temp[0], node.CurrentRegion) + , node); + + temp.RemoveAt(0); + + while (temp.Count > 0) + { + Rtemp = RegionNode.CreateNode(temp[0], + sumSight + + (float)GetOclicdianDistanceRegionAtoB(temp[0], targetRegion) + + (float)GetOclicdianDistanceRegionAtoB(temp[0], Rtemp.CurrentRegion) + , Rtemp); + + temp.RemoveAt(0); + } + + Queue.Push(Rtemp, Rtemp.Score); + } + else if (region.links.Count == 1) + { + continue; + } + } + } + else + { + foreach (RegionLink link in node.CurrentRegion.links) + { + var newregion = + GetRegionLink(node.CurrentRegion, link); + + if (DoneRegion.ContainsKey(newregion.id)) + continue; + + var temp = RegionNode.CreateNode(newregion, + StudyRegion( + newregion, + fac, + fortLimit) + + node.Score + + (float)GetOclicdianDistanceRegionAtoB(newregion, targetRegion) + + (float)GetOclicdianDistanceRegionAtoB(newregion, node.CurrentRegion) + 10f + , node); + + Queue.Push(temp, temp.Score); + } + + + foreach (IntVec3 cell in new IntVec3[]{ + //node.CurrentRegion.extentsLimit.TopRight + //,node.CurrentRegion.extentsLimit.BottomLeft + //,node.CurrentRegion.extentsLimit.Cells.First() + //,node.CurrentRegion.extentsLimit.Cells.Last(), + //TODO Need to be Tested for which one is right LOL + node.CurrentRegion.extentsClose.TopRight + ,node.CurrentRegion.extentsClose.BottomLeft + ,node.CurrentRegion.extentsClose.Cells.First() + ,node.CurrentRegion.extentsClose.Cells.Last()}) + { + if (cell.IsValid) + continue; + + if (!cell.Walkable(map)) + continue; + + if (cell.GetRegion(map) == null) + continue; + + if (DoneRegion.ContainsKey(cell.GetRegion(map).id)) + continue; + + var temp = RegionNode.CreateNode(cell.GetRegion(map), + StudyRegion( + cell.GetRegion(map), + fac, + fortLimit) + + node.Score + + (float)GetOclicdianDistanceRegionAtoB(cell.GetRegion(map), targetRegion) + + (float)GetOclicdianDistanceRegionAtoB(cell.GetRegion(map), node.CurrentRegion) + , node); + + Queue.Push(temp, temp.Score); + } + } + + if (breaK) + break; + } + + yield return null; + } + + class RegionNode + { + private readonly Region currentRegion; + + private readonly float score; + + private readonly RegionNode parent; + + public static RegionNode CreateNode(Region CurrentRegion, float Score, RegionNode parent) + { + return new RegionNode(CurrentRegion, Score, parent); + } + + public static RegionNode CreateNode(Region CurrentRegion, float Score) + { + return new RegionNode(CurrentRegion, Score, null); + } + + private RegionNode(Region CurrentRegion, float Score, RegionNode Parent) + { + this.currentRegion = + CurrentRegion; + this.score = + Score; + this.parent = + Parent; + } + + public Region CurrentRegion + { + get + { + return currentRegion; + } + } + + public float Score + { + get + { + return score; + } + } + + public RegionNode Parent + { + get + { + return parent; + } + } + } + + } +} diff --git a/Source/CombatExtended/AI/PathFinding/SquadPathRegionAStar.cs~ b/Source/CombatExtended/AI/PathFinding/SquadPathRegionAStar.cs~ new file mode 100644 index 0000000000..c017fee3b6 --- /dev/null +++ b/Source/CombatExtended/AI/PathFinding/SquadPathRegionAStar.cs~ @@ -0,0 +1,537 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using UnityEngine; + +namespace CombatExtended.AI +{ + public sealed partial class SquadPather + { + //this is used to mark the number of passes over certin region + + private Dictionary DoneRegion; + + //This is the destination Region TODO Rename it + public readonly Region des; + + private Faction fac; + + private List pawns; + + private const int TEST_CELL_CONST = 4; + + private SquadPath GetPathFromTo(Region startRegion, Region targetRegion, Faction fac, float fortLimit) + { + + //TODO get the list of all pawn in the map + //TODO (Filter Pawns that are Hostiles to the faction TODO Optimize) + + this.fac = fac; + + this.pawns = + map.mapPawns. + AllPawnsSpawned + .FindAll((obj) => obj.Faction.HostileTo(fac)) + .ToList(); + + List RemoverList = + new List(); + + foreach (Pawn pawn in pawns) + { + try + { + if (pawn.Faction == null) + { + RemoverList.Add(pawn); + + continue; + } + + if (!pawn.Faction.HostileTo(fac)) + { + RemoverList.Add(pawn); + + continue; + } + + if (pawn.equipment == null) + { + RemoverList.Add(pawn); + + continue; + } + + if (!pawn.equipment.HasAnything()) + { + RemoverList.Add(pawn); + + continue; + } + + if (pawn.equipment.PrimaryEq == null) + { + RemoverList.Add(pawn); + + continue; + } + + if (pawn.equipment.PrimaryEq.PrimaryVerb == null) + { + RemoverList.Add(pawn); + + continue; + } + + if (pawn.equipment.PrimaryEq.PrimaryVerb.verbProps == null) + { + RemoverList.Add(pawn); + + continue; + } + + } + catch (Exception) + { + RemoverList.Add(pawn); + + continue; + } + } + + foreach (Pawn pawn in RemoverList) + pawns.Remove(pawn); + + RemoverList.Clear(); + + List Path = + GetPathAStar(startRegion + , targetRegion + , fac + , fortLimit).ToList(); + + Path.Reverse(); + + //Smooth Down the Path TODO Need Rework + if (Path.Count != 0) + { + List temp = + new List(); + + for (int i = 0; i < Path.Count - 2; i += 2) + temp.Add(i); + + temp.Reverse(); + + foreach (int i in temp) + Path.RemoveAt(i); + + temp.Clear(); + } + + var squadPath = + new SquadPath(); + + + Log.Message("nodes num " + Path.Count); + + squadPath.nodes = Path; + + return squadPath; + } + + private float StudyRegion(Region region, Faction fac, float fortLimit) + { + //TODO NOW ..... LOL + + var temp = StudyWeaponSights(region) + (float)fac.TacticalMemory + .TrapMemories() + .FindAll( + t => t.loc.GetRegion(t.map).Equals(region) + ).Count; + + var density = + StudyObjectsCount(region); + + if (Math.Abs(temp) <= 5) + return density; + + var speed = + +StudyWalkSpeedRegion(region); + + if (temp > 50f) + { + temp -= density + + speed; + } + + return temp; + } + + private float StudyWalkSpeedRegion(Region region) + { + return (float)(region.Cells.Count() - region.ListerThings.AllThings.Count); + } + + private float StudyObjectsCount(Region region) + { + return region.ListerThings.AllThings.Count; + } + + private float StudyWeaponSights(Region startRegion) + { + + //avg value of cost.. + var sum = 0f; + + var count = 0; + + foreach (Pawn pawn in pawns) + { + if (count > pawns.Count / 2 && pawns.Count > 1) + { + break; + } + + Region targetRegion = + pawn.Position.GetRegion(pawn.Map); + + if (Math.Sqrt( + Math.Pow(targetRegion.Cells.First().x - startRegion.Cells.First().x, 2) + + + Math.Pow(targetRegion.Cells.First().y - startRegion.Cells.First().y, 2) - 10f + ) <= pawn.equipment.PrimaryEq.PrimaryVerb.verbProps.range) + + { + for (int i = 0, j = 0; i < TEST_CELL_CONST + 1 && j < 4; i++) + { + IntVec3 targetPoint = + startRegion.RandomCell; + + IntVec3 startPoint = + targetRegion.RandomCell; + + //TODO Implment Range of weapons + + if (GenSight.LineOfSight(startPoint + , targetPoint + , map + , true)) + { + sum += 12; + + j++; + + count++; + + break; + } + } + } + + if (pawn.equipment.PrimaryEq.PrimaryVerb.verbProps.range * 2f + > Math.Sqrt( + Math.Pow(targetRegion.Cells.First().x - startRegion.Cells.First().x, 2) + + + Math.Pow(targetRegion.Cells.First().y - startRegion.Cells.First().y, 2) + ) + ) + { + var temp = ( + pawn.equipment.PrimaryEq.PrimaryVerb.verbProps.range * 2f - + (float)Math.Sqrt( + Math.Pow(targetRegion.Cells.First().x - startRegion.Cells.First().x, 2) + + + Math.Pow(targetRegion.Cells.First().y - startRegion.Cells.First().y, 2) + ) + ); + + for (int i = 0, j = 0; i < TEST_CELL_CONST + 1 && j < 4; i++) + { + IntVec3 targetPoint = + startRegion.RandomCell; + + IntVec3 startPoint = + targetRegion.RandomCell; + + //TODO Implment Range of weapons + + if (GenSight.LineOfSight(startPoint + , targetPoint + , map + , true)) + { + sum += (float)temp; + + j++; + + count++; + } + } + } + } + + return sum; + } + + private IEnumerable GetPathAStar(Region startRegion, Region targetRegion, Faction fac, float fortLimit) + { + this.DoneRegion = + new Dictionary(); + + BetterPQueue Queue = + new BetterPQueue(); + + var startnode = + RegionNode.CreateNode(startRegion, 0f, null); + + Queue.Push(startnode, startnode.Score); + + var breaK = false; + + while (!Queue.isEmpty()) + { + var node = + Queue.getMin(); + + if (node.CurrentRegion.Equals(targetRegion)) + { + + Queue.Push(node, node.Score); + + while (node != null) + { + yield return node.CurrentRegion; + + node = node.Parent; + } + + break; + } + + if (!DoneRegion.ContainsKey(node.CurrentRegion.id)) + { + this.DoneRegion.Add(node.CurrentRegion.id, 1); + } + + if (node.CurrentRegion.links.Count == 2) + { + List temp = + new List(); + + var region = node.CurrentRegion; + + DoneRegion.Remove(region.id); + + while (region.links.Count == 2) + { + if (region.id == targetRegion.id) + { + while (temp.Count != 0) + { + yield return temp.Last(); + temp.RemoveLast(); + } + + while (node != null) + { + yield return node.CurrentRegion; + + node = node.Parent; + } + + breaK = true; + + break; + } + + if (breaK) + break; + + if (DoneRegion.ContainsKey(region.id)) + { + break; + } + + DoneRegion.Add(region.id, 1); + + if (!DoneRegion.ContainsKey(GetRegionLink(region, region.links.ToList()[0]).id)) + { + temp.Add(GetRegionLink(region, region.links.First())); + region = GetRegionLink(region, region.links.First()); + } + else if (!DoneRegion.ContainsKey(GetRegionLink(region, region.links.ToList()[1]).id)) + { + temp.Add(GetRegionLink(region, region.links.First())); + region = GetRegionLink(region, region.links.First()); + } + else + { + break; + } + } + + if (!breaK) + { + if (region.links.Count > 2) + { + var sumSight = (float)pawns.FindAll((obj) => temp.Contains(obj.GetRegion())).Count * 100; + + foreach (Region r in temp) + { + sumSight += StudyObjectsCount(r) + StudyWalkSpeedRegion(r); + } + + var Rtemp = RegionNode.CreateNode(temp[0], + sumSight + + (float)GetOclicdianDistanceRegionAtoB(temp[0], targetRegion) + + (float)GetOclicdianDistanceRegionAtoB(temp[0], node.CurrentRegion) + , node); + + temp.RemoveAt(0); + + while (temp.Count > 0) + { + Rtemp = RegionNode.CreateNode(temp[0], + sumSight + + (float)GetOclicdianDistanceRegionAtoB(temp[0], targetRegion) + + (float)GetOclicdianDistanceRegionAtoB(temp[0], Rtemp.CurrentRegion) + , Rtemp); + + temp.RemoveAt(0); + } + + Queue.Push(Rtemp, Rtemp.Score); + } + else if (region.links.Count == 1) + { + continue; + } + } + } + else + { + foreach (RegionLink link in node.CurrentRegion.links) + { + var newregion = + GetRegionLink(node.CurrentRegion, link); + + if (DoneRegion.ContainsKey(newregion.id)) + continue; + + var temp = RegionNode.CreateNode(newregion, + StudyRegion( + newregion, + fac, + fortLimit) + + node.Score + + (float)GetOclicdianDistanceRegionAtoB(newregion, targetRegion) + + (float)GetOclicdianDistanceRegionAtoB(newregion, node.CurrentRegion) + 10f + , node); + + Queue.Push(temp, temp.Score); + } + + + foreach (IntVec3 cell in new IntVec3[]{ + //node.CurrentRegion.extentsLimit.TopRight + //,node.CurrentRegion.extentsLimit.BottomLeft + //,node.CurrentRegion.extentsLimit.Cells.First() + //,node.CurrentRegion.extentsLimit.Cells.Last(), + //TODO Need to be Tested for which one is right LOL + node.CurrentRegion.extentsClose.TopRight + ,node.CurrentRegion.extentsClose.BottomLeft + ,node.CurrentRegion.extentsClose.Cells.First() + ,node.CurrentRegion.extentsClose.Cells.Last()}) + { + if (cell.IsValid) + continue; + + if (!cell.Walkable(map)) + continue; + + if (cell.GetRegion(map) == null) + continue; + + if (DoneRegion.ContainsKey(cell.GetRegion(map).id)) + continue; + + var temp = RegionNode.CreateNode(cell.GetRegion(map), + StudyRegion( + cell.GetRegion(map), + fac, + fortLimit) + + node.Score + + (float)GetOclicdianDistanceRegionAtoB(cell.GetRegion(map), targetRegion) + + (float)GetOclicdianDistanceRegionAtoB(cell.GetRegion(map), node.CurrentRegion) + , node); + + Queue.Push(temp, temp.Score); + } + } + + if (breaK) + break; + } + + yield return null; + } + + class RegionNode + { + private readonly Region currentRegion; + + private readonly float score; + + private readonly RegionNode parent; + + public static RegionNode CreateNode(Region CurrentRegion, float Score, RegionNode parent) + { + return new RegionNode(CurrentRegion, Score, parent); + } + + public static RegionNode CreateNode(Region CurrentRegion, float Score) + { + return new RegionNode(CurrentRegion, Score, null); + } + + private RegionNode(Region CurrentRegion, float Score, RegionNode Parent) + { + this.currentRegion = + CurrentRegion; + this.score = + Score; + this.parent = + Parent; + } + + public Region CurrentRegion + { + get + { + return currentRegion; + } + } + + public float Score + { + get + { + return score; + } + } + + public RegionNode Parent + { + get + { + return parent; + } + } + } + + } +} diff --git a/Source/CombatExtended/AI/PathFinding/SquadPather.cs b/Source/CombatExtended/AI/PathFinding/SquadPather.cs new file mode 100644 index 0000000000..72741d10b5 --- /dev/null +++ b/Source/CombatExtended/AI/PathFinding/SquadPather.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using UnityEngine; + +namespace CombatExtended.AI +{ + public partial class SquadPather + { + private readonly Map map; + + private readonly int mapSizeX; + + private readonly int mapSizeZ; + + public SquadPather(Map map) + { + this.map + = map; + + var mapSizePowTwo = + map.info.PowerOfTwoOverMapSize; + + mapSizeX = + map.Size.x; + mapSizeZ = + map.Size.z; + } + + public SquadPath GetSquadPathFromTo(IntVec3 startPos, IntVec3 targetPos, Faction fac, float fortLimit) + { + return GetSquadPathFromTo(startPos.GetRegion(map), targetPos.GetRegion(map), fac, fortLimit); + } + + public SquadPath GetSquadPathFromTo(Region startRegion, Region targetRegion, Faction fac, float fortLimit) + { + // TODO Calculate most efficient region-wise path for squad to reach their objective without exceeding the fortification limit + return GetPathFromTo(startRegion, targetRegion, fac, fortLimit); + } + + private float GetSquadPathScoreFor(Region region, out float fortStrength) + { + throw new NotImplementedException(); + } + + //Get The Next Region to that Link TODO Thanks ZHentar + private static Region GetRegionLink(Region region, RegionLink link) => + Equals(region, link.RegionA) ? link.RegionB : link.RegionA; + + //Use this to get the Distance Bettween two regien without using Region Link + private double GetOclicdianDistanceRegionAtoB(Region startRegion, Region targetRegion) + { + //May be I need to swap them LOL + //Get the End Region Position TODO may need swaping + var StartRegionX = startRegion.Cells.First().x; + var StartRegionY = startRegion.Cells.First().z; + + //Get the End Region Position TODO may need swaping + var EndRegionX = targetRegion.Cells.First().x; + var EndRegionY = targetRegion.Cells.First().z; + + //Need Some Tweaking TODO Tweak distance + return Math.Sqrt(Math.Pow((double)(StartRegionX - EndRegionX), 2.0) + + Math.Pow((double)(StartRegionY - EndRegionY), 2.0)); + } + + private IntVec3 GetRegionLocation(Region region) + { + var RegionX = (int)region.mapIndex / (int)mapSizeX; + var RegionZ = region.mapIndex % mapSizeZ; + + return new IntVec3(RegionX, 0, RegionZ); + } + } +} diff --git a/Source/CombatExtended/AI/SquadBrain/SquadBrain.cs b/Source/CombatExtended/AI/SquadBrain/SquadBrain.cs new file mode 100644 index 0000000000..eb4e1d83ee --- /dev/null +++ b/Source/CombatExtended/AI/SquadBrain/SquadBrain.cs @@ -0,0 +1,427 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using Verse.AI; +using UnityEngine; + +namespace CombatExtended.AI +{ + public enum Squad_Movment_Mode : byte + { + dont_wait_for_others, + wait_for_others, + } + + public enum Squad_Combat_Mode : byte + { + avoid_on_sight, + attack_on_sight, + smart_attack, + avoid_attack, + } + + public enum Squad_Think_Mode : byte + { + wait_for_instruction, + free_will + } + + public class SquadBrain : IExposable + { + private class JobNode + { + public List jobs = new List(); + } + + public bool COMBAT_MODE = true; + + public Squad_Combat_Mode squad_Combat_Mode = Squad_Combat_Mode.attack_on_sight; + + public Squad_Movment_Mode squad_Movment_Mode; + + public Squad_Think_Mode squad_Think_Mode = Squad_Think_Mode.wait_for_instruction; + + private Dictionary squadOrdersForPawns; + + private List squadPawns = new List(); + + private IEnumerable squadPath; + + private Map map; + + private Faction faction; + + public Job GetJobFor(Pawn pawn) + { + //this.squadPawns = map.mapPawns.AllPawnsSpawned.FindAll(t => faction == t.Faction); + return CombatTick(pawn); + } + + private Job GotoJob(IntVec3 target_cell) => new Job(JobDefOf.Goto, target_cell); + + private Job GotoWaitCombat() => new Job(JobDefOf.WaitCombat); + + private Job WaitJob() => new Job(JobDefOf.WaitWander); + + private float GetScoreEnemies(Pawn pawn) => SquadHelper.StudyWeaponSights(pawn.GetRegion(), map.mapPawns.AllPawnsSpawned, map, faction); + + public SquadBrain() { } + + public SquadBrain(IEnumerable squadPawns, Faction faction, Map map) + { + this.map + = map; + + this.faction + = faction; + + this.squadPawns.AddRange(squadPawns); + + this.squadOrdersForPawns + = new Dictionary(); + } + + public void SetTarget(Region target) + { + cur_target = target; + } + + private JobDef JobForTarget; + + private Region start_Point; + + private Region target; + + private Region cur_target; + + private void FindPath() + { + if (this.cur_target != this.target) + cur_target = target; + + SquadPather pather = new SquadPather(map); + + this.squadPath = pather.GetSquadPathFromTo(squadPawns.First().GetRegion() + , target, faction, 0f).nodes; + + if (squadPath.Count() == 0) + { + this.cur_target = null; + + this.target = null; + } + + foreach (Pawn pawn in squadPawns) + { + + if (!squadOrdersForPawns.ContainsKey(pawn)) + { + squadOrdersForPawns.Add(pawn, new JobNode()); + + squadOrdersForPawns[pawn].jobs = new List(); + } + + squadOrdersForPawns[pawn].jobs.Clear(); + + foreach (Region region in this.squadPath) + { + squadOrdersForPawns[pawn].jobs.Add(GotoJob(region.RandomCell)); + } + } + } + + private float GetSaftyForPawns() + { + var temp = 0f; + + foreach (Pawn pawn in squadPawns) + temp += GetScoreEnemies(pawn); + + return temp; + } + + private Job CombatTick(Pawn pawn) + { + if (!squadOrdersForPawns.ContainsKey(pawn)) + { + squadOrdersForPawns.Add(pawn, new JobNode()); + } + + var node = squadOrdersForPawns[pawn]; + + if (node.jobs.Count == 0) + { + return this.Search(pawn); + } + + if (node.jobs.Count > 0 && node.jobs.Count % 2 == 0) + { + var temp = node.jobs[0]; + + node.jobs.RemoveAt(0); + + return temp; + } + + var totalEnemies = 0; + + var enemy_in_sight = FindSightAndRange(pawn, out totalEnemies); + + if (totalEnemies > squadPawns.Count() + 3) + { + return new Job(JobDefOf.FleeAndCower); + } + + if (totalEnemies == 0) + { + return Search(pawn); + } + + var temp_X = node.jobs[0]; + + node.jobs.RemoveAt(0); + + return temp_X; + } + + private Job Search(Pawn pawn) + { + //float verbRange = pawn.equipment?.PrimaryEq?.PrimaryVerb.verbProps.range ?? 0; + + var AntiScore = 0; + + var Score = FindSightAndRange(pawn, out AntiScore); + + + if (AntiScore > squadPawns.Count()) + { + return new Job(JobDefOf.FleeAndCower); + } + + if (AntiScore == 0 && Score == 0) + { + SquadPather pather = new SquadPather(map); + + Pawn enemy = null; + + var Min = 10000; + + var temp_x = 0; + + foreach (Pawn p in map.mapPawns.AllPawnsSpawned.FindAll(t => faction.HostileTo(t.Faction))) + { + var temp = FindSightAndRangeAll(p, out temp_x); + + if (temp < Min) + { + enemy = p; + Min = temp; + } + } + + if (enemy == null) + { + return null; + } + + if (Math.Sqrt( + Math.Pow(pawn.Position.x - enemy.Position.x, 2) + + + Math.Pow(pawn.Position.y - enemy.Position.y, 2) + ) <= getWeaponRange(pawn)) + { + + foreach (Pawn p in squadPawns) + { + var jobs = squadOrdersForPawns[pawn].jobs; + + Job combat = new Job(JobDefOf.WaitCombat); + + combat.expireRequiresEnemiesNearby = false; + + jobs.Add(combat); + } + } + + SquadPath path = pather.GetSquadPathFromTo(pawn.GetRegion(), enemy.GetRegion(), faction, 0f); + + if (path.nodes.Count > 0) + { + path.nodes.RemoveAt(0); + } + else + { + return null; + } + + + foreach (Pawn p in squadPawns) + { + var range = getWeaponRange(p); + + int region_num = (int)(range / 10f) + 1; + + squadOrdersForPawns[pawn].jobs.Clear(); + + var jobs = squadOrdersForPawns[pawn].jobs; + + for (int i = 0; i < path.nodes.Count - region_num; i++) + { + Job job = new Job(JobDefOf.Goto, path.nodes[i].RandomCell); + + job.expireRequiresEnemiesNearby = false; + + jobs.Add(job); + + job = new Job(JobDefOf.WaitCombat); + + jobs.Add(job); + } + + jobs.Add(new Job(CE_JobDefOf.RunForCover)); + + Job combat = new Job(JobDefOf.WaitCombat); + + combat.expireRequiresEnemiesNearby = false; + + jobs.Add(combat); + } + } + + if (squadOrdersForPawns[pawn].jobs.Count == 0) + { + this.Search(pawn); + + Job jb = new Job(JobDefOf.WaitCombat); + + jb.expiryInterval = 60 * 4; + + return jb; + } + + Job temp_job = squadOrdersForPawns[pawn].jobs[0]; + + squadOrdersForPawns[pawn].jobs.RemoveAt(0); + + return temp_job; + } + + private float getWeaponRange(Pawn pawn) + { + + var temp = 0f; + + try + { + if (pawn.equipment != null) + { + + if (pawn.equipment.PrimaryEq != null) + { + temp = pawn.equipment.PrimaryEq.PrimaryVerb.verbProps.range; + } + } + } + catch (Exception) + { + temp = 0; + } + + return temp; + } + + private int FindSightAndRange(Pawn pawn, out int IntRange) + { + var temp = 0; + + var intRange = 0; + + foreach (Pawn enemy in map.mapPawns.AllPawnsSpawned.FindAll(t => faction.HostileTo(t.Faction))) + { + if (GenSight.LineOfSight(pawn.Position + , enemy.Position + , map + , true) == true && Math.Sqrt( + Math.Pow(pawn.Position.x - enemy.Position.x, 2) + + + Math.Pow(pawn.Position.y - enemy.Position.y, 2) + ) <= getWeaponRange(pawn)) + { + temp++; + } + + if (getWeaponRange(enemy) + >= Math.Sqrt( + Math.Pow(pawn.Position.x - enemy.Position.x, 2) + + + Math.Pow(pawn.Position.y - enemy.Position.y, 2) + ) && GenSight.LineOfSight(pawn.Position + , enemy.Position + , map + , true)) + { + intRange++; + } + } + + IntRange = intRange; + + return temp; + } + + private int FindSightAndRangeAll(Pawn pawn, out int IntRange) + { + var temp = 0; + + var intRange = 0; + + foreach (Pawn enemy in map.mapPawns.AllPawnsSpawned) + { + if (enemy == pawn) + continue; + + + + if (GenSight.LineOfSight(pawn.Position + , enemy.Position + , map + , true) == true && Math.Sqrt( + Math.Pow(pawn.Position.x - enemy.Position.x, 2) + + + Math.Pow(pawn.Position.y - enemy.Position.y, 2) + ) <= getWeaponRange(pawn)) + { + temp++; + } + + if (getWeaponRange(enemy) + >= Math.Sqrt( + Math.Pow(pawn.Position.x - enemy.Position.x, 2) + + + Math.Pow(pawn.Position.y - enemy.Position.y, 2) + ) && GenSight.LineOfSight(pawn.Position + , enemy.Position + , map + , true)) + { + intRange++; + } + } + + IntRange = intRange; + + return temp; + } + + public void ExposeData() + { + Scribe_Values.Look(ref map, "map"); + Scribe_Values.Look(ref faction, "faction", Faction.OfPlayer); + Scribe_Collections.Look(ref squadPawns, "squadPawns"); + Scribe_Collections.Look(ref squadOrdersForPawns, "orders"); + } + } +} diff --git a/Source/CombatExtended/AI/SquadBrain/SquadBrain.cs~ b/Source/CombatExtended/AI/SquadBrain/SquadBrain.cs~ new file mode 100644 index 0000000000..8f064f192c --- /dev/null +++ b/Source/CombatExtended/AI/SquadBrain/SquadBrain.cs~ @@ -0,0 +1,419 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using Verse.AI; +using UnityEngine; + +namespace CombatExtended.AI +{ + public enum Squad_Movment_Mode : byte + { + dont_wait_for_others, + wait_for_others, + } + + public enum Squad_Combat_Mode : byte + { + avoid_on_sight, + attack_on_sight, + smart_attack, + avoid_attack, + } + + public enum Squad_Think_Mode : byte + { + wait_for_instruction, + free_will + } + + public class SquadBrain + { + private class JobNode + { + public List jobs = new List(); + } + + public bool COMBAT_MODE = true; + + public Squad_Combat_Mode squad_Combat_Mode = Squad_Combat_Mode.attack_on_sight; + + public Squad_Movment_Mode squad_Movment_Mode; + + public Squad_Think_Mode squad_Think_Mode = Squad_Think_Mode.wait_for_instruction; + + private Dictionary squadOrdersForPawns; + + private IEnumerable squadPawns; + + private IEnumerable squadPath; + + private readonly Map map; + + private readonly Faction faction; + + public Job GetJobFor(Pawn pawn) + { + this.squadPawns = map.mapPawns.AllPawnsSpawned.FindAll(t => faction == t.Faction); + + return CombatTick(pawn); + } + + private Job GotoJob(IntVec3 target_cell) => new Job(JobDefOf.Goto, target_cell); + + private Job GotoWaitCombat() => new Job(JobDefOf.WaitCombat); + + private Job WaitJob() => new Job(JobDefOf.WaitWander); + + private float GetScoreEnemies(Pawn pawn) => SquadHelper.StudyWeaponSights(pawn.GetRegion(), map.mapPawns.AllPawnsSpawned, map, faction); + + public SquadBrain(IEnumerable squadPawns, Faction faction, Map map) + { + this.map + = map; + + this.faction + = faction; + + this.squadPawns + = squadPawns; + + this.squadOrdersForPawns + = new Dictionary(); + } + + public void SetTarget(Region target) + { + cur_target = target; + } + + private JobDef JobForTarget; + + private Region start_Point; + + private Region target; + + private Region cur_target; + + private void FindPath() + { + if (this.cur_target != this.target) + cur_target = target; + + SquadPather pather = new SquadPather(map); + + this.squadPath = pather.GetSquadPathFromTo(squadPawns.First().GetRegion() + , target, faction, 0f).nodes; + + if (squadPath.Count() == 0) + { + this.cur_target = null; + + this.target = null; + } + + foreach (Pawn pawn in squadPawns) + { + + if (!squadOrdersForPawns.ContainsKey(pawn)) + { + squadOrdersForPawns.Add(pawn, new JobNode()); + + squadOrdersForPawns[pawn].jobs = new List(); + } + + squadOrdersForPawns[pawn].jobs.Clear(); + + foreach (Region region in this.squadPath) + { + squadOrdersForPawns[pawn].jobs.Add(GotoJob(region.RandomCell)); + } + } + } + + private float GetSaftyForPawns() + { + var temp = 0f; + + foreach (Pawn pawn in squadPawns) + temp += GetScoreEnemies(pawn); + + return temp; + } + + private Job CombatTick(Pawn pawn) + { + if (!squadOrdersForPawns.ContainsKey(pawn)) + { + squadOrdersForPawns.Add(pawn, new JobNode()); + } + + var node = squadOrdersForPawns[pawn]; + + if (node.jobs.Count == 0) + { + return this.Search(pawn); + } + + if (node.jobs.Count > 0 && node.jobs.Count % 2 == 0) + { + var temp = node.jobs[0]; + + node.jobs.RemoveAt(0); + + return temp; + } + + var totalEnemies = 0; + + var enemy_in_sight = FindSightAndRange(pawn, out totalEnemies); + + if (totalEnemies > squadPawns.Count() + 3) + { + return new Job(JobDefOf.FleeAndCower); + } + + if (totalEnemies == 0 && node.jobs.Count % 3 == 0) + { + return Search(pawn); + } + + var temp_X = node.jobs[0]; + + node.jobs.RemoveAt(0); + + return temp_X; + } + + private Job Search(Pawn pawn) + { + //float verbRange = pawn.equipment?.PrimaryEq?.PrimaryVerb.verbProps.range ?? 0; + + var AntiScore = 0; + + var Score = FindSightAndRange(pawn, out AntiScore); + + + if (AntiScore > squadPawns.Count()) + { + return new Job(JobDefOf.FleeAndCower); + } + + if (AntiScore == 0 && Score == 0) + { + SquadPather pather = new SquadPather(map); + + Pawn enemy = null; + + var Min = 10000; + + var temp_x = 0; + + foreach (Pawn p in map.mapPawns.AllPawnsSpawned.FindAll(t => faction.HostileTo(t.Faction))) + { + var temp = FindSightAndRangeAll(p, out temp_x); + + if (temp < Min) + { + enemy = p; + Min = temp; + } + } + + if (enemy == null) + { + return null; + } + + if (Math.Sqrt( + Math.Pow(pawn.Position.x - enemy.Position.x, 2) + + + Math.Pow(pawn.Position.y - enemy.Position.y, 2) + ) <= getWeaponRange(pawn)) + { + + foreach (Pawn p in squadPawns) + { + var jobs = squadOrdersForPawns[pawn].jobs; + + Job combat = new Job(JobDefOf.WaitCombat); + + combat.expireRequiresEnemiesNearby = false; + + jobs.Add(combat); + } + } + + SquadPath path = pather.GetSquadPathFromTo(pawn.GetRegion(), enemy.GetRegion(), faction, 0f); + + if (path.nodes.Count > 0) + { + path.nodes.RemoveAt(0); + } + else + { + return null; + } + + + foreach (Pawn p in squadPawns) + { + var range = getWeaponRange(p); + + int region_num = (int)(range / 10f) + 1; + + squadOrdersForPawns[pawn].jobs.Clear(); + + var jobs = squadOrdersForPawns[pawn].jobs; + + for (int i = 0; i < path.nodes.Count - region_num; i++) + { + Job job = new Job(JobDefOf.Goto, path.nodes[i].RandomCell); + + job.expireRequiresEnemiesNearby = false; + + jobs.Add(job); + + job = new Job(JobDefOf.WaitCombat); + + jobs.Add(job); + } + + jobs.Add(new Job(CE_JobDefOf.RunForCover)); + + Job combat = new Job(JobDefOf.WaitCombat); + + combat.expireRequiresEnemiesNearby = false; + + jobs.Add(combat); + } + } + + if (squadOrdersForPawns[pawn].jobs.Count == 0) + { + this.Search(pawn); + + Job jb = new Job(JobDefOf.WaitCombat); + + jb.expiryInterval = 60 * 4; + + return jb; + } + + Job temp_job = squadOrdersForPawns[pawn].jobs[0]; + + squadOrdersForPawns[pawn].jobs.RemoveAt(0); + + return temp_job; + } + + private float getWeaponRange(Pawn pawn) + { + + var temp = 0f; + + try + { + if (pawn.equipment != null) + { + + if (pawn.equipment.PrimaryEq != null) + { + temp = pawn.equipment.PrimaryEq.PrimaryVerb.verbProps.range; + } + } + } + catch (Exception) + { + temp = 0; + } + + return temp; + } + + private int FindSightAndRange(Pawn pawn, out int IntRange) + { + var temp = 0; + + var intRange = 0; + + foreach (Pawn enemy in map.mapPawns.AllPawnsSpawned.FindAll(t => faction.HostileTo(t.Faction))) + { + if (GenSight.LineOfSight(pawn.Position + , enemy.Position + , map + , true) == true && Math.Sqrt( + Math.Pow(pawn.Position.x - enemy.Position.x, 2) + + + Math.Pow(pawn.Position.y - enemy.Position.y, 2) + ) <= getWeaponRange(pawn)) + { + temp++; + } + + if (getWeaponRange(enemy) + >= Math.Sqrt( + Math.Pow(pawn.Position.x - enemy.Position.x, 2) + + + Math.Pow(pawn.Position.y - enemy.Position.y, 2) + ) && GenSight.LineOfSight(pawn.Position + , enemy.Position + , map + , true)) + { + intRange++; + } + } + + IntRange = intRange; + + return temp; + } + + private int FindSightAndRangeAll(Pawn pawn, out int IntRange) + { + var temp = 0; + + var intRange = 0; + + foreach (Pawn enemy in map.mapPawns.AllPawnsSpawned) + { + if (enemy == pawn) + continue; + + + + if (GenSight.LineOfSight(pawn.Position + , enemy.Position + , map + , true) == true && Math.Sqrt( + Math.Pow(pawn.Position.x - enemy.Position.x, 2) + + + Math.Pow(pawn.Position.y - enemy.Position.y, 2) + ) <= getWeaponRange(pawn)) + { + temp++; + } + + if (getWeaponRange(enemy) + >= Math.Sqrt( + Math.Pow(pawn.Position.x - enemy.Position.x, 2) + + + Math.Pow(pawn.Position.y - enemy.Position.y, 2) + ) && GenSight.LineOfSight(pawn.Position + , enemy.Position + , map + , true)) + { + intRange++; + } + } + + IntRange = intRange; + + return temp; + } + } +} diff --git a/Source/CombatExtended/AI/SquadBrain/SquadBrainManager.cs b/Source/CombatExtended/AI/SquadBrain/SquadBrainManager.cs new file mode 100644 index 0000000000..4df57e5db7 --- /dev/null +++ b/Source/CombatExtended/AI/SquadBrain/SquadBrainManager.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using UnityEngine; + +namespace CombatExtended.AI +{ + public class SquadBrainManager + { + + } +} diff --git a/Source/CombatExtended/AI/SquadBrain/SquadUtils.cs b/Source/CombatExtended/AI/SquadBrain/SquadUtils.cs new file mode 100644 index 0000000000..4fdffedfea --- /dev/null +++ b/Source/CombatExtended/AI/SquadBrain/SquadUtils.cs @@ -0,0 +1,145 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using UnityEngine; + +namespace CombatExtended.AI +{ + public class SquadHelper + { + public static float StudyWeaponSights(Region startRegion, IEnumerable pawns, Map map, Faction fac) + { + var TEST_CELL_CONST = 0; + + //avg value of cost.. + var sum = 0f; + + List RemoverList = + new List(); + + foreach (Pawn pawn in pawns) + { + try + { + if (pawn.Faction == null) + { + continue; + } + + if (!pawn.Faction.HostileTo(fac)) + { + continue; + } + + if (pawn.equipment == null) + { + continue; + } + + if (!pawn.equipment.HasAnything()) + { + continue; + } + + if (pawn.equipment.PrimaryEq == null) + { + continue; + } + + if (pawn.equipment.PrimaryEq.PrimaryVerb == null) + { + continue; + } + + if (pawn.equipment.PrimaryEq.PrimaryVerb.verbProps == null) + { + continue; + } + + } + catch (Exception er) + { + RemoverList.Add(pawn); + + continue; + } + + Region targetRegion = + pawn.Position.GetRegion(pawn.Map); + + if (Math.Sqrt( + Math.Pow(targetRegion.Cells.First().x - startRegion.Cells.First().x, 2) + + + Math.Pow(targetRegion.Cells.First().y - startRegion.Cells.First().y, 2) - 10f + ) <= pawn.equipment.PrimaryEq.PrimaryVerb.verbProps.range) + + { + for (int i = 0, j = 0; i < TEST_CELL_CONST + 1 && j < 4; i++) + { + IntVec3 targetPoint = + startRegion.RandomCell; + + IntVec3 startPoint = + targetRegion.RandomCell; + + //TODO Implment Range of weapons + + if (GenSight.LineOfSight(startPoint + , targetPoint + , map + , true)) + { + sum += 100f; + + j++; + } + } + } + + if (pawn.equipment.PrimaryEq.PrimaryVerb.verbProps.range * 2f + > Math.Sqrt( + Math.Pow(targetRegion.Cells.First().x - startRegion.Cells.First().x, 2) + + + Math.Pow(targetRegion.Cells.First().y - startRegion.Cells.First().y, 2) + ) + ) + { + var temp = ( + pawn.equipment.PrimaryEq.PrimaryVerb.verbProps.range * 2f - + (float)Math.Sqrt( + Math.Pow(targetRegion.Cells.First().x - startRegion.Cells.First().x, 2) + + + Math.Pow(targetRegion.Cells.First().y - startRegion.Cells.First().y, 2) + ) + ); + + for (int i = 0, j = 0; i < TEST_CELL_CONST + 1 && j < 4; i++) + { + IntVec3 targetPoint = + startRegion.RandomCell; + + IntVec3 startPoint = + targetRegion.RandomCell; + + //TODO Implment Range of weapons + + if (GenSight.LineOfSight(startPoint + , targetPoint + , map + , true)) + { + sum += (float)temp; + + j++; + } + } + } + } + + return sum; + } + } +} diff --git a/Source/CombatExtended/AI/SquadBrain/SquadUtils.cs~ b/Source/CombatExtended/AI/SquadBrain/SquadUtils.cs~ new file mode 100644 index 0000000000..4fdffedfea --- /dev/null +++ b/Source/CombatExtended/AI/SquadBrain/SquadUtils.cs~ @@ -0,0 +1,145 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using UnityEngine; + +namespace CombatExtended.AI +{ + public class SquadHelper + { + public static float StudyWeaponSights(Region startRegion, IEnumerable pawns, Map map, Faction fac) + { + var TEST_CELL_CONST = 0; + + //avg value of cost.. + var sum = 0f; + + List RemoverList = + new List(); + + foreach (Pawn pawn in pawns) + { + try + { + if (pawn.Faction == null) + { + continue; + } + + if (!pawn.Faction.HostileTo(fac)) + { + continue; + } + + if (pawn.equipment == null) + { + continue; + } + + if (!pawn.equipment.HasAnything()) + { + continue; + } + + if (pawn.equipment.PrimaryEq == null) + { + continue; + } + + if (pawn.equipment.PrimaryEq.PrimaryVerb == null) + { + continue; + } + + if (pawn.equipment.PrimaryEq.PrimaryVerb.verbProps == null) + { + continue; + } + + } + catch (Exception er) + { + RemoverList.Add(pawn); + + continue; + } + + Region targetRegion = + pawn.Position.GetRegion(pawn.Map); + + if (Math.Sqrt( + Math.Pow(targetRegion.Cells.First().x - startRegion.Cells.First().x, 2) + + + Math.Pow(targetRegion.Cells.First().y - startRegion.Cells.First().y, 2) - 10f + ) <= pawn.equipment.PrimaryEq.PrimaryVerb.verbProps.range) + + { + for (int i = 0, j = 0; i < TEST_CELL_CONST + 1 && j < 4; i++) + { + IntVec3 targetPoint = + startRegion.RandomCell; + + IntVec3 startPoint = + targetRegion.RandomCell; + + //TODO Implment Range of weapons + + if (GenSight.LineOfSight(startPoint + , targetPoint + , map + , true)) + { + sum += 100f; + + j++; + } + } + } + + if (pawn.equipment.PrimaryEq.PrimaryVerb.verbProps.range * 2f + > Math.Sqrt( + Math.Pow(targetRegion.Cells.First().x - startRegion.Cells.First().x, 2) + + + Math.Pow(targetRegion.Cells.First().y - startRegion.Cells.First().y, 2) + ) + ) + { + var temp = ( + pawn.equipment.PrimaryEq.PrimaryVerb.verbProps.range * 2f - + (float)Math.Sqrt( + Math.Pow(targetRegion.Cells.First().x - startRegion.Cells.First().x, 2) + + + Math.Pow(targetRegion.Cells.First().y - startRegion.Cells.First().y, 2) + ) + ); + + for (int i = 0, j = 0; i < TEST_CELL_CONST + 1 && j < 4; i++) + { + IntVec3 targetPoint = + startRegion.RandomCell; + + IntVec3 startPoint = + targetRegion.RandomCell; + + //TODO Implment Range of weapons + + if (GenSight.LineOfSight(startPoint + , targetPoint + , map + , true)) + { + sum += (float)temp; + + j++; + } + } + } + } + + return sum; + } + } +} diff --git a/Source/CombatRealism/CombatExtended.csproj b/Source/CombatExtended/CombatExtended.csproj similarity index 56% rename from Source/CombatRealism/CombatExtended.csproj rename to Source/CombatExtended/CombatExtended.csproj index 7a655db8f0..c3c5da950a 100644 --- a/Source/CombatRealism/CombatExtended.csproj +++ b/Source/CombatExtended/CombatExtended.csproj @@ -1,199 +1,278 @@ - - - - - Debug - AnyCPU - {AABEDCF4-2B5E-450E-B855-89595E67DC8D} - Library - Properties - CombatExtended - CombatExtended - v3.5 - 512 - - - False - OnBuildSuccess - False - False - False - obj\$(Configuration)\ - $(MSBuildProgramFiles32)\MSBuild\14.0\Bin - - - true - None - False - ..\..\Assemblies\ - DEBUG;TRACE - prompt - 4 - true - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - False - obj\ - - - 4194304 - AnyCPU - False - False - Auto - - - - ..\..\..\..\RimWorld1393Win_Data\Managed\Assembly-CSharp.dll - False - - - - - - - - - ..\..\..\..\RimWorld1393Win_Data\Managed\UnityEngine.dll - False - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + Debug + AnyCPU + {AABEDCF4-2B5E-450E-B855-89595E67DC8D} + Library + Properties + CombatExtended + CombatExtended + v3.5 + 512 + + + False + OnBuildSuccess + False + False + False + obj\$(Configuration)\ + $(MSBuildProgramFiles32)\MSBuild\14.0\Bin + False + + + false + + + False + ..\..\Assemblies\ + DEBUG;TRACE + prompt + 4 + True + Auto + anycpu + + + none + true + ..\..\Assemblies\ + TRACE + prompt + 4 + + + False + obj\ + Program + ..\..\..\..\RimWorld1393Win.exe + + + 4194304 + AnyCPU + False + Auto + + + true + + + False + ..\..\Assemblies\ + DEBUG;TRACE + prompt + 4 + true + Auto + anycpu + + + + AfterBuild + "C:\Program Files (x86)\Mono\bin\pdb2mdb.bat" ..\..\Assemblies\CombatExtended.dll + + + Clean + rm ../../Assemblies/CombatExtended.dll.mdb + + + Clean + rm ../../Assemblies/CombatExtended.pdb + + + + + + + False + ..\..\Assemblies\0Harmony.dll + False + + + ..\..\..\..\RimWorld1557Win_Data\Managed\Assembly-CSharp.dll + False + + + + + + + + + ..\..\..\..\RimWorld1557Win_Data\Managed\UnityEngine.dll + False + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + if $(ConfigurationName) == Debugger call "C:\Program Files (x86)\Mono\bin\pdb2mdb.bat" $(TargetDir)$(TargetName)$(TargetExt) + + + + + + + + + \ No newline at end of file diff --git a/Source/CombatExtended/CombatExtended/Alerts/Alert_ColonistHasShieldAndTwoHandedWeapon.cs b/Source/CombatExtended/CombatExtended/Alerts/Alert_ColonistHasShieldAndTwoHandedWeapon.cs new file mode 100644 index 0000000000..725db79d50 --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Alerts/Alert_ColonistHasShieldAndTwoHandedWeapon.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using UnityEngine; + +namespace CombatExtended +{ + public class Alert_ColonistHasShieldAndTwoHandedWeapon : Alert + { + public Alert_ColonistHasShieldAndTwoHandedWeapon() + { + defaultLabel = "CE_ColonistHasShieldAndTwoHandedWeapon".Translate(); + defaultExplanation = "CE_ColonistHasShieldAndTwoHandedWeaponDesc".Translate(); + } + + public override AlertReport GetReport() + { + foreach (Pawn current in PawnsFinder.AllMaps_FreeColonistsSpawned) + { + if (WorkGiver_HunterHuntCE.HasMeleeShieldAndTwoHandedWeapon(current)) + { + return current; + } + } + return false; + } + } +} diff --git a/Source/CombatExtended/CombatExtended/AmmoInjector.cs b/Source/CombatExtended/CombatExtended/AmmoInjector.cs new file mode 100644 index 0000000000..0d9232cd02 --- /dev/null +++ b/Source/CombatExtended/CombatExtended/AmmoInjector.cs @@ -0,0 +1,172 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Reflection; +using RimWorld; +using Verse; +using UnityEngine; + +namespace CombatExtended +{ + /* Ammo Injection Handler + * + * Automatically enables all ammo types defined and in use by at least one gun somewhere. Also enables appropriate crafting recipes and trading tags. + * This way we can have all ammo defs in one core mod and selectively enable the ones we need based on which gun mods are installed, avoiding duplication + * issues where multiple gun mods are adding the same ammo. + * + * When ammo system is disabled automatically disables crafting and spawning of all ammo. + * + * Call Inject() on game start and whenever ammo system setting is changed. + */ + internal static class AmmoInjector + { + public static readonly FieldInfo _allRecipesCached = typeof(ThingDef).GetField("allRecipesCached", BindingFlags.Instance | BindingFlags.NonPublic); + + private const string enableTradeTag = "CE_AutoEnableTrade"; // The trade tag which designates ammo defs for being automatically switched to Tradeability.Stockable + private const string enableCraftingTag = "CE_AutoEnableCrafting"; // The trade tag which designates ammo defs for having their crafting recipes automatically added to the crafting table + private static ThingDef ammoCraftingStationInt; // The crafting station to which ammo will be automatically added + private static ThingDef ammoCraftingStation + { + get + { + if (ammoCraftingStationInt == null) + ammoCraftingStationInt = ThingDef.Named("AmmoBench"); + return ammoCraftingStationInt; + } + } + + public static void Inject() + { + if (InjectAmmos()) + { + Log.Message("Combat Extended :: Ammo " + (Controller.settings.EnableAmmoSystem ? "injected" : "removed")); + } + else + { + Log.Error("Combat Extended :: Ammo injector failed to get injected"); + } + } + + public static bool InjectAmmos() + { + bool enabled = Controller.settings.EnableAmmoSystem; + if (enabled) + { + // Initialize list of all weapons + CE_Utility.allWeaponDefs.Clear(); + + foreach (ThingDef def in DefDatabase.AllDefsListForReading) + { + if (def.IsWeapon && (def.canBeSpawningInventory || def.tradeability == Tradeability.Stockable || def.weaponTags.Contains("TurretGun"))) + CE_Utility.allWeaponDefs.Add(def); + } + if (CE_Utility.allWeaponDefs.NullOrEmpty()) + { + Log.Warning("CE Ammo Injector found no weapon defs"); + return true; + } + } + else + { + //If the ammo system is not enabled and it appears that there are no weaponDefs at all .. + if (CE_Utility.allWeaponDefs.NullOrEmpty()) + { + //.. return out of the method early because nothing has to be reversed .. + return true; + } + //.. else, continue the method. + } + + var ammoDefs = new HashSet(); + + // Find all ammo using guns + foreach (ThingDef weaponDef in CE_Utility.allWeaponDefs) + { + CompProperties_AmmoUser props = weaponDef.GetCompProperties(); + if (props != null && props.ammoSet != null && !props.ammoSet.ammoTypes.NullOrEmpty()) + { + ammoDefs.UnionWith(props.ammoSet.ammoTypes.Select(x => x.ammo)); + } + } + + // Make sure to exclude all ammo things which double as weapons + ammoDefs.RemoveWhere(CE_Utility.allWeaponDefs.Contains); + + bool canCraft = (ammoCraftingStation != null); + + if (!canCraft) + { + Log.ErrorOnce("CE ammo injector crafting station is null", 84653201); + } + + foreach (AmmoDef ammoDef in ammoDefs) + { + // Toggle ammo visibility in the debug menu + ammoDef.menuHidden = !enabled; + ammoDef.destroyOnDrop = !enabled; + + // Toggle trading + if (ammoDef.tradeTags.Contains(enableTradeTag)) + { + ammoDef.tradeability = enabled ? Tradeability.Stockable : Tradeability.Sellable; + } + + // Toggle craftability + if (canCraft && ammoDef.tradeTags.Contains(enableCraftingTag)) + { + RecipeDef recipe = DefDatabase.GetNamed(("Make" + ammoDef.defName), false); + if (recipe == null) + { + Log.Error("CE ammo injector found no recipe named Make" + ammoDef.defName); + } + else + { + if (enabled) + { + recipe.recipeUsers.Add(ammoCraftingStation); + } + else + { + recipe.recipeUsers.RemoveAll(x => x.defName == ammoCraftingStation.defName); + } + } + } + } + + if (canCraft) + { + // Set ammoCraftingStation.AllRecipes to null so it will reset + _allRecipesCached.SetValue(ammoCraftingStation, null); + + // Remove all bills which contain removed ammo types + if (!enabled) + { + if (Current.Game != null) + { + IEnumerable enumerable = Find.Maps.SelectMany(x => x.listerBuildings.AllBuildingsColonistOfDef(ammoCraftingStation)); + foreach (Building current in enumerable) + { + var billGiver = current as IBillGiver; + if (billGiver != null) + { + for (int i = 0; i < billGiver.BillStack.Count; i++) + { + Bill bill = billGiver.BillStack[i]; + if (!ammoCraftingStation.AllRecipes.Exists(r => bill.recipe == r)) + { + billGiver.BillStack.Delete(bill); + } + } + } + } + } + + CE_Utility.allWeaponDefs.Clear(); + } + } + + return true; + } + } +} diff --git a/Source/CombatExtended/CombatExtended/AmmoUtility.cs b/Source/CombatExtended/CombatExtended/AmmoUtility.cs new file mode 100644 index 0000000000..23451089d0 --- /dev/null +++ b/Source/CombatExtended/CombatExtended/AmmoUtility.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using UnityEngine; + +namespace CombatExtended +{ + public static class AmmoUtility + { + /// + /// Generates a readout text for a projectile with the damage amount, type, secondary explosion and other CE stats for display in info-box + /// + /// The projectile's ThingDef + /// Formatted string listing projectile stats + public static string GetProjectileReadout(this ThingDef projectileDef) + { + // Append ammo stats + ProjectilePropertiesCE props = projectileDef?.projectile as ProjectilePropertiesCE; + if (props == null) + { + Log.Error("CE tried getting projectile readout with null props"); + return ""; + } + + StringBuilder stringBuilder = new StringBuilder(); + + // Damage type/amount + string dmgList = "CE_DescDamage".Translate() + ": "; + if (!props.secondaryDamage.NullOrEmpty()) + { + // If we have multiple damage types, put every one in its own line + stringBuilder.AppendLine(dmgList); + stringBuilder.AppendLine(" " + GenText.ToStringByStyle(props.damageAmountBase, ToStringStyle.Integer) + " (" + props.damageDef.LabelCap + ")"); + foreach (SecondaryDamage sec in props.secondaryDamage) + { + stringBuilder.AppendLine(" " + GenText.ToStringByStyle(sec.amount, ToStringStyle.Integer) + " (" + sec.def.LabelCap + ")"); + } + } + else + { + stringBuilder.AppendLine(dmgList + GenText.ToStringByStyle(props.damageAmountBase, ToStringStyle.Integer) + " (" + props.damageDef.LabelCap + ")"); + } + // Explosion radius + if (props.explosionRadius > 0) + stringBuilder.AppendLine("CE_DescExplosionRadius".Translate() + ": " + GenText.ToStringByStyle(props.explosionRadius, ToStringStyle.FloatOne)); + + // Secondary explosion + CompProperties_ExplosiveCE secExpProps = projectileDef.GetCompProperties(); + if (secExpProps != null) + { + if (secExpProps.explosionRadius > 0) + { + stringBuilder.AppendLine("CE_DescSecondaryExplosion".Translate() + ":"); + stringBuilder.AppendLine(" " + "CE_DescExplosionRadius".Translate() + ": " + GenText.ToStringByStyle(secExpProps.explosionRadius, ToStringStyle.FloatOne)); + stringBuilder.AppendLine(" " + "CE_DescDamage".Translate() + ": " + + GenText.ToStringByStyle(secExpProps.explosionDamage, ToStringStyle.Integer) + " (" + secExpProps.explosionDamageDef.LabelCap + ")"); + } + if (secExpProps.fragRange > 0) + stringBuilder.AppendLine("CE_DescFragRange".Translate() + ": " + GenText.ToStringByStyle(secExpProps.fragRange, ToStringStyle.FloatTwo)); + } + + // CE stats + stringBuilder.AppendLine("CE_DescArmorPenetration".Translate() + ": " + GenText.ToStringByStyle(props.armorPenetration, ToStringStyle.PercentOne)); + if (props.pelletCount > 1) + stringBuilder.AppendLine("CE_DescPelletCount".Translate() + ": " + GenText.ToStringByStyle(props.pelletCount, ToStringStyle.Integer)); + if (props.spreadMult != 1) + stringBuilder.AppendLine("CE_DescSpreadMult".Translate() + ": " + GenText.ToStringByStyle(props.spreadMult, ToStringStyle.PercentZero)); + + return stringBuilder.ToString(); + } + } +} diff --git a/Source/CombatExtended/CombatExtended/ArmorUtilityCE.cs b/Source/CombatExtended/CombatExtended/ArmorUtilityCE.cs new file mode 100644 index 0000000000..9b7d840d16 --- /dev/null +++ b/Source/CombatExtended/CombatExtended/ArmorUtilityCE.cs @@ -0,0 +1,394 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using UnityEngine; + +namespace CombatExtended +{ + public static class ArmorUtilityCE + { + #region Constants + + private const float PenetrationRandVariation = 0.05f; // Armor penetration will be randomized by +- this amount + private const float SoftArmorMinDamageFactor = 0.2f; // Soft body armor will always take at least original damage * this number from sharp attacks + + #endregion + + #region Properties + + private static readonly SimpleCurve dmgMultCurve = new SimpleCurve { new CurvePoint(0.5f, 0), new CurvePoint(1, 0.5f), new CurvePoint(2, 1) }; // Used to calculate the damage reduction from the penetration / armor ratio + private static readonly StuffCategoryDef[] softStuffs = { StuffCategoryDefOf.Fabric, DefDatabase.GetNamed("Leathery") }; + + #endregion + + #region Methods + + /// + /// Calculates damage through armor, depending on damage type, target and natural resistance. Also calculates deflection and adjusts damage type and impacted body part accordingly. + /// + /// The pre-armor damage info + /// The damaged pawn + /// The pawn's body part that has been hit + /// Returns true if attack did not penetrate pawn's melee shield + /// If shot is deflected returns a new dinfo cloned from the original with damage amount, Def and ForceHitPart adjusted for deflection, otherwise a clone with only the damage adjusted + public static DamageInfo GetAfterArmorDamage(DamageInfo originalDinfo, Pawn pawn, BodyPartRecord hitPart, out bool shieldAbsorbed) + { + shieldAbsorbed = false; + + if (originalDinfo.Def.armorCategory == null) return originalDinfo; + + DamageInfo dinfo = new DamageInfo(originalDinfo); + float dmgAmount = dinfo.Amount; + bool involveArmor = dinfo.Def.harmAllLayersUntilOutside; + bool isAmbientDamage = dinfo.IsAmbientDamage(); + + // In case of ambient damage (fire, electricity) we apply a percentage reduction formula based on the sum of all applicable armor + if (isAmbientDamage) + { + dinfo.SetAmount(Mathf.CeilToInt(GetAmbientPostArmorDamage(dmgAmount, originalDinfo.Def.armorCategory.deflectionStat, pawn, hitPart))); + return dinfo; + } + + float penAmount = GetPenetrationValue(originalDinfo); + + // Apply worn armor + if (involveArmor && pawn.apparel != null && !pawn.apparel.WornApparel.NullOrEmpty()) + { + List apparel = pawn.apparel.WornApparel; + + // Check for shields first + Apparel shield = apparel.FirstOrDefault(x => x is Apparel_Shield); + if (shield != null) + { + // Determine whether the hit is blocked by the shield + bool blockedByShield = false; + if (!(dinfo.WeaponGear?.IsMeleeWeapon ?? false)) + { + var shieldDef = shield.def.GetModExtension(); + if (shieldDef == null) + { + Log.ErrorOnce("CE :: shield " + shield.def.ToString() + " is Apparel_Shield but has no ShieldDefExtension", shield.def.GetHashCode() + 12748102); + } + else + { + bool hasCoverage = shieldDef.PartIsCoveredByShield(hitPart, pawn); + if (hasCoverage) + { + // Right arm is vulnerable during warmup/attack/cooldown + blockedByShield = !((pawn.stances?.curStance as Stance_Busy)?.verb != null && hitPart.IsInGroup(DefDatabase.GetNamed("Arms")) && hitPart.def.defName.Contains("Right")); + } + } + } + // Try to penetrate the shield + if (blockedByShield && !TryPenetrateArmor(dinfo.Def, shield.GetStatValue(dinfo.Def.armorCategory.deflectionStat), ref penAmount, ref dmgAmount, shield)) + { + shieldAbsorbed = true; + dinfo.SetAmount(0); + + // Apply secondary damage to shield + var props = dinfo.WeaponGear.projectile as ProjectilePropertiesCE; + if (props != null && !props.secondaryDamage.NullOrEmpty()) + { + foreach(SecondaryDamage sec in props.secondaryDamage) + { + if (shield.Destroyed) break; + var secDinfo = sec.GetDinfo(); + var pen = GetPenetrationValue(originalDinfo); + var dmg = (float)secDinfo.Amount; + TryPenetrateArmor(secDinfo.Def, shield.GetStatValue(secDinfo.Def.armorCategory.deflectionStat), ref pen, ref dmg, shield); + } + } + + return dinfo; + } + } + + // Apparel is arranged in draw order, we run through reverse to go from Shell -> OnSkin + for (int i = apparel.Count - 1; i >= 0; i--) + { + if (apparel[i].def.apparel.CoversBodyPart(hitPart) + && !TryPenetrateArmor(dinfo.Def, apparel[i].GetStatValue(dinfo.Def.armorCategory.deflectionStat), ref penAmount, ref dmgAmount, apparel[i])) + { + // Hit was deflected, convert damage type + dinfo = GetDeflectDamageInfo(dinfo, hitPart); + i++; // We apply this piece of apparel twice on conversion, this means we can't use deflection on Blunt or else we get an infinite loop of eternal deflection + } + if (dmgAmount <= 0) + { + dinfo.SetAmount(0); + return dinfo; + } + } + } + + // Apply natural armor + List partsToHit = new List() { hitPart }; + if (involveArmor) + { + BodyPartRecord curPart = hitPart; + while (curPart.parent != null && curPart.depth == BodyPartDepth.Inside) + { + curPart = curPart.parent; + partsToHit.Add(curPart); + } + } + for (int i = partsToHit.Count - 1; i >= 0; i--) + { + BodyPartRecord curPart = partsToHit[i]; + bool coveredByArmor = curPart.IsInGroup(CE_BodyPartGroupDefOf.CoveredByNaturalArmor); + float partArmor = pawn.HealthScale * 0.05f; // How much armor is provided by sheer meat + if (coveredByArmor) + partArmor += pawn.GetStatValue(dinfo.Def.armorCategory.deflectionStat); + float unused = dmgAmount; + + // Only apply damage reduction when penetrating armored body parts + if (coveredByArmor ? !TryPenetrateArmor(dinfo.Def, partArmor, ref penAmount, ref dmgAmount) : !TryPenetrateArmor(dinfo.Def, partArmor, ref penAmount, ref unused)) + { + dinfo.SetForcedHitPart(curPart); + /* + if(coveredByArmor && pawn.RaceProps.IsMechanoid) + { + // For Mechanoid natural armor, apply deflection and blunt armor + dinfo = GetDeflectDamageInfo(dinfo, curPart); + TryPenetrateArmor(dinfo.Def, partArmor, ref penAmount, ref dmgAmount); + } + */ + break; + } + if (dmgAmount <= 0) + { + dinfo.SetAmount(0); + return dinfo; + } + } + + dinfo.SetAmount(Mathf.CeilToInt(dmgAmount)); + return dinfo; + } + + /// + /// Determines the armor penetration value of a given dinfo. Checks WeaponGear to see if it is a projectile, melee weapon or pawn and tries to retrieve the penetration value accordingly. + /// + /// DamageInfo to determine penetration for + /// Armor penetration value for attack used, 0 if it can't be determined + private static float GetPenetrationValue(DamageInfo dinfo) + { + if (dinfo.Def.isExplosive) + { + return dinfo.Amount * 0.1f; // Explosions have 10% of their damage as penetration + } + + if (dinfo.WeaponGear != null) + { + // Case 1: projectile attack + ProjectilePropertiesCE projectileProps = dinfo.WeaponGear.projectile as ProjectilePropertiesCE; + if (projectileProps != null) + { + return projectileProps.armorPenetration; + } + + // Case 2: melee attack + Pawn instigatorPawn = dinfo.Instigator as Pawn; + if (instigatorPawn != null) + { + // Pawn is using melee weapon + if (dinfo.WeaponGear.IsMeleeWeapon) + { + if (instigatorPawn.equipment == null + || instigatorPawn.equipment.Primary == null + || instigatorPawn.equipment.Primary.def != dinfo.WeaponGear) + { + Log.Error("CE tried getting armor penetration from melee weapon " + dinfo.WeaponGear.defName + " but instigator " + dinfo.Instigator.ToString() + " equipment does not match"); + return 0; + } + return instigatorPawn.equipment.Primary.GetStatValue(CE_StatDefOf.MeleeWeapon_Penetration); + } + + // Pawn is using body parts + if (instigatorPawn.def == dinfo.WeaponGear) + { + // Pawn is augmented + if (dinfo.WeaponLinkedHediff != null) + { + HediffCompProperties_VerbGiver compProps = dinfo.WeaponLinkedHediff.CompPropsFor(typeof(HediffComp_VerbGiver)) as HediffCompProperties_VerbGiver; + if (compProps != null) + { + VerbPropertiesCE verbProps = compProps.verbs.FirstOrDefault(v => v as VerbPropertiesCE != null) as VerbPropertiesCE; + if (verbProps != null) return verbProps.meleeArmorPenetration; + } + return 0; + } + + // Regular pawn melee + if (dinfo.WeaponBodyPartGroup != null + && instigatorPawn.verbTracker != null + && !instigatorPawn.verbTracker.AllVerbs.NullOrEmpty()) + { + Verb verb = instigatorPawn.verbTracker.AllVerbs.FirstOrDefault(v => v.verbProps.linkedBodyPartsGroup == dinfo.WeaponBodyPartGroup); + if (verb == null) + { + Log.Error("CE could not find matching verb on Pawn " + instigatorPawn.ToString() + " for BodyPartGroup " + dinfo.WeaponBodyPartGroup.ToString()); + return 0; + } + VerbPropertiesCE verbProps = verb.verbProps as VerbPropertiesCE; + if (verbProps != null) return verbProps.meleeArmorPenetration; + } + } + } + } +#if DEBUG + Log.Warning("CE could not determine armor penetration, defaulting"); +#endif + return 9999; // Really high default value so vanilla damage sources such as GiveInjuriesToKill always penetrate + } + + /// + /// Calculates armor for penetrating damage types (Blunt, Sharp). Applies damage reduction based on armor penetration to armor ratio and calculates damage accordingly, with the difference being applied to the armor Thing. Also calculates whether a Sharp attack is deflected. + /// + /// The DamageDef of the attack + /// The amount of armor to apply + /// How much penetration the attack still has + /// The pre-armor amount of damage + /// The armor apparel + /// False if the attack is deflected, true otherwise + private static bool TryPenetrateArmor(DamageDef def, float armorAmount, ref float penAmount, ref float dmgAmount, Thing armor = null) + { + // Calculate deflection + bool isSharpDmg = def.armorCategory == DamageArmorCategoryDefOf.Sharp; + float rand = UnityEngine.Random.Range(penAmount - PenetrationRandVariation, penAmount + PenetrationRandVariation); + bool deflected = isSharpDmg && armorAmount > rand; + + // Apply damage reduction + float dmgMult = 1; + DamageDefExtensionCE defCE = def.GetModExtension() ?? new DamageDefExtensionCE(); + if (deflected && defCE != null && defCE.noDamageOnDeflect) dmgMult = 0; + else dmgMult = dmgMultCurve.Evaluate(penAmount / armorAmount); + float newDmgAmount = dmgAmount * dmgMult; + float newPenAmount = penAmount * dmgMult; + + // Apply damage to armor + if (armor != null) + { + bool isSoftArmor = armor.Stuff != null && armor.Stuff.stuffProps.categories.Any(s => softStuffs.Contains(s)); + if (isSoftArmor) + { + // Soft armor takes absorbed damage from sharp and no damage from blunt + if (isSharpDmg) armor.TakeDamage(new DamageInfo(def, Mathf.Max(Mathf.CeilToInt(dmgAmount * SoftArmorMinDamageFactor), Mathf.CeilToInt(dmgAmount - newDmgAmount)))); + } + else + { + // Hard armor takes damage as reduced by damage resistance and can be impervious to low-penetration attacks + armor.TakeDamage(new DamageInfo(def, Mathf.CeilToInt(newDmgAmount))); + } + } + + dmgAmount = Mathf.Max(0, newDmgAmount); + penAmount = Mathf.Max(0, newPenAmount); + return !deflected; + } + + /// + /// Calculates damage reduction for ambient damage types (fire, electricity) versus natural and worn armor of a pawn. Adds up the total armor percentage (clamped at 0-100%) and multiplies damage by that amount. + /// + /// The original amount of damage + /// The armor stat to use for damage reduction + /// The damaged pawn + /// The body part affected + /// The post-armor damage ranging from 0 to the original amount + private static float GetAmbientPostArmorDamage(float dmgAmount, StatDef deflectionStat, Pawn pawn, BodyPartRecord part) + { + float dmgMult = 1 - pawn.GetStatValue(deflectionStat); + if (dmgMult <= 0) return 0; + if (pawn.apparel != null && !pawn.apparel.WornApparel.NullOrEmpty()) + { + List apparelList = pawn.apparel.WornApparel; + foreach (Apparel apparel in apparelList) + { + if (apparel.def.apparel.CoversBodyPart(part)) dmgMult -= apparel.GetStatValue(deflectionStat); + if (dmgMult <= 0) + { + dmgMult = 0; + break; + } + } + } + return dmgAmount * dmgMult; + } + + /// + /// Creates a new DamageInfo from a deflected one. Changes damage type to Blunt and hit part to the outermost parent of the originally hit part. + /// + /// The dinfo that was deflected + /// The originally hit part + /// DamageInfo copied from dinfo with Def and forceHitPart adjusted + private static DamageInfo GetDeflectDamageInfo(DamageInfo dinfo, BodyPartRecord hitPart) + { + DamageInfo newDinfo = new DamageInfo(DamageDefOf.Blunt, dinfo.Amount, dinfo.Angle, dinfo.Instigator, GetOuterMostParent(hitPart), dinfo.WeaponGear); + newDinfo.SetBodyRegion(dinfo.Height, dinfo.Depth); + newDinfo.SetWeaponBodyPartGroup(dinfo.WeaponBodyPartGroup); + newDinfo.SetWeaponHediff(dinfo.WeaponLinkedHediff); + newDinfo.SetInstantOldInjury(dinfo.InstantOldInjury); + newDinfo.SetAllowDamagePropagation(dinfo.AllowDamagePropagation); + + return newDinfo; + } + + /// + /// Retrieves the first parent of a body part with depth Outside + /// + /// The part to get the parent of + /// The first parent part with depth Outside, the original part if it already is Outside or doesn't have a parent, the root part if no parents are Outside + private static BodyPartRecord GetOuterMostParent(BodyPartRecord part) + { + BodyPartRecord curPart = part; + while(curPart.parent != null && curPart.depth != BodyPartDepth.Outside) + { + curPart = curPart.parent; + } + return curPart; + } + + /// + /// Determines whether a dinfo is of an ambient (i.e. heat, electric) damage type and should apply percentage reduction, as opposed to deflection-based reduction + /// + /// + /// True if dinfo armor category is Heat or Electric, false otherwise + private static bool IsAmbientDamage(this DamageInfo dinfo) + { + return (dinfo.Def.GetModExtension() ?? new DamageDefExtensionCE()).isAmbientDamage; + } + + /// + /// Applies damage to a parry object based on its armor values. For ambient damage, percentage reduction is applied, direct damage uses deflection formulas. + /// + /// DamageInfo to apply to parryThing + /// Thing taking the damage + public static void ApplyParryDamage(DamageInfo dinfo, Thing parryThing) + { + Pawn pawn = parryThing as Pawn; + if (pawn != null) + { + // Pawns run their own armor calculations + dinfo.SetAmount(Mathf.CeilToInt(dinfo.Amount * Rand.Range(0f, 0.5f))); + pawn.TakeDamage(dinfo); + } + else if (dinfo.IsAmbientDamage()) + { + int dmgAmount = Mathf.CeilToInt(dinfo.Amount * Mathf.Clamp01(parryThing.GetStatValue(dinfo.Def.armorCategory.deflectionStat))); + dinfo.SetAmount(dmgAmount); + parryThing.TakeDamage(dinfo); + } + else + { + float dmgAmount = dinfo.Amount * 0.5f; + float penAmount = GetPenetrationValue(dinfo); + TryPenetrateArmor(dinfo.Def, parryThing.GetStatValue(dinfo.Def.armorCategory.deflectionStat), ref penAmount, ref dmgAmount, parryThing); + } + } + + #endregion + } +} diff --git a/Source/CombatExtended/CombatExtended/CE_Utility.cs b/Source/CombatExtended/CombatExtended/CE_Utility.cs new file mode 100644 index 0000000000..e22c954f59 --- /dev/null +++ b/Source/CombatExtended/CombatExtended/CE_Utility.cs @@ -0,0 +1,246 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using Verse.AI; +using Verse.Sound; +using UnityEngine; + +namespace CombatExtended +{ + static class CE_Utility + { + #region Misc + + public static List allWeaponDefs = new List(); + + /// + /// Generates a random Vector2 in a circle with given radius + /// + public static Vector2 GenRandInCircle(float radius) + { + //Fancy math to get random point in circle + System.Random rand = new System.Random(); + double angle = rand.NextDouble() * Math.PI * 2; + double range = Math.Sqrt(rand.NextDouble()) * radius; + return new Vector2((float)(range * Math.Cos(angle)), (float)(range * Math.Sin(angle))); + } + + /// + /// Calculates the actual current movement speed of a pawn + /// + /// Pawn to calculate speed of + /// Move speed in cells per second + public static float GetMoveSpeed(Pawn pawn) + { + float movePerTick = 60 / pawn.GetStatValue(StatDefOf.MoveSpeed, false); //Movement per tick + movePerTick += pawn.Map.pathGrid.CalculatedCostAt(pawn.Position, false, pawn.Position); + Building edifice = pawn.Position.GetEdifice(pawn.Map); + if (edifice != null) + { + movePerTick += (int)edifice.PathWalkCostFor(pawn); + } + + //Case switch to handle walking, jogging, etc. + if (pawn.CurJob != null) + { + switch (pawn.CurJob.locomotionUrgency) + { + case LocomotionUrgency.Amble: + movePerTick *= 3; + if (movePerTick < 60) + { + movePerTick = 60; + } + break; + case LocomotionUrgency.Walk: + movePerTick *= 2; + if (movePerTick < 50) + { + movePerTick = 50; + } + break; + case LocomotionUrgency.Jog: + break; + case LocomotionUrgency.Sprint: + movePerTick = Mathf.RoundToInt(movePerTick * 0.75f); + break; + } + } + return 60 / movePerTick; + } + + public static float ClosestDistBetween(Vector2 origin, Vector2 destination, Vector2 target) + { + return Mathf.Abs((destination.y - origin.y) * target.x - (destination.x - origin.x) * target.y + destination.x * origin.y - destination.y * origin.x) / (destination - origin).magnitude; + } + + /// + /// Attempts to find a turret operator. Accepts any Thing as input and does a sanity check to make sure it is an actual turret. + /// + /// The turret to check for an operator + /// Turret operator if one is found, null if not + public static Pawn TryGetTurretOperator(Thing thing) + { + Pawn manningPawn = null; + Building_TurretGun turret = thing as Building_TurretGun; + if (turret != null) + { + CompMannable comp = turret.TryGetComp(); + if (comp != null && comp.MannedNow) + { + manningPawn = comp.ManningPawn; + } + } + return manningPawn; + } + + /// + /// Extension method to determine whether a ranged weapon has ammo available to it + /// + /// True if the gun has no CompAmmoUser, doesn't use ammo or has ammo in its magazine or carrier inventory, false otherwise + public static bool HasAmmo(this ThingWithComps gun) + { + CompAmmoUser comp = gun.TryGetComp(); + if (comp == null) return true; + return !comp.useAmmo || comp.curMagCount > 0 || comp.hasAmmo; + } + + public static bool CanBeStabilizied(this Hediff diff) + { + HediffWithComps hediff = diff as HediffWithComps; + if (hediff == null) + { + return false; + } + if (hediff.BleedRate == 0 || hediff.IsTended() || hediff.IsOld()) + { + return false; + } + HediffComp_Stabilize comp = hediff.TryGetComp(); + return comp != null && !comp.Stabilized; + } + + #endregion Misc + + #region MoteThrower + public static void ThrowEmptyCasing(Vector3 loc, Map map, ThingDef casingMoteDef, float size = 1f) + { + if (!Controller.settings.ShowCasings || !loc.ShouldSpawnMotesAt(map) || map.moteCounter.SaturatedLowPriority) + { + return; + } + MoteThrown moteThrown = (MoteThrown)ThingMaker.MakeThing(casingMoteDef, null); + moteThrown.Scale = Rand.Range(0.5f, 0.3f) * size; + moteThrown.exactRotation = Rand.Range(-3f, 4f); + moteThrown.exactPosition = loc; + moteThrown.airTimeLeft = 60; + moteThrown.SetVelocity((float)Rand.Range(160, 200), Rand.Range(0.7f, 0.5f)); + // moteThrown.SetVelocityAngleSpeed((float)Rand.Range(160, 200), Rand.Range(0.020f, 0.0115f)); + GenSpawn.Spawn(moteThrown, loc.ToIntVec3(), map); + } + #endregion + + #region Physics + public const float gravityConst = 9.8f; + + public static Bounds GetBoundsFor(Thing thing) + { + if (thing == null) + { + return new Bounds(); + } + var height = new CollisionVertical(thing); + var width = GetCollisionWidth(thing) * 2; + var thingPos = thing.DrawPos; + thingPos.y = height.Max - height.HeightRange.Span / 2; + Bounds bounds = new Bounds(thingPos, new Vector3(width, height.HeightRange.Span, width)); + return bounds; + } + + /// + /// Calculates the width of an object for purposes of bullet collision. Return value is distance from center of object to its edge in cells, so a wall filling out an entire cell has a width of 0.5. + /// Also accounts for general body type, humanoids must be specified in the humanoidBodyList and will have reduced width relative to their overall body size. + /// + /// The Thing to measure width of + /// Distance from center of Thing to its edge in cells + public static float GetCollisionWidth(Thing thing) + { + Pawn pawn = thing as Pawn; + if (pawn == null) + { + return 0.5f; //Buildings, etc. fill out half a square to each side + } + return pawn.BodySize * GetCollisionBodyFactors(pawn).First; + } + + /// + /// Calculates body scale factors based on body type + /// + /// Which pawn to measure for + /// Width factor as First, height factor as second + public static Pair GetCollisionBodyFactors(Pawn pawn) + { + if (pawn == null) + { + Log.Error("CE calling GetCollisionBodyHeightFactor with nullPawn"); + return new Pair(1, 1); + } + RacePropertiesExtensionCE props = pawn.def.GetModExtension() ?? new RacePropertiesExtensionCE(); + var shape = props.bodyShape; +#if DEBUG + if (shape == CE_BodyShapeDefOf.Invalid) Log.ErrorOnce("CE returning BodyType Undefined for pawn " + pawn.ToString(), 35000198 + pawn.GetHashCode()); +#else + if (shape == CE_BodyShapeDefOf.Invalid) Log.Warning("CE returning BodyType Undefined for pawn " + pawn.ToString()); +#endif + if (pawn.GetPosture() != PawnPosture.Standing) + { + return new Pair(shape.widthLaying, shape.heightLaying); + } + return new Pair(shape.width, shape.height); + } + + /// + /// Determines whether a pawn should be currently crouching down or not + /// + /// True for humanlike pawns currently doing a job during which they should be crouching down + public static bool IsCrouching(this Pawn pawn) + { + return pawn.RaceProps.Humanlike && (pawn.CurJob?.def.GetModExtension()?.isCrouchJob ?? false); + } + + public static bool IsTree(this Thing thing) + { + return thing.def.category == ThingCategory.Plant && thing.def.altitudeLayer == AltitudeLayer.Building; + } + + #endregion Physics + + #region Inventory + + public static void TryUpdateInventory(Pawn pawn) + { + if (pawn != null) + { + CompInventory comp = pawn.TryGetComp(); + if (comp != null) + { + comp.UpdateInventory(); + } + } + } + + public static void TryUpdateInventory(ThingOwner owner) + { + Pawn pawn = owner?.Owner?.ParentHolder as Pawn; + if (pawn != null) + { + TryUpdateInventory(pawn); + } + } + + #endregion + } +} \ No newline at end of file diff --git a/Source/CombatExtended/CombatExtended/CollisionVertical.cs b/Source/CombatExtended/CombatExtended/CollisionVertical.cs new file mode 100644 index 0000000000..08472ef3a4 --- /dev/null +++ b/Source/CombatExtended/CombatExtended/CollisionVertical.cs @@ -0,0 +1,122 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using UnityEngine; + +namespace CombatExtended +{ + public struct CollisionVertical + { + private const float TreeCollisionHeight = 5f; // Trees are this tall + private const float WallCollisionHeight = 2f; // Walls are this tall + public const float BodyRegionBottomHeight = 0.45f; // Hits below this percentage will impact the corresponding body region + public const float BodyRegionMiddleHeight = 0.85f; // This also sets the altitude at which pawns hold their guns + + private readonly FloatRange heightRange; + public readonly float shotHeight; + + public FloatRange HeightRange => new FloatRange(heightRange.min, heightRange.max); + public float Min => heightRange.min; + public float Max => heightRange.max; + public float BottomHeight => Max * BodyRegionBottomHeight; + public float MiddleHeight => Max * BodyRegionMiddleHeight; + + public CollisionVertical(Thing thing) + { + CalculateHeightRange(thing, out heightRange, out shotHeight); + } + + private static void CalculateHeightRange(Thing thing, out FloatRange heightRange, out float shotHeight) + { + shotHeight = 0; + if (thing == null) + { + heightRange = new FloatRange(0, 0); + return; + } + if (thing is Building) + { + if (thing.def.Fillage == FillCategory.Full) + { + heightRange = new FloatRange(0, WallCollisionHeight); + return; + } + if (thing.IsTree()) + { + heightRange = new FloatRange(0, TreeCollisionHeight); // Check for trees + return; + } + float fillPercent = thing.def.fillPercent; + heightRange = new FloatRange(Mathf.Min(0f, fillPercent), Mathf.Max(0f, fillPercent)); + shotHeight = fillPercent; + return; + } + float collisionHeight = 0f; + float shotHeightOffset = 0; + var pawn = thing as Pawn; + if (pawn != null) + { + collisionHeight = pawn.BodySize * CE_Utility.GetCollisionBodyFactors(pawn).Second; + shotHeightOffset = collisionHeight * (1 - BodyRegionMiddleHeight); + + // Humanlikes in combat crouch to reduce their profile + if (pawn.IsCrouching()) + { + float crouchHeight = BodyRegionBottomHeight * collisionHeight; // Minimum height we can crouch down to + + // Find the highest adjacent cover + Map map = pawn.Map; + foreach(IntVec3 curCell in GenAdjFast.AdjacentCells8Way(pawn.Position)) + { + if (curCell.InBounds(map)) + { + Thing cover = curCell.GetCover(map); + if (cover != null && cover.def.Fillage == FillCategory.Partial && !cover.IsTree()) + { + var coverHeight = new CollisionVertical(cover).Max; + if (coverHeight > crouchHeight) crouchHeight = coverHeight; + } + } + } + collisionHeight = Mathf.Min(collisionHeight, crouchHeight + 0.01f + shotHeightOffset); // We crouch down only so far that we can still shoot over our own cover and never beyond our own body size + } + } + else + { + collisionHeight = thing.def.fillPercent; + } + var edificeHeight = 0f; + if (thing.Map != null) + { + var edifice = thing.Position.GetCover(thing.Map); + if (edifice != null && edifice.GetHashCode() != thing.GetHashCode() && !edifice.IsTree()) + { + edificeHeight = new CollisionVertical(edifice).heightRange.max; + } + } + float fillPercent2 = collisionHeight; + heightRange = new FloatRange(Mathf.Min(edificeHeight, edificeHeight + fillPercent2), Mathf.Max(edificeHeight, edificeHeight + fillPercent2)); + shotHeight = heightRange.max - shotHeightOffset; + } + + /// + /// Calculates the BodyPartHeight based on how high a projectile impacted in relation to overall pawn height. + /// + /// The height of the projectile at time of impact. + /// BodyPartHeight between Bottom and Top. + public BodyPartHeight GetCollisionBodyHeight(float projectileHeight) + { + if (projectileHeight < BottomHeight) return BodyPartHeight.Bottom; + else if (projectileHeight < MiddleHeight) return BodyPartHeight.Middle; + return BodyPartHeight.Top; + } + + public BodyPartHeight GetRandWeightedBodyHeightBelow(float threshold) + { + return GetCollisionBodyHeight(Rand.Range(Min, threshold)); + } + } +} diff --git a/Source/CombatRealism/CombatExtended/Comps/CompAmmoUser.cs b/Source/CombatExtended/CombatExtended/Comps/CompAmmoUser.cs similarity index 50% rename from Source/CombatRealism/CombatExtended/Comps/CompAmmoUser.cs rename to Source/CombatExtended/CombatExtended/Comps/CompAmmoUser.cs index 163b74282d..689ee28b38 100644 --- a/Source/CombatRealism/CombatExtended/Comps/CompAmmoUser.cs +++ b/Source/CombatExtended/CombatExtended/Comps/CompAmmoUser.cs @@ -15,10 +15,10 @@ public class CompAmmoUser : CompRangedGizmoGiver #region Fields private int curMagCountInt; - private LocalTargetInfo storedTarget = null; - private JobDef storedJobDef = null; private AmmoDef currentAmmoInt = null; - public AmmoDef selectedAmmo; + private AmmoDef selectedAmmo; + + private Thing ammoToBeDeleted; public Building_TurretGunCE turret; // Cross-linked from CE turret @@ -49,27 +49,53 @@ public Pawn wielder { get { - if (compEquippable == null || compEquippable.PrimaryVerb == null) + if (compEquippable == null || compEquippable.PrimaryVerb == null || compEquippable.PrimaryVerb.caster == null) { return null; } return compEquippable.PrimaryVerb.CasterPawn; } } + public Pawn holder + { + get + { + return wielder ?? (compEquippable.parent.ParentHolder as Pawn_InventoryTracker)?.pawn; + } + } public bool useAmmo { get { - return Props.ammoSet != null; + return Controller.settings.EnableAmmoSystem && Props.ammoSet != null; } } + public bool hasAndUsesAmmoOrMagazine + { + get + { + return !useAmmo || hasAmmoOrMagazine; + } + } + public bool hasAmmoOrMagazine + { + get + { + return (hasMagazine && curMagCount > 0) || hasAmmo; + } + } + public bool canBeFiredNow + { + get + { + return !useAmmo || ((hasMagazine && curMagCount > 0) || (!hasMagazine && hasAmmo)); + } + } public bool hasAmmo { get { - if (compInventory == null) - return false; - return compInventory.ammoList.Any(x => Props.ammoSet.ammoTypes.Contains(x.def)); + return compInventory != null && compInventory.ammoList.Any(x => Props.ammoSet.ammoTypes.Any(a => a.ammo == x.def)); } } public bool hasMagazine { get { return Props.magazineSize > 0; } } @@ -77,27 +103,55 @@ public AmmoDef currentAmmo { get { - return currentAmmoInt; + return useAmmo ? currentAmmoInt : null; } } + public ThingDef CurAmmoProjectile => Props.ammoSet?.ammoTypes?.FirstOrDefault(x => x.ammo == currentAmmo).projectile; public CompInventory compInventory { get { - return wielder.TryGetComp(); + return holder.TryGetComp(); } } - private IntVec3 position + private IntVec3 Position { get { if (wielder != null) return wielder.Position; else if (turret != null) return turret.Position; + else if (holder != null) return holder.Position; else return parent.Position; } } + private Map Map + { + get + { + if (holder != null) return holder.MapHeld; + else if (turret != null) return turret.MapHeld; + else return parent.MapHeld; + } + } + public bool ShouldThrowMote => Props.throwMote && Props.magazineSize > 1; - #endregion + public AmmoDef SelectedAmmo + { + get + { + return selectedAmmo; + } + set + { + selectedAmmo = value; + if (!hasMagazine && currentAmmo != value) + { + currentAmmoInt = value; + } + } + } + + #endregion Properties #region Methods @@ -105,7 +159,7 @@ public override void Initialize(CompProperties vprops) { base.Initialize(vprops); - curMagCountInt = Props.spawnUnloaded ? 0 : Props.magazineSize; + curMagCountInt = Props.spawnUnloaded && useAmmo ? 0 : Props.magazineSize; // Initialize ammo with default if none is set if (useAmmo) @@ -117,7 +171,7 @@ public override void Initialize(CompProperties vprops) else { if (currentAmmoInt == null) - currentAmmoInt = (AmmoDef)Props.ammoSet.ammoTypes[0]; + currentAmmoInt = (AmmoDef)Props.ammoSet.ammoTypes[0].ammo; if (selectedAmmo == null) selectedAmmo = currentAmmoInt; } @@ -127,9 +181,9 @@ public override void Initialize(CompProperties vprops) public override void PostExposeData() { base.PostExposeData(); - Scribe_Values.LookValue(ref curMagCountInt, "count", 0); - Scribe_Defs.LookDef(ref currentAmmoInt, "currentAmmo"); - Scribe_Defs.LookDef(ref selectedAmmo, "selectedAmmo"); + Scribe_Values.Look(ref curMagCountInt, "count", 0); + Scribe_Defs.Look(ref currentAmmoInt, "currentAmmo"); + Scribe_Defs.Look(ref selectedAmmo, "selectedAmmo"); } private void AssignJobToWielder(Job job) @@ -144,6 +198,31 @@ private void AssignJobToWielder(Job job) } } + public bool Notify_ShotFired() + { + if (ammoToBeDeleted != null) + { + ammoToBeDeleted.Destroy(); + ammoToBeDeleted = null; + compInventory.UpdateInventory(); + if (!hasAmmoOrMagazine) + { + return false; + } + } + return true; + } + + public bool Notify_PostShotFired() + { + if (!hasAmmoOrMagazine) + { + DoOutOfAmmoAction(); + return false; + } + return true; + } + /// /// Reduces ammo count and updates inventory if necessary, call this whenever ammo is consumed by the gun (e.g. firing a shot, clearing a jam) /// @@ -159,25 +238,22 @@ public bool TryReduceAmmoCount() { if (useAmmo) { - Thing ammo; - - if (!TryFindAmmoInInventory(out ammo)) + if (!TryFindAmmoInInventory(out ammoToBeDeleted)) { return false; } - - if (ammo.stackCount > 1) - ammo = ammo.SplitOff(1); - - ammo.Destroy(); - compInventory.UpdateInventory(); - if (!hasAmmo) - DoOutOfAmmoAction(); + if (ammoToBeDeleted.def != currentAmmo) + { + currentAmmoInt = ammoToBeDeleted.def as AmmoDef; + } + + if (ammoToBeDeleted.stackCount > 1) + ammoToBeDeleted = ammoToBeDeleted.SplitOff(1); } return true; } // If magazine is empty, return false - else if (curMagCountInt <= 0) + if (curMagCountInt <= 0) { curMagCountInt = 0; return false; @@ -191,44 +267,24 @@ public bool TryReduceAmmoCount() if (curMagCountInt < 0) TryStartReload(); return true; } - + + // really only used by pawns (JobDriver_Reload) at this point... TODO: Finish making sure this is only used by pawns and fix up the error checking. + /// + /// Overrides a Pawn's current activities to start reloading a gun or turret. Has a code path to resume the interrupted job. + /// public void TryStartReload() { if (!hasMagazine) { return; } - IntVec3 position; - if (wielder == null) - { - if (turret == null) return; - turret.isReloading = true; - position = turret.Position; - } - else - { - position = wielder.Position; - } + if (wielder == null && turret == null) + return; if (useAmmo) { - // Add remaining ammo back to inventory - if (curMagCountInt > 0) - { - Thing ammoThing = ThingMaker.MakeThing(currentAmmoInt); - ammoThing.stackCount = curMagCountInt; - curMagCountInt = 0; - - if (compInventory != null) - { - compInventory.container.TryAdd(ammoThing, ammoThing.stackCount); - } - else - { - Thing outThing; - GenThing.TryDropAndSetForbidden(ammoThing, position, Find.VisibleMap, ThingPlaceMode.Near, out outThing, turret.Faction != Faction.OfPlayer); - } - } + TryUnload(); + // Check for ammo if (wielder != null && !hasAmmo) { @@ -237,106 +293,98 @@ public void TryStartReload() } } - // Throw mote - if (Props.throwMote) - { - MoteMaker.ThrowText(position.ToVector3Shifted(), Find.VisibleMap, "CE_ReloadingMote".Translate()); - } + // secondary branch for if we ended up being called up by a turret somehow... + if (turret != null) + turret.TryOrderReload(); // Issue reload job if (wielder != null) { - Job reloadJob = new Job(CE_JobDefOf.ReloadWeapon, wielder, parent) - { - playerForced = true - }; - - // Store the current job so we can reassign it later - if (wielder.Faction == Faction.OfPlayer - && wielder.CurJob != null - && (wielder.CurJob.def == JobDefOf.AttackStatic || wielder.CurJob.def == JobDefOf.Goto || wielder.CurJob.def == JobDefOf.Hunt)) - { - if (wielder.CurJob.targetA.HasThing) storedTarget = new LocalTargetInfo(wielder.CurJob.targetA.Thing); - else storedTarget = new LocalTargetInfo(wielder.CurJob.targetA.Cell); - storedJobDef = wielder.CurJob.def; - } - else - { - storedTarget = null; - storedJobDef = null; - } - AssignJobToWielder(reloadJob); + Job reloadJob = TryMakeReloadJob(); + if (reloadJob == null) + return; + reloadJob.playerForced = true; + wielder.jobs.StartJob(reloadJob, JobCondition.InterruptForced, null, wielder.CurJob?.def != reloadJob.def, true); } } - public Job ReloadJob() + // used by both turrets (JobDriver_ReloadTurret) and pawns (JobDriver_Reload). + /// + /// Used to unload the weapon. Ammo will be dumped to the unloading Pawn's inventory or the ground if insufficient space. Any ammo that can't be dropped + /// on the ground is destroyed (with a warning). + /// + /// bool, true indicates the weapon was already in an unloaded state or the unload was successful. False indicates an error state. + /// + /// Failure to unload occurs if the weapon doesn't use a magazine. + /// + public bool TryUnload() { - if (!hasMagazine) - { - return null; - } - IntVec3 position = wielder.Position; - - if (useAmmo) - { - // Add remaining ammo back to inventory - if (curMagCountInt > 0) - { - Thing ammoThing = ThingMaker.MakeThing(currentAmmoInt); - ammoThing.stackCount = curMagCountInt; - curMagCountInt = 0; - - if (compInventory != null) - { - compInventory.container.TryAdd(ammoThing, ammoThing.stackCount); - } - else - { - Thing outThing; - GenThing.TryDropAndSetForbidden(ammoThing, position, Find.VisibleMap, ThingPlaceMode.Near, out outThing, turret.Faction != Faction.OfPlayer); - } - } - // Check for ammo - if (wielder != null && !hasAmmo) - { - DoOutOfAmmoAction(); - return null; - } - } + Thing outThing; + return TryUnload(out outThing); + } - // Throw mote - if (Props.throwMote) - { - MoteMaker.ThrowText(position.ToVector3Shifted(), Find.VisibleMap, "CE_ReloadingMote".Translate()); - } + public bool TryUnload(out Thing droppedAmmo) + { + droppedAmmo = null; + if (!hasMagazine || (holder == null && turret == null)) + return false; // nothing to do as we are in a bad state; + + if (!useAmmo || curMagCountInt == 0) + return true; // nothing to do but we aren't in a bad state either. Claim success. + + // Add remaining ammo back to inventory + Thing ammoThing = ThingMaker.MakeThing(currentAmmoInt); + ammoThing.stackCount = curMagCountInt; + bool doDrop = false; - // Issue reload job - if (wielder != null) + if (compInventory != null) + doDrop = (curMagCountInt != compInventory.container.TryAdd(ammoThing, ammoThing.stackCount)); // TryAdd should report how many ammoThing.stackCount it stored. + else + doDrop = true; // Inventory was null so no place to shift the ammo besides the ground. + + if (doDrop) { - Job reloadJob = new Job(CE_JobDefOf.ReloadWeapon, wielder, parent) + // NOTE: If we get here from ThingContainer.TryAdd() it will have modified the ammoThing.stackCount to what it couldn't take. + //Thing outThing; + if (!GenThing.TryDropAndSetForbidden(ammoThing, Position, Map, ThingPlaceMode.Near, out droppedAmmo, turret.Faction != Faction.OfPlayer)) { - playerForced = true - }; - - return reloadJob; + Log.Warning(String.Concat(this.GetType().Assembly.GetName().Name + " :: " + this.GetType().Name + " :: ", + "Unable to drop ", ammoThing.LabelCap, " on the ground, thing was destroyed.")); + } } - return null; + + // don't forget to set the clip to empty... + curMagCountInt = 0; + + return true; } - - + + /// + /// Used to fetch a reload job for the weapon this comp is on. Sets storedInfo to null (as if no job being replaced). + /// + /// Job using JobDriver_Reload + /// TryUnload() should be called before this in most cases. + public Job TryMakeReloadJob() + { + if (!hasMagazine || (holder == null && turret == null)) + return null; // the job couldn't be created. + + return new Job(CE_JobDefOf.ReloadWeapon, holder, parent); + } + private void DoOutOfAmmoAction() { - if (Props.throwMote) + if (ShouldThrowMote) { - MoteMaker.ThrowText(position.ToVector3Shifted(), Find.VisibleMap, "CE_OutOfAmmo".Translate() + "!"); + MoteMaker.ThrowText(Position.ToVector3Shifted(), Find.VisibleMap, "CE_OutOfAmmo".Translate() + "!"); } - if (wielder != null && compInventory != null && (wielder.jobs == null || wielder.CurJob.def != JobDefOf.Hunt)) compInventory.SwitchToNextViableWeapon(); + if (wielder != null && compInventory != null && (wielder.CurJob == null || wielder.CurJob.def != JobDefOf.Hunt)) compInventory.SwitchToNextViableWeapon(); } public void LoadAmmo(Thing ammo = null) { - if (wielder == null && turret == null) - { + if (holder == null && turret == null) + { Log.Error(parent.ToString() + " tried loading ammo with no owner"); return; } @@ -385,8 +433,7 @@ public void LoadAmmo(Thing ammo = null) } curMagCountInt = newMagCount; if (turret != null) turret.isReloading = false; - if (parent.def.soundInteract != null) parent.def.soundInteract.PlayOneShot(new TargetInfo(position, Find.VisibleMap, false)); - if (Props.throwMote) MoteMaker.ThrowText(position.ToVector3Shifted(), Find.VisibleMap, "CE_ReloadedMote".Translate()); + if (parent.def.soundInteract != null) parent.def.soundInteract.PlayOneShot(new TargetInfo(Position, Find.VisibleMap, false)); } private bool TryFindAmmoInInventory(out Thing ammoThing) @@ -405,31 +452,18 @@ private bool TryFindAmmoInInventory(out Thing ammoThing) } // Try finding ammo from different type - foreach (AmmoDef ammoDef in Props.ammoSet.ammoTypes) + foreach (AmmoLink link in Props.ammoSet.ammoTypes) { - ammoThing = compInventory.ammoList.Find(thing => thing.def == ammoDef); + ammoThing = compInventory.ammoList.Find(thing => thing.def == link.ammo); if (ammoThing != null) { - selectedAmmo = ammoDef; + selectedAmmo = (AmmoDef)link.ammo; return true; } } return false; } - public void TryContinuePreviousJob() - { - //If a job is stored, assign it - if (storedTarget != null && storedJobDef != null) - { - AssignJobToWielder(new Job(storedJobDef, storedTarget)); - - //Clear out stored job after assignment - storedTarget = null; - storedJobDef = null; - } - } - public override IEnumerable CompGetGizmosExtra() { GizmoAmmoStatus ammoStatusGizmo = new GizmoAmmoStatus { compAmmo = this }; @@ -438,8 +472,22 @@ public override IEnumerable CompGetGizmosExtra() if ((wielder != null && wielder.Faction == Faction.OfPlayer) || (turret != null && turret.Faction == Faction.OfPlayer)) { Action action = null; - if (wielder != null) action = TryStartReload; - else if (turret != null && turret.GetMannableComp() != null) action = turret.OrderReload; + if (wielder != null) action = delegate { TryStartReload(); }; + else if (turret != null && turret.MannableComp != null) action = turret.TryOrderReload; + + // Check for teaching opportunities + string tag; + if(turret == null) + { + if (hasMagazine) tag = "CE_Reload"; // Teach reloading weapons with magazines + else tag = "CE_ReloadNoMag"; // Teach about mag-less weapons + } + else + { + if (turret.MannableComp == null) tag = "CE_ReloadAuto"; // Teach about auto-turrets + else tag = "CE_ReloadManned"; // Teach about reloading manned turrets + } + LessonAutoActivator.TeachOpportunity(ConceptDef.Named(tag), turret, OpportunityType.GoodToKnow); Command_Reload reloadCommandGizmo = new Command_Reload { @@ -447,22 +495,37 @@ public override IEnumerable CompGetGizmosExtra() action = action, defaultLabel = hasMagazine ? "CE_ReloadLabel".Translate() : "", defaultDesc = "CE_ReloadDesc".Translate(), - icon = currentAmmo == null ? ContentFinder.Get("UI/Buttons/Reload", true) : Def_Extensions.IconTexture(selectedAmmo) + icon = currentAmmo == null ? ContentFinder.Get("UI/Buttons/Reload", true) : Def_Extensions.IconTexture(selectedAmmo), + tutorTag = tag }; yield return reloadCommandGizmo; } } + public override string TransformLabel(string label) + { + string ammoSet = useAmmo && Controller.settings.ShowCaliberOnGuns ? " (" + Props.ammoSet.LabelCap + ") " : ""; + return label + ammoSet; + } + public override string GetDescriptionPart() { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("CE_MagazineSize".Translate() + ": " + GenText.ToStringByStyle(Props.magazineSize, ToStringStyle.Integer)); - stringBuilder.AppendLine("CE_ReloadTime".Translate() + ": " + GenText.ToStringByStyle((Props.reloadTicks / 60), ToStringStyle.Integer) + " s"); - if (Props.ammoSet != null) - stringBuilder.AppendLine("CE_AmmoSet".Translate() + ": " + Props.ammoSet.LabelCap); - return stringBuilder.ToString(); + stringBuilder.AppendLine("CE_ReloadTime".Translate() + ": " + GenText.ToStringByStyle((Props.reloadTime), ToStringStyle.FloatTwo) + " s"); + if (useAmmo) + { + // Append various ammo stats + stringBuilder.AppendLine("CE_AmmoSet".Translate() + ": " + Props.ammoSet.LabelCap + "\n"); + foreach(var cur in Props.ammoSet.ammoTypes) + { + string label = string.IsNullOrEmpty(cur.ammo.ammoClass.LabelCapShort) ? cur.ammo.ammoClass.LabelCap : cur.ammo.ammoClass.LabelCapShort; + stringBuilder.AppendLine(label + ":\n" + cur.projectile.GetProjectileReadout()); + } + } + return stringBuilder.ToString().TrimEndNewlines(); } - #endregion + #endregion Methods } } \ No newline at end of file diff --git a/Source/CombatRealism/CombatExtended/Comps/CompCharges.cs b/Source/CombatExtended/CombatExtended/Comps/CompCharges.cs similarity index 100% rename from Source/CombatRealism/CombatExtended/Comps/CompCharges.cs rename to Source/CombatExtended/CombatExtended/Comps/CompCharges.cs diff --git a/Source/CombatExtended/CombatExtended/Comps/CompExplosiveCE.cs b/Source/CombatExtended/CombatExtended/Comps/CompExplosiveCE.cs new file mode 100644 index 0000000000..46638a904f --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Comps/CompExplosiveCE.cs @@ -0,0 +1,92 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using RimWorld; +using Verse; +using UnityEngine; + +namespace CombatExtended +{ + public class CompExplosiveCE : ThingComp + { + public CompProperties_ExplosiveCE Props + { + get + { + return (CompProperties_ExplosiveCE)props; + } + } + + /// + /// Produces a secondary explosion on impact using the explosion values from the projectile's projectile def. Requires the projectile's launcher to be passed on due to protection level. + /// Intended use is for HEAT and similar weapons that spawn secondary explosions while also penetrating, NOT explosive ammo of anti-materiel rifles as the explosion just spawns + /// on top of the pawn, not inside the hit body part. + /// + /// Additionally handles fragmentation effects if defined. + /// + /// Launcher of the projectile calling the method + public virtual void Explode(Thing instigator, IntVec3 pos, Map map, float scaleFactor = 1) + { + if (map == null) + { + Log.Warning("Tried to do explodeCE in a null map."); + return; + } + if (!pos.InBounds(map)) + { + Log.Warning("Tried to explodeCE out of bounds"); + return; + } + + // Fragmentation stuff + if (!Props.fragments.NullOrEmpty() && GenGrid.InBounds(pos, map)) + { + Vector2 exactOrigin = new Vector2(parent.DrawPos.x, parent.DrawPos.z); + float height = (new CollisionVertical(pos.GetEdifice(map))).Max; + + foreach (ThingCountClass fragment in Props.fragments) + { + for (int i = 0; i < fragment.count; i++) + { + ProjectileCE projectile = (ProjectileCE)ThingMaker.MakeThing(fragment.thingDef, null); + GenSpawn.Spawn(projectile, pos, map); + + var projCE = parent as ProjectileCE; + if (projCE != null) + { + height = Mathf.Max(height, projCE.Height); + } + + projectile.canTargetSelf = true; + projectile.minCollisionSqr = 1f; + projectile.Launch(instigator, exactOrigin, UnityEngine.Random.Range(0, Mathf.PI / 4f), UnityEngine.Random.Range(0, 360), height, Props.fragSpeedFactor * projectile.def.projectile.speed); + } + } + } + // Regular explosion stuff + if (Props.explosionRadius > 0 && Props.explosionDamage > 0 && parent.def != null && GenGrid.InBounds(pos, map)) + { + // Can't use GenExplosion because it no longer allows setting damage amount + + // Copy-paste from GenExplosion + Explosion explosion = new Explosion(); + explosion.position = pos; + explosion.radius = Props.explosionRadius * scaleFactor; + explosion.damType = Props.explosionDamageDef; + explosion.instigator = instigator; + explosion.damAmount = GenMath.RoundRandom(Props.explosionDamage * scaleFactor); + explosion.weaponGear = null; + explosion.preExplosionSpawnThingDef = Props.preExplosionSpawnThingDef; + explosion.preExplosionSpawnChance = Props.explosionSpawnChance; + explosion.preExplosionSpawnThingCount = Props.preExplosionSpawnThingCount; + explosion.postExplosionSpawnThingDef = Props.postExplosionSpawnThingDef; + explosion.postExplosionSpawnChance = Props.postExplosionSpawnChance; + explosion.postExplosionSpawnThingCount = Props.postExplosionSpawnThingCount; + explosion.applyDamageToExplosionCellsNeighbors = Props.applyDamageToExplosionCellsNeighbors; + map.GetComponent().StartExplosion(explosion, Props.soundExplode ?? Props.explosionDamageDef.soundExplosion); + } + } + } +} diff --git a/Source/CombatRealism/CombatExtended/Comps/CompFireModes.cs b/Source/CombatExtended/CombatExtended/Comps/CompFireModes.cs similarity index 67% rename from Source/CombatRealism/CombatExtended/Comps/CompFireModes.cs rename to Source/CombatExtended/CombatExtended/Comps/CompFireModes.cs index c6a42756fa..92b8ddf415 100644 --- a/Source/CombatRealism/CombatExtended/Comps/CompFireModes.cs +++ b/Source/CombatExtended/CombatExtended/Comps/CompFireModes.cs @@ -10,6 +10,19 @@ namespace CombatExtended { public class CompFireModes : CompRangedGizmoGiver { + + #region Fields + + private Verb verbInt = null; + private List availableFireModes = new List(Enum.GetNames(typeof(FireMode)).Length); + private List availableAimModes = new List(Enum.GetNames(typeof(AimMode)).Length) { AimMode.AimedShot }; + private FireMode currentFireModeInt; + private AimMode currentAimModeInt; + + #endregion + + #region Properties + public CompProperties_FireModes Props { get @@ -19,8 +32,7 @@ public CompProperties_FireModes Props } // Fire mode variables - private Verb verbInt = null; - private Verb verb + private Verb Verb { get { @@ -39,39 +51,41 @@ private Verb verb return verbInt; } } - public Thing caster + public Thing Caster { get { - return verb.caster; + return Verb.caster; } } - public Pawn casterPawn + public Pawn CasterPawn { get { - return caster as Pawn; + return Caster as Pawn; } } - private List availableFireModes = new List(); - private List availableAimModes = new List { AimMode.Snapshot, AimMode.AimedShot, AimMode.HoldFire }; - - private FireMode currentFireModeInt; - public FireMode currentFireMode + public FireMode CurrentFireMode { get { + if (useAIModes && Props.aiUseBurstMode && availableFireModes.Contains(FireMode.BurstFire)) return FireMode.BurstFire; return currentFireModeInt; } } - private AimMode currentAimModeInt; - public AimMode currentAimMode + public AimMode CurrentAimMode { get { + if (useAIModes && availableAimModes.Contains(Props.aiAimMode)) return Props.aiAimMode; return currentAimModeInt; } } + private bool useAIModes => Caster.Faction != Faction.OfPlayer; + + #endregion + + #region Methods public override void Initialize(CompProperties props) { @@ -82,20 +96,20 @@ public override void Initialize(CompProperties props) public override void PostExposeData() { base.PostExposeData(); - Scribe_Values.LookValue(ref currentFireModeInt, "currentFireMode", FireMode.AutoFire); - Scribe_Values.LookValue(ref currentAimModeInt, "currentAimMode", AimMode.Snapshot); + Scribe_Values.Look(ref currentFireModeInt, "currentFireMode", FireMode.AutoFire); + Scribe_Values.Look(ref currentAimModeInt, "currentAimMode", AimMode.Snapshot); } private void InitAvailableFireModes() { // Calculate available fire modes - if (verb.verbProps.burstShotCount > 1 || Props.noSingleShot) + if (Verb.verbProps.burstShotCount > 1 || Props.noSingleShot) { availableFireModes.Add(FireMode.AutoFire); } if (Props.aimedBurstShotCount > 1) { - if (Props.aimedBurstShotCount >= verb.verbProps.burstShotCount) + if (Props.aimedBurstShotCount >= Verb.verbProps.burstShotCount) { Log.Warning(parent.LabelCap + " burst fire shot count is same or higher than auto fire"); } @@ -108,10 +122,14 @@ private void InitAvailableFireModes() { availableFireModes.Add(FireMode.SingleFire); } - if (Props.noSnapshot) availableAimModes.Remove(AimMode.Snapshot); + if (!Props.noSnapshot) + { + availableAimModes.Insert(0, AimMode.Snapshot); + availableAimModes.Add(AimMode.SuppressFire); + } // Sanity check in case def changed - if (!availableFireModes.Contains(currentFireModeInt) || !availableAimModes.Contains(currentAimMode)) + if (!availableFireModes.Contains(currentFireModeInt) || !availableAimModes.Contains(currentAimModeInt)) { ResetModes(); } @@ -125,6 +143,7 @@ public void ToggleFireMode() int currentFireModeNum = availableFireModes.IndexOf(currentFireModeInt); currentFireModeNum = (currentFireModeNum + 1) % availableFireModes.Count; currentFireModeInt = availableFireModes.ElementAt(currentFireModeNum); + if (availableFireModes.Count > 1) PlayerKnowledgeDatabase.KnowledgeDemonstrated(CE_ConceptDefOf.CE_FireModes, KnowledgeAmount.Total); } public void ToggleAimMode() @@ -132,6 +151,7 @@ public void ToggleAimMode() int currentAimModeNum = availableAimModes.IndexOf(currentAimModeInt); currentAimModeNum = (currentAimModeNum + 1) % availableAimModes.Count; currentAimModeInt = availableAimModes.ElementAt(currentAimModeNum); + if (availableAimModes.Count > 1) PlayerKnowledgeDatabase.KnowledgeDemonstrated(CE_ConceptDefOf.CE_AimModes, KnowledgeAmount.Total); } /// @@ -145,7 +165,7 @@ public void ResetModes() public override IEnumerable CompGetGizmosExtra() { - if (casterPawn != null && casterPawn.Faction.Equals(Faction.OfPlayer)) + if (CasterPawn != null && CasterPawn.Faction.Equals(Faction.OfPlayer)) { foreach(Command com in GenerateGizmos()) { @@ -159,19 +179,32 @@ public IEnumerable GenerateGizmos() Command_Action toggleFireModeGizmo = new Command_Action { action = ToggleFireMode, - defaultLabel = ("CE_" + currentFireMode.ToString() + "Label").Translate(), + defaultLabel = ("CE_" + currentFireModeInt.ToString() + "Label").Translate(), defaultDesc = "CE_ToggleFireModeDesc".Translate(), - icon = ContentFinder.Get(("UI/Buttons/" + currentFireMode.ToString()), true) + icon = ContentFinder.Get(("UI/Buttons/" + currentFireModeInt.ToString()), true), + tutorTag = availableFireModes.Count > 1 ? "CE_FireModeToggle" : null }; + if (availableFireModes.Count > 1) + { + // Teach about fire modes + toggleFireModeGizmo.tutorTag = "CE_FireModeToggle"; + LessonAutoActivator.TeachOpportunity(CE_ConceptDefOf.CE_FireModes, parent, OpportunityType.GoodToKnow); + } yield return toggleFireModeGizmo; Command_Action toggleAimModeGizmo = new Command_Action { action = ToggleAimMode, - defaultLabel = ("CE_" + currentAimMode.ToString() + "Label").Translate(), + defaultLabel = ("CE_" + currentAimModeInt.ToString() + "Label").Translate(), defaultDesc = "CE_ToggleAimModeDesc".Translate(), - icon = ContentFinder.Get(("UI/Buttons/" + currentAimMode.ToString()), true) + icon = ContentFinder.Get(("UI/Buttons/" + currentAimModeInt.ToString()), true), }; + if (availableAimModes.Count > 1) + { + // Teach about aim modes + toggleAimModeGizmo.tutorTag = "CE_AimModeToggle"; + LessonAutoActivator.TeachOpportunity(CE_ConceptDefOf.CE_AimModes, parent, OpportunityType.GoodToKnow); + } yield return toggleAimModeGizmo; } @@ -190,7 +223,9 @@ public override string GetDescriptionPart() stringBuilder.AppendLine("CE_AimedBurstCount".Translate() + ": " + GenText.ToStringByStyle(Props.aimedBurstShotCount, ToStringStyle.Integer)); } } - return stringBuilder.ToString(); + return stringBuilder.ToString().TrimEndNewlines(); } - } + + #endregion + } } diff --git a/Source/CombatRealism/CombatExtended/Comps/CompInventory.cs b/Source/CombatExtended/CombatExtended/Comps/CompInventory.cs similarity index 80% rename from Source/CombatRealism/CombatExtended/Comps/CompInventory.cs rename to Source/CombatExtended/CombatExtended/Comps/CompInventory.cs index 6b0e18bf4c..cd8572da02 100644 --- a/Source/CombatRealism/CombatExtended/Comps/CompInventory.cs +++ b/Source/CombatExtended/CombatExtended/Comps/CompInventory.cs @@ -11,6 +11,23 @@ namespace CombatExtended { public class CompInventory : ThingComp { + #region Fields + + private Pawn parentPawnInt = null; + private bool initializedLoadouts = false; + private int ticksToInitLoadout = 5; // Generate loadouts this many ticks after spawning + private const int CLEANUPTICKINTERVAL = GenTicks.TickLongInterval; + private int ticksToNextCleanUp = GenTicks.TicksAbs; + private float currentWeightCached; + private float currentBulkCached; + private List ammoListCached = new List(); + private List meleeWeaponListCached = new List(); + private List rangedWeaponListCached = new List(); + + #endregion + + #region Properties + public CompProperties_Inventory Props { get @@ -19,8 +36,6 @@ public CompProperties_Inventory Props } } - private float currentWeightCached; - private float currentBulkCached; public float currentWeight { get @@ -63,7 +78,6 @@ public float capacityWeight return parentPawn.GetStatValue(CE_StatDefOf.CarryWeight); } } - private Pawn parentPawnInt = null; private Pawn parentPawn { get @@ -96,7 +110,7 @@ public float encumberPenalty return MassBulkUtility.EncumberPenalty(currentWeight, capacityWeight); } } - public ThingContainer container + public ThingOwner container { get { @@ -107,24 +121,27 @@ public ThingContainer container return null; } } - private List ammoListCached = new List(); - public List ammoList - { - get - { - return ammoListCached; - } - } - private List meleeWeaponListCached = new List(); + public List ammoList => ammoListCached; public List meleeWeaponList => meleeWeaponListCached; - private List rangedWeaponListCached = new List(); public List rangedWeaponList => rangedWeaponListCached; - private bool initializedLoadouts = false; - private int ticksToInitLoadout = 5; // Generate loadouts this many ticks after spawning - public override void PostSpawnSetup() + #endregion Properties + + #region Methods + + /// + /// Similar to ThingContainer.TotalStackCountOfDef(), returns the count of all matching AmmoDefs in AmmoList cache. + /// + /// ThingDef to count. + /// int amount of AmmoDef found in AmmoList. + public int AmmoCountOfDef(AmmoDef def) + { + return ammoListCached.Where(t => t.def == def).Sum(t => t.stackCount); + } + + public override void PostSpawnSetup(bool respawningAfterLoad) { - base.PostSpawnSetup(); + base.PostSpawnSetup(respawningAfterLoad); UpdateInventory(); } @@ -153,9 +170,11 @@ public void UpdateInventory() foreach (Thing apparel in parentPawn.apparel.WornApparel) { float apparelBulk = apparel.GetStatValue(CE_StatDefOf.WornBulk); - float apparelWeight = apparel.GetStatValue(CE_StatDefOf.WornWeight); + float apparelWeight = apparel.GetStatValue(StatDefOf.Mass); newBulk += apparelBulk; newWeight += apparelWeight; + if (apparelBulk > 0 && parentPawn != null && parentPawn.IsColonist && parentPawn.Spawned) + LessonAutoActivator.TeachOpportunity(CE_ConceptDefOf.CE_WornBulk, OpportunityType.GoodToKnow); } } @@ -165,6 +184,8 @@ public void UpdateInventory() ammoListCached.Clear(); meleeWeaponListCached.Clear(); rangedWeaponListCached.Clear(); + + List recs = LoadoutManager.GetHoldRecords(parentPawn); foreach (Thing thing in parentPawn.inventory.innerContainer) { // Check for weapons @@ -172,7 +193,7 @@ public void UpdateInventory() CompEquippable compEq = thing.TryGetComp(); if (eq != null && compEq != null) { - if (compEq.PrimaryVerb != null) + if (eq.def.IsRangedWeapon) { rangedWeaponListCached.Add(eq); } @@ -192,15 +213,18 @@ public void UpdateInventory() // Add item weight newBulk += thing.GetStatValue(CE_StatDefOf.Bulk) * thing.stackCount; newWeight += thing.GetStatValue(StatDefOf.Mass) * thing.stackCount; - //old newWeight += thing.GetStatValue(CE_StatDefOf.Weight) * thing.stackCount; - - } // Update ammo list if (thing.def is AmmoDef) { ammoListCached.Add(thing); } + if (recs != null) + { + HoldRecord rec = recs.FirstOrDefault(hr => hr.thingDef == thing.def); + if (rec != null && !rec.pickedUp) + rec.pickedUp = true; + } } } currentBulkCached = newBulk; @@ -222,7 +246,7 @@ public bool CanFitInInventory(Thing thing, out int count, bool ignoreEquipment = if (useApparelCalculations) { - thingWeight = thing.GetStatValue(CE_StatDefOf.WornWeight); + thingWeight = thing.GetStatValue(StatDefOf.Mass); thingBulk = thing.GetStatValue(CE_StatDefOf.WornBulk); if (thingWeight <= 0 && thingBulk <= 0) { @@ -283,13 +307,10 @@ public void SwitchToNextViableWeapon(bool useFists = true) // Cycle through available ranged weapons foreach (ThingWithComps gun in rangedWeaponListCached) { - if (parentPawn.equipment == null || parentPawn.equipment.Primary != gun) + if (parentPawn.equipment != null && parentPawn.equipment.Primary != gun) { CompAmmoUser compAmmo = gun.TryGetComp(); - if (compAmmo == null - || !compAmmo.useAmmo - || compAmmo.curMagCount > 0 - || compAmmo.hasAmmo) + if (compAmmo == null || compAmmo.hasAndUsesAmmoOrMagazine) { newEq = gun; break; @@ -305,24 +326,26 @@ public void SwitchToNextViableWeapon(bool useFists = true) { TrySwitchToWeapon(newEq); } - else if (useFists && parentPawn.equipment?.Primary != null) + else if (useFists) { - ThingWithComps oldEq; - if (!parentPawn.equipment.TryTransferEquipmentToContainer(parentPawn.equipment.Primary, container, out oldEq)) + // Put away current weapon + ThingWithComps eq = parentPawn.equipment?.Primary; + if (eq != null && !parentPawn.equipment.TryTransferEquipmentToContainer(eq, container)) { + // If we can't put it into our inventory, drop it if (parentPawn.Position.InBounds(parentPawn.Map)) { ThingWithComps unused; - parentPawn.equipment.TryDropEquipment(oldEq, out unused, parentPawn.Position); + parentPawn.equipment.TryDropEquipment(eq, out unused, parentPawn.Position); } else { #if DEBUG - Log.Message("CE :: CompInventory :: SwitchToNextViableWeapon :: destroying out of bounds equipment" + oldEq.ToString()); + Log.Warning("CE :: CompInventory :: SwitchToNextViableWeapon :: destroying out of bounds equipment" + eq.ToString()); #endif - if (!oldEq.Destroyed) + if (!eq.Destroyed) { - oldEq.Destroy(); + eq.Destroy(); } } } @@ -337,12 +360,10 @@ public void TrySwitchToWeapon(ThingWithComps newEq) } if (parentPawn.equipment.Primary != null) { - - ThingWithComps oldEq; int count; if (CanFitInInventory(parentPawn.equipment.Primary, out count, true)) { - parentPawn.equipment.TryTransferEquipmentToContainer(parentPawn.equipment.Primary, container, out oldEq); + parentPawn.equipment.TryTransferEquipmentToContainer(parentPawn.equipment.Primary, container); } else { @@ -352,7 +373,7 @@ public void TrySwitchToWeapon(ThingWithComps newEq) parentPawn.equipment.MakeRoomFor(newEq); } } - parentPawn.equipment.AddEquipment((ThingWithComps)container.Get(newEq, 1)); + parentPawn.equipment.AddEquipment((ThingWithComps)container.Take(newEq, 1)); if (newEq.def.soundInteract != null) newEq.def.soundInteract.PlayOneShot(new TargetInfo(parent.Position, parent.MapHeld, false)); } @@ -389,9 +410,13 @@ public override void CompTick() } initializedLoadouts = true; } - //Log.Message("CE-RD :: pre-base.comptick"); + if (GenTicks.TicksAbs >= ticksToNextCleanUp) + { + // Ask HoldTracker to clean itself up... + parentPawn.HoldTrackerCleanUp(); + ticksToNextCleanUp = GenTicks.TicksAbs + CLEANUPTICKINTERVAL; + } base.CompTick(); - //Log.Message("CE-RD :: post-base.comptick"); // Remove items from inventory if we're over the bulk limit /* while (availableBulk < 0 && container.Count > 0) @@ -411,6 +436,24 @@ public override void CompTick() } } */ + + if (Controller.settings.DebugEnableInventoryValidation) ValidateCache(); + } + + /// + /// Debug method to catch cases where inventory cache isn't being updated properly on pawn inventory change. ONLY FOR DEBUGGING, DON'T CALL THIS IN ANY KIND OF RELEASE BUILD. + /// + private void ValidateCache() + { + float oldWeight = currentWeight; + float oldBulk = currentBulk; + UpdateInventory(); + if (oldWeight != currentWeight || oldBulk != currentBulk) + { + Log.Error("CE :: CompInventory :: " + parent.ToString() + " failed inventory validation"); + } } + + #endregion Methods } } diff --git a/Source/CombatRealism/CombatExtended/Comps/CompProperties_AmmoUser.cs b/Source/CombatExtended/CombatExtended/Comps/CompProperties_AmmoUser.cs similarity index 93% rename from Source/CombatRealism/CombatExtended/Comps/CompProperties_AmmoUser.cs rename to Source/CombatExtended/CombatExtended/Comps/CompProperties_AmmoUser.cs index 86a5089e58..fd07ac9090 100644 --- a/Source/CombatRealism/CombatExtended/Comps/CompProperties_AmmoUser.cs +++ b/Source/CombatExtended/CombatExtended/Comps/CompProperties_AmmoUser.cs @@ -11,7 +11,7 @@ namespace CombatExtended public class CompProperties_AmmoUser : CompProperties { public int magazineSize = 0; - public int reloadTicks = 300; + public float reloadTime = 1; public bool throwMote = true; public AmmoSetDef ammoSet = null; public bool spawnUnloaded = false; diff --git a/Source/CombatRealism/CombatExtended/Comps/CompProperties_Charges.cs b/Source/CombatExtended/CombatExtended/Comps/CompProperties_Charges.cs similarity index 100% rename from Source/CombatRealism/CombatExtended/Comps/CompProperties_Charges.cs rename to Source/CombatExtended/CombatExtended/Comps/CompProperties_Charges.cs diff --git a/Source/CombatRealism/CombatExtended/Comps/CompProperties_ExplosiveCR.cs b/Source/CombatExtended/CombatExtended/Comps/CompProperties_ExplosiveCE.cs similarity index 96% rename from Source/CombatRealism/CombatExtended/Comps/CompProperties_ExplosiveCR.cs rename to Source/CombatExtended/CombatExtended/Comps/CompProperties_ExplosiveCE.cs index e32cb543ea..636b047cae 100644 --- a/Source/CombatRealism/CombatExtended/Comps/CompProperties_ExplosiveCR.cs +++ b/Source/CombatExtended/CombatExtended/Comps/CompProperties_ExplosiveCE.cs @@ -13,6 +13,7 @@ public class CompProperties_ExplosiveCE : CompProperties public float explosionDamage = -1; public List fragments = new List(); public float fragRange = 0f; + public float fragSpeedFactor = 1f; public float explosionRadius = 0f; public DamageDef explosionDamageDef = DamageDefOf.Bomb; diff --git a/Source/CombatRealism/CombatExtended/Comps/CompProperties_FireModes.cs b/Source/CombatExtended/CombatExtended/Comps/CompProperties_FireModes.cs similarity index 89% rename from Source/CombatRealism/CombatExtended/Comps/CompProperties_FireModes.cs rename to Source/CombatExtended/CombatExtended/Comps/CompProperties_FireModes.cs index 731424c437..8f5b1bc8dd 100644 --- a/Source/CombatRealism/CombatExtended/Comps/CompProperties_FireModes.cs +++ b/Source/CombatExtended/CombatExtended/Comps/CompProperties_FireModes.cs @@ -5,10 +5,10 @@ namespace CombatExtended public class CompProperties_FireModes : CompProperties { public int aimedBurstShotCount = -1; //will default to regular burst setting if not specified in def - public bool aiUseAimMode = false; public bool aiUseBurstMode = false; public bool noSingleShot = false; public bool noSnapshot = false; + public AimMode aiAimMode = AimMode.Snapshot; public CompProperties_FireModes() { diff --git a/Source/CombatRealism/CombatExtended/Comps/CompProperties_Inventory.cs b/Source/CombatExtended/CombatExtended/Comps/CompProperties_Inventory.cs similarity index 100% rename from Source/CombatRealism/CombatExtended/Comps/CompProperties_Inventory.cs rename to Source/CombatExtended/CombatExtended/Comps/CompProperties_Inventory.cs diff --git a/Source/CombatExtended/CombatExtended/Comps/CompProperties_SquadBrain.cs b/Source/CombatExtended/CombatExtended/Comps/CompProperties_SquadBrain.cs new file mode 100644 index 0000000000..a69c993abf --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Comps/CompProperties_SquadBrain.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using UnityEngine; + +namespace CombatExtended +{ + public class CompProperties_SquadBrain : CompProperties + { + public CompProperties_SquadBrain() + { + compClass = typeof(CompSquadBrain); + } + } +} diff --git a/Source/CombatRealism/CombatExtended/Comps/CompProperties_Suppressable.cs b/Source/CombatExtended/CombatExtended/Comps/CompProperties_Suppressable.cs similarity index 100% rename from Source/CombatRealism/CombatExtended/Comps/CompProperties_Suppressable.cs rename to Source/CombatExtended/CombatExtended/Comps/CompProperties_Suppressable.cs diff --git a/Source/CombatExtended/CombatExtended/Comps/CompSquadBrain.cs b/Source/CombatExtended/CombatExtended/Comps/CompSquadBrain.cs new file mode 100644 index 0000000000..a4155b6004 --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Comps/CompSquadBrain.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using UnityEngine; +using CombatExtended.AI; + +namespace CombatExtended +{ + public class CompSquadBrain : ThingComp + { + public SquadBrain squad; + + CompProperties_SquadBrain Props => props as CompProperties_SquadBrain; + } +} diff --git a/Source/CombatExtended/CombatExtended/Comps/CompSuppressable.cs b/Source/CombatExtended/CombatExtended/Comps/CompSuppressable.cs new file mode 100644 index 0000000000..1e4904cbaf --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Comps/CompSuppressable.cs @@ -0,0 +1,258 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using Verse.AI; +using UnityEngine; + +namespace CombatExtended +{ + public class CompSuppressable : ThingComp + { + #region Constants + + private const float minSuppressionDist = 5f; //Minimum distance to be suppressed from, so melee won't be suppressed if it closes within this distance + private const float maxSuppression = 1050f; //Cap to prevent suppression from building indefinitely + private const int TicksForDecayStart = 120; // How long since last suppression before decay starts + private const float suppressionDecayRate = 5f; // How much suppression decays per tick + private const int ticksPerMote = 150; //How many ticks between throwing a mote + + #endregion + + #region Fields + + // --------------- Location calculations --------------- + + /* + * We track the initial location from which a pawn was suppressed and the total amount of suppression coming from that location separately. + * That way if suppression stops coming from location A but keeps coming from location B the location will get updated without bouncing + * pawns or having to track fire coming from multiple locations + */ + private IntVec3 suppressorLoc; + private float locSuppressionAmount = 0f; + + private float currentSuppression = 0f; + public bool isSuppressed = false; + + private int ticksUntilDecay = 0; + + #endregion + + #region Properties + + public CompProperties_Suppressable Props => (CompProperties_Suppressable)props; + public IntVec3 SuppressorLoc => suppressorLoc; + + public float CurrentSuppression => currentSuppression; + public float ParentArmor + { + get + { + float armorValue = 0f; + Pawn pawn = parent as Pawn; + if (pawn != null) + { + //Get most protective piece of armor + if (pawn.apparel.WornApparel != null && pawn.apparel.WornApparel.Count > 0) + { + List wornApparel = new List(pawn.apparel.WornApparel); + foreach (Apparel apparel in wornApparel) + { + float apparelArmor = apparel.GetStatValue(StatDefOf.ArmorRating_Sharp, true); + if (apparelArmor > armorValue) + { + armorValue = apparelArmor; + } + } + } + } + else + { + Log.Error("Tried to get parent armor of non-pawn"); + } + return armorValue; + } + } + private float SuppressionThreshold + { + get + { + float threshold = 0f; + Pawn pawn = parent as Pawn; + if (pawn != null) + { + //Get morale + float hardBreakThreshold = pawn.mindState?.mentalBreaker?.BreakThresholdMajor ?? 0; + float currentMood = pawn.needs?.mood?.CurLevel ?? 0.5f; + threshold = Mathf.Sqrt(Mathf.Max(0, currentMood - hardBreakThreshold)) * maxSuppression * 0.125f; + } + else + { + Log.Error("CE tried to get suppression threshold of non-pawn"); + } + return threshold; + } + } + + public bool IsHunkering + { + get + { + if (currentSuppression > (SuppressionThreshold * 10)) + { + if (isSuppressed) + { + return true; + } + // Removing suppression log + else + { + Log.Error("CE hunkering without suppression, this should never happen"); + } + } + return false; + } + } + public bool CanReactToSuppression + { + get + { + Pawn pawn = parent as Pawn; + return !pawn.Position.InHorDistOf(SuppressorLoc, minSuppressionDist) + && !pawn.Downed + && !pawn.InMentalState; + } + } + + #endregion + + #region Methods + + public override void PostExposeData() + { + base.PostExposeData(); + Scribe_Values.Look(ref currentSuppression, "currentSuppression", 0f); + Scribe_Values.Look(ref suppressorLoc, "suppressorLoc"); + Scribe_Values.Look(ref locSuppressionAmount, "locSuppression", 0f); + Scribe_Values.Look(ref isSuppressed, "isSuppressed", false); + Scribe_Values.Look(ref ticksUntilDecay, "ticksUntilDecay", 0); + } + + public void AddSuppression(float amount, IntVec3 origin) + { + Pawn pawn = parent as Pawn; + if (pawn == null) + { + Log.Error("CE trying to suppress non-pawn " + parent.ToString() + ", this should never happen"); + return; + } + + // No suppression on berserking or fleeing pawns + if (!CanReactToSuppression) + { + currentSuppression = 0f; + isSuppressed = false; + return; + } + + // Add suppression to global suppression counter + var suppressAmount = amount * pawn.GetStatValue(CE_StatDefOf.Suppressability); + currentSuppression += suppressAmount; + if (Controller.settings.DebugShowSuppressionBuildup) + { + MoteMaker.ThrowText(pawn.DrawPos, pawn.Map, suppressAmount.ToString()); + } + ticksUntilDecay = TicksForDecayStart; + if (currentSuppression > maxSuppression) + { + currentSuppression = maxSuppression; + } + + // Add suppression to current suppressor location if appropriate + if (suppressorLoc == origin) + { + locSuppressionAmount += amount; + } + else if (locSuppressionAmount < SuppressionThreshold) + { + suppressorLoc = origin; + locSuppressionAmount = currentSuppression; + } + + // Assign suppressed status and assign reaction job + if (currentSuppression > SuppressionThreshold) + { + isSuppressed = true; + Job reactJob = SuppressionUtility.GetRunForCoverJob(pawn); + if (reactJob == null && IsHunkering) + { + reactJob = new Job(CE_JobDefOf.HunkerDown, pawn); + LessonAutoActivator.TeachOpportunity(CE_ConceptDefOf.CE_Hunkering, pawn, OpportunityType.Critical); + } + if (reactJob != null && reactJob.def != pawn.CurJob?.def) + { + pawn.jobs.StartJob(reactJob, JobCondition.InterruptForced, null, pawn.jobs.curJob?.def==JobDefOf.ManTurret); + LessonAutoActivator.TeachOpportunity(CE_ConceptDefOf.CE_SuppressionReaction, pawn, OpportunityType.Critical); + } + } + } + + public override void CompTick() + { + base.CompTick(); + + //Apply decay once per second + if(ticksUntilDecay > 0) + { + ticksUntilDecay--; + } + else if (currentSuppression > 0) + { + //Decay global suppression + if (Controller.settings.DebugShowSuppressionBuildup && Gen.IsHashIntervalTick(parent, 30)) + { + MoteMaker.ThrowText(parent.DrawPos, parent.Map, "-" + (suppressionDecayRate * 30).ToString(), Color.red); + } + currentSuppression -= Mathf.Min(suppressionDecayRate, currentSuppression); + isSuppressed = currentSuppression > 0; + + //Decay location suppression + locSuppressionAmount -= Mathf.Min(suppressionDecayRate, locSuppressionAmount); + } + + //Throw mote at set interval + if (Gen.IsHashIntervalTick(this.parent, ticksPerMote) && CanReactToSuppression) + { + if (IsHunkering) + { + MoteMaker.ThrowMetaIcon(parent.Position, parent.Map, CE_ThingDefOf.Mote_HunkerIcon); + } + else if (this.isSuppressed) + { + //MoteMaker.ThrowText(this.parent.Position.ToVector3Shifted(), parent.Map, "CE_SuppressedMote".Translate()); + MoteMaker.ThrowMetaIcon(parent.Position, parent.Map, CE_ThingDefOf.Mote_SuppressIcon); + } + } + + /*if (Gen.IsHashIntervalTick(parent, ticksPerMote + Rand.Range(30, 300)) + && parent.def.race.Humanlike && !robotBodyList.Contains(parent.def.race.body.defName)) + { + if (isHunkering || isSuppressed) + { + AGAIN: string rndswearsuppressed = RulePackDef.Named("SuppressedMote").Rules.RandomElement().Generate(); + + if (rndswearsuppressed == "[suppressed]" || rndswearsuppressed == "" || rndswearsuppressed == " ") + { + goto AGAIN; + } + MoteMaker.ThrowText(this.parent.Position.ToVector3Shifted(), Find.VisibleMap, rndswearsuppressed); + } + //standard MoteMaker.ThrowText(parent.Position.ToVector3Shifted(), "CE_SuppressedMote".Translate()); + }*/ + } + + #endregion + } +} \ No newline at end of file diff --git a/Source/CombatExtended/CombatExtended/Comps/HediffCompProperties_InfecterCE.cs b/Source/CombatExtended/CombatExtended/Comps/HediffCompProperties_InfecterCE.cs new file mode 100644 index 0000000000..4a19d32ee2 --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Comps/HediffCompProperties_InfecterCE.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using UnityEngine; + +namespace CombatExtended +{ + public class HediffCompProperties_InfecterCE : HediffCompProperties + { + public float infectionChancePerHourUntended = 0.01f; + + public HediffCompProperties_InfecterCE() + { + this.compClass = typeof(HediffComp_InfecterCE); + } + } +} diff --git a/Source/CombatExtended/CombatExtended/Comps/HediffCompProperties_Stabilize.cs b/Source/CombatExtended/CombatExtended/Comps/HediffCompProperties_Stabilize.cs new file mode 100644 index 0000000000..630ec7b0d3 --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Comps/HediffCompProperties_Stabilize.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using UnityEngine; + +namespace CombatExtended +{ + public class HediffCompProperties_Stabilize : HediffCompProperties + { + public HediffCompProperties_Stabilize() + { + compClass = typeof(HediffComp_Stabilize); + } + } +} diff --git a/Source/CombatExtended/CombatExtended/Comps/HediffComp_InfecterCE.cs b/Source/CombatExtended/CombatExtended/Comps/HediffComp_InfecterCE.cs new file mode 100644 index 0000000000..79a80d7e0c --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Comps/HediffComp_InfecterCE.cs @@ -0,0 +1,94 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using UnityEngine; + +namespace CombatExtended +{ + public class HediffComp_InfecterCE : HediffComp + { + private const float infectionInnerModifier = 3f; // Injuries to inner body parts will be this much more likely to get infected + private static readonly IntRange InfectionDelayHours = new IntRange(6, 12); // Infections will appear somewhere within this timeframe + + private bool alreadyCausedInfection = false; + private int ticksUntilInfect = -1; + private float infectionModifier = 1; + + public HediffCompProperties_InfecterCE Props { get { return (HediffCompProperties_InfecterCE)props; } } + + private void CheckMakeInfection() + { + ticksUntilInfect = -1; + infectionModifier *= Pawn.health.immunity.DiseaseContractChanceFactor(HediffDefOf.WoundInfection, parent.Part); // Apply pawn immunity + if (Pawn.def.race.Animal) infectionModifier *= 0.5f; + + // Adjust for difficulty + if (Pawn.Faction == Faction.OfPlayer) infectionModifier *= Find.Storyteller.difficulty.playerPawnInfectionChanceFactor; + + // Find out how long the wound was untreated + HediffComp_TendDuration compTended = parent.TryGetComp(); + int ticksUntended = parent.ageTicks; + if (compTended != null && compTended.IsTended) + { + int ticksTended = Find.TickManager.TicksGame - compTended.tendTick; + ticksUntended -= ticksTended; + + infectionModifier /= Mathf.Pow(compTended.tendQuality + 0.75f, 2); // Adjust infection chance based on tend quality + } + float infectChance = Props.infectionChancePerHourUntended * (ticksUntended / GenDate.TicksPerHour); // Calculate base chance from time untreated + if (parent.Part.depth == BodyPartDepth.Inside) infectChance *= infectionInnerModifier; // Increase chance of infection for inner organs + if (Rand.Value < infectChance * infectionModifier) + { + alreadyCausedInfection = true; + Pawn.health.AddHediff(HediffDefOf.WoundInfection, parent.Part); + } + } + + public override string CompDebugString() + { + if (this.alreadyCausedInfection) return "already caused infection"; + if (this.ticksUntilInfect <= 0) return "no infection will appear"; + return "infection may appear after: " + ticksUntilInfect + " ticks (infection chance factor: " + infectionModifier.ToString() + ")"; + } + + public override void CompExposeData() + { + Scribe_Values.Look(ref alreadyCausedInfection, "alreadyCausedInfection", false); + Scribe_Values.Look(ref ticksUntilInfect, "ticksUntilInfect", -1); + Scribe_Values.Look(ref infectionModifier, "infectionModifier", 1); + } + + public override void CompPostPostAdd(DamageInfo? dinfo) + { + // Determine time until infection check is made + if (!alreadyCausedInfection + && !parent.Part.def.IsSolid(parent.Part, Pawn.health.hediffSet.hediffs) + && !Pawn.health.hediffSet.PartOrAnyAncestorHasDirectlyAddedParts(parent.Part) + && !parent.IsOld()) + { + ticksUntilInfect = InfectionDelayHours.RandomInRange * GenDate.TicksPerHour; + } + } + + public override void CompPostTick(ref float severityAdjustment) + { + if (!alreadyCausedInfection && ticksUntilInfect > 0) + { + ticksUntilInfect--; + if (ticksUntilInfect == 0) CheckMakeInfection(); + } + } + + public override void CompTended(float quality, int batchPosition = 0) + { + if (Pawn.Spawned) + { + Room room = Pawn.GetRoom(); + infectionModifier *= room == null ? 1.5f : room.GetStat(RoomStatDefOf.InfectionChanceFactor); + } + } + } +} diff --git a/Source/CombatExtended/CombatExtended/Comps/HediffComp_Stabilize.cs b/Source/CombatExtended/CombatExtended/Comps/HediffComp_Stabilize.cs new file mode 100644 index 0000000000..1cc911c65d --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Comps/HediffComp_Stabilize.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using UnityEngine; + +namespace CombatExtended +{ + [StaticConstructorOnStartup] + public class HediffComp_Stabilize : HediffComp + { + private const float bleedIncreasePerSec = 0.01f; // After stabilizing, bleed modifier is increased by this much + private const float internalBleedOffset = 0.2f; + + private static readonly Texture2D StabilizedIcon = ContentFinder.Get("UI/Icons/Medical/Stabilized_Icon"); + + private bool stabilized = false; + private float bleedModifier = 1; + + public HediffCompProperties_Stabilize Props { get { return props as HediffCompProperties_Stabilize; } } + public bool Stabilized { get { return stabilized; } } + public float BleedModifier + { + get + { + float mod = bleedModifier; + if (parent is Hediff_MissingPart) mod *= 0.5f; + if (parent.Part.depth == BodyPartDepth.Inside) mod += internalBleedOffset; + return Mathf.Clamp01(mod); + } + } + + public void Stabilize(Pawn medic, Medicine medicine) + { + if (stabilized) + { + Log.Error("CE tried to stabilize an injury that is already stabilized before"); + return; + } + if (medicine == null) + { + Log.Error("CE tried to stabilize without medicine"); + return; + } + float bleedReduction = 2f * medic.GetStatValue(StatDefOf.MedicalTendQuality) * medicine.GetStatValue(StatDefOf.MedicalPotency); + bleedModifier = 1 - bleedReduction; // Especially high treatment quality extends time at 0% bleed by setting bleedModifier to a negative number + stabilized = true; + } + + public override void CompExposeData() + { + Scribe_Values.Look(ref stabilized, "stabilized", false); + Scribe_Values.Look(ref bleedModifier, "bleedModifier", 1); + } + + public override void CompPostTick(ref float severityAdjustment) + { + // Increase bleed modifier once per second + if (stabilized && bleedModifier < 1 && parent.ageTicks % 60 == 0) + { + bleedModifier = bleedModifier + bleedIncreasePerSec; + if (bleedModifier >= 1) + { + bleedModifier = 1; + //stabilized = false; + } + } + else if (!stabilized && parent.pawn.Downed) + { + // Teach about stabilizing + LessonAutoActivator.TeachOpportunity(CE_ConceptDefOf.CE_Stabilizing, parent.pawn, OpportunityType.Important); + } + } + + public override TextureAndColor CompStateIcon + { + get + { + if (bleedModifier < 1 && !parent.IsOld() && !parent.IsTended()) return new TextureAndColor(StabilizedIcon, Color.white); + return TextureAndColor.None; + } + } + + public override string CompDebugString() + { + if (parent.BleedRate < 0) return "Not bleeding"; + if (!stabilized) return "Not stabilized"; + return String.Concat("Stabilized", parent.Part.depth == BodyPartDepth.Inside ? " internal bleeding" : "", "\nbleed rate modifier: ", bleedModifier.ToString()); + } + } +} diff --git a/Source/CombatRealism/CombatExtended/Comps_CCL/CompMilkableRenameable.cs b/Source/CombatExtended/CombatExtended/Comps_CCL/CompMilkableRenameable.cs similarity index 100% rename from Source/CombatRealism/CombatExtended/Comps_CCL/CompMilkableRenameable.cs rename to Source/CombatExtended/CombatExtended/Comps_CCL/CompMilkableRenameable.cs diff --git a/Source/CombatRealism/CombatExtended/Comps_CCL/CompPawnGizmo.cs b/Source/CombatExtended/CombatExtended/Comps_CCL/CompPawnGizmo.cs similarity index 100% rename from Source/CombatRealism/CombatExtended/Comps_CCL/CompPawnGizmo.cs rename to Source/CombatExtended/CombatExtended/Comps_CCL/CompPawnGizmo.cs diff --git a/Source/CombatRealism/CombatExtended/Comps_CCL/CompProperties_MilkableRenameable.cs b/Source/CombatExtended/CombatExtended/Comps_CCL/CompProperties_MilkableRenameable.cs similarity index 100% rename from Source/CombatRealism/CombatExtended/Comps_CCL/CompProperties_MilkableRenameable.cs rename to Source/CombatExtended/CombatExtended/Comps_CCL/CompProperties_MilkableRenameable.cs diff --git a/Source/CombatRealism/CombatExtended/Comps_CCL/CompProperties_ShearableRenameable.cs b/Source/CombatExtended/CombatExtended/Comps_CCL/CompProperties_ShearableRenameable.cs similarity index 100% rename from Source/CombatRealism/CombatExtended/Comps_CCL/CompProperties_ShearableRenameable.cs rename to Source/CombatExtended/CombatExtended/Comps_CCL/CompProperties_ShearableRenameable.cs diff --git a/Source/CombatRealism/CombatExtended/Comps_CCL/CompRangedGizmoGiver.cs b/Source/CombatExtended/CombatExtended/Comps_CCL/CompRangedGizmoGiver.cs similarity index 100% rename from Source/CombatRealism/CombatExtended/Comps_CCL/CompRangedGizmoGiver.cs rename to Source/CombatExtended/CombatExtended/Comps_CCL/CompRangedGizmoGiver.cs diff --git a/Source/CombatExtended/CombatExtended/Comps_CCL/CompShearableRenameable.cs b/Source/CombatExtended/CombatExtended/Comps_CCL/CompShearableRenameable.cs new file mode 100644 index 0000000000..d462305a81 --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Comps_CCL/CompShearableRenameable.cs @@ -0,0 +1,39 @@ +using RimWorld; +using Verse; + +namespace CombatExtended +{ + + public class CompShearableRenameable : CompShearable + { + + private string growthLabel = "WoolGrowth".Translate(); + + private CompProperties_ShearableRenameable properties + { + get + { + return props as CompProperties_ShearableRenameable; + } + } + + public override void Initialize(CompProperties props) + { + base.Initialize(props); + if (properties != null && !properties.growthLabel.NullOrEmpty()) growthLabel = properties.growthLabel; + } + + public override string CompInspectStringExtra() + { + if (!Active) + { + return (string)null; + } + // Show we learned about explosives + if (properties.woolDef == CE_ThingDefOf.FSX) PlayerKnowledgeDatabase.KnowledgeDemonstrated(CE_ConceptDefOf.CE_ObtainingFSX, KnowledgeAmount.FrameDisplayed); + return growthLabel + ": " + Fullness.ToStringPercent(); + } + + } + +} diff --git a/Source/CombatRealism/CombatExtended/Comps_CCL/Def_Extensions.cs b/Source/CombatExtended/CombatExtended/Comps_CCL/Def_Extensions.cs similarity index 100% rename from Source/CombatRealism/CombatExtended/Comps_CCL/Def_Extensions.cs rename to Source/CombatExtended/CombatExtended/Comps_CCL/Def_Extensions.cs diff --git a/Source/CombatExtended/CombatExtended/Controller.cs b/Source/CombatExtended/CombatExtended/Controller.cs new file mode 100644 index 0000000000..a3772887e4 --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Controller.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using UnityEngine; +using CombatExtended.Harmony; + +namespace CombatExtended +{ + public class Controller : Mod + { + public static Settings settings; + + public Controller(ModContentPack content) : base(content) + { + settings = GetSettings(); + + // Apply Harmony patches + HarmonyBase.InitPatches(); + + // Inject ammo + LongEventHandler.QueueLongEvent(AmmoInjector.Inject, "LibraryStartup", false, null); + + Log.Message("Combat Extended :: initialized"); + } + + public override string SettingsCategory() + { + return "Combat Extended"; + } + + public override void DoSettingsWindowContents(Rect inRect) + { + settings.DoWindowContents(inRect); + } + } +} diff --git a/Source/CombatExtended/CombatExtended/CritDefGenerator.cs b/Source/CombatExtended/CombatExtended/CritDefGenerator.cs new file mode 100644 index 0000000000..839cd704c9 --- /dev/null +++ b/Source/CombatExtended/CombatExtended/CritDefGenerator.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using UnityEngine; + +namespace CombatExtended +{ + public static class CritDefGenerator + { + public static IEnumerable ImpliedCritDefs() + { + foreach(DamageDef current in from def in DefDatabase.AllDefs where def.externalViolence select def) + { + var critDef = new DamageDef() { + defName = current.defName + "_Critical", + workerClass = current.workerClass, + externalViolence = true, + impactSoundType = current.impactSoundType, + spreadOut = current.spreadOut, + harmAllLayersUntilOutside = current.harmAllLayersUntilOutside, + hasChanceToAdditionallyDamageInnerSolidParts = current.hasChanceToAdditionallyDamageInnerSolidParts, + hediff = current.hediff, + hediffSkin = current.hediffSkin, + hediffSolid = current.hediffSolid + }; + yield return critDef; + } + } + } +} diff --git a/Source/CombatExtended/CombatExtended/DamageWorkers/DamageWorker_AddInjuryCE.cs b/Source/CombatExtended/CombatExtended/DamageWorkers/DamageWorker_AddInjuryCE.cs new file mode 100644 index 0000000000..701bb9b359 --- /dev/null +++ b/Source/CombatExtended/CombatExtended/DamageWorkers/DamageWorker_AddInjuryCE.cs @@ -0,0 +1,407 @@ +using RimWorld; +using System; +using System.Collections.Generic; +using System.Linq; +using Verse; +using UnityEngine; + +namespace CombatExtended +{ + public class DamageWorker_AddInjuryCE : DamageWorker + { + private struct LocalInjuryResult + { + public bool wounded; + + public bool headshot; + + public bool deflected; + + public BodyPartRecord lastHitPart; + + public float totalDamageDealt; + + public static DamageWorker_AddInjuryCE.LocalInjuryResult MakeNew() + { + return new DamageWorker_AddInjuryCE.LocalInjuryResult + { + wounded = false, + headshot = false, + deflected = false, + lastHitPart = null, + totalDamageDealt = 0f + }; + } + } + + private const float SpreadDamageChance = 0.5f; + + public override float Apply(DamageInfo dinfo, Thing thing) + { + Pawn pawn = thing as Pawn; + if (pawn == null) + { + return base.Apply(dinfo, thing); + } + return this.ApplyToPawn(dinfo, pawn); + } + + private float ApplyToPawn(DamageInfo dinfo, Pawn pawn) + { + if (dinfo.Amount <= 0) + { + return 0f; + } + if (!DebugSettings.enablePlayerDamage && pawn.Faction == Faction.OfPlayer) + { + return 0f; + } + LocalInjuryResult localInjuryResult = LocalInjuryResult.MakeNew(); + Map mapHeld = pawn.MapHeld; + bool spawnedOrAnyParentSpawned = pawn.SpawnedOrAnyParentSpawned; + if (dinfo.Def.spreadOut) + { + if (pawn.apparel != null) + { + List wornApparel = pawn.apparel.WornApparel; + for (int i = wornApparel.Count - 1; i >= 0; i--) + { + this.CheckApplySpreadDamage(dinfo, wornApparel[i]); + } + } + if (pawn.equipment != null && pawn.equipment.Primary != null) + { + this.CheckApplySpreadDamage(dinfo, pawn.equipment.Primary); + } + if (pawn.inventory != null) + { + ThingOwner innerContainer = pawn.inventory.innerContainer; + for (int j = innerContainer.Count - 1; j >= 0; j--) + { + this.CheckApplySpreadDamage(dinfo, innerContainer[j]); + } + } + } + if (this.ShouldFragmentDamageForDamageType(dinfo)) + { + int num = Rand.RangeInclusive(3, 4); + for (int k = 0; k < num; k++) + { + DamageInfo dinfo2 = dinfo; + dinfo2.SetAmount(dinfo.Amount / num); + this.ApplyDamageToPart(dinfo2, pawn, ref localInjuryResult); + } + } + else + { + this.ApplyDamageToPart(dinfo, pawn, ref localInjuryResult); + this.CheckDuplicateSmallPawnDamageToPartParent(dinfo, pawn, ref localInjuryResult); + } + if (localInjuryResult.wounded) + { + PlayWoundedVoiceSound(dinfo, pawn); + pawn.Drawer.Notify_DamageApplied(dinfo); + InformPsychology(dinfo, pawn); + } + if (localInjuryResult.headshot && pawn.Spawned) + { + MoteMaker.ThrowText(new Vector3((float)pawn.Position.x + 1f, (float)pawn.Position.y, (float)pawn.Position.z + 1f), pawn.Map, "Headshot".Translate(), Color.white, -1f); + if (dinfo.Instigator != null) + { + Pawn pawn2 = dinfo.Instigator as Pawn; + if (pawn2 != null) + { + pawn2.records.Increment(RecordDefOf.Headshots); + } + } + } + if (localInjuryResult.deflected) + { + if (pawn.health.deflectionEffecter == null) + { + pawn.health.deflectionEffecter = EffecterDefOf.ArmorDeflect.Spawn(); + } + pawn.health.deflectionEffecter.Trigger(pawn, pawn); + } + else if (spawnedOrAnyParentSpawned) + { + ImpactSoundUtility.PlayImpactSound(pawn, dinfo.Def.impactSoundType, mapHeld); + } + return localInjuryResult.totalDamageDealt; + } + + private void CheckApplySpreadDamage(DamageInfo dinfo, Thing t) + { + if (dinfo.Def == DamageDefOf.Flame && !t.FlammableNow) + { + return; + } + if (UnityEngine.Random.value < 0.5f) + { + dinfo.SetAmount(Mathf.CeilToInt((float)dinfo.Amount * Rand.Range(0.35f, 0.7f))); + t.TakeDamage(dinfo); + } + } + + private bool ShouldFragmentDamageForDamageType(DamageInfo dinfo) + { + return dinfo.AllowDamagePropagation && dinfo.Amount >= 9 && dinfo.Def.spreadOut; + } + + private void CheckDuplicateSmallPawnDamageToPartParent(DamageInfo dinfo, Pawn pawn, ref DamageWorker_AddInjuryCE.LocalInjuryResult result) + { + if (!dinfo.AllowDamagePropagation) + { + return; + } + if (result.lastHitPart != null && dinfo.Def.harmsHealth && result.lastHitPart != pawn.RaceProps.body.corePart && result.lastHitPart.parent != null && pawn.health.hediffSet.GetPartHealth(result.lastHitPart.parent) > 0f && dinfo.Amount >= 10 && pawn.HealthScale <= 0.5001f) + { + DamageInfo dinfo2 = dinfo; + dinfo2.SetForcedHitPart(result.lastHitPart.parent); + this.ApplyDamageToPart(dinfo2, pawn, ref result); + } + } + + private void ApplyDamageToPart(DamageInfo dinfo, Pawn pawn, ref DamageWorker_AddInjuryCE.LocalInjuryResult result) + { + BodyPartRecord exactPartFromDamageInfo = DamageWorker_AddInjuryCE.GetExactPartFromDamageInfo(dinfo, pawn); + if (exactPartFromDamageInfo == null) + { + return; + } + bool involveArmor = !dinfo.InstantOldInjury; + DamageInfo postArmorDinfo = dinfo; + bool shieldAbsorbed = false; + if (involveArmor) + { + postArmorDinfo = ArmorUtilityCE.GetAfterArmorDamage(dinfo, pawn, exactPartFromDamageInfo, out shieldAbsorbed); + if (dinfo.ForceHitPart == null + && postArmorDinfo.ForceHitPart != null + && exactPartFromDamageInfo != postArmorDinfo.ForceHitPart) + { + exactPartFromDamageInfo = postArmorDinfo.ForceHitPart; // If the shot was deflected, update our body part + if (pawn.Spawned) LessonAutoActivator.TeachOpportunity(CE_ConceptDefOf.CE_ArmorSystem, OpportunityType.Critical); // Inform the player about armor deflection + } + } + + // Vanilla code - apply hediff + if ((double)postArmorDinfo.Amount < 0.001) + { + result.deflected = true; + return; + } + HediffDef hediffDefFromDamage = HealthUtility.GetHediffDefFromDamage(postArmorDinfo.Def, pawn, exactPartFromDamageInfo); + Hediff_Injury hediff_Injury = (Hediff_Injury)HediffMaker.MakeHediff(hediffDefFromDamage, pawn, null); + hediff_Injury.Part = exactPartFromDamageInfo; + hediff_Injury.source = postArmorDinfo.WeaponGear; + hediff_Injury.sourceBodyPartGroup = postArmorDinfo.WeaponBodyPartGroup; + hediff_Injury.sourceHediffDef = postArmorDinfo.WeaponLinkedHediff; + hediff_Injury.Severity = (float)postArmorDinfo.Amount; + if (postArmorDinfo.InstantOldInjury) + { + HediffComp_GetsOld hediffComp_GetsOld = hediff_Injury.TryGetComp(); + if (hediffComp_GetsOld != null) + { + hediffComp_GetsOld.IsOld = true; + } + else + { + Log.Error(string.Concat(new object[] + { + "Tried to create instant old injury on Hediff without a GetsOld comp: ", + hediffDefFromDamage, + " on ", + pawn + })); + } + } + result.wounded = true; + result.lastHitPart = hediff_Injury.Part; + if (DamageWorker_AddInjuryCE.IsHeadshot(postArmorDinfo, hediff_Injury, pawn)) + { + result.headshot = true; + } + if (postArmorDinfo.InstantOldInjury && (hediff_Injury.def.CompPropsFor(typeof(HediffComp_GetsOld)) == null || hediff_Injury.Part.def.oldInjuryBaseChance == 0f || hediff_Injury.Part.def.IsSolid(hediff_Injury.Part, pawn.health.hediffSet.hediffs) || pawn.health.hediffSet.PartOrAnyAncestorHasDirectlyAddedParts(hediff_Injury.Part))) + { + return; + } + this.FinalizeAndAddInjury(pawn, hediff_Injury, postArmorDinfo, ref result); + this.CheckPropagateDamageToInnerSolidParts(postArmorDinfo, pawn, hediff_Injury, involveArmor, ref result); + this.CheckDuplicateDamageToOuterParts(postArmorDinfo, pawn, hediff_Injury, involveArmor, ref result); + + // Apply secondary damage + if (!shieldAbsorbed) + { + var props = dinfo.WeaponGear?.projectile as ProjectilePropertiesCE; + if (props != null && !props.secondaryDamage.NullOrEmpty() && dinfo.Def == props.damageDef) + { + foreach (SecondaryDamage sec in props.secondaryDamage) + { + if (pawn.Dead) return; + var secDinfo = sec.GetDinfo(postArmorDinfo); + secDinfo.SetForcedHitPart(exactPartFromDamageInfo); + pawn.TakeDamage(secDinfo); + } + } + } + } + + private void FinalizeAndAddInjury(Pawn pawn, Hediff_Injury injury, DamageInfo dinfo, ref DamageWorker_AddInjuryCE.LocalInjuryResult result) + { + this.CalculateOldInjuryDamageThreshold(pawn, injury); + result.totalDamageDealt += Mathf.Min(injury.Severity, pawn.health.hediffSet.GetPartHealth(injury.Part)); + pawn.health.AddHediff(injury, null, new DamageInfo?(dinfo)); + } + + private void CalculateOldInjuryDamageThreshold(Pawn pawn, Hediff_Injury injury) + { + HediffComp_GetsOld comp = injury.TryGetComp(); + if (comp == null) + { + return; + } + // No permanent injuries on solid parts, prosthetics or injuries that are already old + if (injury.Part.def.IsSolid(injury.Part, pawn.health.hediffSet.hediffs) || pawn.health.hediffSet.PartOrAnyAncestorHasDirectlyAddedParts(injury.Part) || injury.IsOld()) return; + + // Delicate parts get old instantly + if (injury.Part.def.IsDelicate) + { + comp.oldDamageThreshold = injury.Severity; + comp.IsOld = true; + } + // Check if injury is at least 10% of part health and make a random roll + else if (injury.Severity >= injury.Part.def.GetMaxHealth(pawn) * 0.1f && injury.Severity > 1) + { + float getOldChance = injury.Part.def.oldInjuryBaseChance * comp.Props.becomeOldChance * Mathf.Pow((injury.Severity / injury.Part.def.GetMaxHealth(pawn)), 2); + if (Rand.Value < getOldChance) comp.oldDamageThreshold = Rand.Range(1, injury.Severity); + } + } + + private void CheckPropagateDamageToInnerSolidParts(DamageInfo dinfo, Pawn pawn, Hediff_Injury injury, bool involveArmor, ref DamageWorker_AddInjuryCE.LocalInjuryResult result) + { + if (!dinfo.AllowDamagePropagation) + { + return; + } + if (Rand.Value >= HealthTunings.ChanceToAdditionallyDamageInnerSolidPart) + { + return; + } + if (dinfo.Def.hasChanceToAdditionallyDamageInnerSolidParts && !injury.Part.def.IsSolid(injury.Part, pawn.health.hediffSet.hediffs) && injury.Part.depth == BodyPartDepth.Outside) + { + IEnumerable source = from x in pawn.health.hediffSet.GetNotMissingParts(BodyPartHeight.Undefined, BodyPartDepth.Undefined) + where x.parent == injury.Part && x.def.IsSolid(x, pawn.health.hediffSet.hediffs) && x.depth == BodyPartDepth.Inside + select x; + BodyPartRecord part; + if (source.TryRandomElementByWeight((BodyPartRecord x) => x.coverageAbs, out part)) + { + HediffDef hediffDefFromDamage = HealthUtility.GetHediffDefFromDamage(dinfo.Def, pawn, part); + Hediff_Injury hediff_Injury = (Hediff_Injury)HediffMaker.MakeHediff(hediffDefFromDamage, pawn, null); + hediff_Injury.Part = part; + hediff_Injury.source = injury.source; + hediff_Injury.sourceBodyPartGroup = injury.sourceBodyPartGroup; + hediff_Injury.Severity = (float)(dinfo.Amount / 2); + /* + if (involveArmor) + { + hediff_Injury.Severity = (float)ArmorUtility.GetAfterArmorDamage(pawn, dinfo.Amount / 2, part, dinfo.Def); + } + */ + if (hediff_Injury.Severity <= 0f) + { + return; + } + result.lastHitPart = hediff_Injury.Part; + this.FinalizeAndAddInjury(pawn, hediff_Injury, dinfo, ref result); + } + } + } + + private void CheckDuplicateDamageToOuterParts(DamageInfo dinfo, Pawn pawn, Hediff_Injury injury, bool involveArmor, ref DamageWorker_AddInjuryCE.LocalInjuryResult result) + { + if (!dinfo.AllowDamagePropagation) + { + return; + } + if (dinfo.Def.harmAllLayersUntilOutside && injury.Part.depth == BodyPartDepth.Inside) + { + BodyPartRecord parent = injury.Part.parent; + do + { + if (pawn.health.hediffSet.GetPartHealth(parent) != 0f) + { + HediffDef hediffDefFromDamage = HealthUtility.GetHediffDefFromDamage(dinfo.Def, pawn, parent); + Hediff_Injury hediff_Injury = (Hediff_Injury)HediffMaker.MakeHediff(hediffDefFromDamage, pawn, null); + hediff_Injury.Part = parent; + hediff_Injury.source = injury.source; + hediff_Injury.sourceBodyPartGroup = injury.sourceBodyPartGroup; + hediff_Injury.Severity = (float)dinfo.Amount; + /* + if (involveArmor) + { + //hediff_Injury.Severity = (float)ArmorUtility.GetAfterArmorDamage(pawn, dinfo.Amount, parent, dinfo.Def); + } + */ + if (hediff_Injury.Severity <= 0f) + { + hediff_Injury.Severity = 1f; + } + result.lastHitPart = hediff_Injury.Part; + this.FinalizeAndAddInjury(pawn, hediff_Injury, dinfo, ref result); + } + if (parent.depth == BodyPartDepth.Outside) + { + break; + } + parent = parent.parent; + } + while (parent != null); + } + } + + private static void InformPsychology(DamageInfo dinfo, Pawn pawn) + { + } + + private static bool IsHeadshot(DamageInfo dinfo, Hediff_Injury injury, Pawn pawn) + { + return !dinfo.InstantOldInjury && injury.Part.groups.Contains(BodyPartGroupDefOf.FullHead) && dinfo.Def == DamageDefOf.Bullet; + } + + internal static BodyPartRecord GetExactPartFromDamageInfo(DamageInfo dinfo, Pawn pawn) + { + if (dinfo.ForceHitPart != null) + { + return (from x in pawn.health.hediffSet.GetNotMissingParts(BodyPartHeight.Undefined, BodyPartDepth.Undefined) + where x == dinfo.ForceHitPart + select x).FirstOrDefault(); + } + BodyPartRecord randomNotMissingPart = pawn.health.hediffSet.GetRandomNotMissingPart(dinfo.Def, dinfo.Height, dinfo.Depth); + if (randomNotMissingPart == null) + { + Log.Warning("GetRandomNotMissingPart returned null (any part)."); + } + return randomNotMissingPart; + } + + private static void PlayWoundedVoiceSound(DamageInfo dinfo, Pawn pawn) + { + if (pawn.Dead) + { + return; + } + if (dinfo.InstantOldInjury) + { + return; + } + if (pawn.MapHeld == null) + { + return; + } + if (dinfo.Def.externalViolence) + { + LifeStageUtility.PlayNearestLifestageSound(pawn, (LifeStageAge ls) => ls.soundWounded, 1f); + } + } + } +} diff --git a/Source/CombatRealism/CombatExtended/DamageWorkers/DamageWorker_FlameCE.cs b/Source/CombatExtended/CombatExtended/DamageWorkers/DamageWorker_FlameCE.cs similarity index 56% rename from Source/CombatRealism/CombatExtended/DamageWorkers/DamageWorker_FlameCE.cs rename to Source/CombatExtended/CombatExtended/DamageWorkers/DamageWorker_FlameCE.cs index adbcdac284..256e79bb31 100644 --- a/Source/CombatRealism/CombatExtended/DamageWorkers/DamageWorker_FlameCE.cs +++ b/Source/CombatExtended/CombatExtended/DamageWorkers/DamageWorker_FlameCE.cs @@ -21,13 +21,28 @@ public override float Apply(DamageInfo dinfo, Thing victim) { Find.TickManager.slower.SignalForceNormalSpeedShort(); } - return base.Apply(dinfo, victim); + Map map = victim.Map; + float result = base.Apply(dinfo, victim); + if (victim.Destroyed && map != null && pawn == null) + { + foreach (IntVec3 current in victim.OccupiedRect()) + { + FilthMaker.MakeFilth(current, map, ThingDefOf.FilthAsh, 1); + } + Plant plant = victim as Plant; + if (plant != null && victim.def.plant.IsTree && plant.LifeStage != PlantLifeStage.Sowing && victim.def != ThingDefOf.BurnedTree) + { + DeadPlant deadPlant = (DeadPlant)GenSpawn.Spawn(ThingDefOf.BurnedTree, victim.Position, map); + deadPlant.Growth = plant.Growth; + } + } + return result; } public override void ExplosionAffectCell(Explosion explosion, IntVec3 c, List damagedThings, bool canThrowMotes) { base.ExplosionAffectCell(explosion, c, damagedThings, canThrowMotes); - if (def == DamageDefOf.Flame && c.IsValid && explosion.Map != null) + if (this.def == DamageDefOf.Flame && Rand.Chance(FireUtility.ChanceToStartFireIn(c, explosion.Map))) { FireUtility.TryStartFireIn(c, explosion.Map, Rand.Range(0.2f, 0.6f)); } diff --git a/Source/CombatRealism/CombatExtended/DefOfs/CE_ThingDefOf.cs b/Source/CombatExtended/CombatExtended/DefOfs/CE_BodyPartGroupDefOf.cs similarity index 58% rename from Source/CombatRealism/CombatExtended/DefOfs/CE_ThingDefOf.cs rename to Source/CombatExtended/CombatExtended/DefOfs/CE_BodyPartGroupDefOf.cs index 986065afa9..afb84754e5 100644 --- a/Source/CombatRealism/CombatExtended/DefOfs/CE_ThingDefOf.cs +++ b/Source/CombatExtended/CombatExtended/DefOfs/CE_BodyPartGroupDefOf.cs @@ -4,14 +4,13 @@ using System.Text; using RimWorld; using Verse; +using UnityEngine; namespace CombatExtended { [DefOf] - public static class CE_ThingDefOf + public class CE_BodyPartGroupDefOf { - public static ThingDef FilthPee; - - public static ThingDef Napalm_Fuel; + public static BodyPartGroupDef CoveredByNaturalArmor; } } diff --git a/Source/CombatRealism/CombatExtended/Defs/AmmoDef.cs b/Source/CombatExtended/CombatExtended/DefOfs/CE_BodyShapeDefOf.cs similarity index 52% rename from Source/CombatRealism/CombatExtended/Defs/AmmoDef.cs rename to Source/CombatExtended/CombatExtended/DefOfs/CE_BodyShapeDefOf.cs index e7a5235330..41d4d9330d 100644 --- a/Source/CombatRealism/CombatExtended/Defs/AmmoDef.cs +++ b/Source/CombatExtended/CombatExtended/DefOfs/CE_BodyShapeDefOf.cs @@ -8,10 +8,9 @@ namespace CombatExtended { - public class AmmoDef : ThingDef + [DefOf] + public class CE_BodyShapeDefOf { - public ThingDef linkedProjectile; - public AmmoCategoryDef ammoClass; - public int defaultAmmoCount = 1; + public static BodyShapeDef Invalid; } } diff --git a/Source/CombatExtended/CombatExtended/DefOfs/CE_ConceptDefOf.cs b/Source/CombatExtended/CombatExtended/DefOfs/CE_ConceptDefOf.cs new file mode 100644 index 0000000000..a32f93a2f7 --- /dev/null +++ b/Source/CombatExtended/CombatExtended/DefOfs/CE_ConceptDefOf.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using UnityEngine; + +namespace CombatExtended +{ + [DefOf] + public class CE_ConceptDefOf + { + // *** Modal dialog concepts *** + public static ConceptDef CE_AmmoSettings; + + // *** Self-activated concepts *** + public static ConceptDef CE_InventoryWeightBulk; + public static ConceptDef CE_Loadouts; + public static ConceptDef CE_ObtainingFSX; + public static ConceptDef CE_ObtainingPrometheum; + + // *** Opportunistic concepts *** + public static ConceptDef CE_AimingSystem; + public static ConceptDef CE_FireModes; + public static ConceptDef CE_AimModes; + public static ConceptDef CE_Spotting; + public static ConceptDef CE_MortarDirectFire; + public static ConceptDef CE_Stabilizing; + public static ConceptDef CE_ArmorSystem; + public static ConceptDef CE_SuppressionReaction; + public static ConceptDef CE_Hunkering; + public static ConceptDef CE_WornBulk; + } +} diff --git a/Source/CombatExtended/CombatExtended/DefOfs/CE_DamageArmorCategoryDefOf.cs b/Source/CombatExtended/CombatExtended/DefOfs/CE_DamageArmorCategoryDefOf.cs new file mode 100644 index 0000000000..e9c3534305 --- /dev/null +++ b/Source/CombatExtended/CombatExtended/DefOfs/CE_DamageArmorCategoryDefOf.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using UnityEngine; + +namespace CombatExtended +{ + [DefOf] + public class CE_DamageArmorCategoryDefOf + { + public static DamageArmorCategoryDef Blunt; + } +} diff --git a/Source/CombatExtended/CombatExtended/DefOfs/CE_JobDefOf.cs b/Source/CombatExtended/CombatExtended/DefOfs/CE_JobDefOf.cs new file mode 100644 index 0000000000..547d8c8e63 --- /dev/null +++ b/Source/CombatExtended/CombatExtended/DefOfs/CE_JobDefOf.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using Verse.AI; + +namespace CombatExtended +{ + [DefOf] + public static class CE_JobDefOf + { + public static JobDef TakeFromOther; + public static JobDef ReloadWeapon; + public static JobDef ReloadTurret; + public static JobDef HunkerDown; + public static JobDef RunForCover; + public static JobDef Stabilize; + public static JobDef WaitKnockdown; + } +} diff --git a/Source/CombatRealism/CombatExtended/DefOfs/CE_StatDefOf.cs b/Source/CombatExtended/CombatExtended/DefOfs/CE_StatDefOf.cs similarity index 56% rename from Source/CombatRealism/CombatExtended/DefOfs/CE_StatDefOf.cs rename to Source/CombatExtended/CombatExtended/DefOfs/CE_StatDefOf.cs index 616d026fa7..ec93f2b9d3 100644 --- a/Source/CombatRealism/CombatExtended/DefOfs/CE_StatDefOf.cs +++ b/Source/CombatExtended/CombatExtended/DefOfs/CE_StatDefOf.cs @@ -10,19 +10,28 @@ namespace CombatExtended [DefOf] public static class CE_StatDefOf { + // *** Item stats *** public static readonly StatDef Bulk = StatDef.Named("Bulk"); // for items in inventory - // public static readonly StatDef Mass = StatDef.Named("Mass"); // items in inventory - public static readonly StatDef WornBulk = StatDef.Named("WornBulk"); // apparel offsets - public static readonly StatDef WornWeight = StatDef.Named("WornWeight"); // apparel offsets - public static readonly StatDef CarryBulk = StatDef.Named("CarryBulk"); // pawn capacity - public static readonly StatDef CarryWeight = StatDef.Named("CarryWeight"); // pawn capacity - + public static readonly StatDef WornBulk = StatDef.Named("WornBulk"); // worn apparel + // *** Ranged weapon stats *** public static readonly StatDef ShotSpread = StatDef.Named("ShotSpread"); // pawn capacity public static readonly StatDef SwayFactor = StatDef.Named("SwayFactor"); // pawn capacity - public static readonly StatDef AimEfficiency = StatDef.Named("AimEfficiency"); // pawn capacity + public static StatDef SightsEfficiency; public static readonly StatDef AimingAccuracy = StatDef.Named("AimingAccuracy"); // pawn capacity public static readonly StatDef ReloadSpeed = StatDef.Named("ReloadSpeed"); // pawn capacity + // *** Melee weapon stats *** + public static StatDef MeleeWeapon_Penetration; + + // *** Pawn stats *** + public static StatDef CarryBulk; // Inventory max space + public static StatDef CarryWeight; // Inventory max weight + public static StatDef MeleeCritChance; + public static StatDef MeleeDodgeChance; + public static StatDef MeleeParryChance; + + + public static StatDef Suppressability; } } diff --git a/Source/CombatExtended/CombatExtended/DefOfs/CE_ThingDefOf.cs b/Source/CombatExtended/CombatExtended/DefOfs/CE_ThingDefOf.cs new file mode 100644 index 0000000000..70e9ae6848 --- /dev/null +++ b/Source/CombatExtended/CombatExtended/DefOfs/CE_ThingDefOf.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; + +namespace CombatExtended +{ + [DefOf] + public static class CE_ThingDefOf + { + public static readonly ThingDef Mote_SuppressIcon = ThingDef.Named("Mote_SuppressIcon"); + public static readonly ThingDef Mote_HunkerIcon = ThingDef.Named("Mote_HunkerIcon"); + + public static ThingDef FSX; + } +} diff --git a/Source/CombatRealism/CombatExtended/Defs/AmmoCategoryDef.cs b/Source/CombatExtended/CombatExtended/Defs/AmmoCategoryDef.cs similarity index 68% rename from Source/CombatRealism/CombatExtended/Defs/AmmoCategoryDef.cs rename to Source/CombatExtended/CombatExtended/Defs/AmmoCategoryDef.cs index 48cb7ed4b4..ece9530ca5 100644 --- a/Source/CombatRealism/CombatExtended/Defs/AmmoCategoryDef.cs +++ b/Source/CombatExtended/CombatExtended/Defs/AmmoCategoryDef.cs @@ -9,5 +9,8 @@ namespace CombatExtended public class AmmoCategoryDef : Def { public bool advanced = false; + public string labelShort; + + public string LabelCapShort => labelShort.CapitalizeFirst(); } } diff --git a/Source/CombatExtended/CombatExtended/Defs/AmmoDef.cs b/Source/CombatExtended/CombatExtended/Defs/AmmoDef.cs new file mode 100644 index 0000000000..a014808543 --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Defs/AmmoDef.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using UnityEngine; + +namespace CombatExtended +{ + public class AmmoDef : ThingDef + { + public AmmoCategoryDef ammoClass; + public int defaultAmmoCount = 1; + public float cookOffSpeed = 1f; + public float cookOffFlashScale = 1; + public ThingDef cookOffProjectile = null; + public SoundDef cookOffSound = null; + public SoundDef cookOffTailSound = null; + + private List users; + public List Users + { + get + { + if (users == null) + { + users = CE_Utility.allWeaponDefs.FindAll(delegate(ThingDef def) + { + CompProperties_AmmoUser props = def.GetCompProperties(); + return props != null && props.ammoSet.ammoTypes.Any(x => x.ammo == this); + }); + } + return users; + } + } + } +} diff --git a/Source/CombatExtended/CombatExtended/Defs/AmmoLink.cs b/Source/CombatExtended/CombatExtended/Defs/AmmoLink.cs new file mode 100644 index 0000000000..d4fb57ee19 --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Defs/AmmoLink.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml; +using RimWorld; +using Verse; +using UnityEngine; + +namespace CombatExtended +{ + public class AmmoLink + { + public AmmoDef ammo; + public ThingDef projectile; + + public AmmoLink() { } + + public AmmoLink(AmmoDef ammo, ThingDef projectile) + { + this.ammo = ammo; + this.projectile = projectile; + } + + public void LoadDataFromXmlCustom(XmlNode xmlRoot) + { + if (xmlRoot.ChildNodes.Count != 1) + { + Log.Error("Misconfigured AmmoLink: " + xmlRoot.OuterXml); + return; + } + DirectXmlCrossRefLoader.RegisterObjectWantsCrossRef(this, "ammo", xmlRoot.Name); + DirectXmlCrossRefLoader.RegisterObjectWantsCrossRef(this, "projectile", (string)ParseHelper.FromString(xmlRoot.FirstChild.Value, typeof(string))); + } + + public override string ToString() + { + return string.Concat("(", ammo == null ? "null" : ammo.defName, " -> ", projectile == null ? "null" : projectile.defName, ")"); + } + + public override int GetHashCode() + { + return ammo.shortHash + projectile.shortHash << 16; + } + } +} diff --git a/Source/CombatRealism/CombatExtended/Defs/AmmoSetDef.cs b/Source/CombatExtended/CombatExtended/Defs/AmmoSetDef.cs similarity index 83% rename from Source/CombatRealism/CombatExtended/Defs/AmmoSetDef.cs rename to Source/CombatExtended/CombatExtended/Defs/AmmoSetDef.cs index c6de484f3d..ede696a569 100644 --- a/Source/CombatRealism/CombatExtended/Defs/AmmoSetDef.cs +++ b/Source/CombatExtended/CombatExtended/Defs/AmmoSetDef.cs @@ -10,6 +10,6 @@ namespace CombatExtended { public class AmmoSetDef : Def { - public List ammoTypes; + public List ammoTypes; } } diff --git a/Source/CombatExtended/CombatExtended/Defs/BodyShapeDef.cs b/Source/CombatExtended/CombatExtended/Defs/BodyShapeDef.cs new file mode 100644 index 0000000000..1f23b4b04d --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Defs/BodyShapeDef.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using UnityEngine; + +namespace CombatExtended +{ + public class BodyShapeDef : Def + { + public float width = 1; + public float widthLaying = 1; + public float height = 1; + public float heightLaying = 1; + } +} diff --git a/Source/CombatRealism/CombatExtended/Defs/DamageDef_CE.cs b/Source/CombatExtended/CombatExtended/Defs/DamageDefExtensionCE.cs similarity index 60% rename from Source/CombatRealism/CombatExtended/Defs/DamageDef_CE.cs rename to Source/CombatExtended/CombatExtended/Defs/DamageDefExtensionCE.cs index 1020db1e32..aec2330048 100644 --- a/Source/CombatRealism/CombatExtended/Defs/DamageDef_CE.cs +++ b/Source/CombatExtended/CombatExtended/Defs/DamageDefExtensionCE.cs @@ -8,10 +8,10 @@ namespace CombatExtended { - public class DamageDef_CE : DamageDef + public class DamageDefExtensionCE : DefModExtension { - public bool deflectable = false; - public bool absorbable = false; + public bool noDamageOnDeflect = false; public bool harmOnlyOutsideLayers = false; + public bool isAmbientDamage = false; } } diff --git a/Source/CombatExtended/CombatExtended/Defs/JobDefExtensionCE.cs b/Source/CombatExtended/CombatExtended/Defs/JobDefExtensionCE.cs new file mode 100644 index 0000000000..7710776f34 --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Defs/JobDefExtensionCE.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using UnityEngine; + +namespace CombatExtended +{ + public class JobDefExtensionCE : DefModExtension + { + public bool isCrouchJob = false; + } +} diff --git a/Source/CombatRealism/CombatExtended/Defs/LoadoutGeneratorDef.cs b/Source/CombatExtended/CombatExtended/Defs/LoadoutGeneratorDef.cs similarity index 100% rename from Source/CombatRealism/CombatExtended/Defs/LoadoutGeneratorDef.cs rename to Source/CombatExtended/CombatExtended/Defs/LoadoutGeneratorDef.cs diff --git a/Source/CombatExtended/CombatExtended/Defs/LoadoutGenericDef.cs b/Source/CombatExtended/CombatExtended/Defs/LoadoutGenericDef.cs new file mode 100644 index 0000000000..9178bb57c6 --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Defs/LoadoutGenericDef.cs @@ -0,0 +1,187 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using RimWorld; +using Verse; + +/* Keep the following list up to date: + * Currently defined Generics: + * -for Meals - Pawns auto fetch a best food, generaly meals + * -for Raw Foodstuff - Pawns can auto fetch raw food if no meals, also will fetch for animal training. + * -for Drugs - Pawns can auto fetch drugs to fit a schedule. + * -for Ammo of each Gun that uses CombatExtended Ammo. Created programattically so should automatically get new guns/ammo. + */ +namespace CombatExtended +{ + /// + /// LoadoutGenericDef handles Generic LoadoutSlots. + /// + [StaticConstructorOnStartup] + public class LoadoutGenericDef : Verse.Def + { + #region Fields + public LoadoutCountType defaultCountType = LoadoutCountType.dropExcess; // default: drop anything more than (default)Count. + public int defaultCount = 1; + private Predicate _lambda; + public bool isBasic = false; + + // The following group are intentionally left unsaved so that if the game state changes between saves the new value is calculated. + private float _bulk; + private float _mass; + private bool _cachedVars = false; + + #endregion + + #region Constructors + //UNDONE This doesn't define weapons as yet and the code might not handle that well. Want to get various things stable first RE inventory. + // But we can define generics for short range, assault, pistol, melee. + /* (ProfoundDarkness) Some issues with weapons is that they have durability, quality, and often made of stuffs. + * Also could use a super-generic which fetches x clips for each weapon on the pawn (working on that for something else). + * I'm thinking we could add another button (more clutter) to each loadout slot which is only displayed if the item + * has key properties. Clicking that button would show a new window which lets the user configure parameters like + * a range slider for durability, range slider for quality, and a checklist for stuffs (assuming is made of stuffs). + */ + + /// + /// This constructor gets run on startup of RimWorld and generates the various LoadoutGenericDef instance objects akin to having been loaded from xml. + /// + static LoadoutGenericDef() + { + // Used in a handful of places where all loaded ThingDefs are useful. + IEnumerable everything = DefDatabase.AllDefs; + + // need to generate a list as that's how new defs are taken by DefDatabase. + List defs = new List(); + + + LoadoutGenericDef generic = new LoadoutGenericDef(); + generic.defName = "GenericMeal"; + generic.description = "Generic Loadout for Meals. Intended for compatibility with pawns automatically picking up a meal for themself."; + generic.label = "CE_Generic_Meal".Translate(); + generic.defaultCountType = LoadoutCountType.pickupDrop; // Fits with disabling of RimWorld Pawn behavior of fetching meals themselves. + generic._lambda = td => td.IsNutritionGivingIngestible && td.ingestible.preferability >= FoodPreferability.MealAwful && !td.IsDrug; + generic.isBasic = true; + + defs.Add(generic); + //Log.Message(string.Concat("CombatExtended :: LoadoutGenericDef :: ", generic.LabelCap, " list: ", string.Join(", ", DefDatabase.AllDefs.Where(t => generic.lambda(t)).Select(t => t.label).ToArray()))); + + + float targetNutrition = 0.85f; + generic = new LoadoutGenericDef(); + generic.defName = "GenericRawFood"; + generic.description = "Generic Loadout for Raw Food. Intended for compatibility with pawns automatically picking up raw food to train animals."; + generic.label = "CE_Generic_RawFood".Translate(); + // Exclude drugs and corpses. Also exclude any food worse than RawBad as in testing the pawns would not even pick it up for training. + generic._lambda = td => td.IsNutritionGivingIngestible && td.ingestible.preferability <= FoodPreferability.RawTasty && td.ingestible.HumanEdible && td.plant == null && !td.IsDrug && !td.IsCorpse; + generic.defaultCount = Convert.ToInt32(Math.Floor(targetNutrition / everything.Where(td => generic.lambda(td)).Average(td => td.ingestible.nutrition))); + //generic.defaultCount = 1; + generic.isBasic = false; // doesn't need to be in loadouts by default as animal interaction talks to HoldTracker now. + //TODO: Test pawns fetching raw food if no meal is available, if so then add a patch to have that talk to HoldTracker too. + + defs.Add(generic); + //Log.Message(string.Concat("CombatExtended :: LoadoutGenericDef :: ", generic.LabelCap, " list: ", string.Join(", ", DefDatabase.AllDefs.Where(t => generic.lambda(t)).Select(t => t.label + " B(" + t.GetStatValueAbstract(CE_StatDefOf.Bulk) + ") M(" + t.GetStatValueAbstract(StatDefOf.Mass) + ")").ToArray()))); + + + generic = new LoadoutGenericDef(); + generic.defName = "GenericDrugs"; + generic.defaultCount = 3; + generic.description = "Generic Loadout for Drugs. Intended for compatibility with pawns automatically picking up drugs in compliance with drug policies."; + generic.label = "CE_Generic_Drugs".Translate(); + generic._lambda = td => td.IsDrug; + generic.isBasic = true; + + defs.Add(generic); + //Log.Message(string.Concat("CombatExtended :: LoadoutGenericDef :: ", generic.LabelCap, " list: ", string.Join(", ", DefDatabase.AllDefs.Where(t => generic.lambda(t)).Select(t => t.label).ToArray()))); + + + generic = new LoadoutGenericDef(); + generic.defName = "GenericMedicine"; + generic.defaultCount = 5; + generic.defaultCountType = LoadoutCountType.pickupDrop; + generic.description = "Generic Loadout for Medicine. Intended for pawns which will handle triage activities."; + generic.label = "CE_Generic_Medicine".Translate(); + generic._lambda = td => td.IsMedicine; + + // now for the guns and ammo... + + // Get a list of guns that are player acquireable (not menuHidden but could also go with not dropOnDeath) which have expected comps/compProperties/verbs. + List guns = everything.Where(td => !td.menuHidden && + td.HasComp(typeof(CompAmmoUser)) && td.GetCompProperties() != null && + td.Verbs.FirstOrDefault(v => v is VerbPropertiesCE) != null).ToList(); + string ammoLabel = "CE_Generic_Ammo".Translate(); + const string ammoDescription = "Generic Loadout ammo for {0}. Intended for generic collection of ammo for given gun."; + foreach (ThingDef gun in guns) + { + // make sure the gun has ammo defined... + if (gun.GetCompProperties().ammoSet.ammoTypes.Count <= 0) + continue; + generic = new LoadoutGenericDef(); + generic.defName = "GenericAmmo-" + gun.defName; + generic.description = string.Format(ammoDescription, gun.LabelCap); + generic.label = string.Format(ammoLabel, gun.LabelCap); + generic.defaultCount = gun.GetCompProperties().magazineSize; + generic.defaultCountType = LoadoutCountType.pickupDrop; // we want ammo to get picked up. + //generic._lambda = td => td is AmmoDef && gun.GetCompProperties().ammoSet.ammoTypes.Contains(td); + generic._lambda = td => td is AmmoDef && gun.GetCompProperties().ammoSet.ammoTypes.Any(al => al.ammo == td); + defs.Add(generic); + //Log.Message(string.Concat("CombatExtended :: LoadoutGenericDef :: ", generic.LabelCap, " list: ", string.Join(", ", DefDatabase.AllDefs.Where(t => generic.lambda(t)).Select(t => t.label).ToArray()))); + } + + // finally we add all the defs generated to the DefDatabase. + DefDatabase.Add(defs); + } + + #endregion Constructors + + #region Properties + + /// + /// Property gets/runs the lambda defining what ThingDefs are accepted by this def. + /// + public Predicate lambda { get { return _lambda; } } + + /// + /// Property gets the calculated bulk of this def. This is determined at runtime based on stored Lambda rather than a static value. + /// + public float bulk + { + get + { + if (!_cachedVars) + updateVars(); + return _bulk; + } + } + + /// + /// Property gets the calculated mass of this def. This is determined at runtime based on stored Lambda rather than a static value. + /// + public float mass + { + get + { + if (!_cachedVars) + updateVars(); + return _mass; + } + } + #endregion Properties + + #region Methods + /// + /// Handles updating this def's stored bulk/mass values. + /// + /// Can be a bit expensive but only done once per def the first time such values are requested. + private void updateVars() + { + IEnumerable matches; + matches = DefDatabase.AllDefs.Where(td => lambda(td)); + _bulk = matches.Max(t => t.GetStatValueAbstract(CE_StatDefOf.Bulk)); + _mass = matches.Max(t => t.GetStatValueAbstract(StatDefOf.Mass)); + _cachedVars = true; + } + + #endregion Methods + } +} diff --git a/Source/CombatExtended/CombatExtended/Defs/RacePropertiesExtensionCE.cs b/Source/CombatExtended/CombatExtended/Defs/RacePropertiesExtensionCE.cs new file mode 100644 index 0000000000..101c19e7b6 --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Defs/RacePropertiesExtensionCE.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using UnityEngine; + +namespace CombatExtended +{ + + public class RacePropertiesExtensionCE : DefModExtension + { + public BodyShapeDef bodyShape = CE_BodyShapeDefOf.Invalid; + } +} diff --git a/Source/CombatExtended/CombatExtended/Defs/ShieldDefExtension.cs b/Source/CombatExtended/CombatExtended/Defs/ShieldDefExtension.cs new file mode 100644 index 0000000000..5781ae0700 --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Defs/ShieldDefExtension.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using UnityEngine; + +namespace CombatExtended +{ + public class ShieldDefExtension : DefModExtension + { + public List shieldCoverage = new List(); + public List crouchCoverage = new List(); + public bool drawAsTall = false; + + public bool PartIsCoveredByShield(BodyPartRecord part, Pawn pawn) + { + if (!shieldCoverage.NullOrEmpty()) + { + foreach(BodyPartGroupDef group in shieldCoverage) + { + if (part.IsInGroup(group)) return true; + } + } + if (!crouchCoverage.NullOrEmpty() && pawn.IsCrouching()) + { + foreach(BodyPartGroupDef group in crouchCoverage) + { + if (part.IsInGroup(group)) return true; + } + } + return false; + } + } +} diff --git a/Source/CombatExtended/CombatExtended/Defs/VisibleAccessoryDefExtension.cs b/Source/CombatExtended/CombatExtended/Defs/VisibleAccessoryDefExtension.cs new file mode 100644 index 0000000000..c79fb51d12 --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Defs/VisibleAccessoryDefExtension.cs @@ -0,0 +1,28 @@ +using Verse; + +namespace CombatExtended +{ + public class VisibleAccessoryDefExtension : DefModExtension + { + public int order = 1; + + private bool validated = false; + + public void Validate() + { + if (validated) return; + + if (order < 1) + { + Log.Error("CE detected VisibleAccessoryDefExtension with order lower than 1, viable values are 1-4. Clamping to 1"); + order = 1; + } + else if (order > 4) + { + Log.Error("CE detected VisibleAccessoryDefExtension with order higher than 4, viable values are 1-4. Clamping to 4"); + order = 4; + } + validated = true; + } + } +} diff --git a/Source/CombatRealism/CombatExtended/AimMode.cs b/Source/CombatExtended/CombatExtended/Enums/AimMode.cs similarity index 83% rename from Source/CombatRealism/CombatExtended/AimMode.cs rename to Source/CombatExtended/CombatExtended/Enums/AimMode.cs index 80b371f053..f8a42db22c 100644 --- a/Source/CombatRealism/CombatExtended/AimMode.cs +++ b/Source/CombatExtended/CombatExtended/Enums/AimMode.cs @@ -9,7 +9,6 @@ public enum AimMode : byte { Snapshot, AimedShot, - SuppressFire, - HoldFire + SuppressFire } } diff --git a/Source/CombatRealism/CombatExtended/FireMode.cs b/Source/CombatExtended/CombatExtended/Enums/FireMode.cs similarity index 100% rename from Source/CombatRealism/CombatExtended/FireMode.cs rename to Source/CombatExtended/CombatExtended/Enums/FireMode.cs diff --git a/Source/CombatExtended/CombatExtended/Enums/LoadoutCountType.cs b/Source/CombatExtended/CombatExtended/Enums/LoadoutCountType.cs new file mode 100644 index 0000000000..ea4e3830af --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Enums/LoadoutCountType.cs @@ -0,0 +1,10 @@ +using System; + +namespace CombatExtended +{ + public enum LoadoutCountType : byte + { + pickupDrop, // Indicates that the goal is to keep LoadoutSlot.Count items in inventory. Pickup to get there and drop excess. + dropExcess // Indicates that the goal is to ignore any items of this type until Count is reached, then drop excess. + } +} \ No newline at end of file diff --git a/Source/CombatRealism/CombatExtended/RecoilPattern.cs b/Source/CombatExtended/CombatExtended/Enums/RecoilPattern.cs similarity index 100% rename from Source/CombatRealism/CombatExtended/RecoilPattern.cs rename to Source/CombatExtended/CombatExtended/Enums/RecoilPattern.cs diff --git a/Source/CombatExtended/CombatExtended/Gizmos/Command_Reload.cs b/Source/CombatExtended/CombatExtended/Gizmos/Command_Reload.cs new file mode 100644 index 0000000000..c520428710 --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Gizmos/Command_Reload.cs @@ -0,0 +1,101 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using UnityEngine; +using Verse.AI; + +namespace CombatExtended +{ + public class Command_Reload : Command_Action + { + public CompAmmoUser compAmmo; + + public override void ProcessInput(Event ev) + { + if (compAmmo == null) + { + Log.Error("Command_Reload without ammo comp"); + return; + } + if (((ev.button == 1 || !Controller.settings.RightClickAmmoSelect) + && compAmmo.useAmmo + && (compAmmo.compInventory != null || compAmmo.turret != null)) + || action == null) + { + Find.WindowStack.Add(MakeAmmoMenu()); + } + else if (compAmmo.SelectedAmmo != compAmmo.currentAmmo || compAmmo.curMagCount < compAmmo.Props.magazineSize) + { + base.ProcessInput(ev); + } + // Show we learned something by clicking this + if (!tutorTag.NullOrEmpty()) PlayerKnowledgeDatabase.KnowledgeDemonstrated(ConceptDef.Named(tutorTag), KnowledgeAmount.Total); + } + + private FloatMenu MakeAmmoMenu() + { + List ammoList = new List(); // List of all ammo types the gun can use and the pawn has in his inventory + if (compAmmo.turret != null) + { + // If we have no inventory available (e.g. manned turret), add all possible ammo types to the selection + foreach(AmmoLink link in compAmmo.Props.ammoSet.ammoTypes) + { + ammoList.Add(link.ammo); + } + } + else + { + // Iterate through all suitable ammo types and check if they're in our inventory + foreach (AmmoLink curLink in compAmmo.Props.ammoSet.ammoTypes) + { + if (compAmmo.compInventory.ammoList.Any(x => x.def == curLink.ammo)) + ammoList.Add(curLink.ammo); + } + } + + // Append float menu options for every available ammo type + List floatOptionList = new List(); + if (ammoList.NullOrEmpty()) + { + floatOptionList.Add(new FloatMenuOption("CE_OutOfAmmo".Translate(), null)); + } + else + { + // Append all available ammo types + foreach (ThingDef curDef in ammoList) + { + AmmoDef ammoDef = (AmmoDef)curDef; + floatOptionList.Add(new FloatMenuOption(ammoDef.ammoClass.LabelCap, new Action(delegate { + bool shouldReload = Controller.settings.AutoReloadOnChangeAmmo && (compAmmo.SelectedAmmo != ammoDef || compAmmo.curMagCount < compAmmo.Props.magazineSize) && compAmmo.turret?.MannableComp == null; + compAmmo.SelectedAmmo = ammoDef; + if (shouldReload) + { + if (compAmmo.turret != null) + { + compAmmo.turret.TryOrderReload(); + } + else + { + compAmmo.TryStartReload(); + } + } + }))); + } + } + // Append unload command + if (compAmmo.useAmmo && (compAmmo.wielder != null || compAmmo.turret?.MannableComp != null) && compAmmo.hasMagazine && compAmmo.curMagCount > 0) + { + floatOptionList.Add(new FloatMenuOption("CE_UnloadLabel".Translate(), new Action(delegate { compAmmo.TryUnload(); }))); + } + // Append reload command + if (compAmmo.hasMagazine && !Controller.settings.RightClickAmmoSelect) + { + floatOptionList.Add(new FloatMenuOption("CE_ReloadLabel".Translate(), new Action(action))); + } + return new FloatMenu(floatOptionList); + } + } +} diff --git a/Source/CombatRealism/CombatExtended/Gizmos/Command_VerbTarget.cs b/Source/CombatExtended/CombatExtended/Gizmos/Command_VerbTarget.cs similarity index 100% rename from Source/CombatRealism/CombatExtended/Gizmos/Command_VerbTarget.cs rename to Source/CombatExtended/CombatExtended/Gizmos/Command_VerbTarget.cs diff --git a/Source/CombatRealism/CombatExtended/Gizmos/GizmoAmmoStatus.cs b/Source/CombatExtended/CombatExtended/Gizmos/GizmoAmmoStatus.cs similarity index 100% rename from Source/CombatRealism/CombatExtended/Gizmos/GizmoAmmoStatus.cs rename to Source/CombatExtended/CombatExtended/Gizmos/GizmoAmmoStatus.cs diff --git a/Source/CombatRealism/CombatExtended/Jobs/ExternalPawnDrafter.cs b/Source/CombatExtended/CombatExtended/Jobs/ExternalPawnDrafter.cs similarity index 93% rename from Source/CombatRealism/CombatExtended/Jobs/ExternalPawnDrafter.cs rename to Source/CombatExtended/CombatExtended/Jobs/ExternalPawnDrafter.cs index 46ba7b1afa..b9ab1ccfae 100644 --- a/Source/CombatRealism/CombatExtended/Jobs/ExternalPawnDrafter.cs +++ b/Source/CombatExtended/CombatExtended/Jobs/ExternalPawnDrafter.cs @@ -27,7 +27,7 @@ public static void TakeOrderedJob( Pawn pawn, Job newJob ) return; } pawn.CurJob.playerForced = true; - if ( pawn.jobs.curJob != null && pawn.jobs.curJob.JobIsSameAs( newJob ) ) + if ( pawn.CurJob.JobIsSameAs( newJob ) ) { return; } @@ -47,7 +47,7 @@ public static void TakeOrderedJob( Pawn pawn, Job newJob ) } pawn.jobs.jobQueue.Clear(); pawn.jobs.jobQueue.EnqueueFirst( newJob ); - if ( pawn.jobs.curJob != null ) + if ( pawn.CurJob != null ) { pawn.jobs.curDriver.EndJobWith( JobCondition.InterruptForced ); } diff --git a/Source/CombatExtended/CombatExtended/Jobs/JobDriver_HunkerDown.cs b/Source/CombatExtended/CombatExtended/Jobs/JobDriver_HunkerDown.cs new file mode 100644 index 0000000000..b4271f553d --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Jobs/JobDriver_HunkerDown.cs @@ -0,0 +1,54 @@ +using System.Collections.Generic; +using RimWorld; +using Verse; +using Verse.AI; + +namespace CombatExtended +{ + class JobDriver_HunkerDown : JobDriver + { + private const int getUpCheckInterval = 60; + + public override PawnPosture Posture + { + get + { + return PawnPosture.LayingAny; + } + } + + protected override IEnumerable MakeNewToils() + { + this.FailOnDespawnedOrNull(TargetIndex.A); + + //Define Toil + Toil toilWait = new Toil(); + toilWait.initAction = () => + { + toilWait.actor.pather.StopDead(); + }; + + Toil toilNothing = new Toil(); + //toilNothing.initAction = () => {}; + toilNothing.defaultCompleteMode = ToilCompleteMode.Delay; + toilNothing.defaultDuration = getUpCheckInterval; + + // Start Toil + yield return toilWait; + yield return toilNothing; + yield return Toils_Jump.JumpIf(toilNothing, () => + { + CompSuppressable comp = pawn.TryGetComp(); + if (comp == null) + { + return false; + } + if (!comp.CanReactToSuppression) + { + return false; + } + return comp.IsHunkering; + }); + } + } +} diff --git a/Source/CombatExtended/CombatExtended/Jobs/JobDriver_Hunt.cs b/Source/CombatExtended/CombatExtended/Jobs/JobDriver_Hunt.cs new file mode 100644 index 0000000000..f7ceceffbc --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Jobs/JobDriver_Hunt.cs @@ -0,0 +1,199 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Verse; +using Verse.AI; +using RimWorld; +using UnityEngine; + +namespace CombatExtended +{ + /// + /// Description of JobDriver_Hunt. + /// + public class JobDriver_Hunt : JobDriver + { + protected override IEnumerable MakeNewToils() + { + this.FailOn(delegate + { + if (!CurJob.ignoreDesignations) + { + Pawn victim = Victim; + if (victim != null && !victim.Dead && Map.designationManager.DesignationOn(victim, DesignationDefOf.Hunt) == null) + { + return true; + } + } + return false; + }); + + yield return Toils_Reserve.Reserve(VictimInd, 1); + + var init = new Toil(); + init.initAction = delegate + { + jobStartTick = Find.TickManager.TicksGame; + }; + + yield return init; + + yield return Toils_Combat.TrySetJobToUseAttackVerb(); + + var comp = (pawn.equipment != null && pawn.equipment.Primary != null) ? pawn.equipment.Primary.TryGetComp() : null; + var startCollectCorpse = StartCollectCorpseToil(); + var gotoCastPos = GotoCastPosition(VictimInd, true).JumpIfDespawnedOrNull(VictimInd, startCollectCorpse).FailOn(() => Find.TickManager.TicksGame > jobStartTick + MaxHuntTicks); + + yield return gotoCastPos; + + var moveIfCannotHit = Toils_Jump.JumpIfTargetNotHittable(VictimInd, gotoCastPos); + + yield return moveIfCannotHit; + + yield return Toils_Jump.JumpIfTargetDownedDistant(VictimInd, gotoCastPos); + + yield return Toils_Jump.JumpIfTargetDespawnedOrNull(VictimInd, startCollectCorpse); + + yield return Toils_Combat.CastVerb(VictimInd, false).JumpIfDespawnedOrNull(VictimInd, startCollectCorpse) + .FailOn(() => { + if (Find.TickManager.TicksGame <= jobStartTick + MaxHuntTicks) + { + if (comp == null || comp.hasAndUsesAmmoOrMagazine) + { + return false; + } + } + return true; + }); + + yield return Toils_Jump.Jump(moveIfCannotHit); + + yield return startCollectCorpse; + + yield return Toils_Goto.GotoCell(VictimInd, PathEndMode.ClosestTouch).FailOnDespawnedNullOrForbidden(VictimInd).FailOnSomeonePhysicallyInteracting(VictimInd); + + yield return Toils_Haul.StartCarryThing(VictimInd); + + var carryToCell = Toils_Haul.CarryHauledThingToCell(StoreCellInd); + + yield return carryToCell; + + yield return Toils_Haul.PlaceHauledThingInCell(StoreCellInd, carryToCell, true); + } + + const TargetIndex VictimInd = TargetIndex.A; + + const TargetIndex StoreCellInd = TargetIndex.B; + + const int MaxHuntTicks = 5000; + + int jobStartTick = -1; + + public Pawn Victim + { + get + { + Corpse corpse = Corpse; + return corpse != null ? corpse.InnerPawn : (Pawn)CurJob.GetTarget(TargetIndex.A).Thing; + } + } + + Corpse Corpse + { + get + { + return CurJob.GetTarget(TargetIndex.A).Thing as Corpse; + } + } + + public override void ExposeData() + { + base.ExposeData(); + Scribe_Values.Look(ref jobStartTick, "jobStartTick", 0); + } + + public override string GetReport() + { + return CurJob.def.reportString.Replace("TargetA", Victim.LabelShort); + } + + //Copy of Verse.AI.Toils_CombatGotoCastPosition + Toil GotoCastPosition(TargetIndex targetInd, bool closeIfDowned = false) + { + var toil = new Toil(); + toil.initAction = delegate + { + Pawn actor = toil.actor; + Job curJob = actor.CurJob; + Thing thing = curJob.GetTarget(targetInd).Thing; + var pawnVictim = thing as Pawn; + IntVec3 intVec; + if (!CastPositionFinder.TryFindCastPosition(new CastPositionRequest + { + caster = toil.actor, + target = thing, + verb = curJob.verbToUse, + maxRangeFromTarget = ((closeIfDowned && pawnVictim != null && pawnVictim.Downed) + ? Mathf.Min(curJob.verbToUse.verbProps.range, (float)pawnVictim.RaceProps.executionRange) + //The following line is changed + : HuntRangePerBodysize(pawnVictim.RaceProps.baseBodySize, (float)pawnVictim.RaceProps.executionRange, curJob.verbToUse.verbProps.range)), + wantCoverFromTarget = false + }, out intVec)) + { + toil.actor.jobs.EndCurrentJob(JobCondition.Incompletable, true); + return; + } + toil.actor.pather.StartPath(intVec, PathEndMode.OnCell); + actor.Map.pawnDestinationManager.ReserveDestinationFor(actor, intVec); + }; + toil.FailOnDespawnedOrNull(targetInd); + toil.defaultCompleteMode = ToilCompleteMode.PatherArrival; + return toil; + } + + //Fit for an attack range per body size curve. + public static float HuntRangePerBodysize(float x, float executionRange, float gunRange) + { + return Mathf.Min(Mathf.Clamp(1 + 20 * (1 - Mathf.Exp(-0.65f * x)), executionRange, 20), gunRange); + } + + Toil StartCollectCorpseToil() + { + var toil = new Toil(); + toil.initAction = delegate + { + if (Victim == null) + { + toil.actor.jobs.EndCurrentJob(JobCondition.Incompletable); + return; + } + TaleRecorder.RecordTale(TaleDefOf.Hunted, new object[] + { + pawn, + Victim + }); + Corpse corpse = Victim.Corpse; + if (corpse == null || !this.pawn.CanReserveAndReach(corpse, PathEndMode.ClosestTouch, Danger.Deadly, 1)) + { + pawn.jobs.EndCurrentJob(JobCondition.Incompletable); + return; + } + corpse.SetForbidden(false, true); + IntVec3 c; + if (StoreUtility.TryFindBestBetterStoreCellFor(corpse, pawn, Map, StoragePriority.Unstored, pawn.Faction, out c)) + { + pawn.Reserve(corpse, 1); + pawn.Reserve(c, 1); + pawn.CurJob.SetTarget(TargetIndex.B, c); + pawn.CurJob.SetTarget(TargetIndex.A, corpse); + pawn.CurJob.count = 1; + pawn.CurJob.haulMode = HaulMode.ToCellStorage; + return; + } + pawn.jobs.EndCurrentJob(JobCondition.Succeeded, true); + }; + return toil; + } + } +} diff --git a/Source/CombatExtended/CombatExtended/Jobs/JobDriver_Reload.cs b/Source/CombatExtended/CombatExtended/Jobs/JobDriver_Reload.cs new file mode 100644 index 0000000000..8f30082427 --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Jobs/JobDriver_Reload.cs @@ -0,0 +1,162 @@ +using System.Collections.Generic; +using RimWorld; +using UnityEngine; +using Verse; +using Verse.AI; + +namespace CombatExtended +{ + public class JobDriver_Reload : JobDriver + { + #region Fields + private CompAmmoUser _compReloader = null; + private ThingWithComps initEquipment = null; + private bool reloadingInventory = false; + private bool reloadingEquipment = false; + #endregion Fields + + #region Properties + private string errorBase => this.GetType().Assembly.GetName().Name + " :: " + this.GetType().Name + " :: "; + + // TargetA == Pawn holder/reloader (equipment or inventory) + private TargetIndex indReloader => TargetIndex.A; + private Pawn holder => TargetThingA as Pawn; + // TargetB == ThingWithComps (weapon) + private TargetIndex indWeapon => TargetIndex.B; + private ThingWithComps weapon => TargetThingB as ThingWithComps; //intentionally non-caching. + + private bool weaponEquipped { get { return pawn?.equipment?.Primary == weapon; } } + private bool weaponInInventory { get { return pawn?.inventory?.innerContainer.Contains(weapon) ?? false; } } + + /// + /// Gets and caches the CompAmmoUser. + /// + private CompAmmoUser compReloader + { + get + { + if (_compReloader == null) _compReloader = weapon.TryGetComp(); + return _compReloader; + } + } + + #endregion Properties + + #region Methods + + /// + /// Generates the string which is shown in the interface when a pawn is selected while they are performing this job. + /// + /// string representing the current activity of the pawn doing this job. + public override string GetReport() + { + string text = CE_JobDefOf.ReloadWeapon.reportString; + string flagSource = ""; + if (reloadingEquipment) flagSource = "CE_ReloadingEquipment".Translate(); + if (reloadingInventory) flagSource = "CE_ReloadingInventory".Translate(); + text = text.Replace("FlagSource", flagSource); + text = text.Replace("TargetB", weapon.def.label); + if (Controller.settings.EnableAmmoSystem) + text = text.Replace("AmmoType", compReloader.currentAmmo.label); + else + text = text.Replace("AmmoType", "CE_ReloadingGenericAmmo".Translate()); return text; + } + + /// + /// Additional failure conditions that we want to end this job on. + /// + /// bool, true indicates the job should be halted + private bool HasNoGunOrAmmo() + { + //if (TargetThingB.DestroyedOrNull() || pawn.equipment == null || pawn.equipment.Primary == null || pawn.equipment.Primary != TargetThingB) + if ((reloadingEquipment && (pawn?.equipment?.Primary == null || pawn.equipment.Primary != weapon)) + || (reloadingInventory && (pawn.inventory == null || !pawn.inventory.innerContainer.Contains(weapon))) + || (initEquipment != pawn?.equipment?.Primary)) + return true; + + //CompAmmoUser comp = pawn.equipment.Primary.TryGetComp(); + //return comp != null && comp.useAmmo && !comp.hasAmmo; + //return comp != null && !comp.hasAndUsesAmmoOrMagazine; + // expecting true ends the job. if comp == null then will return false from the first part and not test the second. Job will continue (bad). + + return compReloader == null || !compReloader.hasAndUsesAmmoOrMagazine; + } + + /// + /// Generates a series of actions (toils) that the pawn should perform. + /// + /// Ienumerable of type Toil + /// Remember that, in the case of jobs, effectively the entire method is executed before any actual activity occurs. + protected override IEnumerable MakeNewToils() + { + // Error checking and 'helpful' messages for what is wrong. + if (holder == null) // A later check will catch this (failon) but that fails silently. + { + Log.Error(errorBase + "TargetThingA is null. A Pawn is required to perform a reload."); + yield return null; + } + if (weapon == null) // Required. + { + Log.Error(errorBase + "TargetThingB is null. A weapon (ThingWithComps) is required to perform a reload."); + yield return null; + } + if (compReloader == null) // Required. + { + Log.Error(errorBase + pawn + " tried to do reload job on " + weapon.LabelCap + " which doesn't have a required CompAmmoUser."); + yield return null; + } + if (holder != pawn) // Helps restrict what this job does, not really necessary and may work fine (though possibly undesirable behavior) without this check. + { + Log.Error(errorBase + "TargetThingA (" + holder.Name + ") is not the same Pawn (" + pawn.Name + ") that was given the job."); + yield return null; + } + // get the state of the job (inventory vs other) at the start. + reloadingInventory = weaponInInventory; + reloadingEquipment = weaponEquipped; + // A couple more more 'helpful' error check/message. + if (!reloadingInventory && !reloadingEquipment) // prevent some bad states/behavior on FailOn and job text. + { + Log.Error(errorBase + "Unable to find the weapon to be reloaded (" + weapon.LabelCap + ") in the inventory nor equipment of " + pawn.Name); + yield return null; + } + if (reloadingInventory && reloadingEquipment) // prevent incorrect information on job text. If somehow this was true may cause a FailOn to trip. + { + Log.Error(errorBase + "Something went spectacularly wrong as the weapon to be reloaded was found in both the Pawn's equipment AND inventory at the same time."); + yield return null; + } + + // current state of equipment, want to interrupt the reload if a pawn's equipment changes. + initEquipment = pawn.equipment?.Primary; + + // setup fail states, if something goes wrong with the pawn performing the reload, the weapon, or something else that we want to fail on. + this.FailOnDespawnedOrNull(indReloader); + this.FailOnMentalState(indReloader); + this.FailOnDestroyedOrNull(indWeapon); + this.FailOn(HasNoGunOrAmmo); + + // Throw mote + if (compReloader.ShouldThrowMote) + MoteMaker.ThrowText(pawn.Position.ToVector3Shifted(), Find.VisibleMap, string.Format("CE_ReloadingMote".Translate(), weapon.def.LabelCap)); + + //Toil of do-nothing + Toil waitToil = new Toil() { actor = pawn }; // actor was always null in testing... + waitToil.initAction = () => waitToil.actor.pather.StopDead(); + waitToil.defaultCompleteMode = ToilCompleteMode.Delay; + waitToil.defaultDuration = Mathf.CeilToInt(compReloader.Props.reloadTime.SecondsToTicks() / pawn.GetStatValue(CE_StatDefOf.ReloadSpeed)); + yield return waitToil.WithProgressBarToilDelay(indReloader); + + //Actual reloader + Toil reloadToil = new Toil(); + reloadToil.AddFinishAction(() => compReloader.LoadAmmo()); + yield return reloadToil; + + //Continue previous job if possible + Toil continueToil = new Toil + { + defaultCompleteMode = ToilCompleteMode.Instant + }; + yield return continueToil; + } + #endregion Methods + } +} \ No newline at end of file diff --git a/Source/CombatExtended/CombatExtended/Jobs/JobDriver_ReloadTurret.cs b/Source/CombatExtended/CombatExtended/Jobs/JobDriver_ReloadTurret.cs new file mode 100644 index 0000000000..21060771eb --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Jobs/JobDriver_ReloadTurret.cs @@ -0,0 +1,131 @@ +using System.Collections.Generic; +using RimWorld; +using UnityEngine; +using Verse; +using Verse.AI; + +namespace CombatExtended +{ + public class JobDriver_ReloadTurret : JobDriver + { + #region Fields + private CompAmmoUser _compReloader; + #endregion Fields + + #region Properties + private string errorBase => this.GetType().Assembly.GetName().Name + " :: " + this.GetType().Name + " :: "; + + private Building_TurretGunCE turret => TargetThingA as Building_TurretGunCE; + private AmmoThing ammo => TargetThingB as AmmoThing; + + private CompAmmoUser compReloader + { + get + { + if (_compReloader == null && turret != null) + _compReloader = turret.CompAmmo; + return _compReloader; + } + } + #endregion + + #region Methods + + public override string GetReport() + { + string text = CE_JobDefOf.ReloadTurret.reportString; + string turretType = (turret.def.hasInteractionCell ? "CE_MannedTurret" : "CE_AutoTurret").Translate(); + text = text.Replace("TurretType", turretType); + text = text.Replace("TargetA", TargetThingA.def.label); + if (compReloader.useAmmo) + text = text.Replace("TargetB", TargetThingB.def.label); + else + text = text.Replace("TargetB", "CE_ReloadingGenericAmmo".Translate()); + return text; + } + + protected override IEnumerable MakeNewToils() + { + // Error checking/input validation. + if (turret == null) + { + Log.Error(string.Concat(errorBase, "TargetThingA isn't a Building_TurretGunCE")); + yield return null; + } + if (compReloader == null) + { + Log.Error(string.Concat(errorBase, "TargetThingA (Building_TurretGunCE) is missing it's CompAmmoUser.")); + yield return null; + } + if (compReloader.useAmmo && ammo == null) + { + Log.Error(string.Concat(errorBase, "TargetThingB is either null or not an AmmoThing.")); + yield return null; + } + + // Set fail condition on turret. + if (pawn.Faction != Faction.OfPlayer) + this.FailOnDestroyedOrNull(TargetIndex.A); + else + this.FailOnDestroyedNullOrForbidden(TargetIndex.A); + + // Reserve the turret + yield return Toils_Reserve.Reserve(TargetIndex.A, 1); + + if (compReloader.useAmmo) + { + // Perform ammo system specific activities, failure condition and hauling + if (pawn.Faction != Faction.OfPlayer) + { + ammo.SetForbidden(false, false); + this.FailOnDestroyedOrNull(TargetIndex.B); + } + else + { + this.FailOnDestroyedNullOrForbidden(TargetIndex.B); + } + + // Haul ammo + yield return Toils_Reserve.Reserve(TargetIndex.B, 1); + yield return Toils_Goto.GotoCell(ammo.Position, PathEndMode.ClosestTouch); + yield return Toils_Haul.StartCarryThing(TargetIndex.B); + yield return Toils_Goto.GotoCell(turret.Position, PathEndMode.ClosestTouch); + //yield return Toils_Haul.PlaceHauledThingInCell(TargetIndex.A, null, false); + } else + { + // If ammo system is turned off we just need to go to the turret. + yield return Toils_Goto.GotoCell(turret.Position, PathEndMode.ClosestTouch); + } + + // Wait in place + Toil waitToil = new Toil() { actor = pawn }; + waitToil.initAction = delegate + { + // Initial relaod process activities. + waitToil.actor.pather.StopDead(); + turret.isReloading = true; + if (compReloader.ShouldThrowMote) + MoteMaker.ThrowText(turret.Position.ToVector3Shifted(), turret.Map, string.Format("CE_ReloadingTurretMote".Translate(), TargetThingA.LabelCapNoCount)); + Thing newAmmo; + compReloader.TryUnload(out newAmmo); + if (newAmmo?.CanStackWith(ammo) ?? false) + pawn.carryTracker.TryStartCarry(newAmmo, Mathf.Min(newAmmo.stackCount, compReloader.Props.magazineSize - ammo.stackCount)); + }; + waitToil.AddFinishAction(() => turret.isReloading = false); + waitToil.defaultCompleteMode = ToilCompleteMode.Delay; + waitToil.defaultDuration = Mathf.CeilToInt(compReloader.Props.reloadTime.SecondsToTicks() / pawn.GetStatValue(CE_StatDefOf.ReloadSpeed)); + yield return waitToil.WithProgressBarToilDelay(TargetIndex.A); + + //Actual reloader + Toil reloadToil = new Toil(); + reloadToil.defaultCompleteMode = ToilCompleteMode.Instant; + reloadToil.initAction = delegate + { + compReloader.LoadAmmo(ammo); + }; + //if (compReloader.useAmmo) reloadToil.EndOnDespawnedOrNull(TargetIndex.B); + yield return reloadToil; + } + #endregion Methods + } +} diff --git a/Source/CombatExtended/CombatExtended/Jobs/JobDriver_Stabilize.cs b/Source/CombatExtended/CombatExtended/Jobs/JobDriver_Stabilize.cs new file mode 100644 index 0000000000..8984c144ac --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Jobs/JobDriver_Stabilize.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using Verse.AI; +using UnityEngine; + +namespace CombatExtended +{ + public class JobDriver_Stabilize : JobDriver + { + private const float baseTendDuration = 60f; + + private Pawn Patient { get { return CurJob.targetA.Thing as Pawn; } } + private Medicine Medicine { get { return CurJob.targetB.Thing as Medicine; } } + + protected override IEnumerable MakeNewToils() + { + this.FailOn(() => Patient == null || Medicine == null); + this.FailOnDespawnedNullOrForbidden(TargetIndex.A); + this.FailOnDestroyedNullOrForbidden(TargetIndex.B); + this.FailOnNotDowned(TargetIndex.A); + this.AddEndCondition(delegate + { + if (Patient.health.hediffSet.GetHediffsTendable().Any(h => h.CanBeStabilizied())) return JobCondition.Ongoing; + Medicine.Destroy(); + return JobCondition.Incompletable; + }); + + // Pick up medicine and haul to patient + yield return Toils_Reserve.Reserve(TargetIndex.A); + yield return Toils_Reserve.Reserve(TargetIndex.B); + yield return Toils_Goto.GotoThing(TargetIndex.B, PathEndMode.ClosestTouch); + yield return Toils_Haul.StartCarryThing(TargetIndex.B); + yield return Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.InteractionCell); + yield return Toils_Haul.PlaceHauledThingInCell(TargetIndex.A, null, false); + + // Stabilize patient + int duration = (int)(1f / this.pawn.GetStatValue(StatDefOf.MedicalTendSpeed, true) * baseTendDuration); + Toil waitToil = Toils_General.Wait(duration).WithProgressBarToilDelay(TargetIndex.A).PlaySustainerOrSound(SoundDefOf.Interact_Tend); + yield return waitToil; + Toil stabilizeToil = new Toil(); + stabilizeToil.initAction = delegate + { + float xp = (!Patient.RaceProps.Animal) ? 125f : 50f * Medicine.def.MedicineTendXpGainFactor; + pawn.skills.Learn(SkillDefOf.Medicine, xp); + foreach(Hediff curInjury in from x in Patient.health.hediffSet.GetHediffsTendable() orderby x.BleedRate descending select x) + { + if (curInjury.CanBeStabilizied()) + { + HediffComp_Stabilize comp = curInjury.TryGetComp(); + comp.Stabilize(pawn, Medicine); + break; + } + } + }; + stabilizeToil.defaultCompleteMode = ToilCompleteMode.Instant; + yield return stabilizeToil; + yield return Toils_Jump.Jump(waitToil); + } + } +} diff --git a/Source/CombatExtended/CombatExtended/Jobs/JobDriver_TakeFromOther.cs b/Source/CombatExtended/CombatExtended/Jobs/JobDriver_TakeFromOther.cs new file mode 100644 index 0000000000..ba9dfc2fcb --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Jobs/JobDriver_TakeFromOther.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Verse; +using Verse.AI; +using RimWorld; +using UnityEngine; + +namespace CombatExtended +{ + public class JobDriver_TakeFromOther : JobDriver + { + private TargetIndex thingInd = TargetIndex.A; + private TargetIndex sourceInd = TargetIndex.B; + private TargetIndex flagInd = TargetIndex.C; + + private Thing targetItem + { + get { + return CurJob.GetTarget(thingInd).Thing; + } + } + private Pawn takePawn + { + get { + return (Pawn)CurJob.GetTarget(sourceInd).Thing; + } + } + private bool doEquip + { + get + { + return CurJob.GetTarget(flagInd).HasThing; + } + } + + public override string GetReport() + { + string text = CE_JobDefOf.TakeFromOther.reportString; + text = text.Replace("FlagC", doEquip ? "CE_TakeFromOther_Equipping".Translate() : "CE_TakeFromOther_Taking".Translate()); + text = text.Replace("TargetA", targetItem.Label); + text = text.Replace("TargetB", takePawn.LabelShort); + return text; + } + + + protected override IEnumerable MakeNewToils() + { + this.FailOnDespawnedNullOrForbidden(sourceInd); + yield return Toils_Reserve.Reserve(sourceInd); + yield return Toils_Goto.GotoThing(sourceInd, PathEndMode.Touch); + yield return Toils_General.Wait(10); + yield return new Toil { + initAction = delegate + { + takePawn.inventory.innerContainer.TryTransferToContainer(targetItem, pawn.inventory.innerContainer, CurJob.count); + if (doEquip) + { + CompInventory compInventory = pawn.TryGetComp(); + if (compInventory != null) + compInventory.TrySwitchToWeapon((ThingWithComps)targetItem); + } + } + }; + } + } +} \ No newline at end of file diff --git a/Source/CombatExtended/CombatExtended/Jobs/JobDriver_UnloadYourInventory.cs b/Source/CombatExtended/CombatExtended/Jobs/JobDriver_UnloadYourInventory.cs new file mode 100644 index 0000000000..b1f06828e8 --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Jobs/JobDriver_UnloadYourInventory.cs @@ -0,0 +1,91 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using RimWorld; +using Verse; +using Verse.AI; + +namespace CombatExtended +{ + /// + /// This class gets used when a Pawn returning from a Caravan is unloading it's own inventory. + /// Class is mostly copied from Rimworld with adjustments to have it ask components of CombatExtended for what and how much to drop from the player's own invetory. + /// + public class JobDriver_UnloadYourInventory : JobDriver + { + private const TargetIndex ItemToHaulInd = TargetIndex.A; + + private const TargetIndex StoreCellInd = TargetIndex.B; + + private const int UnloadDuration = 10; + + private int amountToDrop; + + [DebuggerHidden] + protected override IEnumerable MakeNewToils() + { + yield return Toils_General.Wait(10); + yield return new Toil + { + initAction = delegate + { + Thing dropThing; + int dropCount; + if (!this.pawn.inventory.UnloadEverything || !this.pawn.GetAnythingForDrop(out dropThing, out dropCount)) + { + this.EndJobWith(JobCondition.Succeeded); + } + else + { + IntVec3 c; + if (!StoreUtility.TryFindStoreCellNearColonyDesperate(dropThing, this.pawn, out c)) + { + this.pawn.inventory.innerContainer.TryDrop(dropThing, this.pawn.Position, this.pawn.Map, ThingPlaceMode.Near, dropCount, out dropThing); + this.EndJobWith(JobCondition.Succeeded); + } + else + { + this.CurJob.SetTarget(TargetIndex.A, dropThing); + this.CurJob.SetTarget(TargetIndex.B, c); + amountToDrop = dropCount; + } + } + } + }; + yield return Toils_Reserve.Reserve(TargetIndex.B, 1); + yield return Toils_Goto.GotoCell(TargetIndex.B, PathEndMode.Touch); + yield return new Toil + { + initAction = delegate + { + Thing thing = this.CurJob.GetTarget(TargetIndex.A).Thing; + if (thing == null || !this.pawn.inventory.innerContainer.Contains(thing)) + { + this.EndJobWith(JobCondition.Incompletable); + return; + } + if (!this.pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation) || !thing.def.EverStoreable) + { + this.pawn.inventory.innerContainer.TryDrop(thing, this.pawn.Position, this.pawn.Map, ThingPlaceMode.Near, amountToDrop, out thing); + this.EndJobWith(JobCondition.Succeeded); + } + else + { + this.pawn.inventory.innerContainer.TryTransferToContainer(thing, this.pawn.carryTracker.innerContainer, amountToDrop, out thing); + this.CurJob.count = amountToDrop; + this.CurJob.SetTarget(TargetIndex.A, thing); + } + thing.SetForbidden(false, false); + + if (!this.pawn.HasAnythingForDrop()) + { + this.pawn.inventory.UnloadEverything = false; + } + } + }; + Toil carryToCell = Toils_Haul.CarryHauledThingToCell(TargetIndex.B); + yield return carryToCell; + yield return Toils_Haul.PlaceHauledThingInCell(TargetIndex.B, carryToCell, true); + } + } +} diff --git a/Source/CombatExtended/CombatExtended/Jobs/JobDriver_WaitKnockdown.cs b/Source/CombatExtended/CombatExtended/Jobs/JobDriver_WaitKnockdown.cs new file mode 100644 index 0000000000..7815ed8575 --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Jobs/JobDriver_WaitKnockdown.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using Verse.AI; +using UnityEngine; + +namespace CombatExtended +{ + public class JobDriver_WaitKnockdown : JobDriver_Wait + { + public override PawnPosture Posture + { + get + { + return PawnPosture.LayingAny; + } + } + } +} diff --git a/Source/CombatExtended/CombatExtended/Jobs/JobGiver_CheckReload.cs b/Source/CombatExtended/CombatExtended/Jobs/JobGiver_CheckReload.cs new file mode 100644 index 0000000000..18540a4411 --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Jobs/JobGiver_CheckReload.cs @@ -0,0 +1,209 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using RimWorld; +using UnityEngine; +using Verse; +using Verse.AI; + +namespace CombatExtended +{ + public class JobGiver_CheckReload : ThinkNode_JobGiver + { + #region Fields + + // lower priority = less likely to be done. Need to give this a priority below JobGiver_Update Loadout's high priority setting. + const float reloadPriority = 9.1f; // in JobGiver_UpdateLoadout, 9.2 is high priority, 3 is lower priority. + + #endregion Fields + + #region ThinkNode_JobGiver + + /// + /// Informs rimworld how important this job is relative to other potential jobs for the pawn. + /// + /// Pawn that this job is to be considered. + /// float value indicating importance of the job. + public override float GetPriority(Pawn pawn) + { + // need to generate the job here which involves replicating some code from TryStartReload... + + // this MUST not even try to do anything if the inventory state isn't in a good state. + // There are 3 states that JobGiver_UpdateLoadout can end in and I need to know which of those 3 states are active. + + // would be nice to communicate with JobGiver_UpdateLoadout but it will suffice to set our priority below theirs. + + ThingWithComps ignore1; + AmmoDef ignore2; + if (!pawn.Drafted && DoReloadCheck(pawn, out ignore1, out ignore2)) + return reloadPriority; + + return 0.0f; + } + + /// + /// If RimWorld decides the pawn should do this job, this is called to get the pawn working on it. + /// + /// Pawn that the job is supposed to take place on. + /// Job that the pawn is to be working on. + protected override Job TryGiveJob(Pawn pawn) + { + ThingWithComps gun; + AmmoDef ammo; + Job reloadJob = null; + + if (DoReloadCheck(pawn, out gun, out ammo)) + { + CompAmmoUser comp = gun.TryGetComp(); + CompInventory compInventory = pawn.TryGetComp(); + // we relied on DoReloadCheck() to do error checking of many variables. + + if (!comp.TryUnload()) return null; // unload the weapon or stop trying if there was a problem. + + // change ammo type if necessary. + if (comp.useAmmo && comp.currentAmmo != ammo) + comp.SelectedAmmo = ammo; + + // Get the reload job from the comp. + reloadJob = comp.TryMakeReloadJob(); + } + return reloadJob; + } + + #endregion + + #region Methods + + /* Rough Algorithm + * Need Things so the collection of ammo users that use magazines. Also need a collection of ammo (ThingDef is OK here). + * For each weapon (that fits above), + * -If we have no ammo in inventory that the gun is loaded with, check loadouts/holdtracker for a clip's worth of ammo that the gun contains. + * --Find ammo the gun uses that we have a clip's worth in inventory (should check it against loadout/holdtracker as well) + * -If weapon is low on ammo and we have enough in inventory to fill it up. + * + * If either of the above are true, trigger a reload. + */ + /// + /// Check's the pawn's equipment and inventory for weapons that could use a reload. + /// + /// Pawn to check the equipment and inventory of. + /// Thing weapon which needs to be reloaded. + /// AmmoDef ammo to reload the gun with. + /// Bool value indicating if the job needs to be done. + private bool DoReloadCheck(Pawn pawn, out ThingWithComps reloadWeapon, out AmmoDef reloadAmmo) + { + reloadWeapon = null; + reloadAmmo = null; + + // First need to create the collections that will be searched. + List guns = new List(); + CompInventory inventory = pawn.TryGetComp(); + CompAmmoUser tmpComp; + Loadout loadout = pawn.GetLoadout(); + bool pawnHasLoadout = loadout != null && !loadout.Slots.NullOrEmpty(); + + if (inventory == null) + return false; // There isn't any work to do since the pawn doesn't have a CE Inventory. + + if ((tmpComp = pawn.equipment?.Primary?.TryGetComp()) != null && tmpComp.hasMagazine) + guns.Add(pawn.equipment.Primary); + + // CompInventory doesn't track equipment and it's desired to check the pawn's equipped weapon before inventory items so need to copy stuff from Inventory Cache. + guns.AddRange(inventory.rangedWeaponList.Where(t => t.TryGetComp() != null && t.GetComp().hasMagazine)); + + if (guns.NullOrEmpty()) + return false; // There isn't any work to do since the pawn doesn't have any ammo using guns. + + // look at each gun... + foreach (ThingWithComps gun in guns) + { + // Get key stats of the weapon. + tmpComp = gun.TryGetComp(); + AmmoDef ammoType = tmpComp.currentAmmo; + int ammoAmount = tmpComp.curMagCount; + int magazineSize = tmpComp.Props.magazineSize; + + // Is the gun loaded with ammo not in a Loadout/HoldTracker? + if (tmpComp.useAmmo && pawnHasLoadout && !TrackingSatisfied(pawn, ammoType, magazineSize)) + { + // Do we have ammo in the inventory that the gun uses which satisfies requirements? (expensive) + AmmoDef matchAmmo = tmpComp.Props.ammoSet.ammoTypes + .Where(al => al.ammo != ammoType) + .Select(al => al.ammo) + .FirstOrDefault(ad => TrackingSatisfied(pawn, ad, magazineSize) + && inventory.AmmoCountOfDef(ad) >= magazineSize); + + if (matchAmmo != null) + { + reloadWeapon = gun; + reloadAmmo = matchAmmo; + return true; + } + } + + // Is the gun low on ammo? + if (tmpComp.curMagCount < magazineSize) + { + // Do we have enough ammo in the inventory to top it off? + if (!tmpComp.useAmmo || inventory.AmmoCountOfDef(ammoType) >= (magazineSize - tmpComp.curMagCount)) + { + reloadWeapon = gun; + reloadAmmo = ammoType; + return true; + //} else { // (ProfoundDarkness) I think the idea of this branch was that the JobGiver might initiate fetching ammo but it actually runs AFTER the one that fetches ammo for loadout. + // There wasn't enough in the inventory to top it off. At this point we know the loadout is satisfied for this ammo... + // We could do a more strict check to see if the pawn's loadout is satisfied to pick up ammo and if not swap to another ammo...? + } + } + + } + + return false; + } + + /// + /// Basically counts the amount of ThingDef that a loadout can have. Assumes Pawn has a Loadout (caller checked this already). + /// + /// Pawn who's loadout and holdtracker is to be inspected. + /// ThingDef to match + /// int amount of ThingDef desired to be covered by Loadout/HoldTracker + /// int amount of that def that can be had. + private bool TrackingSatisfied(Pawn pawn, ThingDef def, int amount) + { + // first check loadouts... + Loadout loadout = pawn.GetLoadout(); + + foreach (LoadoutSlot slot in loadout.Slots) + { + if (slot.thingDef != null) + { + if (slot.thingDef == def) + amount -= slot.count; + } else if (slot.genericDef != null) + { + if (slot.genericDef.lambda(def)) + amount -= slot.count; + } + if (amount <= 0) + return true; + } + + // if we got here, also check holdRecords. + List records = pawn.GetHoldRecords(); + + if (!records.NullOrEmpty()) + { + foreach (HoldRecord rec in records) + { + if (rec.thingDef == def) + amount -= rec.count; + } + } + + return false; + } + + #endregion Methods + } +} \ No newline at end of file diff --git a/Source/CombatRealism/CombatExtended/Jobs/JobGiver_ConfigurableHostilityResponse.cs b/Source/CombatExtended/CombatExtended/Jobs/JobGiver_ConfigurableHostilityResponse.cs similarity index 83% rename from Source/CombatRealism/CombatExtended/Jobs/JobGiver_ConfigurableHostilityResponse.cs rename to Source/CombatExtended/CombatExtended/Jobs/JobGiver_ConfigurableHostilityResponse.cs index a608799def..1425c6de95 100644 --- a/Source/CombatRealism/CombatExtended/Jobs/JobGiver_ConfigurableHostilityResponse.cs +++ b/Source/CombatExtended/CombatExtended/Jobs/JobGiver_ConfigurableHostilityResponse.cs @@ -4,6 +4,7 @@ using UnityEngine; using Verse; using Verse.AI; +using System; namespace CombatExtended { @@ -47,7 +48,7 @@ private Job TryGetAttackNearbyEnemyJob(Pawn pawn) num = Mathf.Clamp(pawn.equipment.PrimaryEq.PrimaryVerb.verbProps.range * 0.66f, 2f, 20f); } float maxDist = num; - Thing thing = AttackTargetFinder.BestAttackTarget(pawn, TargetScanFlags.NeedLOSToPawns | TargetScanFlags.NeedLOSToNonPawns | TargetScanFlags.NeedReachable | TargetScanFlags.NeedThreat, null, 0f, maxDist, default(IntVec3), 3.40282347E+38f, false); + Thing thing = (Thing)AttackTargetFinder.BestAttackTarget(pawn, TargetScanFlags.NeedLOSToPawns | TargetScanFlags.NeedLOSToNonPawns | TargetScanFlags.NeedReachableIfCantHitFromMyPos | TargetScanFlags.NeedThreat, null, 0f, maxDist, default(IntVec3), 3.40282347E+38f, false); // TODO evaluate if this is necessary? Pawn o = thing as Pawn; if (o != null) if @@ -67,25 +68,19 @@ private Job TryGetAttackNearbyEnemyJob(Pawn pawn) // Check for reload before attacking Verb verb = pawn.TryGetAttackVerb(); - if (pawn.equipment.PrimaryEq != null && verb != null && verb == pawn.equipment.PrimaryEq.PrimaryVerb) + if (pawn.equipment.Primary != null && pawn.equipment.PrimaryEq != null && verb != null && verb == pawn.equipment.PrimaryEq.PrimaryVerb) { - if (pawn.equipment.Primary != null) + CompAmmoUser compAmmo = pawn.equipment.Primary.TryGetComp(); + if (compAmmo != null && !compAmmo.canBeFiredNow) { - CompAmmoUser compAmmo = pawn.equipment.Primary.TryGetComp(); - if (compAmmo != null) - { - if (!compAmmo.hasMagazine) - { - if (compAmmo.useAmmo && !compAmmo.hasAmmo) - return new Job(JobDefOf.AttackMelee, thing); - } - else if (compAmmo.curMagCount <= 0) - { - Job job = new Job(CE_JobDefOf.ReloadWeapon, pawn, pawn.equipment.Primary); - if (job != null) - return job; - } - } + if (compAmmo.hasAmmo) + { + Job job = new Job(CE_JobDefOf.ReloadWeapon, pawn, pawn.equipment.Primary); + if (job != null) + return job; + } + + return new Job(JobDefOf.AttackMelee, thing); } } diff --git a/Source/CombatRealism/CombatExtended/Jobs/JobGiver_HunkerDown.cs b/Source/CombatExtended/CombatExtended/Jobs/JobGiver_HunkerDown.cs similarity index 81% rename from Source/CombatRealism/CombatExtended/Jobs/JobGiver_HunkerDown.cs rename to Source/CombatExtended/CombatExtended/Jobs/JobGiver_HunkerDown.cs index a1163c5d6d..8ce50f2461 100644 --- a/Source/CombatRealism/CombatExtended/Jobs/JobGiver_HunkerDown.cs +++ b/Source/CombatExtended/CombatExtended/Jobs/JobGiver_HunkerDown.cs @@ -8,7 +8,6 @@ class JobGiver_HunkerDown : ThinkNode_JobGiver { protected override Job TryGiveJob(Pawn pawn) { - //if (pawn.TryGetComp().isHunkering && pawn.GetPosture() != PawnPosture.Standing) //{ // return null; @@ -18,11 +17,7 @@ protected override Job TryGiveJob(Pawn pawn) { return null; } - - return new Job(CE_JobDefOf.HunkerDown, pawn) - { -// playerForced = true, - }; + return new Job(CE_JobDefOf.HunkerDown, pawn); } } } diff --git a/Source/CombatExtended/CombatExtended/Jobs/JobGiver_SquadDuty.cs b/Source/CombatExtended/CombatExtended/Jobs/JobGiver_SquadDuty.cs new file mode 100644 index 0000000000..c2bc85bdb9 --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Jobs/JobGiver_SquadDuty.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using Verse.AI; +using UnityEngine; + +namespace CombatExtended +{ + public class JobGiver_SquadDuty : ThinkNode_JobGiver + { + protected override Job TryGiveJob(Pawn pawn) + { + CompSquadBrain comp = pawn.TryGetComp(); + if (comp == null) + { + Log.Error("CE tried running JobGiver_SquadDuty on " + pawn.ToString() + " without CompSquadBrain"); + return null; + } + Job job = comp.squad.GetJobFor(pawn); + //if (job == null) job = new Job(JobDefOf.WaitCombat, pawn.Position); + return job; + } + } +} diff --git a/Source/CombatRealism/CombatExtended/Jobs/JobGiver_TakeAndEquip.cs b/Source/CombatExtended/CombatExtended/Jobs/JobGiver_TakeAndEquip.cs similarity index 66% rename from Source/CombatRealism/CombatExtended/Jobs/JobGiver_TakeAndEquip.cs rename to Source/CombatExtended/CombatExtended/Jobs/JobGiver_TakeAndEquip.cs index 673addf348..c793558816 100644 --- a/Source/CombatRealism/CombatExtended/Jobs/JobGiver_TakeAndEquip.cs +++ b/Source/CombatExtended/CombatExtended/Jobs/JobGiver_TakeAndEquip.cs @@ -16,8 +16,8 @@ private enum WorkPriority Unloading, LowAmmo, Weapon, - Ammo, - Apparel + Ammo + //Apparel } private WorkPriority GetPriorityWork(Pawn pawn) @@ -38,7 +38,7 @@ private WorkPriority GetPriorityWork(Pawn pawn) { return WorkPriority.None; } - if (pawn.jobs.curJob != null && pawn.jobs.curJob.def == JobDefOf.Tame) + if (pawn.CurJob != null && pawn.CurJob.def == JobDefOf.Tame) { return WorkPriority.None; } @@ -55,10 +55,10 @@ private WorkPriority GetPriorityWork(Pawn pawn) if (pawn.equipment.Primary != null && primaryammouser != null) { int ammocount = 0; - foreach (ThingDef ammoDef in primaryammouser.Props.ammoSet.ammoTypes) + foreach (AmmoLink link in primaryammouser.Props.ammoSet.ammoTypes) { Thing ammoThing; - ammoThing = pawn.TryGetComp().ammoList.Find(thing => thing.def == ammoDef); + ammoThing = pawn.TryGetComp().ammoList.Find(thing => thing.def == link.ammo); if (ammoThing != null) { ammocount += ammoThing.stackCount; @@ -85,7 +85,7 @@ private WorkPriority GetPriorityWork(Pawn pawn) } } } - + /* if (!pawn.Faction.IsPlayer && pawn.equipment.Primary != null && !PawnUtility.EnemiesAreNearby(pawn, 30, true) || (!pawn.apparel.BodyPartGroupIsCovered(BodyPartGroupDefOf.Torso) @@ -93,19 +93,22 @@ private WorkPriority GetPriorityWork(Pawn pawn) { return WorkPriority.Apparel; } + */ - else return WorkPriority.None; + return WorkPriority.None; } public override float GetPriority(Pawn pawn) { + if ((!Controller.settings.AutoTakeAmmo && pawn.IsColonist) || !Controller.settings.EnableAmmoSystem) return 0f; + var priority = GetPriorityWork(pawn); if (priority == WorkPriority.Unloading) return 9.2f; else if (priority == WorkPriority.LowAmmo) return 9f; else if (priority == WorkPriority.Weapon) return 8f; else if (priority == WorkPriority.Ammo) return 6f; - else if (priority == WorkPriority.Apparel) return 5f; + //else if (priority == WorkPriority.Apparel) return 5f; else if(priority == WorkPriority.None) return 0f; TimeAssignmentDef assignment = (pawn.timetable != null) ? pawn.timetable.CurrentAssignment : TimeAssignmentDefOf.Anything; @@ -120,6 +123,11 @@ public override float GetPriority(Pawn pawn) protected override Job TryGiveJob(Pawn pawn) { + if (!Controller.settings.EnableAmmoSystem || !Controller.settings.AutoTakeAmmo) + { + return null; + } + if (!pawn.RaceProps.Humanlike || (pawn.story != null && pawn.story.WorkTagIsDisabled(WorkTags.Violent))) { return null; @@ -136,46 +144,39 @@ protected override Job TryGiveJob(Pawn pawn) Log.Message(pawn.ToString() + "capacityBulk: " + pawn.TryGetComp().capacityBulk.ToString()); Log.Message(pawn.ToString() + "currentBulk: " + pawn.TryGetComp().currentBulk.ToString()); */ - - var brawler = pawn.story.traits.HasTrait(TraitDefOf.Brawler); + + var brawler = (pawn.story != null && pawn.story.traits != null && pawn.story.traits.HasTrait(TraitDefOf.Brawler)); CompInventory inventory = pawn.TryGetComp(); - CompAmmoUser ammouser = pawn.TryGetComp(); - CompAmmoUser primaryammouser = pawn.equipment.Primary.TryGetComp(); + bool hasPrimary = (pawn.equipment != null && pawn.equipment.Primary != null); + CompAmmoUser primaryammouser = hasPrimary ? pawn.equipment.Primary.TryGetComp() : null; + if (inventory != null) { - Room room = RoomQuery.RoomAtFast(pawn.Position, pawn.Map); // Prefer ranged weapon in inventory - if (!pawn.Faction.IsPlayer && pawn.equipment != null) + if (!pawn.Faction.IsPlayer && hasPrimary && pawn.equipment.Primary.def.IsMeleeWeapon && !brawler) { - if (pawn.equipment.Primary != null && pawn.equipment.Primary.def.IsMeleeWeapon && !brawler - && (pawn.skills.GetSkill(SkillDefOf.Shooting).Level >= pawn.skills.GetSkill(SkillDefOf.Melee).Level || pawn.skills.GetSkill(SkillDefOf.Shooting).Level >= 6)) + if ((pawn.skills.GetSkill(SkillDefOf.Shooting).Level >= pawn.skills.GetSkill(SkillDefOf.Melee).Level + || pawn.skills.GetSkill(SkillDefOf.Shooting).Level >= 6)) { - ThingWithComps InvListGun3 = inventory.rangedWeaponList.Find(thing => thing.TryGetComp() != null); + ThingWithComps InvListGun3 = inventory.rangedWeaponList.Find(thing => thing.TryGetComp() != null && thing.TryGetComp().hasAmmoOrMagazine); if (InvListGun3 != null) { - Thing ammoInvListGun3 = null; - foreach (ThingDef InvListGunDef3 in InvListGun3.TryGetComp().Props.ammoSet.ammoTypes) - { - ammoInvListGun3 = inventory.ammoList.Find(thing => thing.def == InvListGunDef3); - break; - } - if (ammoInvListGun3 != null) - { - inventory.TrySwitchToWeapon(InvListGun3); - } + inventory.TrySwitchToWeapon(InvListGun3); } } } + // Drop excess ranged weapon - if (!pawn.Faction.IsPlayer && pawn.equipment.Primary != null && primaryammouser != null && GetPriorityWork(pawn) == WorkPriority.Unloading && inventory.rangedWeaponList.Count >= 1) + if (!pawn.Faction.IsPlayer && primaryammouser != null && GetPriorityWork(pawn) == WorkPriority.Unloading && inventory.rangedWeaponList.Count >= 1) { - Thing ListGun = inventory.rangedWeaponList.Find(thing => pawn.equipment != null && pawn.equipment.Primary != null && thing.TryGetComp() != null && thing.def != pawn.equipment.Primary.def); + Thing ListGun = inventory.rangedWeaponList.Find(thing => thing.TryGetComp() != null && thing.def != pawn.equipment.Primary.def); if (ListGun != null) { - Thing ammoListGun = null; - foreach (ThingDef ListGunDef in ListGun.TryGetComp().Props.ammoSet.ammoTypes) + Thing ammoListGun = null; + if (!ListGun.TryGetComp().hasAmmoOrMagazine) + foreach (AmmoLink link in ListGun.TryGetComp().Props.ammoSet.ammoTypes) { - if (inventory.ammoList.Find(thing => thing.def == ListGunDef) == null) + if (inventory.ammoList.Find(thing => thing.def == link.ammo) == null) { ammoListGun = ListGun; break; @@ -192,24 +193,24 @@ protected override Job TryGiveJob(Pawn pawn) } } } + // Find and drop not need ammo from inventory - if (!pawn.Faction.IsPlayer && inventory.ammoList.Count > 1 && GetPriorityWork(pawn) == WorkPriority.Unloading) + if (!pawn.Faction.IsPlayer && hasPrimary && inventory.ammoList.Count > 1 && GetPriorityWork(pawn) == WorkPriority.Unloading) { - Thing WrongammoThing = null; - foreach (ThingDef WrongammoDef in primaryammouser.Props.ammoSet.ammoTypes) - { - WrongammoThing = inventory.ammoList.Find(thing => thing.def != WrongammoDef); - break; - } + Thing WrongammoThing = null; + WrongammoThing = primaryammouser != null + ? inventory.ammoList.Find(thing => !primaryammouser.Props.ammoSet.ammoTypes.Any(a => a.ammo == thing.def)) + : inventory.ammoList.RandomElement(); + if (WrongammoThing != null) { - Thing InvListGun = inventory.rangedWeaponList.Find(thing => pawn.equipment != null && pawn.equipment.Primary != null && thing.TryGetComp() != null && thing.def != pawn.equipment.Primary.def); + Thing InvListGun = inventory.rangedWeaponList.Find(thing => hasPrimary && thing.TryGetComp() != null && thing.def != pawn.equipment.Primary.def); if (InvListGun != null) { Thing ammoInvListGun = null; - foreach (ThingDef InvListGunDef in InvListGun.TryGetComp().Props.ammoSet.ammoTypes) + foreach (AmmoLink link in InvListGun.TryGetComp().Props.ammoSet.ammoTypes) { - ammoInvListGun = inventory.ammoList.Find(thing => thing.def == InvListGunDef); + ammoInvListGun = inventory.ammoList.Find(thing => thing.def == link.ammo); break; } if (ammoInvListGun != null && ammoInvListGun != WrongammoThing) @@ -233,16 +234,20 @@ protected override Job TryGiveJob(Pawn pawn) } } } + + Room room = RegionAndRoomQuery.RoomAtFast(pawn.Position, pawn.Map); + // Find weapon in inventory and try to switch if any ammo in inventory. - if (GetPriorityWork(pawn) == WorkPriority.Weapon && pawn.equipment.Primary == null) + if (GetPriorityWork(pawn) == WorkPriority.Weapon && !hasPrimary) { ThingWithComps InvListGun2 = inventory.rangedWeaponList.Find(thing => thing.TryGetComp() != null); + if (InvListGun2 != null) { Thing ammoInvListGun2 = null; - foreach (ThingDef InvListGunDef2 in InvListGun2.TryGetComp().Props.ammoSet.ammoTypes) + foreach (AmmoLink link in InvListGun2.TryGetComp().Props.ammoSet.ammoTypes) { - ammoInvListGun2 = inventory.ammoList.Find(thing => thing.def == InvListGunDef2); + ammoInvListGun2 = inventory.ammoList.Find(thing => thing.def == link.ammo); break; } if (ammoInvListGun2 != null) @@ -250,87 +255,117 @@ protected override Job TryGiveJob(Pawn pawn) inventory.TrySwitchToWeapon(InvListGun2); } } + // Find weapon with near ammo for ai. - if (!pawn.Faction.IsPlayer && pawn.equipment.Primary == null) + if (!pawn.Faction.IsPlayer) { Predicate validatorWS = (Thing w) => w.def.IsWeapon - && w.MarketValue > 500 && pawn.CanReserve(w, 1) - && pawn.CanReach(w, PathEndMode.Touch, Danger.Deadly, true) - && (!pawn.Faction.HostileTo(Faction.OfPlayer) && pawn.Map.areaManager.Home[w.Position]) || (pawn.Faction.HostileTo(Faction.OfPlayer)) - && (w.Position.DistanceToSquared(pawn.Position) < 15f || room == RoomQuery.RoomAtFast(w.Position, pawn.Map)); - List weapon = ( + && w.MarketValue > 500 && pawn.CanReserve(w, 1) + && (DangerInPosRadius(pawn, w.Position, pawn.Map, 30f).Count() <= 0 + ? pawn.Position.InHorDistOf(w.Position, 25f) + : pawn.Position.InHorDistOf(w.Position, 6f)) + && pawn.CanReach(w, PathEndMode.Touch, Danger.Deadly, true) + && (pawn.Faction.HostileTo(Faction.OfPlayer) || pawn.Faction == Faction.OfPlayer || !pawn.Map.areaManager.Home[w.Position]); + + // generate a list of all weapons (this includes melee weapons) + List allWeapons = ( from w in pawn.Map.listerThings.ThingsInGroup(ThingRequestGroup.HaulableAlways) where validatorWS(w) orderby w.MarketValue - w.Position.DistanceToSquared(pawn.Position) * 2f descending select w ).ToList(); - if (weapon != null && weapon.Count > 0) + + // now just get the ranged weapons out... + List rangedWeapons = allWeapons.Where(w => w.def.IsRangedWeapon).ToList(); + + if (!rangedWeapons.NullOrEmpty()) { - foreach (Thing thing in weapon) + foreach (Thing thing in rangedWeapons) { - List thingDefAmmoList = (from ThingDef g in thing.TryGetComp().Props.ammoSet.ammoTypes - select g).ToList(); - Predicate validatorA = (Thing t) => t.def.category == ThingCategory.Item - && t is AmmoThing && pawn.CanReserve(t, 1) - && pawn.CanReach(t, PathEndMode.Touch, Danger.Deadly, true) - && (t.Position.DistanceToSquared(pawn.Position) < 20f || room == RoomQuery.RoomAtFast(t.Position, pawn.Map)); - List thingAmmoList = ( - from t in pawn.Map.listerThings.ThingsInGroup(ThingRequestGroup.HaulableAlways) - where validatorA(t) - select t - ).ToList(); - if (thingAmmoList.Count > 0 && thingDefAmmoList.Count > 0) + if (thing.TryGetComp() == null) { - foreach (Thing th in thingAmmoList) + // pickup a non-CE ranged weapon... + int numToThing = 0; + if (inventory.CanFitInInventory(thing, out numToThing)) { - foreach (ThingDef thd in thingDefAmmoList) + return new Job(JobDefOf.Equip, thing) { - if (thd == th.def) + checkOverrideOnExpire = true, + expiryInterval = 100 + }; + } + } else { + // pickup a CE ranged weapon... + List thingDefAmmoList = thing.TryGetComp().Props.ammoSet.ammoTypes.Select(g => g.ammo as ThingDef).ToList(); + + Predicate validatorA = (Thing t) => t.def.category == ThingCategory.Item + && t is AmmoThing && pawn.CanReserve(t, 1) + && (DangerInPosRadius(pawn, t.Position, pawn.Map, 30f).Count() <= 0 + ? pawn.Position.InHorDistOf(t.Position, 25f) + : pawn.Position.InHorDistOf(t.Position, 6f)) + && pawn.CanReach(t, PathEndMode.Touch, Danger.Deadly, true) + && (pawn.Faction.HostileTo(Faction.OfPlayer) || pawn.Faction == Faction.OfPlayer || !pawn.Map.areaManager.Home[t.Position]); + + List thingAmmoList = ( + from t in pawn.Map.listerThings.ThingsInGroup(ThingRequestGroup.HaulableAlways) + where validatorA(t) + select t + ).ToList(); + + if (thingAmmoList.Count > 0 && thingDefAmmoList.Count > 0) + { + int desiredStackSize = thing.TryGetComp().Props.magazineSize * 2; + Thing th = thingAmmoList.FirstOrDefault(x => thingDefAmmoList.Contains(x.def) && x.stackCount > desiredStackSize); + if (th != null) + { + int numToThing = 0; + if (inventory.CanFitInInventory(thing, out numToThing)) { - int ammothingcount = 0; - foreach (ThingDef ammoDef in thing.TryGetComp().Props.ammoSet.ammoTypes) - { - ammothingcount += th.stackCount; - } - if (ammothingcount > thing.TryGetComp().Props.magazineSize * 2) + return new Job(JobDefOf.Equip, thing) { - int numToThing = 0; - if (inventory.CanFitInInventory(thing, out numToThing)) - { - if (thing.Position == pawn.Position || thing.Position.AdjacentToCardinal(pawn.Position)) - { - return new Job(JobDefOf.Equip, thing) - { - checkOverrideOnExpire = true, - expiryInterval = 100, - canBash = true, - locomotionUrgency = LocomotionUrgency.Sprint - }; - } - return GotoForce(pawn, thing, PathEndMode.Touch); - } - } + checkOverrideOnExpire = true, + expiryInterval = 100 + }; } } - } - } + } + } } } - } + + // else if no ranged weapons with nearby ammo was found, lets consider a melee weapon. + if (allWeapons != null && allWeapons.Count > 0) + { + // since we don't need to worry about ammo, just pick one. + Thing meleeWeapon = allWeapons.FirstOrDefault(w => !w.def.IsRangedWeapon && w.def.IsMeleeWeapon); + + if (meleeWeapon != null) + { + return new Job(JobDefOf.Equip, meleeWeapon) + { + checkOverrideOnExpire = true, + expiryInterval = 100 + }; + } + } + } } + // Find ammo if ((GetPriorityWork(pawn) == WorkPriority.Ammo || GetPriorityWork(pawn) == WorkPriority.LowAmmo) - && pawn.equipment != null && pawn.equipment.Primary != null && primaryammouser != null) + && primaryammouser != null) { - List curAmmoList = (from ThingDef g in primaryammouser.Props.ammoSet.ammoTypes - select g).ToList(); + List curAmmoList = (from AmmoLink g in primaryammouser.Props.ammoSet.ammoTypes + select g.ammo as ThingDef).ToList(); + if (curAmmoList.Count > 0) { Predicate validator = (Thing t) => t is AmmoThing && pawn.CanReserve(t, 1) - && pawn.CanReach(t, PathEndMode.Touch, Danger.Deadly, true) - && ((pawn.Faction.IsPlayer && !ForbidUtility.IsForbidden(t, pawn)) - || (!pawn.Faction.IsPlayer && (!pawn.Faction.HostileTo(Faction.OfPlayer) && pawn.Map.areaManager.Home[t.Position]) || (pawn.Faction.HostileTo(Faction.OfPlayer)))) - && (t.Position.DistanceToSquared(pawn.Position) < 20f || room == RoomQuery.RoomAtFast(t.Position, pawn.Map)); + && pawn.CanReach(t, PathEndMode.Touch, Danger.Deadly, true) + && ((pawn.Faction.IsPlayer && !ForbidUtility.IsForbidden(t, pawn)) || (!pawn.Faction.IsPlayer && DangerInPosRadius(pawn, t.Position, Find.VisibleMap, 30f).Count() <= 0 + ? pawn.Position.InHorDistOf(t.Position, 25f) + : pawn.Position.InHorDistOf(t.Position, 6f))) + && (pawn.Faction.HostileTo(Faction.OfPlayer) || pawn.Faction == Faction.OfPlayer || !pawn.Map.areaManager.Home[t.Position]); List curThingList = ( from t in pawn.Map.listerThings.ThingsInGroup(ThingRequestGroup.HaulableAlways) where validator(t) @@ -375,22 +410,16 @@ select t } else { - if (th.Position == pawn.Position || th.Position.AdjacentToCardinal(pawn.Position)) + int numToCarry = 0; + if (inventory.CanFitInInventory(th, out numToCarry)) { - int numToCarry = 0; - if (inventory.CanFitInInventory(th, out numToCarry)) + return new Job(JobDefOf.TakeInventory, th) { - return new Job(JobDefOf.TakeInventory, th) - { - count = Mathf.RoundToInt(numToCarry * 0.8f), - expiryInterval = 150, - checkOverrideOnExpire = true, - canBash = true, - locomotionUrgency = LocomotionUrgency.Sprint - }; - } + count = Mathf.RoundToInt(numToCarry * 0.8f), + expiryInterval = 150, + checkOverrideOnExpire = true + }; } - return GotoForce(pawn, th, PathEndMode.Touch); } } } @@ -398,6 +427,7 @@ select t } } } + /* if (!pawn.Faction.IsPlayer && pawn.apparel != null && GetPriorityWork(pawn) == WorkPriority.Apparel) { if (!pawn.apparel.BodyPartGroupIsCovered(BodyPartGroupDefOf.Torso)) @@ -410,8 +440,7 @@ select t { return new Job(JobDefOf.Wear, apparel) { - ignoreForbidden = true, - locomotionUrgency = LocomotionUrgency.Sprint + ignoreForbidden = true }; } } @@ -426,13 +455,11 @@ select t { return new Job(JobDefOf.Wear, apparel2) { - ignoreForbidden = true, - locomotionUrgency = LocomotionUrgency.Sprint + ignoreForbidden = true }; } } } - /* if (!pawn.apparel.BodyPartGroupIsCovered(BodyPartGroupDefOf.FullHead)) { Apparel apparel3 = this.FindGarmentCoveringPart(pawn, BodyPartGroupDefOf.FullHead); @@ -449,16 +476,17 @@ select t } } } - */ } + */ return null; } return null; } + /* private static Job GotoForce(Pawn pawn, LocalTargetInfo target, PathEndMode pathEndMode) { - using (PawnPath pawnPath = pawn.Map.pathFinder.FindPath(pawn.Position, target, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.PassAnything, false), pathEndMode)) + using (PawnPath pawnPath = pawn.Map.pathFinder.FindPath(pawn.Position, target, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.PassAllDestroyableThings, false), pathEndMode)) { IntVec3 cellBeforeBlocker; Thing thing = pawnPath.FirstBlockingBuilding(out cellBeforeBlocker, pawn); @@ -490,13 +518,14 @@ private static Job GotoForce(Pawn pawn, LocalTargetInfo target, PathEndMode path return MeleeOrWaitJob(pawn, thing, cellBeforeBlocker); } } + */ private static bool Unload(Pawn pawn) { var inv = pawn.TryGetComp(); if (inv != null && !pawn.Faction.IsPlayer - && (pawn.jobs.curJob != null && pawn.jobs.curJob.def != JobDefOf.Steal) + && (pawn.CurJob != null && pawn.CurJob.def != JobDefOf.Steal) && ((inv.capacityWeight - inv.currentWeight < 3f) || (inv.capacityBulk - inv.currentBulk < 4f))) { @@ -505,6 +534,11 @@ private static bool Unload(Pawn pawn) else return false; } + private static IEnumerable DangerInPosRadius(Pawn pawn, IntVec3 position, Map map, float distance) + { + return Enumerable.Where(map.mapPawns.AllPawns, (p => p.Position.InHorDistOf(position, distance) && !p.RaceProps.Animal && !p.Downed && !p.Dead && FactionUtility.HostileTo(p.Faction, pawn.Faction))); + } + private static Job MeleeOrWaitJob(Pawn pawn, Thing blocker, IntVec3 cellBeforeBlocker) { if (!pawn.CanReserve(blocker, 1)) @@ -519,12 +553,13 @@ private static Job MeleeOrWaitJob(Pawn pawn, Thing blocker, IntVec3 cellBeforeBl }; } + /* private Apparel FindGarmentCoveringPart(Pawn pawn, BodyPartGroupDef bodyPartGroupDef) { Room room = pawn.GetRoom(); Predicate validator = (Thing t) => pawn.CanReserve(t, 1) && pawn.CanReach(t, PathEndMode.Touch, Danger.Deadly, true) - && (t.Position.DistanceToSquared(pawn.Position) < 12f || room == RoomQuery.RoomAtFast(t.Position, t.Map)); + && (t.Position.DistanceToSquared(pawn.Position) < 12f || room == RegionAndRoomQuery.RoomAtFast(t.Position, t.Map)); List aList = ( from t in pawn.Map.listerThings.ThingsInGroup(ThingRequestGroup.Apparel) orderby t.MarketValue - t.Position.DistanceToSquared(pawn.Position) * 2f descending @@ -541,5 +576,6 @@ select t } return null; } + */ } } diff --git a/Source/CombatExtended/CombatExtended/Jobs/JobGiver_UpdateLoadout.cs b/Source/CombatExtended/CombatExtended/Jobs/JobGiver_UpdateLoadout.cs new file mode 100644 index 0000000000..ace9e234db --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Jobs/JobGiver_UpdateLoadout.cs @@ -0,0 +1,297 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using RimWorld; +using UnityEngine; +using Verse; +using Verse.AI; + +namespace CombatExtended +{ + public class JobGiver_UpdateLoadout : ThinkNode_JobGiver + { + #region InnerClasses + private enum ItemPriority : byte + { + None, + Low, + LowStock, + Proximity + } + #endregion + + #region Fields + private const int proximitySearchRadius = 20; + private const int maximumSearchRadius = 80; + private const int ticksBeforeDropRaw = 40000; + #endregion + + #region Methods + /// + /// Gets a priority value of how important it is for a pawn to do pickup/drop activities. + /// + /// Pawn to fetch priority for + /// float indicating priority of pickup/drop job + public override float GetPriority(Pawn pawn) + { + if (pawn.HasExcessThing()) + { + return 9.2f; + } + ItemPriority priority; + Thing unused; + int i; + Pawn carriedBy; + LoadoutSlot slot = GetPrioritySlot(pawn, out priority, out unused, out i, out carriedBy); + if (slot == null) + { + return 0f; + } + if (priority == ItemPriority.Low) return 3f; + + TimeAssignmentDef assignment = (pawn.timetable != null) ? pawn.timetable.CurrentAssignment : TimeAssignmentDefOf.Anything; + if (assignment == TimeAssignmentDefOf.Sleep) return 3f; + + return 9.2f; + } + + /// + /// This starts the work of finding something lacking that the pawn should pickup. + /// + /// Pawn who's inventory and loadout should be considered. + /// Priority value for how important doing this job is. + /// The thing found to be picked up. + /// The amount of closestThing to pickup. Already checked if inventory can hold it. + /// If unable to find something on the ground to pickup, the pawn (pack animal/prisoner) which has the item to take. + /// LoadoutSlot which has something that can be picked up. + private LoadoutSlot GetPrioritySlot(Pawn pawn, out ItemPriority priority, out Thing closestThing, out int count, out Pawn carriedBy) + { + priority = ItemPriority.None; + LoadoutSlot slot = null; + closestThing = null; + count = 0; + carriedBy = null; + + CompInventory inventory = pawn.TryGetComp(); + if (inventory != null && inventory.container != null) + { + Loadout loadout = pawn.GetLoadout(); + if (loadout != null && !loadout.Slots.NullOrEmpty()) + { + // Need to generate a dictionary and nibble like when dropping in order to allow for conflicting loadouts to work properly. + Dictionary listing = pawn.GetStorageByThingDef(); + + // process each loadout slot... (While the LoadoutSlot.countType property only really makes sense in the context of genericDef != null, it should be the correct value (pickupDrop) on .thingDef != null.) + foreach (LoadoutSlot curSlot in loadout.Slots.Where(s => s.countType != LoadoutCountType.dropExcess)) + { + Thing curThing = null; + ItemPriority curPriority = ItemPriority.None; + Pawn curCarrier = null; + int wantCount = curSlot.count; + + if (curSlot.thingDef != null) + { + if (listing.ContainsKey(curSlot.thingDef)) + { + int amount = listing[curSlot.thingDef].value >= wantCount ? wantCount : listing[curSlot.thingDef].value; + listing[curSlot.thingDef].value -= amount; + wantCount -= amount; + if (listing[curSlot.thingDef].value <= 0) + listing.Remove(curSlot.thingDef); + } + } + if (curSlot.genericDef != null) + { + List killKeys = new List(); + int amount; + foreach (ThingDef def in listing.Keys.Where(td => curSlot.genericDef.lambda(td))) + { + amount = listing[def].value >= wantCount ? wantCount : listing[def].value; + listing[def].value -= amount; + wantCount -= amount; + if (listing[def].value <= 0) + killKeys.Add(def); + if (wantCount <= 0) + break; + } + foreach (ThingDef def in killKeys) // oddly enough removing a dictionary entry while enumerating hasn't caused a problem but this is the 'correct' way based on reading. + listing.Remove(def); + } + if (wantCount > 0) + { + FindPickup(pawn, curSlot, wantCount, out curPriority, out curThing, out curCarrier); + + if (curPriority > priority && curThing != null && inventory.CanFitInInventory(curThing, out count)) + { + priority = curPriority; + slot = curSlot; + count = count >= wantCount ? wantCount : count; + closestThing = curThing; + if (curCarrier != null) + carriedBy = curCarrier; + } + if (priority >= ItemPriority.LowStock) + { + break; + } + } + } + } + } + + return slot; + } + + /// + /// Used by GetPrioritySlot, actually finds a requested thing. + /// + /// Pawn to be considered. Used in checking equipment and position when looking for nearby things. + /// Pawn's LoadoutSlot being considered. + /// Amount of Thing of ThingDef to try and pickup. + /// Priority of the job. + /// Thing found near pawn for potential pickup. + /// Pawn that is holding the curThing that 'pawn' wants. + /// Was split off into a sepearate method so the code could be run from multiple places in caller but that is no longer needed. + private void FindPickup(Pawn pawn, LoadoutSlot curSlot, int findCount, out ItemPriority curPriority, out Thing curThing, out Pawn curCarrier) + { + curPriority = ItemPriority.None; + curThing = null; + curCarrier = null; + + Predicate isFoodInPrison = (Thing t) => t.GetRoom().isPrisonCell && t.def.IsNutritionGivingIngestible && pawn.Faction.IsPlayer; + // Hint: The following block defines how to find items... pay special attention to the Predicates below. + ThingRequest req; + if (curSlot.genericDef != null) + req = ThingRequest.ForGroup(ThingRequestGroup.HaulableEver); + else + req = curSlot.thingDef.Minifiable ? ThingRequest.ForGroup(ThingRequestGroup.MinifiedThing) : ThingRequest.ForDef(curSlot.thingDef); + Predicate findItem; + if (curSlot.genericDef != null) + findItem = t => curSlot.genericDef.lambda(t.GetInnerIfMinified().def); + else + findItem = t => t.GetInnerIfMinified().def == curSlot.thingDef; + Predicate search = t => findItem(t) && !t.IsForbidden(pawn) && pawn.CanReserve(t) && !isFoodInPrison(t); + + // look for a thing near the pawn. + curThing = GenClosest.ClosestThingReachable( + pawn.Position, + pawn.Map, + req, + PathEndMode.ClosestTouch, + TraverseParms.For(pawn, Danger.None, TraverseMode.ByPawn), + proximitySearchRadius, + search); + if (curThing != null) curPriority = ItemPriority.Proximity; + else + { + // look for a thing basically anywhere on the map. + curThing = GenClosest.ClosestThingReachable( + pawn.Position, + pawn.Map, + req, + PathEndMode.ClosestTouch, + TraverseParms.For(pawn, Danger.None, TraverseMode.ByPawn), + maximumSearchRadius, + search); + if (curThing == null && pawn.Map != null) + { + // look for a thing inside caravan pack animals and prisoners. EXCLUDE other colonists to avoid looping state. + List carriers = pawn.Map.mapPawns.AllPawns.Where( + p => p.inventory.innerContainer.Count > 0 && (p.RaceProps.packAnimal && p.Faction == pawn.Faction || p.IsPrisoner && p.HostFaction == pawn.Faction)).ToList(); + foreach (Pawn carrier in carriers) + { + Thing thing = carrier.inventory.innerContainer.FirstOrDefault(t => findItem(t)); + if (thing != null) + { + curThing = thing; + curCarrier = carrier; + break; + } + } + } + if (curThing != null) + { + if (curThing.def.IsNutritionGivingIngestible && findCount / curSlot.count <= 0.5f) curPriority = ItemPriority.LowStock; + else curPriority = ItemPriority.Low; + } + } + } + + /// + /// Tries to give the pawn a job related to picking up or dropping an item from their inventory. + /// + /// Pawn to which the job is given. + /// Job that the pawn was instructed to do, be it hauling a dropped Thing or going and getting a Thing. + protected override Job TryGiveJob(Pawn pawn) + { + // Get inventory + CompInventory inventory = pawn.TryGetComp(); + if (inventory == null) return null; + + Loadout loadout = pawn.GetLoadout(); + if (loadout != null) + { + ThingWithComps dropEq; + if (pawn.GetExcessEquipment(out dropEq)) + { + ThingWithComps droppedEq; + if (pawn.equipment.TryDropEquipment(pawn.equipment.Primary, out droppedEq, pawn.Position, false)) + { + if (droppedEq != null) + return HaulAIUtility.HaulToStorageJob(pawn, droppedEq); + Log.Error(string.Concat(pawn, " tried dropping ", dropEq, " from loadout but resulting thing is null")); + } + } + Thing dropThing; + int dropCount; + if (pawn.GetExcessThing(out dropThing, out dropCount)) + { + Thing droppedThing; + if (inventory.container.TryDrop(dropThing, pawn.Position, pawn.Map, ThingPlaceMode.Near, dropCount, out droppedThing)) + { + if (droppedThing != null) + { + return HaulAIUtility.HaulToStorageJob(pawn, droppedThing); + } + Log.Error(string.Concat(pawn, " tried dropping ", dropThing, " from loadout but resulting thing is null")); + } + } + + // Find missing items + ItemPriority priority; + Thing closestThing; + int count; + Pawn carriedBy; + bool doEquip = false; + LoadoutSlot prioritySlot = GetPrioritySlot(pawn, out priority, out closestThing, out count, out carriedBy); + // moved logic to detect if should equip vs put in inventory here... + if (closestThing != null) + { + if (closestThing.TryGetComp() != null + && (pawn.health != null && pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation)) + && (pawn.equipment == null || pawn.equipment.Primary == null || !loadout.Slots.Any(s => s.thingDef == pawn.equipment.Primary.def + || (s.genericDef != null && s.countType == LoadoutCountType.pickupDrop + && s.genericDef.lambda(pawn.equipment.Primary.def))))) + doEquip = true; + if (carriedBy == null) + { + // Equip gun if unarmed or current gun is not in loadout + if (doEquip) + { + return new Job(JobDefOf.Equip, closestThing); + } + return new Job(JobDefOf.TakeInventory, closestThing) { count = Mathf.Min(closestThing.stackCount, count) }; + } else + { + return new Job(CE_JobDefOf.TakeFromOther, closestThing, carriedBy, doEquip ? pawn : null) { + count = doEquip ? 1 : Mathf.Min(closestThing.stackCount, count) + }; + } + } + } + return null; + } + + #endregion + } +} diff --git a/Source/CombatRealism/CombatExtended/Jobs/WorkGiver_ReloadTurret.cs b/Source/CombatExtended/CombatExtended/Jobs/WorkGiver_ReloadTurret.cs similarity index 57% rename from Source/CombatRealism/CombatExtended/Jobs/WorkGiver_ReloadTurret.cs rename to Source/CombatExtended/CombatExtended/Jobs/WorkGiver_ReloadTurret.cs index 35dbd9da4c..5f2e8fb788 100644 --- a/Source/CombatRealism/CombatExtended/Jobs/WorkGiver_ReloadTurret.cs +++ b/Source/CombatExtended/CombatExtended/Jobs/WorkGiver_ReloadTurret.cs @@ -19,12 +19,20 @@ public override ThingRequest PotentialWorkThingRequest } } - public override bool HasJobOnThingForced(Pawn pawn, Thing t) + public override bool HasJobOnThing(Pawn pawn, Thing t, bool forced = false) { Building_TurretGunCE turret = t as Building_TurretGunCE; - if (turret == null || !turret.needsReload || !pawn.CanReserveAndReach(turret, PathEndMode.ClosestTouch, Danger.Deadly) || turret.IsForbidden(pawn.Faction)) return false; + if (turret == null || (!forced && !turret.AllowAutomaticReload)) return false; + + if (!turret.NeedsReload + || !pawn.CanReserveAndReach(turret, PathEndMode.ClosestTouch, Danger.Deadly) + || turret.IsForbidden(pawn.Faction)) + { + return false; + } + if (!turret.CompAmmo.useAmmo) return true; Thing ammo = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, - ThingRequest.ForDef(turret.compAmmo.selectedAmmo), + ThingRequest.ForDef(turret.CompAmmo.SelectedAmmo), PathEndMode.ClosestTouch, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn), 80, @@ -32,28 +40,26 @@ public override bool HasJobOnThingForced(Pawn pawn, Thing t) return ammo != null; } - public override bool HasJobOnThing(Pawn pawn, Thing t) + public override Job JobOnThing(Pawn pawn, Thing t, bool forced = false) { Building_TurretGunCE turret = t as Building_TurretGunCE; - if (turret == null || !turret.allowAutomaticReload) return false; - return HasJobOnThingForced(pawn, t); - } + if (turret == null || turret.CompAmmo == null) return null; - public override Job JobOnThing(Pawn pawn, Thing t) - { - Building_TurretGunCE turret = t as Building_TurretGunCE; - if (turret == null) return null; + if (!turret.CompAmmo.useAmmo) + { + return new Job(CE_JobDefOf.ReloadTurret, t, null); + } Thing ammo = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, - ThingRequest.ForDef(turret.compAmmo.selectedAmmo), + ThingRequest.ForDef(turret.CompAmmo.SelectedAmmo), PathEndMode.ClosestTouch, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn), 80, x => !x.IsForbidden(pawn) && pawn.CanReserve(x)); if (ammo == null) return null; - int amountNeeded = turret.compAmmo.Props.magazineSize; - if (turret.compAmmo.currentAmmo == turret.compAmmo.selectedAmmo) amountNeeded -= turret.compAmmo.curMagCount; + int amountNeeded = turret.CompAmmo.Props.magazineSize; + if (turret.CompAmmo.currentAmmo == turret.CompAmmo.SelectedAmmo) amountNeeded -= turret.CompAmmo.curMagCount; return new Job(DefDatabase.GetNamed("ReloadTurret"), t, ammo) { count = Mathf.Min(amountNeeded, ammo.stackCount) }; } diff --git a/Source/CombatRealism/CombatExtended/LoadoutGen/LoadoutGenerator.cs b/Source/CombatExtended/CombatExtended/LoadoutGen/LoadoutGenerator.cs similarity index 100% rename from Source/CombatRealism/CombatExtended/LoadoutGen/LoadoutGenerator.cs rename to Source/CombatExtended/CombatExtended/LoadoutGen/LoadoutGenerator.cs diff --git a/Source/CombatRealism/CombatExtended/LoadoutGen/LoadoutGenerator_AmmoPrimary.cs b/Source/CombatExtended/CombatExtended/LoadoutGen/LoadoutGenerator_AmmoPrimary.cs similarity index 79% rename from Source/CombatRealism/CombatExtended/LoadoutGen/LoadoutGenerator_AmmoPrimary.cs rename to Source/CombatExtended/CombatExtended/LoadoutGen/LoadoutGenerator_AmmoPrimary.cs index edc70974c7..e609190afb 100644 --- a/Source/CombatRealism/CombatExtended/LoadoutGen/LoadoutGenerator_AmmoPrimary.cs +++ b/Source/CombatExtended/CombatExtended/LoadoutGen/LoadoutGenerator_AmmoPrimary.cs @@ -17,6 +17,8 @@ public class LoadoutGenerator_AmmoPrimary : LoadoutGenerator_List protected override void InitAvailableDefs() { + if (!Controller.settings.EnableAmmoSystem) return; + Pawn pawn = compInvInt.parent as Pawn; if(pawn == null) { @@ -40,13 +42,12 @@ protected void AddAvailableAmmoFor(ThingWithComps eq) CompAmmoUser compAmmo = eq.TryGetComp(); if (compAmmo != null && !compAmmo.Props.ammoSet.ammoTypes.NullOrEmpty()) { - - List listammo = (from ThingDef g in compAmmo.Props.ammoSet.ammoTypes - where g.canBeSpawningInventory - select g).ToList(); - if (!listammo.NullOrEmpty()) + List listAmmo = (from link in compAmmo.Props.ammoSet.ammoTypes + where link.ammo.canBeSpawningInventory + select link.ammo).ToList(); + if (!listAmmo.NullOrEmpty()) { - ThingDef randomammo = GenCollection.RandomElement(listammo); + AmmoDef randomammo = GenCollection.RandomElement(listAmmo); availableDefs.Add(randomammo); } else return; diff --git a/Source/CombatRealism/CombatExtended/LoadoutGen/LoadoutGenerator_AmmoSecondary.cs b/Source/CombatExtended/CombatExtended/LoadoutGen/LoadoutGenerator_AmmoSecondary.cs similarity index 100% rename from Source/CombatRealism/CombatExtended/LoadoutGen/LoadoutGenerator_AmmoSecondary.cs rename to Source/CombatExtended/CombatExtended/LoadoutGen/LoadoutGenerator_AmmoSecondary.cs diff --git a/Source/CombatRealism/CombatExtended/LoadoutGen/LoadoutGenerator_List.cs b/Source/CombatExtended/CombatExtended/LoadoutGen/LoadoutGenerator_List.cs similarity index 100% rename from Source/CombatRealism/CombatExtended/LoadoutGen/LoadoutGenerator_List.cs rename to Source/CombatExtended/CombatExtended/LoadoutGen/LoadoutGenerator_List.cs diff --git a/Source/CombatRealism/CombatExtended/LoadoutGen/LoadoutGenerator_WeaponByTag.cs b/Source/CombatExtended/CombatExtended/LoadoutGen/LoadoutGenerator_WeaponByTag.cs similarity index 100% rename from Source/CombatRealism/CombatExtended/LoadoutGen/LoadoutGenerator_WeaponByTag.cs rename to Source/CombatExtended/CombatExtended/LoadoutGen/LoadoutGenerator_WeaponByTag.cs diff --git a/Source/CombatRealism/CombatExtended/Loadouts/Dialog_ManageLoadouts.cs b/Source/CombatExtended/CombatExtended/Loadouts/Dialog_ManageLoadouts.cs similarity index 67% rename from Source/CombatRealism/CombatExtended/Loadouts/Dialog_ManageLoadouts.cs rename to Source/CombatExtended/CombatExtended/Loadouts/Dialog_ManageLoadouts.cs index 1a0a780716..83892bc1be 100644 --- a/Source/CombatRealism/CombatExtended/Loadouts/Dialog_ManageLoadouts.cs +++ b/Source/CombatExtended/CombatExtended/Loadouts/Dialog_ManageLoadouts.cs @@ -14,7 +14,9 @@ public enum SourceSelection Ranged, Melee, Ammo, - All + Minified, + Generic, + All // All things, won't include generics, can include minified/able now. } [StaticConstructorOnStartup] @@ -33,10 +35,14 @@ private static Texture2D _iconAmmo = ContentFinder.Get("UI/Icons/ammo"), _iconRanged = ContentFinder.Get("UI/Icons/ranged"), _iconMelee = ContentFinder.Get("UI/Icons/melee"), + _iconMinified = ContentFinder.Get("UI/Icons/minified"), + _iconGeneric = ContentFinder.Get("UI/Icons/generic"), _iconAll = ContentFinder.Get("UI/Icons/all"), _iconAmmoAdd = ContentFinder.Get("UI/Icons/ammoAdd"), _iconSearch = ContentFinder.Get("UI/Icons/search"), - _iconMove = ContentFinder.Get("UI/Icons/move"); + _iconMove = ContentFinder.Get("UI/Icons/move"), + _iconPickupDrop = ContentFinder.Get("UI/Icons/loadoutPickupDrop"), + _iconDropExcess = ContentFinder.Get("UI/Icons/loadoutDropExcess"); private static Regex validNameRegex = new Regex("^[a-zA-Z0-9 '\\-]*$"); private Vector2 _availableScrollPosition = Vector2.zero; @@ -51,6 +57,7 @@ private static Texture2D private float _rowHeight = 30f; private Vector2 _slotScrollPosition = Vector2.zero; private List _source; + private List _sourceGeneric; private SourceSelection _sourceType = SourceSelection.Ranged; private float _topAreaHeight = 30f; @@ -60,7 +67,9 @@ private static Texture2D public Dialog_ManageLoadouts(Loadout loadout) { - CurrentLoadout = loadout; + CurrentLoadout = null; + if (loadout != null && !loadout.defaultLoadout) + CurrentLoadout = loadout; SetSource(SourceSelection.Ranged); doCloseX = true; closeOnClickedOutside = true; @@ -123,7 +132,8 @@ public override void DoWindowContents(Rect canvas) // top buttons Rect selectRect = new Rect(0f, 0f, canvas.width * .2f, _topAreaHeight); Rect newRect = new Rect(selectRect.xMax + _margin, 0f, canvas.width * .2f, _topAreaHeight); - Rect deleteRect = new Rect(newRect.xMax + _margin, 0f, canvas.width * .2f, _topAreaHeight); + Rect copyRect = new Rect(newRect.xMax + _margin, 0f, canvas.width * .2f, _topAreaHeight); + Rect deleteRect = new Rect(copyRect.xMax + _margin, 0f, canvas.width * .2f, _topAreaHeight); // main areas Rect nameRect = new Rect( @@ -153,13 +163,15 @@ public override void DoWindowContents(Rect canvas) (canvas.width - _margin) / 2f, canvas.height - 24f - _topAreaHeight - _margin * 3); - List loadouts = LoadoutManager.Loadouts; + LoadoutManager.SortLoadouts(); + List loadouts = LoadoutManager.Loadouts.Where(l => !l.defaultLoadout).ToList(); // DRAW CONTENTS // buttons // select loadout if (Widgets.ButtonText(selectRect, "CE_SelectLoadout".Translate())) { + List options = new List(); if (loadouts.Count == 0) @@ -169,8 +181,8 @@ public override void DoWindowContents(Rect canvas) for (int i = 0; i < loadouts.Count; i++) { int local_i = i; - options.Add(new FloatMenuOption(loadouts[i].LabelCap, delegate - { CurrentLoadout = loadouts[local_i]; })); + options.Add(new FloatMenuOption(loadouts[i].LabelCap, delegate + { CurrentLoadout = loadouts[local_i]; })); } } @@ -180,9 +192,16 @@ public override void DoWindowContents(Rect canvas) if (Widgets.ButtonText(newRect, "CE_NewLoadout".Translate())) { Loadout loadout = new Loadout(); + loadout.AddBasicSlots(); LoadoutManager.AddLoadout(loadout); CurrentLoadout = loadout; } + // copy loadout + if (CurrentLoadout != null && Widgets.ButtonText(copyRect, "CE_CopyLoadout".Translate())) + { + CurrentLoadout = CurrentLoadout.Copy(); + LoadoutManager.AddLoadout(CurrentLoadout); + } // delete loadout if (loadouts.Any(l => l.canBeDeleted) && Widgets.ButtonText(deleteRect, "CE_DeleteLoadout".Translate())) { @@ -199,8 +218,8 @@ public override void DoWindowContents(Rect canvas) delegate { if (CurrentLoadout == loadouts[local_i]) - CurrentLoadout = null; - loadouts.Remove(loadouts[local_i]); + CurrentLoadout = LoadoutManager.DefaultLoadout; + LoadoutManager.RemoveLoadout(loadouts[local_i]); })); } @@ -219,7 +238,7 @@ public override void DoWindowContents(Rect canvas) // and stop further drawing return; } - + // name DrawNameField(nameRect); @@ -266,6 +285,20 @@ public void DrawSourceSelection(Rect canvas) SetSource(SourceSelection.Ammo); TooltipHandler.TipRegion(button, "CE_SourceAmmoTip".Translate()); button.x += 24f + _margin; + + // Minified + GUI.color = _sourceType == SourceSelection.Minified ? GenUI.MouseoverColor : Color.white; + if (Widgets.ButtonImage(button, _iconMinified)) + SetSource(SourceSelection.Minified); + TooltipHandler.TipRegion(button, "CE_SourceMinifiedTip".Translate()); + button.x += 24f + _margin; + + // Generic + GUI.color = _sourceType == SourceSelection.Generic ? GenUI.MouseoverColor : Color.white; + if (Widgets.ButtonImage(button, _iconGeneric)) + SetSource(SourceSelection.Generic); + TooltipHandler.TipRegion(button, "CE_SourceGenericTip".Translate()); + button.x += 24f + _margin; // All GUI.color = _sourceType == SourceSelection.All ? GenUI.MouseoverColor : Color.white; @@ -298,7 +331,8 @@ public void FilterSource(string filter) public void SetSource(SourceSelection source, bool preserveFilter = false) { - _source = DefDatabase.AllDefsListForReading; + _source = DefDatabase.AllDefs.Where(x => !x.menuHidden).ToList(); + _sourceGeneric = DefDatabase.AllDefs.OrderBy(g => g.label).ToList(); if (!preserveFilter) _filter = ""; @@ -318,6 +352,16 @@ public void SetSource(SourceSelection source, bool preserveFilter = false) _source = _source.Where(td => td is AmmoDef).ToList(); _sourceType = SourceSelection.Ammo; break; + + case SourceSelection.Minified: + _source = _source.Where(td => td.Minifiable).ToList(); + _sourceType = SourceSelection.Minified; + break; + + case SourceSelection.Generic: + _sourceType = SourceSelection.Generic; + initGenericVisibilityDictionary(); + break; case SourceSelection.All: default: @@ -334,12 +378,12 @@ private void DrawCountField(Rect canvas, LoadoutSlot slot) { if (slot == null) return; - string count = GUI.TextField(canvas, slot.Count.ToString()); - TooltipHandler.TipRegion(canvas, "CE_CountFieldTip".Translate(slot.Count)); + string count = GUI.TextField(canvas, slot.count.ToString()); + TooltipHandler.TipRegion(canvas, "CE_CountFieldTip".Translate(slot.count)); int countInt; if (int.TryParse(count, out countInt)) { - slot.Count = countInt; + slot.count = countInt; } } @@ -384,6 +428,11 @@ private void DrawSlot(Rect row, LoadoutSlot slot, bool slotDraggable = true) countRect.xMin - _iconSize - _margin, row.yMin + (row.height - _iconSize) / 2f, _iconSize, _iconSize); + + Rect countModeRect = new Rect( + ammoRect.xMin - _iconSize - _margin, + row.yMin + (row.height - _iconSize) / 2f, + _iconSize, _iconSize); Rect deleteRect = new Rect(countRect.xMax + _margin, row.yMin + (row.height - _iconSize) / 2f, _iconSize, _iconSize); @@ -401,19 +450,19 @@ private void DrawSlot(Rect row, LoadoutSlot slot, bool slotDraggable = true) if (!Mouse.IsOver(deleteRect)) { Widgets.DrawHighlightIfMouseover(row); - TooltipHandler.TipRegion(row, slot.Def.GetWeightAndBulkTip(slot.Count)); + TooltipHandler.TipRegion(row, slot.genericDef != null ? slot.genericDef.GetWeightAndBulkTip(slot.count) : slot.thingDef.GetWeightAndBulkTip(slot.count)); } // label Text.Anchor = TextAnchor.MiddleLeft; - Widgets.Label(labelRect, slot.Def.LabelCap); + Widgets.Label(labelRect, slot.LabelCap); Text.Anchor = TextAnchor.UpperLeft; // easy ammo adder, ranged weapons only - if (slot.Def.IsRangedWeapon) + if (slot.thingDef != null && slot.thingDef.IsRangedWeapon) { // make sure there's an ammoset defined - AmmoSetDef ammoSet = ((slot.Def.GetCompProperties() == null) ? null : slot.Def.GetCompProperties().ammoSet); + AmmoSetDef ammoSet = ((slot.thingDef.GetCompProperties() == null) ? null : slot.thingDef.GetCompProperties().ammoSet); bool? temp = !((((ammoSet == null) ? null : ammoSet.ammoTypes)).NullOrEmpty()); @@ -422,22 +471,40 @@ private void DrawSlot(Rect row, LoadoutSlot slot, bool slotDraggable = true) if (Widgets.ButtonImage(ammoRect, _iconAmmoAdd)) { List options = new List(); + int magazineSize = (slot.thingDef.GetCompProperties() == null) ? 0 : slot.thingDef.GetCompProperties().magazineSize; - foreach (ThingDef ammo in ((ammoSet == null) ? null : ammoSet.ammoTypes)) + foreach (AmmoLink link in ((ammoSet == null) ? null : ammoSet.ammoTypes)) { - options.Add(new FloatMenuOption(ammo.LabelCap, delegate + options.Add(new FloatMenuOption(link.ammo.LabelCap, delegate { - CurrentLoadout.AddSlot(new LoadoutSlot(ammo)); + CurrentLoadout.AddSlot(new LoadoutSlot(link.ammo, (magazineSize <= 1 ? link.ammo.defaultAmmoCount : magazineSize))); })); } + // Add in the generic for this gun. + LoadoutGenericDef generic = DefDatabase.GetNamed("GenericAmmo-" + slot.thingDef.defName); + if (generic != null) + options.Add(new FloatMenuOption(generic.LabelCap, delegate + { + CurrentLoadout.AddSlot(new LoadoutSlot(generic)); + })); - Find.WindowStack.Add(new FloatMenu(options, "CE_AddAmmoFor".Translate(slot.Def.LabelCap))); + Find.WindowStack.Add(new FloatMenu(options, "CE_AddAmmoFor".Translate(slot.thingDef.LabelCap))); } } } // count DrawCountField(countRect, slot); + + // toggle count mode + if (slot.genericDef != null) + { + Texture2D curModeIcon = slot.countType == LoadoutCountType.dropExcess ? _iconDropExcess : _iconPickupDrop; + string tipString = slot.countType == LoadoutCountType.dropExcess ? "Drop Excess" : "Pickup Missing and Drop Excess"; + if (Widgets.ButtonImage(countModeRect, curModeIcon)) + slot.countType = slot.countType == LoadoutCountType.dropExcess ? LoadoutCountType.pickupDrop : LoadoutCountType.dropExcess; + TooltipHandler.TipRegion(countModeRect, tipString); + } // delete if (Mouse.IsOver(deleteRect)) @@ -447,6 +514,7 @@ private void DrawSlot(Rect row, LoadoutSlot slot, bool slotDraggable = true) TooltipHandler.TipRegion(deleteRect, "CE_DeleteFilter".Translate()); } + //TODO: Research if the UI list of items can be cached (That's the Unity UI list)... private void DrawSlotList(Rect canvas) { // set up content canvas @@ -533,43 +601,61 @@ private void DrawSlotList(Rect canvas) private void DrawSlotSelection(Rect canvas) { + int count = _sourceType == SourceSelection.Generic ? _sourceGeneric.Count : _source.Count; GUI.DrawTexture(canvas, _darkBackground); - - if (_source.NullOrEmpty()) + + if ((_sourceType != SourceSelection.Generic && _source.NullOrEmpty()) || (_sourceType == SourceSelection.Generic && _sourceGeneric.NullOrEmpty())) return; - + Rect viewRect = new Rect(canvas); viewRect.width -= 16f; - viewRect.height = _source.Count * _rowHeight; + viewRect.height = count * _rowHeight; Widgets.BeginScrollView(canvas, ref _availableScrollPosition, viewRect.AtZero()); int startRow = (int)Math.Floor((decimal)(_availableScrollPosition.y / _rowHeight)); startRow = (startRow < 0) ? 0 : startRow; int endRow = startRow + (int)(Math.Ceiling((decimal)(canvas.height / _rowHeight))); - endRow = (endRow > _source.Count) ? _source.Count : endRow; + endRow = (endRow > count) ? count : endRow; for (int i = startRow; i < endRow; i++) { // gray out weapons not in stock Color baseColor = GUI.color; - if (Find.VisibleMap.listerThings.AllThings.FindAll(x => x.def == _source[i]).Count <= 0) - GUI.color = Color.gray; + if (_sourceType == SourceSelection.Generic) + { + if (GetVisibleGeneric(_sourceGeneric[i])) + GUI.color = Color.gray; + } else { + //if (Find.VisibleMap.listerThings.AllThings.FindAll(x => x.GetInnerIfMinified().def == _source[i] && !x.def.Minifiable).Count <= 0) + if (Find.VisibleMap.listerThings.AllThings.Find(x => x.GetInnerIfMinified().def == _source[i] && !x.def.Minifiable) == null) + GUI.color = Color.gray; + } Rect row = new Rect(0f, i * _rowHeight, canvas.width, _rowHeight); Rect labelRect = new Rect(row); - TooltipHandler.TipRegion(row, _source[i].GetWeightAndBulkTip()); + if (_sourceType == SourceSelection.Generic) + TooltipHandler.TipRegion(row, _sourceGeneric[i].GetWeightAndBulkTip()); + else + TooltipHandler.TipRegion(row, _source[i].GetWeightAndBulkTip()); labelRect.xMin += _margin; if (i % 2 == 0) GUI.DrawTexture(row, _darkBackground); Text.Anchor = TextAnchor.MiddleLeft; - Widgets.Label(labelRect, _source[i].LabelCap); + if (_sourceType == SourceSelection.Generic) + Widgets.Label(labelRect, _sourceGeneric[i].LabelCap); + else + Widgets.Label(labelRect, _source[i].LabelCap); Text.Anchor = TextAnchor.UpperLeft; Widgets.DrawHighlightIfMouseover(row); if (Widgets.ButtonInvisible(row)) { - LoadoutSlot slot = new LoadoutSlot(_source[i], 1); + LoadoutSlot slot; + if (_sourceType == SourceSelection.Generic) + slot = new LoadoutSlot(_sourceGeneric[i]); + else + slot = new LoadoutSlot(_source[i]); CurrentLoadout.AddSlot(slot); } // revert to original color @@ -577,7 +663,60 @@ private void DrawSlotSelection(Rect canvas) } Widgets.EndScrollView(); } - + #endregion Methods + + #region ListDrawOptimization + + /* This region is used by DrawSlotSelection and setup by SetSource when Generics type is chosen. + * Purpose is to spread the load out over time, instead of checking the state of every generic per frame, only one generic is tested in a given frame. + * and then some time (frames) are allowed to pass before the next check. + * + * The reason is that checking the existence of a generic requires that we consider all possible things. + * A well written generic won't be too hard to test on a given frame. + */ + + static readonly Dictionary genericVisibility = new Dictionary(); + const int advanceTicks = 1; // GenTicks.TicksPerRealSecond / 4; + + /// + /// Purpose is to handle deciding if a generic's state (something on the map or not) should be checked or not based on current frame. + /// + /// + /// + private bool GetVisibleGeneric(LoadoutGenericDef def) + { + if (GenTicks.TicksAbs >= genericVisibility[def].ticksToRecheck) + { + genericVisibility[def].ticksToRecheck = GenTicks.TicksAbs + (advanceTicks * genericVisibility[def].position); + genericVisibility[def].check = Find.VisibleMap.listerThings.AllThings.Find(x => def.lambda(x.GetInnerIfMinified().def) && !x.def.Minifiable) == null; + } + + return genericVisibility[def].check; + } + + private void initGenericVisibilityDictionary() + { + int tick = GenTicks.TicksAbs; + int position = 1; + foreach (LoadoutGenericDef def in _sourceGeneric) + { + if (!genericVisibility.ContainsKey(def)) genericVisibility.Add(def, new VisibilityCache()); + genericVisibility[def].ticksToRecheck = tick; + genericVisibility[def].check = Find.VisibleMap.listerThings.AllThings.Find(x => def.lambda(x.GetInnerIfMinified().def) && !x.def.Minifiable) == null; + genericVisibility[def].position = position; + position++; + tick += advanceTicks; + } + } + + private class VisibilityCache + { + public int ticksToRecheck = 0; + public bool check = true; + public int position = 0; + } + + #endregion GenericDrawOptimization } } diff --git a/Source/CombatExtended/CombatExtended/Loadouts/GameComp_LoadoutManager.cs b/Source/CombatExtended/CombatExtended/Loadouts/GameComp_LoadoutManager.cs new file mode 100644 index 0000000000..fc8a81da9f --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Loadouts/GameComp_LoadoutManager.cs @@ -0,0 +1,253 @@ +using RimWorld; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using UnityEngine; +using Verse; + +/* Notes (ProfoundDarkness) + * The GameComponent works a little different from MapComponent. + * While a Game is being started it's possible for other code to try and use LoadoutManager, until FinalizeInit is called on us we shouldn't be responding to + * requests. This is because some information can leak from current game to loaded game if we don't block access to the object appropriately. + * + * I ended up maintaining the interface between how things used to work and how things would work with a proper instance system. There may have been a proper + * way to retrieve the current instance of the current game QUICKLY but I didn't see it so instead all the static methods have a chance of returning nothing + * without having done any work. (They hide what's going on.) + */ + +namespace CombatExtended +{ + public class LoadoutManager : GameComponent + { + #region Fields + private Dictionary _assignedLoadouts = new Dictionary(); + private List _loadouts = new List(); + private List _trackers = new List(); + private Dictionary _assignedTrackers = new Dictionary(); // track what the pawn is holding to not drop. + private static LoadoutManager _current; // there is a window where accessing the manager is invalid... + #endregion Fields + + #region Constructors + // constructor called on new/first game. + public LoadoutManager(Game game) + { + // create a default empty loadout + // there needs to be at least one default tagged loadout at all times + _loadouts.Add(MakeDefaultLoadout()); + _current = null; // this ensures the window of valid access is maintained by wiping the old instance. + } + // constructor called on Load Game. When this gets called there can actually be 2 instances of our Component... + public LoadoutManager() + { + // this constructor is also used by the scribe. + _current = null; // this ensures the window of valid access is maintained by wiping the old instance. + } + #endregion Constructors + + #region Properties + public static Dictionary AssignedLoadouts => _current != null ? _current._assignedLoadouts : new Dictionary(); + + public static Loadout DefaultLoadout { get { return _current != null ? _current._loadouts.First(l => l.defaultLoadout) : MakeDefaultLoadout(); } } + + public static List Loadouts => _current != null ? _current._loadouts : null; + + #endregion Properties + + #region Override Methods + /// + /// Called by RimWorld when the game is basically ready to be played. + /// + /// If you allow access to your object before this is called (via _current or some other static instance variable) you WILL leak data between game states (bad). + public override void FinalizeInit() + { + base.FinalizeInit(); + _current = Current.Game.GetComponent(); // after this it's valid to be accessing the Component. + } + /* Unused CameComponent override methods: + * GameComponentOnGUI() - is called basically any time something happens with the GUI. + * GameComponentUpdate() - Uncertain, seems to get called any time the game state changes (including while paused if the player does something). + * GameComponentTick() - Called on every tick of the game. + * LoadedGame() - Called after the game is loaded at about the same time as StartedNewGame would get called. + * StartedNewGame() - Called after a new game has been created (ie from the main menu -> start new game). + */ + /// + /// Load/Save handler. + /// + public override void ExposeData() // - called when saving a game as well as in the construction phase of creating a new instance on game load. + { + if (Scribe.mode == LoadSaveMode.Saving) + { + PurgeHoldTrackerRolls(); + PurgeLoadoutRolls(); + } + + Scribe_Collections.Look(ref _loadouts, "loadouts", LookMode.Deep); + Scribe_Collections.Look(ref _assignedLoadouts, "assignmentLoadouts", LookMode.Reference, LookMode.Reference); + bool hasTrackers = _trackers.Any(); + Scribe_Values.Look(ref hasTrackers, "HasTrackers"); + if (hasTrackers) + { + Scribe_Collections.Look(ref _trackers, "HoldTrackers", LookMode.Deep); + Scribe_Collections.Look(ref _assignedTrackers, "assignedTrackers", LookMode.Reference, LookMode.Reference); + } + } + #endregion Override Methods + + #region Methods + /// + /// Creates a new default loadout (there is only one default, the Empty loadout). + /// + /// Loadout which is the Empty Loadout. + private static Loadout MakeDefaultLoadout() + { + return new Loadout("CE_EmptyLoadoutName".Translate(), 1) { canBeDeleted = false, defaultLoadout = true }; + } + + /// + /// Returns a List of HoldRecords for the Pawn. + /// + /// Pawn to get the List for. + /// List of HoldRecords or null if the pawn has none. + public static List GetHoldRecords(Pawn pawn) // Rename Try? + { + if (_current == null) return null; + Tracker tracker; + if (_current._assignedTrackers.TryGetValue(pawn, out tracker)) + return tracker.recs; + return null; + } + + /// + /// Utility to clean up HoldTracker entries for pawns which are dead or who no longer have HoldRecords. Useful pre-save. + /// + public static void PurgeHoldTrackerRolls() + { + if (_current == null) return; + List removeList = new List(_current._assignedTrackers.Keys.Count); + foreach (Pawn pawn in _current._assignedTrackers.Keys) + { + if (pawn.Dead) + removeList.Add(pawn); // remove dead pawns from the rolls + else if (!_current._assignedTrackers[pawn].recs.Any()) + removeList.Add(pawn); // remove pawns with no HoldRecords stored. + else if (pawn.DestroyedOrNull()) + removeList.Add(pawn); // remove pawns have been destroyed or are null. + } + foreach (Pawn pawn in removeList) + { + Tracker remTracker = _current._assignedTrackers[pawn]; + _current._trackers.Remove(remTracker); + _current._assignedTrackers.Remove(pawn); + } + } + + /// + /// Similar to the PurgeHoldTrackerRolls, clean up loadout data, mostly used pre-save but can be used elsewhere. + /// + public static void PurgeLoadoutRolls() + { + if (_current == null) return; + List removeList = new List(_current._assignedLoadouts.Keys.Count); + foreach (Pawn pawn in _current._assignedLoadouts.Keys) + { + if (pawn.Dead) + removeList.Add(pawn); // remove dead pawns from the rolls, they should become null pawns on game save. + else if (pawn.DestroyedOrNull()) + removeList.Add(pawn); // remove pawns that have been destroyed or are null. + } + foreach (Pawn pawn in removeList) + _current._assignedLoadouts.Remove(pawn); + } + + /// + /// Adds a List of HoldRecord to the indicated Pawn. + /// + /// Pawn for whome new List should be stored. + /// List of HoldRecord that should be attached to pawn. + public static void AddHoldRecords(Pawn pawn, List newRecords) + { + if (_current == null) return; + Tracker tracker = new Tracker(newRecords); + _current._trackers.Add(tracker); + _current._assignedTrackers.Add(pawn, tracker); + } + + public static void AddLoadout(Loadout loadout) + { + if (_current == null) return; + _current._loadouts.Add(loadout); + } + + public static void RemoveLoadout(Loadout loadout) + { + if (_current == null) return; + // assign default loadout to pawns that used to use this loadout + List obsolete = AssignedLoadouts.Where(kvp => kvp.Value == loadout).Select(kvp => kvp.Key).ToList(); // ToList separates this from the dictionary, ienumerable in this case would break as we change the relationship. + foreach (Pawn id in obsolete) + AssignedLoadouts[id] = DefaultLoadout; + + _current._loadouts.Remove(loadout); + } + + /// + /// Used to ensure that future retrievals of loadouts are sorted. Doesn't need to be called often, just right before fetching and only when it matters. + /// + public static void SortLoadouts() + { + if (_current == null) return; + _current._loadouts.Sort(); + } + + /// + /// Used turring instanciation of new Tracker objects. + /// + /// + internal static int GetUniqueTrackerID() + { + LoadoutManager manager = Current.Game.GetComponent(); + if (manager != null && manager._assignedTrackers.Values.Any()) + return manager._assignedTrackers.Values.Max(t => t.uniqueID) + 1; + else + return 1; + } + + internal static int GetUniqueLoadoutID() + { + LoadoutManager manager = Current.Game.GetComponent(); + if (manager != null && manager._loadouts.Any()) + return manager._loadouts.Max(l => l.uniqueID) + 1; + else + return 1; + } + + internal static string GetUniqueLabel() + { + return GetUniqueLabel("CE_DefaultLoadoutName".Translate()); + } + + internal static string GetUniqueLabel(string head) + { + LoadoutManager manager = Current.Game.GetComponent(); + string label; + int i = 1; + if (manager != null) + { + do + { + label = head + i++; + } + while (manager._loadouts.Any(l => l.label == label)); + } else + label = head + i++; + return label; + } + + internal static Loadout GetLoadoutById(int id) + { + if (_current == null) return null; + return Loadouts.Find(x => x.uniqueID == id); + } + #endregion Methods + } +} \ No newline at end of file diff --git a/Source/CombatExtended/CombatExtended/Loadouts/HoldRecord.cs b/Source/CombatExtended/CombatExtended/Loadouts/HoldRecord.cs new file mode 100644 index 0000000000..c42848b7b5 --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Loadouts/HoldRecord.cs @@ -0,0 +1,88 @@ +using RimWorld; +using Verse; + +namespace CombatExtended +{ + /// + /// HoldRecord stores key information for an individual element of HoldTracker. + /// + /// Wow this is looking a lot like a LoadoutSlot now... Remembering by Thing doesn't work out. + public class HoldRecord : IExposable + { + #region Fields + const int INVALIDTICKS = GenDate.TicksPerDay; + + private ThingDef _def; + public int count; + public bool pickedUp; + private int _tickJobIssued; + + #endregion + + #region Constructors + /// + /// Constructor for when a pawn was instructed to pick something up but hasn't yet, ie HoldTracker was notified. By default pickedUp will be false. + /// + /// The ThingDef to add to HoldTracker. + /// How much to hold onto. + public HoldRecord(ThingDef newThingDef, int newCount) + { + _def = newThingDef; + count = newCount; + pickedUp = false; + _tickJobIssued = GenTicks.TicksAbs; + } + + /// + /// Default Constructor. Used by Rimworld Load/Save and shouldn't be used by any other code. + /// + public HoldRecord() + { + } + #endregion + + #region Properties + /// + /// If the item hasn't been picked up is it still valid to remember? + /// + public bool isTimeValid { get { return !pickedUp && ((GenTicks.TicksAbs - _tickJobIssued) <= INVALIDTICKS); } } + + public ThingDef thingDef { get { return this._def; } } + + #endregion + + #region Methods + /// + /// Meant to be used in debug messages, attempt to capture the state of the object if a tad wordy. + /// + /// string containing debug message. + public override string ToString() + { + return string.Concat("HoldRecord for ", thingDef, " of count ", count, " which has", (!pickedUp ? "n't" : ""), " been picked up", + (!pickedUp ? string.Concat(" with a job issue time of ", (GenTicks.TicksAbs - _tickJobIssued), + " ago and will go invalid in ", (GenTicks.TicksAbs + INVALIDTICKS - _tickJobIssued)) : ".")); + } + #endregion + + #region IExposable implementation + + /// + /// RimWorld Load/Save handler. + /// + public void ExposeData() + { + Log.Message("Saving _def"); + Scribe_Defs.Look(ref _def, "ThingDef"); + Log.Message("Saving count"); + Scribe_Values.Look(ref count, "count"); + Log.Message("Saving pickedUp"); + Scribe_Values.Look(ref pickedUp, "pickedUp"); + if (!pickedUp) + { + Log.Message("Saving tickOfPickedupJob"); + Scribe_Values.Look(ref _tickJobIssued, "tickOfPickupJob"); + } + } + #endregion + } +} \ No newline at end of file diff --git a/Source/CombatExtended/CombatExtended/Loadouts/HoldTrackerAssignment.cs b/Source/CombatExtended/CombatExtended/Loadouts/HoldTrackerAssignment.cs new file mode 100644 index 0000000000..7a6f5277c1 --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Loadouts/HoldTrackerAssignment.cs @@ -0,0 +1,41 @@ +using RimWorld; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Verse; + +namespace CombatExtended +{ + public class HoldTrackerAssignment : IExposable + { + #region Fields + + internal Pawn pawn; + internal List recs; + + #endregion Fields + + public bool Valid + { + get + { + return ((pawn != null) && (recs != null)); + } + } + + #region Methods + + public void ExposeData() + { + Scribe_References.Look( ref pawn, "pawn" ); + Scribe_Collections.Look( ref recs, "holdRecords" ); + +#if DEBUG +Log.Message( Scribe.mode + ", pawn: " + ( pawn == null ? "NULL" : pawn.NameStringShort ) + ", holdRecords: " + ( recs == null ? "NULL" : string.Join(", ", recs.Select(hr => hr.thingDef.ToString()).ToArray()) ) ); +#endif + } + + #endregion Methods + } +} \ No newline at end of file diff --git a/Source/CombatRealism/CombatExtended/Loadouts/ITabInjector.cs b/Source/CombatExtended/CombatExtended/Loadouts/ITabInjector.cs similarity index 100% rename from Source/CombatRealism/CombatExtended/Loadouts/ITabInjector.cs rename to Source/CombatExtended/CombatExtended/Loadouts/ITabInjector.cs diff --git a/Source/CombatRealism/CombatExtended/Loadouts/ITab_Inventory.cs b/Source/CombatExtended/CombatExtended/Loadouts/ITab_Inventory.cs similarity index 78% rename from Source/CombatRealism/CombatExtended/Loadouts/ITab_Inventory.cs rename to Source/CombatExtended/CombatExtended/Loadouts/ITab_Inventory.cs index 9fd3c705e5..c957cdfe4d 100644 --- a/Source/CombatRealism/CombatExtended/Loadouts/ITab_Inventory.cs +++ b/Source/CombatExtended/CombatExtended/Loadouts/ITab_Inventory.cs @@ -1,4 +1,5 @@ -using RimWorld; +using System.Text.RegularExpressions; +using RimWorld; using System; using System.Collections.Generic; using System.Linq; @@ -85,6 +86,8 @@ protected override void FillTab() if (comp != null) { + PlayerKnowledgeDatabase.KnowledgeDemonstrated(CE_ConceptDefOf.CE_InventoryWeightBulk, KnowledgeAmount.FrameDisplayed); + // adjust rects if comp found listRect.height -= (_margin / 2 + _barHeight) * 2; Rect weightRect = new Rect(_margin, listRect.yMax + _margin / 2, listRect.width, _barHeight); @@ -115,7 +118,7 @@ protected override void FillTab() if (SelPawnForGear.equipment != null) { Widgets.ListSeparator(ref num, viewRect.width, "Equipment".Translate()); - foreach (ThingWithComps current in SelPawnForGear.equipment.AllEquipment) + foreach (ThingWithComps current in SelPawnForGear.equipment.AllEquipmentListForReading) { DrawThingRow(ref num, viewRect.width, current); } @@ -132,12 +135,45 @@ orderby ap.def.apparel.bodyPartGroups[0].listOrder descending } if (SelPawnForGear.inventory != null) { + // get the loadout so we can make a decision to show a button. + bool showMakeLoadout = false; + Loadout curLoadout = SelPawnForGear.GetLoadout(); + if (SelPawnForGear.IsColonist && (curLoadout == null || curLoadout.Slots.NullOrEmpty()) && (SelPawnForGear.inventory.innerContainer.Any() || SelPawnForGear.equipment?.Primary != null)) + showMakeLoadout = true; + + if (showMakeLoadout) num+=3; // Make a little room for the button. + + float buttonY = num; // Could be accomplished with seperator being after the button... + Widgets.ListSeparator(ref num, viewRect.width, "Inventory".Translate()); + + // only offer this button if the pawn has no loadout or has the default loadout and there are things/equipment... + if (showMakeLoadout) + { + Rect loadoutButtonRect = new Rect(viewRect.width / 2, buttonY, viewRect.width / 2, 26f); // button is half the available width... + if(Widgets.ButtonText(loadoutButtonRect, "Make Loadout")) + { + Loadout loadout = SelPawnForGear.GenerateLoadoutFromPawn(); + LoadoutManager.AddLoadout(loadout); + SelPawnForGear.SetLoadout(loadout); + + // UNDONE ideally we'd open the assign (MainTabWindow_OutfitsAndLoadouts) tab as if the user clicked on it here. + // (ProfoundDarkness) But I have no idea how to do that just yet. The attempts I made seem to put the RimWorld UI into a bit of a bad state. + // ie opening the tab like the dialog below. + // Need to understand how RimWorld switches tabs and see if something similar can be done here + // (or just remove the unfinished marker). + + // Opening this window is the same way as if from the assign tab so should be correct. + Find.WindowStack.Add(new Dialog_ManageLoadouts(SelPawnForGear.GetLoadout())); + + } + } + workingInvList.Clear(); workingInvList.AddRange(SelPawnForGear.inventory.innerContainer); for (int i = 0; i < workingInvList.Count; i++) { - DrawThingRow(ref num, viewRect.width, workingInvList[i].GetInnerIfMinified()); + DrawThingRow(ref num, viewRect.width, workingInvList[i].GetInnerIfMinified(), true); } } if (Event.current.type == EventType.Layout) @@ -150,13 +186,13 @@ orderby ap.def.apparel.bodyPartGroups[0].listOrder descending Text.Anchor = TextAnchor.UpperLeft; } - private void DrawThingRow(ref float y, float width, Thing thing) + private void DrawThingRow(ref float y, float width, Thing thing, bool showDropButtonIfPrisoner = false) { Rect rect = new Rect(0f, y, width, _thingRowHeight); Widgets.InfoCardButton(rect.width - 24f, y, thing); rect.width -= 24f; - if (CanControl) + if (CanControl || SelPawnForGear.Faction == Faction.OfPlayer && SelPawnForGear.RaceProps.packAnimal || showDropButtonIfPrisoner && SelPawnForGear.HostFaction == Faction.OfPlayer) { Rect dropRect = new Rect(rect.width - 24f, y, 24f, 24f); TooltipHandler.TipRegion(dropRect, "DropThing".Translate()); @@ -195,7 +231,8 @@ private void DrawThingRow(ref float y, float width, Thing thing) GUI.color = _thingLabelColor; Rect thingLabelRect = new Rect(_thingLeftX, y, rect.width - _thingLeftX, _thingRowHeight); string thingLabel = thing.LabelCap; - if (thing is Apparel && SelPawnForGear.outfits != null && SelPawnForGear.outfits.forcedHandler.IsForced((Apparel)thing)) + if ((thing is Apparel && SelPawnForGear.outfits != null && SelPawnForGear.outfits.forcedHandler.IsForced((Apparel)thing)) + || (SelPawnForGear.inventory != null && SelPawnForGear.HoldTrackerIsHeld(thing))) { thingLabel = thingLabel + ", " + "ApparelForcedLower".Translate(); } @@ -222,13 +259,12 @@ private void DrawThingRow(ref float y, float width, Thing thing) { FloatMenuOption equipOption; string eqLabel = GenLabel.ThingLabel(eq.def, eq.Stuff, 1); - if (SelPawnForGear.equipment.AllEquipment.Contains(eq) && SelPawnForGear.inventory != null) + if (SelPawnForGear.equipment.AllEquipmentListForReading.Contains(eq) && SelPawnForGear.inventory != null) { equipOption = new FloatMenuOption("CE_PutAway".Translate(new object[] { eqLabel }), new Action(delegate { - ThingWithComps oldEq; - SelPawnForGear.equipment.TryTransferEquipmentToContainer(SelPawnForGear.equipment.Primary, SelPawnForGear.inventory.innerContainer, out oldEq); + SelPawnForGear.equipment.TryTransferEquipmentToContainer(SelPawnForGear.equipment.Primary, SelPawnForGear.inventory.innerContainer); })); } else if (!SelPawnForGear.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation)) @@ -272,6 +308,15 @@ private void DrawThingRow(ref float y, float width, Thing thing) } floatOptionList.Add(new FloatMenuOption("DropThing".Translate(), dropApparel)); floatOptionList.Add(new FloatMenuOption("CE_DropThingHaul".Translate(), dropApparelHaul)); + if (this.CanControl && SelPawnForGear.HoldTrackerIsHeld(thing)) + { + Action forgetHoldTracker = delegate + { + SoundDefOf.TickHigh.PlayOneShotOnCamera(); + SelPawnForGear.HoldTrackerForget(thing); + }; + floatOptionList.Add(new FloatMenuOption("CE_HoldTrackerForget".Translate(), forgetHoldTracker)); + } } FloatMenu window = new FloatMenu(floatOptionList, thing.LabelCap, false); Find.WindowStack.Add(window); @@ -331,32 +376,39 @@ private void TryDrawComfyTemperatureRange(ref float curY, float width) // RimWorld.ITab_Pawn_Gear private void InterfaceDrop(Thing t) { + if (SelPawnForGear.HoldTrackerIsHeld(t)) + SelPawnForGear.HoldTrackerForget(t); ThingWithComps thingWithComps = t as ThingWithComps; Apparel apparel = t as Apparel; if (apparel != null && this.SelPawnForGear.apparel != null && this.SelPawnForGear.apparel.WornApparel.Contains(apparel)) { this.SelPawnForGear.jobs.TryTakeOrderedJob(new Job(JobDefOf.RemoveApparel, apparel)); } - else if (thingWithComps != null && this.SelPawnForGear.equipment != null && this.SelPawnForGear.equipment.AllEquipment.Contains(thingWithComps)) + else if (thingWithComps != null && this.SelPawnForGear.equipment != null && this.SelPawnForGear.equipment.AllEquipmentListForReading.Contains(thingWithComps)) { this.SelPawnForGear.jobs.TryTakeOrderedJob(new Job(JobDefOf.DropEquipment, thingWithComps)); } else if (!t.def.destroyOnDrop) { Thing thing; - this.SelPawnForGear.inventory.innerContainer.TryDrop(t, this.SelPawnForGear.Position, this.SelPawnForGear.Map, ThingPlaceMode.Near, out thing, null); + Thing dropThing = t; + if (t.def.Minifiable) + dropThing = this.SelPawnForGear.inventory.innerContainer.FirstOrDefault(x => x.GetInnerIfMinified().ThingID == t.ThingID); + this.SelPawnForGear.inventory.innerContainer.TryDrop(dropThing, this.SelPawnForGear.Position, this.SelPawnForGear.Map, ThingPlaceMode.Near, out thing, null); } } private void InterfaceDropHaul(Thing t) { + if (SelPawnForGear.HoldTrackerIsHeld(t)) + SelPawnForGear.HoldTrackerForget(t); ThingWithComps thingWithComps = t as ThingWithComps; Apparel apparel = t as Apparel; if (apparel != null && this.SelPawnForGear.apparel != null && this.SelPawnForGear.apparel.WornApparel.Contains(apparel)) { this.SelPawnForGear.jobs.TryTakeOrderedJob(new Job(JobDefOf.RemoveApparel, apparel) { haulDroppedApparel = true }); } - else if (thingWithComps != null && this.SelPawnForGear.equipment != null && this.SelPawnForGear.equipment.AllEquipment.Contains(thingWithComps)) + else if (thingWithComps != null && this.SelPawnForGear.equipment != null && this.SelPawnForGear.equipment.AllEquipmentListForReading.Contains(thingWithComps)) { this.SelPawnForGear.jobs.TryTakeOrderedJob(new Job(JobDefOf.DropEquipment, thingWithComps)); } @@ -369,19 +421,9 @@ private void InterfaceDropHaul(Thing t) private void InterfaceEatThis(Thing t) { - ThingWithComps thingWithComps = t as ThingWithComps; - Thing food = t as Thing; - if (food != null && food.def.ingestible != null && food.def.ingestible.nutrition > 0) - { - Pawn selPawnForGear = SelPawn; - if (selPawnForGear.jobs.CanTakeOrderedJob() && selPawnForGear.RaceProps.EatsFood) - { - Job job = new Job(JobDefOf.Ingest, food); - job.count = FoodUtility.WillIngestStackCountOf(selPawnForGear, food.def); - job.playerForced = true; - selPawnForGear.jobs.TryTakeOrderedJob(job); - } - } + Job job = new Job(JobDefOf.Ingest, t); + job.count = Mathf.Min(t.stackCount, t.def.ingestible.maxNumToIngestAtOnce); + SelPawnForGear.jobs.TryTakeOrderedJob(job, JobTag.Misc); } #endregion Methods diff --git a/Source/CombatExtended/CombatExtended/Loadouts/Loadout.cs b/Source/CombatExtended/CombatExtended/Loadouts/Loadout.cs new file mode 100644 index 0000000000..7aed5fc667 --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Loadouts/Loadout.cs @@ -0,0 +1,241 @@ +using System.Text.RegularExpressions; +using RimWorld; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using UnityEngine; +using Verse; + +namespace CombatExtended +{ + /// + /// Contains a series of LoadoutSlot slots which define what a pawn using this loadout should try to keep in their inventory. + /// + public class Loadout : IExposable, ILoadReferenceable, IComparable + { + #region Fields + + public bool canBeDeleted = true; + public bool defaultLoadout = false; //NOTE: assumed that there is only ever one loadout which is marked default. + public string label; + internal int uniqueID; + private List _slots = new List(); + + #endregion Fields + + #region Constructors + + public Loadout() + { + // this constructor is also used by the scribe, in which case defaults generated here will get overwritten. + + // create a unique default name. + label = LoadoutManager.GetUniqueLabel(); + + // create a unique ID. + uniqueID = LoadoutManager.GetUniqueLoadoutID(); + } + + public Loadout(string label) + { + this.label = label; + + // create a unique ID. + uniqueID = LoadoutManager.GetUniqueLoadoutID(); + } + + /// + /// CAUTION: This constructor allows setting the uniqueID and goes unchecked for collisions. + /// + /// string label of new Loadout, preferably unique but not required. + /// int ID of new Loadout. This should be unique to avoid bugs. + public Loadout(string label, int uniqueID) + { + this.label = label; + this.uniqueID = uniqueID; + } + + /// + /// Handles adding any LoadoutGenercDef as LoadoutSlots if they are flagged as basic. + /// + public void AddBasicSlots() + { + IEnumerable defs = DefDatabase.AllDefs.Where(d => d.isBasic); + foreach (LoadoutGenericDef def in defs) + { + LoadoutSlot slot = new LoadoutSlot(def); + AddSlot(slot); + } + } + + #endregion Constructors + + #region Properties + + public float Bulk { get { return _slots.Sum(slot => slot.bulk * slot.count); } } + public string LabelCap { get { return label.CapitalizeFirst(); } } + public int SlotCount { get { return _slots.Count; } } + public List Slots { get { return _slots; } } + public float Weight { get { return _slots.Sum(slot => slot.mass * slot.count); } } + + #endregion Properties + + #region Methods + + // Returns a copy of this loadout slot with a new unique ID and a label based on the original name. + // LoadoutSlots need to be copied. + /// + /// Handles copying one Loadout to a new Loadout object. + /// + /// Loadout from which to copy properties/fields from. + /// new Loadout with copied properties from 'source' + /// + /// uniqueID will be different as required. + /// label will be different as required, but related to original. + /// Slots are copied (not the same object) but have the same properties as source.Slots. + /// + static Loadout Copy(Loadout source) + { + string newName = source.label; + Regex reNum = new Regex(@"^(.*?)\d+$"); + if (reNum.IsMatch(newName)) + newName = reNum.Replace(newName, @"$1"); + newName = LoadoutManager.GetUniqueLabel(newName); + + Loadout dest = new Loadout(newName); + dest.defaultLoadout = source.defaultLoadout; + dest.canBeDeleted = source.canBeDeleted; + dest._slots = new List(); + foreach(LoadoutSlot slot in source.Slots) + dest.AddSlot(slot.Copy()); + return dest; + } + + /// + /// Copies self to a new Loadout. . + /// + /// new Loadout with copied properties from self. + public Loadout Copy() + { + return Copy(this); + } + + /// + /// Handles adding a new LoadoutSlot to self. If self already has the same slot (based on Def) then increment the already present slot.count. + /// + /// LoadoutSlot to add to this Loadout. + public void AddSlot(LoadoutSlot slot) + { + LoadoutSlot old = _slots.FirstOrDefault(slot.isSameDef); + Log.Message(string.Concat("Adding ThingDef ", slot.thingDef == null ? "Null" : slot.thingDef.LabelCap, " added, count: ", slot.count)); + if (old != null) + old.count += slot.count; + else + _slots.Add(slot); + } + + /// + /// Handles the save/load process as part of IExplosable. + /// + public void ExposeData() + { + // basic info about this loadout + Scribe_Values.Look(ref label, "label"); + Scribe_Values.Look(ref uniqueID, "uniqueID"); + Scribe_Values.Look(ref canBeDeleted, "canBeDeleted", true); + Scribe_Values.Look(ref defaultLoadout, "defaultLoadout", false); + + // slots + Scribe_Collections.Look(ref _slots, "slots", LookMode.Deep); + } + + public string GetUniqueLoadID() + { + return "Loadout_" + label + "_" + uniqueID; + } + + /// + /// Used to move a slot in this Loadout to a different position in the List. + /// + /// LoadoutSlot being moved. + /// int position (index) to move slot to. + public void MoveSlot(LoadoutSlot slot, int toIndex) + { + int fromIndex = _slots.IndexOf(slot); + MoveTo(fromIndex, toIndex); + } + + /// + /// Used to remove a LoadoutSlot from this Loadout. + /// + /// LoadoutSlot to remove. + public void RemoveSlot(LoadoutSlot slot) + { + _slots.Remove(slot); + } + + /// + /// Used to remove a LoadoutSlot by index from this Loadout. Usually used when moving slots around (ie drag and drop). + /// + /// int index of this Loadout's Slot List to remove. + public void RemoveSlot(int index) + { + _slots.RemoveAt(index); + } + + /// + /// Used to move one LoadoutSlot into a different position in this Loadout's List. Generally connected to drag and drop activities by user. + /// + /// int index (source) in List to move from. + /// int index (target) in List to move to. + /// + private int MoveTo(int fromIndex, int toIndex) + { + if (fromIndex < 0 || fromIndex >= _slots.Count || toIndex < 0 || toIndex >= _slots.Count) + { + throw new Exception("Attempted to move i " + fromIndex + " to " + toIndex + ", bounds are [0," + (_slots.Count - 1) + "]."); + } + + // fetch the filter we're moving + LoadoutSlot temp = _slots[fromIndex]; + + // remove from old location + _slots.RemoveAt(fromIndex); + + // this may have changed the toIndex + if (fromIndex + 1 < toIndex) + toIndex--; + + // insert at new location + _slots.Insert(toIndex, temp); + return toIndex; + } + + #endregion Methods + + #region IComparable implementation + + /// + /// Used when sorting lists of Loadouts. + /// + /// other object to compare to. + /// int -1 indicating this is before obj, 0 indicates this is the same as obj, 1 indicates this is after obj. + public int CompareTo(object obj) + { + Loadout other = obj as Loadout; + if (other == null) + throw new ArgumentException("Loadout.CompareTo(obj), obj is not of type Loadout."); + + // initial case, default comes first. Currently there aren't more than one default and should never be. + if (this.defaultLoadout && other.defaultLoadout) return 0; + if (this.defaultLoadout) return -1; + if (other.defaultLoadout) return 1; + + // now we just compare by name of loadout... + return this.label.CompareTo(other.label); + } + + #endregion + } +} \ No newline at end of file diff --git a/Source/CombatRealism/CombatExtended/Loadouts/LoadoutAssignment.cs b/Source/CombatExtended/CombatExtended/Loadouts/LoadoutAssignment.cs similarity index 84% rename from Source/CombatRealism/CombatExtended/Loadouts/LoadoutAssignment.cs rename to Source/CombatExtended/CombatExtended/Loadouts/LoadoutAssignment.cs index f2222cd268..08bcbb1287 100644 --- a/Source/CombatRealism/CombatExtended/Loadouts/LoadoutAssignment.cs +++ b/Source/CombatExtended/CombatExtended/Loadouts/LoadoutAssignment.cs @@ -28,8 +28,8 @@ public bool Valid public void ExposeData() { - Scribe_References.LookReference( ref pawn, "pawn" ); - Scribe_References.LookReference( ref loadout, "loadout" ); + Scribe_References.Look( ref pawn, "pawn" ); + Scribe_References.Look( ref loadout, "loadout" ); #if DEBUG Log.Message( Scribe.mode + ", pawn: " + ( pawn == null ? "NULL" : pawn.NameStringShort ) + ", loadout: " + ( loadout == null ? "NULL" : loadout.label ) ); diff --git a/Source/CombatExtended/CombatExtended/Loadouts/LoadoutSlot.cs b/Source/CombatExtended/CombatExtended/Loadouts/LoadoutSlot.cs new file mode 100644 index 0000000000..7048ff77a0 --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Loadouts/LoadoutSlot.cs @@ -0,0 +1,148 @@ +using RimWorld; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using UnityEngine; +using Verse; + + +// Considered having a Generic and Specific slot and pass that through an interface but instead of a bunch of slot.Def != null there'd be a bunch of +// slot is Def and slot as Def... equally messy IMO and might still have some null checks tossed around. +namespace CombatExtended +{ + // this has been reduced to a thingCount at this point, with the exception of the added default count bit + // -- Fluffy + + /// + /// LoadoutSlot contains details about what items a Pawn's inventory should contain. + /// + public class LoadoutSlot : IExposable + { + #region Fields + + private const int _defaultCount = 1; + private int _count; + private Def _def; + private Type _type; // to help with save/load. + private LoadoutCountType _countType = LoadoutCountType.pickupDrop; // default mode for new loadout slots. + + #endregion Fields + + #region Constructors + + /// + /// Constructor for Specific slots which look for specific a ThingDef in order to fulfill their storage requirements. + /// + /// ThingDef to look for + /// int indicating number of items of ThingDef to store. + public LoadoutSlot( ThingDef def, int count = 1 ) + { + _type = typeof(ThingDef); + _count = count; + _def = def; + + _count = _count < 1 ? 1 : _count; + } + + /// + /// Constructor for Generic slots which use a lambda to determine what is picked up and stored. + /// + /// LoadoutGenericDef to use for picking up items. + /// Optional int how many should be picked up. If left blank then the default value from the LoadoutGenericDef is used. + public LoadoutSlot(LoadoutGenericDef def, int count = 0) + { + _type = typeof(LoadoutGenericDef); + if ( count < 1) + count = def.defaultCount; + + _count = count < 1 ? _count = 1 : _count = count; + _countType = def.defaultCountType; + _def = def; + } + + /// + /// Constructor exists for scribe and shouldn't generally be used. + /// + public LoadoutSlot() + { + // for scribe; if Count is set default will be overwritten. Def is always stored/loaded. + _count = _defaultCount; + } + + #endregion Constructors + + #region Properties + + public int count { get { return _count; } set { _count = value; } } + public LoadoutCountType countType { get { return _countType; } set { _countType = value; } } + public ThingDef thingDef { get { return (_def is ThingDef) ? (ThingDef)_def : null; } } + public LoadoutGenericDef genericDef { get { return (_def is LoadoutGenericDef) ? (LoadoutGenericDef)_def : null; } } + + // hand out some properties/fields of internal def for when user doesn't need to know specific/generic. + public string label { get { return _def.label; } } + public string LabelCap { get { return _def.LabelCap; } } + + // hide where the bulk/mass came from. Higher level doesn't care as long as it has a number. + public float bulk { get { return (thingDef != null ? thingDef.GetStatValueAbstract(CE_StatDefOf.Bulk) : genericDef.bulk); } } + public float mass { get { return (thingDef != null ? thingDef.GetStatValueAbstract(StatDefOf.Mass) : genericDef.mass); } } + + //public ThingDef def { get { return _def; } set { _def = value; } } + + #endregion Properties + + #region Methods + + /// + /// Used during Rimworld Save/Load. + /// + /// passed by ref since during load the contents of the variable is restored from the save. + public void ExposeData() + { + Scribe_Values.Look( ref _count, "count", _defaultCount ); + Scribe_Values.Look(ref _type, "DefType"); + ThingDef td = thingDef; + LoadoutGenericDef gd = genericDef; + if (_type == typeof(ThingDef)) + Scribe_Defs.Look(ref td, "def"); + if (_type == typeof(LoadoutGenericDef)) + Scribe_Defs.Look(ref gd, "def"); + if (Scribe.mode == LoadSaveMode.LoadingVars) + _def = (_type == typeof(ThingDef) ? td as Def : gd as Def); + //Scribe_Defs.LookDef( ref _def, "def" ); + + // when saving _def is defined. When loading _def should have gotten it's contents by now. + if (genericDef != null) + Scribe_Values.Look(ref _countType, "countType", LoadoutCountType.pickupDrop); + } + + /// + /// Used to determine if two slots are referring to the same def without exposing the internal def directly. + /// + /// The other slot to compare to. + /// bool true if both LoadoutSlots refer to the same def. + public bool isSameDef(LoadoutSlot slot) + { + Def def = (slot.thingDef as Def) ?? (slot.genericDef as Def); + return _def == def; + } + + /// + /// Handles copying self to a new LoadoutSlot. + /// + /// new LoadoutSlot containing the same key properties as self. + /// The stored def isn't deep copied and shouldn't be. + public LoadoutSlot Copy() + { + if (genericDef != null) + { + LoadoutSlot slot = new LoadoutSlot(genericDef, _count); + slot.countType = _countType; + return slot; + } // else if (thingDef != null) + return new LoadoutSlot(thingDef, _count); + } + + #endregion Methods + } +} \ No newline at end of file diff --git a/Source/CombatRealism/CombatExtended/Loadouts/MainTabWindow_OutfitsAndLoadouts.cs b/Source/CombatExtended/CombatExtended/Loadouts/MainTabWindow_OutfitsAndLoadouts.cs similarity index 90% rename from Source/CombatRealism/CombatExtended/Loadouts/MainTabWindow_OutfitsAndLoadouts.cs rename to Source/CombatExtended/CombatExtended/Loadouts/MainTabWindow_OutfitsAndLoadouts.cs index d0b7737d73..df7c08357f 100644 --- a/Source/CombatRealism/CombatExtended/Loadouts/MainTabWindow_OutfitsAndLoadouts.cs +++ b/Source/CombatExtended/CombatExtended/Loadouts/MainTabWindow_OutfitsAndLoadouts.cs @@ -130,6 +130,7 @@ public override void DoWindowContents(Rect canvas) if (Widgets.ButtonImage(editLoadoutRect, _iconEdit)) { Find.WindowStack.Add(new Dialog_ManageLoadouts(null)); + PlayerKnowledgeDatabase.KnowledgeDemonstrated(CE_ConceptDefOf.CE_Loadouts, KnowledgeAmount.Total); } Widgets.Label(weightRect, "CE_Weight".Translate()); Widgets.Label(bulkRect, "CE_Bulk".Translate()); @@ -193,13 +194,17 @@ protected override void DrawPawnRow(Rect rect, Pawn p) rowRect.height); Rect labelLoadoutRect = new Rect(loadoutRect.xMin, loadoutRect.yMin, - loadoutRect.width - _margin * 2 - _buttonSize, + loadoutRect.width - _margin * 3 - _buttonSize * 2, loadoutRect.height) .ContractedBy(_margin / 2f); Rect editLoadoutRect = new Rect(labelLoadoutRect.xMax + _margin, loadoutRect.yMin + ((loadoutRect.height - _buttonSize) / 2), _buttonSize, _buttonSize); + Rect forcedHoldRect = new Rect(labelLoadoutRect.xMax + _buttonSize + _margin * 2, + loadoutRect.yMin + ((loadoutRect.height - _buttonSize) /2), + _buttonSize, + _buttonSize); // fight or flight button HostilityResponseModeUtility.DrawResponseButton(responsePos, p); @@ -292,6 +297,7 @@ protected override void DrawPawnRow(Rect rect, Pawn p) // main button if (Widgets.ButtonText(labelLoadoutRect, p.GetLoadout().LabelCap, true, false)) { + LoadoutManager.SortLoadouts(); List options = new List(); foreach (Loadout loadout in LoadoutManager.Loadouts) { @@ -312,6 +318,26 @@ protected override void DrawPawnRow(Rect rect, Pawn p) Find.WindowStack.Add(new Dialog_ManageLoadouts(p.GetLoadout())); } + // clear forced held button + if (p.HoldTrackerAnythingHeld()) + { + TooltipHandler.TipRegion(forcedHoldRect, "ClearForcedApparel".Translate()); // "Clear forced" is sufficient and that's what this is at the moment. + if (Widgets.ButtonImage(forcedHoldRect, _iconClearForced)) // also can re-use the icon for clearing forced at the moment. + { + p.HoldTrackerClear(); // yes this will also delete records that haven't been picked up and thus not shown to the player... + } + TooltipHandler.TipRegion(forcedHoldRect, new TipSignal(delegate + { + string text = "CE_ForcedHold".Translate() + ":\n"; + foreach (HoldRecord rec in LoadoutManager.GetHoldRecords(p)) + { + if (!rec.pickedUp) continue; + text = text + "\n " + rec.thingDef.LabelCap + " x" + rec.count; + } + return text; + }, p.GetHashCode() * 613)); + } + // STATUS BARS // fetch the comp CompInventory comp = p.TryGetComp(); diff --git a/Source/CombatExtended/CombatExtended/Loadouts/PawnColumnWorker_Loadout.cs b/Source/CombatExtended/CombatExtended/Loadouts/PawnColumnWorker_Loadout.cs new file mode 100644 index 0000000000..d93c2a9cf1 --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Loadouts/PawnColumnWorker_Loadout.cs @@ -0,0 +1,121 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using UnityEngine; + +namespace CombatExtended +{ + // Mostly based on PawnColumnWorker_Outfit and adapted for loadouts. Should be kept up-to-date with any style changes in vanilla. -NIA + public class PawnColumnWorker_Loadout : PawnColumnWorker + { + private const int TopAreaHeight = 65; + + private const int ManageOutfitsButtonHeight = 32; + + internal static float _MinWidth = 197f; //194f default + internal static float _OptimalWidth = 214; //354f default + + public override void DoHeader(Rect rect, PawnTable table) + { + base.DoHeader(rect, table); + Rect rect2 = new Rect(rect.x, rect.y + (rect.height - TopAreaHeight), Mathf.Min(rect.width, 360f), ManageOutfitsButtonHeight); + if (Widgets.ButtonText(rect2, "CE_ManageLoadouts".Translate(), true, false, true)) + { + Find.WindowStack.Add(new Dialog_ManageLoadouts(null)); + PlayerKnowledgeDatabase.KnowledgeDemonstrated(CE_ConceptDefOf.CE_Loadouts, KnowledgeAmount.Total); + } + UIHighlighter.HighlightOpportunity(rect2, "CE_ManageLoadouts"); + } + + public override void DoCell(Rect rect, Pawn pawn, PawnTable table) + { + if (pawn.outfits == null) + { + return; + } + int num = Mathf.FloorToInt((rect.width - 4f) * 0.714285731f); + int num2 = Mathf.FloorToInt((rect.width - 4f) * 0.2857143f); + float num3 = rect.x; + + // Reduce width if we're adding a clear forced button + bool somethingIsForced = pawn.HoldTrackerAnythingHeld(); + Rect loadoutButtonRect = new Rect(num3, rect.y + 2f, (float)num, rect.height - 4f); + if (somethingIsForced) + { + loadoutButtonRect.width -= 4f + (float)num2; + } + + // Main loadout button + string label = pawn.GetLoadout().label.Truncate(loadoutButtonRect.width, null); + if (Widgets.ButtonText(loadoutButtonRect, label, true, false, true)) + { + LoadoutManager.SortLoadouts(); + List options = new List(); + foreach (Loadout loadout in LoadoutManager.Loadouts) + { + // need to create a local copy for delegate + Loadout localLoadout = loadout; + options.Add(new FloatMenuOption(localLoadout.LabelCap, delegate + { + pawn.SetLoadout(localLoadout); + }, MenuOptionPriority.Default, null, null)); + } + Find.WindowStack.Add(new FloatMenu(options)); + } + + // Clear forced button + num3 += loadoutButtonRect.width; + num3 += 4f; + Rect forcedHoldRect = new Rect(num3, rect.y + 2f, (float)num2, rect.height - 4f); + if (somethingIsForced) + { + if (Widgets.ButtonText(forcedHoldRect, "ClearForcedApparel".Translate(), true, false, true)) // "Clear forced" is sufficient and that's what this is at the moment. + { + pawn.HoldTrackerClear(); // yes this will also delete records that haven't been picked up and thus not shown to the player... + } + TooltipHandler.TipRegion(forcedHoldRect, new TipSignal(delegate + { + string text = "CE_ForcedHold".Translate() + ":\n"; + foreach (HoldRecord rec in LoadoutManager.GetHoldRecords(pawn)) + { + if (!rec.pickedUp) continue; + text = text + "\n " + rec.thingDef.LabelCap + " x" + rec.count; + } + return text; + }, pawn.GetHashCode() * 613)); + num3 += (float)num2; + num3 += 4f; + } + + Rect assignTabRect = new Rect(num3, rect.y + 2f, (float)num2, rect.height - 4f); + if (Widgets.ButtonText(assignTabRect, "AssignTabEdit".Translate(), true, false, true)) + { + Find.WindowStack.Add(new Dialog_ManageLoadouts(pawn.GetLoadout())); + } + num3 += (float)num2; + } + + public override int GetMinWidth(PawnTable table) + { + return Mathf.Max(base.GetMinWidth(table), Mathf.CeilToInt(_MinWidth)); + } + + public override int GetOptimalWidth(PawnTable table) + { + return Mathf.Clamp(Mathf.CeilToInt(_OptimalWidth), this.GetMinWidth(table), this.GetMaxWidth(table)); + } + + public override int GetMinHeaderHeight(PawnTable table) + { + return Mathf.Max(base.GetMinHeaderHeight(table), TopAreaHeight); + } + + public override int Compare(Pawn a, Pawn b) + { + return a.GetLoadoutId().CompareTo(b.GetLoadoutId()); + } + } +} diff --git a/Source/CombatExtended/CombatExtended/Loadouts/PawnColumnWorker_MassBulkBars.cs b/Source/CombatExtended/CombatExtended/Loadouts/PawnColumnWorker_MassBulkBars.cs new file mode 100644 index 0000000000..95c35d352e --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Loadouts/PawnColumnWorker_MassBulkBars.cs @@ -0,0 +1,76 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using UnityEngine; + +namespace CombatExtended +{ + // Mostly based on PawnColumnWorker_Loadout and adapted for mass/bulk. + public class PawnColumnWorker_MassBulkBar : PawnColumnWorker + { + private const int TopAreaHeight = 65; + private const string BarMass = "CEMass"; + private const string BarBulk = "CEBulk"; + private static int _MinWidth = 40; + private static int _OptimalWidth = 50; + + public override void DoHeader(Rect rect, PawnTable table) + { + base.DoHeader(rect, table); + } + + public override void DoCell(Rect rect, Pawn pawn, PawnTable table) + { + CompInventory inventory = pawn.TryGetComp(); + if (inventory == null) + { + return; + } + Rect barRect = new Rect(rect.x, rect.y + 2f, rect.width, rect.height - 4f); + if (this.def.defName.Equals(BarMass)) + { + Utility_Loadouts.DrawBar(barRect, inventory.currentBulk, inventory.capacityBulk, "", pawn.GetBulkTip()); + } + if (this.def.defName.Equals(BarBulk)) + { + Utility_Loadouts.DrawBar(barRect, inventory.currentWeight, inventory.capacityWeight, "", pawn.GetWeightTip()); + } + } + + public override int GetMinWidth(PawnTable table) + { + return Mathf.Max(base.GetMinWidth(table), Mathf.CeilToInt(_MinWidth)); + } + + public override int GetOptimalWidth(PawnTable table) + { + return Mathf.Clamp(Mathf.CeilToInt(_OptimalWidth), this.GetMinWidth(table), this.GetMaxWidth(table)); + } + + public override int GetMinHeaderHeight(PawnTable table) + { + return Mathf.Max(base.GetMinHeaderHeight(table), TopAreaHeight); + } + + public override int Compare(Pawn a, Pawn b) + { + CompInventory inventoryA = a.TryGetComp(); + CompInventory inventoryB = b.TryGetComp(); + if (inventoryA == null || inventoryB == null) + return 0; + + if (this.def.defName.Equals(BarMass)) + { + return (inventoryA.capacityBulk - inventoryA.currentBulk).CompareTo(inventoryB.capacityBulk - inventoryB.currentBulk); + } + if (this.def.defName.Equals(BarBulk)) + { + return (inventoryA.capacityWeight - inventoryA.currentWeight).CompareTo(inventoryB.capacityWeight - inventoryB.currentWeight); + } + return 0; + } + } +} diff --git a/Source/CombatExtended/CombatExtended/Loadouts/Tracker.cs b/Source/CombatExtended/CombatExtended/Loadouts/Tracker.cs new file mode 100644 index 0000000000..627dfbe644 --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Loadouts/Tracker.cs @@ -0,0 +1,62 @@ +using System.Text.RegularExpressions; +using RimWorld; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using UnityEngine; +using Verse; + +namespace CombatExtended +{ + /// + /// Contains a series of HoldRecord items. Functionally not that different from a List of HoldRecord but that list cannot be saved, this can be. + /// + public class Tracker : IExposable, ILoadReferenceable + { + #region Fields + private List _recs; + internal int uniqueID; + #endregion Fields + + #region Constructors + public Tracker() + { + // this constructor is also used by the scribe. + uniqueID = LoadoutManager.GetUniqueTrackerID(); + _recs = new List(); + } + + public Tracker(List newRecs) + { + uniqueID = LoadoutManager.GetUniqueTrackerID(); + _recs = newRecs; + } + #endregion Constructors + + #region Properties + public List recs => _recs; + #endregion Properties + + #region Methods + /// + /// Handles the save/load process as part of IExplosable. + /// + public void ExposeData() + { + // basic info about this loadout + Scribe_Values.Look(ref uniqueID, "TrackerID"); + Scribe_Collections.Look(ref _recs, "HoldRecords"); + } + + /// + /// Used by save/load to uniquely identify this instance. + /// + /// + public string GetUniqueLoadID() + { + return "Loadout_" + uniqueID; + } + #endregion Methods + } +} \ No newline at end of file diff --git a/Source/CombatExtended/CombatExtended/Loadouts/Utility_HoldTracker.cs b/Source/CombatExtended/CombatExtended/Loadouts/Utility_HoldTracker.cs new file mode 100644 index 0000000000..d02b094260 --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Loadouts/Utility_HoldTracker.cs @@ -0,0 +1,417 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using RimWorld; +using Verse; +using Verse.AI; + +namespace CombatExtended +{ + /// + /// Just wraps an int so that the counts can be modified in the Dictionary without ending up modifying the Dictionary. + /// + public class Integer + { + public int value; + public Integer(int num) + { + value = num; + } + } + + /// + /// Primary responsibility of HoldTracker concept is to remember any items that the Pawn was instructed (forced) to pickup while having a loadout. + /// + /// + /// Secondarily is also the primary party to consult when looking to automatically drop items since it is aware of HoldTracker concept as well as Loadout(Specific/Generic) concepts. + /// + static class Utility_HoldTracker + { + #region Fields + static private int _tickLastPurge = 0; + #endregion + + #region HoldTracker Methods + + /// + /// Used when a pawn is about to be ordered to pickup a Thing. + /// + /// + /// + static public void Notify_HoldTrackerJob(this Pawn pawn, Job job) + { + // make sure it's the right kind of job. + if (job.def != JobDefOf.TakeInventory) + throw new ArgumentException(); + + // if the pawn doesn't have a normal loadout, nothing to do... + if (pawn.GetLoadout().defaultLoadout) + return; + + // find out if we are already remembering this thing on this pawn... + List recs = LoadoutManager.GetHoldRecords(pawn); + + if (recs == null) + { + recs = new List(); + LoadoutManager.AddHoldRecords(pawn, recs); + } + + // could check isHeld but that tells us if there is a record AND it's been picked up. + HoldRecord rec = recs.FirstOrDefault(hr => hr.thingDef == job.targetA.Thing.def); + if (rec != null) + { + if (rec.pickedUp) + { + // modifying a record for which the pawn should have some of that thing in their inventory. + CompInventory inventory = pawn.TryGetComp(); + if (inventory != null) + rec.count = inventory.container.TotalStackCountOfDef(rec.thingDef) + job.count; + else + rec.count += job.count; // probably won't generally follow this code path but good not to throw an error if possible. + } + else + { + // modifying a record that hasn't been picked up... do it blind. + rec.count += job.count; + } + // useful debug message... + //Log.Message(string.Concat("Job was issued to pickup items for this existing record: ", rec)); + return; + } + // if we got this far we know that there isn't a record being stored for this thingDef... + rec = new HoldRecord(job.targetA.Thing.def, job.count); + recs.Add(rec); + // useful debug message... + //Log.Message(string.Concat("Job was issued to pickup for this new record: ", rec)); + } + + /// + /// Simply reports back if the pawn is tracking an item by ThingDef if it's been picked up. + /// + /// Pawn to check tracking on. + /// Thing who's def should be checked if being held. + /// + public static bool HoldTrackerIsHeld(this Pawn pawn, Thing thing) + { + List recs = LoadoutManager.GetHoldRecords(pawn); + if (recs != null && recs.Any(hr => hr.thingDef == thing.def)) + return true; + return false; + } + + /// + /// Is there any hold tracker records for this pawn? This doesn't care if an item is actually present in the pawn's inventory. + /// + /// Pawn who's HoldTracker is to be polled + /// bool indicating if the pawn has any HoldTracker records. + public static bool HoldTrackerAnythingHeld(this Pawn pawn) + { + List recs = LoadoutManager.GetHoldRecords(pawn); + if (recs == null || recs.NullOrEmpty()) + return false; + return recs.Any(r => r.pickedUp); + } + + public static void HoldTrackerClear(this Pawn pawn) + { + List recs = LoadoutManager.GetHoldRecords(pawn); + recs.Clear(); + } + + /// + /// This should be called periodically so that HoldTracker can remove items that are no longer in the inventory via a method which isn't being watched. + /// + /// The pawn who's tracker should be checked. + public static void HoldTrackerCleanUp(this Pawn pawn) + { + if (_tickLastPurge <= GenTicks.TicksAbs) + { + LoadoutManager.PurgeHoldTrackerRolls(); + _tickLastPurge = GenTicks.TicksAbs + GenDate.TicksPerDay; + } + List recs = LoadoutManager.GetHoldRecords(pawn); + CompInventory inventory = pawn.TryGetComp(); + if (recs == null || inventory == null) + return; + + for (int i = recs.Count - 1; i > 0; i--) + { + if (recs[i].pickedUp && inventory.container.TotalStackCountOfDef(recs[i].thingDef) <= 0) + recs.RemoveAt(i); + } + } + + /// + /// Called when a pawn is instructed to drop something as well as if the user explicitly specifies the item should no longer be held onto. + /// + /// + /// Thing who's def should be forgotten. + public static void HoldTrackerForget(this Pawn pawn, Thing thing) + { + List recs = LoadoutManager.GetHoldRecords(pawn); + if (recs == null) + { + Log.Error(string.Concat(pawn.Name, " wasn't being tracked by HoldTracker and tried to forget a ThingDef ", thing.def, ".")); + return; + } + HoldRecord rec = recs.FirstOrDefault(hr => hr.thingDef == thing.def); + if (rec != null) + recs.RemoveAt(recs.IndexOf(rec)); + } + + /// + /// Makes it convenient to fetch a pawn's holdTracker (List of HoldRecords). + /// + /// Pawn to fetch the records for. + /// List of HoldRecords otherwise known as the Pawn's holdTracker. + public static List GetHoldRecords(this Pawn pawn) + { + return LoadoutManager.GetHoldRecords(pawn); + } + + #endregion + + #region Loadout/Holdtracker methods. + + /// + /// Does a check on the pawn's inventory to determine if there is something that should be dropped. See GetExcessEquipment and GetExcessThing. + /// + /// bool, true if there is something the pawn needs to drop. + static public bool HasExcessThing(this Pawn pawn) + { + Thing ignore1; + int ignore2; + ThingWithComps ignore3; + return GetExcessEquipment(pawn, out ignore3) || GetExcessThing(pawn, out ignore1, out ignore2); + } + + /// + /// Similar to GetExcessThing though narrower in scope. If there is NOT a loadout which covers the equipped item, it should be dropped. + /// + /// + /// Thing which should be unequiped. + /// bool, true if there is equipment that should be unequipped. + static public bool GetExcessEquipment(this Pawn pawn, out ThingWithComps dropEquipment) + { + Loadout loadout = pawn.GetLoadout(); + dropEquipment = null; + if (loadout == null || (loadout != null && loadout.Slots.NullOrEmpty()) || pawn.equipment?.Primary == null) + return false; + + LoadoutSlot eqSlot = loadout.Slots.FirstOrDefault(s => s.count >= 1 && ((s.thingDef != null && s.thingDef == pawn.equipment.Primary.def) + || (s.genericDef != null && s.genericDef.lambda(pawn.equipment.Primary.def)))); + if (eqSlot == null) + { + dropEquipment = pawn.equipment.Primary; + return true; + } + return false; + } + + + /// + /// Shorthand to find out if there is more stuff to drop without caring about what there is to drop. + /// + /// Pawn who's inventory is to be checked against their Loadout and HoldRecord. + /// bool true indicates something to drop. + public static bool HasAnythingForDrop(this Pawn pawn) + { + Thing ignore1; + int ignore2; + return GetAnythingForDrop(pawn, out ignore1, out ignore2); + } + + /// + /// Called when trying to find something to drop (ie coming back from a caravan). This is useful even on pawns without a loadout. + /// + /// Thing to be dropped from inventory. + /// Amount to drop from inventory. + /// + static public bool GetAnythingForDrop(this Pawn pawn, out Thing dropThing, out int dropCount) + { + dropThing = null; + dropCount = 0; + + if (pawn.inventory == null || pawn.inventory.innerContainer == null) + return false; + + Loadout loadout = pawn.GetLoadout(); + if (loadout == null || loadout.Slots.NullOrEmpty()) + { + List recs = LoadoutManager.GetHoldRecords(pawn); + if (recs != null) + { + // hand out any inventory item not covered by a HoldRecord. + foreach (Thing thing in pawn.inventory.innerContainer) + { + int numContained = pawn.inventory.innerContainer.TotalStackCountOfDef(thing.def); + HoldRecord rec = recs.FirstOrDefault(hr => hr.thingDef == thing.def); + if (rec == null) + { + // we don't have a HoldRecord for this thing, drop it. + dropThing = thing; + dropCount = numContained > dropThing.stackCount ? dropThing.stackCount : numContained; + return true; + } + + if (numContained > rec.count) + { + dropThing = thing; + dropCount = numContained - rec.count; + dropCount = dropCount > dropThing.stackCount ? dropThing.stackCount : dropCount; + return true; + } + } + } else { + // we have nither a HoldTracker nor a Loadout that we can ask, so just pick stuff at random from Inventory. + dropThing = pawn.inventory.innerContainer.RandomElement(); + dropCount = dropThing.stackCount; + } + } else { + // hand out an item from GetExcessThing... + return GetExcessThing(pawn, out dropThing, out dropCount); + } + + return false; + } + + /// + /// Gets the Pawn's inventory as well as equipment and returns a dictionary keyed by ThingDef. + /// + /// Pawn to get the storage information from. + /// Dictionary containing keys of ThingDef and values of InventoryCount. + public static Dictionary GetStorageByThingDef(this Pawn pawn) + { + Dictionary storage = new Dictionary(); + CompAmmoUser gun; + // get the pawn's weapon. Also want ammo in the weapon. + if (pawn.equipment?.Primary != null) + { + storage.Add(pawn.equipment.Primary.def, new Integer(1)); + gun = pawn.equipment.Primary.TryGetComp(); + if (gun != null && gun.useAmmo) + storage.Add(gun.currentAmmo, new Integer(gun.curMagCount)); + } + // get the pawn's inventory + foreach (Thing thing in pawn.inventory.innerContainer) + { + if (!storage.ContainsKey(thing.def)) + storage.Add(thing.def, new Integer(0)); + storage[thing.def].value += thing.stackCount; + gun = thing.TryGetComp(); + if (gun != null && gun.useAmmo) + { + if (storage.ContainsKey(gun.currentAmmo)) + storage[gun.currentAmmo].value += gun.curMagCount; + else + storage.Add(gun.currentAmmo, new Integer(gun.curMagCount)); + } + } + + return storage; + } + + /// + /// Find an item that should be dropped from the pawn's inventory and how much to drop. + /// + /// + /// The thing which should be dropped. + /// The amount to drop. + /// bool, true indicates that the out variables are filled with something to do work on (drop). + // NOTE (ProfoundDarkness): Ended up doing this by nibbling away at the pawn's inventory (or dictionary representation of ThingDefs/Count). + // Probably not efficient but was easier to handle atm. + static public bool GetExcessThing(this Pawn pawn, out Thing dropThing, out int dropCount) + { + //(ProfoundDarkness) Thanks to erdelf on the RimWorldMod discord for helping me figure out some dictionary stuff and C# concepts related to 'Primitives' (pass by Value). + CompInventory inventory = pawn.TryGetComp(); + Loadout loadout = pawn.GetLoadout(); + List records = LoadoutManager.GetHoldRecords(pawn); + dropThing = null; + dropCount = 0; + + if (inventory == null || inventory.container == null || loadout == null || loadout.Slots.NullOrEmpty()) + return false; + + Dictionary listing = GetStorageByThingDef(pawn); + + // iterate over specifics and generics and Chip away at the dictionary. + foreach (LoadoutSlot slot in loadout.Slots) + { + if (slot.thingDef != null && listing.ContainsKey(slot.thingDef)) + { + listing[slot.thingDef].value -= slot.count; + if (listing[slot.thingDef].value <= 0) + listing.Remove(slot.thingDef); + } + if (slot.genericDef != null) + { + List killKeys = new List(); + int desiredCount = slot.count; + // find dictionary entries which corespond to covered slot. + foreach (ThingDef def in listing.Keys.Where(td => slot.genericDef.lambda(td))) + { + listing[def].value -= desiredCount; + if (listing[def].value <= 0) + { + desiredCount = 0 - listing[def].value; + killKeys.Add(def); // the thing in inventory is exausted, forget about it. + } else { + break; // we have satisifed this loadout so no need to keep enumerating. + } + } + // cleanup dictionary. + foreach (ThingDef def in killKeys) + listing.Remove(def); + } + } + + // if there is something left in the dictionary, that is what is to be dropped. + // Complicated by the fact that we now consider ammo in guns as part of the inventory... + if (listing.Any()) + { + if (records != null && !records.NullOrEmpty()) + { + // look at each remaining 'uneaten' thingdef in pawn's inventory. + foreach (ThingDef def in listing.Keys) + { + HoldRecord rec = records.FirstOrDefault(r => r.thingDef == def); + if (rec == null) + { + // the item we have extra of has no HoldRecord, drop it. + dropThing = inventory.container.FirstOrDefault(t => t.def == def); + if (dropThing != null) + { + dropCount = listing[def].value > dropThing.stackCount ? dropThing.stackCount : listing[def].value; + return true; + } + else if (rec.count > listing[def].value) + { + // the item we have extra of HAS a HoldRecord but the amount carried is above the limit of the HoldRecord, drop extra. + dropThing = pawn.inventory.innerContainer.FirstOrDefault(t => t.def == def); + if (dropThing != null) + { + dropCount = listing[def].value - rec.count; + dropCount = dropCount > dropThing.stackCount ? dropThing.stackCount : dropCount; + return true; + } + } + } + } + } else { + foreach (ThingDef def in listing.Keys) + { + dropThing = inventory.container.FirstOrDefault(t => t.def == def); + if (dropThing != null) + { + dropCount = listing[def].value > dropThing.stackCount ? dropThing.stackCount : listing[def].value; + return true; + } + } + } + } // else + return false; + } + #endregion + } +} \ No newline at end of file diff --git a/Source/CombatRealism/CombatExtended/Loadouts/Utility_Loadouts.cs b/Source/CombatExtended/CombatExtended/Loadouts/Utility_Loadouts.cs similarity index 75% rename from Source/CombatRealism/CombatExtended/Loadouts/Utility_Loadouts.cs rename to Source/CombatExtended/CombatExtended/Loadouts/Utility_Loadouts.cs index 6d92bb3835..b622621354 100644 --- a/Source/CombatRealism/CombatExtended/Loadouts/Utility_Loadouts.cs +++ b/Source/CombatExtended/CombatExtended/Loadouts/Utility_Loadouts.cs @@ -1,4 +1,5 @@ -using RimWorld; +using System.Text.RegularExpressions; +using RimWorld; using System; using System.Collections.Generic; using System.Linq; @@ -176,6 +177,12 @@ public static string GetWeightAndBulkTip(this ThingDef def, int count = 1) (count != 1 ? " x" + count : "") + "\n" + def.GetWeightTip(count) + "\n" + def.GetBulkTip(count); } + + public static string GetWeightAndBulkTip(this LoadoutGenericDef def, int count = 1) + { + return "CE_Weight".Translate() + ": " + StatDefOf.Mass.ValueToString(def.mass * count, StatDefOf.Mass.toStringNumberSense) + "\n" + + "CE_Bulk".Translate() + ": " + CE_StatDefOf.Bulk.ValueToString(def.bulk * count, CE_StatDefOf.Bulk.toStringNumberSense); + } public static string GetWeightTip(this ThingDef def, int count = 1) { @@ -265,8 +272,81 @@ private static float Median(float[] xs) else return ys[Mathf.FloorToInt(ys.Length / 2)]; } - - + + /// + /// Generates a loadout from a pawn's current equipment and inventory. Attempts to put items which fit in Generics that are default/DropExcess into said Generic. + /// + /// Pawn to check equipment/inventory on and generate a Loadout from. + /// Loadout which was generated based on Pawn's inventory. + public static Loadout GenerateLoadoutFromPawn(this Pawn pawn) + { + // generate the name for this new pawn based loadout. + string newName = string.Concat(pawn.NameStringShort, " ", "CE_DefaultLoadoutName".Translate()); + Regex reNum = new Regex(@"^(.*?)\d+$"); + if (reNum.IsMatch(newName)) + newName = reNum.Replace(newName, @"$1"); + newName = LoadoutManager.GetUniqueLabel(newName); + + // set basic loadout properties. + Loadout loadout = new Loadout(newName); + loadout.defaultLoadout = false; + loadout.canBeDeleted = true; + + LoadoutSlot slot = null; + + // grab the pawn's current equipment as a loadoutslot. + if (pawn.equipment?.Primary != null) + { + slot = new LoadoutSlot(pawn.equipment.Primary.def); + loadout.AddSlot(slot); + } + + // get a list of generics which are drop only. Assumes that anything that doesn't fit here is a Specific slot later. + IEnumerable generics = DefDatabase.AllDefs.Where(gd => gd.defaultCountType == LoadoutCountType.dropExcess); + + // enumerate each item in the pawn's inventory and add appropriate slots. + foreach (Thing thing in pawn.inventory.innerContainer) + { + LoadoutGenericDef foundGeneric = null; + // first check if it's a generic-able item... + foreach(LoadoutGenericDef generic in generics) + { + if (generic.lambda(thing.def)) + { + foundGeneric = generic; + break; + } + } + + // assign a loadout slot that fits the thing. + if (foundGeneric != null) + { + slot = new LoadoutSlot(foundGeneric, thing.stackCount); + } else { + slot = new LoadoutSlot(thing.def, thing.stackCount); + } + + // add the slot (this also takes care of adding to existing slots) + loadout.AddSlot(slot); + } + + // finally check the loadout and make sure that it has sufficient generics like what happens with a new loadout in the management UI. + foreach (LoadoutGenericDef generic in generics.Where(gd => gd.isBasic)) + { + slot = loadout.Slots.FirstOrDefault(s => s.genericDef == generic); + if (slot != null) + { + if (slot.count < slot.genericDef.defaultCount) + slot.count = slot.genericDef.defaultCount; + } else { + slot = new LoadoutSlot(generic); + loadout.AddSlot(slot); + } + } + + return loadout; + } + #endregion Methods } } diff --git a/Source/CombatRealism/CombatExtended/MassBulkUtility.cs b/Source/CombatExtended/CombatExtended/MassBulkUtility.cs similarity index 100% rename from Source/CombatRealism/CombatExtended/MassBulkUtility.cs rename to Source/CombatExtended/CombatExtended/MassBulkUtility.cs diff --git a/Source/CombatExtended/CombatExtended/ParryTracker.cs b/Source/CombatExtended/CombatExtended/ParryTracker.cs new file mode 100644 index 0000000000..bf27f6b832 --- /dev/null +++ b/Source/CombatExtended/CombatExtended/ParryTracker.cs @@ -0,0 +1,94 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using UnityEngine; + +namespace CombatExtended +{ + public class ParryTracker : MapComponent + { + private struct ParryCounter + { + public int parries; + private int timeoutTick; + + public ParryCounter(int timeoutTicks) + { + parries = 0; + timeoutTick = Find.TickManager.TicksGame + timeoutTicks; + } + + public bool ShouldTimeout() + { + return Find.TickManager.TicksGame >= timeoutTick; + } + } + + private const int SkillPerParry = 4; // Award another parry per this many skill levels + private const int TicksToTimeout = 120; // Reset parry counter after this many ticks + + private Dictionary parryTracker = new Dictionary(); + + public ParryTracker(Map map) : base(map) + { + } + + private int GetUsedParriesFor(Pawn pawn) + { + ParryCounter counter; + if (!parryTracker.TryGetValue(pawn, out counter)) + { + return 0; + } + return counter.parries; + } + + public bool CheckCanParry(Pawn pawn) + { + if (pawn == null) + { + Log.Error("CE tried checking CanParry with Null-Pawn"); + return false; + } + + int parriesLeft = Mathf.RoundToInt(pawn.skills.GetSkill(SkillDefOf.Melee).Level / SkillPerParry) - GetUsedParriesFor(pawn); + return parriesLeft > 0; + } + + public void RegisterParryFor(Pawn pawn, int timeoutTicks) + { + ParryCounter counter; + if (!parryTracker.TryGetValue(pawn, out counter)) + { + // Register new pawn in tracker + counter = new ParryCounter(timeoutTicks); + parryTracker.Add(pawn, counter); + } + counter.parries++; + } + + public void ResetParriesFor(Pawn pawn) + { + parryTracker.Remove(pawn); + } + + public override void MapComponentTick() + { + if (Find.TickManager.TicksGame % 10 == 0) + { + foreach (var entry in parryTracker.Where(kvp => kvp.Value.ShouldTimeout()).ToArray()) + { + parryTracker.Remove(entry.Key); + } + } + } + + public override void ExposeData() + { + // TODO Save parryTracker + } + } +} diff --git a/Source/CombatRealism/CombatExtended/Projectiles/ArtilleryMarker.cs b/Source/CombatExtended/CombatExtended/Projectiles/ArtilleryMarker.cs similarity index 76% rename from Source/CombatRealism/CombatExtended/Projectiles/ArtilleryMarker.cs rename to Source/CombatExtended/CombatExtended/Projectiles/ArtilleryMarker.cs index 4fa627308c..6fafaaf0f8 100644 --- a/Source/CombatRealism/CombatExtended/Projectiles/ArtilleryMarker.cs +++ b/Source/CombatExtended/CombatExtended/Projectiles/ArtilleryMarker.cs @@ -13,7 +13,7 @@ class ArtilleryMarker : AttachableThing public const string MarkerDef = "ArtilleryMarker"; public float aimingAccuracy = 1f; - public float aimEfficiency = 1f; + public float sightsEfficiency = 1f; public float lightingShift = 0f; public float weatherShift = 0f; @@ -27,11 +27,11 @@ public override string InspectStringAddon public override void ExposeData() { base.ExposeData(); - Scribe_Values.LookValue(ref this.aimingAccuracy, "aimingAccuracy"); - Scribe_Values.LookValue(ref this.aimEfficiency, "aimEfficiency"); - Scribe_Values.LookValue(ref this.lightingShift, "lightingShift"); - Scribe_Values.LookValue(ref this.weatherShift, "weatherShift"); - Scribe_Values.LookValue(ref this.lifetimeTicks, "lifetimeTicks"); + Scribe_Values.Look(ref this.aimingAccuracy, "aimingAccuracy"); + Scribe_Values.Look(ref this.sightsEfficiency, "sightsEfficiency"); + Scribe_Values.Look(ref this.lightingShift, "lightingShift"); + Scribe_Values.Look(ref this.weatherShift, "weatherShift"); + Scribe_Values.Look(ref this.lifetimeTicks, "lifetimeTicks"); } public override void Tick() diff --git a/Source/CombatExtended/CombatExtended/Projectiles/BulletCE.cs b/Source/CombatExtended/CombatExtended/Projectiles/BulletCE.cs new file mode 100644 index 0000000000..02a0b832e0 --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Projectiles/BulletCE.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Verse; +using Verse.Sound; +using RimWorld; +using UnityEngine; + +namespace CombatExtended +{ + public class BulletCE : ProjectileCE + { + private const float StunChance = 0.1f; + + protected override void Impact(Thing hitThing) + { + Map map = base.Map; + base.Impact(hitThing); + if (hitThing != null) + { + int damageAmountBase = def.projectile.damageAmountBase; + ThingDef equipmentDef = this.equipmentDef; + DamageDefExtensionCE damDefCE = def.projectile.damageDef.GetModExtension() ?? new DamageDefExtensionCE(); + + DamageInfo dinfo = new DamageInfo( + def.projectile.damageDef, + damageAmountBase, + ExactRotation.eulerAngles.y, + launcher, + null, + def); + + // Set impact height + BodyPartDepth partDepth = damDefCE != null && damDefCE.harmOnlyOutsideLayers ? BodyPartDepth.Outside : BodyPartDepth.Undefined; + BodyPartHeight partHeight = new CollisionVertical(hitThing).GetCollisionBodyHeight(Height); + dinfo.SetBodyRegion(partHeight, partDepth); + if (damDefCE != null && damDefCE.harmOnlyOutsideLayers) dinfo.SetBodyRegion(BodyPartHeight.Undefined, BodyPartDepth.Outside); + + // Apply primary damage + hitThing.TakeDamage(dinfo); + } + else + { + SoundDefOf.BulletImpactGround.PlayOneShot(new TargetInfo(base.Position, map, false)); + MoteMaker.MakeStaticMote(ExactPosition, map, ThingDefOf.Mote_ShotHit_Dirt, 1f); + } + } + } +} \ No newline at end of file diff --git a/Source/CombatExtended/CombatExtended/Projectiles/ProjectileCE.cs b/Source/CombatExtended/CombatExtended/Projectiles/ProjectileCE.cs new file mode 100644 index 0000000000..c0eb37d7bf --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Projectiles/ProjectileCE.cs @@ -0,0 +1,649 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using RimWorld; +using UnityEngine; +using Verse; +using Verse.Sound; + +namespace CombatExtended +{ + public abstract class ProjectileCE : ThingWithComps + { + private const int SuppressionRadius = 3; // Suppression is applied within this area + private const int collisionCheckSize = 5; // Check for collision with multi-cell pawns and apply suppression in area of this size, centered on flight path. + + protected Vector2 origin; + + private IntVec3 originInt = new IntVec3(0, -1000, 0); + protected IntVec3 OriginIV3 + { + get + { + if (originInt.y < 0) + { + originInt = new IntVec3(origin); + } + return originInt; + } + } + + protected Vector3 destinationInt = new Vector3(0f, 0f, -1f); + protected Vector2 Destination + { + get + { + if (destinationInt.z < 0) + { + destinationInt = GetDestination(origin, shotAngle, shotRotation, shotSpeed, shotHeight); + destinationInt.z = 0f; + } + // Since returning as a Vector2 yields Vector2(Vector3.x, Vector3.y)! + return destinationInt; + } + } + + protected ThingDef equipmentDef; + protected Thing launcher; + public float minCollisionSqr; + public bool canTargetSelf; + + #region Vanilla + protected bool landed; + protected int ticksToImpact; + private Sustainer ambientSustainer; + #endregion + + private float suppressionAmount; + + #region FreeIntercept + private static List checkedCells = new List(); + #endregion + + float startingTicksToImpactInt = -1f; + protected float StartingTicksToImpact + { + get + { + if (startingTicksToImpactInt < 0f) + { + // Optimization in case shotHeight is zero (for example for fragments) + if (shotHeight < 0.001f) + { + // Opt-out in case the projectile is to collide instantly + if (shotAngle < 0f) + { + destinationInt = origin; + startingTicksToImpactInt = 0f; + ImpactSomething(); + return 0f; + } + // Multiplied by ticksPerSecond since the calculated time is actually in seconds. + startingTicksToImpactInt = (float)((origin - Destination).magnitude / (Mathf.Cos(shotAngle) * shotSpeed)) * (float)GenTicks.TicksPerRealSecond; + return startingTicksToImpactInt; + } + + startingTicksToImpactInt = GetFlightTime() * (float)GenTicks.TicksPerRealSecond; + } + return startingTicksToImpactInt; + } + } + + #region Height + private bool heightOutdated = true; + private float heightInt = 0f; + /// + /// If heightOutdated is true, Height calculates the quadratic formula (g/2)t^2 + (-v_0y)t + (y-y0) for {g -> gravity, v_0y -> shotSpeed * Mathf.Sin(shotAngle), y0 -> shotHeight, t -> seconds} to find y rounded to the nearest 3 decimals. + /// + /// If heightOutdated is false, it returns a locally stored value heightInt which is the product of previous calculation. + /// + public float Height + { + get + { + if (heightOutdated) + { + heightInt = GetHeightAtTicks(FlightTicks); + heightOutdated = false; + } + return heightInt; + } + } + #endregion + + #region Ticks/Seconds + /// + /// An integer ceil value of StartingTicksToImpact. Is equal to -1 when not initialized. + /// + int intTicksToImpact = -1; + protected int IntTicksToImpact + { + get + { + if (intTicksToImpact < 0) + { + intTicksToImpact = Mathf.CeilToInt(StartingTicksToImpact); + } + return intTicksToImpact; + } + } + + /// + /// The amount of ticks this projectile has remained in the air for. + /// + protected int FlightTicks + { + get + { + return IntTicksToImpact - ticksToImpact; + } + } + protected float fTicks + { + get + { + return (ticksToImpact == 0 ? StartingTicksToImpact : (float)FlightTicks); + } + } + #endregion + + #region Position + private Vector2 Vec2Position + { + get + { + return Vector2.Lerp(origin, Destination, fTicks / StartingTicksToImpact); + } + } + + public virtual Vector3 ExactPosition + { + get + { + var v = Vec2Position; + return new Vector3(v.x, 0f, v.y); + } + } + + public virtual Quaternion ExactRotation + { + get + { + return Quaternion.AngleAxis(shotRotation, Vector3.up); + } + } + + public override Vector3 DrawPos + { + get + { + var v = Vec2Position; + return new Vector3(v.x, def.Altitude, v.y); + //return new Vector3(v.x, def.Altitude, v.y + 0.5f*Height); + } + } + #endregion + + /// + /// Angle off the ground [radians]. + /// + public float shotAngle = 0f; + /// + /// Angle rotation between shooter and destination [degrees]. + /// + public float shotRotation = 0f; + /// + /// Shot height in vertical cells. Humans start their shot at 0.85f [vcells]. + /// + public float shotHeight = 0f; + /// + /// The assigned shot speed, in general equal to the projectile.def.speed value. + /// + public float shotSpeed = -1f; + + private float _gravityFactor = -1; + + private float GravityFactor + { + get + { + if (_gravityFactor < 0) + { + _gravityFactor = CE_Utility.gravityConst; + var props = def.projectile as ProjectilePropertiesCE; + if (props != null) _gravityFactor = props.Gravity; + } + return _gravityFactor; + } + } + + /* + * *** End of class variables *** + */ + + #region Methods + + /// + /// Saves new variables shotAngle, shotHeight, shotSpeed. + /// + public override void ExposeData() + { + base.ExposeData(); + + if (Scribe.mode == LoadSaveMode.Saving && launcher != null && launcher.Destroyed) + { + launcher = null; + } + Scribe_Values.Look(ref origin, "ori", default(Vector2), true); + + Scribe_Defs.Look(ref equipmentDef, "ed"); + Scribe_References.Look(ref launcher, "lcr"); + Scribe_Values.Look(ref landed, "lnd", false, false); + Scribe_Values.Look(ref ticksToImpact, "tTI", 0, true); + + //Here be new variables + Scribe_Values.Look(ref shotAngle, "ang", 0f, true); + Scribe_Values.Look(ref shotRotation, "rot", 0f, true); + Scribe_Values.Look(ref shotHeight, "hgt", 0f, true); + Scribe_Values.Look(ref shotSpeed, "spd", 0f, true); + Scribe_Values.Look(ref canTargetSelf, "cts", false, false); + } + + /// + /// Physics-enabled Launch() method. + /// + /// The Thing that launched this projectile. + /// The origin of the projectile (different from the launcher for e.g grenade fragments) + /// Angle off the ground [radians]. + /// Rotation between shooter and destination [degrees]. + /// The shot height, usually the max height of the non-pawn caster, a portion of the height of the pawn caster OR zero. (default: 0) + /// The shot speed (default: def.projectile.speed) + /// The equipment used to fire the projectile. + public virtual void Launch(Thing launcher, Vector2 origin, float shotAngle, float shotRotation, float shotHeight = 0f, float shotSpeed = -1f, Thing equipment = null) + { + this.shotAngle = shotAngle; + this.shotHeight = shotHeight; + this.shotRotation = shotRotation; + + Launch(launcher, origin, equipment); + if (shotSpeed > 0f) + { + this.shotSpeed = shotSpeed; + } + + ticksToImpact = IntTicksToImpact; + } + + public virtual void Launch(Thing launcher, Vector2 origin, Thing equipment = null) + { + this.shotSpeed = def.projectile.speed; + this.launcher = launcher; + this.origin = origin; + equipmentDef = (equipment != null) ? equipment.def : null; + + if (!def.projectile.soundAmbient.NullOrUndefined()) + { + SoundInfo info = SoundInfo.InMap(this, MaintenanceType.PerTick); + ambientSustainer = def.projectile.soundAmbient.TrySpawnSustainer(info); + } + } + + //Removed minimum collision distance + private bool CheckForCollisionBetween(Vector2 lastExactPos, Vector2 newExactPos) + { + var lastPos = new IntVec3(lastExactPos); + var newPos = new IntVec3(newExactPos); + // Sanity checks + if (newPos == lastPos) + { + return false; + } + if (!lastPos.InBounds(base.Map) || !newPos.InBounds(base.Map)) + { + return false; + } + + if (DebugViewSettings.drawInterceptChecks) + { + Map.debugDrawer.FlashLine(lastPos, newPos); + } + + // Determine flight path + var from = new Vector3(lastExactPos.x, GetHeightAtTicks(FlightTicks - 1), lastExactPos.y); + var dest = new Vector3(newExactPos.x, GetHeightAtTicks(FlightTicks), newExactPos.y); + var shotLine = new Ray(from, (dest - from)); + + // Early opt-out, if we only moved by one cell only check the new cell + if ((newPos - lastPos).LengthManhattan == 1) + { + if (DebugViewSettings.drawInterceptChecks) + { + Map.debugDrawer.FlashCell(newPos, 1, "1"); + } + return CheckCellForCollision(newPos, shotLine); + } + + // Iterate through all cells between the last and the new position + var cells = GenSight.PointsOnLineOfSight(lastPos, newPos); + foreach(IntVec3 cell in cells) + { + if (CheckCellForCollision(cell, shotLine)) + { + return true; + } + + if (DebugViewSettings.drawInterceptChecks) + { + Map.debugDrawer.FlashCell(cell, 1, "o"); + } + } + return false; + } + + /// + /// Checks whether a collision occurs along flight path within this cell. + /// + /// Where to check for collisions in + /// Projectile's flight path + /// True if collision occured, false otherwise + private bool CheckCellForCollision(IntVec3 cell, Ray shotLine) + { + //Check for minimum collision distance + float distFromOrigin = (cell - OriginIV3).LengthHorizontalSquared; + if (!def.projectile.alwaysFreeIntercept + && minCollisionSqr <= 1f + ? distFromOrigin < 1f + : distFromOrigin < Mathf.Min(144f, minCollisionSqr / 4)) + { + return false; + } + List mainThingList = new List(base.Map.thingGrid.ThingsListAtFast(cell)).Where(t => t is Pawn || t.def.Fillage != FillCategory.None).ToList(); + + //Find pawns in adjacent cells and append them to main list + List adjList = new List(); + adjList.AddRange(GenAdj.CellsAdjacentCardinal(cell, Rot4.FromAngleFlat(shotRotation), new IntVec2(collisionCheckSize, 0)).ToList()); + + //Iterate through adjacent cells and find all the pawns + foreach (IntVec3 curCell in adjList) + { + if (curCell != cell && curCell.InBounds(base.Map)) + { + mainThingList.AddRange(Map.thingGrid.ThingsListAtFast(curCell) + .Where(thing => thing.def.category == ThingCategory.Pawn)); + + if (DebugViewSettings.drawInterceptChecks) + { + Map.debugDrawer.FlashCell(curCell, 0.7f); + } + } + } + + foreach (Thing thing in mainThingList.Distinct()) + { + if (thing == launcher && !canTargetSelf) continue; + + // Skip collision detection for walls and such + if (thing.def.Fillage == FillCategory.Full) + { + Impact(thing); + return true; + } + + // Apply suppression + Pawn pawn = thing as Pawn; + if (pawn != null) + { + ApplySuppression(pawn); + } + + // Check for collision + if (TryCollideWith(thing, shotLine)) return true; + } + return false; + } + + /// + /// Tries to impact the thing based on whether it intersects the given flight path. Trees have RNG chance to not collide even on intersection. + /// + /// What to impact + /// Projectile's path of travel + /// True if impact occured, false otherwise + private bool TryCollideWith(Thing thing, Ray shotLine) + { + // Trees have RNG chance to collide + if (thing.IsTree()) + { + float chance = thing.def.fillPercent * ((thing.Position - OriginIV3).LengthHorizontal / 40); + if (Controller.settings.DebugShowTreeCollisionChance) MoteMaker.ThrowText(thing.Position.ToVector3Shifted(), thing.Map, chance.ToString()); + if (!Rand.Chance(chance)) return false; + } + else + { + var bounds = CE_Utility.GetBoundsFor(thing); + if (!bounds.IntersectRay(shotLine)) + { + return false; + } + } + + + if (DebugViewSettings.drawInterceptChecks) MoteMaker.ThrowText(thing.Position.ToVector3Shifted(), thing.Map, "x", Color.red); + Impact(thing); + return true; + } + + private void ApplySuppression(Pawn pawn) + { + ShieldBelt shield = null; + if (pawn.RaceProps.Humanlike) + { + // check for shield user + + List wornApparel = pawn.apparel.WornApparel; + for (int i = 0; i < wornApparel.Count; i++) + { + var personalShield = wornApparel[i] as ShieldBelt; + if (personalShield != null) + { + shield = personalShield; + break; + } + } + } + //Add suppression + CompSuppressable compSuppressable = pawn.TryGetComp(); + if (compSuppressable != null + && pawn.Faction != launcher?.Faction + && (shield == null || shield?.ShieldState == ShieldState.Resetting)) + { + suppressionAmount = def.projectile.damageAmountBase; + ProjectilePropertiesCE propsCE = def.projectile as ProjectilePropertiesCE; + float penetrationAmount = propsCE == null ? 0f : propsCE.armorPenetration; + suppressionAmount *= 1 - Mathf.Clamp(compSuppressable.ParentArmor - penetrationAmount, 0, 1); + compSuppressable.AddSuppression(suppressionAmount, OriginIV3); + } + } + + //Unmodified + public override void Tick() + { + base.Tick(); + if (landed) + { + return; + } + Vector2 lastExactPosition = Vec2Position; + ticksToImpact--; + if (!ExactPosition.InBounds(base.Map)) + { + ticksToImpact++; + Position = ExactPosition.ToIntVec3(); + Destroy(DestroyMode.Vanish); + return; + } + heightOutdated = true; + if (ticksToImpact >= 0 + && !def.projectile.flyOverhead + && CheckForCollisionBetween(lastExactPosition, Vec2Position)) + { + return; + } + Position = ExactPosition.ToIntVec3(); + if (ticksToImpact == 60 && Find.TickManager.CurTimeSpeed == TimeSpeed.Normal && + def.projectile.soundImpactAnticipate != null) + { + def.projectile.soundImpactAnticipate.PlayOneShot(this); + } + if (ticksToImpact <= 0) + { + ImpactSomething(); + return; + } + if (ambientSustainer != null) + { + ambientSustainer.Maintain(); + } + } + + //Unmodified + public override void Draw() + { + Graphics.DrawMesh(MeshPool.plane10, DrawPos, ExactRotation, def.DrawMatSingle, 0); + Comps_PostDraw(); + } + + //Modified collision with downed pawns + private void ImpactSomething() + { + //Not modified, just mortar code + if (def.projectile.flyOverhead) + { + RoofDef roofDef = base.Map.roofGrid.RoofAt(Position); + if (roofDef != null) + { + if (roofDef.isThickRoof) + { + this.def.projectile.soundHitThickRoof.PlayOneShot(new TargetInfo(base.Position, base.Map, false)); + this.Destroy(DestroyMode.Vanish); + return; + } + if (base.Position.GetEdifice(base.Map) == null || base.Position.GetEdifice(base.Map).def.Fillage != FillCategory.Full) + { + RoofCollapserImmediate.DropRoofInCells(base.Position, base.Map); + } + } + } + //Modified + var height = Height; + + // Determine flight path - Need to refactor this to be less hacky + var pos = Vec2Position; + var lastPos = Vector2.Lerp(this.origin, Destination, (fTicks - 1) / StartingTicksToImpact); + + var vec3dest = new Vector3(pos.x, GetHeightAtTicks(FlightTicks), pos.y); + var vec3lastPos = new Vector3(lastPos.x, GetHeightAtTicks(FlightTicks - 1), lastPos.y); + var shotLine = new Ray(vec3lastPos, (vec3dest - vec3lastPos)); + + // FIXME : Early opt-out + Thing thing = Position.GetFirstPawn(Map); + if (thing != null && TryCollideWith(thing, shotLine)) + { + return; + } + List list = Map.thingGrid.ThingsListAt(Position).Where(t => t is Pawn || t.def.Fillage != FillCategory.None).ToList(); + if (list.Count > 0) + { + foreach (var thing2 in list) { + if (TryCollideWith(thing2, shotLine)) + return; + } + } + Impact(null); + } + + protected virtual void Impact(Thing hitThing) + { + CompExplosiveCE comp = this.TryGetComp(); + if (comp != null && Position.IsValid) + { + comp.Explode(launcher, Position, Find.VisibleMap); + } + + // Apply suppression around impact area + var suppressThings = GenRadial.RadialDistinctThingsAround(Position, Map, SuppressionRadius + def.projectile.explosionRadius, true); + foreach (Thing thing in suppressThings) + { + Pawn pawn = thing as Pawn; + if (pawn != null) ApplySuppression(pawn); + } + + Destroy(); + } + + private float GetHeightAtTicks(int ticks) + { + float seconds = ((float)ticks) / GenTicks.TicksPerRealSecond; + return (float)Math.Round(shotHeight + shotSpeed * Mathf.Sin(shotAngle) * seconds - (GravityFactor * seconds * seconds) / 2f, 3); + } + + #region Ballistics + /// + /// Calculates the time in seconds the arc characterized by angle, shotHeight takes to traverse at speed velocity - e.g until the height reaches zero. Does not take into account air resistance. + /// + /// Projectile velocity in cells per second. + /// Shot angle in radians off the ground. + /// Height from which the projectile is fired in vertical cells. + /// Time in seconds that the projectile will take to traverse the given arc. + private float GetFlightTime() + { + //Calculates quadratic formula (g/2)t^2 + (-v_0y)t + (y-y0) for {g -> gravity, v_0y -> vSin, y -> 0, y0 -> shotHeight} to find t in fractional ticks where height equals zero. + return (Mathf.Sin(shotAngle) * shotSpeed + Mathf.Sqrt(Mathf.Pow(Mathf.Sin(shotAngle) * shotSpeed, 2f) + 2f * GravityFactor * shotHeight)) / GravityFactor; + } + + /// + /// Calculates the range reachable with a projectile of speed velocity fired at angle from height shotHeight. Does not take into account air resistance. + /// + /// Projectile velocity in cells per second. + /// Shot angle in radians off the ground. + /// Height from which the projectile is fired in vertical cells. + /// Distance in cells that the projectile will fly at the given arc. + private float GetDistanceTraveled(float velocity, float angle, float shotHeight) + { + if (shotHeight < 0.001f) + { + return (Mathf.Pow(velocity, 2f) / GravityFactor) * Mathf.Sin(2f * angle); + } + return ((velocity * Mathf.Cos(angle)) / GravityFactor) * (velocity * Mathf.Sin(angle) + Mathf.Sqrt(Mathf.Pow(velocity * Mathf.Sin(angle), 2f) + 2f * GravityFactor * shotHeight)); + } + + /// + /// Calculates the destination reached with a projectile of speed velocity fired at angle from height shotHeight starting from origin. Does not take into account air resistance. + /// + /// Vector2 source of the projectile. + /// Shot angle in radians off the ground. + /// Shot angle in degrees between source/target. + /// Projectile velocity in cells per second. + /// Height from which the projectile is fired in vertical cells. + /// The Vector2 destination of the projectile, e.g the Vector2 when it hits the ground at height = 0f. + private Vector2 GetDestination(Vector2 origin, float angle, float rotation, float velocity, float shotHeight) + { + return origin + Vector2.up.RotatedBy(rotation) * GetDistanceTraveled(velocity, angle, shotHeight); + } + + /// + /// Calculates the shot angle necessary to reach range with a projectile of speed velocity at a height difference of heightDifference, returning either the upper or lower arc in radians. Does not take into account air resistance. + /// + /// Projectile velocity in cells per second. + /// Cells between shooter and target. + /// Difference between initial shot height and target height in vertical cells. + /// Whether to take the lower (False) or upper (True) arc angle. + /// Arc angle in radians off the ground. + public static float GetShotAngle(float velocity, float range, float heightDifference, bool flyOverhead, float gravity) + { + return Mathf.Atan((Mathf.Pow(velocity, 2f) + (flyOverhead ? 1f : -1f) * Mathf.Sqrt(Mathf.Pow(velocity, 4f) - gravity * (gravity * Mathf.Pow(range, 2f) + 2f * heightDifference * Mathf.Pow(velocity, 2f)))) / (gravity * range)); + } + #endregion + + #endregion + } +} diff --git a/Source/CombatRealism/CombatExtended/Projectiles/ProjectileCE_Explosive.cs b/Source/CombatExtended/CombatExtended/Projectiles/ProjectileCE_Explosive.cs similarity index 90% rename from Source/CombatRealism/CombatExtended/Projectiles/ProjectileCE_Explosive.cs rename to Source/CombatExtended/CombatExtended/Projectiles/ProjectileCE_Explosive.cs index a1ddf39324..0401066a67 100644 --- a/Source/CombatRealism/CombatExtended/Projectiles/ProjectileCE_Explosive.cs +++ b/Source/CombatExtended/CombatExtended/Projectiles/ProjectileCE_Explosive.cs @@ -11,7 +11,7 @@ public class ProjectileCE_Explosive : ProjectileCE public override void ExposeData() { base.ExposeData(); - Scribe_Values.LookValue(ref this.ticksToDetonation, "ticksToDetonation", 0, false); + Scribe_Values.Look(ref this.ticksToDetonation, "ticksToDetonation", 0, false); } public override void Tick() { @@ -54,7 +54,7 @@ protected virtual void Explode() this.def.projectile.postExplosionSpawnThingDef, this.def.projectile.explosionSpawnChance, 1, - false, // propsCE == null ? false : propsCE.damageAdjacentTiles, + propsCE == null ? false : propsCE.damageAdjacentTiles, preExplosionSpawnThingDef, explosionSpawnChance, 1); @@ -65,9 +65,9 @@ protected virtual void Explode() } CompExplosiveCE comp = this.TryGetComp(); - if (comp != null && this.launcher != null && this.Position.IsValid) + if (comp != null && Position.IsValid) { - comp.Explode(launcher, this.Position, Find.VisibleMap); + comp.Explode(launcher, Position, Find.VisibleMap); } } diff --git a/Source/CombatExtended/CombatExtended/Projectiles/ProjectileCE_Explosive_RL.cs b/Source/CombatExtended/CombatExtended/Projectiles/ProjectileCE_Explosive_RL.cs new file mode 100644 index 0000000000..b78111272d --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Projectiles/ProjectileCE_Explosive_RL.cs @@ -0,0 +1,60 @@ +using System; +using Verse; +using UnityEngine; +using RimWorld; + +namespace CombatExtended +{ + public class ProjectileCE_Explosive_RL : ProjectileCE_Explosive + { + private int Burnticks = 3; + public override void Tick() + { + Map map = base.Map; + if (--Burnticks == 0) + { + ThrowSmokeForRocketsandMortars(base.Position.ToVector3Shifted(), 1f); + ThrowRocketExhaustFlame(base.Position.ToVector3Shifted(), 2f); + Burnticks = 3; + } + base.Tick(); + } + + public override void SpawnSetup(Map map) + { + base.SpawnSetup(map); + ThrowSmokeForRocketsandMortars(base.Position.ToVector3Shifted(), 4f); + ThrowRocketExhaustFlame(base.Position.ToVector3Shifted(), 1f); + } + + public static void ThrowRocketExhaustFlame(Vector3 loc, float size) + { + IntVec3 intVec = loc.ToIntVec3(); + if (!intVec.InBounds(Find.VisibleMap)) + { + return; + } + MoteThrown moteThrown = (MoteThrown)ThingMaker.MakeThing(ThingDefOf.Mote_ShotFlash, null); + moteThrown.Scale = Rand.Range(1.5f, 2.5f) * size; + moteThrown.exactRotation = Rand.Range(-0.5f, 0.5f); + moteThrown.exactPosition = loc; + moteThrown.SetVelocity((float)Rand.Range(30, 40), Rand.Range(0.08f, 0.12f)); + GenSpawn.Spawn(moteThrown, loc.ToIntVec3(), Find.VisibleMap); + } + + public static void ThrowSmokeForRocketsandMortars(Vector3 loc, float size) + { + IntVec3 intVec = loc.ToIntVec3(); + if (!intVec.InBounds(Find.VisibleMap)) + { + return; + } + MoteThrown moteThrown = (MoteThrown)ThingMaker.MakeThing(ThingDefOf.Mote_Smoke, null); + moteThrown.Scale = Rand.Range(1.5f, 2.5f) * size; + moteThrown.exactRotation = Rand.Range(-0.5f, 0.5f); + moteThrown.exactPosition = loc; + moteThrown.SetVelocity((float)Rand.Range(30, 40), Rand.Range(0.08f, 0.12f)); + GenSpawn.Spawn(moteThrown, loc.ToIntVec3(), Find.VisibleMap); + } + } +} \ No newline at end of file diff --git a/Source/CombatRealism/CombatExtended/Projectiles/ProjectilePropertiesCE.cs b/Source/CombatExtended/CombatExtended/Projectiles/ProjectilePropertiesCE.cs similarity index 83% rename from Source/CombatRealism/CombatExtended/Projectiles/ProjectilePropertiesCE.cs rename to Source/CombatExtended/CombatExtended/Projectiles/ProjectilePropertiesCE.cs index af9153d12d..1b0c03e448 100644 --- a/Source/CombatRealism/CombatExtended/Projectiles/ProjectilePropertiesCE.cs +++ b/Source/CombatExtended/CombatExtended/Projectiles/ProjectilePropertiesCE.cs @@ -17,5 +17,8 @@ public class ProjectilePropertiesCE : ProjectileProperties public bool damageAdjacentTiles = false; public bool dropsCasings = false; public string casingMoteDefname = "Mote_EmptyCasing"; + public float gravityFactor = 1; + + public float Gravity => CE_Utility.gravityConst * gravityFactor; } } \ No newline at end of file diff --git a/Source/CombatExtended/CombatExtended/Projectiles/Projectile_FireTrail.cs b/Source/CombatExtended/CombatExtended/Projectiles/Projectile_FireTrail.cs new file mode 100644 index 0000000000..d441019cb6 --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Projectiles/Projectile_FireTrail.cs @@ -0,0 +1,33 @@ +using System; +using Verse; +using UnityEngine; + +namespace CombatExtended +{ + public class Projectile_FireTrail : ProjectileCE_Explosive + { + private int TicksforAppearence = 5; + public override void Tick() + { + base.Tick(); + if (--TicksforAppearence == 0) + { + Projectile_FireTrail.ThrowFireTrail(base.Position.ToVector3Shifted(), base.Map, 0.5f); + TicksforAppearence = 5; + } + } + public static void ThrowFireTrail(Vector3 loc, Map map, float size) + { + if (!loc.ShouldSpawnMotesAt(map)) + { + return; + } + MoteThrown moteThrown = (MoteThrown)ThingMaker.MakeThing(ThingDef.Named("Mote_Firetrail"), null); + moteThrown.Scale = Rand.Range(1.5f, 2.5f) * size; + moteThrown.exactRotation = Rand.Range(-0.5f, 0.5f); + moteThrown.exactPosition = loc; + moteThrown.SetVelocity((float)Rand.Range(30, 40), Rand.Range(0.008f, 0.012f)); + GenSpawn.Spawn(moteThrown, loc.ToIntVec3(), map); + } + } +} \ No newline at end of file diff --git a/Source/CombatExtended/CombatExtended/SecondaryDamage.cs b/Source/CombatExtended/CombatExtended/SecondaryDamage.cs new file mode 100644 index 0000000000..1e606e27d8 --- /dev/null +++ b/Source/CombatExtended/CombatExtended/SecondaryDamage.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using UnityEngine; + +namespace CombatExtended +{ + public class SecondaryDamage + { + public DamageDef def; + public int amount; + + public DamageInfo GetDinfo() + { + return new DamageInfo(def, amount); + } + + public DamageInfo GetDinfo(DamageInfo primaryDinfo) + { + var dinfo = new DamageInfo(def, + amount, + primaryDinfo.Angle, + primaryDinfo.Instigator, + primaryDinfo.ForceHitPart, + primaryDinfo.WeaponGear); + dinfo.SetBodyRegion(primaryDinfo.Height, primaryDinfo.Depth); + return dinfo; + } + } +} \ No newline at end of file diff --git a/Source/CombatExtended/CombatExtended/Settings.cs b/Source/CombatExtended/CombatExtended/Settings.cs new file mode 100644 index 0000000000..6a9ce2a9a1 --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Settings.cs @@ -0,0 +1,153 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using UnityEngine; + +namespace CombatExtended +{ + public class Settings : ModSettings + { + #region Settings + + // General settings + private bool showCasings = true; + private bool showTaunts = true; + private bool allowMeleeHunting = false; + + public bool ShowCasings => showCasings; + public bool ShowTaunts => showTaunts; + public bool AllowMeleeHunting => allowMeleeHunting; + + // Ammo settings + private bool enableAmmoSystem = true; + private bool rightClickAmmoSelect = false; + private bool autoReloadOnChangeAmmo = true; + private bool autoTakeAmmo = true; + private bool showCaliberOnGuns = true; + + public bool EnableAmmoSystem => enableAmmoSystem; + public bool RightClickAmmoSelect => rightClickAmmoSelect; + public bool AutoReloadOnChangeAmmo => autoReloadOnChangeAmmo; + public bool AutoTakeAmmo => autoTakeAmmo; + public bool ShowCaliberOnGuns => showCaliberOnGuns; + + // Debug settings - make sure all of these default to false for the release build + private bool debugDrawPartialLoSChecks = false; + private bool debugEnableInventoryValidation = false; + private bool debugDrawTargetCoverChecks = false; + private bool debugShowTreeCollisionChance = false; + private bool debugShowSuppressionBuildup = false; + + public bool DebugDrawPartialLoSChecks => debugDrawPartialLoSChecks; + public bool DebugEnableInventoryValidation => debugEnableInventoryValidation; + public bool DebugDrawTargetCoverChecks => debugDrawTargetCoverChecks; + public bool DebugShowTreeCollisionChance => debugShowTreeCollisionChance; + public bool DebugShowSuppressionBuildup => debugShowSuppressionBuildup; + + #endregion + + private bool lastAmmoSystemStatus; + + #region Methods + + public override void ExposeData() + { + base.ExposeData(); + Scribe_Values.Look(ref showCasings, "showCasings", true); + Scribe_Values.Look(ref showTaunts, "showTaunts", true); + Scribe_Values.Look(ref allowMeleeHunting, "allowMeleeHunting", false); + +#if DEBUG + // Debug settings + Scribe_Values.Look(ref debugDrawPartialLoSChecks, "drawPartialLoSChecks", false); + Scribe_Values.Look(ref debugEnableInventoryValidation, "enableInventoryValidation", false); + Scribe_Values.Look(ref debugDrawTargetCoverChecks, "debugDrawTargetCoverChecks", false); + Scribe_Values.Look(ref debugShowTreeCollisionChance, "debugShowTreeCollisionChance", false); + Scribe_Values.Look(ref debugShowSuppressionBuildup, "debugShowSuppressionBuildup", false); +#endif + + // Ammo settings + Scribe_Values.Look(ref enableAmmoSystem, "enableAmmoSystem", true); + Scribe_Values.Look(ref rightClickAmmoSelect, "rightClickAmmoSelect", false); + Scribe_Values.Look(ref autoReloadOnChangeAmmo, "autoReloadOnChangeAmmo", true); + Scribe_Values.Look(ref autoTakeAmmo, "autoTakeAmmo", true); + Scribe_Values.Look(ref showCaliberOnGuns, "showCaliberOnGuns", true); + + lastAmmoSystemStatus = enableAmmoSystem; // Store this now so we can monitor for changes + } + + public void DoWindowContents(Rect canvas) + { + Listing_Standard list = new Listing_Standard(); + list.ColumnWidth = (canvas.width - 17) / 2; // Subtract 17 for gap between columns + list.Begin(canvas); + + // Do general settings + Text.Font = GameFont.Medium; + list.Label("CE_Settings_HeaderGeneral".Translate()); + Text.Font = GameFont.Small; + list.Gap(); + + list.CheckboxLabeled("CE_Settings_ShowCasings_Title".Translate(), ref showCasings, "CE_Settings_ShowCasings_Desc".Translate()); + list.CheckboxLabeled("CE_Settings_ShowTaunts_Title".Translate(), ref showTaunts, "CE_Settings_ShowTaunts_Desc".Translate()); + list.CheckboxLabeled("CE_Settings_AllowMeleeHunting_Title".Translate(), ref allowMeleeHunting, "CE_Settings_AllowMeleeHunting_Desc".Translate()); + +#if DEBUG + // Do Debug settings + list.GapLine(); + Text.Font = GameFont.Medium; + list.Label("Debug"); + Text.Font = GameFont.Small; + list.Gap(); + + list.CheckboxLabeled("Draw partial LoS checks", ref debugDrawPartialLoSChecks, "Displays line of sight checks against partial cover."); + list.CheckboxLabeled("Draw target cover checks", ref debugDrawTargetCoverChecks, "Displays highest cover of target as it is selected."); + list.CheckboxLabeled("Enable inventory validation", ref debugEnableInventoryValidation, "Inventory will refresh its cache every tick and log any discrepancies."); + list.CheckboxLabeled("Display tree collision chances", ref debugShowTreeCollisionChance, "Projectiles will display chances of coliding with trees as they pass by."); + list.CheckboxLabeled("Display suppression buildup", ref debugShowSuppressionBuildup, "Pawns will display buildup numbers when taking suppression."); +#endif + + // Do ammo settings + list.NewColumn(); + + Text.Font = GameFont.Medium; + list.Label("CE_Settings_HeaderAmmo".Translate()); + Text.Font = GameFont.Small; + list.Gap(); + + list.CheckboxLabeled("CE_Settings_EnableAmmoSystem_Title".Translate(), ref enableAmmoSystem, "CE_Settings_EnableAmmoSystem_Desc".Translate()); + list.GapLine(); + if (enableAmmoSystem) + { + list.CheckboxLabeled("CE_Settings_RightClickAmmoSelect_Title".Translate(), ref rightClickAmmoSelect, "CE_Settings_RightClickAmmoSelect_Desc".Translate()); + list.CheckboxLabeled("CE_Settings_AutoReloadOnChangeAmmo_Title".Translate(), ref autoReloadOnChangeAmmo, "CE_Settings_AutoReloadOnChangeAmmo_Desc".Translate()); + list.CheckboxLabeled("CE_Settings_AutoTakeAmmo_Title".Translate(), ref autoTakeAmmo, "CE_Settings_AutoTakeAmmo_Desc".Translate()); + list.CheckboxLabeled("CE_Settings_ShowCaliberOnGuns_Title".Translate(), ref showCaliberOnGuns, "CE_Settings_ShowCaliberOnGuns_Desc".Translate()); + } + else + { + GUI.contentColor = Color.gray; + list.Label("CE_Settings_RightClickAmmoSelect_Title".Translate()); + list.Label("CE_Settings_AutoReloadOnChangeAmmo_Title".Translate()); + list.Label("CE_Settings_AutoTakeAmmo_Title".Translate()); + list.Label("CE_Settings_ShowCaliberOnGuns_Title".Translate()); + GUI.contentColor = Color.white; + } + + list.End(); + + // Update ammo if setting changes + if (lastAmmoSystemStatus != enableAmmoSystem) + { + AmmoInjector.Inject(); + lastAmmoSystemStatus = enableAmmoSystem; + TutorUtility.DoModalDialogIfNotKnown(CE_ConceptDefOf.CE_AmmoSettings); + } + } + + #endregion + } +} diff --git a/Source/CombatRealism/CombatExtended/ShiftVecReport.cs b/Source/CombatExtended/CombatExtended/ShiftVecReport.cs similarity index 82% rename from Source/CombatRealism/CombatExtended/ShiftVecReport.cs rename to Source/CombatExtended/CombatExtended/ShiftVecReport.cs index 42b8fdf510..b1a75e65e1 100644 --- a/Source/CombatRealism/CombatExtended/ShiftVecReport.cs +++ b/Source/CombatExtended/CombatExtended/ShiftVecReport.cs @@ -19,7 +19,7 @@ public Pawn targetPawn } } public float aimingAccuracy = 1f; - public float aimEfficiency = 1f; + public float sightsEfficiency = 1f; private float accuracyFactorInt = -1f; public float accuracyFactor @@ -28,7 +28,7 @@ public float accuracyFactor { if (accuracyFactorInt < 0) { - accuracyFactorInt = (1.5f - aimingAccuracy) / aimEfficiency; + accuracyFactorInt = (1.5f - aimingAccuracy) / sightsEfficiency; } return accuracyFactorInt; } @@ -47,7 +47,7 @@ public float visibilityShift { if (visibilityShiftInt < 0) { - visibilityShiftInt = (lightingShift + weatherShift) * (shotDist / 50) * (2 - aimingAccuracy); + visibilityShiftInt = (lightingShift + weatherShift + smokeDensity) * (shotDist / 50) * (2 - aimingAccuracy); } return visibilityShiftInt; } @@ -105,12 +105,13 @@ public float distShift public float swayDegrees = 0f; public float spreadDegrees = 0f; public Thing cover = null; + public float smokeDensity = 0f; // Copy-constructor public ShiftVecReport(ShiftVecReport report) { target = report.target; - aimEfficiency = report.aimEfficiency; + sightsEfficiency = report.sightsEfficiency; aimingAccuracy = report.aimingAccuracy; circularMissRadius = report.circularMissRadius; indirectFireShift = report.indirectFireShift; @@ -121,6 +122,7 @@ public ShiftVecReport(ShiftVecReport report) swayDegrees = report.swayDegrees; spreadDegrees = report.spreadDegrees; cover = report.cover; + smokeDensity = report.smokeDensity; } public ShiftVecReport() @@ -139,17 +141,17 @@ public float GetRandDist() return dist; } - public Vector3 GetRandLeadVec() + public Vector2 GetRandLeadVec() { - Vector3 leadVec = new Vector3(); + Vector3 moveVec = new Vector3(); if (targetIsMoving) { - Vector3 moveVec = (targetPawn.pather.nextCell - targetPawn.Position).ToVector3(); - leadVec = moveVec * (leadDist + UnityEngine.Random.Range(-leadShift, leadShift)); + moveVec = (targetPawn.pather.nextCell - targetPawn.Position).ToVector3() * (leadDist + UnityEngine.Random.Range(-leadShift, leadShift)); } - return leadVec; + return new Vector2(moveVec.x, moveVec.z); } + /// Angle Vector2 in degrees public Vector2 GetRandSpreadVec() { Vector2 vec = UnityEngine.Random.insideUnitCircle * spreadDegrees; @@ -176,6 +178,10 @@ public string GetTextReadout() { stringBuilder.AppendLine(" " + "Weather".Translate() + "\t" + AsPercent(weatherShift)); } + if (smokeDensity > 0) + { + stringBuilder.AppendLine(" " + "CE_SmokeDensity".Translate() + "\t" + AsPercent(smokeDensity)); + } } if (leadShift > 0) { @@ -200,19 +206,21 @@ public string GetTextReadout() if (indirectFireShift > 0) { stringBuilder.AppendLine(" " + "CE_IndirectFire".Translate() + "\t" + GenText.ToStringByStyle(indirectFireShift, ToStringStyle.FloatTwo) + " c"); + PlayerKnowledgeDatabase.KnowledgeDemonstrated(CE_ConceptDefOf.CE_MortarDirectFire, KnowledgeAmount.FrameDisplayed); // Show we learned about indirect fire penalties } } else { if (cover != null) { - stringBuilder.AppendLine(" " + "CE_CoverHeight".Translate() + "\t" + GenText.ToStringByStyle(CE_Utility.GetCollisionHeight(cover), ToStringStyle.FloatTwo) + " c"); + stringBuilder.AppendLine(" " + "CE_CoverHeight".Translate() + "\t" + new CollisionVertical(cover).Max + " c"); } if (target.Thing != null) { - stringBuilder.AppendLine(" " + "CE_TargetHeight".Translate() + "\t" + GenText.ToStringByStyle(CE_Utility.GetCollisionHeight(target.Thing), ToStringStyle.FloatTwo) + " c"); + stringBuilder.AppendLine(" " + "CE_TargetHeight".Translate() + "\t" + GenText.ToStringByStyle(new CollisionVertical(target.Thing).HeightRange.Span, ToStringStyle.FloatTwo) + " c"); stringBuilder.AppendLine(" " + "CE_TargetWidth".Translate() + "\t" + GenText.ToStringByStyle(CE_Utility.GetCollisionWidth(target.Thing) * 2, ToStringStyle.FloatTwo) + " c"); } + PlayerKnowledgeDatabase.KnowledgeDemonstrated(CE_ConceptDefOf.CE_AimingSystem, KnowledgeAmount.FrameDisplayed); // Show we learned about the aiming system } return stringBuilder.ToString(); } diff --git a/Source/CombatExtended/CombatExtended/StatWorkers/StatWorker_MeleeArmorPenetration.cs b/Source/CombatExtended/CombatExtended/StatWorkers/StatWorker_MeleeArmorPenetration.cs new file mode 100644 index 0000000000..1a593281da --- /dev/null +++ b/Source/CombatExtended/CombatExtended/StatWorkers/StatWorker_MeleeArmorPenetration.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using UnityEngine; + +namespace CombatExtended +{ + public class StatWorker_MeleeArmorPenetration : StatWorker + { + private float GetMeleePenetration(StatRequest req, DamageDef damageType = null) + { + Pawn pawn = req.Thing as Pawn; + if (pawn == null) + { + return 0; + } + List updatedAvailableVerbsList = pawn.meleeVerbs.GetUpdatedAvailableVerbsList(); + if (updatedAvailableVerbsList.Count == 0) + { + return 0; + } + + List verbsList; + if (damageType != null) verbsList = updatedAvailableVerbsList.Where(x => x.verb.verbProps.meleeDamageDef == damageType).ToList(); + else verbsList = updatedAvailableVerbsList; + + + float totalSelectionWeight = 0f; + for (int i = 0; i < verbsList.Count; i++) + { + totalSelectionWeight += verbsList[i].SelectionWeight; + } + float totalAveragePen = 0f; + foreach (VerbEntry current in verbsList) + { + var propsCE = current.verb.verbProps as VerbPropertiesCE; + if (propsCE != null) + { + ThingWithComps ownerEquipment = current.verb.ownerEquipment; + var weightFactor = current.SelectionWeight / totalSelectionWeight; + totalAveragePen += weightFactor * propsCE.meleeArmorPenetration; + } + } + return totalAveragePen; + } + + public override float GetValueUnfinalized(StatRequest req, bool applyPostProcess = true) + { + return GetMeleePenetration(req); + } + + public override string GetExplanation(StatRequest req, ToStringNumberSense numberSense) + { + var pawn = req.Thing as Pawn; + if (pawn == null) + return base.GetExplanation(req, numberSense); + + // Find all damage types of our verbs + List allDamageTypes = new List(); + foreach(VerbEntry current in pawn.meleeVerbs.GetUpdatedAvailableVerbsList()) + { + var dam = current.verb.verbProps.meleeDamageDef; + if (dam != null) allDamageTypes.Add(dam); + } + + // Generate entries + StringBuilder stringBuilder = new StringBuilder(); + foreach(DamageDef current in allDamageTypes.Distinct()) + { + var averageString = ""; + if (allDamageTypes.FindAll(x => x == current).Count > 1) + { + averageString = " (" + "AverageOfAllAttacks".Translate() + ")"; + } + stringBuilder.AppendLine(current.LabelCap + averageString); + stringBuilder.AppendLine(" " + GetMeleePenetration(req, current).ToString("0.##")); + stringBuilder.AppendLine(); + } + stringBuilder.Length--; // Move back one position to remove last empty line + + return stringBuilder.ToString(); + } + } +} diff --git a/Source/CombatRealism/CombatExtended/StatWorkers/StatWorker_MoveSpeed.cs b/Source/CombatExtended/CombatExtended/StatWorkers/StatWorker_MoveSpeed.cs similarity index 98% rename from Source/CombatRealism/CombatExtended/StatWorkers/StatWorker_MoveSpeed.cs rename to Source/CombatExtended/CombatExtended/StatWorkers/StatWorker_MoveSpeed.cs index 49feeb061a..78e3430bbd 100644 --- a/Source/CombatRealism/CombatExtended/StatWorkers/StatWorker_MoveSpeed.cs +++ b/Source/CombatExtended/CombatExtended/StatWorkers/StatWorker_MoveSpeed.cs @@ -48,7 +48,7 @@ private float GetStatFactor(Thing thing) CompInventory comp = thing.TryGetComp(); if (comp != null) { - factor = Mathf.Clamp(comp.moveSpeedFactor - comp.encumberPenalty, 0.01f, 1f); + factor = Mathf.Clamp(comp.moveSpeedFactor - comp.encumberPenalty, 0.5f, 1f); } return factor; } diff --git a/Source/CombatRealism/CombatExtended/StatWorkers/StatWorker_WorkSpeedGlobal.cs b/Source/CombatExtended/CombatExtended/StatWorkers/StatWorker_WorkSpeedGlobal.cs similarity index 100% rename from Source/CombatRealism/CombatExtended/StatWorkers/StatWorker_WorkSpeedGlobal.cs rename to Source/CombatExtended/CombatExtended/StatWorkers/StatWorker_WorkSpeedGlobal.cs diff --git a/Source/CombatExtended/CombatExtended/SuppressionUtility.cs b/Source/CombatExtended/CombatExtended/SuppressionUtility.cs new file mode 100644 index 0000000000..9c66a23fd9 --- /dev/null +++ b/Source/CombatExtended/CombatExtended/SuppressionUtility.cs @@ -0,0 +1,118 @@ +using System.Collections.Generic; +using System.Linq; +using RimWorld; +using UnityEngine; +using Verse; +using Verse.AI; + +namespace CombatExtended +{ + public static class SuppressionUtility + { + public const float maxCoverDist = 10f; //Maximum distance to run for cover to + + public static Job GetRunForCoverJob(Pawn pawn) + { + //Calculate cover position + CompSuppressable comp = pawn.TryGetComp(); + if (comp == null) + { + return null; + } + float distToSuppressor = (pawn.Position - comp.SuppressorLoc).LengthHorizontal; + IntVec3 coverPosition; + + //Try to find cover position to move up to + if (!GetCoverPositionFrom(pawn, comp.SuppressorLoc, maxCoverDist, out coverPosition)) + { + return null; + } + + //Sanity check + if (pawn.Position.Equals(coverPosition)) + { + return null; + } + + //Tell pawn to move to position + pawn.Map.pawnDestinationManager.ReserveDestinationFor(pawn, coverPosition); + return new Job(CE_JobDefOf.RunForCover, coverPosition) + { + locomotionUrgency = LocomotionUrgency.Sprint, + playerForced = true + }; + } + + private static bool GetCoverPositionFrom(Pawn pawn, IntVec3 fromPosition, float maxDist, out IntVec3 coverPosition) + { + List cellList = new List(GenRadial.RadialCellsAround(pawn.Position, maxDist, true)); + IntVec3 bestPos = pawn.Position; + float bestRating = GetCellCoverRatingForPawn(pawn, pawn.Position, fromPosition); + + if (bestRating <= 0) + { + // Go through each cell in radius around the pawn + Region pawnRegion = pawn.Position.GetRegion(pawn.Map); + List adjacentRegions = pawnRegion.Neighbors.ToList(); + adjacentRegions.Add(pawnRegion); + // Make sure only cells within bounds are evaluated + foreach (IntVec3 cell in cellList.Where(x => x.InBounds(pawn.Map))) + { + // Check for adjacency so we don't path to the other side of a wall or some such + if (cell.InBounds(pawn.Map) && adjacentRegions.Contains(cell.GetRegion(pawn.Map))) + { + float cellRating = GetCellCoverRatingForPawn(pawn, cell, fromPosition); + if (cellRating > bestRating) + { + bestRating = cellRating; + bestPos = cell; + } + } + } + } + coverPosition = bestPos; + return bestRating >= 0; + } + + private static float GetCellCoverRatingForPawn(Pawn pawn, IntVec3 cell, IntVec3 shooterPos) + { + // Check for invalid locations + if (!cell.IsValid || !cell.Standable(pawn.Map) || !pawn.CanReserveAndReach(cell, PathEndMode.OnCell, Danger.Deadly) || cell.ContainsStaticFire(pawn.Map)) + { + return -1; + } + + float cellRating = 0; + + if (!GenSight.LineOfSight(shooterPos, cell, pawn.Map)) + { + cellRating += 2f; + } + else + { + //Check if cell has cover in desired direction + Vector3 coverVec = (shooterPos - cell).ToVector3().normalized; + IntVec3 coverCell = (cell.ToVector3Shifted() + coverVec).ToIntVec3(); + Thing cover = coverCell.GetCover(pawn.Map); + cellRating += GetCoverRating(cover); + } + + //Check time to path to that location + if (!pawn.Position.Equals(cell)) + { + // float pathCost = pawn.Map.pathFinder.FindPath(pawn.Position, cell, TraverseMode.NoPassClosedDoors).TotalCost; + float pathCost = (pawn.Position - cell).LengthHorizontal; + if (!GenSight.LineOfSight(pawn.Position, cell, pawn.Map)) pathCost *= 5; + cellRating = cellRating / pathCost; + } + return cellRating; + } + + private static float GetCoverRating(Thing cover) + { + if (cover == null) return 0; + if (cover.def.category == ThingCategory.Plant) return cover.def.fillPercent; // Plant cover only has a random chance to block gunfire and is rated lower + return 1; + } + } +} diff --git a/Source/CombatRealism/CombatExtended/TexButton.cs b/Source/CombatExtended/CombatExtended/TexButton.cs similarity index 100% rename from Source/CombatRealism/CombatExtended/TexButton.cs rename to Source/CombatExtended/CombatExtended/TexButton.cs diff --git a/Source/CombatExtended/CombatExtended/Things/AmmoThing.cs b/Source/CombatExtended/CombatExtended/Things/AmmoThing.cs new file mode 100644 index 0000000000..b4c3abb6ca --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Things/AmmoThing.cs @@ -0,0 +1,121 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using Verse.Sound; +using UnityEngine; + +namespace CombatExtended +{ + public class AmmoThing : ThingWithComps + { + private int numToCookOff; + + #region Properties + + private AmmoDef AmmoDef => def as AmmoDef; + + #endregion + + #region Methods + + public override string GetDescription() + { + if(AmmoDef != null && AmmoDef.ammoClass != null) + { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.AppendLine(base.GetDescription()); + + // Append ammo class description + stringBuilder.AppendLine("\n" + AmmoDef.ammoClass.LabelCap + ":"); + stringBuilder.AppendLine(AmmoDef.ammoClass.description); + + // Append guns that use this caliber + stringBuilder.AppendLine("\n" + "CE_UsedBy".Translate() + ":"); + foreach(var user in AmmoDef.Users) + { + stringBuilder.AppendLine(" -" + user.LabelCap); + } + + return stringBuilder.ToString().TrimEndNewlines(); + } + return base.GetDescription(); + } + + public override void PreApplyDamage(DamageInfo dinfo, out bool absorbed) + { + base.PreApplyDamage(dinfo, out absorbed); + if (!absorbed && Spawned && dinfo.Def.externalViolence) + { + if (HitPoints - dinfo.Amount > 0) + { + numToCookOff += Mathf.RoundToInt(def.stackLimit * ((float)dinfo.Amount / HitPoints) * (def.smallVolume ? Rand.Range(1f, 2f) : Rand.Range(0.0f, 1f))); + } + else TryDetonate(Mathf.Lerp(1, Mathf.Min(5, stackCount), stackCount / def.stackLimit)); + } + } + + public override void Tick() + { + // Self-destruct if ammo is disabled + if (!Controller.settings.EnableAmmoSystem && !def.IsWeapon) Destroy(DestroyMode.Vanish); + + base.Tick(); + + // Cook off ammo based on how much damage we've taken so far + if (numToCookOff > 0 && Rand.Chance((float)numToCookOff / def.stackLimit)) + { + if(TryLaunchCookOffProjectile() || TryDetonate()) + { + // Reduce stack count + if (stackCount > 1) + { + numToCookOff--; + stackCount--; + } + else + { + numToCookOff = 0; + Destroy(DestroyMode.KillFinalize); + } + } + } + } + + private bool TryDetonate(float scale = 1) + { + CompExplosiveCE comp = this.TryGetComp(); + if (comp != null) + { + if(Rand.Chance(Mathf.Clamp01(0.75f - Mathf.Pow(HitPoints / MaxHitPoints, 2)))) comp.Explode(this, Position, Map, scale); + return true; + } + return false; + } + + private bool TryLaunchCookOffProjectile() + { + if (AmmoDef.cookOffProjectile == null) return false; + ProjectileCE projectile = (ProjectileCE)ThingMaker.MakeThing(AmmoDef.cookOffProjectile); + GenSpawn.Spawn(projectile, Position, Map); + + // Launch in random direction + projectile.canTargetSelf = true; + projectile.minCollisionSqr = 0f; + projectile.Launch(this, + new Vector2(DrawPos.x, DrawPos.z), + UnityEngine.Random.Range(0, Mathf.PI / 2f), + UnityEngine.Random.Range(0, 360), + 0.1f, + AmmoDef.cookOffProjectile.projectile.speed * AmmoDef.cookOffSpeed); + if (AmmoDef.cookOffFlashScale > 0.01) MoteMaker.MakeStaticMote(Position, Map, ThingDefOf.Mote_ShotFlash, AmmoDef.cookOffFlashScale); + if (AmmoDef.cookOffSound != null) AmmoDef.cookOffSound.PlayOneShot(new TargetInfo(Position, Map)); + if (AmmoDef.cookOffTailSound != null) AmmoDef.cookOffTailSound.PlayOneShotOnCamera(); + return true; + } + + #endregion + } +} diff --git a/Source/CombatExtended/CombatExtended/Things/Apparel_Shield.cs b/Source/CombatExtended/CombatExtended/Things/Apparel_Shield.cs new file mode 100644 index 0000000000..b83d7e1a27 --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Things/Apparel_Shield.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using UnityEngine; + +namespace CombatExtended +{ + public class Apparel_Shield : Apparel + { + public const string OneHandedTag = "CE_OneHandedWeapon"; + private bool drawShield => Wearer.Drafted || (Wearer.CurJob?.def.alwaysShowWeapon ?? false) || (Wearer.mindState.duty?.def.alwaysShowWeapon ?? false); // Copied from PawnRenderer.CarryWeaponOpenly(), we show the shield whenever weapons are drawn + private bool IsTall => def.GetModExtension()?.drawAsTall ?? false; + + public override bool AllowVerbCast(IntVec3 root, Map map, LocalTargetInfo targ) + { + ThingWithComps primary = Wearer.equipment?.Primary; + return primary == null || (primary.def.weaponTags?.Contains(OneHandedTag) ?? false); + } + + public override void DrawWornExtras() + { + if (Wearer == null || !Wearer.Spawned) return; + if (!drawShield) return; + + float num = 0f; + Vector3 vector = this.Wearer.Drawer.DrawPos; + vector.y = Altitudes.AltitudeFor(AltitudeLayer.Pawn); + Vector3 s = new Vector3(1f, 1f, 1f); + if (this.Wearer.Rotation == Rot4.North) + { + //vector.y = Altitudes.AltitudeFor(AltitudeLayer.Pawn); + vector.x -= 0.1f; + vector.z -= IsTall ? -0.1f : 0.2f; + } + else + { + if (this.Wearer.Rotation == Rot4.South) + { + //vector.y = Altitudes.AltitudeFor(AltitudeLayer.MoteOverhead); + vector.y += 0.0375f; + vector.x += 0.1f; + vector.z -= IsTall ? -0.05f : 0.2f; + } + else + { + if (this.Wearer.Rotation == Rot4.East) + { + //vector.y = Altitudes.AltitudeFor(AltitudeLayer.Pawn); + if (IsTall) vector.x += 0.1f; + vector.z -= IsTall ? -0.05f : 0.2f; + num = 22.5f; + } + else + { + if (this.Wearer.Rotation == Rot4.West) + { + //vector.y = Altitudes.AltitudeFor(AltitudeLayer.MoteOverhead); + vector.y += 0.0425f; + if (IsTall) vector.x -= 0.1f; + vector.z -= IsTall ? -0.05f : 0.2f; + num = 337.5f; + } + } + } + } + Material mat = Graphic.GetColoredVersion(ShaderDatabase.Cutout, DrawColor, DrawColorTwo).MatSingle; + Matrix4x4 matrix = default(Matrix4x4); + matrix.SetTRS(vector, Quaternion.AngleAxis(num, Vector3.up), s); + Graphics.DrawMesh(MeshPool.plane10, matrix, mat, 0); + } + } +} diff --git a/Source/CombatExtended/CombatExtended/Things/Apparel_VisibleAccessory.cs b/Source/CombatExtended/CombatExtended/Things/Apparel_VisibleAccessory.cs new file mode 100644 index 0000000000..922e3137c3 --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Things/Apparel_VisibleAccessory.cs @@ -0,0 +1,201 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using UnityEngine; + +namespace CombatExtended +{ + public class Apparel_VisibleAccessory : Apparel + { + /* Pawn offset reference based on Verse.PawnRenderer and method RenderPawnInternal: + * (Offsets valid for pawns facing any direction but North). + * Wounds offset: 0.02f + * Shell offset: 0.0249999985f + * Head offset: 0.03f + * Upperhead offset: 0.34 + * Ceiling offset: 0449999981f + * North flips order shell/head + * Hair (if drawn gets important when north) offset: 0.035f + */ + const float _HeadOffset = 0.032f; + const float _BodyOffset = 0.0269999985f; + const float _OffsetFactor = 0.001f; + static readonly Dictionary _OnHeadCache = new Dictionary(); + + + public override void DrawWornExtras() + { + if (Wearer == null || !Wearer.Spawned) return; + Building_Bed bed = Wearer.CurrentBed(); + if (bed != null && !bed.def.building.bed_showSleeperBody && !onHead) return; + + //Since I haven't a head apparel item to test the drawing code against for now we throw an error (ONCE) and exit. + if (this.onHead) + { + Log.ErrorOnce(string.Concat("CombatExtended :: Apparel_VisibleAccessory: The head drawing code is incomplete and the apparel '", + this.Label, "' will not be drawn."), this.def.debugRandomId); + return; + } + + // compute drawVec, angle and Rot4 vars + Rot4 rotation; + Rot4 bedRotation = new Rot4(); + float angle = 0; + Vector3 drawVec = Wearer.Drawer.DrawPos; + if (Wearer.GetPosture() != PawnPosture.Standing) + { + rotation = LayingFacing(); + if (bed != null) + { + bedRotation = bed.Rotation; + bedRotation.AsInt += 2; + angle = bedRotation.AsAngle; + AltitudeLayer altitude = (AltitudeLayer)((byte)Mathf.Max((int)bed.def.altitudeLayer, 14)); + drawVec.y = Wearer.Position.ToVector3ShiftedWithAltitude(altitude).y; + drawVec += bedRotation.FacingCell.ToVector3() * (-Wearer.Drawer.renderer.BaseHeadOffsetAt(Rot4.South).z); + } else { + drawVec.y = Wearer.Position.ToVector3ShiftedWithAltitude(AltitudeLayer.LayingPawn).y; + if (Wearer.Downed) // Wearer.Spawned == false when Pawn.Dead == true. + { + float? newAngle = (((((Wearer.Drawer == null) ? null : Wearer.Drawer.renderer) == null) ? null : Wearer.Drawer.renderer.wiggler) == null) ? (float?)null : Wearer.Drawer.renderer.wiggler.downedAngle; + if (newAngle != null) + angle = newAngle.Value; + } + else + { + angle = rotation.FacingCell.AngleFlat; + } + } + drawVec.y += 0.005f; + } else { + rotation = Wearer.Rotation; + drawVec.y = Wearer.Position.ToVector3ShiftedWithAltitude(AltitudeLayer.Pawn).y; + } + + drawVec.y += GetAltitudeOffset(rotation); + + // Get the graphic path + string path = def.graphicData.texPath + "_" + ((Wearer == null) ? null : Wearer.story.bodyType.ToString()); + Graphic graphic = GraphicDatabase.Get(path, ShaderDatabase.Cutout, def.graphicData.drawSize, DrawColor); + ApparelGraphicRecord apparelGraphic = new ApparelGraphicRecord(graphic, this); + + Material mat = apparelGraphic.graphic.MatAt(rotation); + Vector3 s = new Vector3(1.5f, 1.5f, 1.5f); + + mat.shader = ShaderDatabase.CutoutComplex; + mat.color = DrawColor; + Matrix4x4 matrix = default(Matrix4x4); + matrix.SetTRS(drawVec, Quaternion.AngleAxis(angle, Vector3.up), s); + Graphics.DrawMesh(rotation == Rot4.West ? MeshPool.plane10Flip : MeshPool.plane10, matrix, mat, 0); + } + + protected float GetAltitudeOffset(Rot4 rotation) + { + VisibleAccessoryDefExtension myDef = def.GetModExtension() ?? new VisibleAccessoryDefExtension(); + myDef.Validate(); + float offset = _OffsetFactor * myDef.order; + + if (!onHead) + { + if (rotation == Rot4.North) + offset += _HeadOffset; + else + offset += _BodyOffset; + } else { + if (rotation == Rot4.North) + offset += _BodyOffset; + else + offset += _HeadOffset; + } + return offset; + } + + // Copied from PawnRenderer + private Rot4 LayingFacing() + { + if (Wearer == null) + { + return Rot4.Random; + } + if (Wearer.GetPosture() == PawnPosture.LayingFaceUp) + { + return Rot4.South; + } + if (Wearer.RaceProps.Humanlike) + { + switch (Wearer.thingIDNumber % 4) + { + case 0: + return Rot4.South; + case 1: + return Rot4.South; + case 2: + return Rot4.East; + case 3: + return Rot4.West; + } + } + else + { + switch (Wearer.thingIDNumber % 4) + { + case 0: + return Rot4.South; + case 1: + return Rot4.East; + case 2: + return Rot4.West; + case 3: + return Rot4.West; + } + } + return Rot4.Random; + } + + //Utility, return if the apparel is worn on the head/body. + protected bool onHead + { + get { + if (!_OnHeadCache.ContainsKey(def.defName)) + { + List parts = Wearer.RaceProps.body.AllParts.Where(def.apparel.CoversBodyPart).ToList(); + bool gotHit = false; + foreach (BodyPartRecord part in parts) + { + BodyPartRecord p = part; + while (p != null) + { + if (p.groups.Contains(BodyPartGroupDefOf.Torso)) + { + _OnHeadCache.Add(def.defName, false); + gotHit = true; + break; + } + if (p.groups.Contains(BodyPartGroupDefOf.FullHead)) + { + _OnHeadCache.Add(def.defName, true); + gotHit = true; + break; + } + p = p.parent; + } + if (gotHit) + break; + } + if (!_OnHeadCache.ContainsKey(def.defName)) + { + Log.ErrorOnce(string.Concat("CombatExtended :: ", this.GetType(), " was unable to determine if body or head on item '", Label, + "', might the Wearer be non-human? Assuming apparel is on body."), def.debugRandomId); + _OnHeadCache.Add(def.defName, false); + } + } + bool ret; + _OnHeadCache.TryGetValue(def.defName, out ret); // is there a better way? Dictionary.Item isn't there. Didn't bother with try/catch as by now it should have the key. + return ret; + } + } + } +} diff --git a/Source/CombatExtended/CombatExtended/Things/Building_TurretGunCE.cs b/Source/CombatExtended/CombatExtended/Things/Building_TurretGunCE.cs new file mode 100644 index 0000000000..300ec75098 --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Things/Building_TurretGunCE.cs @@ -0,0 +1,664 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using Verse.AI; +using Verse.Sound; +using UnityEngine; + +namespace CombatExtended +{ + /* Class is cloned from Building_TurretGun with various changes made to support fire modes and ammo + * + * Unmodified methods should be kept up-to-date with vanilla class so long as they don't conflict with changes made. Please mark any changes you make from vanilla. + * -NIA + */ + [StaticConstructorOnStartup] + public class Building_TurretGunCE : Building_Turret + { + private const int minTicksBeforeAutoReload = 1800; // This much time must pass before haulers will try to automatically reload an auto-turret + + #region Fields + + protected int burstCooldownTicksLeft; + public int burstWarmupTicksLeft; // Need this public so aim mode can modify it + protected LocalTargetInfo currentTargetInt = LocalTargetInfo.Invalid; + private Thing gunInt; + private bool holdFire; + protected CompMannable mannableComp; + protected CompPowerTrader powerComp; + protected TurretTopCE top; + + public static Material ForcedTargetLineMat = MaterialPool.MatFrom(GenDraw.LineTexPath, ShaderDatabase.Transparent, new Color(1f, 0.5f, 0.5f)); + + // New fields + private CompAmmoUser compAmmo = null; + private CompFireModes compFireModes = null; + public bool isReloading = false; + private int ticksUntilAutoReload = 0; + + #endregion + + #region Properties + + public override Verb AttackVerb + { + get + { + if (Gun == null) + { + return null; + } + return this.GunCompEq.verbTracker.PrimaryVerb; + } + } + private bool CanSetForcedTarget + { + get + { + return mannableComp == null || MannedByColonist; // Add check for mannableComp == null since we allow auto-turrets to manually target stuff + } + } + public override LocalTargetInfo CurrentTarget + { + get + { + return this.currentTargetInt; + } + } + public CompEquippable GunCompEq + { + get + { + return Gun.TryGetComp(); + } + } + private bool WarmingUp + { + get + { + return this.burstWarmupTicksLeft > 0; + } + } + private bool CanToggleHoldFire + { + get + { + return base.Faction == Faction.OfPlayer || this.MannedByColonist; + } + } + private bool MannedByColonist + { + get + { + return this.mannableComp != null && this.mannableComp.ManningPawn != null && this.mannableComp.ManningPawn.Faction == Faction.OfPlayer; + } + } + public Thing Gun + { + get + { + if (this.gunInt == null) + { + this.gunInt = ThingMaker.MakeThing(this.def.building.turretGunDef, null); + InitGun(); + // FIXME: Hack to make player-crafted turrets spawn unloaded + if (Faction == Faction.OfPlayer) + { + Thing ammo; + if (CompAmmo != null && CompAmmo.TryUnload(out ammo) && !ammo.DestroyedOrNull()) + { + ammo.Destroy(); + } + } + } + return this.gunInt; + } + } + + // New properties + public CompAmmoUser CompAmmo + { + get + { + if (compAmmo == null && Gun != null) compAmmo = Gun.TryGetComp(); + return compAmmo; + } + } + public CompFireModes CompFireModes + { + get + { + if (compFireModes == null && Gun != null) compFireModes = Gun.TryGetComp(); + return compFireModes; + } + } + public bool NeedsReload + { + get + { + return mannableComp == null + && CompAmmo != null + && CompAmmo.hasMagazine + && (CompAmmo.curMagCount < CompAmmo.Props.magazineSize || CompAmmo.SelectedAmmo != CompAmmo.currentAmmo); + } + } + public bool AllowAutomaticReload + { + get + { + return mannableComp == null && CompAmmo != null + && CompAmmo.hasMagazine + && (ticksUntilAutoReload == 0 || CompAmmo.curMagCount <= Mathf.CeilToInt(CompAmmo.Props.magazineSize / 6)); + } + } + public CompMannable MannableComp => mannableComp; + + #endregion + + #region Constructors + + // Uses new TurretTopCE class + public Building_TurretGunCE() + { + this.top = new TurretTopCE(this); + } + + #endregion + + #region Methods + + // Added handling for ticksUntilAutoReload + protected void BeginBurst() + { + ticksUntilAutoReload = minTicksBeforeAutoReload; + GunCompEq.PrimaryVerb.TryStartCastOn(CurrentTarget, false, true); + OnAttackedTarget(CurrentTarget); + } + + // Added CompAmmo reload check + protected void BurstComplete() + { + if (this.def.building.turretBurstCooldownTime >= 0f) + { + this.burstCooldownTicksLeft = this.def.building.turretBurstCooldownTime.SecondsToTicks(); + } + else + { + this.burstCooldownTicksLeft = this.GunCompEq.PrimaryVerb.verbProps.defaultCooldownTime.SecondsToTicks(); + } + if (CompAmmo != null && CompAmmo.curMagCount <= 0) + { + TryOrderReload(); + } + } + + public override void DeSpawn() + { + base.DeSpawn(); + this.ResetCurrentTarget(); + } + + public override void Draw() + { + top.DrawTurret(); + base.Draw(); + } + + public override void DrawExtraSelectionOverlays() + { + float range = this.GunCompEq.PrimaryVerb.verbProps.range; + if (range < 90f) + { + GenDraw.DrawRadiusRing(base.Position, range); + } + float minRange = this.GunCompEq.PrimaryVerb.verbProps.minRange; + if (minRange < 90f && minRange > 0.1f) + { + GenDraw.DrawRadiusRing(base.Position, minRange); + } + if (this.WarmingUp) + { + int degreesWide = (int)((float)this.burstWarmupTicksLeft * 0.5f); + GenDraw.DrawAimPie(this, this.CurrentTarget, degreesWide, def.size.x * 0.5f); + } + if (this.forcedTarget.IsValid && (!this.forcedTarget.HasThing || this.forcedTarget.Thing.Spawned)) + { + Vector3 b; + if (this.forcedTarget.HasThing) + { + b = this.forcedTarget.Thing.TrueCenter(); + } + else + { + b = this.forcedTarget.Cell.ToVector3Shifted(); + } + Vector3 a = this.TrueCenter(); + b.y = Altitudes.AltitudeFor(AltitudeLayer.MetaOverlays); + a.y = b.y; + GenDraw.DrawLineBetween(a, b, Building_TurretGun.ForcedTargetLineMat); + } + } + + // Added new variables, removed bool loaded (not used in CE) + public override void ExposeData() + { + base.ExposeData(); + + // Look new variables + Scribe_Deep.Look(ref gunInt, "gunInt"); + InitGun(); + Scribe_Values.Look(ref isReloading, "isReloading", false); + Scribe_Values.Look(ref ticksUntilAutoReload, "ticksUntilAutoReload", 0); + + Scribe_Values.Look(ref this.burstCooldownTicksLeft, "burstCooldownTicksLeft", 0, false); + Scribe_Values.Look(ref this.burstWarmupTicksLeft, "burstWarmupTicksLeft", 0, false); + Scribe_TargetInfo.Look(ref this.currentTargetInt, "currentTarget"); + Scribe_Values.Look(ref this.holdFire, "holdFire", false, false); + } + + private void InitGun() + { + // Callback for ammo comp + if (CompAmmo != null) + { + CompAmmo.turret = this; + //if (def.building.turretShellDef != null && def.building.turretShellDef is AmmoDef) CompAmmo.selectedAmmo = (AmmoDef)def.building.turretShellDef; + } + List allVerbs = this.gunInt.TryGetComp().AllVerbs; + for (int i = 0; i < allVerbs.Count; i++) + { + Verb verb = allVerbs[i]; + verb.caster = this; + verb.castCompleteCallback = new Action(this.BurstComplete); + } + } + + // Replaced vanilla loaded text with CE reloading + public override string GetInspectString() + { + StringBuilder stringBuilder = new StringBuilder(); + string inspectString = base.GetInspectString(); + if (!inspectString.NullOrEmpty()) + { + stringBuilder.AppendLine(inspectString); + } + stringBuilder.AppendLine("GunInstalled".Translate() + ": " + this.Gun.LabelCap); + if (this.GunCompEq.PrimaryVerb.verbProps.minRange > 0f) + { + stringBuilder.AppendLine("MinimumRange".Translate() + ": " + this.GunCompEq.PrimaryVerb.verbProps.minRange.ToString("F0")); + } + + if (isReloading) + { + stringBuilder.AppendLine("CE_TurretReloading".Translate()); + } + else if (Spawned && burstCooldownTicksLeft > 0) + { + stringBuilder.AppendLine("CanFireIn".Translate() + ": " + this.burstCooldownTicksLeft.TicksToSecondsString()); + } + + if (CompAmmo != null && CompAmmo.Props.ammoSet != null) + { + stringBuilder.AppendLine("CE_AmmoSet".Translate() + ": " + CompAmmo.Props.ammoSet.LabelCap); + } + /* + if (this.def.building.turretShellDef != null) + { + if (this.loaded) + { + stringBuilder.AppendLine("ShellLoaded".Translate()); + } + else + { + stringBuilder.AppendLine("ShellNotLoaded".Translate()); + } + } + */ + return stringBuilder.ToString().TrimEndNewlines(); + } + + private bool IsValidTarget(Thing t) + { + Pawn pawn = t as Pawn; + if (pawn != null) + { + if (this.GunCompEq.PrimaryVerb.verbProps.projectileDef.projectile.flyOverhead) + { + RoofDef roofDef = base.Map.roofGrid.RoofAt(t.Position); + if (roofDef != null && roofDef.isThickRoof) + { + return false; + } + } + if (this.mannableComp == null) + { + return !GenAI.MachinesLike(base.Faction, pawn); + } + if (pawn.RaceProps.Animal && pawn.Faction == Faction.OfPlayer) + { + return false; + } + } + return true; + } + + public override void OrderAttack(LocalTargetInfo targ) + { + if (!targ.IsValid) + { + if (this.forcedTarget.IsValid) + { + this.ResetForcedTarget(); + } + return; + } + if ((targ.Cell - base.Position).LengthHorizontal < this.GunCompEq.PrimaryVerb.verbProps.minRange) + { + Messages.Message("MessageTargetBelowMinimumRange".Translate(), this, MessageSound.RejectInput); + return; + } + if ((targ.Cell - base.Position).LengthHorizontal > this.GunCompEq.PrimaryVerb.verbProps.range) + { + Messages.Message("MessageTargetBeyondMaximumRange".Translate(), this, MessageSound.RejectInput); + return; + } + if (this.forcedTarget != targ) + { + this.forcedTarget = targ; + if (this.burstCooldownTicksLeft <= 0) + { + this.TryStartShootSomething(false); + } + } + } + + private void ResetCurrentTarget() + { + this.currentTargetInt = LocalTargetInfo.Invalid; + this.burstWarmupTicksLeft = 0; + } + + private void ResetForcedTarget() + { + this.forcedTarget = LocalTargetInfo.Invalid; + this.burstWarmupTicksLeft = 0; + if (this.burstCooldownTicksLeft <= 0) + { + this.TryStartShootSomething(false); + } + } + + // Added CompAmmo setup + public override void SpawnSetup(Map map, bool respawningAfterLoad) + { + base.SpawnSetup(map, respawningAfterLoad); + powerComp = base.GetComp(); + mannableComp = base.GetComp(); + } + + private IAttackTargetSearcher TargSearcher() + { + if (this.mannableComp != null && this.mannableComp.MannedNow) + { + return this.mannableComp.ManningPawn; + } + return this; + } + + public override void Tick() + { + base.Tick(); + if (ticksUntilAutoReload > 0) ticksUntilAutoReload--; // Reduce time until we can auto-reload + if (CompAmmo?.curMagCount == 0 && (MannableComp?.MannedNow ?? false)) TryOrderReload(); + /* + if (!CanSetForcedTarget && forcedTarget.IsValid) + { + ResetForcedTarget(); + } + */ + if (!CanToggleHoldFire) + { + holdFire = false; + } + if (forcedTarget.ThingDestroyed) + { + ResetForcedTarget(); + } + bool flag = (this.powerComp == null || this.powerComp.PowerOn) && (this.mannableComp == null || this.mannableComp.MannedNow); + if (flag && base.Spawned) + { + this.GunCompEq.verbTracker.VerbsTick(); + if (!this.stunner.Stunned && this.GunCompEq.PrimaryVerb.state != VerbState.Bursting) + { + if (this.WarmingUp) + { + this.burstWarmupTicksLeft--; + if (this.burstWarmupTicksLeft == 0) + { + this.BeginBurst(); + } + } + else + { + if (this.burstCooldownTicksLeft > 0) + { + this.burstCooldownTicksLeft--; + } + if (this.burstCooldownTicksLeft <= 0) + { + this.TryStartShootSomething(true); + } + } + this.top.TurretTopTick(); + } + } + else + { + this.ResetCurrentTarget(); + } + } + + protected LocalTargetInfo TryFindNewTarget() + { + IAttackTargetSearcher attackTargetSearcher = this.TargSearcher(); + Faction faction = attackTargetSearcher.Thing.Faction; + float range = this.GunCompEq.PrimaryVerb.verbProps.range; + float minRange = this.GunCompEq.PrimaryVerb.verbProps.minRange; + Building t; + if (Rand.Value < 0.5f && this.GunCompEq.PrimaryVerb.verbProps.projectileDef.projectile.flyOverhead && faction.HostileTo(Faction.OfPlayer) && base.Map.listerBuildings.allBuildingsColonist.Where(delegate (Building x) + { + float num = (float)x.Position.DistanceToSquared(this.Position); + return num > minRange * minRange && num < range * range; + }).TryRandomElement(out t)) + { + return t; + } + TargetScanFlags targetScanFlags = TargetScanFlags.NeedThreat; + if (!this.GunCompEq.PrimaryVerb.verbProps.projectileDef.projectile.flyOverhead) + { + targetScanFlags |= TargetScanFlags.NeedLOSToAll; + targetScanFlags |= TargetScanFlags.LOSBlockableByGas; + } + if (this.GunCompEq.PrimaryVerb.verbProps.ai_IsIncendiary) + { + targetScanFlags |= TargetScanFlags.NeedNonBurning; + } + return (Thing)AttackTargetFinder.BestShootTargetFromCurrentPosition(attackTargetSearcher, new Predicate(this.IsValidTarget), range, minRange, targetScanFlags); + } + + // Added ammo check and use verb warmup time instead of turret's + protected void TryStartShootSomething(bool canBeginBurstImmediately) + { + // Check for ammo first + if (!base.Spawned + || (this.holdFire && this.CanToggleHoldFire) + || (this.GunCompEq.PrimaryVerb.verbProps.projectileDef.projectile.flyOverhead && base.Map.roofGrid.Roofed(base.Position)) + || (CompAmmo != null && (isReloading || (mannableComp == null && CompAmmo.curMagCount <= 0)))) + { + this.ResetCurrentTarget(); + return; + } + bool isValid = this.currentTargetInt.IsValid; + if (this.forcedTarget.IsValid) + { + this.currentTargetInt = this.forcedTarget; + } + else + { + this.currentTargetInt = this.TryFindNewTarget(); + } + if (!isValid && this.currentTargetInt.IsValid) + { + SoundDefOf.TurretAcquireTarget.PlayOneShot(new TargetInfo(base.Position, base.Map, false)); + } + if (this.currentTargetInt.IsValid) + { + // Use verb warmup time instead of turret's + if (AttackVerb.verbProps.warmupTime > 0f) + { + this.burstWarmupTicksLeft = AttackVerb.verbProps.warmupTime.SecondsToTicks(); + } + else if (canBeginBurstImmediately) + { + this.BeginBurst(); + } + else + { + this.burstWarmupTicksLeft = 1; + } + } + else + { + this.ResetCurrentTarget(); + } + } + + // New methods + + public void TryOrderReload() + { + /* + if (mannableComp == null) + { + if (!CompAmmo.useAmmo) CompAmmo.LoadAmmo(); + return; + } + */ + + if ((!mannableComp?.MannedNow ?? true) || (CompAmmo.currentAmmo == CompAmmo.SelectedAmmo && CompAmmo.curMagCount == CompAmmo.Props.magazineSize)) return; + Job reloadJob = null; + if (CompAmmo.useAmmo) + { + CompInventory inventory = mannableComp.ManningPawn.TryGetComp(); + if (inventory != null) + { + Thing ammo = inventory.container.FirstOrDefault(x => x.def == CompAmmo.SelectedAmmo); + if (ammo != null) + { + Thing droppedAmmo; + int amount = CompAmmo.Props.magazineSize; + if (CompAmmo.currentAmmo == CompAmmo.SelectedAmmo) amount -= CompAmmo.curMagCount; + if (inventory.container.TryDrop(ammo, this.Position, this.Map, ThingPlaceMode.Direct, Mathf.Min(ammo.stackCount, amount), out droppedAmmo)) + { + reloadJob = new Job(CE_JobDefOf.ReloadTurret, this, droppedAmmo) { count = droppedAmmo.stackCount }; + } + } + } + } + if (reloadJob == null) + { + reloadJob = new WorkGiver_ReloadTurret().JobOnThing(mannableComp.ManningPawn, this); + } + if (reloadJob != null) + { + var pawn = mannableComp.ManningPawn; + pawn.jobs.StartJob(reloadJob, JobCondition.Ongoing, null, pawn.CurJob?.def != reloadJob.def); + } + } + + public override IEnumerable GetGizmos() + { + foreach (Gizmo gizmo in base.GetGizmos()) + { + yield return gizmo; + } + // Ammo gizmos + if (CompAmmo != null) + { + foreach (Command com in CompAmmo.CompGetGizmosExtra()) + { + yield return com; + } + } + // Fire mode gizmos + if (CompFireModes != null) + { + foreach (Command com in CompFireModes.GenerateGizmos()) + { + yield return com; + } + } + if (Faction == Faction.OfPlayer) + { + // Set forced target gizmo + if (CanSetForcedTarget) + { + yield return new Command_VerbTarget + { + defaultLabel = "CommandSetForceAttackTarget".Translate(), + defaultDesc = "CommandSetForceAttackTargetDesc".Translate(), + icon = ContentFinder.Get("UI/Commands/Attack", true), + verb = GunCompEq.PrimaryVerb, + hotKey = KeyBindingDefOf.Misc4 + }; + } + // Stop forced attack gizmo + if (forcedTarget.IsValid) + { + Command_Action stop = new Command_Action(); + stop.defaultLabel = "CommandStopForceAttack".Translate(); + stop.defaultDesc = "CommandStopForceAttackDesc".Translate(); + stop.icon = ContentFinder.Get("UI/Commands/Halt", true); + stop.action = delegate + { + ResetForcedTarget(); + SoundDefOf.TickLow.PlayOneShotOnCamera(null); + }; + if (!this.forcedTarget.IsValid) + { + stop.Disable("CommandStopAttackFailNotForceAttacking".Translate()); + } + stop.hotKey = KeyBindingDefOf.Misc5; + yield return stop; + } + // Toggle fire gizmo + if (CanToggleHoldFire) + { + yield return new Command_Toggle + { + defaultLabel = "CommandHoldFire".Translate(), + defaultDesc = "CommandHoldFireDesc".Translate(), + icon = ContentFinder.Get("UI/Commands/HoldFire", true), + hotKey = KeyBindingDefOf.Misc6, + toggleAction = delegate + { + holdFire = !holdFire; + if (holdFire) + { + ResetForcedTarget(); + } + }, + isActive = (() => holdFire) + }; + } + } + + } + + #endregion + + } +} diff --git a/Source/CombatRealism/CombatExtended/Things/IncendiaryFuel.cs b/Source/CombatExtended/CombatExtended/Things/IncendiaryFuel.cs similarity index 90% rename from Source/CombatRealism/CombatExtended/Things/IncendiaryFuel.cs rename to Source/CombatExtended/CombatExtended/Things/IncendiaryFuel.cs index 6f66b784cd..bbc43d587f 100644 --- a/Source/CombatRealism/CombatExtended/Things/IncendiaryFuel.cs +++ b/Source/CombatExtended/CombatExtended/Things/IncendiaryFuel.cs @@ -12,9 +12,9 @@ public class IncendiaryFuel : Filth { private const float maxFireSize = 1.75f; - public override void SpawnSetup(Map map) + public override void SpawnSetup(Map map, bool respawningAfterLoad) { - base.SpawnSetup(map); + base.SpawnSetup(map, respawningAfterLoad); List list = new List(Position.GetThingList(map)); foreach (Thing thing in list) { diff --git a/Source/CombatRealism/CombatExtended/Things/LoadoutGeneratorThing.cs b/Source/CombatExtended/CombatExtended/Things/LoadoutGeneratorThing.cs similarity index 100% rename from Source/CombatRealism/CombatExtended/Things/LoadoutGeneratorThing.cs rename to Source/CombatExtended/CombatExtended/Things/LoadoutGeneratorThing.cs diff --git a/Source/CombatRealism/CombatExtended/Things/Plant_Blazebulb.cs b/Source/CombatExtended/CombatExtended/Things/Plant_Blazebulb.cs similarity index 78% rename from Source/CombatRealism/CombatExtended/Things/Plant_Blazebulb.cs rename to Source/CombatExtended/CombatExtended/Things/Plant_Blazebulb.cs index c2907b09af..3c558561a0 100644 --- a/Source/CombatRealism/CombatExtended/Things/Plant_Blazebulb.cs +++ b/Source/CombatExtended/CombatExtended/Things/Plant_Blazebulb.cs @@ -10,7 +10,13 @@ namespace CombatExtended { class Plant_Blazebulb : Plant { - private const int ignitionTemp = 21; // Temperature (in Celsius) above which the plant will start catching fire + private const int ignitionTemp = 28; // Temperature (in Celsius) above which the plant will start catching fire + + public override void SpawnSetup(Map map, bool respawningAfterLoad) + { + base.SpawnSetup(map, respawningAfterLoad); + PlayerKnowledgeDatabase.KnowledgeDemonstrated(CE_ConceptDefOf.CE_ObtainingPrometheum, KnowledgeAmount.Total); + } public override void TickLong() { @@ -33,7 +39,7 @@ public override void PostApplyDamage(DamageInfo dinfo, float totalDamageDealt) if(dinfo.Def != DamageDefOf.Rotting) { // Find existing fuel puddle or spawn one if needed - Thing fuel = Position.GetThingList(this.Map).FirstOrDefault(x => x.def == CE_ThingDefOf.Napalm_Fuel); + Thing fuel = Position.GetThingList(this.Map).FirstOrDefault(x => x.def == ThingDefOf.FilthFuel); int fuelHPFromDamage = Mathf.CeilToInt(fuel.MaxHitPoints * Mathf.Clamp01(totalDamageDealt / MaxHitPoints)); if (fuel != null) { @@ -41,7 +47,7 @@ public override void PostApplyDamage(DamageInfo dinfo, float totalDamageDealt) } else { - fuel = ThingMaker.MakeThing(CE_ThingDefOf.Napalm_Fuel); + fuel = ThingMaker.MakeThing(ThingDefOf.FilthFuel); GenSpawn.Spawn(fuel, Position, this.Map); fuel.HitPoints = fuelHPFromDamage; } diff --git a/Source/CombatExtended/CombatExtended/ThinkNodes/ThinkNode_ConditionalHasSquad.cs b/Source/CombatExtended/CombatExtended/ThinkNodes/ThinkNode_ConditionalHasSquad.cs new file mode 100644 index 0000000000..e6cfe3e72e --- /dev/null +++ b/Source/CombatExtended/CombatExtended/ThinkNodes/ThinkNode_ConditionalHasSquad.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using UnityEngine; + +namespace CombatExtended +{ + public class ThinkNode_ConditionalHasSquad : ThinkNode_Conditional + { + protected override bool Satisfied(Pawn pawn) + { + CompSquadBrain comp = pawn.TryGetComp(); + return comp != null && comp.squad != null; + } + } +} diff --git a/Source/CombatRealism/CombatExtended/ThinkNodes/ThinkNode_ConditionalHunkering.cs b/Source/CombatExtended/CombatExtended/ThinkNodes/ThinkNode_ConditionalHunkering.cs similarity index 52% rename from Source/CombatRealism/CombatExtended/ThinkNodes/ThinkNode_ConditionalHunkering.cs rename to Source/CombatExtended/CombatExtended/ThinkNodes/ThinkNode_ConditionalHunkering.cs index a1f1f57772..55c8da6cf6 100644 --- a/Source/CombatRealism/CombatExtended/ThinkNodes/ThinkNode_ConditionalHunkering.cs +++ b/Source/CombatExtended/CombatExtended/ThinkNodes/ThinkNode_ConditionalHunkering.cs @@ -13,16 +13,7 @@ class ThinkNode_ConditionalHunkering : ThinkNode_Conditional protected override bool Satisfied(Pawn pawn) { CompSuppressable comp = pawn.TryGetComp(); - if (comp == null) - { - return false; - } - float distToSuppressor = (pawn.Position - comp.suppressorLoc).LengthHorizontal; - if (distToSuppressor < CompSuppressable.minSuppressionDist) - { - return false; - } - return comp.isHunkering; + return comp != null && comp.CanReactToSuppression && comp.IsHunkering; } } } diff --git a/Source/CombatRealism/CombatExtended/ThinkNodes/ThinkNode_ConditionalNoJob.cs b/Source/CombatExtended/CombatExtended/ThinkNodes/ThinkNode_ConditionalNoJob.cs similarity index 82% rename from Source/CombatRealism/CombatExtended/ThinkNodes/ThinkNode_ConditionalNoJob.cs rename to Source/CombatExtended/CombatExtended/ThinkNodes/ThinkNode_ConditionalNoJob.cs index bcbd1cd945..1ca244afa9 100644 --- a/Source/CombatRealism/CombatExtended/ThinkNodes/ThinkNode_ConditionalNoJob.cs +++ b/Source/CombatExtended/CombatExtended/ThinkNodes/ThinkNode_ConditionalNoJob.cs @@ -12,7 +12,7 @@ public class ThinkNode_ConditionalNoJob : ThinkNode_Conditional { protected override bool Satisfied(Pawn pawn) { - return pawn.jobs == null || pawn.jobs.curJob == null; + return pawn.CurJob == null; } } } diff --git a/Source/CombatRealism/CombatExtended/ThinkNodes/ThinkNode_ConditionalSuppressed.cs b/Source/CombatExtended/CombatExtended/ThinkNodes/ThinkNode_ConditionalSuppressed.cs similarity index 52% rename from Source/CombatRealism/CombatExtended/ThinkNodes/ThinkNode_ConditionalSuppressed.cs rename to Source/CombatExtended/CombatExtended/ThinkNodes/ThinkNode_ConditionalSuppressed.cs index d541e39172..bc72708363 100644 --- a/Source/CombatRealism/CombatExtended/ThinkNodes/ThinkNode_ConditionalSuppressed.cs +++ b/Source/CombatExtended/CombatExtended/ThinkNodes/ThinkNode_ConditionalSuppressed.cs @@ -13,16 +13,7 @@ class ThinkNode_ConditionalSuppressed : ThinkNode_Conditional protected override bool Satisfied(Pawn pawn) { CompSuppressable comp = pawn.TryGetComp(); - if (comp == null) - { - return false; - } - float distToSuppressor = (pawn.Position - comp.suppressorLoc).LengthHorizontal; - if (distToSuppressor < CompSuppressable.minSuppressionDist) - { - return false; - } - return comp.isSuppressed; + return comp != null && comp.CanReactToSuppression && comp.isSuppressed; } } } diff --git a/Source/CombatRealism/CombatExtended/ThoughtWorkers/ThoughtWorker_Suppressed.cs b/Source/CombatExtended/CombatExtended/ThoughtWorkers/ThoughtWorker_Suppressed.cs similarity index 89% rename from Source/CombatRealism/CombatExtended/ThoughtWorkers/ThoughtWorker_Suppressed.cs rename to Source/CombatExtended/CombatExtended/ThoughtWorkers/ThoughtWorker_Suppressed.cs index f745289f46..ca28685d39 100644 --- a/Source/CombatRealism/CombatExtended/ThoughtWorkers/ThoughtWorker_Suppressed.cs +++ b/Source/CombatExtended/CombatExtended/ThoughtWorkers/ThoughtWorker_Suppressed.cs @@ -15,7 +15,7 @@ protected override ThoughtState CurrentStateInternal(Pawn p) CompSuppressable comp = p.TryGetComp(); if (comp != null) { - if (comp.isHunkering) + if (comp.IsHunkering) { return ThoughtState.ActiveAtStage(2); } @@ -23,7 +23,7 @@ protected override ThoughtState CurrentStateInternal(Pawn p) { return ThoughtState.ActiveAtStage(1); } - else if (comp.currentSuppression > 0) + else if (comp.CurrentSuppression > 0) { return ThoughtState.ActiveAtStage(0); } diff --git a/Source/CombatRealism/CombatExtended/TurretTopCE.cs b/Source/CombatExtended/CombatExtended/TurretTopCE.cs similarity index 100% rename from Source/CombatRealism/CombatExtended/TurretTopCE.cs rename to Source/CombatExtended/CombatExtended/TurretTopCE.cs diff --git a/Source/CombatRealism/CombatExtended/Verbs/VerbPropertiesCE.cs b/Source/CombatExtended/CombatExtended/Verbs/VerbPropertiesCE.cs similarity index 100% rename from Source/CombatRealism/CombatExtended/Verbs/VerbPropertiesCE.cs rename to Source/CombatExtended/CombatExtended/Verbs/VerbPropertiesCE.cs diff --git a/Source/CombatExtended/CombatExtended/Verbs/Verb_LaunchProjectileCE.cs b/Source/CombatExtended/CombatExtended/Verbs/Verb_LaunchProjectileCE.cs new file mode 100644 index 0000000000..7c84695c54 --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Verbs/Verb_LaunchProjectileCE.cs @@ -0,0 +1,732 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using RimWorld; +using Verse; +using Verse.AI; +using UnityEngine; + +namespace CombatExtended +{ + public class Verb_LaunchProjectileCE : Verse.Verb + { + #region Constants + + // Cover check constants + private const float distToCheckForCover = 3f; // How many cells to raycast on the cover check + private const float segmentLength = 0.2f; // How long a single raycast segment is + //private const float shotHeightFactor = 0.85f; // The height at which pawns hold their guns + + #endregion + + #region Fields + + // Targeting factors + private float estimatedTargDist = -1; // Stores estimate target distance for each burst, so each burst shot uses the same + private int numShotsFired = 0; // Stores how many shots were fired for purposes of recoil + + // Angle in Vector2(degrees, radians) + private Vector2 newTargetLoc = new Vector2(0, 0); + private Vector2 sourceLoc = new Vector2(0, 0); + + private float shotAngle = 0f; // Shot angle off the ground in radians. + private float shotRotation = 0f; // Angle rotation towards target. + + protected CompCharges compCharges = null; + protected CompAmmoUser compAmmo = null; + protected CompFireModes compFireModes = null; + private float shotSpeed = -1; + + private float rotationDegrees = 0f; + private float angleRadians = 0f; + + private int lastTauntTick; + + #endregion + + #region Properties + + public VerbPropertiesCE VerbPropsCE => this.verbProps as VerbPropertiesCE; + public ProjectilePropertiesCE projectilePropsCE => this.ProjectileDef.projectile as ProjectilePropertiesCE; + + // Returns either the pawn aiming the weapon or in case of turret guns the turret operator or null if neither exists + public Pawn ShooterPawn => CasterPawn != null ? CasterPawn : CE_Utility.TryGetTurretOperator(this.caster); + + protected CompCharges CompCharges + { + get + { + if (this.compCharges == null && this.ownerEquipment != null) + { + this.compCharges = this.ownerEquipment.TryGetComp(); + } + return this.compCharges; + } + } + private float ShotSpeed + { + get + { + if (shotSpeed < 0) + { + if (CompCharges != null) + { + Vector2 bracket; + if (CompCharges.GetChargeBracket((currentTarget.Cell - caster.Position).LengthHorizontal, out bracket)) + { + shotSpeed = bracket.x; + } + } + else + { + shotSpeed = verbProps.projectileDef.projectile.speed; + } + } + return shotSpeed; + } + } + private float ShotHeight => (new CollisionVertical(caster)).shotHeight; + private Vector3 ShotSource + { + get + { + var casterPos = caster.DrawPos; + return new Vector3(casterPos.x, ShotHeight, casterPos.z); + } + } + + protected float ShootingAccuracy => CasterPawn?.GetStatValue(StatDefOf.ShootingAccuracy) ?? 2f; + protected float AimingAccuracy => ShooterPawn?.GetStatValue(CE_StatDefOf.AimingAccuracy) ?? 0.75f; + protected float SightsEfficiency => ownerEquipment.GetStatValue(CE_StatDefOf.SightsEfficiency); + protected virtual float SwayAmplitude => Mathf.Max(0, (4.5f - ShootingAccuracy) * ownerEquipment.GetStatValue(StatDef.Named("SwayFactor"))); + + // Ammo variables + protected CompAmmoUser CompAmmo + { + get + { + if (compAmmo == null && this.ownerEquipment != null) + { + compAmmo = this.ownerEquipment.TryGetComp(); + } + return compAmmo; + } + } + public ThingDef ProjectileDef + { + get + { + if (CompAmmo != null) + { + if (CompAmmo.currentAmmo != null) + { + return CompAmmo.CurAmmoProjectile; + } + } + return this.VerbPropsCE.projectileDef; + } + } + + protected CompFireModes CompFireModes + { + get + { + if (this.compFireModes == null && this.ownerEquipment != null) + { + this.compFireModes = this.ownerEquipment.TryGetComp(); + } + return this.compFireModes; + } + } + + #endregion + + #region Methods + + /// + /// Highlights explosion radius of the projectile if it has one + /// + /// Projectile explosion radius + public override float HighlightFieldRadiusAroundTarget() + { + return ProjectileDef.projectile.explosionRadius; + } + + /// + /// Resets current burst shot count and estimated distance at beginning of the burst + /// + public override void WarmupComplete() + { + // attack shooting expression + Pawn shooter = ShooterPawn; + if (Controller.settings.ShowTaunts + && shooter != null + && shooter.Map != null + && shooter.def.race.Humanlike + && currentTarget != null + && currentTarget.Thing is Pawn + && Find.TickManager.TicksGame - lastTauntTick >= 120 + && Rand.Chance(0.25f)) + { + string rndswear = RulePackDef.Named("AttackMote").Rules.RandomElement().Generate(); + if (rndswear == "[swear]" || rndswear == "" || rndswear == " ") + { + Log.Warning("CE tried throwing invalid taunt for " + shooter.ToString()); + } + else + { + MoteMaker.ThrowText(shooter.Position.ToVector3Shifted(), shooter.Map, rndswear); + } + lastTauntTick = Find.TickManager.TicksGame; + } + + this.numShotsFired = 0; + base.WarmupComplete(); + } + + /// + /// Shifts the original target position in accordance with target leading, range estimation and weather/lighting effects + /// + protected virtual void ShiftTarget(ShiftVecReport report, bool calculateMechanicalOnly = false) + { + if (!calculateMechanicalOnly) + { + Vector3 u = CasterPawn != null ? CasterPawn.DrawPos : caster.Position.ToVector3Shifted(); + sourceLoc.Set(u.x, u.z); + + if (this.numShotsFired == 0) + { + // On first shot of burst do a range estimate + estimatedTargDist = report.GetRandDist(); + } + + Vector3 v = report.targetPawn != null ? report.targetPawn.DrawPos : report.target.Cell.ToVector3Shifted(); + newTargetLoc.Set(v.x, v.z); + + // ----------------------------------- STEP 1: Actual location + Shift for visibility + + //FIXME : GetRandCircularVec may be causing recoil to be unnoticeable - each next shot in the burst has a new random circular vector around the target. + newTargetLoc += report.GetRandCircularVec(); + + // ----------------------------------- STEP 2: Estimated shot to hit location + + newTargetLoc = sourceLoc + (newTargetLoc - sourceLoc).normalized * estimatedTargDist; + + // Lead a moving target + newTargetLoc += report.GetRandLeadVec(); + + // ----------------------------------- STEP 3: Recoil, Skewing, Skill checks, Cover calculations + + rotationDegrees = 0f; + angleRadians = 0f; + + GetSwayVec(ref rotationDegrees, ref angleRadians); + GetRecoilVec(ref rotationDegrees, ref angleRadians); + + // Height difference calculations for ShotAngle + float targetHeight = 0f; + + var coverRange = new CollisionVertical(report.cover).HeightRange; //Get " " cover, assume it is the edifice + + // Projectiles with flyOverhead target the ground below the target and ignore cover + if (ProjectileDef.projectile.flyOverhead) + { + targetHeight = coverRange.max; + } + else + { + var victimVert = new CollisionVertical(currentTarget.Thing); + var targetRange = victimVert.HeightRange; //Get lower and upper heights of the target + if (targetRange.min < coverRange.max) //Some part of the target is hidden behind cover + { + // - It is possible for targetVertical.max < coverVertical.max, technically, in which case the shooter will never hit until the cover is gone. + // - This should be checked for in LoS -NIA + targetRange.min = coverRange.max; + + // Shift aim upwards if we're doing suppressive fire + if (targetRange.max <= coverRange.max && CompFireModes?.CurrentAimMode == AimMode.SuppressFire) + { + targetRange.max = coverRange.max * 2; + targetRange.min = coverRange.max; + } + } + else if (currentTarget.Thing is Pawn) + { + // Aim for center of mass on an exposed target + targetRange.min = victimVert.BottomHeight; + targetRange.max = victimVert.MiddleHeight; + } + targetHeight = targetRange.Average; + } + angleRadians += ProjectileCE.GetShotAngle(ShotSpeed, (newTargetLoc - sourceLoc).magnitude, targetHeight - ShotHeight, ProjectileDef.projectile.flyOverhead, projectilePropsCE.Gravity); + } + + // ----------------------------------- STEP 4: Mechanical variation + + // Get shotvariation, in angle Vector2 RADIANS. + Vector2 spreadVec = report.GetRandSpreadVec(); + + // ----------------------------------- STEP 5: Finalization + + var w = (newTargetLoc - sourceLoc); + shotRotation = (90 + Mathf.Rad2Deg * Mathf.Atan2(-w.y, w.x) + rotationDegrees + spreadVec.x) % 360; + shotAngle = angleRadians + spreadVec.y * Mathf.Deg2Rad; + } + + /// + /// Calculates the amount of recoil at a given point in a burst, up to a maximum + /// + /// The ref float to have horizontal recoil in degrees added to. + /// The ref float to have vertical recoil in radians added to. + private void GetRecoilVec(ref float rotation, ref float angle) + { + var recoil = VerbPropsCE.recoilAmount; + float maxX = 0; + float minX = 0; + float maxY = 0; + float minY = 0; + switch (VerbPropsCE.recoilPattern) + { + case RecoilPattern.None: + return; + case RecoilPattern.Regular: + float num = VerbPropsCE.recoilAmount / 3; + minX = -(num / 3); + maxX = num; + minY = -num; + maxY = VerbPropsCE.recoilAmount; + break; + case RecoilPattern.Mounted: + float num2 = VerbPropsCE.recoilAmount / 3; + minX = -num2; + maxX = num2; + minY = -num2; + maxY = VerbPropsCE.recoilAmount; + break; + } + float recoilMagnitude = Mathf.Pow((5 - ShootingAccuracy), (Mathf.Min(10, numShotsFired) / 6.25f)); + + rotation += recoilMagnitude * UnityEngine.Random.Range(minX, maxX); + angle += Mathf.Deg2Rad * recoilMagnitude * UnityEngine.Random.Range(minY, maxY); + } + + /// + /// Calculates current weapon sway based on a parametric function with maximum amplitude depending on shootingAccuracy and scaled by weapon's swayFactor. + /// + /// The ref float to have horizontal sway in degrees added to. + /// The ref float to have vertical sway in radians added to. + protected void GetSwayVec(ref float rotation, ref float angle) + { + float ticks = (float)(Find.TickManager.TicksAbs + this.caster.thingIDNumber); + rotation += SwayAmplitude * (float)Mathf.Sin(ticks * 0.022f); + angle += Mathf.Deg2Rad * 0.25f * SwayAmplitude * (float)Mathf.Sin(ticks * 0.0165f); + } + + public virtual ShiftVecReport ShiftVecReportFor(LocalTargetInfo target) + { + IntVec3 targetCell = target.Cell; + ShiftVecReport report = new ShiftVecReport(); + report.target = target; + report.aimingAccuracy = this.AimingAccuracy; + report.sightsEfficiency = this.SightsEfficiency; + report.shotDist = (targetCell - this.caster.Position).LengthHorizontal; + + report.lightingShift = 1 - caster.Map.glowGrid.GameGlowAt(targetCell); + if (!this.caster.Position.Roofed(caster.Map) || !targetCell.Roofed(caster.Map)) //Change to more accurate algorithm? + { + report.weatherShift = 1 - caster.Map.weatherManager.CurWeatherAccuracyMultiplier; + } + report.shotSpeed = this.ShotSpeed; + report.swayDegrees = this.SwayAmplitude; + report.spreadDegrees = this.ownerEquipment.GetStatValue(StatDef.Named("ShotSpread")) * this.projectilePropsCE.spreadMult; + Thing cover; + float smokeDensity; + this.GetHighestCoverAndSmokeForTarget(target, out cover, out smokeDensity); + report.cover = cover; + report.smokeDensity = smokeDensity; + + return report; + } + + /// + /// Checks for cover along the flight path of the bullet, doesn't check for walls or trees, only intended for cover with partial fillPercent + /// + /// The target of which to find cover of + /// Output parameter, filled with the highest cover object found + /// True if cover was found, false otherwise + private bool GetHighestCoverAndSmokeForTarget(LocalTargetInfo target, out Thing cover, out float smokeDensity) + { + Map map = caster.Map; + Thing targetThing = target.Thing; + Thing highestCover = null; + float highestCoverHeight = 0f; + + smokeDensity = 0; + + // Iterate through all cells on line of sight and check for cover and smoke + var cells = GenSight.PointsOnLineOfSight(target.Cell, caster.Position).ToArray(); + if (cells.Length < 3) + { + cover = null; + return false; + } + for (int i = 0; i <= cells.Length / 2; i++) + { + var cell = cells[i]; + + if (cell.AdjacentTo8Way(caster.Position)) continue; + + // Check for smoke + var gas = cell.GetGas(map); + if (gas != null) + { + smokeDensity += gas.def.gas.accuracyPenalty; + } + + // Check for cover in the second half of LoS + if (i <= cells.Length / 2) + { + Pawn pawn = cell.GetFirstPawn(map); + Thing newCover = pawn == null ? cell.GetCover(map) : pawn; + float newCoverHeight = new CollisionVertical(newCover).Max; + + // Cover check, if cell has cover compare collision height and get the highest piece of cover, ignore if cover is the target (e.g. solar panels, crashed ship, etc) + if (newCover != null + && (targetThing == null || !newCover.Equals(targetThing)) + && (highestCover == null || highestCoverHeight < newCoverHeight) + && newCover.def.Fillage == FillCategory.Partial + && !newCover.IsTree()) + { + highestCover = newCover; + highestCoverHeight = newCoverHeight; + if (Controller.settings.DebugDrawTargetCoverChecks) map.debugDrawer.FlashCell(cell, highestCoverHeight, highestCoverHeight.ToString()); + } + } + } + cover = highestCover; + + //Report success if found cover + return cover != null; + } + + /// + /// Checks if the shooter can hit the target from a certain position with regards to cover height + /// + /// The position from which to check + /// The target to check for line of sight + /// True if shooter can hit target from root position, false otherwise + public override bool CanHitTargetFrom(IntVec3 root, LocalTargetInfo targ) + { + string unused; + return CanHitTargetFrom(root, targ, out unused); + } + + public bool CanHitTarget(LocalTargetInfo targ, out string report) + { + return CanHitTargetFrom(caster.Position, targ, out report); + } + + public virtual bool CanHitTargetFrom(IntVec3 root, LocalTargetInfo targ, out string report) + { + report = ""; + if (!targ.Cell.InBounds(caster.Map) || !root.InBounds(caster.Map)) + { + report = "Out of bounds"; + return false; + } + // Check target self + if (targ.Thing != null && targ.Thing == this.caster) + { + if (!verbProps.targetParams.canTargetSelf) + { + report = "Can't target self"; + return false; + } + return true; + } + // Check thick roofs + if (ProjectileDef.projectile.flyOverhead) + { + RoofDef roofDef = caster.Map.roofGrid.RoofAt(targ.Cell); + if (roofDef != null && roofDef.isThickRoof) + { + report = "Blocked by roof"; + return false; + } + } + // Check for apparel + if (CasterIsPawn && CasterPawn.apparel != null) + { + List wornApparel = CasterPawn.apparel.WornApparel; + foreach(Apparel current in wornApparel) + { + if (!current.AllowVerbCast(root, caster.Map, targ)) + { + report = "Shooting disallowed by " + current.LabelShort; + return false; + } + } + } + // Check for line of sight + ShootLine shootLine; + if (!TryFindCEShootLineFromTo(root, targ, out shootLine)) + { + float lengthHorizontalSquared = (root - targ.Cell).LengthHorizontalSquared; + if (lengthHorizontalSquared > verbProps.range * verbProps.range) + { + report = "Out of range"; + } + else if(lengthHorizontalSquared < verbProps.minRange * verbProps.minRange) + { + report = "Within minimum range"; + } + else + { + report = "No line of sight"; + } + return false; + } + return true; + } + + /// + /// Fires a projectile using the new aiming system + /// + /// True for successful shot, false otherwise + protected override bool TryCastShot() + { + ShootLine shootLine; + if (!TryFindCEShootLineFromTo(caster.Position, currentTarget, out shootLine)) + { + return false; + } + if (projectilePropsCE.pelletCount < 1) + { + Log.Error(ownerEquipment.LabelCap + " tried firing with pelletCount less than 1."); + return false; + } + ShiftVecReport report = ShiftVecReportFor(currentTarget); + bool pelletMechanicsOnly = false; + for (int i = 0; i < projectilePropsCE.pelletCount; i++) + { + ProjectileCE projectile = (ProjectileCE)ThingMaker.MakeThing(ProjectileDef, null); + GenSpawn.Spawn(projectile, shootLine.Source, caster.Map); + ShiftTarget(report, pelletMechanicsOnly); + + //New aiming algorithm + if (verbProps.targetParams.canTargetSelf) + { + projectile.canTargetSelf = true; + } + projectile.minCollisionSqr = (sourceLoc - currentTarget.Cell.ToIntVec2.ToVector2Shifted()).sqrMagnitude; + projectile.Launch(caster, sourceLoc, shotAngle, shotRotation, ShotHeight, ShotSpeed, ownerEquipment); + pelletMechanicsOnly = true; + } + pelletMechanicsOnly = false; + this.numShotsFired++; + return true; + } + + /// + /// This is a custom CE ticker. Since the vanilla VerbTick() method is non-virtual we need to detour VerbTracker and make it call this method in addition to the vanilla ticker in order to + /// add custom ticker functionality. + /// + public virtual void VerbTickCE() + { + } + + #region Line of Sight Utility + + /* Line of sight calculating methods + * + * Copied from vanilla Verse.Verb class, the only change here is usage of our own validator for partial cover checks. Copy-paste should be kept up to date with vanilla + * and if possible replaced with a cleaner solution. + * + * -NIA + */ + + private static List tempDestList = new List(); + private static List tempLeanShootSources = new List(); + + public bool TryFindCEShootLineFromTo(IntVec3 root, LocalTargetInfo targ, out ShootLine resultingLine) + { + if (targ.HasThing && targ.Thing.Map != this.caster.Map) + { + resultingLine = default(ShootLine); + return false; + } + if (this.verbProps.MeleeRange) + { + resultingLine = new ShootLine(root, targ.Cell); + return ReachabilityImmediate.CanReachImmediate(root, targ, this.caster.Map, PathEndMode.Touch, null); + } + CellRect cellRect = (!targ.HasThing) ? CellRect.SingleCell(targ.Cell) : targ.Thing.OccupiedRect(); + float num = cellRect.ClosestDistSquaredTo(root); + if (num > this.verbProps.range * this.verbProps.range || num < this.verbProps.minRange * this.verbProps.minRange) + { + resultingLine = new ShootLine(root, targ.Cell); + return false; + } + if (!this.verbProps.NeedsLineOfSight) + { + resultingLine = new ShootLine(root, targ.Cell); + return true; + } + if (this.CasterIsPawn) + { + IntVec3 dest; + if (this.CanHitFromCellIgnoringRange(root, targ, out dest)) + { + resultingLine = new ShootLine(root, dest); + return true; + } + ShootLeanUtility.LeanShootingSourcesFromTo(root, cellRect.ClosestCellTo(root), this.caster.Map, tempLeanShootSources); + for (int i = 0; i < tempLeanShootSources.Count; i++) + { + IntVec3 intVec = tempLeanShootSources[i]; + if (this.CanHitFromCellIgnoringRange(intVec, targ, out dest)) + { + resultingLine = new ShootLine(intVec, dest); + return true; + } + } + } + else + { + CellRect.CellRectIterator iterator = this.caster.OccupiedRect().GetIterator(); + while (!iterator.Done()) + { + IntVec3 current = iterator.Current; + IntVec3 dest; + if (this.CanHitFromCellIgnoringRange(current, targ, out dest)) + { + resultingLine = new ShootLine(current, dest); + return true; + } + iterator.MoveNext(); + } + } + resultingLine = new ShootLine(root, targ.Cell); + return false; + } + + private bool CanHitFromCellIgnoringRange(IntVec3 sourceCell, LocalTargetInfo targ, out IntVec3 goodDest) + { + if (targ.Thing != null) + { + if (targ.Thing.Map != this.caster.Map) + { + goodDest = IntVec3.Invalid; + return false; + } + // (ProfoundDarkness) I only ever see this code execute for the target, not the shooter... + // (ProfoundDarkness) I don't know what I'm doing here so basically if the target has a structure next to them assume they will lean, rather than a more precise and accurate + // test. + + // If the target is near something they might have to lean around to shoot then calculate their leans. + // NOTE: CellsAdjacent8Way includes the check for if a location is in map bounds so can use CanBeSeenOverFast. The alternative is fast 8way and slow (bounds checking) CanBeSeenOver. + if ((targ.Thing as Pawn)?.CurJob?.def != CE_JobDefOf.HunkerDown && GenAdjFast.AdjacentCells8Way(targ.Thing).FirstOrDefault(c => !c.CanBeSeenOver(targ.Thing.Map)) != null) + { + ShootLeanUtility.CalcShootableCellsOf(tempDestList, targ.Thing); + } else // otherwise just assume that the target won't lean... + { + tempDestList.Clear(); + tempDestList.Add(targ.Cell); + } + + for (int i = 0; i < tempDestList.Count; i++) + { + if (this.CanHitCellFromCellIgnoringRange(sourceCell, tempDestList[i], targ.Thing, targ.Thing.def.Fillage == FillCategory.Full)) + { // if any of the locations the target is at or can lean to for shooting can be shot by the shooter then lets have the shooter shoot. + goodDest = tempDestList[i]; + return true; + } + } + } + else if (this.CanHitCellFromCellIgnoringRange(sourceCell, targ.Cell, targ.Thing)) + { + goodDest = targ.Cell; + return true; + } + goodDest = IntVec3.Invalid; + return false; + } + + // Added targetThing to parameters so we can calculate its height + private bool CanHitCellFromCellIgnoringRange(IntVec3 sourceSq, IntVec3 targetLoc, Thing targetThing = null, bool includeCorners = false) + { + // Vanilla checks + if (this.verbProps.mustCastOnOpenGround && (!targetLoc.Standable(this.caster.Map) || this.caster.Map.thingGrid.CellContains(targetLoc, ThingCategory.Pawn))) + { + return false; + } + if (this.verbProps.requireLineOfSight) + { + // Calculate shot vector + Vector3 shotSource = ShotSource; + + Vector3 targetPos; + if (targetThing != null) + { + Vector3 targDrawPos = targetThing.DrawPos; + targetPos = new Vector3(targDrawPos.x, new CollisionVertical(targetThing).Max, targDrawPos.z); + } + else + { + targetPos = targetLoc.ToVector3Shifted(); + } + Ray shotLine = new Ray(shotSource, (targetPos - shotSource)); + + // Create validator to check for intersection with partial cover + var aimMode = CompFireModes?.CurrentAimMode; + Func validator = delegate (IntVec3 cell) + { + // Skip this check entirely if we're doing suppressive fire and cell is adjacent to target + if (aimMode == AimMode.SuppressFire) + return true; + + Thing cover = cell.GetFirstPawn(caster.Map); + if (cover == null) + { + cover = cell.GetCover(caster.Map); + } + if (cover != null && !cover.IsTree() && !cover.Position.AdjacentTo8Way(sourceSq)) + { + Bounds bounds = CE_Utility.GetBoundsFor(cover); + + // Check for intersect + if (bounds.IntersectRay(shotLine)) + { + if (Controller.settings.DebugDrawPartialLoSChecks) caster.Map.debugDrawer.FlashCell(cell, 0, bounds.size.y.ToString()); + return false; + } + else if (Controller.settings.DebugDrawPartialLoSChecks) + { + caster.Map.debugDrawer.FlashCell(cell, 0.7f, bounds.size.y.ToString()); + } + } + return true; + }; + // Add validator to parameters + if (!includeCorners) + { + if (!GenSight.LineOfSight(sourceSq, targetLoc, this.caster.Map, true, validator, 0, 0)) + { + return false; + } + } + else if (!GenSight.LineOfSightToEdges(sourceSq, targetLoc, this.caster.Map, true, validator)) + { + return false; + } + } + return true; + } + + #endregion + + #endregion + } +} diff --git a/Source/CombatRealism/CombatExtended/Verbs/Verb_MarkForArtilleryCE.cs b/Source/CombatExtended/CombatExtended/Verbs/Verb_MarkForArtilleryCE.cs similarity index 73% rename from Source/CombatRealism/CombatExtended/Verbs/Verb_MarkForArtilleryCE.cs rename to Source/CombatExtended/CombatExtended/Verbs/Verb_MarkForArtilleryCE.cs index 09375bccf7..a57fb67ee2 100644 --- a/Source/CombatRealism/CombatExtended/Verbs/Verb_MarkForArtilleryCE.cs +++ b/Source/CombatExtended/CombatExtended/Verbs/Verb_MarkForArtilleryCE.cs @@ -23,7 +23,7 @@ protected override bool TryCastShot() { ArtilleryMarker marker = ThingMaker.MakeThing(ThingDef.Named(ArtilleryMarker.MarkerDef)) as ArtilleryMarker; ShiftVecReport report = ShiftVecReportFor(currentTarget); - marker.aimEfficiency = report.aimEfficiency; + marker.sightsEfficiency = report.sightsEfficiency; marker.aimingAccuracy = report.aimingAccuracy; marker.lightingShift = report.lightingShift; marker.weatherShift = report.weatherShift; @@ -39,7 +39,18 @@ protected override bool TryCastShot() marker.AttachTo(this.currentTarget.Thing); } } + // Show we learned something + PlayerKnowledgeDatabase.KnowledgeDemonstrated(CE_ConceptDefOf.CE_Spotting, KnowledgeAmount.SmallInteraction); + return true; } + + public override void VerbTickCE() + { + if (CasterPawn != null && CasterPawn.IsColonistPlayerControlled) + { + LessonAutoActivator.TeachOpportunity(CE_ConceptDefOf.CE_Spotting, OpportunityType.GoodToKnow); + } + } } } diff --git a/Source/CombatExtended/CombatExtended/Verbs/Verb_MeleeAttackCE.cs b/Source/CombatExtended/CombatExtended/Verbs/Verb_MeleeAttackCE.cs new file mode 100644 index 0000000000..e0499821be --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Verbs/Verb_MeleeAttackCE.cs @@ -0,0 +1,528 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +using RimWorld; +using Verse; +using Verse.AI; +using Verse.Sound; + +namespace CombatExtended +{ + /* Copied from Verb_MeleeAttack + * + * Added dodge/parry mechanics, crits, height check. + * + * Unmodified methods should be kept up-to-date with vanilla between Alphas (at least as far as logic is concerned) so long as they don't interfere with our own. + * Please tag changes you're making from vanilla. + * + * -NIA + */ + public class Verb_MeleeAttackCE : Verb_MeleeAttack + { + + #region Constants + + private const int TargetCooldown = 50; + private const float DefaultHitChance = 0.6f; + private const float ShieldBlockChance = 0.75f; // If we have a shield equipped, this is the chance a parry will be a shield block + private const int KnockdownDuration = 120; // Animal knockdown lasts for this long + + // XP variables + private const float HitXP = 200; // Vanilla is 250 + private const float DodgeXP = 50; + private const float ParryXP = 50; + private const float CritXP = 100; + + /* Base stats + * + * These are the baseline stats we want for crit/dodge/parry for pawns of equal skill. These need to be the same as set in the base factors set in the + * stat defs. Ideally we would access them from the defs but the relevant values are all set to private and there is no real way to get at them that I + * can see. + * + * -NIA + */ + + private const float BaseCritChance = 0.1f; + private const float BaseDodgeChance = 0.1f; + private const float BaseParryChance = 0.2f; + + #endregion + + #region Properties + + DamageDef CritDamageDef + { + get + { + if (CasterPawn.def.race.Animal) + return verbProps.meleeDamageDef; + if (verbProps.meleeDamageDef.armorCategory == CE_DamageArmorCategoryDefOf.Blunt) + { + return DamageDefOf.Stun; + } + return DefDatabase.GetNamed(verbProps.meleeDamageDef.defName + "_Critical"); + } + } + + #endregion + + #region Methods + + /// + /// Performs the actual melee attack part. Awards XP, calculates and applies whether an attack connected and the outcome. + /// + /// True if the attack connected, false otherwise + protected override bool TryCastShot() + { + Pawn casterPawn = CasterPawn; + if (casterPawn.stances.FullBodyBusy) + { + return false; + } + Thing targetThing = currentTarget.Thing; + if (!CanHitTarget(targetThing)) + { + Log.Warning(string.Concat(new object[] + { + casterPawn, + " meleed ", + targetThing, + " from out of melee position." + })); + } + casterPawn.Drawer.rotator.Face(targetThing.DrawPos); + + // Award XP as per vanilla + bool targetImmobile = IsTargetImmobile(currentTarget); + if (!targetImmobile && casterPawn.skills != null) + { + casterPawn.skills.Learn(SkillDefOf.Melee, HitXP, false); + } + + // Hit calculations + bool result; + string moteText = ""; + SoundDef soundDef; + Pawn defender = targetThing as Pawn; + //var hitRoll = Rand.Value; + if (Rand.Chance(GetHitChance(targetThing))) + { + // Check for dodge + if (!targetImmobile && !surpriseAttack && Rand.Chance(defender.GetStatValue(StatDefOf.MeleeDodgeChance))) + { + // Attack is evaded + moteText = "TextMote_Dodge".Translate(); + result = false; + soundDef = SoundMiss(); + defender.skills?.Learn(SkillDefOf.Melee, DodgeXP, false); + } + else + { + // Attack connects, calculate resolution + //var resultRoll = Rand.Value; + var parryChance = GetParryChanceAgainst(casterPawn, defender); + if (!surpriseAttack && defender != null && CanDoParry(defender) && Rand.Chance(parryChance)) + { + // Attack is parried + Apparel shield = defender.apparel.WornApparel.FirstOrDefault(x => x is Apparel_Shield); + bool isShieldBlock = shield != null && Rand.Chance(ShieldBlockChance); + Thing parryThing = isShieldBlock ? shield + : defender.equipment?.Primary != null ? defender.equipment.Primary : defender; + + if (Rand.Chance(GetCritChanceAgainst(defender, casterPawn))) + { + // Do a riposte + DoParry(defender, parryThing, true); + moteText = "CE_TextMote_Riposted".Translate(); + defender.skills?.Learn(SkillDefOf.Melee, CritXP + ParryXP, false); + } + else + { + // Do a parry + DoParry(defender, parryThing); + moteText = "CE_TextMote_Parried".Translate(); + defender.skills?.Learn(SkillDefOf.Melee, ParryXP, false); + } + + result = false; + soundDef = SoundMiss(); // TODO Set hit sound to something more appropriate + } + else + { + // Attack connects + if (!surpriseAttack && Rand.Chance(GetCritChanceAgainst(casterPawn, defender))) + { + // Do a critical hit + ApplyMeleeDamageToTarget(currentTarget, true); + moteText = casterPawn.def.race.Animal ? "CE_TextMote_Knockdown".Translate() : "CE_TextMote_CriticalHit".Translate(); + casterPawn.skills?.Learn(SkillDefOf.Melee, CritXP, false); + } + else + { + // Do a regular hit as per vanilla + ApplyMeleeDamageToTarget(currentTarget); + } + result = true; + soundDef = targetThing.def.category == ThingCategory.Building ? SoundHitBuilding() : SoundHitPawn(); + } + } + } + else + { + // Attack missed + result = false; + soundDef = SoundMiss(); + } + if (!moteText.NullOrEmpty()) + MoteMaker.ThrowText(targetThing.PositionHeld.ToVector3Shifted(), casterPawn.Map, moteText); + soundDef.PlayOneShot(new TargetInfo(targetThing.PositionHeld, casterPawn.Map, false)); + casterPawn.Drawer.Notify_MeleeAttackOn(targetThing); + if (defender != null && !defender.Dead) + { + defender.stances.StaggerFor(95); + if (casterPawn.MentalStateDef != MentalStateDefOf.SocialFighting || defender.MentalStateDef != MentalStateDefOf.SocialFighting) + { + defender.mindState.meleeThreat = casterPawn; + defender.mindState.lastMeleeThreatHarmTick = Find.TickManager.TicksGame; + } + } + casterPawn.Drawer.rotator.FaceCell(targetThing.Position); + if (casterPawn.caller != null) + { + casterPawn.caller.Notify_DidMeleeAttack(); + } + return result; + } + + /// + /// Calculates primary DamageInfo from verb, as well as secondary DamageInfos to apply (i.e. surprise attack stun damage). + /// Also calculates the maximum body height an attack can target, so we don't get rabbits biting out a colonist's eye or something. + /// + /// The target damage is to be applied to + /// Collection with primary DamageInfo, followed by secondary types + private IEnumerable DamageInfosToApply(LocalTargetInfo target, bool isCrit = false) + { + float damAmount = (float)this.verbProps.AdjustedMeleeDamageAmount(this, base.CasterPawn, this.ownerEquipment); + var critDamDef = CritDamageDef; + DamageDef damDef = isCrit && critDamDef != DamageDefOf.Stun ? critDamDef : verbProps.meleeDamageDef; + BodyPartGroupDef bodyPartGroupDef = null; + HediffDef hediffDef = null; + if (base.CasterIsPawn) + { + if (damAmount >= 1f) + { + bodyPartGroupDef = this.verbProps.linkedBodyPartsGroup; + if (this.ownerHediffComp != null) + { + hediffDef = this.ownerHediffComp.Def; + } + } + else + { + damAmount = 1f; + damDef = DamageDefOf.Blunt; + } + } + ThingDef source; + if (this.ownerEquipment != null) + { + source = this.ownerEquipment.def; + } + else + { + source = base.CasterPawn.def; + } + Vector3 direction = (target.Thing.Position - base.CasterPawn.Position).ToVector3(); + Thing caster = this.caster; + BodyPartHeight bodyRegion = GetBodyPartHeightFor(target); // Add check for body height + DamageInfo mainDinfo = new DamageInfo(damDef, GenMath.RoundRandom(damAmount), -1f, caster, null, source); + mainDinfo.SetBodyRegion(bodyRegion, BodyPartDepth.Outside); + mainDinfo.SetWeaponBodyPartGroup(bodyPartGroupDef); + mainDinfo.SetWeaponHediff(hediffDef); + mainDinfo.SetAngle(direction); + yield return mainDinfo; + + // Apply secondary damage on surprise attack + if (this.surpriseAttack && this.verbProps.surpriseAttack != null && this.verbProps.surpriseAttack.extraMeleeDamages != null) + { + List extraDamages = this.verbProps.surpriseAttack.extraMeleeDamages; + for (int i = 0; i < extraDamages.Count; i++) + { + ExtraMeleeDamage extraDamage = extraDamages[i]; + int amount = GenMath.RoundRandom((float)extraDamage.amount * base.GetDamageFactorFor(base.CasterPawn)); + caster = this.caster; + DamageInfo extraDinfo = new DamageInfo(extraDamage.def, amount, -1f, caster, null, source); + extraDinfo.SetBodyRegion(bodyRegion, BodyPartDepth.Outside); + extraDinfo.SetWeaponBodyPartGroup(bodyPartGroupDef); + extraDinfo.SetWeaponHediff(hediffDef); + extraDinfo.SetAngle(direction); + yield return extraDinfo; + } + } + + // Apply critical damage + if (isCrit && critDamDef == DamageDefOf.Stun) + { + var critAmount = GenMath.RoundRandom(mainDinfo.Amount * 0.25f); + var critDinfo = new DamageInfo(critDamDef, critAmount, -1, caster, null, source); + critDinfo.SetBodyRegion(bodyRegion, BodyPartDepth.Outside); + critDinfo.SetWeaponBodyPartGroup(bodyPartGroupDef); + critDinfo.SetWeaponHediff(hediffDef); + critDinfo.SetAngle(direction); + yield return critDinfo; + } + } + + // unmodified + private float GetHitChance(LocalTargetInfo target) + { + if (this.surpriseAttack) + { + return 1f; + } + if (this.IsTargetImmobile(target)) + { + return 1f; + } + if (base.CasterPawn.skills != null) + { + return base.CasterPawn.GetStatValue(StatDefOf.MeleeHitChance, true); + } + return DefaultHitChance; + } + + /// + /// Checks whether a target can move. Immobile targets include anything that's not a pawn and pawns that are lying down/incapacitated. + /// Immobile targets don't award XP, nor do they benefit from dodge/parry and attacks against them always crit. + /// + /// + /// + private bool IsTargetImmobile(LocalTargetInfo target) + { + Thing thing = target.Thing; + Pawn pawn = thing as Pawn; + return thing.def.category != ThingCategory.Pawn || pawn.Downed || pawn.GetPosture() != PawnPosture.Standing || pawn.stances.stunner.Stunned; // Added check for stunned + } + + /// + /// Applies all DamageInfosToApply to the target. Increases damage on critical hits. + /// + /// Target to apply damage to + /// Whether we should apply critical damage + private void ApplyMeleeDamageToTarget(LocalTargetInfo target, bool isCrit = false) + { + foreach (DamageInfo current in DamageInfosToApply(target, isCrit)) + { + if (target.ThingDestroyed) + { + return; + } + target.Thing.TakeDamage(current); + } + // Apply animal knockdown + if (isCrit && CasterPawn.def.race.Animal) + { + var pawn = target.Thing as Pawn; + if (pawn != null) + { + //pawn.stances?.stunner.StunFor(KnockdownDuration); + pawn.stances?.SetStance(new Stance_Cooldown(KnockdownDuration, pawn, null)); + pawn.jobs?.StartJob(new Job(CE_JobDefOf.WaitKnockdown) { expiryInterval = KnockdownDuration }, JobCondition.InterruptForced, null, false, false); + } + } + } + + /// + /// Checks ParryTracker for whether the specified pawn can currently perform a parry. + /// + /// Pawn to check + /// True if pawn still has parries available or no parry tracker could be found, false otherwise + private bool CanDoParry(Pawn pawn) + { + if (pawn == null + || pawn.Dead + || !pawn.RaceProps.Humanlike + || pawn.story.WorkTagIsDisabled(WorkTags.Violent) + || !pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation) + || IsTargetImmobile(pawn)) + { + return false; + } + ParryTracker tracker = pawn.Map.GetComponent(); + if (tracker == null) + { + Log.Error("CE failed to find ParryTracker to check pawn " + pawn.ToString()); + return true; + } + return tracker.CheckCanParry(pawn); + } + + /// + /// Performs parry calculations. Deflects damage from defender-pawn onto parryThing, applying armor reduction in the process. + /// On critical parry does a riposte against this verb's CasterPawn. + /// + /// Pawn doing the parrying + /// Thing used to parry the blow (weapon/shield) + /// Whether to do a riposte + private void DoParry(Pawn defender, Thing parryThing, bool isRiposte = false) + { + if (parryThing != null) + { + foreach(var dinfo in DamageInfosToApply(defender)) + { + ArmorUtilityCE.ApplyParryDamage(dinfo, parryThing); + } + } + if (isRiposte) + { + SoundDef sound = null; + if (parryThing is Apparel_Shield) + { + // Shield bash + DamageInfo dinfo = new DamageInfo(DamageDefOf.Blunt, 6, -1, defender, null, parryThing.def); + caster.TakeDamage(dinfo); + if (!parryThing.Stuff.stuffProps.soundMeleeHitBlunt.NullOrUndefined()) + sound = parryThing.Stuff.stuffProps.soundMeleeHitBlunt; + } + else + { + Verb_MeleeAttackCE verb = defender.meleeVerbs.TryGetMeleeVerb() as Verb_MeleeAttackCE; + if (verb == null) + { + Log.Error("CE failed to get attack verb for riposte from Pawn " + defender.ToString()); + } + else + { + verb.ApplyMeleeDamageToTarget(caster); + sound = verb.SoundHitPawn(); + } + } + sound?.PlayOneShot(new TargetInfo(caster.Position, caster.Map)); + } + // Register with parry tracker + ParryTracker tracker = defender.Map.GetComponent(); + if (tracker == null) + { + Log.Error("CE failed to find ParryTracker to register pawn " + defender.ToString()); + } + else + { + tracker.RegisterParryFor(defender, verbProps.AdjustedCooldownTicks(ownerEquipment)); + } + } + + /// + /// Selects a random BodyPartHeight out of the ones our CasterPawn can hit, depending on our body size vs the target's. So a rabbit can hit top height of another rabbit, but not of a human. + /// + /// + /// + private BodyPartHeight GetBodyPartHeightFor(LocalTargetInfo target) + { + Pawn pawn = target.Thing as Pawn; + if (pawn == null || CasterPawn == null) return BodyPartHeight.Undefined; + var casterReach = new CollisionVertical(CasterPawn).Max * 1.2f; + var targetHeight = new CollisionVertical(pawn); + BodyPartHeight maxHeight = targetHeight.GetRandWeightedBodyHeightBelow(casterReach); + BodyPartHeight height = (BodyPartHeight)Rand.RangeInclusive(1, (int)maxHeight); + return height; + } + + // unmodified + private SoundDef SoundHitPawn() + { + if (this.ownerEquipment != null && this.ownerEquipment.Stuff != null) + { + if (this.verbProps.meleeDamageDef.armorCategory == DamageArmorCategoryDefOf.Sharp) + { + if (!this.ownerEquipment.Stuff.stuffProps.soundMeleeHitSharp.NullOrUndefined()) + { + return this.ownerEquipment.Stuff.stuffProps.soundMeleeHitSharp; + } + } + else if (!this.ownerEquipment.Stuff.stuffProps.soundMeleeHitBlunt.NullOrUndefined()) + { + return this.ownerEquipment.Stuff.stuffProps.soundMeleeHitBlunt; + } + } + if (base.CasterPawn != null && !base.CasterPawn.def.race.soundMeleeHitPawn.NullOrUndefined()) + { + return base.CasterPawn.def.race.soundMeleeHitPawn; + } + return SoundDefOf.Pawn_Melee_Punch_HitPawn; + } + + // unmodified + private SoundDef SoundHitBuilding() + { + if (this.ownerEquipment != null && this.ownerEquipment.Stuff != null) + { + if (this.verbProps.meleeDamageDef.armorCategory == DamageArmorCategoryDefOf.Sharp) + { + if (!this.ownerEquipment.Stuff.stuffProps.soundMeleeHitSharp.NullOrUndefined()) + { + return this.ownerEquipment.Stuff.stuffProps.soundMeleeHitSharp; + } + } + else if (!this.ownerEquipment.Stuff.stuffProps.soundMeleeHitBlunt.NullOrUndefined()) + { + return this.ownerEquipment.Stuff.stuffProps.soundMeleeHitBlunt; + } + } + if (base.CasterPawn != null && !base.CasterPawn.def.race.soundMeleeHitBuilding.NullOrUndefined()) + { + return base.CasterPawn.def.race.soundMeleeHitBuilding; + } + return SoundDefOf.Pawn_Melee_Punch_HitBuilding; + } + + // unmodified + private SoundDef SoundMiss() + { + if (base.CasterPawn != null && !base.CasterPawn.def.race.soundMeleeMiss.NullOrUndefined()) + { + return base.CasterPawn.def.race.soundMeleeMiss; + } + return SoundDefOf.Pawn_Melee_Punch_Miss; + } + + #region Stat calculations + + private static float GetCritChanceAgainst(Pawn attacker, Pawn defender) + { + if (attacker == null || defender == null) + return 0; + var stat = CE_StatDefOf.MeleeCritChance; + var offSkill = attacker.GetStatValue(stat); + var defSkill = defender.GetStatValue(stat); + var chance = Mathf.Clamp01(BaseCritChance + offSkill - defSkill); + return chance; + } + + private static float GetParryChanceAgainst(Pawn attacker, Pawn defender) + { + if (attacker == null || defender == null) + return 0; + var stat = CE_StatDefOf.MeleeParryChance; + var offSkill = attacker.GetStatValue(stat); + var defSkill = defender.GetStatValue(stat); + var chance = Mathf.Clamp01(BaseParryChance + defSkill - offSkill); + return chance; + } + + private static float GetDodgeChanceAgainst(Pawn attacker, Pawn defender) + { + if (attacker == null || defender == null) + return 0; + var stat = StatDefOf.MeleeDodgeChance; + var offSkill = attacker.GetStatValue(stat); + var defSkill = defender.GetStatValue(stat); + var chance = Mathf.Clamp01(BaseDodgeChance + defSkill - offSkill); + return chance; + } + + #endregion + + #endregion + } +} diff --git a/Source/CombatRealism/CombatExtended/Verbs/Verb_ShootCE.cs b/Source/CombatExtended/CombatExtended/Verbs/Verb_ShootCE.cs similarity index 60% rename from Source/CombatRealism/CombatExtended/Verbs/Verb_ShootCE.cs rename to Source/CombatExtended/CombatExtended/Verbs/Verb_ShootCE.cs index f2c941a43a..5d2211d9f5 100644 --- a/Source/CombatRealism/CombatExtended/Verbs/Verb_ShootCE.cs +++ b/Source/CombatExtended/CombatExtended/Verbs/Verb_ShootCE.cs @@ -4,104 +4,96 @@ using UnityEngine; using Verse; using Verse.AI; +using Verse.Sound; namespace CombatExtended { public class Verb_ShootCE : Verb_LaunchProjectileCE { + #region Constants + + // How much time to spend on aiming + private const int aimTicksMin = 30; + private const int aimTicksMax = 240; + + // XP amounts As of A17 non-hostile pawns/objects are (per shot) worth 6xp and hostile pawns are worth 240 xp. + private const float objectXP = 0.1f; + private const float pawnXP = 0.75f; + private const float hostileXP = 3.6f; + + // Suppression aim penalty + private const float SuppressionSwayFactor = 1.5f; + + #endregion + + #region Fields + + private bool isAiming = false; + private int xpTicks = 0; // Tracker to see how much xp should be awarded for time spent aiming + bursting + const float BaseXPMultiplyer = 0.5f; // the amount warmup time is multiplied by for the quickshot fire mode (initial XP) + + #endregion + + #region Properties + protected override int ShotsPerBurst { get { - if (this.compFireModes != null) + if (this.CompFireModes != null) { - if (this.compFireModes.currentFireMode == FireMode.SingleFire) + if (this.CompFireModes.CurrentFireMode == FireMode.SingleFire) { return 1; } - if ((this.compFireModes.currentFireMode == FireMode.BurstFire || (useDefaultModes && this.compFireModes.Props.aiUseBurstMode)) - && this.compFireModes.Props.aimedBurstShotCount > 0) + if (this.CompFireModes.CurrentFireMode == FireMode.BurstFire + && this.CompFireModes.Props.aimedBurstShotCount > 0) { - return this.compFireModes.Props.aimedBurstShotCount; + return this.CompFireModes.Props.aimedBurstShotCount; } } - return this.verbPropsCE.burstShotCount; - } - } - - private CompFireModes compFireModesInt = null; - private CompFireModes compFireModes - { - get - { - if (this.compFireModesInt == null && this.ownerEquipment != null) - { - this.compFireModesInt = this.ownerEquipment.TryGetComp(); - } - return this.compFireModesInt; + return this.VerbPropsCE.burstShotCount; } } - private bool shouldAim + private bool ShouldAim { get { - if (compFireModes != null) + if (CompFireModes != null) { if (this.CasterIsPawn) { // Check for hunting job - if (CasterPawn.jobs != null && CasterPawn.jobs.curJob != null && CasterPawn.jobs.curJob.def == JobDefOf.Hunt) + if (CasterPawn.CurJob != null && CasterPawn.CurJob.def == JobDefOf.Hunt) return true; // Check for suppression - CompSuppressable comp = this.caster.TryGetComp(); - if (comp != null) - { - if (comp.isSuppressed) - { - return false; - } - } + if (IsSuppressed) return false; } - return this.compFireModes.currentAimMode == AimMode.AimedShot || (useDefaultModes && this.compFireModes.Props.aiUseAimMode); + return this.CompFireModes.CurrentAimMode == AimMode.AimedShot; } return false; } } - private bool isAiming = false; - private int xpTicks = 0; // Tracker to see how much xp should be awarded for time spent aiming + bursting - // How much time to spend on aiming - private const int aimTicksMin = 30; - private const int aimTicksMax = 240; - - // XP amounts - private const float objectXP = 0.1f; - private const float pawnXP = 0.75f; - private const float hostileXP = 3.6f; - - protected override float swayAmplitude + protected override float SwayAmplitude { get { - float sway = base.swayAmplitude; - if (this.shouldAim) - { - sway *= Mathf.Max(0, 1 - aimingAccuracy); - } + float sway = base.SwayAmplitude; + if (ShouldAim) sway = (sway / Mathf.Max(1, ownerEquipment.GetStatValue(CE_StatDefOf.SightsEfficiency))) * Mathf.Max(0, 1 - AimingAccuracy); + else if (IsSuppressed) sway *= SuppressionSwayFactor; return sway; } } - // Whether this gun should use default AI firing modes - private bool useDefaultModes - { - get - { - return !(caster.Faction == Faction.OfPlayer); - } - } + // Whether our shooter is currently under suppressive fire + private bool IsSuppressed => CasterPawn?.TryGetComp()?.isSuppressed ?? false; + + #endregion + + #region Methods /// /// Handles activating aim mode at the start of the burst @@ -109,9 +101,9 @@ private bool useDefaultModes public override void WarmupComplete() { if (xpTicks <= 0) - xpTicks = Mathf.CeilToInt(verbProps.warmupTime * 0.5f); + xpTicks = Mathf.CeilToInt(verbProps.warmupTime * BaseXPMultiplyer); - if (this.shouldAim && !this.isAiming) + if (this.ShouldAim && !this.isAiming) { float targetDist = (this.currentTarget.Cell - this.caster.Position).LengthHorizontal; int aimTicks = (int)Mathf.Lerp(aimTicksMin, aimTicksMax, (targetDist / 100)); @@ -143,7 +135,7 @@ public override void VerbTickCE() if (this.isAiming) { this.xpTicks++; - if (!this.shouldAim) + if (!this.ShouldAim) { this.WarmupComplete(); } @@ -175,7 +167,7 @@ public override void VerbTickCE() xpPerTick = pawnXP; } } - this.ShooterPawn.skills.Learn(SkillDefOf.Shooting, xpPerTick * xpTicks); + this.ShooterPawn.skills.Learn(SkillDefOf.Shooting, Mathf.Max(xpPerTick * xpTicks, 1)); } this.xpTicks = 0; } @@ -187,47 +179,72 @@ public override void VerbTickCE() public override void Notify_EquipmentLost() { base.Notify_EquipmentLost(); - if (this.compFireModes != null) + if (this.CompFireModes != null) { - this.compFireModes.ResetModes(); + this.CompFireModes.ResetModes(); } caster = null; } /// - /// Checks to see if fire mode is set to hold fire before doing the base check + /// Checks to see if enemy is blind before shooting /// public override bool CanHitTargetFrom(IntVec3 root, LocalTargetInfo targ) { if (CasterIsPawn && !CasterPawn.health.capacities.CapableOf(PawnCapacityDefOf.Sight)) return false; - if (this.compFireModes != null && this.compFireModes.currentAimMode == AimMode.HoldFire - && (!CasterIsPawn || CasterPawn.CurJob == null || CasterPawn.CurJob.def != JobDefOf.Hunt)) - return false; return base.CanHitTargetFrom(root, targ); } - + protected override bool TryCastShot() { //Reduce ammunition - if (compAmmo != null) + if (CompAmmo != null) { - if (!compAmmo.TryReduceAmmoCount()) + if (!CompAmmo.TryReduceAmmoCount()) { - if (compAmmo.hasMagazine) - compAmmo.TryStartReload(); + if (CompAmmo.hasMagazine) + CompAmmo.TryStartReload(); return false; } } if (base.TryCastShot()) { //Drop casings - if (verbPropsCE.ejectsCasings && projectilePropsCE.dropsCasings) + if (VerbPropsCE.ejectsCasings && projectilePropsCE.dropsCasings) + { + CE_Utility.ThrowEmptyCasing(caster.DrawPos, caster.Map, ThingDef.Named(projectilePropsCE.casingMoteDefname)); + } + // This needs to here for weapons without magazine to ensure their last shot plays sounds + if (CompAmmo != null && !CompAmmo.hasMagazine && CompAmmo.useAmmo) { - CE_Utility.ThrowEmptyCasing(this.caster.DrawPos, caster.Map, ThingDef.Named(this.projectilePropsCE.casingMoteDefname)); + if (!CompAmmo.Notify_ShotFired()) + { + if (VerbPropsCE.muzzleFlashScale > 0.01f) + { + MoteMaker.MakeStaticMote(caster.Position, caster.Map, ThingDefOf.Mote_ShotFlash, VerbPropsCE.muzzleFlashScale); + } + if (VerbPropsCE.soundCast != null) + { + VerbPropsCE.soundCast.PlayOneShot(new TargetInfo(caster.Position, caster.Map)); + } + if (VerbPropsCE.soundCastTail != null) + { + VerbPropsCE.soundCastTail.PlayOneShotOnCamera(); + } + if (CasterIsPawn) + { + if (CasterPawn.thinker != null) + { + CasterPawn.mindState.lastEngageTargetTick = Find.TickManager.TicksGame; + } + } + } + return CompAmmo.Notify_PostShotFired(); } return true; } return false; } + #endregion } } \ No newline at end of file diff --git a/Source/CombatRealism/CombatExtended/Verbs/Verb_ShootCEOneUse.cs b/Source/CombatExtended/CombatExtended/Verbs/Verb_ShootCEOneUse.cs similarity index 93% rename from Source/CombatRealism/CombatExtended/Verbs/Verb_ShootCEOneUse.cs rename to Source/CombatExtended/CombatExtended/Verbs/Verb_ShootCEOneUse.cs index a699cc207d..616af478d1 100644 --- a/Source/CombatRealism/CombatExtended/Verbs/Verb_ShootCEOneUse.cs +++ b/Source/CombatExtended/CombatExtended/Verbs/Verb_ShootCEOneUse.cs @@ -16,7 +16,7 @@ protected override bool TryCastShot() } return true; } - if (compAmmo != null && compAmmo.hasMagazine && compAmmo.curMagCount <= 0) + if (CompAmmo != null && CompAmmo.hasMagazine && CompAmmo.curMagCount <= 0) { this.SelfConsume(); } diff --git a/Source/CombatRealism/CombatExtended/Verbs/Verb_ShootMortarCE.cs b/Source/CombatExtended/CombatExtended/Verbs/Verb_ShootMortarCE.cs similarity index 79% rename from Source/CombatRealism/CombatExtended/Verbs/Verb_ShootMortarCE.cs rename to Source/CombatExtended/CombatExtended/Verbs/Verb_ShootMortarCE.cs index 8dbfd3f1fc..b4517f7583 100644 --- a/Source/CombatRealism/CombatExtended/Verbs/Verb_ShootMortarCE.cs +++ b/Source/CombatExtended/CombatExtended/Verbs/Verb_ShootMortarCE.cs @@ -24,22 +24,22 @@ public override ShiftVecReport ShiftVecReportFor(LocalTargetInfo target) { marker = (ArtilleryMarker)this.currentTarget.Thing.GetAttachment(ThingDef.Named(ArtilleryMarker.MarkerDef)); } - else + else if (currentTarget.Cell.InBounds(caster.Map)) { marker = (ArtilleryMarker)this.currentTarget.Cell.GetFirstThing(caster.Map, ThingDef.Named(ArtilleryMarker.MarkerDef)); } if (marker != null) { report.aimingAccuracy = marker.aimingAccuracy; - report.aimEfficiency = marker.aimEfficiency; + report.sightsEfficiency = marker.sightsEfficiency; report.weatherShift = marker.weatherShift; report.lightingShift = marker.lightingShift; - + PlayerKnowledgeDatabase.KnowledgeDemonstrated(CE_ConceptDefOf.CE_Spotting, KnowledgeAmount.SpecificInteraction); } // If we don't have a marker check for indirect fire and apply penalty - else if (report.shotDist > 107 || !GenSight.LineOfSight(this.caster.Position, report.target.Cell, caster.Map, true)) + else if (report.shotDist > 75 || !GenSight.LineOfSight(this.caster.Position, report.target.Cell, caster.Map, true)) { - report.indirectFireShift = this.verbPropsCE.indirectFirePenalty * report.shotDist; + report.indirectFireShift = this.VerbPropsCE.indirectFirePenalty * report.shotDist; report.weatherShift = 0f; report.lightingShift = 0f; } @@ -49,10 +49,10 @@ public override ShiftVecReport ShiftVecReportFor(LocalTargetInfo target) private float GetMissRadiusForDist(float targDist) { float maxRange = this.verbProps.range; - if (this.compCharges != null) + if (this.CompCharges != null) { Vector2 bracket; - if (this.compCharges.GetChargeBracket(targDist, out bracket)) + if (this.CompCharges.GetChargeBracket(targDist, out bracket)) { maxRange = bracket.y; } diff --git a/Source/CombatExtended/CombatExtended/WorkGivers/WorkGiver_HunterHuntCE.cs b/Source/CombatExtended/CombatExtended/WorkGivers/WorkGiver_HunterHuntCE.cs new file mode 100644 index 0000000000..00fa1a7212 --- /dev/null +++ b/Source/CombatExtended/CombatExtended/WorkGivers/WorkGiver_HunterHuntCE.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using UnityEngine; + +namespace CombatExtended +{ + public class WorkGiver_HunterHuntCE : WorkGiver_HunterHunt + { + public override bool ShouldSkip(Pawn pawn) + { + return base.ShouldSkip(pawn) || HasMeleeShieldAndTwoHandedWeapon(pawn); + } + + public static bool HasMeleeShieldAndTwoHandedWeapon(Pawn p) + { + if(p.equipment.Primary != null && !(p.equipment.Primary.def.weaponTags?.Contains(Apparel_Shield.OneHandedTag) ?? false)) + { + List wornApparel = p.apparel.WornApparel; + foreach (Apparel apparel in wornApparel) + { + if (apparel is Apparel_Shield) return true; + } + } + return false; + } + } +} diff --git a/Source/CombatExtended/Harmony/Harmony-DefGenerator.cs b/Source/CombatExtended/Harmony/Harmony-DefGenerator.cs new file mode 100644 index 0000000000..93f272825b --- /dev/null +++ b/Source/CombatExtended/Harmony/Harmony-DefGenerator.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using UnityEngine; +using Harmony; + +namespace CombatExtended.Harmony +{ + [HarmonyPatch(typeof(DefGenerator), "GenerateImpliedDefs_PreResolve")] + static class Harmony_DefGenerator + { + public static void Postfix() + { + var enumerable = CritDefGenerator.ImpliedCritDefs().ToArray(); + foreach (DamageDef current in enumerable) + { + current.PostLoad(); + DefDatabase.Add(current); + } + } + } +} diff --git a/Source/CombatExtended/Harmony/Harmony-FloatMenuMakerMap.cs b/Source/CombatExtended/Harmony/Harmony-FloatMenuMakerMap.cs new file mode 100644 index 0000000000..e1d9d7e2ff --- /dev/null +++ b/Source/CombatExtended/Harmony/Harmony-FloatMenuMakerMap.cs @@ -0,0 +1,385 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Reflection.Emit; +using Harmony; +using Verse; +using RimWorld; +using UnityEngine; +using Verse.AI; + +namespace CombatExtended.Harmony +{ + /* + * The additional item to be inserted adds learning information for CE when a weapon is selected for equipping. + * The target is actually a nested (compiler generated) class' method. + * Used dynamic targetting in case the target assemly changes the name of the target class will most certainly change or even shift position (removing the ability to count). + * Looking for a signature (field by name/type) that identifies the desired class without looking at it's code. + */ + [HarmonyPatch] + static class FloatMenuMakerMap_PatchKnowledge + { + static readonly string logPrefix = Assembly.GetExecutingAssembly().GetName().Name + " :: " + typeof(FloatMenuMakerMap_PatchKnowledge).Name + " :: "; + + static MethodBase TargetMethod() + { + List classes = typeof(FloatMenuMakerMap).GetNestedTypes(AccessTools.all).ToList(); + MethodBase target = null; //classes.First().GetMethods().First(); // a bailout so that harmony doesn't choke. + foreach (Type clas in classes.Where(c => c.Name.Contains("AddHumanlikeOrders"))) + { + FieldInfo info = AccessTools.Field(clas, "equipment"); + if (info != null && info.FieldType == typeof(ThingWithComps)) + { + target = clas.GetMethods(AccessTools.all).FirstOrDefault(m => m.Name.Contains("m__")); + break; + } + } + return target; + } + + // __instance required, don't need to interface with any properties/fields. + // __result isn't apt, target return is void. + static void Postfix() + { + LessonAutoActivator.TeachOpportunity(CE_ConceptDefOf.CE_AimingSystem, OpportunityType.GoodToKnow); + } + + } + + [HarmonyPatch(typeof(FloatMenuMakerMap))] + [HarmonyPatch("AddHumanlikeOrders")] + [HarmonyPatch(new Type[] { typeof(Vector3), typeof(Pawn), typeof(List) })] + static class FloatMenuMakerMap_Modify_AddHumanlikeOrders + { + static readonly string logPrefix = Assembly.GetExecutingAssembly().GetName().Name + " :: " + typeof(FloatMenuMakerMap_Modify_AddHumanlikeOrders).Name + " :: "; + + /* + * Opted for a postfix as the original Detour had the code inserted generally after other code had run and because we want the target's code + * to always run unmodified. + * There are two goals for this postfix, to add menu items for stabalizing a target and to add inventory pickup functions for pawns. + * -Both when right clicking on something with a pawn selected. + */ + + // __instance isn't apt, target is static. + // __result isn't apt, target return is void. + [HarmonyPostfix] + static void AddMenuItems(Vector3 clickPos, Pawn pawn, List opts) + { + // Stabilize + if (pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation)) + { + foreach (LocalTargetInfo curTarget in GenUI.TargetsAt(clickPos, TargetingParameters.ForRescue(pawn), true)) // !! This needs to be patched into A17 + { + Pawn patient = (Pawn)curTarget.Thing; + if (patient.Downed + //&& pawn.CanReserveAndReach(patient, PathEndMode.InteractionCell, Danger.Deadly) + && pawn.CanReach(patient, PathEndMode.InteractionCell, Danger.Deadly) + && patient.health.hediffSet.GetHediffsTendable().Any(h => h.CanBeStabilizied())) + { + if (pawn.story.WorkTypeIsDisabled(WorkTypeDefOf.Doctor)) + { + opts.Add(new FloatMenuOption("CE_CannotStabilize".Translate() + ": " + "IncapableOfCapacity".Translate(WorkTypeDefOf.Doctor.gerundLabel), null, MenuOptionPriority.Default)); + } + else + { + string label = "CE_Stabilize".Translate(patient.LabelCap); + Action action = delegate + { + if (pawn.inventory == null || pawn.inventory.innerContainer == null || !pawn.inventory.innerContainer.Any(t => t.def.IsMedicine)) + { + Messages.Message("CE_CannotStabilize".Translate() + ": " + "CE_NoMedicine".Translate(), patient, MessageSound.RejectInput); + return; + } + // Drop medicine from inventory + Medicine medicine = (Medicine)pawn.inventory.innerContainer.OrderByDescending(t => t.GetStatValue(StatDefOf.MedicalPotency)).FirstOrDefault(); + Thing medThing; + if (medicine != null && pawn.inventory.innerContainer.TryDrop(medicine, pawn.Position, pawn.Map, ThingPlaceMode.Direct, 1, out medThing)) + { + Job job = new Job(CE_JobDefOf.Stabilize, patient, medThing); + job.count = 1; + pawn.jobs.TryTakeOrderedJob(job); + PlayerKnowledgeDatabase.KnowledgeDemonstrated(CE_ConceptDefOf.CE_Stabilizing, KnowledgeAmount.Total); + } + }; + opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(label, action, MenuOptionPriority.Default, null, patient), pawn, patient, "ReservedBy")); + } + } + } + } + + // Item pickup. + IntVec3 c = IntVec3.FromVector3(clickPos); + CompInventory compInventory = pawn.TryGetComp(); + if (compInventory != null) + { + List thingList = c.GetThingList(pawn.Map); + if (!thingList.NullOrEmpty()) + { + Thing item = thingList.FirstOrDefault(thing => thing.def.alwaysHaulable && !(thing is Corpse)); + if (item != null) + { + FloatMenuOption pickUpOption; + int count = 0; + if (!pawn.CanReach(item, PathEndMode.Touch, Danger.Deadly)) + { + pickUpOption = new FloatMenuOption("CE_CannotPickUp".Translate() + " " + item.LabelShort + " (" + "NoPath".Translate() + ")", null); + } + /* else if (!pawn.CanReserve(item)) + { + pickUpOption = new FloatMenuOption("CE_CannotPickUp".Translate() + " " + item.LabelShort + " (" + "ReservedBy".Translate(new object[] { pawn.Map.reservationManager.FirstReserverOf(item, pawn.Faction).LabelShort }), null); + } */ + else if (!compInventory.CanFitInInventory(item, out count)) + { + pickUpOption = new FloatMenuOption("CE_CannotPickUp".Translate() + " " + item.LabelShort + " (" + "CE_InventoryFull".Translate() + ")", null); + } + else + { + // Pick up one + pickUpOption = FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption("CE_PickUp".Translate() + " " + item.LabelShort, + new Action(delegate + { + item.SetForbidden(false, false); + Job job = new Job(JobDefOf.TakeInventory, item); + job.count = 1; + job.playerForced = true; + pawn.Notify_HoldTrackerJob(job); + pawn.jobs.TryTakeOrderedJob(job); + PlayerKnowledgeDatabase.KnowledgeDemonstrated(CE_ConceptDefOf.CE_InventoryWeightBulk, KnowledgeAmount.SpecificInteraction); + })), pawn, item, "ReservedBy"); + } + opts.Add(pickUpOption); + if (count > 1 && item.stackCount > 1) + { + // Pick up half + int countHalf = item.def.stackLimit / 2; + if (count > 3 && count > countHalf) + { + FloatMenuOption pickUpHalfStackOption = FloatMenuUtility.DecoratePrioritizedTask( new FloatMenuOption("CE_PickUpHalf".Translate() + " " + item.LabelShort + " x" + countHalf.ToString(), + new Action(delegate + { + item.SetForbidden(false, false); + Job job = new Job(JobDefOf.TakeInventory, item); + job.count = countHalf; + job.playerForced = true; + pawn.Notify_HoldTrackerJob(job); + pawn.jobs.TryTakeOrderedJob(job); + PlayerKnowledgeDatabase.KnowledgeDemonstrated(CE_ConceptDefOf.CE_InventoryWeightBulk, KnowledgeAmount.SpecificInteraction); + })), pawn, item, "ReservedBy"); + opts.Add(pickUpHalfStackOption); + } + + // Pick up all + FloatMenuOption pickUpStackOption = FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption("CE_PickUp".Translate() + " " + item.LabelShort + " x" + count.ToString(), + new Action(delegate + { + item.SetForbidden(false, false); + Job job = new Job(JobDefOf.TakeInventory, item); + job.count = count; + job.playerForced = true; + pawn.Notify_HoldTrackerJob(job); + pawn.jobs.TryTakeOrderedJob(job); + PlayerKnowledgeDatabase.KnowledgeDemonstrated(CE_ConceptDefOf.CE_InventoryWeightBulk, KnowledgeAmount.SpecificInteraction); + })), pawn, item, "ReservedBy"); + opts.Add(pickUpStackOption); + } + } + } + } + } + + + /* Dev Notes (Don't need to read this, a short explanation is just before the method below): + * The IL of the region I'm interested in (As of RimWorld 0.17.6351.26908, generated via Harmony debug mode): + * + * L_0b20: br Label #71 //end of previous logic block ("CannotWearBecauseOfMissingBodyParts") + * // want to insert the new logic here... + * L_0b25: Label #70 //Make sure this label is on our new logic block and not right here. + * L_0b25: ldstr "ForceWear" + * L_0b2a: ldc.i4.1 + * L_0b2b: newarr System.Object + * L_0b30: dup + * L_0b31: ldc.i4.0 + * L_0b32: ldloc.s 42 (RimWorld.FloatMenuMakerMap+c__AnonStorey43C) + * L_0b34: ldfld RimWorld.Apparel apparel // need to remember the instruction before this to load the apparel as an arg to caller. + * L_0b39: callvirt System.String get_LabelShort() + * L_0b3e: stelem.ref + * L_0b3f: call System.String Translate(System.String, System.Object[]) + * L_0b44: ldloc.s 42 (RimWorld.FloatMenuMakerMap+c__AnonStorey43C) + * L_0b46: ldftn Void <>m__63B() + * L_0b4c: newobj Void .ctor(Object, IntPtr) + * L_0b51: ldc.i4.5 + * L_0b52: ldnull + * L_0b53: ldnull + * L_0b54: ldc.r4 0 + * L_0b59: ldnull + * L_0b5a: ldnull + * L_0b5b: newobj Void .ctor(String, Action, MenuOptionPriority, Action, Thing, Single, Func`2, WorldObject) // creates the force wear menu item. + * L_0b60: ldloc.s 34 (RimWorld.FloatMenuMakerMap+c__AnonStorey436) + * L_0b62: ldfld Verse.Pawn pawn + * L_0b67: ldloc.s 42 (RimWorld.FloatMenuMakerMap+c__AnonStorey43C) + * L_0b69: ldfld RimWorld.Apparel apparel + * L_0b6e: call LocalTargetInfo op_Implicit(Verse.Thing) + * L_0b73: ldstr "ReservedBy" + * L_0b78: call Verse.FloatMenuOption DecoratePrioritizedTask(Verse.FloatMenuOption, Verse.Pawn, LocalTargetInfo, System.String) + * L_0b7d: stloc.s 21 (Verse.FloatMenuOption) + * L_0b7f: Label #69 + * L_0b7f: Label #71 + * L_0b7f: ldarg.2 + * L_0b80: ldloc.s 21 (Verse.FloatMenuOption) // need to remember this instruction for re-use in call. + * L_0b82: callvirt Void Add(Verse.FloatMenuOption) //adds the menu item to the list (opts). + * L_0b87: Label #66 //This is the label we want to jump to in our new logic. + * L_0b87: Label #67 + * L_0b87: ldloc.s 34 (RimWorld.FloatMenuMakerMap+c__AnonStorey436) + * L_0b89: ldfld Verse.Pawn pawn + * L_0b8e: callvirt Verse.Map get_Map() + * L_0b93: callvirt Boolean get_IsPlayerHome() + * + * A couple of routes, opted to allow the called new method to modify the list directly but could have altered the + * IL structure to store the returned object (or null) to the local variable, branch if not null to the list.add code. + * The path I went with should be easier to maintain. + * + * New method call signature: (Pawn, Apparel, List. (mem1) + * -Start keeping a previous instruction cache. + * -Locate ldfld RimWorld.Apparel apparel + * --When found, store the previous instruction unaltered for re-use later. (mem2) + * -Locate callvirt Void Add(Verse.FloatMenuOption) + * -The next instruction found is expected to have a label. + * --If it has a label, store the label as an object for re-use later. (mem3) + * --If it DOES NOT have a label, dump the unaltered instructions as the patch failed. + * *Patch phase: + * -Locate ldstr "ForceWear" + * -Insert (before) + * --load arg1 onto the stack (Pawn), ensure that the label (mem1) is on this instruction. + * --load the remembered class in mem1 + * --load the field RimWorld.Apparel apparel, expected that this replaces the previous item on the stack (so only 2 things so far). + * --load arg2 onto the stack (List Modify_ForceWear(IEnumerable instructions, ILGenerator generator) + { + int searchPhase = 0; + bool patched = false; + string targetString = "ForceWear"; + CodeInstruction previous = null; + + List