New Traitor mech: Justice. (#84097)
## About The Pull Request Adds new mech that can be created from emaged fabricator. To craft this mech you need: 1. Emag Fabricator to recive Justice disgine(done this, fabricator will emit a text and sound signal that can reveal you). 2. You need to craft it like any other mech but you also need 8 telecrystals to finish constraction. 3. To board a mech you need syndicate access (traitor can get it by purchasing an agent card). About Mech: Video: https://youtu.be/QwJfO_lbLK0 Text: Health 200 Damage 60 Only melee attacks(can't attach range weapons(can't attach anything in his arms at all)) Block chanse 60 Speed - in safty mode 2.5 in combat mode 4.5 Attack effects: In addition to damage, it has a 50 percent chance of cutting off an arm or leg (does not put you to sleep or give a knockdown effect when hit like regular combat mechs do). If a target in crit or stun makes a finishing attack instead of a regular attack, the mech says an epic phrase and after a second cuts off the target's head by dashing through the target. Special actions(can't be used if mech in safty mode): Invisability - Makes the mech invisible for 20 seconds. If the mech is pushed or collides with someone or if the pilot presses the invisibility button again, the mech will no longer be invisible and will go into a 5 second cooldown (the same will happen after 20 seconds). If you attack in invisibility, then instead of a normal attack the mech will make an AoE 3x3 attack 1 second after pressing (the attack will be accompanied by a sound and visual effect and for a second the mech will not be able to move, which gives enemies time to run away from the attack). Upon completion AoE attack, everyone( except peoples in crit and in stunned condition) in a 3x3 radius will receive 35 damage and a 25 chance of having one of their limbs cut off. Charge Attack - Mech makes a dash towards the cursor at a distance of up to 7 cells, breaking all obstacles in its path. If the obstacle is a living person (and he is not in crit and is not stunned) then he will receive 35 damage and a 25 chance of cutting off a limb. Cooldown 5 Seconds. P.S. Also added emag_act on fabricator so you can put any new secret traitor mechs on it. Also made the sounds of mech melee attacks to vars so that it would be more convenient to change them. Also fix a runtime error where if you set something in the mech's max_equip_by_category to 0, the mech UI panel doesn't load. ## Why It's Good For The Game Adds a traitor mech with fun and interesting mechanics. This is a new mech with new unique abilities that turns the battle with you into a boss fight. ## Changelog 🆑 add: New traitor mech: Justice. Emag fabricator to get it. /🆑 --------- Co-authored-by: Jacquerel <hnevard@gmail.com>
@@ -35,10 +35,12 @@
|
||||
#define EXOSUIT_MODULE_MARAUDER (1<<10)
|
||||
/// Module is compatible with Paddy models
|
||||
#define EXOSUIT_MODULE_PADDY (1<<11)
|
||||
/// Module is compatible with Justice models
|
||||
#define EXOSUIT_MODULE_JUSTICE (1<<12)
|
||||
|
||||
/// Module is compatible with "Working" Exosuit models - Ripley and Clarke
|
||||
#define EXOSUIT_MODULE_WORKING (EXOSUIT_MODULE_RIPLEY | EXOSUIT_MODULE_CLARKE)
|
||||
/// Module is compatible with "Combat" Exosuit models - Gygax, H.O.N.K, Durand and Phazon, or any Exosuit with an empty Concealed Weapon Bay
|
||||
#define EXOSUIT_MODULE_COMBAT (EXOSUIT_MODULE_GYGAX | EXOSUIT_MODULE_HONK | EXOSUIT_MODULE_DURAND | EXOSUIT_MODULE_PHAZON | EXOSUIT_MODULE_SAVANNAH | EXOSUIT_MODULE_RETICENCE | EXOSUIT_MODULE_MARAUDER | EXOSUIT_MODULE_PADDY | EXOSUIT_MODULE_CONCEALED_WEP_BAY)
|
||||
#define EXOSUIT_MODULE_COMBAT (EXOSUIT_MODULE_GYGAX | EXOSUIT_MODULE_HONK | EXOSUIT_MODULE_DURAND | EXOSUIT_MODULE_PHAZON | EXOSUIT_MODULE_SAVANNAH | EXOSUIT_MODULE_RETICENCE | EXOSUIT_MODULE_MARAUDER | EXOSUIT_MODULE_PADDY | EXOSUIT_MODULE_JUSTICE | EXOSUIT_MODULE_CONCEALED_WEP_BAY)
|
||||
/// Module is compatible with "Medical" Exosuit modelsm - Odysseus
|
||||
#define EXOSUIT_MODULE_MEDICAL EXOSUIT_MODULE_ODYSSEUS
|
||||
|
||||
@@ -134,6 +134,7 @@
|
||||
#define RND_CATEGORY_MECHFAB_PHAZON "/Phazon"
|
||||
#define RND_CATEGORY_MECHFAB_CLARKE "/Clarke"
|
||||
#define RND_CATEGORY_MECHFAB_SAVANNAH_IVANOV "/Savannah-Ivanov"
|
||||
#define RND_CATEGORY_MECHFAB_JUSTICE "/Justice"
|
||||
#define RND_SUBCATEGORY_MECHFAB_CHASSIS "/Chassis"
|
||||
#define RND_SUBCATEGORY_MECHFAB_SUPPORTED_EQUIPMENT "/Supported Equipment"
|
||||
#define RND_SUBCATEGORY_MECHFAB_CONTROL_INTERFACES "/Control Interfaces"
|
||||
|
||||
@@ -709,3 +709,29 @@
|
||||
flags = ANIMATION_RELATIVE,
|
||||
)
|
||||
return ..()
|
||||
|
||||
/obj/effect/temp_visual/mech_sparks
|
||||
name = "mech sparks"
|
||||
icon_state = "mech_sparks"
|
||||
duration = 0.4 SECONDS
|
||||
|
||||
/obj/effect/temp_visual/mech_sparks/Initialize(mapload, set_color)
|
||||
. = ..()
|
||||
pixel_x = rand(-16, 16)
|
||||
pixel_y = rand(-8, 8)
|
||||
|
||||
/obj/effect/temp_visual/mech_attack_aoe_charge
|
||||
name = "mech attack aoe charge"
|
||||
icon = 'icons/effects/96x96.dmi'
|
||||
icon_state = "mech_attack_aoe_charge"
|
||||
duration = 1 SECONDS
|
||||
pixel_x = -32
|
||||
pixel_y = -32
|
||||
|
||||
/obj/effect/temp_visual/mech_attack_aoe_attack
|
||||
name = "mech attack aoe attack"
|
||||
icon = 'icons/effects/96x96.dmi'
|
||||
icon_state = "mech_attack_aoe_attack"
|
||||
duration = 0.5 SECONDS
|
||||
pixel_x = -32
|
||||
pixel_y = -32
|
||||
|
||||
@@ -907,6 +907,104 @@
|
||||
RND_CATEGORY_MECHFAB_SAVANNAH_IVANOV + RND_SUBCATEGORY_MECHFAB_CHASSIS
|
||||
)
|
||||
|
||||
//Justice (emaged only)
|
||||
/datum/design/justice_chassis
|
||||
name = "Exosuit Chassis (\"Justice\")"
|
||||
id = "justice_chassis"
|
||||
build_type = MECHFAB
|
||||
build_path = /obj/item/mecha_parts/chassis/justice
|
||||
materials = list(/datum/material/iron=SHEET_MATERIAL_AMOUNT*20)
|
||||
construction_time = 10 SECONDS
|
||||
category = list(
|
||||
RND_CATEGORY_MECHFAB_JUSTICE + RND_SUBCATEGORY_MECHFAB_CHASSIS
|
||||
)
|
||||
|
||||
/datum/design/justice_torso
|
||||
name = "Exosuit Torso (\"Justice\")"
|
||||
id = "justice_torso"
|
||||
build_type = MECHFAB
|
||||
build_path = /obj/item/mecha_parts/part/justice_torso
|
||||
materials = list(
|
||||
/datum/material/iron = SHEET_MATERIAL_AMOUNT * 50,
|
||||
/datum/material/silver = SHEET_MATERIAL_AMOUNT * 5,
|
||||
)
|
||||
construction_time = 30 SECONDS
|
||||
category = list(
|
||||
RND_CATEGORY_MECHFAB_JUSTICE + RND_SUBCATEGORY_MECHFAB_CHASSIS
|
||||
)
|
||||
|
||||
/datum/design/justice_left_arm
|
||||
name = "Exosuit Left Arm (\"Justice\")"
|
||||
id = "justice_left_arm"
|
||||
build_type = MECHFAB
|
||||
build_path = /obj/item/mecha_parts/part/justice_left_arm
|
||||
materials = list(
|
||||
/datum/material/iron = SHEET_MATERIAL_AMOUNT * 5,
|
||||
/datum/material/silver = SHEET_MATERIAL_AMOUNT * 2,
|
||||
)
|
||||
construction_time = 10 SECONDS
|
||||
category = list(
|
||||
RND_CATEGORY_MECHFAB_JUSTICE + RND_SUBCATEGORY_MECHFAB_CHASSIS
|
||||
)
|
||||
|
||||
/datum/design/justice_right_arm
|
||||
name = "Exosuit Right Arm (\"Justice\")"
|
||||
id = "justice_right_arm"
|
||||
build_type = MECHFAB
|
||||
build_path = /obj/item/mecha_parts/part/justice_right_arm
|
||||
materials = list(
|
||||
/datum/material/iron=SHEET_MATERIAL_AMOUNT*5,
|
||||
/datum/material/silver=SHEET_MATERIAL_AMOUNT*2,
|
||||
)
|
||||
construction_time = 10 SECONDS
|
||||
category = list(
|
||||
RND_CATEGORY_MECHFAB_JUSTICE + RND_SUBCATEGORY_MECHFAB_CHASSIS
|
||||
)
|
||||
|
||||
/datum/design/justice_left_leg
|
||||
name = "Exosuit Left Leg (\"Justice\")"
|
||||
id = "justice_left_leg"
|
||||
build_type = MECHFAB
|
||||
build_path = /obj/item/mecha_parts/part/justice_left_leg
|
||||
materials = list(
|
||||
/datum/material/iron=SHEET_MATERIAL_AMOUNT*5,
|
||||
/datum/material/titanium=SHEET_MATERIAL_AMOUNT*2,
|
||||
)
|
||||
construction_time = 10 SECONDS
|
||||
category = list(
|
||||
RND_CATEGORY_MECHFAB_JUSTICE + RND_SUBCATEGORY_MECHFAB_CHASSIS
|
||||
)
|
||||
|
||||
/datum/design/justice_right_leg
|
||||
name = "Exosuit Right Leg (\"Justice\")"
|
||||
id = "justice_right_leg"
|
||||
build_type = MECHFAB
|
||||
build_path = /obj/item/mecha_parts/part/justice_right_leg
|
||||
materials = list(
|
||||
/datum/material/iron=SHEET_MATERIAL_AMOUNT*5,
|
||||
/datum/material/titanium=SHEET_MATERIAL_AMOUNT*2,
|
||||
)
|
||||
construction_time = 10 SECONDS
|
||||
category = list(
|
||||
RND_CATEGORY_MECHFAB_JUSTICE + RND_SUBCATEGORY_MECHFAB_CHASSIS
|
||||
)
|
||||
|
||||
/datum/design/justice_armor
|
||||
name = "Exosuit Armor (\"Justice\")"
|
||||
id = "justice_armor"
|
||||
build_type = MECHFAB
|
||||
build_path = /obj/item/mecha_parts/part/justice_armor
|
||||
materials = list(
|
||||
/datum/material/silver=SHEET_MATERIAL_AMOUNT*10,
|
||||
/datum/material/titanium=SHEET_MATERIAL_AMOUNT*10,
|
||||
/datum/material/plastic=SHEET_MATERIAL_AMOUNT*5,
|
||||
/datum/material/diamond=SHEET_MATERIAL_AMOUNT*1,
|
||||
)
|
||||
construction_time = 20 SECONDS
|
||||
category = list(
|
||||
RND_CATEGORY_MECHFAB_JUSTICE + RND_SUBCATEGORY_MECHFAB_CHASSIS
|
||||
)
|
||||
|
||||
//Clarke
|
||||
/datum/design/clarke_chassis
|
||||
name = "Exosuit Chassis (\"Clarke\")"
|
||||
|
||||
@@ -40,6 +40,8 @@
|
||||
var/list/experiments_to_unlock = list()
|
||||
/// Whether or not this node should show on the wiki
|
||||
var/show_on_wiki = TRUE
|
||||
/// Hidden Mech nodes unlocked when mech fabricator emaged.
|
||||
var/illegal_mech_node = FALSE
|
||||
|
||||
/datum/techweb_node/error_node
|
||||
id = "ERROR"
|
||||
|
||||
@@ -194,6 +194,22 @@
|
||||
)
|
||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_4_POINTS)
|
||||
|
||||
/datum/techweb_node/justice
|
||||
id = "mecha_justice"
|
||||
display_name = "EXOSUIT: Justice"
|
||||
description = "Justice exosuit designs"
|
||||
design_ids = list(
|
||||
"justice_armor",
|
||||
"justice_chassis",
|
||||
"justice_left_arm",
|
||||
"justice_left_leg",
|
||||
"justice_right_arm",
|
||||
"justice_right_leg",
|
||||
"justice_torso",
|
||||
)
|
||||
hidden = TRUE
|
||||
illegal_mech_node = TRUE
|
||||
|
||||
/datum/techweb_node/mech_energy_guns
|
||||
id = TECHWEB_NODE_MECH_ENERGY_GUNS
|
||||
display_name = "Mech Energy Guns"
|
||||
|
||||
@@ -390,3 +390,4 @@
|
||||
restricted = TRUE
|
||||
refundable = FALSE
|
||||
purchasable_from = parent_type::purchasable_from & ~UPLINK_SPY
|
||||
|
||||
|
||||
@@ -137,6 +137,15 @@
|
||||
var/stepsound = 'sound/mecha/mechstep.ogg'
|
||||
///Sound played when the mech walks
|
||||
var/turnsound = 'sound/mecha/mechturn.ogg'
|
||||
///Sounds for types of melee attack
|
||||
var/brute_attack_sound = 'sound/weapons/punch4.ogg'
|
||||
var/burn_attack_sound = 'sound/items/welder.ogg'
|
||||
var/tox_attack_sound = 'sound/effects/spray2.ogg'
|
||||
///Sound on wall destroying
|
||||
var/destroy_wall_sound = 'sound/effects/meteorimpact.ogg'
|
||||
|
||||
///Melee attack verb
|
||||
var/list/attack_verbs = list("hit", "hits", "hitting")
|
||||
|
||||
///Cooldown duration between melee punches
|
||||
var/melee_cooldown = CLICK_CD_SLOW
|
||||
@@ -151,6 +160,8 @@
|
||||
var/is_currently_ejecting = FALSE
|
||||
///Safety for weapons. Won't fire if enabled, and toggled by middle click.
|
||||
var/weapons_safety = FALSE
|
||||
///Don't play standard sound when set safety if TRUE.
|
||||
var/safety_sound_custom = FALSE
|
||||
|
||||
var/datum/effect_system/fluid_spread/smoke/smoke_system
|
||||
|
||||
@@ -365,7 +376,8 @@
|
||||
*/
|
||||
/obj/vehicle/sealed/mecha/proc/set_safety(mob/user)
|
||||
weapons_safety = !weapons_safety
|
||||
SEND_SOUND(user, sound('sound/machines/beep.ogg', volume = 25))
|
||||
if(!safety_sound_custom)
|
||||
SEND_SOUND(user, sound('sound/machines/beep.ogg', volume = 25))
|
||||
balloon_alert(user, "equipment [weapons_safety ? "safe" : "ready"]")
|
||||
set_mouse_pointer()
|
||||
SEND_SIGNAL(src, COMSIG_MECH_SAFETIES_TOGGLE, user, weapons_safety)
|
||||
@@ -905,3 +917,9 @@
|
||||
act.button_icon_state = "mech_lights_off"
|
||||
balloon_alert(occupant, "lights [mecha_flags & LIGHTS_ON ? "on":"off"]")
|
||||
act.build_all_button_icons()
|
||||
|
||||
/obj/vehicle/sealed/mecha/proc/melee_attack_effect(mob/living/victim, heavy)
|
||||
if(heavy)
|
||||
victim.Unconscious(2 SECONDS)
|
||||
else
|
||||
victim.Knockdown(4 SECONDS)
|
||||
|
||||
@@ -0,0 +1,535 @@
|
||||
#define DISMEMBER_CHANCE_HIGH 50
|
||||
#define DISMEMBER_CHANCE_LOW 25
|
||||
|
||||
#define MOVEDELAY_ANGRY 4.5
|
||||
#define MOVEDELAY_SAFETY 2.5
|
||||
|
||||
/obj/vehicle/sealed/mecha/justice
|
||||
name = "\improper Justice"
|
||||
desc = "Black and red syndicate mech designed for execution orders. \
|
||||
For safety reasons, the syndicate advises against standing too close."
|
||||
icon_state = "justice"
|
||||
base_icon_state = "justice"
|
||||
movedelay = MOVEDELAY_SAFETY // fast
|
||||
max_integrity = 200 // but weak
|
||||
accesses = list(ACCESS_SYNDICATE)
|
||||
armor_type = /datum/armor/mecha_justice
|
||||
max_temperature = 40000
|
||||
force = 60 // dangerous in melee
|
||||
damtype = BRUTE
|
||||
destruction_sleep_duration = 10
|
||||
exit_delay = 10
|
||||
wreckage = /obj/structure/mecha_wreckage/justice
|
||||
mech_type = EXOSUIT_MODULE_JUSTICE
|
||||
resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF
|
||||
mecha_flags = ID_LOCK_ON | QUIET_STEPS | QUIET_TURNS | CAN_STRAFE | HAS_LIGHTS | MMI_COMPATIBLE | IS_ENCLOSED
|
||||
destroy_wall_sound = 'sound/mecha/mech_blade_break_wall.ogg'
|
||||
brute_attack_sound = 'sound/mecha/mech_blade_attack.ogg'
|
||||
attack_verbs = list("cut", "cuts", "cutting")
|
||||
weapons_safety = TRUE
|
||||
safety_sound_custom = TRUE
|
||||
max_equip_by_category = list(
|
||||
MECHA_L_ARM = null,
|
||||
MECHA_R_ARM = null,
|
||||
MECHA_UTILITY = 3,
|
||||
MECHA_POWER = 1,
|
||||
MECHA_ARMOR = 2,
|
||||
)
|
||||
step_energy_drain = 2
|
||||
|
||||
/datum/armor/mecha_justice
|
||||
melee = 30
|
||||
bullet = 20
|
||||
laser = 20
|
||||
energy = 30
|
||||
fire = 100
|
||||
acid = 100
|
||||
|
||||
/obj/vehicle/sealed/mecha/justice/Initialize(mapload, built_manually)
|
||||
. = ..()
|
||||
RegisterSignal(src, COMSIG_MECHA_MELEE_CLICK, PROC_REF(justice_fatality)) //We do not hit those who are in crit or stun. We are finishing them.
|
||||
transform = transform.Scale(1.04, 1.04)
|
||||
|
||||
/obj/vehicle/sealed/mecha/justice/generate_actions()
|
||||
. = ..()
|
||||
initialize_passenger_action_type(/datum/action/vehicle/sealed/mecha/invisibility)
|
||||
initialize_passenger_action_type(/datum/action/vehicle/sealed/mecha/charge_attack)
|
||||
|
||||
/obj/vehicle/sealed/mecha/justice/update_icon_state()
|
||||
. = ..()
|
||||
if(LAZYLEN(occupants))
|
||||
icon_state = weapons_safety ? "[base_icon_state]" : "[base_icon_state]-angry"
|
||||
if(!has_gravity())
|
||||
icon_state = "[icon_state]-fly"
|
||||
|
||||
/obj/vehicle/sealed/mecha/justice/set_safety(mob/user)
|
||||
. = ..()
|
||||
if(weapons_safety)
|
||||
movedelay = MOVEDELAY_SAFETY
|
||||
else
|
||||
movedelay = MOVEDELAY_ANGRY
|
||||
|
||||
playsound(src, 'sound/mecha/mech_blade_safty.ogg', 75, FALSE) //everyone need to hear this sound
|
||||
|
||||
update_appearance(UPDATE_ICON_STATE)
|
||||
|
||||
/obj/vehicle/sealed/mecha/justice/Move(newloc, dir)
|
||||
if(HAS_TRAIT(src, TRAIT_IMMOBILIZED))
|
||||
return
|
||||
. = ..()
|
||||
update_appearance(UPDATE_ICON_STATE)
|
||||
|
||||
/// Says 1 of 3 epic phrases before attacking and make a finishing blow to targets in stun or crit after 1 SECOND.
|
||||
/obj/vehicle/sealed/mecha/justice/proc/justice_fatality(datum/source, mob/living/pilot, atom/target, on_cooldown, is_adjacent)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(!ishuman(target))
|
||||
return FALSE
|
||||
var/mob/living/carbon/human/live_or_dead = target
|
||||
if(live_or_dead.stat < UNCONSCIOUS && live_or_dead.getStaminaLoss() < 100)
|
||||
return FALSE
|
||||
var/obj/item/bodypart/check_head = live_or_dead.get_bodypart(BODY_ZONE_HEAD)
|
||||
if(!check_head)
|
||||
return FALSE
|
||||
INVOKE_ASYNC(src, PROC_REF(finish_him), src, pilot, live_or_dead)
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* ## finish_him
|
||||
*
|
||||
* Target's head is cut off (if it has one)
|
||||
* Attack from invisibility and charged attack have higher priority.
|
||||
* Arguments:
|
||||
* * finisher - Mech pilot who makes an attack.
|
||||
* * him - Target at which the mech makes an attack.
|
||||
*/
|
||||
/obj/vehicle/sealed/mecha/justice/proc/finish_him(obj/vehicle/sealed/mecha/my_mech, mob/finisher, mob/living/him)
|
||||
say(pick("Take my Justice-Slash!", "A falling leaf...", "Justice is quite a lonely path"), forced = "Justice Mech")
|
||||
playsound(src, 'sound/mecha/mech_stealth_pre_attack.ogg', 75, FALSE)
|
||||
if(!do_after(finisher, 1 SECONDS, him))
|
||||
return
|
||||
if(QDELETED(finisher))
|
||||
return
|
||||
if(QDELETED(him))
|
||||
return
|
||||
if(QDELETED(my_mech))
|
||||
return
|
||||
if(!LAZYLEN(my_mech.occupants))
|
||||
return
|
||||
var/turf/finish_turf = get_step(him, get_dir(my_mech, him))
|
||||
var/turf/for_line_turf = get_turf(my_mech)
|
||||
var/obj/item/bodypart/in_your_head = him.get_bodypart(BODY_ZONE_HEAD)
|
||||
in_your_head?.dismember(BRUTE)
|
||||
playsound(src, brute_attack_sound, 75, FALSE)
|
||||
for_line_turf.Beam(src, icon_state = "mech_charge", time = 8)
|
||||
forceMove(finish_turf)
|
||||
|
||||
/obj/vehicle/sealed/mecha/justice/melee_attack_effect(mob/living/victim, heavy)
|
||||
if(!heavy)
|
||||
victim.Knockdown(4 SECONDS)
|
||||
return
|
||||
if(!prob(DISMEMBER_CHANCE_HIGH))
|
||||
return
|
||||
var/obj/item/bodypart/cut_bodypart = victim.get_bodypart(pick(BODY_ZONE_R_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_ARM, BODY_ZONE_L_LEG))
|
||||
cut_bodypart?.dismember(BRUTE)
|
||||
|
||||
|
||||
/obj/vehicle/sealed/mecha/justice/mob_exit(mob/M, silent, randomstep, forced)
|
||||
. = ..()
|
||||
if(alpha == 255)
|
||||
return
|
||||
animate(src, alpha = 255, time = 0.5 SECONDS)
|
||||
playsound(src, 'sound/mecha/mech_stealth_effect.ogg' , 75, FALSE)
|
||||
|
||||
/obj/vehicle/sealed/mecha/justice/take_damage(damage_amount, damage_type, damage_flag, sound_effect, attack_dir, armour_penetration)
|
||||
if(LAZYLEN(occupants))
|
||||
if(prob(60))
|
||||
new /obj/effect/temp_visual/mech_sparks(get_turf(src))
|
||||
playsound(src, 'sound/mecha/mech_stealth_effect.ogg' , 75, FALSE)
|
||||
return
|
||||
return ..()
|
||||
|
||||
/datum/action/vehicle/sealed/mecha/invisibility
|
||||
name = "Invisibility"
|
||||
button_icon_state = "mech_stealth_off"
|
||||
/// Is invisibility activated.
|
||||
var/on = FALSE
|
||||
/// Recharge check.
|
||||
var/charge = TRUE
|
||||
/// Varset for invisibility timer
|
||||
var/invisibility_timer
|
||||
/// Energy cost to become invisibile
|
||||
var/energy_cost = 200
|
||||
/// Aoe pre attack sound.
|
||||
var/stealth_pre_attack_sound = 'sound/mecha/mech_stealth_pre_attack.ogg'
|
||||
/// Aoe attack sound.
|
||||
var/stealth_attack_sound = 'sound/mecha/mech_stealth_attack.ogg'
|
||||
|
||||
/datum/action/vehicle/sealed/mecha/invisibility/set_chassis(passed_chassis)
|
||||
. = ..()
|
||||
RegisterSignal(chassis, COMSIG_MECH_SAFETIES_TOGGLE, PROC_REF(on_toggle_safety))
|
||||
|
||||
/// update button icon when toggle safety.
|
||||
/datum/action/vehicle/sealed/mecha/invisibility/proc/on_toggle_safety()
|
||||
SIGNAL_HANDLER
|
||||
|
||||
build_all_button_icons(UPDATE_BUTTON_STATUS)
|
||||
|
||||
/datum/action/vehicle/sealed/mecha/invisibility/Trigger(trigger_flags)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
on = !on
|
||||
if(on)
|
||||
invisibility_on()
|
||||
else
|
||||
invisibility_off()
|
||||
|
||||
/datum/action/vehicle/sealed/mecha/invisibility/IsAvailable(feedback)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return FALSE
|
||||
if(!chassis.has_charge(energy_cost))
|
||||
if(feedback)
|
||||
owner.balloon_alert(owner, "not enough energy!")
|
||||
return FALSE
|
||||
if(chassis.weapons_safety)
|
||||
if(feedback)
|
||||
owner.balloon_alert(owner, "safety is on!")
|
||||
return FALSE
|
||||
if(!charge)
|
||||
if(feedback)
|
||||
owner.balloon_alert(owner, "recharging!")
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
///Called when invisibility activated.
|
||||
/datum/action/vehicle/sealed/mecha/invisibility/proc/invisibility_on()
|
||||
new /obj/effect/temp_visual/mech_sparks(get_turf(chassis))
|
||||
playsound(chassis, 'sound/mecha/mech_stealth_effect.ogg' , 75, FALSE)
|
||||
check_charge_attack()
|
||||
animate(chassis, alpha = 0, time = 0.5 SECONDS)
|
||||
button_icon_state = "mech_stealth_on"
|
||||
invisibility_timer = addtimer(CALLBACK(src, PROC_REF(end_stealth)), 20 SECONDS)
|
||||
RegisterSignal(chassis, COMSIG_MECHA_MELEE_CLICK, PROC_REF(stealth_attack_aoe))
|
||||
RegisterSignal(chassis, COMSIG_MOVABLE_BUMP, PROC_REF(bumb_on))
|
||||
RegisterSignal(chassis, COMSIG_ATOM_BUMPED, PROC_REF(bumbed_on))
|
||||
RegisterSignal(chassis, COMSIG_ATOM_TAKE_DAMAGE, PROC_REF(take_damage))
|
||||
chassis.use_energy(energy_cost)
|
||||
build_all_button_icons()
|
||||
|
||||
///Called when invisibility deactivated.
|
||||
/datum/action/vehicle/sealed/mecha/invisibility/proc/invisibility_off()
|
||||
new /obj/effect/temp_visual/mech_sparks(get_turf(chassis))
|
||||
playsound(chassis, 'sound/mecha/mech_stealth_effect.ogg' , 75, FALSE)
|
||||
invisibility_timer = null
|
||||
charge = FALSE
|
||||
addtimer(CALLBACK(src, PROC_REF(charge)), 5 SECONDS)
|
||||
button_icon_state = "mech_stealth_cooldown"
|
||||
animate(chassis, alpha = 255, time = 0.5 SECONDS)
|
||||
UnregisterSignal(chassis, list(
|
||||
COMSIG_MECHA_MELEE_CLICK,
|
||||
COMSIG_MOVABLE_BUMP,
|
||||
COMSIG_ATOM_BUMPED,
|
||||
COMSIG_ATOM_TAKE_DAMAGE
|
||||
))
|
||||
build_all_button_icons()
|
||||
|
||||
///Check if mech use charge attack and deactivate it when we activate invisibility.
|
||||
/datum/action/vehicle/sealed/mecha/invisibility/proc/check_charge_attack()
|
||||
for(var/mob/living/occupant in chassis.occupants)
|
||||
var/datum/action/vehicle/sealed/mecha/charge_attack/charge_action = LAZYACCESSASSOC(chassis.occupant_actions, occupant, /datum/action/vehicle/sealed/mecha/charge_attack)
|
||||
if(charge_action?.on)
|
||||
charge_action.on = !on
|
||||
charge_action.charge_attack_off()
|
||||
/**
|
||||
* ## end_stealth
|
||||
*
|
||||
* Called when mech runs out of invisibility time.
|
||||
*/
|
||||
/datum/action/vehicle/sealed/mecha/invisibility/proc/end_stealth()
|
||||
make_visible()
|
||||
|
||||
/**
|
||||
* ## bumb_on
|
||||
*
|
||||
* Called when mech bumb on somthing. If is living somthing shutdown mech invisibility.
|
||||
*/
|
||||
/datum/action/vehicle/sealed/mecha/invisibility/proc/bumb_on(obj/vehicle/sealed/mecha/our_mech, atom/obstacle)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(!isliving(obstacle))
|
||||
return
|
||||
make_visible()
|
||||
|
||||
/**
|
||||
* ## bumbed_on
|
||||
*
|
||||
* Called when somthing bumbed on mech. If is living somthing shutdown mech invisibility.
|
||||
*/
|
||||
/datum/action/vehicle/sealed/mecha/invisibility/proc/bumbed_on(obj/vehicle/sealed/mecha/our_mech, atom/movable/bumped_atom)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(!isliving(bumped_atom))
|
||||
return
|
||||
make_visible()
|
||||
|
||||
/**
|
||||
* ## take_damage
|
||||
*
|
||||
* Called when mech take damage. Shutdown mech invisibility.
|
||||
*/
|
||||
/datum/action/vehicle/sealed/mecha/invisibility/proc/take_damage(obj/vehicle/sealed/mecha/our_mech)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
make_visible()
|
||||
|
||||
/**
|
||||
* ## make_visible
|
||||
*
|
||||
* Called when somthing force invisibility shutdown.
|
||||
*/
|
||||
/datum/action/vehicle/sealed/mecha/invisibility/proc/make_visible()
|
||||
if(!on)
|
||||
return
|
||||
on = !on
|
||||
invisibility_off()
|
||||
|
||||
/**
|
||||
* Proc makes an AOE attack after 1 SECOND.
|
||||
* Called by the mech pilot when he is in stealth mode and wants to attack.
|
||||
* During this, mech cannot move.
|
||||
*/
|
||||
/datum/action/vehicle/sealed/mecha/invisibility/proc/stealth_attack_aoe(datum/source, mob/living/pilot, atom/target, on_cooldown, is_adjacent)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(!charge)
|
||||
return FALSE
|
||||
if(chassis.alpha != 0)
|
||||
UnregisterSignal(chassis, COMSIG_MECHA_MELEE_CLICK)
|
||||
return FALSE
|
||||
UnregisterSignal(chassis, COMSIG_MECHA_MELEE_CLICK)
|
||||
new /obj/effect/temp_visual/mech_attack_aoe_charge(get_turf(chassis))
|
||||
ADD_TRAIT(chassis, TRAIT_IMMOBILIZED, REF(src))
|
||||
playsound(chassis, stealth_pre_attack_sound, 75, FALSE)
|
||||
addtimer(CALLBACK(src, PROC_REF(attack_in_aoe), pilot), 1 SECONDS)
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* ## attack_in_aoe
|
||||
*
|
||||
* Brings mech out of invisibility.
|
||||
* Deal everyone in range 3x3 35 damage and 25 chanse to cut off limb.
|
||||
* Arguments:
|
||||
* * pilot - occupant inside mech.
|
||||
*/
|
||||
/datum/action/vehicle/sealed/mecha/invisibility/proc/attack_in_aoe(mob/living/pilot)
|
||||
invisibility_off()
|
||||
new /obj/effect/temp_visual/mech_attack_aoe_attack(get_turf(chassis))
|
||||
for(var/mob/living/something_living in range(1, get_turf(chassis)))
|
||||
if(something_living.stat >= UNCONSCIOUS)
|
||||
continue
|
||||
if(something_living.getStaminaLoss() >= 100)
|
||||
continue
|
||||
if(something_living == pilot)
|
||||
continue
|
||||
if(prob(DISMEMBER_CHANCE_LOW))
|
||||
var/obj/item/bodypart/cut_bodypart = something_living.get_bodypart(pick(BODY_ZONE_R_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_ARM, BODY_ZONE_L_LEG))
|
||||
cut_bodypart?.dismember(BRUTE)
|
||||
something_living.apply_damage(35, BRUTE)
|
||||
playsound(chassis, stealth_attack_sound, 75, FALSE)
|
||||
REMOVE_TRAIT(chassis, TRAIT_IMMOBILIZED, REF(src))
|
||||
on = !on
|
||||
charge = FALSE
|
||||
button_icon_state = "mech_stealth_cooldown"
|
||||
build_all_button_icons()
|
||||
addtimer(CALLBACK(src, PROC_REF(charge)), 5 SECONDS)
|
||||
|
||||
/**
|
||||
* ## charge
|
||||
*
|
||||
* Recharge invisibility action after 5 SECONDS.
|
||||
*/
|
||||
/datum/action/vehicle/sealed/mecha/invisibility/proc/charge()
|
||||
button_icon_state = "mech_stealth_off"
|
||||
charge = TRUE
|
||||
build_all_button_icons()
|
||||
|
||||
/datum/action/vehicle/sealed/mecha/charge_attack
|
||||
name = "Charge Attack"
|
||||
button_icon_state = "mech_charge_off"
|
||||
/// Is charge attack activated.
|
||||
var/on = FALSE
|
||||
/// Recharge check.
|
||||
var/charge = TRUE
|
||||
/// Energy cost to perform charge attack
|
||||
var/energy_cost = 400
|
||||
/// Maximum range of charge attack.
|
||||
var/max_charge_range = 7
|
||||
/// Sound when mech do charge attack.
|
||||
var/charge_attack_sound = 'sound/mecha/mech_charge_attack.ogg'
|
||||
|
||||
/datum/action/vehicle/sealed/mecha/charge_attack/set_chassis(passed_chassis)
|
||||
. = ..()
|
||||
RegisterSignal(chassis, COMSIG_MECH_SAFETIES_TOGGLE, PROC_REF(on_toggle_safety))
|
||||
|
||||
/// update button icon when toggle safety.
|
||||
/datum/action/vehicle/sealed/mecha/charge_attack/proc/on_toggle_safety()
|
||||
SIGNAL_HANDLER
|
||||
|
||||
build_all_button_icons(UPDATE_BUTTON_STATUS)
|
||||
|
||||
/datum/action/vehicle/sealed/mecha/charge_attack/Trigger(trigger_flags)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
on = !on
|
||||
if(on)
|
||||
charge_attack_on()
|
||||
else
|
||||
charge_attack_off()
|
||||
|
||||
/datum/action/vehicle/sealed/mecha/charge_attack/IsAvailable(feedback)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return FALSE
|
||||
if(!chassis.has_charge(energy_cost))
|
||||
if(feedback)
|
||||
owner.balloon_alert(owner, "not enough energy!")
|
||||
return FALSE
|
||||
if(chassis.weapons_safety)
|
||||
if(feedback)
|
||||
owner.balloon_alert(owner, "safety is on!")
|
||||
return FALSE
|
||||
if(!charge)
|
||||
if(feedback)
|
||||
owner.balloon_alert(owner, "recharging!")
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
///Called when charge attack activated
|
||||
/datum/action/vehicle/sealed/mecha/charge_attack/proc/charge_attack_on()
|
||||
check_visability()
|
||||
button_icon_state = "mech_charge_on"
|
||||
RegisterSignal(chassis, COMSIG_MECHA_MELEE_CLICK, PROC_REF(click_try_charge))
|
||||
build_all_button_icons()
|
||||
|
||||
///Called when charge attack deactivated
|
||||
/datum/action/vehicle/sealed/mecha/charge_attack/proc/charge_attack_off()
|
||||
button_icon_state = "mech_charge_off"
|
||||
UnregisterSignal(chassis, COMSIG_MECHA_MELEE_CLICK)
|
||||
build_all_button_icons()
|
||||
|
||||
///Check if mech use invisibility and deactivate it when we activate charge attack.
|
||||
/datum/action/vehicle/sealed/mecha/charge_attack/proc/check_visability()
|
||||
for(var/who_inside in chassis.occupants)
|
||||
var/mob/living/occupant = who_inside
|
||||
var/datum/action/vehicle/sealed/mecha/invisibility/stealth_action = LAZYACCESSASSOC(chassis.occupant_actions, occupant, /datum/action/vehicle/sealed/mecha/invisibility)
|
||||
if(stealth_action?.on)
|
||||
stealth_action.make_visible()
|
||||
|
||||
///Called when mech attacks with charge attack enabled.
|
||||
/datum/action/vehicle/sealed/mecha/charge_attack/proc/click_try_charge(datum/source, mob/living/pilot, atom/target, on_cooldown, is_adjacent)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
var/turf = get_turf(target)
|
||||
if(!on)
|
||||
UnregisterSignal(chassis, COMSIG_MECHA_MELEE_CLICK)
|
||||
return FALSE
|
||||
if(isnull(turf))
|
||||
pilot.balloon_alert(pilot, "invalid direction!")
|
||||
return FALSE
|
||||
if(!charge)
|
||||
pilot.balloon_alert(pilot, "recharging!")
|
||||
return FALSE
|
||||
else
|
||||
if(charge_attack(pilot, turf))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/**
|
||||
* ## charge_attack
|
||||
*
|
||||
* Deal everyone in line for mech location to mouse location 35 damage and 25 chanse to cut off limb.
|
||||
* Teleport mech to the end of line.
|
||||
* Arguments:
|
||||
* * charger - occupant inside mech.
|
||||
* * target - occupant inside mech.
|
||||
*/
|
||||
/datum/action/vehicle/sealed/mecha/charge_attack/proc/charge_attack(mob/living/charger, turf/target)
|
||||
var/turf/start_charge_here = get_turf(charger)
|
||||
var/charge_range = min(get_dist_euclidean(start_charge_here, target), max_charge_range)
|
||||
var/turf/but_we_gonna_here = get_ranged_target_turf(start_charge_here, get_dir(start_charge_here, target), floor(charge_range))
|
||||
var/turf/here_we_go = start_charge_here
|
||||
for(var/turf/line_turf in get_line(get_step(start_charge_here, get_dir(start_charge_here, target)), but_we_gonna_here))
|
||||
if(get_turf(charger) == get_turf(line_turf))
|
||||
continue
|
||||
if(isclosedturf(line_turf))
|
||||
break
|
||||
var/obj/machinery/power/supermatter_crystal/funny_crystal = locate() in line_turf
|
||||
if(funny_crystal)
|
||||
funny_crystal.Bumped(chassis)
|
||||
break
|
||||
var/obj/machinery/door/airlock/like_a_wall = locate() in line_turf
|
||||
if(like_a_wall?.density)
|
||||
break
|
||||
if(locate(/obj/structure/window) in line_turf)
|
||||
break
|
||||
for(var/mob/living/something_living in line_turf.contents)
|
||||
if(something_living.stat >= UNCONSCIOUS || something_living.getStaminaLoss() >= 100 || something_living == charger)
|
||||
continue
|
||||
if(prob(DISMEMBER_CHANCE_LOW))
|
||||
var/obj/item/bodypart/cut_bodypart = something_living.get_bodypart(pick(BODY_ZONE_R_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_ARM, BODY_ZONE_L_LEG, BODY_ZONE_HEAD))
|
||||
cut_bodypart?.dismember(BRUTE)
|
||||
something_living.apply_damage(35, BRUTE)
|
||||
here_we_go = line_turf
|
||||
|
||||
// If the mech didn't move, it didn't charge
|
||||
if(here_we_go == start_charge_here)
|
||||
charger.balloon_alert(charger, "invalid direction!")
|
||||
return FALSE
|
||||
chassis.forceMove(here_we_go)
|
||||
start_charge_here.Beam(chassis, icon_state = "mech_charge", time = 8)
|
||||
playsound(chassis, charge_attack_sound, 75, FALSE)
|
||||
on = !on
|
||||
chassis.use_energy(energy_cost)
|
||||
UnregisterSignal(chassis, COMSIG_MECHA_MELEE_CLICK)
|
||||
charge = FALSE
|
||||
button_icon_state = "mech_charge_cooldown"
|
||||
build_all_button_icons()
|
||||
addtimer(CALLBACK(src, PROC_REF(charge)), 5 SECONDS)
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* ## charge
|
||||
*
|
||||
* Recharge charge attack action after 5 SECONDS.
|
||||
*/
|
||||
/datum/action/vehicle/sealed/mecha/charge_attack/proc/charge()
|
||||
charge = TRUE
|
||||
button_icon_state = "mech_charge_off"
|
||||
build_all_button_icons()
|
||||
|
||||
/obj/vehicle/sealed/mecha/justice/loaded
|
||||
equip_by_category = list(
|
||||
MECHA_L_ARM = null,
|
||||
MECHA_R_ARM = null,
|
||||
MECHA_UTILITY = list(/obj/item/mecha_parts/mecha_equipment/radio, /obj/item/mecha_parts/mecha_equipment/air_tank/full, /obj/item/mecha_parts/mecha_equipment/thrusters/ion),
|
||||
MECHA_POWER = list(),
|
||||
MECHA_ARMOR = list(),
|
||||
)
|
||||
|
||||
/obj/vehicle/sealed/mecha/justice/loaded/populate_parts()
|
||||
cell = new /obj/item/stock_parts/power_store/cell/bluespace(src)
|
||||
scanmod = new /obj/item/stock_parts/scanning_module/triphasic(src)
|
||||
capacitor = new /obj/item/stock_parts/capacitor/quadratic(src)
|
||||
servo = new /obj/item/stock_parts/servo/femto(src)
|
||||
update_part_values()
|
||||
|
||||
#undef DISMEMBER_CHANCE_HIGH
|
||||
#undef DISMEMBER_CHANCE_LOW
|
||||
|
||||
#undef MOVEDELAY_ANGRY
|
||||
#undef MOVEDELAY_SAFETY
|
||||
@@ -52,10 +52,14 @@
|
||||
//looping sound for printing items
|
||||
var/datum/looping_sound/lathe_print/print_sound
|
||||
|
||||
/// Local designs that only this mechfab have(using when mechfab emaged so it's illegal designs).
|
||||
var/list/datum/design/illegal_local_designs
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/Initialize(mapload)
|
||||
print_sound = new(src, FALSE)
|
||||
rmat = AddComponent(/datum/component/remote_materials, mapload && link_on_init)
|
||||
cached_designs = list()
|
||||
illegal_local_designs = list()
|
||||
RefreshParts() //Recalculating local material sizes if the fab isn't linked
|
||||
return ..()
|
||||
|
||||
@@ -142,6 +146,26 @@
|
||||
balloon_alert(user, "rotated to [dir2text(dir)].")
|
||||
return CLICK_ACTION_SUCCESS
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/emag_act(mob/user, obj/item/card/emag/emag_card)
|
||||
if(obj_flags & EMAGGED)
|
||||
return FALSE
|
||||
if(user.job != JOB_ROBOTICIST)
|
||||
to_chat(user, span_warning("You clicking and typing but don’t understand what to do with it"))
|
||||
return FALSE
|
||||
obj_flags |= EMAGGED
|
||||
for(var/found_illegal_mech_nods in SSresearch.techweb_nodes)
|
||||
var/datum/techweb_node/illegal_mech_node = SSresearch.techweb_nodes[found_illegal_mech_nods]
|
||||
if(!illegal_mech_node?.illegal_mech_node)
|
||||
continue
|
||||
for(var/id in illegal_mech_node.design_ids)
|
||||
var/datum/design/illegal_mech_design = SSresearch.techweb_design_by_id(id)
|
||||
illegal_local_designs |= illegal_mech_design
|
||||
cached_designs |= illegal_mech_design
|
||||
say("R$c!i&ed ERROR de#i$ns. C@n%ec$%ng to ~NULL~ se%ve$s.")
|
||||
playsound(src, 'sound/machines/uplinkerror.ogg', 50, TRUE)
|
||||
update_static_data_for_all_viewers()
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Updates the `final_sets` and `buildable_parts` for the current mecha fabricator.
|
||||
*/
|
||||
@@ -418,7 +442,7 @@
|
||||
if(!istext(design_id))
|
||||
continue
|
||||
|
||||
if(!stored_research.researched_designs.Find(design_id))
|
||||
if(!(stored_research.researched_designs.Find(design_id) || is_type_in_list(SSresearch.techweb_design_by_id(design_id), illegal_local_designs)))
|
||||
continue
|
||||
|
||||
var/datum/design/design = SSresearch.techweb_design_by_id(design_id)
|
||||
|
||||
@@ -21,15 +21,15 @@
|
||||
mecha_attacker.do_attack_animation(src)
|
||||
switch(mecha_attacker.damtype)
|
||||
if(BRUTE)
|
||||
playsound(src, 'sound/weapons/punch4.ogg', 50, TRUE)
|
||||
playsound(src, mecha_attacker.brute_attack_sound, 50, TRUE)
|
||||
if(BURN)
|
||||
playsound(src, 'sound/items/welder.ogg', 50, TRUE)
|
||||
playsound(src, mecha_attacker.burn_attack_sound, 50, TRUE)
|
||||
else
|
||||
return 0
|
||||
mecha_attacker.visible_message(span_danger("[mecha_attacker] hits [src]!"), span_danger("You hit [src]!"), null, COMBAT_MESSAGE_RANGE)
|
||||
if(prob(hardness + mecha_attacker.force) && mecha_attacker.force > 20)
|
||||
dismantle_wall(1)
|
||||
playsound(src, 'sound/effects/meteorimpact.ogg', 100, TRUE)
|
||||
playsound(src, mecha_attacker.destroy_wall_sound, 100, TRUE)
|
||||
else
|
||||
add_dent(WALL_DENT_HIT)
|
||||
..()
|
||||
@@ -58,9 +58,9 @@
|
||||
mecha_attacker.do_attack_animation(src)
|
||||
switch(mecha_attacker.damtype)
|
||||
if(BRUTE)
|
||||
playsound(src, 'sound/weapons/punch4.ogg', 50, TRUE)
|
||||
playsound(src, mecha_attacker.brute_attack_sound, 50, TRUE)
|
||||
if(BURN)
|
||||
playsound(src, 'sound/items/welder.ogg', 50, TRUE)
|
||||
playsound(src, mecha_attacker.burn_attack_sound, 50, TRUE)
|
||||
else
|
||||
return 0
|
||||
mecha_attacker.visible_message(span_danger("[mecha_attacker] hits [src]!"), span_danger("You hit [src]!"), null, COMBAT_MESSAGE_RANGE)
|
||||
@@ -88,29 +88,34 @@
|
||||
if(mecha_attacker.damtype == BRUTE)
|
||||
step_away(src, mecha_attacker, 15)
|
||||
var/obj/item/bodypart/selected_zone = get_bodypart(pick(BODY_ZONE_CHEST, BODY_ZONE_CHEST, BODY_ZONE_CHEST, BODY_ZONE_HEAD))
|
||||
if(selected_zone)
|
||||
var/dmg = rand(mecha_attacker.force * 0.5, mecha_attacker.force)
|
||||
switch(mecha_attacker.damtype)
|
||||
if(BRUTE)
|
||||
if(mecha_attacker.force > 35) // durand and other heavy mechas
|
||||
Unconscious(20)
|
||||
else if(mecha_attacker.force > 20 && !IsKnockdown()) // lightweight mechas like gygax
|
||||
Knockdown(40)
|
||||
var/dmg = rand(mecha_attacker.force * 0.5, mecha_attacker.force)
|
||||
switch(mecha_attacker.damtype)
|
||||
if(BRUTE)
|
||||
if(mecha_attacker.force > 35) // durand and other heavy mechas
|
||||
mecha_attacker.melee_attack_effect(src, heavy = TRUE)
|
||||
else if(mecha_attacker.force > 20 && !IsKnockdown()) // lightweight mechas like gygax
|
||||
mecha_attacker.melee_attack_effect(src, heavy = FALSE)
|
||||
if(selected_zone)
|
||||
selected_zone.receive_damage(dmg, 0, updating_health = TRUE)
|
||||
playsound(src, 'sound/weapons/punch4.ogg', 50, TRUE)
|
||||
if(FIRE)
|
||||
selected_zone.receive_damage(0, dmg, updating_health = TRUE)
|
||||
playsound(src, 'sound/items/welder.ogg', 50, TRUE)
|
||||
if(TOX)
|
||||
playsound(src, 'sound/effects/spray2.ogg', 50, TRUE)
|
||||
if((reagents.get_reagent_amount(/datum/reagent/cryptobiolin) + mecha_attacker.force) < mecha_attacker.force*2)
|
||||
reagents.add_reagent(/datum/reagent/cryptobiolin, mecha_attacker.force/2)
|
||||
if((reagents.get_reagent_amount(/datum/reagent/toxin) + mecha_attacker.force) < mecha_attacker.force*2)
|
||||
reagents.add_reagent(/datum/reagent/toxin, mecha_attacker.force/2.5)
|
||||
else
|
||||
return 0
|
||||
. = dmg
|
||||
visible_message(span_danger("[mecha_attacker.name] hits [src]!"), \
|
||||
span_userdanger("[mecha_attacker.name] hits you!"), span_hear("You hear a sickening sound of flesh hitting flesh!"), COMBAT_MESSAGE_RANGE, list(mecha_attacker))
|
||||
to_chat(mecha_attacker, span_danger("You hit [src]!"))
|
||||
apply_damage(dmg, BRUTE)
|
||||
playsound(src, mecha_attacker.brute_attack_sound, 50, TRUE)
|
||||
if(FIRE)
|
||||
if(selected_zone)
|
||||
selected_zone.receive_damage(0, dmg, updating_health = TRUE)
|
||||
else
|
||||
apply_damage(dmg, BURN)
|
||||
playsound(src, mecha_attacker.burn_attack_sound, 50, TRUE)
|
||||
if(TOX)
|
||||
playsound(src, mecha_attacker.tox_attack_sound, 50, TRUE)
|
||||
if((reagents.get_reagent_amount(/datum/reagent/cryptobiolin) + mecha_attacker.force) < mecha_attacker.force*2)
|
||||
reagents.add_reagent(/datum/reagent/cryptobiolin, mecha_attacker.force/2)
|
||||
if((reagents.get_reagent_amount(/datum/reagent/toxin) + mecha_attacker.force) < mecha_attacker.force*2)
|
||||
reagents.add_reagent(/datum/reagent/toxin, mecha_attacker.force/2.5)
|
||||
else
|
||||
return 0
|
||||
. = dmg
|
||||
visible_message(span_danger("[mecha_attacker.name] [mecha_attacker.attack_verbs[1]] [src]!"), \
|
||||
span_userdanger("[mecha_attacker.name] [mecha_attacker.attack_verbs[2]] you!"), span_hear("You hear a sickening sound of flesh [mecha_attacker.attack_verbs[3]] flesh!"), COMBAT_MESSAGE_RANGE, list(mecha_attacker))
|
||||
to_chat(mecha_attacker, span_danger("You [mecha_attacker.attack_verbs[1]] [src]!"))
|
||||
..()
|
||||
|
||||
@@ -819,3 +819,39 @@
|
||||
|
||||
outer_plating = /obj/item/stack/sheet/plasteel
|
||||
outer_plating_amount = 5
|
||||
|
||||
//Justice
|
||||
/datum/component/construction/unordered/mecha_chassis/justice
|
||||
result = /datum/component/construction/mecha/justice
|
||||
steps = list(
|
||||
/obj/item/mecha_parts/part/justice_torso,
|
||||
/obj/item/mecha_parts/part/justice_left_arm,
|
||||
/obj/item/mecha_parts/part/justice_right_arm,
|
||||
/obj/item/mecha_parts/part/justice_left_leg,
|
||||
/obj/item/mecha_parts/part/justice_right_leg
|
||||
)
|
||||
|
||||
/datum/component/construction/mecha/justice
|
||||
result = /obj/vehicle/sealed/mecha/justice
|
||||
base_icon = "justice"
|
||||
|
||||
inner_plating = /obj/item/stack/telecrystal
|
||||
inner_plating_amount = 8
|
||||
|
||||
outer_plating = /obj/item/mecha_parts/part/justice_armor
|
||||
outer_plating_amount = 1
|
||||
|
||||
/datum/component/construction/mecha/justice/get_circuit_steps()
|
||||
return list()
|
||||
|
||||
/datum/component/construction/mecha/justice/get_inner_plating_steps()
|
||||
return list(
|
||||
list(
|
||||
"key" = inner_plating,
|
||||
"amount" = inner_plating_amount,
|
||||
"back_key" = TOOL_SCREWDRIVER,
|
||||
"desc" = "The power cell is secured, and [inner_plating_amount] <b>telecrystals</b> can be added.",
|
||||
"forward_message" = "added telecrystal",
|
||||
"backward_message" = "unsecured power cell"
|
||||
)
|
||||
)
|
||||
|
||||
@@ -332,6 +332,42 @@
|
||||
desc="Savannah-Ivanov armor plates. They are uniquely shaped and reinforced to deal with the stresses of two pilots, grandiose leaps, and missiles."
|
||||
icon_state = "savannah_ivanov_armor"
|
||||
|
||||
// Justice
|
||||
|
||||
/obj/item/mecha_parts/chassis/justice
|
||||
name = "\improper Justice chassis"
|
||||
construct_type = /datum/component/construction/unordered/mecha_chassis/justice
|
||||
|
||||
/obj/item/mecha_parts/part/justice_torso
|
||||
name="\improper Justice torso"
|
||||
desc="A Justice torso part."
|
||||
icon_state = "justice_torso"
|
||||
|
||||
/obj/item/mecha_parts/part/justice_left_arm
|
||||
name="\improper Justice left arm"
|
||||
desc="A Justice left arm."
|
||||
icon_state = "justice_l_arm"
|
||||
|
||||
/obj/item/mecha_parts/part/justice_right_arm
|
||||
name="\improper Justice right arm"
|
||||
desc="A Justice left arm."
|
||||
icon_state = "justice_r_arm"
|
||||
|
||||
/obj/item/mecha_parts/part/justice_left_leg
|
||||
name="\improper Justice left leg"
|
||||
desc="A Justice left leg."
|
||||
icon_state = "justice_l_leg"
|
||||
|
||||
/obj/item/mecha_parts/part/justice_right_leg
|
||||
name="\improper Justice right leg"
|
||||
desc="A Justice left leg."
|
||||
icon_state = "justice_r_leg"
|
||||
|
||||
/obj/item/mecha_parts/part/justice_armor
|
||||
name="Justice armor"
|
||||
desc="Justice armor plates."
|
||||
icon_state = "justice_armor"
|
||||
|
||||
///////// Circuitboards
|
||||
|
||||
/obj/item/circuitboard/mecha
|
||||
|
||||
@@ -111,16 +111,17 @@
|
||||
var/module_index = 0
|
||||
for(var/category in max_equip_by_category)
|
||||
var/max_per_category = max_equip_by_category[category]
|
||||
for(var/i = 1 to max_per_category)
|
||||
var/equipment = equip_by_category[category]
|
||||
var/is_slot_free = islist(equipment) ? i > length(equipment) : isnull(equipment)
|
||||
if(is_slot_free)
|
||||
data += list(list(
|
||||
"slot" = category
|
||||
))
|
||||
if(ui_selected_module_index == module_index)
|
||||
ui_selected_module_index = null
|
||||
else
|
||||
if(max_per_category)
|
||||
for(var/i = 1 to max_per_category)
|
||||
var/equipment = equip_by_category[category]
|
||||
var/is_slot_free = islist(equipment) ? i > length(equipment) : isnull(equipment)
|
||||
if(is_slot_free)
|
||||
data += list(list(
|
||||
"slot" = category
|
||||
))
|
||||
if(ui_selected_module_index == module_index)
|
||||
ui_selected_module_index = null
|
||||
continue
|
||||
var/obj/item/mecha_parts/mecha_equipment/module = islist(equipment) ? equipment[i] : equipment
|
||||
data += list(list(
|
||||
"slot" = category,
|
||||
@@ -140,7 +141,7 @@
|
||||
))
|
||||
if(isnull(ui_selected_module_index))
|
||||
ui_selected_module_index = module_index
|
||||
module_index++
|
||||
module_index++
|
||||
return data
|
||||
|
||||
/obj/vehicle/sealed/mecha/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
|
||||
|
||||
@@ -245,3 +245,8 @@
|
||||
/obj/item/mecha_parts/part/odysseus_right_arm,
|
||||
/obj/item/mecha_parts/part/odysseus_left_leg,
|
||||
/obj/item/mecha_parts/part/odysseus_right_leg)
|
||||
|
||||
/obj/structure/mecha_wreckage/justice
|
||||
name = "\improper Justice wreckage"
|
||||
icon_state = "justice-broken"
|
||||
welder_salvage = list(/obj/item/stack/sheet/iron, /obj/item/stack/rods)
|
||||
|
||||
|
Before Width: | Height: | Size: 1.9 MiB After Width: | Height: | Size: 2.0 MiB |
|
Before Width: | Height: | Size: 128 KiB After Width: | Height: | Size: 128 KiB |
|
Before Width: | Height: | Size: 904 KiB After Width: | Height: | Size: 904 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 86 KiB After Width: | Height: | Size: 93 KiB |
|
Before Width: | Height: | Size: 112 KiB After Width: | Height: | Size: 182 KiB |
@@ -6101,6 +6101,7 @@
|
||||
#include "code\modules\vehicles\mecha\combat\durand.dm"
|
||||
#include "code\modules\vehicles\mecha\combat\gygax.dm"
|
||||
#include "code\modules\vehicles\mecha\combat\honker.dm"
|
||||
#include "code\modules\vehicles\mecha\combat\justice.dm"
|
||||
#include "code\modules\vehicles\mecha\combat\marauder.dm"
|
||||
#include "code\modules\vehicles\mecha\combat\phazon.dm"
|
||||
#include "code\modules\vehicles\mecha\combat\reticence.dm"
|
||||
|
||||