diff --git a/code/__defines/objects.dm b/code/__defines/objects.dm
index 3d2891a3c5..d6530fecff 100644
--- a/code/__defines/objects.dm
+++ b/code/__defines/objects.dm
@@ -40,4 +40,12 @@
#define CATALOGUER_REWARD_SUPERHARD 2560 // Very difficult and dangerous, such as scanning the Advanced Dark Gygax.
// 5 10 20 40 80 160
-// 10 40 160 640 2560
\ No newline at end of file
+// 10 40 160 640 2560
+
+// Defines for Exosuit components.
+
+#define MECH_HULL "Hull"
+#define MECH_ACTUATOR "Actuator"
+#define MECH_ARMOR "Plating"
+#define MECH_GAS "Life Support"
+#define MECH_ELECTRIC "Firmware"
diff --git a/code/datums/autolathe/arms.dm b/code/datums/autolathe/arms.dm
index e170d8c885..53a2f14fac 100644
--- a/code/datums/autolathe/arms.dm
+++ b/code/datums/autolathe/arms.dm
@@ -33,6 +33,12 @@
path =/obj/item/ammo_casing/a12g/stunshell
hidden = 1
+/datum/category_item/autolathe/arms/flechetteshell
+ name = "ammunition (flechette cartridge, shotgun)"
+ path =/obj/item/ammo_casing/a12g/flechette
+ hidden = 1
+ man_rating = 2
+
//////////////////
/*Ammo magazines*/
//////////////////
@@ -64,6 +70,18 @@
name = "pistol magazine (.45 flash)"
path =/obj/item/ammo_magazine/m45/flash
+/datum/category_item/autolathe/arms/pistol_45ap
+ name = "pistol magazine (.45 armor piercing)"
+ path =/obj/item/ammo_magazine/m45/ap
+ hidden = 1
+ resources = list(DEFAULT_WALL_MATERIAL = 500, MAT_PLASTEEL = 300)
+
+/datum/category_item/autolathe/arms/pistol_45hp
+ name = "pistol magazine (.45 hollowpoint)"
+ path =/obj/item/ammo_magazine/m45/hp
+ hidden = 1
+ resources = list(DEFAULT_WALL_MATERIAL = 500, MAT_PLASTIC = 200)
+
/datum/category_item/autolathe/arms/pistol_45uzi
name = "uzi magazine (.45)"
path =/obj/item/ammo_magazine/m45uzi
@@ -138,6 +156,12 @@
name = "top-mounted SMG magazine (9mm flash)"
path =/obj/item/ammo_magazine/m9mmt/flash
+/datum/category_item/autolathe/arms/smg_9mmap
+ name = "top-mounted SMG magazine (9mm armor piercing)"
+ path =/obj/item/ammo_magazine/m9mmt/ap
+ hidden = 1
+ man_rating = 2
+
/////// 10mm
/datum/category_item/autolathe/arms/smg_10mm
name = "SMG magazine (10mm)"
diff --git a/code/datums/autolathe/autolathe.dm b/code/datums/autolathe/autolathe.dm
index 91c9ec37b7..003212fe75 100644
--- a/code/datums/autolathe/autolathe.dm
+++ b/code/datums/autolathe/autolathe.dm
@@ -71,6 +71,7 @@ var/datum/category_collection/autolathe/autolathe_recipes
var/is_stack // Creates multiple of an item if applied to non-stack items
var/max_stack
var/no_scale
+ var/man_rating = 0
/datum/category_item/autolathe/dd_SortValue()
return name
\ No newline at end of file
diff --git a/code/datums/autolathe/general.dm b/code/datums/autolathe/general.dm
index 891e73fb6b..5ad54b68bf 100644
--- a/code/datums/autolathe/general.dm
+++ b/code/datums/autolathe/general.dm
@@ -98,6 +98,18 @@
is_stack = TRUE
no_scale = TRUE //prevents material duplication exploits
+/datum/category_item/autolathe/general/plasteel
+ name = "plasteel sheets"
+ path =/obj/item/stack/material/plasteel
+ is_stack = TRUE
+ no_scale = TRUE //prevents material duplication exploits
+
+/datum/category_item/autolathe/general/plastic
+ name = "plastic sheets"
+ path =/obj/item/stack/material/plastic
+ is_stack = TRUE
+ no_scale = TRUE //prevents material duplication exploits
+
//TFF 24/12/19 - Let people print more spray bottles if needed.
/datum/category_item/autolathe/general/spraybottle
name = "spray bottle"
@@ -133,6 +145,19 @@
name = "maglight"
path =/obj/item/device/flashlight/maglight
+<<<<<<< HEAD
+=======
+/datum/category_item/autolathe/general/ecigcartridge
+ name = "ecigarette cartridge"
+ path = /obj/item/weapon/reagent_containers/ecig_cartridge/blank
+
+/datum/category_item/autolathe/general/idcard
+ name = "ID Card"
+ path = /obj/item/weapon/card/id
+ resources = list(DEFAULT_WALL_MATERIAL = 100, MAT_GLASS = 100, MAT_PLASTIC = 300)
+ man_rating = 2
+
+>>>>>>> 282b42d... Exosuit Modular Internals, The Squeakening (#7329)
/datum/category_item/autolathe/general/handcuffs
name = "handcuffs"
path =/obj/item/weapon/handcuffs
diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm
index 1629b77bdd..3e1188198b 100644
--- a/code/game/machinery/autolathe.dm
+++ b/code/game/machinery/autolathe.dm
@@ -12,8 +12,8 @@
circuit = /obj/item/weapon/circuitboard/autolathe
var/datum/category_collection/autolathe/machine_recipes
- var/list/stored_material = list(DEFAULT_WALL_MATERIAL = 0, "glass" = 0)
- var/list/storage_capacity = list(DEFAULT_WALL_MATERIAL = 0, "glass" = 0)
+ var/list/stored_material = list(DEFAULT_WALL_MATERIAL = 0, MAT_GLASS = 0, MAT_PLASTEEL = 0, MAT_PLASTIC = 0)
+ var/list/storage_capacity = list(DEFAULT_WALL_MATERIAL = 0, MAT_GLASS = 0, MAT_PLASTEEL = 0, MAT_PLASTIC = 0)
var/datum/category_group/autolathe/current_category
var/hacked = 0
@@ -26,6 +26,9 @@
var/datum/wires/autolathe/wires = null
+ var/mb_rating = 0
+ var/man_rating = 0
+
var/filtertext
/obj/machinery/autolathe/Initialize()
@@ -64,6 +67,9 @@
var/list/material_bottom = list("
")
for(var/material in stored_material)
+ if(material != DEFAULT_WALL_MATERIAL && material != MAT_GLASS) // Don't show the Extras unless people care enough to put them in.
+ if(stored_material[material] <= 0)
+ continue
material_top += "| [material] | "
material_bottom += "[stored_material[material]]/[storage_capacity[material]] | "
@@ -72,7 +78,9 @@
dat += "Printable Designs
"
for(var/datum/category_item/autolathe/R in current_category.items)
- if(R.hidden && !hacked)
+ if(R.hidden && !hacked) // Illegal or nonstandard.
+ continue
+ if(R.man_rating > man_rating) // Advanced parts.
continue
if(filtertext && findtext(R.name, filtertext) == 0)
continue
@@ -311,14 +319,16 @@
//Updates overall lathe storage size.
/obj/machinery/autolathe/RefreshParts()
..()
- var/mb_rating = 0
- var/man_rating = 0
+ mb_rating = 0
+ man_rating = 0
for(var/obj/item/weapon/stock_parts/matter_bin/MB in component_parts)
mb_rating += MB.rating
for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts)
man_rating += M.rating
storage_capacity[DEFAULT_WALL_MATERIAL] = mb_rating * 25000
+ storage_capacity[MAT_PLASTIC] = mb_rating * 20000
+ storage_capacity[MAT_PLASTEEL] = mb_rating * 16250
storage_capacity["glass"] = mb_rating * 12500
build_time = 50 / man_rating
mat_efficiency = 1.1 - man_rating * 0.1// Normally, price is 1.25 the amount of material, so this shouldn't go higher than 0.6. Maximum rating of parts is 5
diff --git a/code/game/mecha/combat/combat.dm b/code/game/mecha/combat/combat.dm
index b5d3351b21..d618d276c3 100644
--- a/code/game/mecha/combat/combat.dm
+++ b/code/game/mecha/combat/combat.dm
@@ -17,6 +17,14 @@
max_special_equip = 1
cargo_capacity = 1
+ starting_components = list(
+ /obj/item/mecha_parts/component/hull/durable,
+ /obj/item/mecha_parts/component/actuator,
+ /obj/item/mecha_parts/component/armor/reinforced,
+ /obj/item/mecha_parts/component/gas,
+ /obj/item/mecha_parts/component/electrical
+ )
+
/*
/obj/mecha/combat/range_action(target as obj|mob|turf)
if(internal_damage&MECHA_INT_CONTROL_LOST)
diff --git a/code/game/mecha/combat/durand.dm b/code/game/mecha/combat/durand.dm
index 5ab43a93ee..aa5a9e000c 100644
--- a/code/game/mecha/combat/durand.dm
+++ b/code/game/mecha/combat/durand.dm
@@ -5,8 +5,8 @@
initial_icon = "durand"
step_in = 4
dir_in = 1 //Facing North.
- health = 400
- maxhealth = 400 //Don't forget to update the /old variant if you change this number.
+ health = 300
+ maxhealth = 300 //Don't forget to update the /old variant if you change this number.
deflect_chance = 20
damage_absorption = list("brute"=0.5,"fire"=1.1,"bullet"=0.65,"laser"=0.85,"energy"=0.9,"bomb"=0.8)
max_temperature = 30000
@@ -23,6 +23,14 @@
max_universal_equip = 1
max_special_equip = 1
+ starting_components = list(
+ /obj/item/mecha_parts/component/hull/durable,
+ /obj/item/mecha_parts/component/actuator,
+ /obj/item/mecha_parts/component/armor/military,
+ /obj/item/mecha_parts/component/gas,
+ /obj/item/mecha_parts/component/electrical
+ )
+
defence_mode_possible = 1
/*
@@ -73,5 +81,5 @@
/obj/mecha/combat/durand/old/New()
..()
health = 25
- maxhealth = 350 //Just slightly worse.
+ maxhealth = 250 //Just slightly worse.
cell.charge = rand(0, (cell.charge/2))
\ No newline at end of file
diff --git a/code/game/mecha/combat/gygax.dm b/code/game/mecha/combat/gygax.dm
index d74b96cf99..0323124c47 100644
--- a/code/game/mecha/combat/gygax.dm
+++ b/code/game/mecha/combat/gygax.dm
@@ -5,8 +5,8 @@
initial_icon = "gygax"
step_in = 3
dir_in = 1 //Facing North.
- health = 300
- maxhealth = 300 //Don't forget to update the /old variant if you change this number.
+ health = 250
+ maxhealth = 250 //Don't forget to update the /old variant if you change this number.
deflect_chance = 15
damage_absorption = list("brute"=0.75,"fire"=1,"bullet"=0.8,"laser"=0.7,"energy"=0.85,"bomb"=1)
max_temperature = 25000
@@ -21,6 +21,14 @@
max_universal_equip = 1
max_special_equip = 1
+ starting_components = list(
+ /obj/item/mecha_parts/component/hull/lightweight,
+ /obj/item/mecha_parts/component/actuator,
+ /obj/item/mecha_parts/component/armor/marshal,
+ /obj/item/mecha_parts/component/gas,
+ /obj/item/mecha_parts/component/electrical
+ )
+
overload_possible = 1
//Not quite sure how to move those yet.
@@ -58,17 +66,12 @@
max_universal_equip = 1
max_special_equip = 2
-/obj/mecha/combat/gygax/dark/Initialize()
- ..()
- var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/scattershot
- ME.attach(src)
- ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/grenade/clusterbang
- ME.attach(src)
- ME = new /obj/item/mecha_parts/mecha_equipment/teleporter
- ME.attach(src)
- ME = new /obj/item/mecha_parts/mecha_equipment/tesla_energy_relay
- ME.attach(src)
- return
+ starting_equipment = list(
+ /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/scattershot,
+ /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/grenade/clusterbang,
+ /obj/item/mecha_parts/mecha_equipment/tesla_energy_relay,
+ /obj/item/mecha_parts/mecha_equipment/teleporter
+ )
/obj/mecha/combat/gygax/dark/add_cell(var/obj/item/weapon/cell/C=null)
if(C)
@@ -101,6 +104,14 @@
max_universal_equip = 1
max_special_equip = 1
+ starting_components = list(
+ /obj/item/mecha_parts/component/hull,
+ /obj/item/mecha_parts/component/actuator,
+ /obj/item/mecha_parts/component/armor/lightweight,
+ /obj/item/mecha_parts/component/gas,
+ /obj/item/mecha_parts/component/electrical
+ )
+
var/obj/item/clothing/glasses/hud/health/mech/hud
/obj/mecha/combat/gygax/serenity/New()
diff --git a/code/game/mecha/combat/marauder.dm b/code/game/mecha/combat/marauder.dm
index a79dc3fda2..e2c0b9467a 100644
--- a/code/game/mecha/combat/marauder.dm
+++ b/code/game/mecha/combat/marauder.dm
@@ -5,8 +5,8 @@
icon_state = "marauder"
initial_icon = "marauder"
step_in = 5
- health = 500
- maxhealth = 500 //Don't forget to update the /old variant if you change this number.
+ health = 350
+ maxhealth = 350 //Don't forget to update the /old variant if you change this number.
deflect_chance = 25
damage_absorption = list("brute"=0.5,"fire"=0.7,"bullet"=0.45,"laser"=0.6,"energy"=0.7,"bomb"=0.7)
max_temperature = 60000
@@ -29,6 +29,21 @@
zoom_possible = 1
thrusters_possible = 1
+ starting_components = list(
+ /obj/item/mecha_parts/component/hull/durable,
+ /obj/item/mecha_parts/component/actuator,
+ /obj/item/mecha_parts/component/armor/military,
+ /obj/item/mecha_parts/component/gas,
+ /obj/item/mecha_parts/component/electrical
+ )
+
+ starting_equipment = list(
+ /obj/item/mecha_parts/mecha_equipment/weapon/energy/pulse,
+ /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/explosive,
+ /obj/item/mecha_parts/mecha_equipment/tesla_energy_relay,
+ /obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster
+ )
+
/obj/mecha/combat/marauder/seraph
desc = "Heavy-duty, command-type exosuit. This is a custom model, utilized only by high-ranking military personnel."
name = "Seraph"
@@ -37,12 +52,20 @@
initial_icon = "seraph"
operation_req_access = list(access_cent_creed)
step_in = 3
- health = 550
+ health = 450
wreckage = /obj/effect/decal/mecha_wreckage/seraph
internal_damage_threshold = 20
force = 55
max_equip = 5
+ starting_equipment = list(
+ /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/scattershot,
+ /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/explosive,
+ /obj/item/mecha_parts/mecha_equipment/tesla_energy_relay,
+ /obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster,
+ /obj/item/mecha_parts/mecha_equipment/teleporter
+ )
+
//Note that is the Mauler
/obj/mecha/combat/marauder/mauler
desc = "Heavy-duty, combat exosuit, developed off of the existing Marauder model."
@@ -53,40 +76,6 @@
wreckage = /obj/effect/decal/mecha_wreckage/mauler
mech_faction = MECH_FACTION_SYNDI
-//Note that is the default Marauder
-/obj/mecha/combat/marauder/Initialize()
- ..()
- var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/weapon/energy/pulse
- ME.attach(src)
- ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/explosive
- ME.attach(src)
- ME = new /obj/item/mecha_parts/mecha_equipment/tesla_energy_relay(src)
- ME.attach(src)
- ME = new /obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster(src)
- ME.attach(src)
- return
-
-//Note that this is the seraph.
-/obj/mecha/combat/marauder/seraph/Initialize()
- ..()//Let it equip whatever is needed.
- var/obj/item/mecha_parts/mecha_equipment/ME
- if(equipment.len)//Now to remove it and equip anew.
- for(ME in equipment)
- ME.detach()
- qdel(ME)
- ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/scattershot(src)
- ME.attach(src)
- ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/explosive(src)
- ME.attach(src)
- ME = new /obj/item/mecha_parts/mecha_equipment/teleporter(src)
- ME.attach(src)
- ME = new /obj/item/mecha_parts/mecha_equipment/tesla_energy_relay(src)
- ME.attach(src)
- ME = new /obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster(src)
- ME.attach(src)
- return
-
-
//I'll break this down later
/obj/mecha/combat/marauder/relaymove(mob/user,direction)
if(user != src.occupant) //While not "realistic", this piece is player friendly.
@@ -150,17 +139,10 @@
/obj/mecha/combat/marauder/old
desc = "Heavy-duty, combat exosuit, developed after the Durand model. Rarely found among civilian populations. This one is particularly worn looking and likely isn't as sturdy."
+ starting_equipment = null
+
/obj/mecha/combat/marauder/old/New()
..()
health = 25
- maxhealth = 400 //Just slightly worse.
+ maxhealth = 300 //Just slightly worse.
cell.charge = rand(0, (cell.charge/2))
-
-/obj/mecha/combat/marauder/old/Initialize()
- ..()
- var/obj/item/mecha_parts/mecha_equipment/ME
- if(equipment.len)
- for(ME in equipment)
- ME.detach()
- qdel(ME)
- return
\ No newline at end of file
diff --git a/code/game/mecha/combat/phazon.dm b/code/game/mecha/combat/phazon.dm
index 121bab34f9..17aea92345 100644
--- a/code/game/mecha/combat/phazon.dm
+++ b/code/game/mecha/combat/phazon.dm
@@ -25,15 +25,24 @@
max_universal_equip = 3
max_special_equip = 4
- phasing_possible = 1
- switch_dmg_type_possible = 1
+ starting_components = list(
+ /obj/item/mecha_parts/component/hull/durable,
+ /obj/item/mecha_parts/component/actuator,
+ /obj/item/mecha_parts/component/armor/alien,
+ /obj/item/mecha_parts/component/gas,
+ /obj/item/mecha_parts/component/electrical
+ )
+
+ cloak_possible = TRUE
+ phasing_possible = TRUE
+ switch_dmg_type_possible = TRUE
/obj/mecha/combat/phazon/equipped/Initialize()
..()
- var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/tool/rcd
- ME.attach(src)
- ME = new /obj/item/mecha_parts/mecha_equipment/gravcatapult
- ME.attach(src)
+ starting_equipment = list(
+ /obj/item/mecha_parts/mecha_equipment/tool/rcd,
+ /obj/item/mecha_parts/mecha_equipment/gravcatapult
+ )
return
/* Leaving this until we are really sure we don't need it for reference.
@@ -95,8 +104,9 @@
max_universal_equip = 2
max_special_equip = 2
- phasing_possible = 1
- switch_dmg_type_possible = 1
+ phasing_possible = TRUE
+ switch_dmg_type_possible = TRUE
+ cloak_possible = FALSE
/obj/mecha/combat/phazon/janus/take_damage(amount, type="brute")
..()
diff --git a/code/game/mecha/components/_component.dm b/code/game/mecha/components/_component.dm
new file mode 100644
index 0000000000..aadf390c61
--- /dev/null
+++ b/code/game/mecha/components/_component.dm
@@ -0,0 +1,155 @@
+
+/obj/item/mecha_parts/component
+ name = "mecha component"
+ icon = 'icons/mecha/mech_component.dmi'
+ icon_state = "component"
+ w_class = ITEMSIZE_HUGE
+ origin_tech = list(TECH_DATA = 2, TECH_ENGINEERING = 2)
+
+ var/component_type = null
+
+ var/obj/mecha/chassis = null
+ var/start_damaged = FALSE
+
+ var/emp_resistance = 0 // Amount of emp 'levels' removed.
+
+ var/list/required_type = null // List, if it exists. Exosuits meant to use the component (Unique var changes / effects)
+
+ var/integrity
+ var/integrity_danger_mod = 0.5 // Multiplier for comparison to max_integrity before problems start.
+ var/max_integrity = 100
+
+ var/step_delay = 0
+
+ var/relative_size = 30 // Percent chance for the component to be hit.
+
+ var/internal_damage_flag // If set, the component will toggle the flag on or off if it is destroyed / severely damaged.
+
+/obj/item/mecha_parts/component/examine(mob/user)
+ . = ..()
+ var/show_integrity = round(integrity/max_integrity*100, 0.1)
+ switch(show_integrity)
+ if(85 to 100)
+ . += "It's fully intact."
+ if(65 to 85)
+ . += "It's slightly damaged."
+ if(45 to 65)
+ . += "It's badly damaged."
+ if(25 to 45)
+ . += "It's heavily damaged."
+ if(2 to 25)
+ . += "It's falling apart."
+ if(0 to 1)
+ . += "It is completely destroyed."
+
+/obj/item/mecha_parts/component/Initialize()
+ ..()
+ integrity = max_integrity
+
+ if(start_damaged)
+ integrity = round(integrity * integrity_danger_mod)
+
+/obj/item/mecha_parts/component/Destroy()
+ detach()
+ return ..()
+
+// Damage code.
+
+/obj/item/mecha_parts/component/emp_act(var/severity = 4)
+ if(severity + emp_resistance > 4)
+ return
+
+ severity = clamp(severity + emp_resistance, 1, 4)
+
+ take_damage((4 - severity) * round(integrity * 0.1, 0.1))
+
+/obj/item/mecha_parts/component/proc/adjust_integrity(var/amt = 0)
+ integrity = clamp(integrity + amt, 0, max_integrity)
+ return
+
+/obj/item/mecha_parts/component/proc/damage_part(var/dam_amt = 0, var/type = BRUTE)
+ if(dam_amt <= 0)
+ return FALSE
+
+ adjust_integrity(-1 * dam_amt)
+
+ if(chassis && internal_damage_flag)
+ if(get_efficiency() < 0.5)
+ chassis.check_for_internal_damage(list(internal_damage_flag), TRUE)
+
+ return TRUE
+
+/obj/item/mecha_parts/component/proc/get_efficiency()
+ var/integ_limit = round(max_integrity * integrity_danger_mod)
+
+ if(integrity < integ_limit)
+ var/int_percent = round(integrity / integ_limit, 0.1)
+
+ return int_percent
+
+ return 1
+
+// Attach/Detach code.
+
+/obj/item/mecha_parts/component/proc/attach(var/obj/mecha/target, var/mob/living/user)
+ if(target)
+ if(!(component_type in target.internal_components))
+ if(user)
+ to_chat(user, "\The [target] doesn't seem to have anywhere to put \the [src].")
+ return FALSE
+ if(target.internal_components[component_type])
+ if(user)
+ to_chat(user, "\The [target] already has a [component_type] installed!")
+ return FALSE
+ chassis = target
+ if(user)
+ user.drop_from_inventory(src)
+ forceMove(target)
+
+ if(internal_damage_flag)
+ if(integrity > (max_integrity * integrity_danger_mod))
+ if(chassis.hasInternalDamage(internal_damage_flag))
+ chassis.clearInternalDamage(internal_damage_flag)
+
+ else
+ chassis.check_for_internal_damage(list(internal_damage_flag))
+
+ chassis.internal_components[component_type] = src
+
+ if(user)
+ chassis.visible_message("[user] installs \the [src] in \the [chassis].")
+ return TRUE
+ return FALSE
+
+/obj/item/mecha_parts/component/proc/detach()
+ if(chassis)
+ chassis.internal_components[component_type] = null
+
+ if(internal_damage_flag && chassis.hasInternalDamage(internal_damage_flag)) // If the module has been removed, it's kind of unfair to keep it causing problems by being damaged. It's nonfunctional either way.
+ chassis.clearInternalDamage(internal_damage_flag)
+
+ forceMove(get_turf(chassis))
+ chassis = null
+ return TRUE
+
+
+/obj/item/mecha_parts/component/attackby(obj/item/weapon/W as obj, mob/user as mob)
+ if(istype(W,/obj/item/stack/nanopaste))
+ var/obj/item/stack/nanopaste/NP = W
+
+ if(integrity < max_integrity)
+ while(integrity < max_integrity && NP)
+ if(do_after(user, 1 SECOND, src) && NP.use(1))
+ adjust_integrity(10)
+
+ return
+
+ return ..()
+
+// Various procs to handle different calls by Exosuits. IE, movement actions, damage actions, etc.
+
+/obj/item/mecha_parts/component/proc/get_step_delay()
+ return step_delay
+
+/obj/item/mecha_parts/component/proc/handle_move()
+ return
diff --git a/code/game/mecha/components/actuators.dm b/code/game/mecha/components/actuators.dm
new file mode 100644
index 0000000000..d814518629
--- /dev/null
+++ b/code/game/mecha/components/actuators.dm
@@ -0,0 +1,37 @@
+
+/obj/item/mecha_parts/component/actuator
+ name = "mecha actuator"
+ icon = 'icons/mecha/mech_component.dmi'
+ icon_state = "motor"
+ w_class = ITEMSIZE_HUGE
+ origin_tech = list(TECH_DATA = 2, TECH_ENGINEERING = 2)
+
+ component_type = MECH_ACTUATOR
+
+ start_damaged = FALSE
+
+ emp_resistance = 1
+
+ required_type = null // List, if it exists. Exosuits meant to use the component.
+
+ integrity_danger_mod = 0.6 // Multiplier for comparison to max_integrity before problems start.
+ max_integrity = 50
+
+ internal_damage_flag = MECHA_INT_CONTROL_LOST
+
+ var/strafing_multiplier = 1.5
+
+/obj/item/mecha_parts/component/actuator/get_step_delay()
+ return step_delay
+
+/obj/item/mecha_parts/component/actuator/hispeed
+ name = "overclocked mecha actuator"
+
+ step_delay = -1
+
+ emp_resistance = -1
+
+ integrity_danger_mod = 0.7
+ max_integrity = 60
+
+ strafing_multiplier = 1.2
diff --git a/code/game/mecha/components/armor.dm b/code/game/mecha/components/armor.dm
new file mode 100644
index 0000000000..b64c37bca5
--- /dev/null
+++ b/code/game/mecha/components/armor.dm
@@ -0,0 +1,238 @@
+
+/obj/item/mecha_parts/component/armor
+ name = "mecha plating"
+ icon = 'icons/mecha/mech_component.dmi'
+ icon_state = "armor"
+ w_class = ITEMSIZE_HUGE
+ origin_tech = list(TECH_DATA = 1, TECH_ENGINEERING = 2)
+
+ component_type = MECH_ARMOR
+
+ start_damaged = FALSE
+
+ emp_resistance = 4
+
+ required_type = null // List, if it exists. Exosuits meant to use the component.
+
+ integrity_danger_mod = 0.4 // Multiplier for comparison to max_integrity before problems start.
+ max_integrity = 120
+
+ internal_damage_flag = MECHA_INT_TEMP_CONTROL
+
+ step_delay = 1
+
+ var/deflect_chance = 10
+ var/list/damage_absorption = list(
+ "brute"= 0.8,
+ "fire"= 1.2,
+ "bullet"= 0.9,
+ "laser"= 1,
+ "energy"= 1,
+ "bomb"= 1,
+ "bio"= 1,
+ "rad"= 1
+ )
+
+ var/damage_minimum = 10
+ var/minimum_penetration = 0
+ var/fail_penetration_value = 0.66
+
+/obj/item/mecha_parts/component/armor/mining
+ name = "blast-resistant mecha plating"
+
+ step_delay = 2
+ max_integrity = 80
+
+ damage_absorption = list(
+ "brute"=0.8,
+ "fire"=0.8,
+ "bullet"=1.2,
+ "laser"=1.2,
+ "energy"=1,
+ "bomb"=0.5,
+ "bio"=1,
+ "rad"=1
+ )
+
+/obj/item/mecha_parts/component/armor/lightweight
+ name = "lightweight mecha plating"
+
+ max_integrity = 50
+ step_delay = 0
+
+ damage_absorption = list(
+ "brute"=1,
+ "fire"=1.4,
+ "bullet"=1.1,
+ "laser"=1.2,
+ "energy"=1,
+ "bomb"=1,
+ "bio"=1,
+ "rad"=1
+ )
+
+/obj/item/mecha_parts/component/armor/reinforced
+ name = "reinforced mecha plating"
+
+ step_delay = 4
+
+ max_integrity = 80
+
+ minimum_penetration = 10
+
+ damage_absorption = list(
+ "brute"=0.7,
+ "fire"=1,
+ "bullet"=0.7,
+ "laser"=0.85,
+ "energy"=1,
+ "bomb"=0.8
+ )
+
+/obj/item/mecha_parts/component/armor/military
+ name = "military grade mecha plating"
+
+ step_delay = 6
+
+ max_integrity = 100
+
+ emp_resistance = 2
+
+ required_type = list(/obj/mecha/combat)
+
+ damage_minimum = 15
+ minimum_penetration = 25
+
+ damage_absorption = list(
+ "brute"=0.5,
+ "fire"=1.1,
+ "bullet"=0.65,
+ "laser"=0.85,
+ "energy"=0.9,
+ "bomb"=0.8
+ )
+
+/obj/item/mecha_parts/component/armor/military/attach(var/obj/mecha/target, var/mob/living/user)
+ . = ..()
+ if(.)
+ var/typepass = FALSE
+ for(var/type in required_type)
+ if(istype(chassis, type))
+ typepass = TRUE
+
+ if(typepass)
+ step_delay = 3
+ else
+ step_delay = initial(step_delay)
+
+/obj/item/mecha_parts/component/armor/marshal
+ name = "marshal mecha plating"
+
+ step_delay = 5
+
+ max_integrity = 100
+
+ emp_resistance = 3
+
+ deflect_chance = 15
+
+ minimum_penetration = 10
+
+ required_type = list(/obj/mecha/combat)
+
+ damage_absorption = list(
+ "brute"=0.75,
+ "fire"=1,
+ "bullet"=0.8,
+ "laser"=0.7,
+ "energy"=0.85,
+ "bomb"=1
+ )
+
+/obj/item/mecha_parts/component/armor/marshal/attach(var/obj/mecha/target, var/mob/living/user)
+ . = ..()
+ if(.)
+ var/typepass = FALSE
+ for(var/type in required_type)
+ if(istype(chassis, type))
+ typepass = TRUE
+
+ if(typepass)
+ step_delay = 2
+ else
+ step_delay = initial(step_delay)
+
+/obj/item/mecha_parts/component/armor/marshal/reinforced
+ name = "blackops mecha plating"
+
+ step_delay = 5
+
+ damage_absorption = list(
+ "brute"=0.6,
+ "fire"=0.8,
+ "bullet"=0.6,
+ "laser"=0.5,
+ "energy"=0.65,
+ "bomb"=0.8
+ )
+
+/obj/item/mecha_parts/component/armor/military/marauder
+ name = "cutting edge mecha plating"
+
+ step_delay = 4
+
+ max_integrity = 150
+
+ emp_resistance = 3
+
+ required_type = list(/obj/mecha/combat/marauder)
+
+ deflect_chance = 25
+ damage_minimum = 30
+ minimum_penetration = 25
+
+ damage_absorption = list(
+ "brute"=0.5,
+ "fire"=0.7,
+ "bullet"=0.45,
+ "laser"=0.6,
+ "energy"=0.7,
+ "bomb"=0.7
+ )
+
+/obj/item/mecha_parts/component/armor/military/marauder/attach(var/obj/mecha/target, var/mob/living/user)
+ . = ..()
+ if(.)
+ var/typepass = FALSE
+ for(var/type in required_type)
+ if(istype(chassis, type))
+ typepass = TRUE
+
+ if(typepass)
+ step_delay = 1
+ else
+ step_delay = initial(step_delay)
+
+/obj/item/mecha_parts/component/armor/alien
+ name = "strange mecha plating"
+ step_delay = 3
+ damage_absorption = list(
+ "brute"=0.7,
+ "fire"=0.7,
+ "bullet"=0.7,
+ "laser"=0.7,
+ "energy"=0.7,
+ "bomb"=0.7
+ )
+
+/obj/item/mecha_parts/component/armor/alien/attach(var/obj/mecha/target, var/mob/living/user)
+ . = ..()
+ if(.)
+ if(istype(target, /obj/mecha/combat/phazon/janus))
+ step_delay = -1
+
+ else if(istype(target, /obj/mecha/combat/phazon))
+ step_delay = -3
+
+ else
+ step_delay = initial(step_delay)
diff --git a/code/game/mecha/components/electrical.dm b/code/game/mecha/components/electrical.dm
new file mode 100644
index 0000000000..de07c96c84
--- /dev/null
+++ b/code/game/mecha/components/electrical.dm
@@ -0,0 +1,31 @@
+
+/obj/item/mecha_parts/component/electrical
+ name = "mecha electrical harness"
+ icon = 'icons/mecha/mech_component.dmi'
+ icon_state = "board"
+ w_class = ITEMSIZE_HUGE
+ origin_tech = list(TECH_DATA = 2, TECH_ENGINEERING = 2)
+
+ component_type = MECH_ELECTRIC
+
+ emp_resistance = 1
+
+ integrity_danger_mod = 0.4
+ max_integrity = 40
+
+ step_delay = 0
+
+ relative_size = 20
+
+ internal_damage_flag = MECHA_INT_SHORT_CIRCUIT
+
+ var/charge_cost_mod = 1
+
+/obj/item/mecha_parts/component/electrical/high_current
+ name = "efficient mecha electrical harness"
+
+ emp_resistance = 0
+ max_integrity = 30
+
+ relative_size = 10
+ charge_cost_mod = 0.6
diff --git a/code/game/mecha/components/hull.dm b/code/game/mecha/components/hull.dm
new file mode 100644
index 0000000000..16d01ad92c
--- /dev/null
+++ b/code/game/mecha/components/hull.dm
@@ -0,0 +1,33 @@
+
+/obj/item/mecha_parts/component/hull
+ name = "mecha hull"
+ icon = 'icons/mecha/mech_component.dmi'
+ icon_state = "hull"
+ w_class = ITEMSIZE_HUGE
+ origin_tech = list(TECH_DATA = 2, TECH_ENGINEERING = 2)
+
+ component_type = MECH_HULL
+
+ emp_resistance = 0 // Amount of emp 'levels' removed.
+
+ required_type = null // List, if it exists. Exosuits meant to use the component.
+
+ integrity_danger_mod = 0.5 // Multiplier for comparison to max_integrity before problems start.
+ max_integrity = 50
+
+ internal_damage_flag = MECHA_INT_FIRE
+
+ step_delay = 2
+
+/obj/item/mecha_parts/component/hull/durable
+ name = "durable mecha hull"
+
+ step_delay = 4
+ integrity_danger_mod = 0.3
+ max_integrity = 100
+
+/obj/item/mecha_parts/component/hull/lightweight
+ name = "lightweight mecha hull"
+
+ step_delay = 1
+ integrity_danger_mod = 0.3
diff --git a/code/game/mecha/components/lifesupport.dm b/code/game/mecha/components/lifesupport.dm
new file mode 100644
index 0000000000..d98cefda4d
--- /dev/null
+++ b/code/game/mecha/components/lifesupport.dm
@@ -0,0 +1,28 @@
+
+/obj/item/mecha_parts/component/gas
+ name = "mecha life-support"
+ icon = 'icons/mecha/mech_component.dmi'
+ icon_state = "lifesupport"
+ w_class = ITEMSIZE_HUGE
+ origin_tech = list(TECH_DATA = 2, TECH_ENGINEERING = 2)
+
+ component_type = MECH_GAS
+
+ emp_resistance = 1
+
+ integrity_danger_mod = 0.4
+ max_integrity = 40
+
+ step_delay = 0
+
+ relative_size = 20
+
+ internal_damage_flag = MECHA_INT_TANK_BREACH
+
+/obj/item/mecha_parts/component/gas/reinforced
+ name = "reinforced mecha life-support"
+
+ emp_resistance = 2
+ max_integrity = 80
+
+ relative_size = 40
diff --git a/code/game/mecha/equipment/mecha_equipment.dm b/code/game/mecha/equipment/mecha_equipment.dm
index 678ac64910..617af4849f 100644
--- a/code/game/mecha/equipment/mecha_equipment.dm
+++ b/code/game/mecha/equipment/mecha_equipment.dm
@@ -28,6 +28,8 @@
var/ready_sound = 'sound/mecha/mech_reload_default.ogg' //Sound to play once the fire delay passed.
var/enable_special = FALSE // Will the tool do its special?
+ var/step_delay = 0 // Does the component slow/speed up the suit?
+
/obj/item/mecha_parts/mecha_equipment/proc/do_after_cooldown(target=1)
sleep(equip_cooldown)
set_ready_state(1)
@@ -273,3 +275,6 @@
/obj/item/mecha_parts/mecha_equipment/proc/MoveAction() //Allows mech equipment to do an action upon the mech moving
return
+
+/obj/item/mecha_parts/mecha_equipment/proc/get_step_delay() // Equipment returns its slowdown or speedboost.
+ return step_delay
diff --git a/code/game/mecha/equipment/tools/armor_melee.dm b/code/game/mecha/equipment/tools/armor_melee.dm
index 8390a2cc52..085148d938 100644
--- a/code/game/mecha/equipment/tools/armor_melee.dm
+++ b/code/game/mecha/equipment/tools/armor_melee.dm
@@ -9,6 +9,8 @@
var/deflect_coeff = 1.15
var/damage_coeff = 0.8
+ step_delay = 1
+
equip_type = EQUIP_HULL
/obj/item/mecha_parts/mecha_equipment/anticcw_armor_booster/get_equip_info()
diff --git a/code/game/mecha/equipment/tools/armor_ranged.dm b/code/game/mecha/equipment/tools/armor_ranged.dm
index 4fb3aac32b..5b8d6d8172 100644
--- a/code/game/mecha/equipment/tools/armor_ranged.dm
+++ b/code/game/mecha/equipment/tools/armor_ranged.dm
@@ -9,6 +9,8 @@
var/deflect_coeff = 1.15
var/damage_coeff = 0.8
+ step_delay = 2
+
equip_type = EQUIP_HULL
/obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster/handle_projectile_contact(var/obj/item/projectile/Proj, var/inc_damage)
diff --git a/code/game/mecha/equipment/tools/repair_droid.dm b/code/game/mecha/equipment/tools/repair_droid.dm
index f4f9696aa5..7cd8ebd9ab 100644
--- a/code/game/mecha/equipment/tools/repair_droid.dm
+++ b/code/game/mecha/equipment/tools/repair_droid.dm
@@ -11,6 +11,8 @@
var/icon/droid_overlay
var/list/repairable_damage = list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH)
+ step_delay = 1
+
equip_type = EQUIP_HULL
/obj/item/mecha_parts/mecha_equipment/repair_droid/New()
@@ -79,8 +81,23 @@
RD.chassis.clearInternalDamage(int_dam_flag)
repaired = 1
break
- if(health_boost<0 || RD.chassis.health < initial(RD.chassis.health))
+
+ var/obj/item/mecha_parts/component/AC = RD.chassis.internal_components[MECH_ARMOR]
+ var/obj/item/mecha_parts/component/HC = RD.chassis.internal_components[MECH_HULL]
+
+ var/damaged_armor = AC.integrity < AC.max_integrity
+
+ var/damaged_hull = HC.integrity < HC.max_integrity
+
+ if(health_boost<0 || RD.chassis.health < initial(RD.chassis.health) || damaged_armor || damaged_hull)
RD.chassis.health += min(health_boost, initial(RD.chassis.health)-RD.chassis.health)
+
+ if(AC)
+ AC.adjust_integrity(round(health_boost * 0.5, 0.5))
+
+ if(HC)
+ HC.adjust_integrity(round(health_boost * 0.5, 0.5))
+
repaired = 1
if(repaired)
if(RD.chassis.use_power(RD.energy_drain))
diff --git a/code/game/mecha/equipment/tools/shield.dm b/code/game/mecha/equipment/tools/shield.dm
index 1ceab07945..453c2ba9da 100644
--- a/code/game/mecha/equipment/tools/shield.dm
+++ b/code/game/mecha/equipment/tools/shield.dm
@@ -7,6 +7,8 @@
energy_drain = 20
range = 0
+ step_delay = 1
+
var/obj/item/shield_projector/line/exosuit/my_shield = null
var/my_shield_type = /obj/item/shield_projector/line/exosuit
var/icon/drone_overlay
@@ -66,9 +68,11 @@
my_shield.attack_self(chassis.occupant)
if(my_shield.active)
set_ready_state(0)
+ step_delay = 4
log_message("Activated.")
else
set_ready_state(1)
+ step_delay = 1
log_message("Deactivated.")
/obj/item/mecha_parts/mecha_equipment/combat_shield/Topic(href, href_list)
diff --git a/code/game/mecha/equipment/tools/shield_omni.dm b/code/game/mecha/equipment/tools/shield_omni.dm
index 1d230c4deb..aae68ef4cd 100644
--- a/code/game/mecha/equipment/tools/shield_omni.dm
+++ b/code/game/mecha/equipment/tools/shield_omni.dm
@@ -9,6 +9,8 @@
energy_drain = OMNI_SHIELD_DRAIN
range = 0
+ step_delay = 1
+
var/obj/item/shield_projector/shields = null
var/shield_type = /obj/item/shield_projector/rectangle/mecha
@@ -42,9 +44,11 @@
shields.set_on(!shields.active)
if(shields.active)
set_ready_state(0)
+ step_delay = 4
log_message("Activated.")
else
set_ready_state(1)
+ step_delay = 1
log_message("Deactivated.")
/obj/item/mecha_parts/mecha_equipment/omni_shield/Topic(href, href_list)
diff --git a/code/game/mecha/equipment/tools/speedboost.dm b/code/game/mecha/equipment/tools/speedboost.dm
index 6e7ad06f69..7ffbeaee38 100644
--- a/code/game/mecha/equipment/tools/speedboost.dm
+++ b/code/game/mecha/equipment/tools/speedboost.dm
@@ -7,6 +7,9 @@
equip_type = EQUIP_HULL
+ var/slowdown_multiplier = 0.75 // How much does the exosuit multiply its slowdown by if it's the proper type?
+
+/*
/obj/item/mecha_parts/mecha_equipment/speedboost/attach(obj/mecha/M as obj)
..()
if(enable_special)
@@ -14,6 +17,13 @@
else
chassis.step_in = 6 // Improper parts slow the mech down
return
+*/
+
+/obj/item/mecha_parts/mecha_equipment/speedboost/get_step_delay()
+ if(enable_special)
+ return -1
+ else
+ return 3
/obj/item/mecha_parts/mecha_equipment/speedboost/detach()
chassis.step_in = initial(chassis.step_in)
diff --git a/code/game/mecha/equipment/weapons/ballistic/mortar.dm b/code/game/mecha/equipment/weapons/ballistic/mortar.dm
index 86928c9da5..c192d0fc9b 100644
--- a/code/game/mecha/equipment/weapons/ballistic/mortar.dm
+++ b/code/game/mecha/equipment/weapons/ballistic/mortar.dm
@@ -11,6 +11,8 @@
projectile = /obj/item/projectile/arc/fragmentation/mortar
projectile_energy_cost = 600
+ step_delay = 2
+
origin_tech = list(TECH_MATERIAL = 4, TECH_COMBAT = 5, TECH_ILLEGAL = 3)
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/mortar/action_checks(atom/target)
diff --git a/code/game/mecha/equipment/weapons/ballistic/shotgun.dm b/code/game/mecha/equipment/weapons/ballistic/shotgun.dm
index d2232d0004..e6b12d8ebd 100644
--- a/code/game/mecha/equipment/weapons/ballistic/shotgun.dm
+++ b/code/game/mecha/equipment/weapons/ballistic/shotgun.dm
@@ -11,6 +11,8 @@
deviation = 0.7
projectile_energy_cost = 25
+ step_delay = 2
+
origin_tech = list(TECH_MATERIAL = 3, TECH_COMBAT = 4)
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/scattershot/rigged
diff --git a/code/game/mecha/equipment/weapons/energy/laser.dm b/code/game/mecha/equipment/weapons/energy/laser.dm
index 8bdcbcf71f..0dfcbd1328 100644
--- a/code/game/mecha/equipment/weapons/energy/laser.dm
+++ b/code/game/mecha/equipment/weapons/energy/laser.dm
@@ -52,6 +52,8 @@
projectile = /obj/item/projectile/beam/heavylaser
fire_sound = 'sound/weapons/lasercannonfire.ogg'
+ step_delay = 2
+
origin_tech = list(TECH_MATERIAL = 3, TECH_COMBAT = 4, TECH_MAGNET = 4)
/obj/item/mecha_parts/mecha_equipment/weapon/energy/laser/heavy/rigged
diff --git a/code/game/mecha/equipment/weapons/explosive/missile.dm b/code/game/mecha/equipment/weapons/explosive/missile.dm
index 1c14a8c1dd..df8cf0c3bb 100644
--- a/code/game/mecha/equipment/weapons/explosive/missile.dm
+++ b/code/game/mecha/equipment/weapons/explosive/missile.dm
@@ -2,6 +2,8 @@
var/missile_speed = 2
var/missile_range = 30
+ step_delay = 2
+
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/Fire(atom/movable/AM, atom/target, turf/aimloc)
AM.throw_at(target,missile_range, missile_speed, chassis)
@@ -19,6 +21,8 @@
missile_range = 15
required_type = /obj/mecha //Why restrict it to just mining or combat mechs?
+ step_delay = 0
+
equip_type = EQUIP_UTILITY
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flare/Fire(atom/movable/AM, atom/target, turf/aimloc)
diff --git a/code/game/mecha/equipment/weapons/fire/flamethrower.dm b/code/game/mecha/equipment/weapons/fire/flamethrower.dm
index f97f598e24..532c35a6b4 100644
--- a/code/game/mecha/equipment/weapons/fire/flamethrower.dm
+++ b/code/game/mecha/equipment/weapons/fire/flamethrower.dm
@@ -7,6 +7,8 @@
energy_drain = 30
+ step_delay = 2
+
projectile = /obj/item/projectile/bullet/incendiary/flamethrower/large
fire_sound = 'sound/weapons/towelwipe.ogg'
diff --git a/code/game/mecha/equipment/weapons/fire/incendiary.dm b/code/game/mecha/equipment/weapons/fire/incendiary.dm
index 3d3c174839..ff49d42016 100644
--- a/code/game/mecha/equipment/weapons/fire/incendiary.dm
+++ b/code/game/mecha/equipment/weapons/fire/incendiary.dm
@@ -16,3 +16,5 @@
projectile_energy_cost = 40
fire_cooldown = 3
origin_tech = list(TECH_MATERIAL = 4, TECH_COMBAT = 5, TECH_PHORON = 2, TECH_ILLEGAL = 1)
+
+ step_delay = 1
diff --git a/code/game/mecha/equipment/weapons/weapons.dm b/code/game/mecha/equipment/weapons/weapons.dm
index 355ce629ac..9dccf551c9 100644
--- a/code/game/mecha/equipment/weapons/weapons.dm
+++ b/code/game/mecha/equipment/weapons/weapons.dm
@@ -12,6 +12,8 @@
var/auto_rearm = 0 //Does the weapon reload itself after each shot?
required_type = list(/obj/mecha/combat, /obj/mecha/working/hoverpod/combatpod)
+ step_delay = 1
+
equip_type = EQUIP_WEAPON
/obj/item/mecha_parts/mecha_equipment/weapon/action_checks(atom/target)
diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm
index ca2bcab7b9..130b6f20e6 100644
--- a/code/game/mecha/mecha.dm
+++ b/code/game/mecha/mecha.dm
@@ -7,6 +7,11 @@
#define MELEE 1
#define RANGED 2
+#define MECHA_OPERATING 0
+#define MECHA_BOLTS_SECURED 1
+#define MECHA_PANEL_LOOSE 2
+#define MECHA_CELL_OPEN 3
+#define MECHA_CELL_OUT 4
#define MECH_FACTION_NT "nano"
#define MECH_FACTION_SYNDI "syndi"
@@ -48,7 +53,7 @@
var/fail_penetration_value = 0.66 //By how much failing to penetrate reduces your shit. 66% by default.
var/obj/item/weapon/cell/cell
- var/state = 0
+ var/state = MECHA_OPERATING
var/list/log = new
var/last_message = 0
var/add_req_access = 1
@@ -108,6 +113,24 @@
var/max_universal_equip = 2
var/max_special_equip = 1
+ var/list/starting_equipment = null // List containing starting tools.
+
+// Mech Components, similar to Cyborg, but Bigger.
+ var/list/internal_components = list(
+ MECH_HULL = null,
+ MECH_ACTUATOR = null,
+ MECH_ARMOR = null,
+ MECH_GAS = null,
+ MECH_ELECTRIC = null
+ )
+ var/list/starting_components = list(
+ /obj/item/mecha_parts/component/hull,
+ /obj/item/mecha_parts/component/actuator,
+ /obj/item/mecha_parts/component/armor,
+ /obj/item/mecha_parts/component/gas,
+ /obj/item/mecha_parts/component/electrical
+ )
+
//Working exosuit vars
var/list/cargo = list()
var/cargo_capacity = 3
@@ -139,7 +162,7 @@
var/phasing_possible = 0 //This is to allow phasing.
var/can_phase = TRUE //This is an internal check during the relevant procs.
var/phasing_energy_drain = 200
-
+
var/switch_dmg_type_possible = 0 //Can you switch damage type? It is mostly for the Phazon and its children.
var/smoke_possible = 0
@@ -148,6 +171,8 @@
var/smoke_cooldown = 100 //How long you have between uses.
var/datum/effect/effect/system/smoke_spread/smoke_system = new
+ var/cloak_possible = FALSE // Can this exosuit innately cloak?
+
////All of those are for the HUD buttons in the top left. See Grant and Remove procs in mecha_actions.
var/datum/action/innate/mecha/mech_eject/eject_action = new
@@ -164,10 +189,20 @@
var/datum/action/innate/mecha/mech_cycle_equip/cycle_action = new
var/datum/action/innate/mecha/mech_switch_damtype/switch_damtype_action = new
var/datum/action/innate/mecha/mech_toggle_phasing/phasing_action = new
+ var/datum/action/innate/mecha/mech_toggle_cloaking/cloak_action = new
var/weapons_only_cycle = FALSE //So combat mechs don't switch to their equipment at times.
+/obj/mecha/Initialize()
+ ..()
+ for(var/path in starting_components)
+ var/obj/item/mecha_parts/component/C = new path(src)
+ C.attach(src)
+ if(starting_equipment && LAZYLEN(starting_equipment))
+ for(var/path in starting_equipment)
+ var/obj/item/mecha_parts/mecha_equipment/ME = new path(src)
+ ME.attach(src)
/obj/mecha/drain_power(var/drain_check)
@@ -245,6 +280,15 @@
else
E.forceMove(loc)
E.destroy()
+
+ for(var/slot in internal_components)
+ var/obj/item/mecha_parts/component/C = internal_components[slot]
+ if(istype(C))
+ C.damage_part(rand(10, 20))
+ C.detach()
+ WR.crowbar_salvage += C
+ C.forceMove(WR)
+
if(cell)
WR.crowbar_salvage += cell
cell.forceMove(WR)
@@ -256,6 +300,11 @@
for(var/obj/item/mecha_parts/mecha_equipment/E in equipment)
E.detach(loc)
E.destroy()
+ for(var/slot in internal_components)
+ var/obj/item/mecha_parts/component/C = internal_components[slot]
+ if(istype(C))
+ C.detach()
+ qdel(C)
if(cell)
qdel(cell)
if(internal_tank)
@@ -351,6 +400,26 @@
/obj/mecha/examine(mob/user)
. = ..()
+
+ var/obj/item/mecha_parts/component/armor/AC = internal_components[MECH_ARMOR]
+
+ var/obj/item/mecha_parts/component/hull/HC = internal_components[MECH_HULL]
+
+ if(AC)
+ . += "It has [AC] attached. [AC.get_efficiency()<0.5?"It is severely damaged.":""]"
+ else
+ . += "It has no armor plating."
+
+ if(HC)
+ if(!AC || AC.get_efficiency() < 0.7)
+ . += "It has [HC] attached. [HC.get_efficiency()<0.5?"It is severely damaged.":""]"
+ else
+ . += "You cannot tell what type of hull it has."
+
+ else
+ . += "It does not seem to have a completed hull."
+
+
var/integrity = health/initial(health)*100
switch(integrity)
if(85 to 100)
@@ -536,6 +605,12 @@
user.forceMove(get_turf(src))
to_chat(user, "You climb out from [src]")
return 0
+
+ var/obj/item/mecha_parts/component/hull/HC = internal_components[MECH_HULL]
+ if(!HC)
+ occupant_message("You can't operate an exosuit that doesn't have a hull!")
+ return
+
if(connected_port)
if(world.time - last_message > 20)
src.occupant_message("Unable to move while connected to the air system port")
@@ -562,6 +637,44 @@
return call((proc_res["dyndomove"]||src), "dyndomove")(direction)
+/obj/mecha/proc/get_step_delay()
+ var/tally = 0
+
+ if(overload)
+ tally = min(1, round(step_in/2))
+
+ for(var/slot in internal_components)
+ var/obj/item/mecha_parts/component/C = internal_components[slot]
+ if(C && C.get_step_delay())
+ tally += C.get_step_delay()
+
+ for(var/obj/item/mecha_parts/mecha_equipment/ME in equipment)
+ if(ME.get_step_delay())
+ tally += ME.get_step_delay()
+
+ var/obj/item/mecha_parts/component/actuator/actuator = internal_components[MECH_ACTUATOR]
+
+ if(!actuator) // Relying purely on hydraulic pumps. You're going nowhere fast.
+ tally = 2 SECONDS
+
+ return tally
+
+ tally += 0.5 SECONDS * (1 - actuator.get_efficiency()) // Damaged actuators run slower, slowing as damage increases beyond its threshold.
+
+ if(strafing)
+ tally = round(tally * actuator.strafing_multiplier)
+
+ for(var/obj/item/mecha_parts/mecha_equipment/ME in equipment)
+ if(istype(ME, /obj/item/mecha_parts/mecha_equipment/speedboost))
+ var/obj/item/mecha_parts/mecha_equipment/speedboost/SB = ME
+ for(var/path in ME.required_type)
+ if(istype(src, path))
+ tally = round(tally * SB.slowdown_multiplier)
+ break
+ break
+
+ return max(1, round(tally))
+
/obj/mecha/proc/dyndomove(direction)
if(!can_move)
return 0
@@ -600,7 +713,6 @@
health--
if(health < initial(health) - initial(health)/3)
overload = 0
- step_in = initial(step_in)
step_energy_drain = initial(step_energy_drain)
src.occupant_message("Leg actuators damage threshold exceded. Disabling overload.")
@@ -656,7 +768,7 @@
if(!src.check_for_support())
src.pr_inertial_movement.start(list(src,direction))
src.log_message("Movement control lost. Inertial movement started.")
- if(do_after(step_in))
+ if(do_after(get_step_delay()))
can_move = 1
return 1
return 0
@@ -708,7 +820,7 @@
flick("[initial_icon]-phase", src)
src.loc = get_step(src,src.dir)
src.use_power(phasing_energy_drain)
- sleep(step_in*3)
+ sleep(get_step_delay() * 3)
can_phase = TRUE
occupant_message("Phazed.")
. = ..(obstacle)
@@ -785,16 +897,57 @@
update_damage_alerts()
if(amount)
var/damage = absorbDamage(amount,type)
+
+ damage = components_handle_damage(damage,type)
+
health -= damage
+
update_health()
log_append_to_last("Took [damage] points of damage. Damage type: \"[type]\".",1)
return
+/obj/mecha/proc/components_handle_damage(var/damage, var/type = BRUTE)
+ var/obj/item/mecha_parts/component/armor/AC = internal_components[MECH_ARMOR]
+
+ if(AC)
+ var/armor_efficiency = AC.get_efficiency()
+ var/damage_change = armor_efficiency * (damage * 0.5) * AC.damage_absorption[type]
+ AC.damage_part(damage_change, type)
+ damage -= damage_change
+
+ var/obj/item/mecha_parts/component/hull/HC = internal_components[MECH_HULL]
+
+ if(HC)
+ if(HC.integrity)
+ var/hull_absorb = round(rand(5, 10) / 10, 0.1) * damage
+ HC.damage_part(hull_absorb, type)
+ damage -= hull_absorb
+
+ for(var/obj/item/mecha_parts/component/C in (internal_components - list(MECH_HULL, MECH_ARMOR)))
+ if(prob(C.relative_size))
+ var/damage_part_amt = round(damage / 4, 0.1)
+ C.damage_part(damage_part_amt)
+ damage -= damage_part_amt
+
+ return damage
+
+/obj/mecha/proc/get_damage_absorption()
+ var/obj/item/mecha_parts/component/armor/AC = internal_components[MECH_ARMOR]
+
+ if(!istype(AC))
+ return
+
+ else
+ if(AC.get_efficiency() > 0.25)
+ return AC.damage_absorption
+
+ return
+
/obj/mecha/proc/absorbDamage(damage,damage_type)
return call((proc_res["dynabsorbdamage"]||src), "dynabsorbdamage")(damage,damage_type)
/obj/mecha/proc/dynabsorbdamage(damage,damage_type)
- return damage*(listgetindex(damage_absorption,damage_type) || 1)
+ return damage*(listgetindex(get_damage_absorption(),damage_type) || 1)
/obj/mecha/airlock_crush(var/crush_damage)
..()
@@ -814,14 +967,24 @@
if(user == occupant)
show_radial_occupant(user)
return
-
+
user.setClickCooldown(user.get_attack_speed())
src.log_message("Attack by hand/paw. Attacker - [user].",1)
+ var/obj/item/mecha_parts/component/armor/ArmC = internal_components[MECH_ARMOR]
+
+ var/temp_deflect_chance = deflect_chance
+
+ if(!ArmC)
+ temp_deflect_chance = 1
+
+ else
+ temp_deflect_chance = round(ArmC.get_efficiency() * ArmC.deflect_chance + (defence_mode ? 25 : 0))
+
if(istype(user,/mob/living/carbon/human))
var/mob/living/carbon/human/H = user
if(H.species.can_shred(user))
- if(!prob(src.deflect_chance))
+ if(!prob(temp_deflect_chance))
src.take_damage(15) //The take_damage() proc handles armor values
if(prob(25)) //Why would they get free internal damage. At least make it a bit RNG.
src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
@@ -838,7 +1001,7 @@
user.visible_message("\The [user] hits \the [src]. Nothing happens.","You hit \the [src] with no visible effect.")
src.log_append_to_last("Armor saved.")
return
- else if ((HULK in user.mutations) && !prob(src.deflect_chance))
+ else if ((HULK in user.mutations) && !prob(temp_deflect_chance))
src.take_damage(15) //The take_damage() proc handles armor values
if(prob(25)) //Hulks punch hard but lets not give them consistent internal damage.
src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
@@ -856,11 +1019,30 @@
//I think this is relative to throws.
/obj/mecha/proc/dynhitby(atom/movable/A)
+ var/obj/item/mecha_parts/component/armor/ArmC = internal_components[MECH_ARMOR]
+
+ var/temp_deflect_chance = deflect_chance
+ var/temp_damage_minimum = damage_minimum
+ var/temp_minimum_penetration = minimum_penetration
+ var/temp_fail_penetration_value = fail_penetration_value
+
+ if(!ArmC)
+ temp_deflect_chance = 0
+ temp_damage_minimum = 0
+ temp_minimum_penetration = 0
+ temp_fail_penetration_value = 1
+
+ else
+ temp_deflect_chance = round(ArmC.get_efficiency() * ArmC.deflect_chance + (defence_mode ? 25 : 0))
+ temp_damage_minimum = round(ArmC.get_efficiency() * ArmC.damage_minimum)
+ temp_minimum_penetration = round(ArmC.get_efficiency() * ArmC.minimum_penetration)
+ temp_fail_penetration_value = round(ArmC.get_efficiency() * ArmC.fail_penetration_value)
+
if(istype(A, /obj/item/mecha_parts/mecha_tracking))
A.forceMove(src)
src.visible_message("The [A] fastens firmly to [src].")
return
- if(prob(src.deflect_chance) || istype(A, /mob))
+ if(prob(temp_deflect_chance) || istype(A, /mob))
src.occupant_message("\The [A] bounces off the armor.")
src.visible_message("\The [A] bounces off \the [src] armor")
src.log_append_to_last("Armor saved.")
@@ -873,18 +1055,18 @@
var/pass_damage = O.throwforce
var/pass_damage_reduc_mod
- if(pass_damage <= damage_minimum)//Too little to go through.
+ if(pass_damage <= temp_damage_minimum)//Too little to go through.
src.occupant_message("\The [A] bounces off the armor.")
src.visible_message("\The [A] bounces off \the [src] armor")
return
- else if(O.armor_penetration < minimum_penetration) //If you don't have enough pen, you won't do full damage
+ else if(O.armor_penetration < temp_minimum_penetration) //If you don't have enough pen, you won't do full damage
src.occupant_message("\The [A] struggles to bypass \the [src] armor.")
src.visible_message("\The [A] struggles to bypass \the [src] armor")
- pass_damage_reduc_mod = fail_penetration_value //This will apply to reduce damage to 2/3 or 66% by default
+ pass_damage_reduc_mod = temp_fail_penetration_value //This will apply to reduce damage to 2/3 or 66% by default
else
- src.occupant_message("\The [A] manages to pierces \the [src] armor.")
- src.visible_message("\The [A] manages to pierces \the [src] armor")
+ src.occupant_message("\The [A] manages to pierce \the [src] armor.")
+// src.visible_message("\The [A] manages to pierce \the [src] armor")
pass_damage_reduc_mod = 1
@@ -911,7 +1093,26 @@
return
/obj/mecha/proc/dynbulletdamage(var/obj/item/projectile/Proj)
- if(prob(src.deflect_chance))
+ var/obj/item/mecha_parts/component/armor/ArmC = internal_components[MECH_ARMOR]
+
+ var/temp_deflect_chance = deflect_chance
+ var/temp_damage_minimum = damage_minimum
+ var/temp_minimum_penetration = minimum_penetration
+ var/temp_fail_penetration_value = fail_penetration_value
+
+ if(!ArmC)
+ temp_deflect_chance = 0
+ temp_damage_minimum = 0
+ temp_minimum_penetration = 0
+ temp_fail_penetration_value = 1
+
+ else
+ temp_deflect_chance = round(ArmC.get_efficiency() * ArmC.deflect_chance + (defence_mode ? 25 : 0))
+ temp_damage_minimum = round(ArmC.get_efficiency() * ArmC.damage_minimum)
+ temp_minimum_penetration = round(ArmC.get_efficiency() * ArmC.minimum_penetration)
+ temp_fail_penetration_value = round(ArmC.get_efficiency() * ArmC.fail_penetration_value)
+
+ if(prob(temp_deflect_chance))
src.occupant_message("The armor deflects incoming projectile.")
src.visible_message("The [src.name] armor deflects the projectile")
src.log_append_to_last("Armor saved.")
@@ -930,19 +1131,19 @@
for(var/obj/item/mecha_parts/mecha_equipment/ME in equipment)
pass_damage = ME.handle_projectile_contact(Proj, pass_damage)
- if(pass_damage < damage_minimum)//too pathetic to really damage you.
+ if(pass_damage < temp_damage_minimum)//too pathetic to really damage you.
src.occupant_message("The armor deflects incoming projectile.")
src.visible_message("The [src.name] armor deflects\the [Proj]")
return
- else if(Proj.armor_penetration < minimum_penetration) //If you don't have enough pen, you won't do full damage
+ else if(Proj.armor_penetration < temp_minimum_penetration) //If you don't have enough pen, you won't do full damage
src.occupant_message("\The [Proj] struggles to pierce \the [src] armor.")
src.visible_message("\The [Proj] struggles to pierce \the [src] armor")
- pass_damage_reduc_mod = fail_penetration_value //This will apply to reduce damage to 2/3 or 66% by default
+ pass_damage_reduc_mod = temp_fail_penetration_value //This will apply to reduce damage to 2/3 or 66% by default
else //You go through completely because you use AP. Nice.
src.occupant_message("\The [Proj] manages to pierce \the [src] armor.")
- src.visible_message("\The [Proj] manages to pierce \the [src] armor")
+// src.visible_message("\The [Proj] manages to pierce \the [src] armor")
pass_damage_reduc_mod = 1
pass_damage = (pass_damage_reduc_mod*pass_damage)//Apply damage reduction before usage.
@@ -961,7 +1162,7 @@
Proj.attack_mob(src.occupant, distance)
hit_occupant = 0
else
- if(pass_damage > internal_damage_minimum) //Only decently painful attacks trigger a chance of mech damage.
+ if(pass_damage > internal_damage_minimum) //Only decently painful attacks trigger a chance of mech damage.
src.check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT), 1)
Proj.penetrating--
@@ -974,24 +1175,34 @@
//This refer to whenever you are caught in an explosion.
/obj/mecha/ex_act(severity)
+ var/obj/item/mecha_parts/component/armor/ArmC = internal_components[MECH_ARMOR]
+
+ var/temp_deflect_chance = deflect_chance
+
+ if(!ArmC)
+ temp_deflect_chance = 0
+
+ else
+ temp_deflect_chance = round(ArmC.get_efficiency() * ArmC.deflect_chance + (defence_mode ? 25 : 0))
+
src.log_message("Affected by explosion of severity: [severity].",1)
- if(prob(src.deflect_chance))
+ if(prob(temp_deflect_chance))
severity++
src.log_append_to_last("Armor saved, changing severity to [severity].")
switch(severity)
if(1.0)
- qdel(src)
+ src.take_damage(initial(src.health), "bomb")
if(2.0)
if (prob(30))
- qdel(src)
+ src.take_damage(initial(src.health), "bomb")
else
- src.take_damage(initial(src.health)/2) //The take_damage() proc handles armor values
+ src.take_damage(initial(src.health)/2, "bomb")
src.check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT),1)
if(3.0)
if (prob(5))
qdel(src)
else
- src.take_damage(initial(src.health)/5) //The take_damage() proc handles armor values
+ src.take_damage(initial(src.health)/5, "bomb")
src.check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT),1)
return
@@ -1038,20 +1249,39 @@
src.log_message("Attacked by [W]. Attacker - [user]")
var/pass_damage_reduc_mod //Modifer for failing to bring AP.
- if(prob(src.deflect_chance)) //Does your attack get deflected outright.
+ var/obj/item/mecha_parts/component/armor/ArmC = internal_components[MECH_ARMOR]
+
+ var/temp_deflect_chance = deflect_chance
+ var/temp_damage_minimum = damage_minimum
+ var/temp_minimum_penetration = minimum_penetration
+ var/temp_fail_penetration_value = fail_penetration_value
+
+ if(!ArmC)
+ temp_deflect_chance = 0
+ temp_damage_minimum = 0
+ temp_minimum_penetration = 0
+ temp_fail_penetration_value = 1
+
+ else
+ temp_deflect_chance = round(ArmC.get_efficiency() * ArmC.deflect_chance + (defence_mode ? 25 : 0))
+ temp_damage_minimum = round(ArmC.get_efficiency() * ArmC.damage_minimum)
+ temp_minimum_penetration = round(ArmC.get_efficiency() * ArmC.minimum_penetration)
+ temp_fail_penetration_value = round(ArmC.get_efficiency() * ArmC.fail_penetration_value)
+
+ if(prob(temp_deflect_chance)) //Does your attack get deflected outright.
src.occupant_message("\The [W] bounces off [src.name].")
to_chat(user, "\The [W] bounces off [src.name].")
src.log_append_to_last("Armor saved.")
- else if(W.force < damage_minimum) //Is your attack too PATHETIC to do anything. 3 damage to a person shouldn't do anything to a mech.
+ else if(W.force < temp_damage_minimum) //Is your attack too PATHETIC to do anything. 3 damage to a person shouldn't do anything to a mech.
src.occupant_message("\The [W] bounces off the armor.")
src.visible_message("\The [W] bounces off \the [src] armor")
return
- else if(W.armor_penetration < minimum_penetration) //If you don't have enough pen, you won't do full damage
+ else if(W.armor_penetration < temp_minimum_penetration) //If you don't have enough pen, you won't do full damage
src.occupant_message("\The [W] struggles to bypass \the [src] armor.")
src.visible_message("\The [W] struggles to bypass \the [src] armor")
- pass_damage_reduc_mod = fail_penetration_value //This will apply to reduce damage to 2/3 or 66% by default
+ pass_damage_reduc_mod = temp_fail_penetration_value //This will apply to reduce damage to 2/3 or 66% by default
else
pass_damage_reduc_mod = 1 //Just making sure.
@@ -1080,6 +1310,11 @@
to_chat(user, "[src]-MMI interface initialization failed.")
return
+ if(istype(W, /obj/item/device/robotanalyzer))
+ var/obj/item/device/robotanalyzer/RA = W
+ RA.do_scan(src, user)
+ return
+
if(istype(W, /obj/item/mecha_parts/mecha_equipment))
var/obj/item/mecha_parts/mecha_equipment/E = W
spawn()
@@ -1090,6 +1325,20 @@
else
to_chat(user, "You were unable to attach [W] to [src]")
return
+
+ if(istype(W, /obj/item/mecha_parts/component) && state == MECHA_CELL_OUT)
+ var/obj/item/mecha_parts/component/MC = W
+ spawn()
+ if(MC.attach(src))
+ user.drop_item()
+ MC.forceMove(src)
+ user.visible_message("[user] installs \the [W] in \the [src]", "You install \the [W] in \the [src].")
+ return
+
+ if(istype(W, /obj/item/weapon/card/robot))
+ var/obj/item/weapon/card/robot/RoC = W
+ return attackby(RoC.dummy_card, user)
+
if(istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda))
if(add_req_access || maint_access)
if(internals_access_allowed(usr))
@@ -1106,23 +1355,39 @@
else
to_chat(user, "Maintenance protocols disabled by operator.")
else if(W.is_wrench())
- if(state==1)
- state = 2
+ if(state==MECHA_BOLTS_SECURED)
+ state = MECHA_PANEL_LOOSE
to_chat(user, "You undo the securing bolts.")
- else if(state==2)
- state = 1
+ else if(state==MECHA_PANEL_LOOSE)
+ state = MECHA_BOLTS_SECURED
to_chat(user, "You tighten the securing bolts.")
return
else if(W.is_crowbar())
- if(state==2)
- state = 3
+ if(state==MECHA_PANEL_LOOSE)
+ state = MECHA_CELL_OPEN
to_chat(user, "You open the hatch to the power unit")
- else if(state==3)
- state=2
+ else if(state==MECHA_CELL_OPEN)
+ state=MECHA_PANEL_LOOSE
to_chat(user, "You close the hatch to the power unit")
+ else if(state==MECHA_CELL_OUT)
+ var/list/removable_components = list()
+ for(var/slot in internal_components)
+ var/obj/item/mecha_parts/component/MC = internal_components[slot]
+ if(istype(MC))
+ removable_components[MC.name] = MC
+ else
+ to_chat(user, "\The [src] appears to be missing \the [slot].")
+
+ var/remove = input(user, "Which component do you want to pry out?", "Remove Component") as null|anything in removable_components
+ if(!remove)
+ return
+
+ var/obj/item/mecha_parts/component/RmC = removable_components[remove]
+ RmC.detach()
+
return
else if(istype(W, /obj/item/stack/cable_coil))
- if(state == 3 && hasInternalDamage(MECHA_INT_SHORT_CIRCUIT))
+ if(state >= MECHA_CELL_OPEN && hasInternalDamage(MECHA_INT_SHORT_CIRCUIT))
var/obj/item/stack/cable_coil/CC = W
if(CC.use(2))
clearInternalDamage(MECHA_INT_SHORT_CIRCUIT)
@@ -1134,19 +1399,19 @@
if(hasInternalDamage(MECHA_INT_TEMP_CONTROL))
clearInternalDamage(MECHA_INT_TEMP_CONTROL)
to_chat(user, "You repair the damaged temperature controller.")
- else if(state==3 && src.cell)
+ else if(state==MECHA_CELL_OPEN && src.cell)
src.cell.forceMove(src.loc)
src.cell = null
- state = 4
+ state = MECHA_CELL_OUT
to_chat(user, "You unscrew and pry out the powercell.")
src.log_message("Powercell removed")
- else if(state==4 && src.cell)
- state=3
+ else if(state==MECHA_CELL_OUT && src.cell)
+ state=MECHA_CELL_OPEN
to_chat(user, "You screw the cell in place")
return
else if(istype(W, /obj/item/device/multitool))
- if(state>=3 && src.occupant)
+ if(state>=MECHA_CELL_OPEN && src.occupant)
to_chat(user, "You attempt to eject the pilot using the maintenance controls.")
if(src.occupant.stat)
src.go_out()
@@ -1158,7 +1423,7 @@
return
else if(istype(W, /obj/item/weapon/cell))
- if(state==4)
+ if(state==MECHA_CELL_OUT)
if(!src.cell)
to_chat(user, "You install the powercell")
user.drop_item()
@@ -1191,6 +1456,28 @@
user.visible_message("[user] attaches [W] to [src].", "You attach [W] to [src]")
return
+ else if(istype(W,/obj/item/stack/nanopaste))
+ if(state >= MECHA_PANEL_LOOSE)
+ var/obj/item/stack/nanopaste/NP = W
+
+ for(var/slot in internal_components)
+ var/obj/item/mecha_parts/component/C = internal_components[slot]
+
+ if(C)
+
+ if(C.integrity < C.max_integrity)
+ while(C.integrity < C.max_integrity && NP && do_after(user, 1 SECOND, src))
+ if(NP.use(1))
+ C.adjust_integrity(10)
+
+ to_chat(user, "You repair damage to \the [C].")
+
+ return
+
+ else
+ to_chat(user, "You can't reach \the [src]'s internal components.")
+ return
+
else
call((proc_res["dynattackby"]||src), "dynattackby")(W,user)
/*
@@ -1299,7 +1586,8 @@
return
/obj/mecha/remove_air(amount)
- if(use_internal_tank)
+ var/obj/item/mecha_parts/component/gas/GC = internal_components[MECH_GAS]
+ if(use_internal_tank && (GC && prob(GC.get_efficiency() * 100)))
return cabin_air.remove(amount)
else
var/turf/T = get_turf(src)
@@ -1314,7 +1602,8 @@
/obj/mecha/proc/return_pressure()
. = 0
- if(use_internal_tank)
+ var/obj/item/mecha_parts/component/gas/GC = internal_components[MECH_GAS]
+ if(use_internal_tank && (GC && prob(GC.get_efficiency() * 100)))
. = cabin_air.return_pressure()
else
var/datum/gas_mixture/t_air = get_turf_air()
@@ -1325,7 +1614,8 @@
//skytodo: //No idea what you want me to do here, mate.
/obj/mecha/proc/return_temperature()
. = 0
- if(use_internal_tank)
+ var/obj/item/mecha_parts/component/gas/GC = internal_components[MECH_GAS]
+ if(use_internal_tank && (GC && prob(GC.get_efficiency() * 100)))
. = cabin_air.temperature
else
var/datum/gas_mixture/t_air = get_turf_air()
@@ -1380,13 +1670,17 @@
set category = "Exosuit Interface"
set src = usr.loc
set popup_menu = 0
-
+
if(!occupant)
return
-
+
if(usr != occupant)
return
-
+
+ var/obj/item/mecha_parts/component/gas/GC = internal_components[MECH_GAS]
+ if(!GC)
+ return
+
for(var/turf/T in locs)
var/obj/machinery/atmospherics/portables_connector/possible_port = locate(/obj/machinery/atmospherics/portables_connector) in T
if(possible_port)
@@ -1407,13 +1701,13 @@
set category = "Exosuit Interface"
set src = usr.loc
set popup_menu = 0
-
+
if(!occupant)
return
-
+
if(usr != occupant)
return
-
+
if(disconnect())
occupant_message("[name] disconnects from the port.")
verbs -= /obj/mecha/verb/disconnect_from_port
@@ -1449,6 +1743,16 @@
/obj/mecha/proc/internal_tank()
if(usr!=src.occupant)
return
+
+ var/obj/item/mecha_parts/component/gas/GC = internal_components[MECH_GAS]
+ if(!GC)
+ to_chat(occupant, "The life support systems don't seem to respond.")
+ return
+
+ if(!prob(GC.get_efficiency() * 100))
+ to_chat(occupant, "\The [GC] shudders and barks, before returning to how it was before.")
+ return
+
use_internal_tank = !use_internal_tank
src.occupant_message("Now taking air from [use_internal_tank?"internal airtank":"environment"].")
src.log_message("Now taking air from [use_internal_tank?"internal airtank":"environment"].")
@@ -1579,6 +1883,8 @@
verbs -= /obj/mecha/verb/toggle_phasing
if(!switch_dmg_type_possible)
verbs -= /obj/mecha/verb/switch_damtype
+ if(!cloak_possible)
+ verbs -= /obj/mecha/verb/toggle_cloak
occupant.in_enclosed_vehicle = 1 //Useful for when you need to know if someone is in a mecho.
update_cell_alerts()
@@ -1697,8 +2003,13 @@
/obj/mecha/proc/internals_access_allowed(mob/living/carbon/human/H)
- for(var/atom/ID in list(H.get_active_hand(), H.wear_id, H.belt))
- if(src.check_access(ID,src.internals_req_access))
+ if(istype(H))
+ for(var/atom/ID in list(H.get_active_hand(), H.wear_id, H.belt))
+ if(src.check_access(ID,src.internals_req_access))
+ return 1
+ else if(istype(H, /mob/living/silicon/robot))
+ var/mob/living/silicon/robot/R = H
+ if(src.check_access(R.idcard,src.internals_req_access))
return 1
return 0
@@ -1799,9 +2110,15 @@
var/tank_pressure = internal_tank ? round(internal_tank.return_pressure(),0.01) : "None"
var/tank_temperature = internal_tank ? internal_tank.return_temperature() : "Unknown"
var/cabin_pressure = round(return_pressure(),0.01)
+
+ var/obj/item/mecha_parts/component/hull/HC = internal_components[MECH_HULL]
+ var/obj/item/mecha_parts/component/armor/AC = internal_components[MECH_ARMOR]
+
var/output = {"[report_internal_damage()]
+ Armor Integrity: [AC?"[round(AC.integrity / AC.max_integrity * 100, 0.1)]%":"ARMOR MISSING"]
+ Hull Integrity: [HC?"[round(HC.integrity / HC.max_integrity * 100, 0.1)]%":"HULL MISSING"]
[integrity<30?"DAMAGE LEVEL CRITICAL
":null]
- Integrity: [integrity]%
+ Chassis Integrity: [integrity]%
Powercell charge: [isnull(cell_charge)?"No powercell installed":"[cell.percent()]%"]
Air source: [use_internal_tank?"Internal Airtank":"Environment"]
Airtank pressure: [tank_pressure]kPa
@@ -1888,6 +2205,7 @@
output += "Universal Module: [W.name] Detach
"
for(var/obj/item/mecha_parts/mecha_equipment/W in special_equipment)
output += "Special Module: [W.name] Detach
"
+<<<<<<< HEAD
for(var/obj/item/mecha_parts/mecha_equipment/W in micro_utility_equipment) // VOREstation Edit - Adds micro equipent to the menu
output += "Micro Utility Module: [W.name] Detach
"
for(var/obj/item/mecha_parts/mecha_equipment/W in micro_weapon_equipment)
@@ -1901,6 +2219,15 @@
Available special slots: [max_special_equip-special_equipment.len]
"}
+=======
+ output += {"Available hull slots: [max_hull_equip-hull_equipment.len]
+ Available weapon slots: [max_weapon_equip-weapon_equipment.len]
+ Available utility slots: [max_utility_equip-utility_equipment.len]
+ Available universal slots: [max_universal_equip-universal_equipment.len]
+ Available special slots: [max_special_equip-special_equipment.len]
+
+ "}
+>>>>>>> 282b42d... Exosuit Modular Internals, The Squeakening (#7329)
return output
/obj/mecha/proc/get_equipment_list() //outputs mecha equipment list in html
@@ -2109,15 +2436,15 @@
if(!in_range(src, usr)) return
var/mob/user = top_filter.getMob("user")
if(user)
- if(state==0)
- state = 1
+ if(state==MECHA_OPERATING)
+ state = MECHA_BOLTS_SECURED
to_chat(user, "The securing bolts are now exposed.")
- else if(state==1)
- state = 0
+ else if(state==MECHA_BOLTS_SECURED)
+ state = MECHA_OPERATING
to_chat(user, "The securing bolts are now hidden.")
output_maintenance_dialog(top_filter.getObj("id_card"),user)
return
- if(href_list["set_internal_tank_valve"] && state >=1)
+ if(href_list["set_internal_tank_valve"] && state >=MECHA_BOLTS_SECURED)
if(!in_range(src, usr)) return
var/mob/user = top_filter.getMob("user")
if(user)
@@ -2125,7 +2452,7 @@
if(new_pressure)
internal_tank_valve = new_pressure
to_chat(user, "The internal pressure valve has been set to [internal_tank_valve]kPa.")
- if(href_list["remove_passenger"] && state >= 1)
+ if(href_list["remove_passenger"] && state >= MECHA_BOLTS_SECURED)
var/mob/user = top_filter.getMob("user")
var/list/passengers = list()
for (var/obj/item/mecha_parts/mecha_equipment/tool/passenger/P in contents)
@@ -2284,6 +2611,13 @@
/obj/mecha/proc/dynusepower(amount)
update_cell_alerts()
+ var/obj/item/mecha_parts/component/electrical/EC = internal_components[MECH_ELECTRIC]
+
+ if(EC)
+ amount = amount * (2 - EC.get_efficiency()) * EC.charge_cost_mod
+ else
+ amount *= 5
+
if(get_charge())
cell.use(amount)
return 1
@@ -2291,6 +2625,13 @@
/obj/mecha/proc/give_power(amount)
update_cell_alerts()
+ var/obj/item/mecha_parts/component/electrical/EC = internal_components[MECH_ELECTRIC]
+
+ if(!EC)
+ amount /= 4
+ else
+ amount *= EC.get_efficiency()
+
if(!isnull(get_charge()))
cell.give(amount)
return 1
@@ -2306,6 +2647,19 @@
//This is for mobs mostly.
/obj/mecha/attack_generic(var/mob/user, var/damage, var/attack_message)
+ var/obj/item/mecha_parts/component/armor/ArmC = internal_components[MECH_ARMOR]
+
+ var/temp_deflect_chance = deflect_chance
+ var/temp_damage_minimum = damage_minimum
+
+ if(!ArmC)
+ temp_deflect_chance = 1
+ temp_damage_minimum = 0
+
+ else
+ temp_deflect_chance = round(ArmC.get_efficiency() * ArmC.deflect_chance + (defence_mode ? 25 : 0))
+ temp_damage_minimum = round(ArmC.get_efficiency() * ArmC.damage_minimum)
+
user.setClickCooldown(user.get_attack_speed())
if(!damage)
return 0
@@ -2313,14 +2667,14 @@
src.log_message("Attacked. Attacker - [user].",1)
user.do_attack_animation(src)
- if(prob(src.deflect_chance))//Deflected
+ if(prob(temp_deflect_chance))//Deflected
src.log_append_to_last("Armor saved.")
src.occupant_message("\The [user]'s attack is stopped by the armor.")
visible_message("\The [user] rebounds off [src.name]'s armor!")
user.attack_log += text("\[[time_stamp()]\] attacked [src.name]")
playsound(src, 'sound/weapons/slash.ogg', 50, 1, -1)
- else if(damage < damage_minimum)//Pathetic damage levels just don't harm MECH.
+ else if(damage < temp_damage_minimum)//Pathetic damage levels just don't harm MECH.
src.occupant_message("\The [user]'s doesn't dent \the [src] paint.")
src.visible_message("\The [user]'s attack doesn't dent \the [src] armor")
src.log_append_to_last("Armor saved.")
diff --git a/code/game/mecha/mecha_actions.dm b/code/game/mecha/mecha_actions.dm
index 33307c77d3..c70c3b9b83 100644
--- a/code/game/mecha/mecha_actions.dm
+++ b/code/game/mecha/mecha_actions.dm
@@ -3,7 +3,7 @@
//THIS FILE CONTAINS THE CODE TO ADD THE HUD BUTTONS AND THE MECH ACTIONS THEMSELVES.
//
//
-// I better get some free food for this..
+// I better get some free food for this..
@@ -35,7 +35,9 @@
phasing_action.Grant(user, src)
if(switch_dmg_type_possible)
switch_damtype_action.Grant(user, src)
-
+ if(cloak_possible)
+ cloak_action.Grant(user, src)
+
/obj/mecha/proc/RemoveActions(mob/living/user, human_occupant = 0)
if(human_occupant)
eject_action.Remove(user, src)
@@ -51,8 +53,8 @@
thrusters_action.Remove(user, src)
phasing_action.Remove(user, src)
switch_damtype_action.Remove(user, src)
- overload_action.Remove(user, src)
-
+ overload_action.Remove(user, src)
+ cloak_action.Remove(user, src)
//
@@ -242,6 +244,15 @@
+/datum/action/innate/mecha/mech_toggle_cloaking
+ name = "Toggle Mech phasing"
+ button_icon_state = "mech_phasing_off"
+
+/datum/action/innate/mecha/mech_toggle_cloaking/Activate()
+ button_icon_state = "mech_phasing_[chassis.cloaked ? "off" : "on"]"
+ button.UpdateIcon()
+ chassis.toggle_cloaking()
+
/////
@@ -293,12 +304,10 @@
return
if(overload)
overload = 0
- step_in = initial(step_in)
step_energy_drain = initial(step_energy_drain)
src.occupant_message("You disable leg actuators overload.")
else
overload = 1
- step_in = min(1, round(step_in/2))
step_energy_drain = step_energy_drain*overload_coeff
src.occupant_message("You enable leg actuators overload.")
src.log_message("Toggled leg actuators overload.")
@@ -324,7 +333,7 @@
if(smoke_ready)
smoke_reserve-- //Remove ammo
src.occupant_message("Smoke fired. [smoke_reserve] usages left.")
-
+
var/datum/effect/effect/system/smoke_spread/smoke = new /datum/effect/effect/system/smoke_spread()
smoke.attach(src)
smoke.set_up(10, 0, usr.loc)
@@ -422,6 +431,25 @@
return
+/obj/mecha/verb/toggle_cloak()
+ set category = "Exosuit Interface"
+ set name = "Toggle cloaking"
+ set src = usr.loc
+ set popup_menu = 0
+ toggle_cloaking()
+
+/obj/mecha/proc/toggle_cloaking()
+ if(usr!=src.occupant)
+ return
+
+ if(cloaked)
+ uncloak()
+ else
+ cloak()
+
+ src.occupant_message("En":"#f00\">Dis"]abled cloaking.")
+ return
+
/obj/mecha/verb/toggle_weapons_only_cycle()
set category = "Exosuit Interface"
set name = "Toggle weapons only cycling"
@@ -435,4 +463,3 @@
weapons_only_cycle = !weapons_only_cycle
src.occupant_message("En":"#f00\">Dis"]abled weapons only cycling.")
return
-
diff --git a/code/game/mecha/medical/medical.dm b/code/game/mecha/medical/medical.dm
index 6e9dee5047..973ddec3fc 100644
--- a/code/game/mecha/medical/medical.dm
+++ b/code/game/mecha/medical/medical.dm
@@ -9,6 +9,14 @@
cargo_capacity = 1
+ starting_components = list(
+ /obj/item/mecha_parts/component/hull,
+ /obj/item/mecha_parts/component/actuator,
+ /obj/item/mecha_parts/component/armor/lightweight,
+ /obj/item/mecha_parts/component/gas,
+ /obj/item/mecha_parts/component/electrical
+ )
+
/obj/mecha/medical/Initialize()
. = ..()
var/turf/T = get_turf(src)
diff --git a/code/game/mecha/medical/odysseus.dm b/code/game/mecha/medical/odysseus.dm
index 00be6d3c3f..dbba0cd251 100644
--- a/code/game/mecha/medical/odysseus.dm
+++ b/code/game/mecha/medical/odysseus.dm
@@ -1,4 +1,4 @@
-/obj/mecha/medical/odysseus/
+/obj/mecha/medical/odysseus
desc = "These exosuits are developed and produced by Vey-Med. (© All rights reserved)."
name = "Odysseus"
catalogue_data = list(
@@ -9,8 +9,8 @@
initial_icon = "odysseus"
step_in = 2
max_temperature = 15000
- health = 120
- maxhealth = 120
+ health = 70
+ maxhealth = 70
wreckage = /obj/effect/decal/mecha_wreckage/odysseus
internal_damage_threshold = 35
deflect_chance = 15
@@ -139,5 +139,5 @@
/obj/mecha/medical/odysseus/old/New()
..()
health = 25
- maxhealth = 100 //Just slightly worse.
+ maxhealth = 50 //Just slightly worse.
cell.charge = rand(0, (cell.charge/2))
\ No newline at end of file
diff --git a/code/game/mecha/working/ripley.dm b/code/game/mecha/working/ripley.dm
index 5bfe3b4395..86405b6934 100644
--- a/code/game/mecha/working/ripley.dm
+++ b/code/game/mecha/working/ripley.dm
@@ -14,6 +14,14 @@
minimum_penetration = 10
+ starting_components = list(
+ /obj/item/mecha_parts/component/hull/durable,
+ /obj/item/mecha_parts/component/actuator,
+ /obj/item/mecha_parts/component/armor/mining,
+ /obj/item/mecha_parts/component/gas,
+ /obj/item/mecha_parts/component/electrical
+ )
+
/obj/mecha/working/ripley/Destroy()
for(var/atom/movable/A in src.cargo)
A.loc = loc
diff --git a/code/game/objects/items/weapons/storage/boxes.dm b/code/game/objects/items/weapons/storage/boxes.dm
index 3ef882c381..96e4c87da3 100644
--- a/code/game/objects/items/weapons/storage/boxes.dm
+++ b/code/game/objects/items/weapons/storage/boxes.dm
@@ -199,6 +199,16 @@
/obj/item/weapon/storage/box/empshells/large
starts_with = list(/obj/item/ammo_casing/a12g/emp = 16)
+/obj/item/weapon/storage/box/flechetteshells
+ name = "box of shotgun flechettes"
+ desc = "It has a picture of a gun and several warning symbols on the front.
WARNING: Live ammunition. Misuse may result in serious injury or death."
+ icon_state = "lethalslug_box"
+ item_state_slots = list(slot_r_hand_str = "syringe_kit", slot_l_hand_str = "syringe_kit")
+ starts_with = list(/obj/item/ammo_casing/a12g/flechette = 8)
+
+/obj/item/weapon/storage/box/flechetteshells/large
+ starts_with = list(/obj/item/ammo_casing/a12g/flechette = 16)
+
/obj/item/weapon/storage/box/sniperammo
name = "box of 14.5mm shells"
desc = "It has a picture of a gun and several warning symbols on the front.
WARNING: Live ammunition. Misuse may result in serious injury or death."
diff --git a/code/modules/mob/living/silicon/robot/analyzer.dm b/code/modules/mob/living/silicon/robot/analyzer.dm
index f1b2d76eec..e946c7999c 100644
--- a/code/modules/mob/living/silicon/robot/analyzer.dm
+++ b/code/modules/mob/living/silicon/robot/analyzer.dm
@@ -34,6 +34,8 @@
scan_type = "robot"
else if(istype(M, /mob/living/carbon/human))
scan_type = "prosthetics"
+ else if(istype(M, /obj/mecha))
+ scan_type = "mecha"
else
to_chat(user, "You can't analyze non-robotic things!")
return
@@ -95,5 +97,37 @@
if(!organ_found)
to_chat(user, "No prosthetics located.")
+ if("mecha")
+
+ var/obj/mecha/Mecha = M
+
+ var/integrity = Mecha.health/initial(Mecha.health)*100
+ var/cell_charge = Mecha.get_charge()
+ var/tank_pressure = Mecha.internal_tank ? round(Mecha.internal_tank.return_pressure(),0.01) : "None"
+ var/tank_temperature = Mecha.internal_tank ? Mecha.internal_tank.return_temperature() : "Unknown"
+ var/cabin_pressure = round(Mecha.return_pressure(),0.01)
+
+ var/output = {"Analyzing Results for \the [Mecha]:
+ Chassis Integrity: [integrity]%
+ Powercell charge: [isnull(cell_charge)?"No powercell installed":"[Mecha.cell.percent()]%"]
+ Air source: [Mecha.use_internal_tank?"Internal Airtank":"Environment"]
+ Airtank pressure: [tank_pressure]kPa
+ Airtank temperature: [tank_temperature]K|[tank_temperature - T0C]°C
+ Cabin pressure: [cabin_pressure>WARNING_HIGH_PRESSURE ? "[cabin_pressure]": cabin_pressure]kPa
+ Cabin temperature: [Mecha.return_temperature()]K|[Mecha.return_temperature() - T0C]°C
+ DNA Lock: [Mecha.dna?"Mecha.dna":"Not Found"]
+ "}
+
+ to_chat(user, output)
+ to_chat(user, "
")
+ to_chat(user, "Internal Diagnostics:")
+ for(var/slot in Mecha.internal_components)
+ var/obj/item/mecha_parts/component/MC = Mecha.internal_components[slot]
+ to_chat(user, "[MC?"[slot]: [MC] [round((MC.integrity / MC.max_integrity) * 100, 0.1)]% integrity. [MC.get_efficiency() * 100] Operational capacity.":"[slot]: Component Not Found"]")
+
+ to_chat(user, "
")
+ to_chat(user, "General Statistics:")
+ to_chat(user, "Movement Weight: [Mecha.get_step_delay()]
")
+
src.add_fingerprint(user)
return
diff --git a/code/modules/projectiles/ammunition/magazines.dm b/code/modules/projectiles/ammunition/magazines.dm
index 7ccdbfc9ba..1d08811bae 100644
--- a/code/modules/projectiles/ammunition/magazines.dm
+++ b/code/modules/projectiles/ammunition/magazines.dm
@@ -88,6 +88,10 @@
name = "magazine (.45 AP)"
ammo_type = /obj/item/ammo_casing/a45/ap
+/obj/item/ammo_magazine/m45/hp
+ name = "magazine (.45 HP)"
+ ammo_type = /obj/item/ammo_casing/a45/hp
+
/obj/item/ammo_magazine/box/emp/b45
name = "ammunition box (.45 haywire)"
ammo_type = /obj/item/ammo_casing/a45/emp
@@ -293,6 +297,11 @@
name = "top mounted magazine (9mm practice)"
ammo_type = /obj/item/ammo_casing/a9mm/practice
+/obj/item/ammo_magazine/m9mmt/ap
+ name = "top mounted magazine (9mm armor piercing)"
+ ammo_type = /obj/item/ammo_casing/a9mm/ap
+ matter = list(DEFAULT_WALL_MATERIAL = 1000, MAT_PLASTEEL = 2000)
+
/obj/item/ammo_magazine/m9mmp90
name = "large capacity top mounted magazine (9mm armor-piercing)"
icon_state = "p90"
diff --git a/code/modules/projectiles/ammunition/rounds.dm b/code/modules/projectiles/ammunition/rounds.dm
index b83d7ad235..fa6c5d21aa 100644
--- a/code/modules/projectiles/ammunition/rounds.dm
+++ b/code/modules/projectiles/ammunition/rounds.dm
@@ -131,6 +131,7 @@
desc = "A .45 Armor-Piercing bullet casing."
icon_state = "r-casing"
projectile_type = /obj/item/projectile/bullet/pistol/medium/ap
+ matter = list(DEFAULT_WALL_MATERIAL = 50, MAT_PLASTEEL = 25)
/obj/item/ammo_casing/a45/practice
desc = "A .45 practice bullet casing."
@@ -160,6 +161,7 @@
/obj/item/ammo_casing/a45/hp
desc = "A .45 hollow-point bullet casing."
projectile_type = /obj/item/projectile/bullet/pistol/medium/hp
+ matter = list(DEFAULT_WALL_MATERIAL = 60, MAT_PLASTIC = 15)
/*
* 10mm
@@ -246,6 +248,14 @@
// projectile_type = /obj/item/projectile/bullet/shotgun/ion
matter = list(DEFAULT_WALL_MATERIAL = 360, "uranium" = 240)
+/obj/item/ammo_casing/a12g/flechette
+ name = "shotgun flechette"
+ desc = "A 12 gauge flechette cartidge, also known as nailshot."
+ icon_state = "slshell"
+ caliber = "12g"
+ projectile_type = /obj/item/projectile/scatter/flechette
+ matter = list(DEFAULT_WALL_MATERIAL = 360, MAT_PLASTEEL = 100)
+
/*
* 7.62mm
*/
diff --git a/code/modules/projectiles/projectile/scatter.dm b/code/modules/projectiles/projectile/scatter.dm
index 4b0511d0b4..b3900f8429 100644
--- a/code/modules/projectiles/projectile/scatter.dm
+++ b/code/modules/projectiles/projectile/scatter.dm
@@ -27,6 +27,10 @@
/obj/item/projectile/bullet/pellet/shotgun/flak = 3
)
+/*
+ * Energy
+ */
+
/obj/item/projectile/scatter/laser
damage = 40
@@ -61,6 +65,12 @@
/obj/item/projectile/bullet/shotgun/ion = 3
)
+
+/*
+ * Flame
+ */
+
+
/obj/item/projectile/scatter/flamethrower
damage = 5
submunition_spread_max = 100
@@ -70,3 +80,19 @@
submunitions = list(
/obj/item/projectile/bullet/incendiary/flamethrower/tiny = 7
)
+
+
+/*
+ * Ballistic
+ */
+
+
+/obj/item/projectile/scatter/flechette
+ damage = 60
+
+ submunition_spread_max = 40
+ submunition_spread_min = 10
+
+ submunitions = list(
+ /obj/item/projectile/bullet/magnetic/flechette/small = 4
+ )
diff --git a/code/modules/research/circuitprinter.dm b/code/modules/research/circuitprinter.dm
index 468c7ff6bb..d0aaebb7d8 100644
--- a/code/modules/research/circuitprinter.dm
+++ b/code/modules/research/circuitprinter.dm
@@ -16,7 +16,7 @@ using metal and glass, it uses glass and reagents (usually sulphuric acid).
var/mat_efficiency = 1
var/speed = 1
- materials = list(DEFAULT_WALL_MATERIAL = 0, "glass" = 0, MAT_PLASTEEL = 0, "plastic" = 0, MAT_GRAPHITE, "gold" = 0, "silver" = 0, "osmium" = 0, MAT_LEAD = 0, "phoron" = 0, "uranium" = 0, "diamond" = 0, MAT_DURASTEEL = 0, MAT_VERDANTIUM = 0, MAT_MORPHIUM = 0, MAT_METALHYDROGEN = 0, MAT_SUPERMATTER = 0)
+ materials = list(DEFAULT_WALL_MATERIAL = 0, "glass" = 0, MAT_PLASTEEL = 0, "plastic" = 0, MAT_GRAPHITE = 0, "gold" = 0, "silver" = 0, "osmium" = 0, MAT_LEAD = 0, "phoron" = 0, "uranium" = 0, "diamond" = 0, MAT_DURASTEEL = 0, MAT_VERDANTIUM = 0, MAT_MORPHIUM = 0, MAT_METALHYDROGEN = 0, MAT_SUPERMATTER = 0)
hidden_materials = list(MAT_PLASTEEL, MAT_DURASTEEL, MAT_GRAPHITE, MAT_VERDANTIUM, MAT_MORPHIUM, MAT_METALHYDROGEN, MAT_SUPERMATTER)
diff --git a/code/modules/research/designs/circuits/circuits.dm b/code/modules/research/designs/circuits/circuits.dm
index e2479a8e1c..425223ffe7 100644
--- a/code/modules/research/designs/circuits/circuits.dm
+++ b/code/modules/research/designs/circuits/circuits.dm
@@ -493,6 +493,8 @@ CIRCUITS BELOW
name = "'Durand' central control"
id = "durand_main"
req_tech = list(TECH_DATA = 4)
+ materials = list("glass" = 2000, MAT_GRAPHITE = 1250)
+ chemicals = list("pacid" = 20)
build_path = /obj/item/weapon/circuitboard/mecha/durand/main
sort_string = "NAADA"
@@ -500,6 +502,8 @@ CIRCUITS BELOW
name = "'Durand' peripherals control"
id = "durand_peri"
req_tech = list(TECH_DATA = 4)
+ materials = list("glass" = 2000, MAT_GRAPHITE = 1250)
+ chemicals = list("pacid" = 20)
build_path = /obj/item/weapon/circuitboard/mecha/durand/peripherals
sort_string = "NAADB"
@@ -507,6 +511,8 @@ CIRCUITS BELOW
name = "'Durand' weapon control and targeting"
id = "durand_targ"
req_tech = list(TECH_DATA = 4, TECH_COMBAT = 2)
+ materials = list("glass" = 2000, MAT_GRAPHITE = 1250)
+ chemicals = list("pacid" = 20)
build_path = /obj/item/weapon/circuitboard/mecha/durand/targeting
sort_string = "NAADC"
diff --git a/code/modules/research/designs/weapons.dm b/code/modules/research/designs/weapons.dm
index 13d6036edd..f57b285118 100644
--- a/code/modules/research/designs/weapons.dm
+++ b/code/modules/research/designs/weapons.dm
@@ -100,14 +100,23 @@
sort_string = "MABBA"
/datum/design/item/weapon/ballistic/ammo/stunshell
- name = "stun shell"
+ name = "stun shells"
desc = "A stunning shell for a shotgun."
id = "stunshell"
req_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 3)
materials = list(DEFAULT_WALL_MATERIAL = 4000)
- build_path = /obj/item/ammo_casing/a12g/stunshell
+ build_path = /obj/item/weapon/storage/box/stunshells
sort_string = "MABBB"
+/datum/design/item/weapon/ballistic/ammo/empshell
+ name = "emp shells"
+ desc = "An electromagnetic shell for a shotgun."
+ id = "empshell"
+ req_tech = list(TECH_COMBAT = 4, TECH_MAGNET = 3)
+ materials = list(DEFAULT_WALL_MATERIAL = 4000, MAT_URANIUM = 1000)
+ build_path = /obj/item/weapon/storage/box/empshells
+ sort_string = "MABBC"
+
// Phase weapons
/datum/design/item/weapon/phase/AssembleDesignName()
diff --git a/code/modules/research/mechfab_designs.dm b/code/modules/research/mechfab_designs.dm
index 7316c42179..899b5fd9db 100644
--- a/code/modules/research/mechfab_designs.dm
+++ b/code/modules/research/mechfab_designs.dm
@@ -177,57 +177,57 @@
name = "Durand Chassis"
id = "durand_chassis"
build_path = /obj/item/mecha_parts/chassis/durand
- time = 10
- materials = list(DEFAULT_WALL_MATERIAL = 18750)
+ time = 20
+ materials = list(DEFAULT_WALL_MATERIAL = 18750, MAT_PLASTEEL = 20000)
/datum/design/item/mechfab/durand/torso
name = "Durand Torso"
id = "durand_torso"
build_path = /obj/item/mecha_parts/part/durand_torso
- time = 30
- materials = list(DEFAULT_WALL_MATERIAL = 41250, "glass" = 15000, "silver" = 7500)
+ time = 60
+ materials = list(DEFAULT_WALL_MATERIAL = 41250, MAT_PLASTEEL = 15000, "silver" = 7500)
/datum/design/item/mechfab/durand/head
name = "Durand Head"
id = "durand_head"
build_path = /obj/item/mecha_parts/part/durand_head
- time = 20
+ time = 40
materials = list(DEFAULT_WALL_MATERIAL = 18750, "glass" = 7500, "silver" = 2250)
/datum/design/item/mechfab/durand/left_arm
name = "Durand Left Arm"
id = "durand_left_arm"
build_path = /obj/item/mecha_parts/part/durand_left_arm
- time = 20
+ time = 40
materials = list(DEFAULT_WALL_MATERIAL = 26250, "silver" = 2250)
/datum/design/item/mechfab/durand/right_arm
name = "Durand Right Arm"
id = "durand_right_arm"
build_path = /obj/item/mecha_parts/part/durand_right_arm
- time = 20
+ time = 40
materials = list(DEFAULT_WALL_MATERIAL = 26250, "silver" = 2250)
/datum/design/item/mechfab/durand/left_leg
name = "Durand Left Leg"
id = "durand_left_leg"
build_path = /obj/item/mecha_parts/part/durand_left_leg
- time = 20
+ time = 40
materials = list(DEFAULT_WALL_MATERIAL = 30000, "silver" = 2250)
/datum/design/item/mechfab/durand/right_leg
name = "Durand Right Leg"
id = "durand_right_leg"
build_path = /obj/item/mecha_parts/part/durand_right_leg
- time = 20
+ time = 40
materials = list(DEFAULT_WALL_MATERIAL = 30000, "silver" = 2250)
/datum/design/item/mechfab/durand/armour
name = "Durand Armour Plates"
id = "durand_armour"
build_path = /obj/item/mecha_parts/part/durand_armour
- time = 60
- materials = list(DEFAULT_WALL_MATERIAL = 37500, "uranium" = 7500)
+ time = 90
+ materials = list(DEFAULT_WALL_MATERIAL = 27500, MAT_PLASTEEL = 10000, "uranium" = 7500)
/datum/design/item/mechfab/janus
category = "Janus"
@@ -1038,4 +1038,151 @@
time = 20
req_tech = list(TECH_MATERIAL = 6, TECH_ENGINEERING = 5, TECH_PHORON = 3, TECH_MAGNET = 4, TECH_POWER = 6)
materials = list(DEFAULT_WALL_MATERIAL = 10000, "glass" = 6000, "silver" = 4000)
-
\ No newline at end of file
+
+// Exosuit Internals
+
+/datum/design/item/mechfab/exointernal
+ category = "Exosuit Internals"
+ time = 120
+ req_tech = list(TECH_MATERIAL = 3, TECH_ENGINEERING = 3)
+
+/datum/design/item/mechfab/exointernal/stan_armor
+ name = "Armor Plate (Standard)"
+ category = "Exosuit Internals"
+ id = "exo_int_armor_standard"
+ req_tech = list(TECH_MATERIAL = 2, TECH_ENGINEERING = 2)
+ materials = list(DEFAULT_WALL_MATERIAL = 10000)
+ build_path = /obj/item/mecha_parts/component/armor
+
+/datum/design/item/mechfab/exointernal/light_armor
+ name = "Armor Plate (Lightweight)"
+ category = "Exosuit Internals"
+ id = "exo_int_armor_lightweight"
+ req_tech = list(TECH_MATERIAL = 2, TECH_ENGINEERING = 3)
+ materials = list(DEFAULT_WALL_MATERIAL = 5000, MAT_PLASTIC = 3000)
+ build_path = /obj/item/mecha_parts/component/armor/lightweight
+
+/datum/design/item/mechfab/exointernal/reinf_armor
+ name = "Armor Plate (Reinforced)"
+ category = "Exosuit Internals"
+ id = "exo_int_armor_reinforced"
+ req_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 4)
+ materials = list(DEFAULT_WALL_MATERIAL = 20000, MAT_PLASTEEL = 10000)
+ build_path = /obj/item/mecha_parts/component/armor/reinforced
+
+/datum/design/item/mechfab/exointernal/mining_armor
+ name = "Armor Plate (Blast)"
+ category = "Exosuit Internals"
+ id = "exo_int_armor_blast"
+ req_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 4)
+ materials = list(DEFAULT_WALL_MATERIAL = 20000, MAT_PLASTEEL = 10000)
+ build_path = /obj/item/mecha_parts/component/armor/mining
+
+/datum/design/item/mechfab/exointernal/gygax_armor
+ name = "Armor Plate (Marshal)"
+ category = "Exosuit Internals"
+ id = "exo_int_armor_gygax"
+ req_tech = list(TECH_MATERIAL = 5, TECH_ENGINEERING = 4, TECH_COMBAT = 2)
+ materials = list(DEFAULT_WALL_MATERIAL = 40000, MAT_DIAMOND = 8000)
+ build_path = /obj/item/mecha_parts/component/armor/marshal
+
+/datum/design/item/mechfab/exointernal/darkgygax_armor
+ name = "Armor Plate (Blackops)"
+ category = "Exosuit Internals"
+ id = "exo_int_armor_dgygax"
+ req_tech = list(TECH_MATERIAL = 5, TECH_ENGINEERING = 5, TECH_COMBAT = 4, TECH_ILLEGAL = 2)
+ materials = list(MAT_PLASTEEL = 20000, MAT_DIAMOND = 10000, MAT_GRAPHITE = 20000)
+ build_path = /obj/item/mecha_parts/component/armor/marshal/reinforced
+
+/datum/design/item/mechfab/exointernal/durand_armour
+ name = "Armor Plate (Military)"
+ id = "exo_int_armor_durand"
+ req_tech = list(TECH_MATERIAL = 5, TECH_ENGINEERING = 4, TECH_COMBAT = 2)
+ materials = list(DEFAULT_WALL_MATERIAL = 40000, MAT_PLASTEEL = 9525, "uranium" = 8000)
+ build_path = /obj/item/mecha_parts/component/armor/military
+
+/datum/design/item/mechfab/exointernal/marauder_armour
+ name = "Armor Plate (Cutting Edge)"
+ id = "exo_int_armor_marauder"
+ req_tech = list(TECH_MATERIAL = 8, TECH_ENGINEERING = 7, TECH_COMBAT = 6, TECH_ILLEGAL = 4)
+ materials = list(MAT_DURASTEEL = 40000, MAT_GRAPHITE = 8000, MAT_OSMIUM = 8000)
+ build_path = /obj/item/mecha_parts/component/armor/military/marauder
+
+/datum/design/item/mechfab/exointernal/phazon_armour
+ name = "Armor Plate (Janus)"
+ id = "exo_int_armor_phazon"
+ req_tech = list(TECH_MATERIAL = 6, TECH_ENGINEERING = 6, TECH_COMBAT = 6, TECH_ILLEGAL = 4)
+ materials = list(MAT_MORPHIUM = 40000, MAT_DURASTEEL = 8000, MAT_OSMIUM = 8000)
+ build_path = /obj/item/mecha_parts/component/armor/alien
+
+/datum/design/item/mechfab/exointernal/stan_hull
+ name = "Hull (Standard)"
+ category = "Exosuit Internals"
+ id = "exo_int_hull_standard"
+ req_tech = list(TECH_MATERIAL = 2, TECH_ENGINEERING = 2)
+ materials = list(DEFAULT_WALL_MATERIAL = 10000)
+ build_path = /obj/item/mecha_parts/component/hull
+
+/datum/design/item/mechfab/exointernal/durable_hull
+ name = "Hull (Durable)"
+ category = "Exosuit Internals"
+ id = "exo_int_hull_durable"
+ req_tech = list(TECH_MATERIAL = 2, TECH_ENGINEERING = 2)
+ materials = list(DEFAULT_WALL_MATERIAL = 8000, MAT_PLASTEEL = 5000)
+ build_path = /obj/item/mecha_parts/component/hull/durable
+
+/datum/design/item/mechfab/exointernal/light_hull
+ name = "Hull (Lightweight)"
+ category = "Exosuit Internals"
+ id = "exo_int_hull_light"
+ req_tech = list(TECH_MATERIAL = 3, TECH_ENGINEERING = 4)
+ materials = list(DEFAULT_WALL_MATERIAL = 5000, MAT_PLASTIC = 3000)
+ build_path = /obj/item/mecha_parts/component/hull/lightweight
+
+/datum/design/item/mechfab/exointernal/stan_gas
+ name = "Life-Support (Standard)"
+ category = "Exosuit Internals"
+ id = "exo_int_lifesup_standard"
+ req_tech = list(TECH_MATERIAL = 2, TECH_ENGINEERING = 2)
+ materials = list(DEFAULT_WALL_MATERIAL = 10000)
+ build_path = /obj/item/mecha_parts/component/gas
+
+/datum/design/item/mechfab/exointernal/reinf_gas
+ name = "Life-Support (Reinforced)"
+ category = "Exosuit Internals"
+ id = "exo_int_lifesup_reinforced"
+ req_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 4)
+ materials = list(DEFAULT_WALL_MATERIAL = 8000, MAT_PLASTEEL = 8000, MAT_GRAPHITE = 1000)
+ build_path = /obj/item/mecha_parts/component/gas/reinforced
+
+/datum/design/item/mechfab/exointernal/stan_electric
+ name = "Electrical Harness (Standard)"
+ category = "Exosuit Internals"
+ id = "exo_int_electric_standard"
+ req_tech = list(TECH_POWER = 2, TECH_ENGINEERING = 2)
+ materials = list(DEFAULT_WALL_MATERIAL = 5000, MAT_PLASTIC = 1000)
+ build_path = /obj/item/mecha_parts/component/electrical
+
+/datum/design/item/mechfab/exointernal/efficient_electric
+ name = "Electrical Harness (High)"
+ category = "Exosuit Internals"
+ id = "exo_int_electric_efficient"
+ req_tech = list(TECH_POWER = 4, TECH_ENGINEERING = 4, TECH_DATA = 2)
+ materials = list(DEFAULT_WALL_MATERIAL = 5000, MAT_PLASTIC = 3000, MAT_SILVER = 3000)
+ build_path = /obj/item/mecha_parts/component/electrical/high_current
+
+/datum/design/item/mechfab/exointernal/stan_actuator
+ name = "Actuator Lattice (Standard)"
+ category = "Exosuit Internals"
+ id = "exo_int_actuator_standard"
+ req_tech = list(TECH_MATERIAL = 2, TECH_ENGINEERING = 2)
+ materials = list(DEFAULT_WALL_MATERIAL = 10000)
+ build_path = /obj/item/mecha_parts/component/actuator
+
+/datum/design/item/mechfab/exointernal/hispeed_actuator
+ name = "Actuator Lattice (Overclocked)"
+ category = "Exosuit Internals"
+ id = "exo_int_actuator_overclock"
+ req_tech = list(TECH_MATERIAL = 5, TECH_ENGINEERING = 4, TECH_POWER = 4)
+ materials = list(MAT_PLASTEEL = 10000, MAT_OSMIUM = 3000, MAT_GOLD = 5000)
+ build_path = /obj/item/mecha_parts/component/actuator/hispeed
\ No newline at end of file
diff --git a/html/changelogs/mechoid - exointernals.yml b/html/changelogs/mechoid - exointernals.yml
new file mode 100644
index 0000000000..dd25e29efb
--- /dev/null
+++ b/html/changelogs/mechoid - exointernals.yml
@@ -0,0 +1,39 @@
+################################
+# Example Changelog File
+#
+# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb.
+#
+# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.)
+# When it is, any changes listed below will disappear.
+#
+# Valid Prefixes:
+# bugfix
+# wip (For works in progress)
+# tweak
+# soundadd
+# sounddel
+# rscadd (general adding of nice things)
+# rscdel (general deleting of nice things)
+# imageadd
+# imagedel
+# maptweak
+# spellcheck (typo fixes)
+# experiment
+#################################
+
+# Your name.
+author: Mechoid
+
+# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again.
+delete-after: True
+
+# Any changes you've made. See valid prefix list above.
+# INDENT WITH TWO SPACES. NOT TABS. SPACES.
+# SCREW THIS UP AND IT WON'T WORK.
+# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries.
+# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog.
+changes:
+ - rscadd: "Exosuits now have internal components."
+ - rscadd: "Autolathes can use plastic and plasteel."
+ - rscadd: "Autolathes can have tiered recipes, based on their manipulator rating."
+ - tweak: "Exosuit base health has been lowered due to the changes to damage processing."
diff --git a/icons/effects/actions_mecha.dmi b/icons/effects/actions_mecha.dmi
index 0a505767a3..882ceb534f 100644
Binary files a/icons/effects/actions_mecha.dmi and b/icons/effects/actions_mecha.dmi differ
diff --git a/icons/mecha/mech_component.dmi b/icons/mecha/mech_component.dmi
new file mode 100644
index 0000000000..c23c2d81e1
Binary files /dev/null and b/icons/mecha/mech_component.dmi differ
diff --git a/vorestation.dme b/vorestation.dme
index 7772b2ebf9..1ba2305d3d 100644
--- a/vorestation.dme
+++ b/vorestation.dme
@@ -941,6 +941,12 @@
#include "code\game\mecha\combat\gygax.dm"
#include "code\game\mecha\combat\marauder.dm"
#include "code\game\mecha\combat\phazon.dm"
+#include "code\game\mecha\components\_component.dm"
+#include "code\game\mecha\components\actuators.dm"
+#include "code\game\mecha\components\armor.dm"
+#include "code\game\mecha\components\electrical.dm"
+#include "code\game\mecha\components\hull.dm"
+#include "code\game\mecha\components\lifesupport.dm"
#include "code\game\mecha\equipment\mecha_equipment.dm"
#include "code\game\mecha\equipment\mecha_equipment_dynamicprocs.dm"
#include "code\game\mecha\equipment\tools\armor_melee.dm"