@@ -217,12 +135,14 @@
output += ..()
return output
-/obj/mecha/combat/marauder/Topic(href, href_list)
+//Meant for random spawns.
+/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()
..()
- if (href_list["toggle_thrusters"])
- src.toggle_thrusters()
- if (href_list["smoke"])
- src.smoke()
- if (href_list["toggle_zoom"])
- src.zoom()
- return
\ No newline at end of file
+ health = 25
+ maxhealth = 300 //Just slightly worse.
+ cell.charge = rand(0, (cell.charge/2))
diff --git a/code/game/mecha/combat/phazon.dm b/code/game/mecha/combat/phazon.dm
index 48394f47f45..17aea92345e 100644
--- a/code/game/mecha/combat/phazon.dm
+++ b/code/game/mecha/combat/phazon.dm
@@ -6,8 +6,8 @@
step_in = 1
dir_in = 1 //Facing North.
step_energy_drain = 3
- health = 200
- maxhealth = 200
+ health = 200 //God this is low
+ maxhealth = 200 //Don't forget to update the /old variant if you change this number.
deflect_chance = 30
damage_absorption = list("brute"=0.7,"fire"=0.7,"bullet"=0.7,"laser"=0.7,"energy"=0.7,"bomb"=0.7)
max_temperature = 25000
@@ -17,9 +17,6 @@
//operation_req_access = list()
internal_damage_threshold = 25
force = 15
- var/phasing = 0
- var/can_phase = TRUE
- var/phasing_energy_drain = 200
max_equip = 4
max_hull_equip = 3
@@ -28,14 +25,27 @@
max_universal_equip = 3
max_special_equip = 4
+ 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.
/obj/mecha/combat/phazon/Bump(var/atom/obstacle)
if(phasing && get_charge()>=phasing_energy_drain)
spawn()
@@ -49,35 +59,8 @@
else
. = ..()
return
+*/
-/obj/mecha/combat/phazon/click_action(atom/target,mob/user)
- if(phasing)
- src.occupant_message("Unable to interact with objects while phasing")
- return
- else
- return ..()
-
-/obj/mecha/combat/phazon/verb/switch_damtype()
- set category = "Exosuit Interface"
- set name = "Change melee damage type"
- set src = usr.loc
- set popup_menu = 0
- if(usr!=src.occupant)
- return
-
- query_damtype()
-
-/obj/mecha/combat/phazon/proc/query_damtype()
- var/new_damtype = alert(src.occupant,"Melee Damage Type",null,"Brute","Fire","Toxic")
- switch(new_damtype)
- if("Brute")
- damtype = "brute"
- if("Fire")
- damtype = "fire"
- if("Toxic")
- damtype = "tox"
- src.occupant_message("Melee damage type switched to [new_damtype ]")
- return
/obj/mecha/combat/phazon/get_commands()
var/output = {"
@@ -91,15 +74,7 @@
output += ..()
return output
-/obj/mecha/combat/phazon/Topic(href, href_list)
- ..()
- if (href_list["switch_damtype"])
- src.switch_damtype()
- if (href_list["phasing"])
- phasing = !phasing
- send_byjax(src.occupant,"exosuit.browser","phasing_command","[phasing?"Dis":"En"]able phasing")
- src.occupant_message("
En":"#f00\">Dis"]abled phasing.")
- return
+
/obj/mecha/combat/phazon/janus
name = "Phazon Prototype Janus Class"
@@ -121,7 +96,6 @@
wreckage = /obj/effect/decal/mecha_wreckage/janus
internal_damage_threshold = 25
force = 20
- phasing = FALSE
phasing_energy_drain = 300
max_hull_equip = 2
@@ -130,6 +104,10 @@
max_universal_equip = 2
max_special_equip = 2
+ phasing_possible = TRUE
+ switch_dmg_type_possible = TRUE
+ cloak_possible = FALSE
+
/obj/mecha/combat/phazon/janus/take_damage(amount, type="brute")
..()
if(phasing)
@@ -173,3 +151,13 @@
damtype = "halloss"
src.occupant_message("Melee damage type switched to [new_damtype]")
return
+
+//Meant for random spawns.
+/obj/mecha/combat/phazon/old
+ desc = "An exosuit which can only be described as 'WTF?'. This one is particularly worn looking and likely isn't as sturdy."
+
+/obj/mecha/combat/phazon/old/New()
+ ..()
+ health = 25
+ maxhealth = 150 //Just slightly worse.
+ cell.charge = rand(0, (cell.charge/2))
\ No newline at end of file
diff --git a/code/game/mecha/components/_component.dm b/code/game/mecha/components/_component.dm
new file mode 100644
index 00000000000..aadf390c615
--- /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 00000000000..d814518629c
--- /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 00000000000..ac4ce81ec53
--- /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 = 4
+
+ 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 = 0
+ else
+ step_delay = initial(step_delay)
+
+/obj/item/mecha_parts/component/armor/marshal
+ name = "marshal mecha plating"
+
+ step_delay = 3
+
+ 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 = 2
+ 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 00000000000..de07c96c84b
--- /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 00000000000..16d01ad92cc
--- /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 00000000000..d98cefda4dc
--- /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 678ac649105..617af4849fc 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 8390a2cc52a..ed5724ce649 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 = 0.5
+
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 4fb3aac32b6..e1a06bef2d9 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 = 1
+
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 f4f9696aa5c..7cd8ebd9ab7 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 1ceab079454..ce0c43e7da9 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 = 0.2
+
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 1d230c4deb6..ca61a138e42 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 = 0.2
+
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 = initial(step_delay)
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 1cb0df9469f..7ffbeaee38a 100644
--- a/code/game/mecha/equipment/tools/speedboost.dm
+++ b/code/game/mecha/equipment/tools/speedboost.dm
@@ -7,13 +7,23 @@
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)
- chassis.step_in = (chassis.step_in-2) // Make the ripley as fast as a durand
+ chassis.step_in = 3 // As fast as a gygax without overload. Slower than Ody.
else
- chassis.step_in = (chassis.step_in+1) // Improper parts slow the mech down
+ 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 86928c9da58..c192d0fc9b8 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 d2232d00047..e698248b7f6 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 = 0.5
+
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 8bdcbcf71f8..5a480a96918 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 = 1
+
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 1c14a8c1dd6..9ff28ade8e5 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 = 0.5
+
/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 f97f598e243..5e2d79615c6 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 = 0.5
+
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 3d3c1748394..ff49d42016f 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/honk.dm b/code/game/mecha/equipment/weapons/honk.dm
index 427d53295c3..e7bee193dd4 100644
--- a/code/game/mecha/equipment/weapons/honk.dm
+++ b/code/game/mecha/equipment/weapons/honk.dm
@@ -26,7 +26,7 @@
return
to_chat(M, "
Your ears feel like they're bleeding!")
playsound(M, 'sound/effects/bang.ogg', 70, 1, 30)
- M.sleeping = 0
+ M.SetSleeping(0)
M.ear_deaf += 30
M.ear_damage += rand(5, 20)
M.Weaken(3)
diff --git a/code/game/mecha/equipment/weapons/weapons.dm b/code/game/mecha/equipment/weapons/weapons.dm
index 355ce629ace..fa7e2005c6b 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 = 0.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 1b00505bc9a..bfdb4508e94 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"
@@ -15,39 +20,54 @@
/obj/mecha
name = "Mecha"
desc = "Exosuit"
+ description_info = "Alt click to strafe."
icon = 'icons/mecha/mecha.dmi'
- density = 1 //Dense. To raise the heat.
- opacity = 1 ///opaque. Menacing.
- anchored = 1 //no pulling around.
- unacidable = 1 //and no deleting hoomans inside
- layer = MOB_LAYER //icon draw layer
- infra_luminosity = 15 //byond implementation is bugged.
- var/initial_icon = null //Mech type for resetting icon. Only used for reskinning kits (see custom items)
+ density = 1 //Dense. To raise the heat.
+ opacity = 1 ///opaque. Menacing.
+ anchored = 1 //no pulling around.
+ unacidable = 1 //and no deleting hoomans inside
+ layer = MOB_LAYER //icon draw layer
+ infra_luminosity = 15 //byond implementation is bugged.
+ var/initial_icon = null //Mech type for resetting icon. Only used for reskinning kits (see custom items)
var/can_move = 1
var/mob/living/carbon/occupant = null
- var/step_in = 10 //make a step in step_in/10 sec.
- var/dir_in = 2//What direction will the mech face when entered/powered on? Defaults to South.
+ var/step_in = 10 //make a step in step_in/10 sec.
+ var/dir_in = 2 //What direction will the mech face when entered/powered on? Defaults to South.
var/step_energy_drain = 10
- var/health = 300 //health is health
- var/maxhealth = 300 //maxhealth is maxhealth.
- var/deflect_chance = 10 //chance to deflect the incoming projectiles, hits, or lesser the effect of ex_act.
+ var/health = 300 //health is health
+ var/maxhealth = 300 //maxhealth is maxhealth.
+ var/deflect_chance = 10 //chance to deflect the incoming projectiles, hits, or lesser the effect of ex_act.
//the values in this list show how much damage will pass through, not how much will be absorbed.
- var/list/damage_absorption = list("brute"=0.8,"fire"=1.2,"bullet"=0.9,"laser"=1,"energy"=1,"bomb"=1)
+ 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 //Incoming damage lower than this won't actually deal damage. Scrapes shouldn't be a real thing.
+ var/minimum_penetration = 15 //Incoming damage won't be fully applied if you don't have at least 20. Almost all AP clears this.
+ 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
var/maint_access = 1
- var/dna //dna-locking the mech
- var/list/proc_res = list() //stores proc owners, like proc_res["functionname"] = owner reference
+ var/dna //dna-locking the mech
+ var/list/proc_res = list() //stores proc owners, like proc_res["functionname"] = owner reference
var/datum/effect/effect/system/spark_spread/spark_system = new
var/lights = 0
var/lights_power = 6
var/force = 0
var/mech_faction = null
- var/firstactivation = 0 //It's simple. If it's 0, no one entered it yet. Otherwise someone entered it at least once.
+ var/firstactivation = 0 //It's simple. If it's 0, no one entered it yet. Otherwise someone entered it at least once.
var/stomp_sound = 'sound/mecha/mechstep.ogg'
var/swivel_sound = 'sound/mecha/mechturn.ogg'
@@ -61,25 +81,27 @@
var/obj/item/device/radio/radio = null
- var/max_temperature = 25000
- var/internal_damage_threshold = 50 //health percentage below which internal damage is possible
- var/internal_damage = 0 //contains bitflags
+ var/max_temperature = 25000 //Kelvin values.
+ var/internal_damage_threshold = 33 //health percentage below which internal damage is possible
+ var/internal_damage_minimum = 15 //At least this much damage to trigger some real bad hurt.
+ var/internal_damage = 0 //contains bitflags
var/list/operation_req_access = list()//required access level for mecha operation
var/list/internals_req_access = list(access_engine,access_robotics)//required access level to open cell compartment
- var/datum/global_iterator/pr_int_temp_processor //normalizes internal air mixture temperature
- var/datum/global_iterator/pr_inertial_movement //controls intertial movement in spesss
- var/datum/global_iterator/pr_give_air //moves air from tank to cabin
- var/datum/global_iterator/pr_internal_damage //processes internal damage
+ var/datum/global_iterator/pr_int_temp_processor //normalizes internal air mixture temperature
+ var/datum/global_iterator/pr_inertial_movement //controls intertial movement in spesss
+ var/datum/global_iterator/pr_give_air //moves air from tank to cabin
+ var/datum/global_iterator/pr_internal_damage //processes internal damage
var/wreckage
- var/list/equipment = new
+ var/list/equipment = new //This lists holds what stuff you bolted onto your baby ride
var/obj/item/mecha_parts/mecha_equipment/selected
var/max_equip = 2
var/datum/events/events
+
//mechaequipt2 stuffs
var/list/hull_equipment = new
var/list/weapon_equipment = new
@@ -91,6 +113,25 @@
var/max_utility_equip = 2
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
@@ -100,8 +141,69 @@
var/static/image/radial_image_lighttoggle = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_light")
var/static/image/radial_image_statpanel = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_examine2")
+//Mech actions
var/datum/mini_hud/mech/minihud //VOREStation Edit
- var/strafing = 0
+ var/strafing = 0 //Are we strafing or not?
+
+ var/defence_mode_possible = 0 //Can we even use defence mode? This is used to assign it to mechs and check for verbs.
+ var/defence_mode = 0 //Are we in defence mode
+ var/defence_deflect = 35 //How much it deflect
+
+ var/overload_possible = 0 //Same as above. Don't forget to GRANT the verb&actions if you want everything to work proper.
+ var/overload = 0 //Are our legs overloaded
+ var/overload_coeff = 1 //How much extra energy you use when use the L E G
+
+ var/zoom = 0
+ var/zoom_possible = 0
+
+ var/thrusters = 0
+ var/thrusters_possible = 0
+
+ var/phasing = 0 //Are we currently phasing
+ 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
+ var/smoke_reserve = 5 //How many shots you have. Might make a reload later on. MIGHT.
+ var/smoke_ready = 1 //This is a check for the whether or not the cooldown is ongoing.
+ 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
+ var/datum/action/innate/mecha/mech_toggle_internals/internals_action = new
+ var/datum/action/innate/mecha/mech_toggle_lights/lights_action = new
+ var/datum/action/innate/mecha/mech_view_stats/stats_action = new
+ var/datum/action/innate/mecha/strafe/strafing_action = new
+
+ var/datum/action/innate/mecha/mech_defence_mode/defence_action = new
+ var/datum/action/innate/mecha/mech_overload_mode/overload_action = new
+ var/datum/action/innate/mecha/mech_smoke/smoke_action = new
+ var/datum/action/innate/mecha/mech_zoom/zoom_action = new
+ var/datum/action/innate/mecha/mech_toggle_thrusters/thrusters_action = new
+ 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)
@@ -123,8 +225,14 @@
if(!add_airtank()) //we check this here in case mecha does not have an internal tank available by default - WIP
removeVerb(/obj/mecha/verb/connect_to_port)
removeVerb(/obj/mecha/verb/toggle_internal_tank)
+
spark_system.set_up(2, 0, src)
spark_system.attach(src)
+
+ if(smoke_possible)//I am pretty sure that's needed here.
+ src.smoke_system.set_up(3, 0, src)
+ src.smoke_system.attach(src)
+
add_cell()
add_iterators()
removeVerb(/obj/mecha/verb/disconnect_from_port)
@@ -173,6 +281,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)
@@ -184,6 +301,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)
@@ -192,6 +314,9 @@
cell = null
internal_tank = null
+ if(smoke_possible) //Just making sure nothing is running.
+ qdel(smoke_system)
+
QDEL_NULL(pr_int_temp_processor)
QDEL_NULL(pr_inertial_movement)
QDEL_NULL(pr_give_air)
@@ -276,6 +401,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)
@@ -283,11 +428,11 @@
if(65 to 85)
. += "It's slightly damaged."
if(45 to 65)
- . += "It's badly damaged."
+ . += "
It's badly damaged."
if(25 to 45)
- . += "It's heavily damaged."
+ . += "
It's heavily damaged."
else
- . += "It's falling apart."
+ . += "
It's falling apart. "
if(equipment?.len)
. += "It's equipped with:"
for(var/obj/item/mecha_parts/mecha_equipment/ME in equipment)
@@ -319,6 +464,7 @@
"Toggle Light" = radial_image_lighttoggle,
"View Stats" = radial_image_statpanel
)
+
var/choice = show_radial_menu(user, src, choices, custom_check = CALLBACK(src, .proc/check_occupant_radial, user), require_near = TRUE, tooltips = TRUE)
if(!check_occupant_radial(user))
return
@@ -380,6 +526,11 @@
if(state)
occupant_message("
Maintenance protocols in effect")
return
+
+ if(phasing)//Phazon and other mechs with phasing.
+ src.occupant_message("Unable to interact with objects while phasing")//Haha dumbass.
+ return
+
if(!get_charge()) return
if(src == target) return
var/dir_to_target = get_dir(src,target)
@@ -455,6 +606,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")
@@ -463,6 +620,13 @@
if(state)
occupant_message("
Maintenance protocols in effect")
return
+/*
+ if(zoom)
+ if(world.time - last_message > 20)
+ src.occupant_message("Unable to move while in zoom mode.")
+ last_message = world.time
+ return 0
+*/
return domove(direction)
/obj/mecha/proc/can_ztravel()
@@ -474,6 +638,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, 0.1))
+
/obj/mecha/proc/dyndomove(direction)
if(!can_move)
return 0
@@ -482,6 +684,40 @@
if(!has_charge(step_energy_drain))
return 0
+ //Can we even move, below is if yes.
+
+ if(defence_mode)//Check if we are currently locked down
+ if(world.time - last_message > 20)
+ src.occupant_message("
Unable to move while in defence mode")
+ last_message = world.time
+ return 0
+
+ if(zoom)//:eyes:
+ if(world.time - last_message > 20)
+ src.occupant_message("Unable to move while in zoom mode.")
+ last_message = world.time
+ return 0
+
+
+/*
+//A first draft of a check to stop mechs from moving fully. TBD when all thrusters modules are unified.
+ if(!thrusters && !src.pr_inertial_movement.active() && isspace(src.loc))//No thrsters, not drifting, in space
+ src.occupant_message("Error 543")//debug
+ return 0
+*/
+
+
+ if(!thrusters && src.pr_inertial_movement.active()) //I think this mean 'if you try to move in space without thruster, u no move'
+ return 0
+
+ if(overload)//Check if you have leg overload
+ health--
+ if(health < initial(health) - initial(health)/3)
+ overload = 0
+ step_energy_drain = initial(step_energy_drain)
+ src.occupant_message("
Leg actuators damage threshold exceded. Disabling overload.")
+
+
var/move_result = 0
if(hasInternalDamage(MECHA_INT_CONTROL_LOST))
@@ -533,7 +769,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
@@ -572,21 +808,35 @@
/obj/mecha/Bump(var/atom/obstacle)
// src.inertia_dir = null
- if(istype(obstacle, /obj))
+ if(istype(obstacle, /mob))//First we check if it is a mob. Mechs mostly shouln't go through them, even while phasing.
+ var/mob/M = obstacle
+ M.Move(get_step(obstacle,src.dir))
+ else if(istype(obstacle, /obj))//Then we check for regular obstacles.
var/obj/O = obstacle
- if(istype(O, /obj/effect/portal)) //derpfix
- src.anchored = 0
+
+ if(phasing && get_charge()>=phasing_energy_drain)//Phazon check. This could use an improvement elsewhere.
+ spawn()
+ if(can_phase)
+ can_phase = FALSE
+ flick("[initial_icon]-phase", src)
+ src.loc = get_step(src,src.dir)
+ src.use_power(phasing_energy_drain)
+ sleep(get_step_delay() * 3)
+ can_phase = TRUE
+ occupant_message("Phazed.")
+ . = ..(obstacle)
+ return
+ if(istype(O, /obj/effect/portal)) //derpfix
+ src.anchored = 0 //I have no idea what this really fix.
O.Crossed(src)
spawn(0)//countering portal teleport spawn(0), hurr
src.anchored = 1
- else if(!O.anchored)
- step(obstacle,src.dir)
- else //I have no idea why I disabled this
+ else if(O.anchored)
obstacle.Bumped(src)
- else if(istype(obstacle, /mob))
- var/mob/M = obstacle
- M.Move(get_step(obstacle,src.dir))
- else
+ else
+ step(obstacle,src.dir)
+
+ else//No idea when this triggers, so i won't touch it.
. = ..(obstacle)
return
@@ -594,18 +844,21 @@
//////// Internal damage ////////
///////////////////////////////////
+//ATM, the ignore_threshold is literally only used for the pulse rifles beams used mostly by deathsquads.
/obj/mecha/proc/check_for_internal_damage(var/list/possible_int_damage,var/ignore_threshold=null)
if(!islist(possible_int_damage) || isemptylist(possible_int_damage)) return
- if(prob(20))
- if(ignore_threshold || src.health*100/initial(src.health)
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)
..()
take_damage(crush_damage)
- check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
+ if(prob(50)) //Try to avoid that.
+ check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
return 1
/obj/mecha/proc/update_health()
@@ -673,16 +968,27 @@
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))
- src.take_damage(15)
- src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
+ 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))
playsound(src, 'sound/weapons/slash.ogg', 50, 1, -1)
to_chat(user, "You slash at the armored suit!")
visible_message("\The [user] slashes at [src.name]'s armor!")
@@ -696,9 +1002,10 @@
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))
- src.take_damage(15)
- src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
+ 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))
user.visible_message("[user] hits [src.name], doing some damage.", "You hit [src.name] with all your might. The metal creaks and bends.")
else
user.visible_message("[user] hits [src.name]. Nothing happens.","You hit [src.name] with no visible effect.")
@@ -711,12 +1018,32 @@
call((proc_res["dynhitby"]||src), "dynhitby")(A)
return
+//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.")
@@ -728,11 +1055,30 @@
if(O.throwforce)
var/pass_damage = O.throwforce
+ var/pass_damage_reduc_mod
+ 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 < 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 = 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 pierce \the [src] armor.")
+// src.visible_message("\The [A] manages to pierce \the [src] armor")
+ pass_damage_reduc_mod = 1
+
+
+
for(var/obj/item/mecha_parts/mecha_equipment/ME in equipment)
pass_damage = ME.handle_ranged_contact(A, pass_damage)
- src.take_damage(pass_damage)
- src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
+ pass_damage = (pass_damage*pass_damage_reduc_mod)//Applying damage reduction
+ src.take_damage(pass_damage) //The take_damage() proc handles armor values
+ if(pass_damage > internal_damage_minimum) //Only decently painful attacks trigger a chance of mech damage.
+ src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
return
@@ -748,7 +1094,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.")
@@ -759,16 +1124,35 @@
if(!(Proj.nodamage))
var/ignore_threshold
- if(istype(Proj, /obj/item/projectile/beam/pulse))
+ if(istype(Proj, /obj/item/projectile/beam/pulse)) //ATM, this is literally only for the pulse rifles used mostly by deathsquads.
ignore_threshold = 1
var/pass_damage = Proj.damage
+ var/pass_damage_reduc_mod
for(var/obj/item/mecha_parts/mecha_equipment/ME in equipment)
pass_damage = ME.handle_projectile_contact(Proj, pass_damage)
- src.take_damage(pass_damage, Proj.check_armour)
- if(prob(25)) spark_system.start()
- 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),ignore_threshold)
+ 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 < 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 = 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")
+ pass_damage_reduc_mod = 1
+
+ pass_damage = (pass_damage_reduc_mod*pass_damage)//Apply damage reduction before usage.
+ src.take_damage(pass_damage, Proj.check_armour) //The take_damage() proc handles armor values
+ if(prob(25))
+ spark_system.start()
+ 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),ignore_threshold)
//AP projectiles have a chance to cause additional damage
if(Proj.penetrating)
@@ -779,7 +1163,8 @@
Proj.attack_mob(src.occupant, distance)
hit_occupant = 0
else
- 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(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--
@@ -789,25 +1174,36 @@
Proj.on_hit(src) //on_hit just returns if it's argument is not a living mob so does this actually do anything?
return
+//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)
+ 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)
+ 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
@@ -838,36 +1234,68 @@
use_power((cell.charge/2)/severity)
take_damage(50 / severity,"energy")
src.log_message("EMP detected",1)
- check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT),1)
+ if(prob(80))
+ check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT),1)
return
/obj/mecha/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
if(exposed_temperature>src.max_temperature)
src.log_message("Exposed to dangerous temperature.",1)
- src.take_damage(5,"fire")
+ src.take_damage(5,"fire") //The take_damage() proc handles armor values
src.check_for_internal_damage(list(MECHA_INT_FIRE, MECHA_INT_TEMP_CONTROL))
return
/obj/mecha/proc/dynattackby(obj/item/weapon/W as obj, mob/user as mob)
user.setClickCooldown(user.get_attack_speed(W))
src.log_message("Attacked by [W]. Attacker - [user]")
- if(prob(src.deflect_chance))
+ var/pass_damage_reduc_mod //Modifer for failing to bring AP.
+
+ 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.")
-/*
- for (var/mob/V in viewers(src))
- if(V.client && !(V.blinded))
- V.show_message("The [W] bounces off [src.name] armor.", 1)
-*/
+
+ 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 < 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 = 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.
src.occupant_message("[user] hits [src] with [W].")
user.visible_message("[user] hits [src] with [W].", "You hit [src] with [W].")
var/pass_damage = W.force
+ pass_damage = (pass_damage*pass_damage_reduc_mod) //Apply the reduction of damage from not having enough armor penetration. This is not regular armor values at play.
for(var/obj/item/mecha_parts/mecha_equipment/ME in equipment)
- pass_damage = ME.handle_projectile_contact(W, pass_damage)
- src.take_damage(pass_damage,W.damtype)
- src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
+ pass_damage = ME.handle_projectile_contact(W, user, pass_damage)
+ src.take_damage(pass_damage,W.damtype) //The take_damage() proc handles armor values
+ if(pass_damage > internal_damage_minimum) //Only decently painful attacks trigger a chance of mech damage.
+ src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
return
//////////////////////
@@ -883,6 +1311,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()
@@ -893,6 +1326,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))
@@ -909,23 +1356,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)
@@ -937,19 +1400,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()
@@ -961,7 +1424,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()
@@ -994,6 +1457,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)
/*
@@ -1102,7 +1587,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)
@@ -1117,7 +1603,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()
@@ -1128,7 +1615,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()
@@ -1183,13 +1671,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)
@@ -1210,13 +1702,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
@@ -1229,6 +1721,9 @@
set category = "Exosuit Interface"
set src = usr.loc
set popup_menu = 0
+ lights()
+
+/obj/mecha/verb/lights()
if(usr!=occupant) return
lights = !lights
if(lights) set_light(light_range + lights_power)
@@ -1244,18 +1739,36 @@
set category = "Exosuit Interface"
set src = usr.loc
set popup_menu = 0
+ internal_tank()
+
+/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"].")
+ playsound(src, 'sound/mecha/gasdisconnected.ogg', 30, 1)
return
+
/obj/mecha/verb/toggle_strafing()
set name = "Toggle strafing"
set category = "Exosuit Interface"
set src = usr.loc
set popup_menu = 0
+ strafing()
+
+/obj/mecha/proc/strafing()
if(usr!=src.occupant)
return
strafing = !strafing
@@ -1274,11 +1787,13 @@
move_inside()
-/obj/mecha/verb/move_inside()
+/obj/mecha/verb/enter()
set category = "Object"
set name = "Enter Exosuit"
set src in oview(1)
+ move_inside()
+/obj/mecha/proc/move_inside()
if (usr.stat || !ishuman(usr))
return
@@ -1324,6 +1839,8 @@
if(enter_after(40,usr))
if(!src.occupant)
moved_inside(usr)
+ if(ishuman(occupant)) //Aeiou
+ GrantActions(occupant, 1)
else if(src.occupant!=usr)
to_chat(usr, "[src.occupant] was faster. Try better next time, loser.")
else
@@ -1345,8 +1862,32 @@
src.verbs += /obj/mecha/verb/eject
src.log_append_to_last("[H] moved in as pilot.")
src.icon_state = src.reset_icon()
+ //VOREStation Edit Add
if(occupant.hud_used)
minihud = new (occupant.hud_used, src)
+ //VOREStation Edit Add End
+
+//This part removes all the verbs if you don't have them the _possible on your mech. This is a little clunky, but it lets you just add that to any mech.
+//And it's not like this 10yo code wasn't clunky before.
+
+ if(!smoke_possible) //Can't use smoke? No verb for you.
+ verbs -= /obj/mecha/verb/toggle_smoke
+ if(!thrusters_possible) //Can't use thrusters? No verb for you.
+ verbs -= /obj/mecha/verb/toggle_thrusters
+ if(!defence_mode_possible) //Do i need to explain everything?
+ verbs -= /obj/mecha/verb/toggle_defence_mode
+ if(!overload_possible)
+ verbs -= /obj/mecha/verb/toggle_overload
+ if(!zoom_possible)
+ verbs -= /obj/mecha/verb/toggle_zoom
+ if(!phasing_possible)
+ 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()
update_damage_alerts()
set_dir(dir_in)
@@ -1376,6 +1917,9 @@
else//Everyone else gets the normal noise
who << sound('sound/mecha/nominal.ogg',volume=50)
+/obj/mecha/AltClick(mob/living/user)
+ if(user == occupant)
+ strafing()
/obj/mecha/verb/view_stats()
set name = "View Stats"
@@ -1415,6 +1959,7 @@
QDEL_NULL(minihud)
if(ishuman(occupant))
mob_container = src.occupant
+ RemoveActions(occupant, human_occupant=1)//AEIOU
else if(istype(occupant, /mob/living/carbon/brain))
var/mob/living/carbon/brain/brain = occupant
mob_container = brain.container
@@ -1434,10 +1979,19 @@
occupant.canmove = 0
occupant.clear_alert("charge")
occupant.clear_alert("mech damage")
+ occupant.in_enclosed_vehicle = 0
occupant = null
icon_state = src.reset_icon()+"-open"
set_dir(dir_in)
verbs -= /obj/mecha/verb/eject
+
+ //src.zoom = 0
+
+ // Doesn't seem needed.
+ if(src.occupant && src.occupant.client)
+ src.occupant.client.view = world.view
+ src.zoom = 0
+
strafing = 0
return
@@ -1453,8 +2007,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
@@ -1555,9 +2114,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
@@ -1567,7 +2132,18 @@
Lights: [lights?"on":"off"]
[src.dna?"DNA-locked:
[src.dna] \[Reset\]
":null]
"}
-//Cargo components.
+
+
+ if(defence_mode_possible)
+ output += "Defence mode: [defence_mode?"on":"off"]
"
+ if(overload_possible)
+ output += "Leg actuators overload: [overload?"on":"off"]
"
+ if(smoke_possible)
+ output += "Smoke: [smoke_reserve]
"
+ if(thrusters_possible)
+ output += "Thrusters: [thrusters?"on":"off"]
"
+
+//Cargo components. Keep this last otherwise it does weird alignment issues.
output += "Cargo Compartment Contents:"
if(src.cargo.len)
for(var/obj/O in src.cargo)
@@ -1637,15 +2213,15 @@
output += "Micro Utility Module: [W.name]
Detach"
for(var/obj/item/mecha_parts/mecha_equipment/W in micro_weapon_equipment)
output += "Micro Weapon Module: [W.name]
Detach"
- output += {"
Available hull slots: [max_hull_equip-hull_equipment.len]
-
Available weapon slots: [max_weapon_equip-weapon_equipment.len]
-
Available micro weapon slots: [max_micro_weapon_equip-micro_weapon_equipment.len]
-
Available utility slots: [max_utility_equip-utility_equipment.len]
-
Available micro utility slots: [max_micro_utility_equip-micro_utility_equipment.len]
-
Available universal slots: [max_universal_equip-universal_equipment.len]
-
Available special slots: [max_special_equip-special_equipment.len]
-