diff --git a/code/_onclick/hud/action_button.dm b/code/_onclick/hud/action_button.dm index 16cb8baa044..32a9d7cf46d 100644 --- a/code/_onclick/hud/action_button.dm +++ b/code/_onclick/hud/action_button.dm @@ -17,7 +17,7 @@ //Hide/Show Action Buttons ... Button /obj/screen/movable/action_button/hide_toggle name = "Hide Buttons" - icon = 'icons/mob/actions.dmi' + icon = 'icons/mob/actions/actions.dmi' icon_state = "bg_default" var/hidden = 0 diff --git a/code/_onclick/hud/alert.dm b/code/_onclick/hud/alert.dm index a187dfe3648..99991fa7b72 100644 --- a/code/_onclick/hud/alert.dm +++ b/code/_onclick/hud/alert.dm @@ -358,12 +358,48 @@ so as to remain in compliance with the most up-to-date laws." AI.eyeobj.setLoc(T) //MECHS - /obj/screen/alert/low_mech_integrity name = "Mech Damaged" desc = "Mech integrity is low." icon_state = "low_mech_integrity" +/obj/screen/alert/mech_port_available + name = "Connect to Port" + desc = "Click here to connect to an air port and refill your oxygen!" + icon_state = "mech_port" + var/obj/machinery/atmospherics/unary/portables_connector/target = null + +/obj/screen/alert/mech_port_available/Destroy() + target = null + return ..() + +/obj/screen/alert/mech_port_available/Click() + if(!usr || !usr.client) + return + if(!istype(usr.loc, /obj/mecha) || !target) + return + var/obj/mecha/M = usr.loc + if(M.connect(target)) + to_chat(usr, "[M] connects to the port.") + else + to_chat(usr, "[M] failed to connect to the port.") + +/obj/screen/alert/mech_port_disconnect + name = "Disconnect from Port" + desc = "Click here to disconnect from your air port." + icon_state = "mech_port_x" + +/obj/screen/alert/mech_port_disconnect/Click() + if(!usr || !usr.client) + return + if(!istype(usr.loc, /obj/mecha)) + return + var/obj/mecha/M = usr.loc + if(M.disconnect()) + to_chat(usr, "[M] disconnects from the port.") + else + to_chat(usr, "[M] is not connected to a port at the moment.") + //GUARDIANS /obj/screen/alert/cancharge name = "Charge Ready" diff --git a/code/datums/action.dm b/code/datums/action.dm index e0634527104..a9c895f3482 100644 --- a/code/datums/action.dm +++ b/code/datums/action.dm @@ -11,10 +11,10 @@ var/check_flags = 0 var/processing = 0 var/obj/screen/movable/action_button/button = null - var/button_icon = 'icons/mob/actions.dmi' + var/button_icon = 'icons/mob/actions/actions.dmi' var/background_icon_state = "bg_default" - var/icon_icon = 'icons/mob/actions.dmi' + var/icon_icon = 'icons/mob/actions/actions.dmi' var/button_icon_state = "default" var/mob/owner diff --git a/code/datums/spell.dm b/code/datums/spell.dm index 653cc0020bc..dee057c5568 100644 --- a/code/datums/spell.dm +++ b/code/datums/spell.dm @@ -97,7 +97,7 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin var/centcom_cancast = 1 //Whether or not the spell should be allowed on z2 var/datum/action/spell_action/action = null - var/action_icon = 'icons/mob/actions.dmi' + var/action_icon = 'icons/mob/actions/actions.dmi' var/action_icon_state = "spell_default" var/action_background_icon_state = "bg_spell" diff --git a/code/game/mecha/combat/durand.dm b/code/game/mecha/combat/durand.dm index 6f3a8b51354..a1264b753e6 100644 --- a/code/game/mecha/combat/durand.dm +++ b/code/game/mecha/combat/durand.dm @@ -12,10 +12,15 @@ max_temperature = 30000 infra_luminosity = 8 force = 40 - var/defence = 0 - var/defence_deflect = 35 wreckage = /obj/effect/decal/mecha_wreckage/durand +/obj/mecha/combat/durand/GrantActions(mob/living/user, human_occupant = 0) + ..() + defense_action.Grant(user, src) + +/obj/mecha/combat/durand/RemoveActions(mob/living/user, human_occupant = 0) + ..() + defense_action.Remove(user) /obj/mecha/combat/durand/loaded/New() ..() @@ -24,54 +29,6 @@ ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack ME.attach(src) - -/obj/mecha/combat/durand/relaymove(mob/user,direction) - if(defence) - if(world.time - last_message > 20) - occupant_message("Unable to move while in defence mode") - last_message = world.time - return 0 - . = ..() - - -/obj/mecha/combat/durand/verb/defence_mode() - set category = "Exosuit Interface" - set name = "Toggle defence mode" - set src = usr.loc - set popup_menu = 0 - if(usr != occupant) - return - defence = !defence - if(defence) - deflect_chance = defence_deflect - occupant_message("You enable [src] defence mode.") - else - deflect_chance = initial(deflect_chance) - occupant_message("You disable [src] defence mode.") - log_message("Toggled defence mode.") - - -/obj/mecha/combat/durand/get_stats_part() - var/output = ..() - output += "Defence mode: [defence?"on":"off"]" - return output - -/obj/mecha/combat/durand/get_commands() - var/output = {"
-
Special
- -
- "} - output += ..() - return output - -/obj/mecha/combat/durand/Topic(href, href_list) - ..() - if(href_list["toggle_defence_mode"]) - defence_mode() - /obj/mecha/combat/durand/old desc = "A retired, third-generation combat exosuit utilized by the Nanotrasen corporation. Originally developed to combat hostile alien lifeforms." name = "Durand" diff --git a/code/game/mecha/combat/gygax.dm b/code/game/mecha/combat/gygax.dm index 05e02901ce2..c930df4b97b 100644 --- a/code/game/mecha/combat/gygax.dm +++ b/code/game/mecha/combat/gygax.dm @@ -11,13 +11,21 @@ armor = list(melee = 25, bullet = 20, laser = 30, energy = 15, bomb = 0, bio = 0, rad = 0) max_temperature = 25000 infra_luminosity = 6 - var/overload = 0 - var/overload_coeff = 2 + leg_overload_coeff = 2 wreckage = /obj/effect/decal/mecha_wreckage/gygax internal_damage_threshold = 35 max_equip = 3 maxsize = 2 step_energy_drain = 3 + normal_step_energy_drain = 3 + +/obj/mecha/combat/gygax/GrantActions(mob/living/user, human_occupant = 0) + ..() + overload_action.Grant(user, src) + +/obj/mecha/combat/gygax/RemoveActions(mob/living/user, human_occupant = 0) + ..() + overload_action.Remove(user) /obj/mecha/combat/gygax/loaded/New() ..() @@ -35,7 +43,7 @@ deflect_chance = 15 damage_absorption = list("brute"=0.6,"fire"=0.8,"bullet"=0.6,"laser"=0.5,"energy"=0.65,"bomb"=0.8) max_temperature = 35000 - overload_coeff = 1 + leg_overload_coeff = 100 operation_req_access = list(access_syndicate) wreckage = /obj/effect/decal/mecha_wreckage/gygax/dark max_equip = 4 @@ -55,57 +63,4 @@ /obj/mecha/combat/gygax/dark/add_cell() cell = new /obj/item/stock_parts/cell/bluespace(src) cell.charge = 30000 - cell.maxcharge = 30000 - - -/obj/mecha/combat/gygax/verb/overload() - set category = "Exosuit Interface" - set name = "Toggle leg actuators overload" - set src = usr.loc - set popup_menu = 0 - if(usr != occupant) - return - if(overload) - overload = 0 - step_in = initial(step_in) - step_energy_drain = initial(step_energy_drain) - occupant_message("You disable leg actuators overload.") - else - overload = 1 - step_in = min(1, round(step_in/2)) - step_energy_drain = step_energy_drain*overload_coeff - occupant_message("You enable leg actuators overload.") - log_message("Toggled leg actuators overload.") - -/obj/mecha/combat/gygax/domove(direction) - if(!..()) - return - if(overload) - health-- - if(health < initial(health) - initial(health) / 3) - overload = 0 - step_in = initial(step_in) - step_energy_drain = initial(step_energy_drain) - occupant_message("Leg actuators damage threshold exceded. Disabling overload.") - - -/obj/mecha/combat/gygax/get_stats_part() - var/output = ..() - output += "Leg actuators overload: [overload?"on":"off"]" - return output - -/obj/mecha/combat/gygax/get_commands() - var/output = {"
-
Special
- -
- "} - output += ..() - return output - -/obj/mecha/combat/gygax/Topic(href, href_list) - ..() - if(href_list["toggle_leg_overload"]) - overload() \ No newline at end of file + cell.maxcharge = 30000 \ No newline at end of file diff --git a/code/game/mecha/combat/marauder.dm b/code/game/mecha/combat/marauder.dm index b05f97acbcd..8e16b6128dd 100644 --- a/code/game/mecha/combat/marauder.dm +++ b/code/game/mecha/combat/marauder.dm @@ -11,12 +11,6 @@ max_temperature = 60000 burn_state = LAVA_PROOF infra_luminosity = 3 - var/zoom = 0 - var/thrusters = 0 - var/smoke = 5 - var/smoke_ready = 1 - var/smoke_cooldown = 100 - var/datum/effect_system/smoke_spread/smoke_system = new operation_req_access = list(access_cent_specops) wreckage = /obj/effect/decal/mecha_wreckage/marauder add_req_access = 0 @@ -24,6 +18,17 @@ force = 45 max_equip = 5 +/obj/mecha/combat/marauder/GrantActions(mob/living/user, human_occupant = 0) + . = ..() + thrusters_action.Grant(user, src) + smoke_action.Grant(user, src) + zoom_action.Grant(user, src) + +/obj/mecha/combat/marauder/RemoveActions(mob/living/user, human_occupant = 0) + . = ..() + thrusters_action.Remove(user) + smoke_action.Remove(user) + zoom_action.Remove(user) /obj/mecha/combat/marauder/loaded/New() ..() @@ -37,8 +42,6 @@ ME.attach(src) ME = new /obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster(src) ME.attach(src) - smoke_system.set_up(3, 0, src) - smoke_system.attach(src) /obj/mecha/combat/marauder/seraph desc = "Heavy-duty, command-type exosuit. This is a custom model, utilized only by high-ranking military personnel." @@ -98,100 +101,4 @@ ME = new /obj/item/mecha_parts/mecha_equipment/tesla_energy_relay(src) ME.attach(src) ME = new /obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster(src) - ME.attach(src) - smoke_system.set_up(3, 0, src) - smoke_system.attach(src) - - -/obj/mecha/combat/marauder/relaymove(mob/user,direction) - if(zoom) - if(world.time - last_message > 20) - occupant_message("Unable to move while in zoom mode.") - last_message = world.time - return 0 - return ..() - -/obj/mecha/combat/marauder/Process_Spacemove(var/movement_dir = 0) - if(..()) - return 1 - if(thrusters && movement_dir && use_power(step_energy_drain)) - return 1 - return 0 - -/obj/mecha/combat/marauder/verb/toggle_thrusters() - set category = "Exosuit Interface" - set name = "Toggle thrusters" - set src = usr.loc - set popup_menu = 0 - if(usr != occupant) - return - if(occupant) - if(get_charge() > 0) - thrusters = !thrusters - log_message("Toggled thrusters.") - occupant_message("Thrusters [thrusters?"en":"dis"]abled.") - - -/obj/mecha/combat/marauder/verb/smoke() - set category = "Exosuit Interface" - set name = "Smoke" - set src = usr.loc - set popup_menu = 0 - if(usr != occupant) - return - if(smoke_ready && smoke>0) - smoke_system.start() - smoke-- - smoke_ready = 0 - spawn(smoke_cooldown) - smoke_ready = 1 - -/obj/mecha/combat/marauder/verb/zoom() - set category = "Exosuit Interface" - set name = "Zoom" - set src = usr.loc - set popup_menu = 0 - if(usr != occupant) - return - if(occupant.client) - zoom = !zoom - log_message("Toggled zoom mode.") - occupant_message("Zoom mode [zoom?"en":"dis"]abled.") - if(zoom) - occupant.client.AddViewMod("mecha", 12) - to_chat(occupant, sound('sound/mecha/imag_enh.ogg',volume=50)) - else - occupant.client.RemoveViewMod("mecha") - - - -/obj/mecha/combat/marauder/get_stats_part() - var/output = ..() - output += {"Smoke: [smoke] -
- Thrusters: [thrusters?"on":"off"] - "} - return output - - -/obj/mecha/combat/marauder/get_commands() - var/output = {"
-
Special
- -
- "} - output += ..() - return output - -/obj/mecha/combat/marauder/Topic(href, href_list) - ..() - if(href_list["toggle_thrusters"]) - toggle_thrusters() - if(href_list["smoke"]) - smoke() - if(href_list["toggle_zoom"]) - zoom() \ No newline at end of file + ME.attach(src) \ No newline at end of file diff --git a/code/game/mecha/combat/phazon.dm b/code/game/mecha/combat/phazon.dm index 5dbffb62f29..af48fb1b6dc 100644 --- a/code/game/mecha/combat/phazon.dm +++ b/code/game/mecha/combat/phazon.dm @@ -6,6 +6,7 @@ step_in = 2 dir_in = 2 //Facing south. step_energy_drain = 3 + normal_step_energy_drain = 3 health = 200 deflect_chance = 30 damage_absorption = list("brute"=0.7,"fire"=0.7,"bullet"=0.7,"laser"=0.7,"energy"=0.7,"bomb"=0.7) @@ -17,10 +18,16 @@ //operation_req_access = list() internal_damage_threshold = 25 force = 15 - var/phasing = 0 - var/phasing_energy_drain = 200 + phase_state = "phazon-phase" max_equip = 3 +/obj/mecha/combat/phazon/GrantActions(mob/living/user, human_occupant = 0) + ..() + phasing_action.Grant(user, src) + +/obj/mecha/combat/phazon/RemoveActions(mob/living/user, human_occupant = 0) + ..() + phasing_action.Remove(user) /obj/mecha/combat/phazon/New() ..() @@ -29,25 +36,6 @@ ME = new /obj/item/mecha_parts/mecha_equipment/gravcatapult ME.attach(src) -/obj/mecha/combat/phazon/mechstep(direction) - . = ..() - if(!. && phasing && get_charge() >= phasing_energy_drain) - if(can_move) - can_move = 0 - flick("phazon-phase", src) - forceMove(get_step(src, direction)) - use_power(phasing_energy_drain) - playsound(src,stepsound,40,1) - sleep(step_in * 3) - can_move = 1 - return 1 - -/obj/mecha/combat/phazon/click_action(atom/target,mob/user) - if(phasing) - occupant_message("Unable to interact with objects while phasing") - return - return ..() - /obj/mecha/combat/phazon/verb/switch_damtype() set category = "Exosuit Interface" set name = "Reconfigure arm microtool arrays" @@ -72,7 +60,6 @@ var/output = {"
Special
@@ -83,8 +70,4 @@ /obj/mecha/combat/phazon/Topic(href, href_list) ..() if(href_list["switch_damtype"]) - switch_damtype() - if(href_list["phasing"]) - phasing = !phasing - send_byjax(occupant,"exosuit.browser","phasing_command","[phasing?"Dis":"En"]able phasing") - occupant_message("En":"#f00\">Dis"]abled phasing.") \ No newline at end of file + switch_damtype() \ No newline at end of file diff --git a/code/game/mecha/combat/reticence.dm b/code/game/mecha/combat/reticence.dm index 9e51be0357d..ba4566a1e91 100644 --- a/code/game/mecha/combat/reticence.dm +++ b/code/game/mecha/combat/reticence.dm @@ -15,7 +15,8 @@ add_req_access = 0 internal_damage_threshold = 60 max_equip = 3 - step_energy_drain = 3 + step_energy_drain = 3 + normal_step_energy_drain = 3 stepsound = null turnsound = null diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index 64874762050..1cdecf3f2a1 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -7,6 +7,9 @@ #define MELEE 1 #define RANGED 2 +#define MECHAMOVE_RAND 1 +#define MECHAMOVE_TURN 2 +#define MECHAMOVE_STEP 4 /obj/mecha name = "Mecha" @@ -25,7 +28,9 @@ 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/normal_step_energy_drain = 10 var/step_energy_drain = 10 + var/overload_step_energy_drain_min = 100 var/health = 300 //health is health 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. @@ -69,13 +74,26 @@ var/turf/crashing = null var/occupant_sight_flags = 0 - var/stepsound = 'sound/mecha/mechstep.ogg' var/turnsound = 'sound/mecha/mechturn.ogg' var/melee_cooldown = 10 var/melee_can_hit = 1 + // Action vars + var/defence_mode = FALSE + var/defence_mode_deflect_chance = 35 + var/leg_overload_mode = FALSE + var/leg_overload_coeff = 100 + var/thrusters_active = FALSE + var/smoke = 5 + var/smoke_ready = 1 + var/smoke_cooldown = 100 + var/zoom_mode = FALSE + var/phasing = FALSE + var/phasing_energy_drain = 200 + var/phase_state = "" //icon_state when phasing + hud_possible = list (DIAG_STAT_HUD, DIAG_BATT_HUD, DIAG_MECH_HUD, DIAG_TRACK_HUD) /obj/mecha/New() @@ -84,17 +102,14 @@ icon_state += "-open" add_radio() add_cabin() - - 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) - + add_airtank() spark_system.set_up(2, 0, src) spark_system.attach(src) + smoke_system.set_up(3, src) + smoke_system.attach(src) add_cell() processing_objects.Add(src) - removeVerb(/obj/mecha/verb/disconnect_from_port) GLOB.poi_list |= src log_message("[src] created.") GLOB.mechas_list += src //global mech list @@ -176,6 +191,9 @@ return if(user.incapacitated()) return + if(phasing) + occupant_message("Unable to interact with objects while phasing.") + return if(state) occupant_message("Maintenance protocols in effect.") return @@ -251,6 +269,8 @@ . = ..() if(.) return 1 + if(thrusters_active && movement_dir && use_power(step_energy_drain)) + return 1 var/atom/movable/backup = get_spacemove_backup() if(backup) @@ -284,23 +304,55 @@ return 0 if(!has_charge(step_energy_drain)) return 0 + if(defence_mode) + if(world.time - last_message > 20) + occupant_message("Unable to move while in defence mode.") + last_message = world.time + return 0 + if(zoom_mode) + if(world.time - last_message > 20) + occupant_message("Unable to move while in zoom mode.") + last_message = world.time + return 0 var/move_result = 0 + var/move_type = 0 if(internal_damage & MECHA_INT_CONTROL_LOST) move_result = mechsteprand() + move_type = MECHAMOVE_RAND else if(dir != direction) move_result = mechturn(direction) + move_type = MECHAMOVE_TURN else move_result = mechstep(direction) + move_type = MECHAMOVE_STEP - can_move = 0 + can_move = FALSE spawn(step_in) - can_move = 1 + can_move = TRUE - if(move_result) - use_power(step_energy_drain) - return 1 - return 0 + if(move_result && move_type) + aftermove(move_type) + return TRUE + return FALSE + +/obj/mecha/proc/aftermove(move_type) + use_power(step_energy_drain) + if(move_type & (MECHAMOVE_RAND | MECHAMOVE_STEP) && occupant) + var/obj/machinery/atmospherics/unary/portables_connector/possible_port = locate(/obj/machinery/atmospherics/unary/portables_connector) in loc + if(possible_port) + var/obj/screen/alert/mech_port_available/A = occupant.throw_alert("mechaport", /obj/screen/alert/mech_port_available, override = TRUE) + if(A) + A.target = possible_port + else + occupant.clear_alert("mechaport") + if(leg_overload_mode) + take_damage(1) + if(health < initial(health) - initial(health) / 3) + leg_overload_mode = FALSE + step_in = initial(step_in) + step_energy_drain = initial(step_energy_drain) + occupant_message("Leg actuators damage threshold exceded. Disabling overload.") /obj/mecha/proc/mechturn(direction) @@ -310,16 +362,25 @@ return 1 /obj/mecha/proc/mechstep(direction) - var/result = step(src,direction) - if(result && stepsound) - playsound(src,stepsound,40,1) - return result + . = step(src, direction) + if(!.) + if(phasing && get_charge() >= phasing_energy_drain) + if(can_move) + can_move = 0 + . = TRUE + flick("phazon-phase", src) + forceMove(get_step(src, direction)) + use_power(phasing_energy_drain) + playsound(src, stepsound, 40, 1) + spawn(step_in * 3) + can_move = 1 + else if(stepsound) + playsound(src, stepsound, 40, 1) /obj/mecha/proc/mechsteprand() - var/result = step_rand(src) - if(result && stepsound) - playsound(src,stepsound,40,1) - return result + . = step_rand(src) + if(. && stepsound) + playsound(src, stepsound, 40, 1) @@ -627,6 +688,7 @@ qdel(cabin_air) cabin_air = null QDEL_NULL(spark_system) + QDEL_NULL(smoke_system) GLOB.mechas_list -= src //global mech list return ..() @@ -777,8 +839,8 @@ else if(iswelder(W) && user.a_intent != INTENT_HARM) var/obj/item/weldingtool/WT = W if(healthYou repair the damaged gas tank.") else @@ -958,6 +1020,10 @@ to_chat(AI, "[AI.can_dominate_mechs ? "Takeover of [name] complete! You are now permanently loaded onto the onboard computer. Do not attempt to leave the station sector!" \ : "You have been uploaded to a mech's onboard computer."]") to_chat(AI, "Use Middle-Mouse to activate mech functions and equipment. Click normally for AI interactions.") + if(interaction == AI_TRANS_FROM_CARD) + GrantActions(AI, FALSE) + else + GrantActions(AI, !AI.can_dominate_mechs) ///////////////////////////////////// //////// Atmospheric stuff //////// @@ -994,7 +1060,7 @@ /obj/mecha/proc/connect(obj/machinery/atmospherics/unary/portables_connector/new_port) //Make sure not already connected to something else - if(connected_port || !new_port || new_port.connected_device) + if(connected_port || !istype(new_port) || new_port.connected_device) return 0 //Make sure are close enough for a valid connection @@ -1006,6 +1072,10 @@ connected_port.connected_device = src connected_port.parent.reconcile_air() + if(occupant) + occupant.clear_alert("mechaport") + occupant.throw_alert("mechaport_d", /obj/screen/alert/mech_port_disconnect) + log_message("Connected to gas port.") return 1 @@ -1016,6 +1086,8 @@ connected_port.connected_device = null connected_port = null log_message("Disconnected from gas port.") + if(occupant) + occupant.clear_alert("mechaport_d") return 1 /obj/mecha/portableConnectorReturnAir() @@ -1025,71 +1097,19 @@ ///////////////////////// //////// Verbs //////// ///////////////////////// - - -/obj/mecha/verb/connect_to_port() - set name = "Connect to port" - set category = "Exosuit Interface" - set src = usr.loc - set popup_menu = 0 - if(!occupant) return - if(usr!=occupant) - return - var/obj/machinery/atmospherics/unary/portables_connector/possible_port = locate(/obj/machinery/atmospherics/unary/portables_connector/) in loc - if(possible_port) - if(connect(possible_port)) - occupant_message("[name] connects to the port.") - verbs += /obj/mecha/verb/disconnect_from_port - verbs -= /obj/mecha/verb/connect_to_port - return - else - occupant_message("[name] failed to connect to the port.") - return - else - occupant_message("Nothing happens") - - -/obj/mecha/verb/disconnect_from_port() - set name = "Disconnect from port" - 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 - verbs += /obj/mecha/verb/connect_to_port - else - occupant_message("[name] is not connected to the port at the moment.") - -/obj/mecha/verb/toggle_lights() - set name = "Toggle Lights" - set category = "Exosuit Interface" - set src = usr.loc - set popup_menu = 0 - if(usr!=occupant) return +/obj/mecha/proc/toggle_lights() lights = !lights - if(lights) set_light(light_range + lights_power) - else set_light(light_range - lights_power) - occupant_message("Toggled lights [lights?"on":"off"].") - log_message("Toggled lights [lights?"on":"off"].") - return + if(lights) + set_light(light_range + lights_power) + else + set_light(light_range - lights_power) + occupant_message("Toggled lights [lights ? "on" : "off"].") + log_message("Toggled lights [lights ? "on" : "off"].") - -/obj/mecha/verb/toggle_internal_tank() - set name = "Toggle internal airtank usage." - set category = "Exosuit Interface" - set src = usr.loc - set popup_menu = 0 - if(usr!=occupant) - return +/obj/mecha/proc/toggle_internal_tank() use_internal_tank = !use_internal_tank - occupant_message("Now taking air from [use_internal_tank?"internal airtank":"environment"].") - log_message("Now taking air from [use_internal_tank?"internal airtank":"environment"].") - return - + occupant_message("Now taking air from [use_internal_tank ? "internal airtank" : "environment"].") + log_message("Now taking air from [use_internal_tank ? "internal airtank" : "environment"].") /obj/mecha/MouseDrop_T(mob/M, mob/user) if(user.incapacitated()) @@ -1147,7 +1167,7 @@ H.forceMove(src) H.reset_perspective(src) add_fingerprint(H) - //GrantActions(H, human_occupant=1) + GrantActions(H, human_occupant = 1) forceMove(loc) log_append_to_last("[H] moved in as pilot.") icon_state = reset_icon() @@ -1204,7 +1224,6 @@ to_chat(brainmob, "Your imprint to [R.imprinted_master] has been temporarily disabled. You should help the crew and not commit harm.") mmi_as_oc.loc = src mmi_as_oc.mecha = src - verbs -= /obj/mecha/verb/eject Entered(mmi_as_oc) Move(loc) icon_state = reset_icon() @@ -1212,6 +1231,7 @@ log_message("[mmi_as_oc] moved in as pilot.") if(!hasInternalDamage()) to_chat(occupant, sound('sound/mecha/nominal.ogg',volume=50)) + GrantActions(brainmob) return 1 else return 0 @@ -1228,27 +1248,6 @@ /obj/mecha/proc/pilot_mmi_hud(var/mob/living/carbon/brain/pilot) return -/obj/mecha/verb/view_stats() - set name = "View Stats" - set category = "Exosuit Interface" - set src = usr.loc - set popup_menu = 0 - if(usr!=occupant) - return - occupant << browse(get_stats_html(), "window=exosuit") - return - -/obj/mecha/verb/eject() - set name = "Eject" - set category = "Exosuit Interface" - set src = usr.loc - set popup_menu = 0 - if(usr != occupant) - return - go_out() - add_fingerprint(usr) - - /obj/mecha/Exited(atom/movable/M, atom/newloc) if(occupant && occupant == M) // The occupant exited the mech without calling go_out() go_out(1, newloc) @@ -1259,17 +1258,19 @@ var/atom/movable/mob_container occupant.clear_alert("charge") occupant.clear_alert("mech damage") + occupant.clear_alert("mechaport") + occupant.clear_alert("mechaport_d") if(ishuman(occupant)) mob_container = occupant - //RemoveActions(occupant, human_occupant=1) + RemoveActions(occupant, human_occupant = 1) else if(isbrain(occupant)) var/mob/living/carbon/brain/brain = occupant - //RemoveActions(brain) + RemoveActions(brain) mob_container = brain.container else if(isAI(occupant)) var/mob/living/silicon/ai/AI = occupant if(forced)//This should only happen if there are multiple AIs in a round, and at least one is Malf. - //RemoveActions(occupant) + RemoveActions(occupant) occupant.gib() //If one Malf decides to steal a mech from another AI (even other Malfs!), they are destroyed, as they have nowhere to go when replaced. occupant = null return @@ -1281,7 +1282,7 @@ to_chat(AI, "Returning to core...") AI.controlled_mech = null AI.remote_control = null - //RemoveActions(occupant, 1) + RemoveActions(occupant, 1) mob_container = AI newloc = get_turf(AI.linked_core) qdel(AI.linked_core) @@ -1310,6 +1311,7 @@ if(L && L.client) L.client.RemoveViewMod("mecha") + zoom_mode = FALSE ///////////////////////// ////// Access stuff ///// @@ -1319,14 +1321,14 @@ if(!ishuman(H)) return 0 for(var/ID in list(H.get_active_hand(), H.wear_id, H.belt)) - if(check_access(ID,operation_req_access)) + if(check_access(ID, operation_req_access)) return 1 return 0 /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(check_access(ID,internals_req_access)) + if(check_access(ID, internals_req_access)) return 1 return 0 diff --git a/code/game/mecha/mecha_actions.dm b/code/game/mecha/mecha_actions.dm new file mode 100644 index 00000000000..2db88a3b57b --- /dev/null +++ b/code/game/mecha/mecha_actions.dm @@ -0,0 +1,205 @@ +/obj/mecha + //Action datums + 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/mech_defence_mode/defense_action = new + var/datum/action/innate/mecha/mech_overload_mode/overload_action = new + var/datum/action/innate/mecha/mech_toggle_thrusters/thrusters_action = new + var/datum/effect_system/smoke_spread/smoke_system = new //not an action, but trigged by one + 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_phasing/phasing_action = new + // var/datum/action/innate/mecha/mech_switch_damtype/switch_damtype_action = new + +/obj/mecha/proc/GrantActions(mob/living/user, human_occupant = 0) + if(human_occupant) + eject_action.Grant(user, src) + internals_action.Grant(user, src) + lights_action.Grant(user, src) + stats_action.Grant(user, src) + +/obj/mecha/proc/RemoveActions(mob/living/user, human_occupant = 0) + if(human_occupant) + eject_action.Remove(user) + internals_action.Remove(user) + lights_action.Remove(user) + stats_action.Remove(user) + +/datum/action/innate/mecha + check_flags = AB_CHECK_RESTRAINED | AB_CHECK_STUNNED | AB_CHECK_CONSCIOUS + icon_icon = 'icons/mob/actions/actions_mecha.dmi' + var/obj/mecha/chassis + +/datum/action/innate/mecha/Grant(mob/living/L, obj/mecha/M) + if(M) + chassis = M + . = ..() + +/datum/action/innate/mecha/Destroy() + chassis = null + return ..() + +/datum/action/innate/mecha/mech_eject + name = "Eject From Mech" + button_icon_state = "mech_eject" + +/datum/action/innate/mecha/mech_eject/Activate() + if(!owner) + return + if(!chassis || chassis.occupant != owner) + return + chassis.go_out() + +/datum/action/innate/mecha/mech_toggle_internals + name = "Toggle Internal Airtank Usage" + button_icon_state = "mech_internals_off" + +/datum/action/innate/mecha/mech_toggle_internals/Activate() + if(!owner || !chassis || chassis.occupant != owner) + return + chassis.use_internal_tank = !chassis.use_internal_tank + button_icon_state = "mech_internals_[chassis.use_internal_tank ? "on" : "off"]" + chassis.occupant_message("Now taking air from [chassis.use_internal_tank ? "internal airtank" : "environment"].") + chassis.log_message("Now taking air from [chassis.use_internal_tank ? "internal airtank" : "environment"].") + UpdateButtonIcon() + +/datum/action/innate/mecha/mech_toggle_lights + name = "Toggle Lights" + button_icon_state = "mech_lights_off" + +/datum/action/innate/mecha/mech_toggle_lights/Activate() + if(!owner || !chassis || chassis.occupant != owner) + return + chassis.lights = !chassis.lights + if(chassis.lights) + chassis.set_light(chassis.lights_power) + button_icon_state = "mech_lights_on" + else + chassis.set_light(-chassis.lights_power) + button_icon_state = "mech_lights_off" + chassis.occupant_message("Toggled lights [chassis.lights ? "on" : "off"].") + chassis.log_message("Toggled lights [chassis.lights ? "on" : "off"].") + UpdateButtonIcon() + +/datum/action/innate/mecha/mech_view_stats + name = "View Stats" + button_icon_state = "mech_view_stats" + +/datum/action/innate/mecha/mech_view_stats/Activate() + if(!owner || !chassis || chassis.occupant != owner) + return + chassis.occupant << browse(chassis.get_stats_html(), "window=exosuit") + +/datum/action/innate/mecha/mech_defence_mode + name = "Toggle Defence Mode" + button_icon_state = "mech_defense_mode_off" + +/datum/action/innate/mecha/mech_defence_mode/Activate(forced_state = null) + if(!owner || !chassis || chassis.occupant != owner) + return + if(!isnull(forced_state)) + chassis.defence_mode = forced_state + else + chassis.defence_mode = !chassis.defence_mode + button_icon_state = "mech_defense_mode_[chassis.defence_mode ? "on" : "off"]" + if(chassis.defence_mode) + chassis.deflect_chance = chassis.defence_mode_deflect_chance + chassis.occupant_message("You enable [chassis] defence mode.") + else + chassis.deflect_chance = initial(chassis.deflect_chance) + chassis.occupant_message("You disable [chassis] defence mode.") + chassis.log_message("Toggled defence mode.") + UpdateButtonIcon() + + +/datum/action/innate/mecha/mech_overload_mode + name = "Toggle leg actuators overload" + button_icon_state = "mech_overload_off" + +/datum/action/innate/mecha/mech_overload_mode/Activate(forced_state = null) + if(!owner || !chassis || chassis.occupant != owner) + return + if(chassis.health < initial(chassis.health) - initial(chassis.health) / 3) + chassis.occupant_message("The leg actuators are too damaged to overload!") + return // Can't activate them if the mech is too damaged + if(!isnull(forced_state)) + chassis.leg_overload_mode = forced_state + else + chassis.leg_overload_mode = !chassis.leg_overload_mode + button_icon_state = "mech_overload_[chassis.leg_overload_mode ? "on" : "off"]" + chassis.log_message("Toggled leg actuators overload.") + if(chassis.leg_overload_mode) + chassis.leg_overload_mode = 1 + // chassis.bumpsmash = 1 + chassis.step_in = min(1, round(chassis.step_in / 2)) + chassis.step_energy_drain = max(chassis.overload_step_energy_drain_min, chassis.step_energy_drain * chassis.leg_overload_coeff) + chassis.occupant_message("You enable leg actuators overload.") + else + chassis.leg_overload_mode = 0 + // chassis.bumpsmash = 0 + chassis.step_in = initial(chassis.step_in) + chassis.step_energy_drain = chassis.normal_step_energy_drain + chassis.occupant_message("You disable leg actuators overload.") + UpdateButtonIcon() + +/datum/action/innate/mecha/mech_toggle_thrusters + name = "Toggle Thrusters" + button_icon_state = "mech_thrusters_off" + +/datum/action/innate/mecha/mech_toggle_thrusters/Activate() + if(!owner || !chassis || chassis.occupant != owner) + return + if(chassis.get_charge() > 0) + chassis.thrusters_active = !chassis.thrusters_active + button_icon_state = "mech_thrusters_[chassis.thrusters_active ? "on" : "off"]" + chassis.log_message("Toggled thrusters.") + chassis.occupant_message("Thrusters [chassis.thrusters_active ? "en" : "dis"]abled.") + +/datum/action/innate/mecha/mech_smoke + name = "Smoke" + button_icon_state = "mech_smoke" + +/datum/action/innate/mecha/mech_smoke/Activate() + if(!owner || !chassis || chassis.occupant != owner) + return + if(chassis.smoke_ready && chassis.smoke > 0) + chassis.smoke_system.start() + chassis.smoke-- + chassis.smoke_ready = 0 + spawn(chassis.smoke_cooldown) + chassis.smoke_ready = 1 + else + chassis.occupant_message("You are either out of smoke, or the smoke isn't ready yet.") + +/datum/action/innate/mecha/mech_zoom + name = "Zoom" + button_icon_state = "mech_zoom_off" + +/datum/action/innate/mecha/mech_zoom/Activate() + if(!owner || !chassis || chassis.occupant != owner) + return + if(owner.client) + chassis.zoom_mode = !chassis.zoom_mode + button_icon_state = "mech_zoom_[chassis.zoom_mode ? "on" : "off"]" + chassis.log_message("Toggled zoom mode.") + chassis.occupant_message("Zoom mode [chassis.zoom_mode ? "en" : "dis"]abled.") + if(chassis.zoom_mode) + owner.client.AddViewMod("mecha", 12) + SEND_SOUND(owner, sound('sound/mecha/imag_enh.ogg',volume=50)) + else + owner.client.RemoveViewMod("mecha") + UpdateButtonIcon() + +/datum/action/innate/mecha/mech_toggle_phasing + name = "Toggle Phasing" + button_icon_state = "mech_phasing_off" + +/datum/action/innate/mecha/mech_toggle_phasing/Activate() + if(!owner || !chassis || chassis.occupant != owner) + return + chassis.phasing = !chassis.phasing + button_icon_state = "mech_phasing_[chassis.phasing ? "on" : "off"]" + chassis.occupant_message("En":"#f00\">Dis"]abled phasing.") + UpdateButtonIcon() \ No newline at end of file diff --git a/code/game/mecha/mecha_topic.dm b/code/game/mecha/mecha_topic.dm index 2ce732f83ed..41d4c3aa540 100644 --- a/code/game/mecha/mecha_topic.dm +++ b/code/game/mecha/mecha_topic.dm @@ -73,81 +73,80 @@ var/cell_charge = get_charge() var/tank_pressure = internal_tank ? round(internal_tank.return_pressure(),0.01) : "None" var/tank_temperature = internal_tank ? internal_tank.return_temperature() : "Unknown" + var/tank_temperature_c = internal_tank ? internal_tank.return_temperature() - T0C : "Unknown" var/cabin_pressure = round(return_pressure(),0.01) - var/output = {"[report_internal_damage()] - [integrity<30?"DAMAGE LEVEL CRITICAL
":null] - 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
- Airtank temperature: [tank_temperature]°K|[tank_temperature - T0C]°C
- Cabin pressure: [cabin_pressure>WARNING_HIGH_PRESSURE ? "[cabin_pressure]": cabin_pressure]kPa
- Cabin temperature: [return_temperature()]°K|[return_temperature() - T0C]°C
- Lights: [lights?"on":"off"]
- [dna?"DNA-locked:
[dna] \[Reset\]
":null] - "} - return output + . = "[report_internal_damage()]" + . += "[integrity<30?"DAMAGE LEVEL CRITICAL
":null]" + . += "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
" + . += "Airtank temperature: [tank_temperature]°K|[tank_temperature_c]°C
" + . += "Cabin pressure: [cabin_pressure>WARNING_HIGH_PRESSURE ? "[cabin_pressure]": cabin_pressure]kPa
" + . += "Cabin temperature: [return_temperature()]°K|[return_temperature() - T0C]°C
" + . += "Lights: [lights?"on":"off"]
" + . += "[dna ? "DNA-locked:
[dna] \[Reset\]
" : ""]" + . += "[defense_action.owner ? "Defence Mode: [defence_mode ? "Enabled" : "Disabled"]
" : ""]" + . += "[overload_action.owner ? "Leg Actuators Overload: [leg_overload_mode ? "Enabled" : "Disabled"]
" : ""]" + . += "[thrusters_action.owner ? "Thrusters: [thrusters_active ? "Enabled" : "Disabled"]
" : ""]" + . += "[smoke_action.owner ? "Smoke: [smoke]
" : ""]" + . += "[zoom_action.owner ? "Zoom: [zoom_mode ? "Enabled" : "Disabled"]
" : ""]" + . += "[phasing_action.owner ? "Phase Modulator: [phasing ? "Enabled" : "Disabled"]
" : ""]" /obj/mecha/proc/get_commands() - var/output = {"
-
Electronics
- -
-
-
Airtank
- -
- -
[get_equipment_menu()]
-
- [(/obj/mecha/verb/eject in verbs)?"Eject
":null] - "} - return output + . = "
" + . += "
Electronics
" + . += "" + . += "
" + . += "
" + . += "
Airtank
" + . += "" + . += "
" + . += "
" + . += "
Permissions & Logging
" + . += "" + . += "
" + . += "
[get_equipment_menu()]
" + . += "
" + . += "Eject
" /obj/mecha/proc/get_equipment_menu() //outputs mecha html equipment menu - var/output + . = "" if(equipment.len) - output += {"
-
Equipment
-
" /obj/mecha/proc/get_equipment_list() //outputs mecha equipment list in html if(!equipment.len) return - var/output = "Equipment:
" + . = "Equipment:
" for(var/obj/item/mecha_parts/mecha_equipment/MT in equipment) - output += "
[MT.get_equip_info()]
" - output += "
" - return output + . += "
[MT.get_equip_info()]
" + . += "
" /obj/mecha/proc/get_log_html() @@ -248,11 +247,11 @@ selected = equip occupant_message("You switch to [equip]") visible_message("[src] raises [equip]") - send_byjax(occupant,"exosuit.browser","eq_list",get_equipment_list()) + send_byjax(occupant, "exosuit.browser", "eq_list", get_equipment_list()) return if(href_list["eject"]) if(usr != occupant) return - eject() + go_out() return if(href_list["toggle_lights"]) if(usr != occupant) return @@ -280,14 +279,6 @@ radio.set_frequency(new_frequency) send_byjax(occupant,"exosuit.browser","rfreq","[format_frequency(radio.frequency)]") return - if(href_list["port_disconnect"]) - if(usr != occupant) return - disconnect_from_port() - return - if(href_list["port_connect"]) - if(usr != occupant) return - connect_to_port() - return if(href_list["view_log"]) if(usr != occupant) return occupant << browse(get_log_html(), "window=exosuit_log") diff --git a/code/game/mecha/medical/odysseus.dm b/code/game/mecha/medical/odysseus.dm index d0fcb0f99be..da746290e8a 100644 --- a/code/game/mecha/medical/odysseus.dm +++ b/code/game/mecha/medical/odysseus.dm @@ -10,6 +10,7 @@ internal_damage_threshold = 35 deflect_chance = 15 step_energy_drain = 6 + normal_step_energy_drain = 6 var/builtin_hud_user = 0 /obj/mecha/medical/odysseus/moved_inside(var/mob/living/carbon/human/H) diff --git a/code/game/mecha/working/ripley.dm b/code/game/mecha/working/ripley.dm index 407c9cd63dc..ab38ee3a0d0 100644 --- a/code/game/mecha/working/ripley.dm +++ b/code/game/mecha/working/ripley.dm @@ -83,6 +83,7 @@ damage_absorption = list("brute"=0.6,"fire"=0.4,"bullet"=0.6,"laser"=0.6,"energy"=1,"bomb"=0.3) wreckage = /obj/effect/decal/mecha_wreckage/ripley/deathripley step_energy_drain = 0 + normal_step_energy_drain = 0 /obj/mecha/working/ripley/deathripley/New() ..() diff --git a/code/modules/admin/verbs/freeze.dm b/code/modules/admin/verbs/freeze.dm index 8dc852e9221..76a7a693838 100644 --- a/code/modules/admin/verbs/freeze.dm +++ b/code/modules/admin/verbs/freeze.dm @@ -104,7 +104,6 @@ var/global/list/frozen_mob_list = list() M.can_move = 0 M.overlays += adminomaly if(M.occupant) - M.removeVerb(/obj/mecha/verb/eject) to_chat(M.occupant, "You have been frozen by [key]") message_admins("[key_name_admin(usr)] froze [key_name(M.occupant)] in a [M.name]") log_admin("[key_name(usr)] froze [key_name(M.occupant)] in a [M.name]") @@ -115,7 +114,6 @@ var/global/list/frozen_mob_list = list() M.can_move = 1 M.overlays -= adminomaly if(M.occupant) - M.addVerb(/obj/mecha/verb/eject) to_chat(M.occupant, "You have been unfrozen by [key]") message_admins("[key_name_admin(usr)] unfroze [key_name(M.occupant)] in a [M.name]") log_admin("[key_name(usr)] unfroze [key_name(M.occupant)] in a [M.name]") diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/dragon.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/dragon.dm index 82e4af1862f..efeec62ae96 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/dragon.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/dragon.dm @@ -101,7 +101,7 @@ Difficulty: Medium animate(src, pixel_z = 0, time = 12) /obj/effect/temp_visual/target - icon = 'icons/mob/actions.dmi' + icon = 'icons/mob/actions/actions.dmi' icon_state = "sniper_zoom" layer = MOB_LAYER - 0.1 luminosity = 2 diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/actions.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/actions.dm index f2bed558b8c..b0756cddd7f 100644 --- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/actions.dm +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/actions.dm @@ -65,7 +65,7 @@ /datum/action/innate/terrorspider/queen/queensense name = "Hive Sense" - icon_icon = 'icons/mob/actions.dmi' + icon_icon = 'icons/mob/actions/actions.dmi' button_icon_state = "mindswap" /datum/action/innate/terrorspider/queen/queensense/Activate() diff --git a/icons/mob/actions.dmi b/icons/mob/actions/actions.dmi similarity index 100% rename from icons/mob/actions.dmi rename to icons/mob/actions/actions.dmi diff --git a/icons/mob/actions/actions_mecha.dmi b/icons/mob/actions/actions_mecha.dmi new file mode 100644 index 00000000000..81c706b22c8 Binary files /dev/null and b/icons/mob/actions/actions_mecha.dmi differ diff --git a/icons/mob/screen_alert.dmi b/icons/mob/screen_alert.dmi index 56c1730fd3a..b2e0a83bd35 100644 Binary files a/icons/mob/screen_alert.dmi and b/icons/mob/screen_alert.dmi differ diff --git a/paradise.dme b/paradise.dme index 8c37b4e4f1c..a1f78604645 100644 --- a/paradise.dme +++ b/paradise.dme @@ -694,6 +694,7 @@ #include "code\game\mecha\mech_bay.dm" #include "code\game\mecha\mech_fabricator.dm" #include "code\game\mecha\mecha.dm" +#include "code\game\mecha\mecha_actions.dm" #include "code\game\mecha\mecha_construction_paths.dm" #include "code\game\mecha\mecha_control_console.dm" #include "code\game\mecha\mecha_parts.dm"