Middle Mouse Button now toggles equipment safety on mechs. (#66185) (#13292)

- Mechs now have a weapons_safety toggle. If set to true, clicking does not use equipment. This is mostly intended to allow users to keep from accidentally firing. Weapon safety defaults to off, but will keep the same state it was in between pilot exit/entry events.
- All mechs now use the green reticle mouse icon. If weapons_safety is enabled, the mouse is reverted to normal. The reticle (if shown) still turns red during an EMP-related weapons fault.
- AIs can use mech weapons if the safety is off, and use AI clicks if the safety is on.

Co-authored-by: zxaber <37497534+zxaber@users.noreply.github.com>
This commit is contained in:
SkyratBot
2022-05-03 17:05:31 +02:00
committed by GitHub
parent f25fa2b28b
commit 4c46268492
8 changed files with 65 additions and 21 deletions

View File

@@ -20,6 +20,11 @@
return
next_click = world.time + 1
var/list/modifiers = params2list(params)
if(SEND_SIGNAL(src, COMSIG_MOB_CLICKON, A, modifiers) & COMSIG_MOB_CANCEL_CLICKON)
return
if(!can_interact_with(A))
return
@@ -51,7 +56,6 @@
send2tgs_adminless_only("NOCHEAT", message)
return
var/list/modifiers = params2list(params)
if(LAZYACCESS(modifiers, SHIFT_CLICK))
if(LAZYACCESS(modifiers, CTRL_CLICK))
CtrlShiftClickOn(A)

View File

@@ -34,6 +34,7 @@
light_range = 8
generic_canpass = FALSE
hud_possible = list(DIAG_STAT_HUD, DIAG_BATT_HUD, DIAG_MECH_HUD, DIAG_TRACK_HUD)
mouse_pointer = 'icons/effects/mouse_pointers/mecha_mouse.dmi'
///What direction will the mech face when entered/powered on? Defaults to South.
var/dir_in = SOUTH
///How much energy the mech will consume each time it moves. This variable is a backup for when leg actuators affect the energy drain.
@@ -145,6 +146,8 @@
var/silicon_icon_state = null
///Currently ejecting, and unable to do things
var/is_currently_ejecting = FALSE
///Safety for weapons. Won't fire if enabled, and toggled by middle click.
var/weapons_safety = FALSE
var/datum/effect_system/smoke_spread/smoke_system = new
@@ -292,6 +295,37 @@
icon_state = get_mecha_occupancy_state()
return ..()
/**
* Toggles Weapons Safety
*
* Handles enabling or disabling the safety function.
*/
/obj/vehicle/sealed/mecha/proc/set_safety(mob/user)
weapons_safety = !weapons_safety
SEND_SOUND(user, sound('sound/machines/beep.ogg', volume = 25))
balloon_alert(user, "equipment [weapons_safety ? "safe" : "ready"]")
set_mouse_pointer()
/**
* Updates the pilot's mouse cursor override.
*
* If the mech's weapons safety is enabled, there should be no override, and the user gets their regular mouse cursor. If safety
* is off but the mech's equipment is disabled (such as by EMP), the cursor should be the red disabled version. Otherwise, if
* safety is off and the equipment is functional, the cursor should be the regular green cursor. This proc sets the cursor.
* correct and then updates it for each mob in the occupants list.
*/
/obj/vehicle/sealed/mecha/proc/set_mouse_pointer()
if(weapons_safety)
mouse_pointer = ""
else
if(equipment_disabled)
mouse_pointer = 'icons/effects/mouse_pointers/mecha_mouse-disable.dmi'
else
mouse_pointer = 'icons/effects/mouse_pointers/mecha_mouse.dmi'
for(var/mob/mob_occupant as anything in occupants)
mob_occupant.update_mouse_pointer()
//override this proc if you need to split up mecha control between multiple people (see savannah_ivanov.dm)
/obj/vehicle/sealed/mecha/auto_assign_occupant_flags(mob/M)
if(driver_amount() < max_drivers)
@@ -334,7 +368,7 @@
var/mob/mob_occupant = occupant
SEND_SOUND(mob_occupant, sound('sound/items/timer.ogg', volume=50))
to_chat(mob_occupant, span_notice("Equipment control unit has been rebooted successfully."))
mob_occupant.update_mouse_pointer()
set_mouse_pointer()
/obj/vehicle/sealed/mecha/CheckParts(list/parts_list)
. = ..()
@@ -561,14 +595,19 @@
///Called when a driver clicks somewhere. Handles everything like equipment, punches, etc.
/obj/vehicle/sealed/mecha/proc/on_mouseclick(mob/user, atom/target, list/modifiers)
SIGNAL_HANDLER
if(LAZYACCESS(modifiers, MIDDLE_CLICK))
set_safety(user)
return COMSIG_MOB_CANCEL_CLICKON
if(weapons_safety)
return
if(isAI(user)) //For AIs: If safeties are off, use mech functions. If safeties are on, use AI functions.
. = COMSIG_MOB_CANCEL_CLICKON
if(modifiers[SHIFT_CLICK]) //Allows things to be examined.
return
if(!isturf(target) && !isturf(target.loc)) // Prevents inventory from being drilled
return
if(completely_disabled || is_currently_ejecting || (mecha_flags & CANNOT_INTERACT))
return
if(isAI(user) == !LAZYACCESS(modifiers, MIDDLE_CLICK))//BASICALLY if a human uses MMB, or an AI doesn't, then do nothing.
return
if(phasing)
balloon_alert(user, "not while [phasing]!")
return
@@ -633,11 +672,6 @@
target.mech_melee_attack(src, user)
TIMER_COOLDOWN_START(src, COOLDOWN_MECHA_MELEE_ATTACK, melee_cooldown)
/obj/vehicle/sealed/mecha/proc/on_middlemouseclick(mob/user, atom/target, params)
SIGNAL_HANDLER
if(isAI(user))
on_mouseclick(user, target, params)
//////////////////////////////////
//////// Movement procs ////////
//////////////////////////////////
@@ -970,7 +1004,7 @@
AI.remote_control = src
to_chat(AI, AI.can_dominate_mechs ? span_greenannounce("Takeover of [name] complete! You are now loaded onto the onboard computer. Do not attempt to leave the station sector!") :\
span_notice("You have been uploaded to a mech's onboard computer."))
to_chat(AI, "<span class='reallybig boldnotice'>Use Middle-Mouse to activate mech functions and equipment. Click normally for AI interactions.</span>")
to_chat(AI, "<span class='reallybig boldnotice'>Use Middle-Mouse to toggle equipment safety. Clicks with safety enabled will pass AI commands.</span>")
///Handles an actual AI (simple_animal mecha pilot) entering the mech
@@ -1040,6 +1074,7 @@
log_message("[newoccupant] moved in as pilot.", LOG_MECHA)
setDir(dir_in)
playsound(src, 'sound/machines/windowdoor.ogg', 50, TRUE)
set_mouse_pointer()
if(!internal_damage)
SEND_SOUND(newoccupant, sound('sound/mecha/nominal.ogg',volume=50))
return TRUE
@@ -1158,7 +1193,6 @@
/obj/vehicle/sealed/mecha/add_occupant(mob/M, control_flags)
RegisterSignal(M, COMSIG_LIVING_DEATH, .proc/mob_exit)
RegisterSignal(M, COMSIG_MOB_CLICKON, .proc/on_mouseclick)
RegisterSignal(M, COMSIG_MOB_MIDDLECLICKON, .proc/on_middlemouseclick) //For AIs
RegisterSignal(M, COMSIG_MOB_SAY, .proc/display_speech_bubble)
. = ..()
update_appearance()
@@ -1166,7 +1200,6 @@
/obj/vehicle/sealed/mecha/remove_occupant(mob/M)
UnregisterSignal(M, COMSIG_LIVING_DEATH)
UnregisterSignal(M, COMSIG_MOB_CLICKON)
UnregisterSignal(M, COMSIG_MOB_MIDDLECLICKON)
UnregisterSignal(M, COMSIG_MOB_SAY)
M.clear_alert(ALERT_CHARGE)
M.clear_alert(ALERT_MECH_DAMAGE)

View File

@@ -2,7 +2,6 @@
force = 30
internals_req_access = list(ACCESS_MECH_SCIENCE, ACCESS_MECH_SECURITY)
armor = list(MELEE = 30, BULLET = 30, LASER = 15, ENERGY = 20, BOMB = 20, BIO = 0, FIRE = 100, ACID = 100)
mouse_pointer = 'icons/effects/mouse_pointers/mecha_mouse.dmi'
destruction_sleep_duration = 40
exit_delay = 40

View File

@@ -181,15 +181,11 @@
take_damage(30 / severity, BURN, ENERGY, 1)
log_message("EMP detected", LOG_MECHA, color="red")
if(istype(src, /obj/vehicle/sealed/mecha/combat)) //todo this stupid mouse icon should be a flag
mouse_pointer = 'icons/effects/mouse_pointers/mecha_mouse-disable.dmi'
for(var/occus in occupants)
var/mob/living/occupant = occus
occupant.update_mouse_pointer()
if(!equipment_disabled && LAZYLEN(occupants)) //prevent spamming this message with back-to-back EMPs
to_chat(occupants, span_warning("Error -- Connection to equipment control unit has been lost."))
addtimer(CALLBACK(src, /obj/vehicle/sealed/mecha.proc/restore_equipment), 3 SECONDS, TIMER_UNIQUE | TIMER_OVERRIDE)
equipment_disabled = TRUE
set_mouse_pointer()
/obj/vehicle/sealed/mecha/should_atmos_process(datum/gas_mixture/air, exposed_temperature)
return exposed_temperature > max_temperature

View File

@@ -122,6 +122,7 @@
data["cabin_pressure"] = round(return_pressure(), 0.01)
data["cabin_temp"] = return_temperature()
data["dna_lock"] = dna_lock
data["weapons_safety"] = weapons_safety
data["mech_view"] = ui_view.assigned_map
if(radio)
data["mech_electronics"] = list(
@@ -268,6 +269,9 @@
tgui_alert(usr, "You cannot set a name that contains a word prohibited in IC chat!")
return
name = userinput
if("toggle_safety")
set_safety(usr)
return
if("dna_lock")
var/mob/living/carbon/user = usr
if(!istype(user) || !user.dna)

View File

@@ -13,11 +13,12 @@ export const ArmPane=(props:{weapon:MechWeapon}, context) => {
} = props.weapon;
const {
power_level,
weapons_safety,
} = data;
return (
<Stack fill vertical>
<Stack.Item bold>
{name}
<Stack.Item bold color={weapons_safety ? "red" : ""}>
{weapons_safety ? "SAFETY OVERRIDE IN EFFECT" : name}
</Stack.Item>
<Stack.Item>
<Stack>
@@ -62,7 +63,7 @@ export const ArmPane=(props:{weapon:MechWeapon}, context) => {
<Stack.Item>
<Snowflake weapon={props.weapon} />
</Stack.Item>
<Stack.Item>
<Stack.Item color={weapons_safety ? "red" : ""}>
{desc}
</Stack.Item>
</Stack>

View File

@@ -8,6 +8,7 @@ export const MechStatPane = (props, context) => {
const {
name,
integrity,
weapons_safety,
air_source,
cabin_pressure,
cabin_dangerous_highpressure,
@@ -42,6 +43,11 @@ export const MechStatPane = (props, context) => {
<LabeledList.Item label="Power">
<PowerBar />
</LabeledList.Item>
<LabeledList.Item label="Safety">
<Button color={weapons_safety ? "red" : ""} onClick={() => act('toggle_safety')}>
{weapons_safety ? "Dis" : "En"}able
</Button>
</LabeledList.Item>
</LabeledList>
</Section>
</Stack.Item>

View File

@@ -81,6 +81,7 @@ export type OperatorData = {
mech_electronics: MechElectronics;
right_arm_weapon: MechWeapon | null;
left_arm_weapon: MechWeapon | null;
weapons_safety: boolean;
mech_equipment: string[];
mech_view: string;
mineral_material_amount: number;