mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-24 13:38:41 +01:00
## About The Pull Request Mechs store almost all of their behaviors on base /mecha type, such as Maradeur's smoke charges and zoom or Phazon's phasing. I've moved all mech type specific variables and interactions onto their own types, cleaned up general code and refactored how Durand's shield is handled (it is now displayed in vis_contents and no longer an object present on the turf) ## Changelog 🆑 code: Cleaned up generic mech code and moved subtype specific behaviors to said subtypes refactor: Refactored how Durand's shield works /🆑
225 lines
7.9 KiB
Plaintext
225 lines
7.9 KiB
Plaintext
/obj/vehicle/sealed/mecha/durand
|
|
desc = "An aging combat exosuit utilized by the Nanotrasen corporation. Originally developed to combat hostile alien lifeforms."
|
|
name = "\improper Durand"
|
|
icon_state = "durand"
|
|
base_icon_state = "durand"
|
|
movedelay = 4
|
|
max_integrity = 400
|
|
accesses = list(ACCESS_MECH_SCIENCE, ACCESS_MECH_SECURITY)
|
|
armor_type = /datum/armor/mecha_durand
|
|
max_temperature = 30000
|
|
force = 40
|
|
destruction_sleep_duration = 40
|
|
exit_delay = 40
|
|
wreckage = /obj/structure/mecha_wreckage/durand
|
|
mech_type = EXOSUIT_MODULE_DURAND
|
|
max_equip_by_category = list(
|
|
MECHA_L_ARM = 1,
|
|
MECHA_R_ARM = 1,
|
|
MECHA_UTILITY = 3,
|
|
MECHA_POWER = 1,
|
|
MECHA_ARMOR = 1,
|
|
)
|
|
|
|
/// Bool for energy shield on/off
|
|
var/defense_mode = FALSE
|
|
/// Fake shield object we use as a way to redirect attacks off ourselves
|
|
var/obj/durand_shield/shield = null
|
|
/// Is the shield currently switching modes?
|
|
var/switching = FALSE
|
|
|
|
/datum/armor/mecha_durand
|
|
melee = 40
|
|
bullet = 35
|
|
laser = 15
|
|
energy = 10
|
|
bomb = 20
|
|
fire = 100
|
|
acid = 100
|
|
|
|
/obj/vehicle/sealed/mecha/durand/Initialize(mapload)
|
|
. = ..()
|
|
shield = new(src, src)
|
|
vis_contents += shield
|
|
|
|
/obj/vehicle/sealed/mecha/durand/Destroy()
|
|
if(shield)
|
|
QDEL_NULL(shield)
|
|
return ..()
|
|
|
|
/obj/vehicle/sealed/mecha/durand/generate_actions()
|
|
. = ..()
|
|
initialize_passenger_action_type(/datum/action/vehicle/sealed/mecha/mech_defense_mode)
|
|
|
|
/obj/vehicle/sealed/mecha/durand/process()
|
|
. = ..()
|
|
// Defence mode can only be on with a occupant so we check if one of them can toggle it and toggle
|
|
if(defense_mode && !use_energy(0.01 * STANDARD_CELL_CHARGE))
|
|
toggle_defense()
|
|
|
|
/obj/vehicle/sealed/mecha/durand/mob_exit(mob/M, silent = FALSE, randomstep = FALSE, forced = FALSE)
|
|
if(defense_mode)
|
|
toggle_defense()
|
|
return ..()
|
|
|
|
//Redirects projectiles to the shield if defense_check decides they should be blocked and returns true.
|
|
/obj/vehicle/sealed/mecha/durand/projectile_hit(obj/projectile/hitting_projectile, def_zone, piercing_hit, blocked)
|
|
if(defense_check(hitting_projectile.loc) && shield)
|
|
return shield.projectile_hit(hitting_projectile, def_zone, piercing_hit, blocked)
|
|
return ..()
|
|
|
|
/**
|
|
* Checks if defense mode is enabled, and if the attacker is standing in an area covered by the shield.
|
|
* Expects a turf. Returns true if the attack should be blocked, false if not.
|
|
**/
|
|
/obj/vehicle/sealed/mecha/durand/proc/defense_check(turf/aloc)
|
|
if (!defense_mode || !shield || switching)
|
|
return FALSE
|
|
|
|
switch(dir)
|
|
if (NORTH)
|
|
return abs(x - aloc.x) <= (y - aloc.y) * -2
|
|
if (SOUTH)
|
|
return abs(x - aloc.x) <= (y - aloc.y) * 2
|
|
if (EAST)
|
|
return abs(y - aloc.y) <= (x - aloc.x) * -2
|
|
if (WEST)
|
|
return abs(y - aloc.y) <= (x - aloc.x) * 2
|
|
|
|
/obj/vehicle/sealed/mecha/durand/proc/toggle_defense(mob/living/user)
|
|
if(!LAZYLEN(occupants))
|
|
return
|
|
|
|
if(switching && (user || !defense_mode)) // Allow force shutdowns during animation
|
|
return
|
|
|
|
if(!defense_mode && cell?.charge < 100) // If it's off, and we have less than 100 units of power
|
|
if (user)
|
|
balloon_alert(user, "insufficient power")
|
|
return
|
|
|
|
switching = TRUE
|
|
defense_mode = !defense_mode
|
|
|
|
if(user)
|
|
balloon_alert(user, "shield [defense_mode ? "enabled" : "disabled"]")
|
|
log_message("User has toggled defense mode -- now [defense_mode ? "enabled" : "disabled"].", LOG_MECHA)
|
|
else
|
|
log_message("defense mode state changed -- now [defense_mode ? "enabled" : "disabled"].", LOG_MECHA)
|
|
|
|
for(var/mob/living/occupant as anything in occupants)
|
|
var/datum/action/button = occupant_actions[occupant][/datum/action/vehicle/sealed/mecha/mech_defense_mode]
|
|
button.button_icon_state = "mech_defense_mode_[defense_mode ? "on" : "off"]"
|
|
button.build_all_button_icons()
|
|
|
|
shield.set_light_on(defense_mode)
|
|
|
|
if(defense_mode)
|
|
shield.icon_state = "shield"
|
|
flick("shield_raise", shield)
|
|
playsound(src, 'sound/vehicles/mecha/mech_shield_raise.ogg', 50, FALSE)
|
|
else
|
|
shield.icon_state = "shield_null"
|
|
flick("shield_drop", shield)
|
|
playsound(src, 'sound/vehicles/mecha/mech_shield_drop.ogg', 50, FALSE)
|
|
|
|
addtimer(VARSET_CALLBACK(src, switching, FALSE), 0.7 SECONDS) // Shield animation length
|
|
|
|
/obj/vehicle/sealed/mecha/durand/attack_generic(mob/user, damage_amount = 0, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, armor_penetration = 0)
|
|
if(defense_check(get_turf(user)))
|
|
log_message("Attack absorbed by defense field. Attacker - [user].", LOG_MECHA, color="orange")
|
|
return shield.attack_generic(user, damage_amount, damage_type, damage_flag, sound_effect, armor_penetration)
|
|
return ..()
|
|
|
|
/obj/vehicle/sealed/mecha/durand/blob_act(obj/structure/blob/blob)
|
|
if(!defense_check(get_turf(blob)))
|
|
return ..()
|
|
log_message("Attack by blob. Attacker - [blob].", LOG_MECHA, color="red")
|
|
log_message("Attack absorbed by defense field.", LOG_MECHA, color="orange")
|
|
return shield.blob_act(blob)
|
|
|
|
/obj/vehicle/sealed/mecha/durand/attackby(obj/item/weapon, mob/user as mob, list/modifiers, list/attack_modifiers)
|
|
if(defense_check(get_turf(user)))
|
|
log_message("Attack absorbed by defense field. Attacker - [user], with [weapon]", LOG_MECHA, color="orange")
|
|
return shield.attackby(weapon, user, modifiers)
|
|
return ..()
|
|
|
|
/obj/vehicle/sealed/mecha/durand/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum)
|
|
if(defense_check(get_turf(AM)))
|
|
log_message("Impact with [AM] absorbed by defense field.", LOG_MECHA, color="orange")
|
|
return shield.hitby(AM, skipcatch, hitpush, blocked, throwingdatum)
|
|
return ..()
|
|
|
|
/datum/action/vehicle/sealed/mecha/mech_defense_mode
|
|
name = "Toggle Shield"
|
|
desc = "Toggle an energy shield that blocks all attacks from the faced direction at a heavy power cost."
|
|
button_icon_state = "mech_defense_mode_off"
|
|
|
|
/datum/action/vehicle/sealed/mecha/mech_defense_mode/Trigger(mob/clicker, trigger_flags, forced_state = FALSE)
|
|
. = ..()
|
|
if(!.)
|
|
return
|
|
if(chassis && (owner in chassis.occupants))
|
|
var/obj/vehicle/sealed/mecha/durand/durand = chassis
|
|
durand.toggle_defense(owner)
|
|
|
|
// Shield processing
|
|
|
|
/**
|
|
* An object to take the hit for us when using the Durand's defense mode.
|
|
* It is spawned in during the durand's initilization.
|
|
* Normally invisible, until defense mode is actvated. When the durand detects an attack that should be blocked, the
|
|
* attack is passed to the shield. The shield takes the damage, uses it to calculate charge cost, and then sets its
|
|
* own integrity back to max. Shield is automatically dropped if we run out of power or the user gets out.
|
|
**/
|
|
|
|
/obj/durand_shield //projectiles get passed to this when defense mode is enabled
|
|
name = "defense grid"
|
|
icon = 'icons/mob/effects/durand_shield.dmi'
|
|
icon_state = "shield_null"
|
|
pixel_z = 4
|
|
max_integrity = 10000
|
|
anchored = TRUE
|
|
light_system = OVERLAY_LIGHT
|
|
light_range = 2.8
|
|
light_power = 1
|
|
light_color = LIGHT_COLOR_FAINT_CYAN
|
|
light_on = FALSE
|
|
light_flags = LIGHT_ATTACHED
|
|
vis_flags = VIS_INHERIT_DIR | VIS_INHERIT_LAYER | VIS_INHERIT_PLANE | VIS_INHERIT_ID
|
|
resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF // The shield should not take damage from fire, lava, or acid; that's the mech's job.
|
|
/// Our link back to the durand
|
|
var/obj/vehicle/sealed/mecha/durand/chassis
|
|
|
|
/obj/durand_shield/Initialize(mapload, obj/vehicle/sealed/mecha/durand/chassis)
|
|
. = ..()
|
|
src.chassis = chassis
|
|
|
|
/obj/durand_shield/Destroy()
|
|
if(chassis)
|
|
chassis.shield = null
|
|
chassis = null
|
|
return ..()
|
|
|
|
/obj/durand_shield/take_damage(damage_amount, damage_type = BRUTE, damage_flag = "", sound_effect = TRUE, attack_dir, armour_penetration = 0)
|
|
if(!chassis)
|
|
qdel(src)
|
|
return
|
|
if(!chassis.defense_mode) //if defense mode is disabled, we're taking damage that we shouldn't be taking
|
|
return
|
|
. = ..()
|
|
flick("shield_impact", src)
|
|
if(!.)
|
|
return
|
|
if(!chassis.use_energy(. * (STANDARD_CELL_CHARGE / 150)))
|
|
chassis.cell?.charge = 0
|
|
chassis.toggle_defense()
|
|
atom_integrity = 10000
|
|
|
|
/obj/durand_shield/play_attack_sound()
|
|
playsound(src, 'sound/vehicles/mecha/mech_shield_deflect.ogg', 100, TRUE)
|
|
|
|
/obj/durand_shield/bullet_act()
|
|
play_attack_sound()
|
|
. = ..()
|