diff --git a/code/_onclick/hud/action_button.dm b/code/_onclick/hud/action_button.dm index 5ce1d3130d..b347a5c55a 100644 --- a/code/_onclick/hud/action_button.dm +++ b/code/_onclick/hud/action_button.dm @@ -29,25 +29,31 @@ return ..() /atom/movable/screen/movable/action_button/proc/can_use(mob/user) - if (linked_action) + if(isobserver(user)) + var/mob/dead/observer/dead_mob = user + if(dead_mob.observetarget) // Observers can only click on action buttons if they're not observing something + return FALSE + + if(linked_action) if(linked_action.viewers[user.hud_used]) return TRUE return FALSE - else if (isobserver(user)) - var/mob/dead/observer/O = user - return !O.observetarget - else - return TRUE + + return TRUE /atom/movable/screen/movable/action_button/Click(location,control,params) if (!can_use(usr)) return var/list/modifiers = params2list(params) - if(modifiers["shift"]) + if(LAZYACCESS(modifiers, SHIFT_CLICK)) var/datum/hud/our_hud = usr.hud_used our_hud.position_action(src, SCRN_OBJ_DEFAULT) return TRUE + var/mob/clicker = usr + if(!clicker.CheckActionCooldown()) + return + clicker.DelayNextAction(1) linked_action.Trigger() return TRUE @@ -82,7 +88,7 @@ closeToolTip(usr) return ..() -/atom/movable/screen/movable/action_button/MouseDrop(over_object) +/atom/movable/screen/movable/action_button/MouseDrop(atom/over_object, mob/user, src_location, over_location, params) last_hovored_ref = null if(!can_use(usr)) return @@ -107,7 +113,6 @@ our_hud.position_action_relative(src, button) save_position() return - . = ..() our_hud.position_action(src, screen_loc) save_position() @@ -141,6 +146,12 @@ user.client.prefs.action_buttons_screen_locs -= "[name]_[id]" user.client.prefs.queue_save_pref(1 SECONDS, TRUE) +/** + * This is a silly proc used in hud code code to determine what icon and icon state we should be using + * for hud elements (such as action buttons) that don't have their own icon and icon state set. + * + * It returns a list, which is pretty much just a struct of info + */ /datum/hud/proc/get_action_buttons_icons() . = list() .["bg_icon"] = ui_style @@ -153,8 +164,15 @@ var/datum/action/A = X A.UpdateButtons(status_only) -//This is the proc used to update all the action buttons. -/mob/proc/update_action_buttons(reload_screen) +/** + * This proc handles adding all of the mob's actions to their screen + * + * If you just need to update existing buttons, use [/mob/proc/update_mob_action_buttons]! + * + * Arguments: + * * update_flags - reload_screen - bool, if TRUE, this proc will add the button to the screen of the passed mob as well + */ +/mob/proc/update_action_buttons(reload_screen = FALSE) if(!hud_used || !client) return diff --git a/code/datums/action.dm b/code/datums/action.dm index 4c9099fc72..f7093b1ff6 100644 --- a/code/datums/action.dm +++ b/code/datums/action.dm @@ -5,32 +5,50 @@ #define AB_CHECK_ALIVE 16 /datum/action + /// The name of the action var/name = "Generic Action" + /// The description of what the action does, shown in button tooltips var/desc = null - var/atom/target = null - var/check_flags = 0 - var/required_mobility_flags = MOBILITY_USE - var/processing = FALSE - var/buttontooltipstyle = "" - var/transparent_when_unavailable = TRUE + /// The target the action is attached to. If the target datum is deleted, the action is as well. + /// Set in New() via the proc link_to(). PLEASE set a target if you're making an action + var/datum/target = null /// Where any buttons we create should be by default. Accepts screen_loc and location defines var/default_button_position = SCRN_OBJ_IN_LIST - - var/button_icon = 'icons/mob/actions/backgrounds.dmi' //This is the file for the BACKGROUND icon - var/background_icon_state = ACTION_BUTTON_DEFAULT_BACKGROUND //And this is the state for the background icon - - var/icon_icon = 'icons/mob/actions.dmi' //This is the file for the ACTION icon - var/button_icon_state = "default" //And this is the state for the action icon + /// This is who currently owns the action, and most often, this is who is using the action if it is triggered + /// This can be the same as "target" but is not ALWAYS the same - this is set and unset with Grant() and Remove() var/mob/owner + /// Flags that will determine of the owner / user of the action can... use the action + var/check_flags = NONE + var/required_mobility_flags = MOBILITY_USE + var/processing = FALSE + /// Whether the button becomes transparent when it can't be used, or just reddened + var/transparent_when_unavailable = TRUE ///List of all mobs that are viewing our action button -> A unique movable for them to view. var/list/viewers = list() + /// The style the button's tooltips appear to be + var/buttontooltipstyle = "" + + /// This is the file for the BACKGROUND underlay icon of the button + var/button_icon = 'icons/mob/actions/backgrounds.dmi' + /// This is the icon state state for the BACKGROUND underlay icon of the button + /// (If set to ACTION_BUTTON_DEFAULT_BACKGROUND, uses the hud's default background) + var/background_icon_state = ACTION_BUTTON_DEFAULT_BACKGROUND + + /// This is the file for the icon that appears on the button + var/icon_icon = 'icons/mob/actions.dmi' + /// This is the icon state for the icon that appears on the button + var/button_icon_state = "default" + /datum/action/New(Target) link_to(Target) /datum/action/proc/link_to(Target) target = Target - RegisterSignal(Target, COMSIG_ATOM_UPDATED_ICON, PROC_REF(OnUpdatedIcon)) + RegisterSignal(Target, COMSIG_PARENT_QDELETING, PROC_REF(clear_ref), override = TRUE) + + if(isatom(Target)) + RegisterSignal(Target, COMSIG_ATOM_UPDATED_ICON, PROC_REF(OnUpdatedIcon)) /datum/action/Destroy() if(owner) @@ -39,23 +57,8 @@ QDEL_LIST_ASSOC_VAL(viewers) // Qdel the buttons in the viewers list **NOT THE HUDS** return ..() -/datum/action/proc/Grant(mob/M) - if(!M) - Remove(owner) - return - if(owner) - if(owner == M) - return - Remove(owner) - owner = M - RegisterSignal(owner, COMSIG_PARENT_QDELETING, PROC_REF(clear_ref), override = TRUE) - // Register some signals based on our check_flags - // so that our button icon updates when relevant - if(check_flags & AB_CHECK_CONSCIOUS) - RegisterSignal(owner, COMSIG_MOB_STATCHANGE, PROC_REF(update_status_on_signal)) - - GiveAction(M) - +/// Signal proc that clears any references based on the owner or target deleting +/// If the owner's deleted, we will simply remove from them, but if the target's deleted, we will self-delete /datum/action/proc/clear_ref(datum/ref) SIGNAL_HANDLER if(ref == owner) @@ -63,23 +66,51 @@ if(ref == target) qdel(src) -/datum/action/proc/Remove(mob/M) +/datum/action/proc/Grant(mob/grant_to) + if(isnull(grant_to)) + Remove(owner) + return + if(grant_to == owner) + return // We already have it + var/mob/previous_owner = owner + owner = grant_to + if(!isnull(previous_owner)) + Remove(previous_owner) + RegisterSignal(owner, COMSIG_PARENT_QDELETING, PROC_REF(clear_ref), override = TRUE) + + // Register some signals based on our check_flags + // so that our button icon updates when relevant + if(check_flags & AB_CHECK_CONSCIOUS) + RegisterSignal(owner, COMSIG_MOB_STATCHANGE, PROC_REF(update_status_on_signal)) + + GiveAction(grant_to) + +/datum/action/proc/Remove(mob/remove_from) + SHOULD_CALL_PARENT(TRUE) + for(var/datum/hud/hud in viewers) if(!hud.mymob) continue HideFrom(hud.mymob) - LAZYREMOVE(M.actions, src) // We aren't always properly inserted into the viewers list, gotta make sure that action's cleared + LAZYREMOVE(remove_from.actions, src) // We aren't always properly inserted into the viewers list, gotta make sure that action's cleared viewers = list() - if(owner) - UnregisterSignal(owner, list( - COMSIG_PARENT_QDELETING, - COMSIG_MOB_STATCHANGE - )) - if(target == owner) - RegisterSignal(target, COMSIG_PARENT_QDELETING, PROC_REF(clear_ref)) + if(isnull(owner)) + return + UnregisterSignal(owner, COMSIG_PARENT_QDELETING) + + // Clean up our check_flag signals + UnregisterSignal(owner, list( + COMSIG_MOB_STATCHANGE + )) + + if(target == owner) + RegisterSignal(target, COMSIG_PARENT_QDELETING, PROC_REF(clear_ref)) + if(owner == remove_from) owner = null +/// Actually triggers the effects of the action. +/// Called when the on-screen button is clicked, for example. /datum/action/proc/Trigger() if(!IsAvailable()) return FALSE @@ -90,6 +121,10 @@ /datum/action/proc/Process() return +/** + * Whether our action is currently available to use or not + * * silent - If false this is being called to check if we have any messages to show to the owner + */ /datum/action/proc/IsAvailable(silent = FALSE) if(!owner) return FALSE @@ -104,9 +139,13 @@ return FALSE if(check_flags & AB_CHECK_LYING) if(istype(L) && !CHECK_MOBILITY(L, MOBILITY_STAND)) + if (!silent) + owner.balloon_alert(owner, "must stand up!") return FALSE if(check_flags & AB_CHECK_CONSCIOUS) if(owner.stat) + if (!silent) + owner.balloon_alert(owner, "unconscious!") return FALSE if(check_flags & AB_CHECK_ALIVE) if(owner.stat == DEAD) @@ -166,7 +205,8 @@ SIGNAL_HANDLER UpdateButtons(force = TRUE) -//Give our action button to the player +/// Gives our action to the passed viewer. +/// Puts our action in their actions list and shows them the button. /datum/action/proc/GiveAction(mob/viewer) var/datum/hud/our_hud = viewer.hud_used if(viewers[our_hud]) // Already have a copy of us? go away @@ -175,7 +215,7 @@ LAZYOR(viewer.actions, src) // Move this in ShowTo(viewer) -//Adds our action button to the screen of a player +/// Adds our action button to the screen of the passed viewer. /datum/action/proc/ShowTo(mob/viewer) var/datum/hud/our_hud = viewer.hud_used if(!our_hud || viewers[our_hud]) // There's no point in this if you have no hud in the first place @@ -192,7 +232,7 @@ button.load_position(viewer) viewer.update_action_buttons() -//Removes our action button from the screen of a player +/// Removes our action from the passed viewer. /datum/action/proc/HideFrom(mob/viewer) var/datum/hud/our_hud = viewer.hud_used var/atom/movable/screen/movable/action_button/button = viewers[our_hud] @@ -445,7 +485,8 @@ /datum/action/item_action/toggle/New(Target) ..() - name = "Toggle [target.name]" + var/obj/item/item_target = target + name = "Toggle [item_target.name]" /datum/action/item_action/halt name = "HALT!" @@ -473,7 +514,9 @@ /datum/action/item_action/adjust/New(Target) ..() - name = "Adjust [target.name]" + var/obj/item/item_target = target + name = "Adjust [item_target.name]" + /datum/action/item_action/switch_hud name = "Switch HUD" @@ -548,21 +591,31 @@ return ..() /datum/action/item_action/organ_action + name = "Organ Action" check_flags = AB_CHECK_CONSCIOUS /datum/action/item_action/organ_action/IsAvailable(silent = FALSE) - var/obj/item/organ/I = target - if(!I.owner) + var/obj/item/organ/attached_organ = target + if(!attached_organ.owner) return FALSE return ..() +/datum/action/item_action/organ_action/toggle + name = "Toggle Organ" + /datum/action/item_action/organ_action/toggle/New(Target) ..() - name = "Toggle [target.name]" + var/obj/item/organ/organ_target = target + name = "Toggle [organ_target.name]" + +/datum/action/item_action/organ_action/use + name = "Use Organ" /datum/action/item_action/organ_action/use/New(Target) ..() - name = "Use [target.name]" + var/obj/item/organ/organ_target = target + name = "Use [organ_target.name]" + /datum/action/item_action/cult_dagger name = "Draw Blood Rune" @@ -956,20 +1009,8 @@ /datum/action/item_action/storage_gather_mode name = "Switch gathering mode" desc = "Switches the gathering mode of a storage object." - icon_icon = 'icons/mob/actions/actions_items.dmi' - button_icon_state = "storage_gather_switch" - -/datum/action/item_action/storage_gather_mode/ApplyIcon(atom/movable/screen/movable/action_button/current_button) - . = ..() - var/old_layer = target.layer - var/old_plane = target.plane - target.layer = FLOAT_LAYER //AAAH - target.plane = FLOAT_PLANE //^ what that guy said - current_button.cut_overlays() - current_button.add_overlay(target) - target.layer = old_layer - target.plane = old_plane - current_button.appearance_cache = target.appearance + button_icon = 'icons/mob/actions/actions_items.dmi' + background_icon_state = "storage_gather_switch" /proc/get_action_of_type(mob/M, action_type) if(!M.actions || !ispath(action_type, /datum/action)) diff --git a/code/datums/elements/polychromic.dm b/code/datums/elements/polychromic.dm index 79e186ffe9..bc6a6dd1da 100644 --- a/code/datums/elements/polychromic.dm +++ b/code/datums/elements/polychromic.dm @@ -204,7 +204,9 @@ check_flags = NONE /datum/action/item_action/polychromic/ApplyIcon(atom/movable/screen/movable/action_button/current_button, force) - var/matrix/save_matrix = target.transform - target.transform = matrix(0.8, 0, 0, 0, 0.8, 0) + var/atom/polychromic_thing = target + + var/matrix/save_matrix = polychromic_thing.transform + polychromic_thing.transform = matrix(0.8, 0, 0, 0, 0.8, 0) . = ..() - target.transform = save_matrix + polychromic_thing.transform = save_matrix diff --git a/code/game/machinery/computer/camera_advanced.dm b/code/game/machinery/computer/camera_advanced.dm index 95c4a089f3..a34a0ed500 100644 --- a/code/game/machinery/computer/camera_advanced.dm +++ b/code/game/machinery/computer/camera_advanced.dm @@ -3,18 +3,23 @@ desc = "Used to access the various cameras on the station." icon_screen = "cameras" icon_keyboard = "security_key" + light_color = LIGHT_COLOR_RED + var/list/z_lock = list() // Lock use to these z levels var/lock_override = NONE var/mob/camera/aiEye/remote/eyeobj var/mob/living/current_user = null var/list/networks = list("ss13") - var/datum/action/innate/camera_off/off_action = new - var/datum/action/innate/camera_jump/jump_action = new - var/list/actions = list() - /// Should we suppress the user's view? - var/should_supress_view_changes = TRUE + /// Typepath of the action button we use as "off" + /// It's a typepath so subtypes can give it fun new names + var/datum/action/innate/camera_off/off_action = /datum/action/innate/camera_off + /// Typepath for jumping + var/datum/action/innate/camera_jump/jump_action = /datum/action/innate/camera_jump - light_color = LIGHT_COLOR_RED + /// List of all actions to give to a user when they're well, granted actions + var/list/actions = list() + ///Should we supress any view changes? + var/should_supress_view_changes = TRUE /obj/machinery/computer/camera_advanced/Initialize(mapload) . = ..() @@ -31,6 +36,11 @@ if(lock_override & CAMERA_LOCK_REEBE) z_lock |= SSmapping.levels_by_trait(ZTRAIT_REEBE) + if(off_action) + actions += new off_action(src) + if(jump_action) + actions += new jump_action(src) + /obj/machinery/computer/camera_advanced/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE) for(var/i in networks) networks -= i @@ -47,40 +57,30 @@ eyeobj.origin = src /obj/machinery/computer/camera_advanced/proc/GrantActions(mob/living/user) - if(off_action) - off_action.target = user - off_action.Grant(user) - actions += off_action - - if(jump_action) - jump_action.target = user - jump_action.Grant(user) - actions += jump_action + for(var/datum/action/to_grant as anything in actions) + to_grant.Grant(user) /obj/machinery/proc/remove_eye_control(mob/living/user) CRASH("[type] does not implement ai eye handling") /obj/machinery/computer/camera_advanced/remove_eye_control(mob/living/user) - if(!user) + if(isnull(user?.client)) return - for(var/V in actions) - var/datum/action/A = V - A.Remove(user) - actions.Cut() - for(var/V in eyeobj.visibleCameraChunks) - var/datum/camerachunk/C = V - C.remove(eyeobj) - if(user.client) - user.reset_perspective(null) - if(eyeobj.visible_icon && user.client) - user.client.images -= eyeobj.user_image + + for(var/datum/action/actions_removed as anything in actions) + actions_removed.Remove(user) + for(var/datum/camerachunk/camerachunks_gone as anything in eyeobj.visibleCameraChunks) + camerachunks_gone.remove(eyeobj) + + user.reset_perspective(null) + if(eyeobj.visible_icon) + user.client.images -= eyeobj.user_image + user.client.view_size.unsupress() + eyeobj.eye_user = null user.remote_control = null - current_user = null - user.unset_machine() - user.client.view_size.unsupress() - playsound(src, 'sound/machines/terminal_off.ogg', 25, 0) + playsound(src, 'sound/machines/terminal_off.ogg', 25, FALSE) /obj/machinery/computer/camera_advanced/check_eye(mob/user) if( (stat & (NOPOWER|BROKEN)) || (!Adjacent(user) && hasSiliconAccessInArea(user)) || user.eye_blind || user.incapacitated() ) @@ -89,8 +89,7 @@ /obj/machinery/computer/camera_advanced/Destroy() if(current_user) current_user.unset_machine() - if(eyeobj) - qdel(eyeobj) + QDEL_NULL(eyeobj) QDEL_LIST(actions) return ..() @@ -153,6 +152,8 @@ return //AIs would need to disable their own camera procs to use the console safely. Bugs happen otherwise. /obj/machinery/computer/camera_advanced/proc/give_eye_control(mob/user) + if(isnull(user?.client)) + return GrantActions(user) current_user = user eyeobj.eye_user = user @@ -193,16 +194,19 @@ return eye_user.client return null -/mob/camera/aiEye/remote/setLoc(T) +/mob/camera/aiEye/remote/setLoc(destination) if(eye_user) - T = get_turf(T) - if (T) - forceMove(T) + destination = get_turf(destination) + if (destination) + abstract_move(destination) else moveToNullspace() + update_ai_detect_hud() + if(use_static != USE_STATIC_NONE) GLOB.cameranet.visibility(src, GetViewerClient(), null, use_static) + if(visible_icon) if(eye_user.client) eye_user.client.images -= user_image @@ -233,12 +237,11 @@ button_icon_state = "camera_off" /datum/action/innate/camera_off/Activate() - if(!target || !isliving(target)) + if(!owner || !isliving(owner)) return - var/mob/living/C = target - var/mob/camera/aiEye/remote/remote_eye = C.remote_control + var/mob/camera/aiEye/remote/remote_eye = owner.remote_control var/obj/machinery/computer/camera_advanced/console = remote_eye.origin - console.remove_eye_control(target) + console.remove_eye_control(owner) /datum/action/innate/camera_jump name = "Jump To Camera" @@ -246,16 +249,15 @@ button_icon_state = "camera_jump" /datum/action/innate/camera_jump/Activate() - if(!target || !isliving(target)) + if(!owner || !isliving(owner)) return - var/mob/living/C = target - var/mob/camera/aiEye/remote/remote_eye = C.remote_control + var/mob/camera/aiEye/remote/remote_eye = owner.remote_control var/obj/machinery/computer/camera_advanced/origin = remote_eye.origin var/list/L = list() - for (var/obj/machinery/camera/cam in GLOB.cameranet.cameras) - if(origin.z_lock.len && !(cam.z in origin.z_lock)) + for (var/obj/machinery/camera/cam as anything in GLOB.cameranet.cameras) + if(length(origin.z_lock) && !(cam.z in origin.z_lock)) continue L.Add(cam) @@ -265,17 +267,23 @@ for (var/obj/machinery/camera/netcam in L) var/list/tempnetwork = netcam.network & origin.networks - if (tempnetwork.len) + if (length(tempnetwork)) + if(!netcam.c_tag) + continue T["[netcam.c_tag][netcam.can_use() ? null : " (Deactivated)"]"] = netcam - playsound(origin, 'sound/machines/terminal_prompt.ogg', 25, 0) + playsound(origin, 'sound/machines/terminal_prompt.ogg', 25, FALSE) var/camera = input("Choose which camera you want to view", "Cameras") as null|anything in T + if(isnull(camera)) + return + if(isnull(T[camera])) + return var/obj/machinery/camera/final = T[camera] - playsound(src, "terminal_type", 25, 0) + playsound(src, "terminal_type", 25, FALSE) if(final) - playsound(origin, 'sound/machines/terminal_prompt_confirm.ogg', 25, 0) + playsound(origin, 'sound/machines/terminal_prompt_confirm.ogg', 25, FALSE) remote_eye.setLoc(get_turf(final)) - C.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/tiled/flash/static) - C.clear_fullscreen("flash", 3) //Shorter flash than normal since it's an ~~advanced~~ console! + owner.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/tiled/flash/static) + owner.clear_fullscreen("flash", 3) //Shorter flash than normal since it's an ~~advanced~~ console! else - playsound(origin, 'sound/machines/terminal_prompt_deny.ogg', 25, 0) + playsound(origin, 'sound/machines/terminal_prompt_deny.ogg', 25, FALSE) diff --git a/code/modules/antagonists/cult/cult.dm b/code/modules/antagonists/cult/cult.dm index f5761f6508..63b82f26ce 100644 --- a/code/modules/antagonists/cult/cult.dm +++ b/code/modules/antagonists/cult/cult.dm @@ -254,7 +254,7 @@ /datum/team/cult name = "Cult" - var/blood_target + var/atom/blood_target var/image/blood_target_image var/blood_target_reset_timer diff --git a/code/modules/antagonists/cult/cult_comms.dm b/code/modules/antagonists/cult/cult_comms.dm index b81422157c..cd348485f1 100644 --- a/code/modules/antagonists/cult/cult_comms.dm +++ b/code/modules/antagonists/cult/cult_comms.dm @@ -363,8 +363,8 @@ addtimer(CALLBACK(owner, TYPE_PROC_REF(/mob, update_action_buttons_icon)), base_cooldown) C.cult_team.blood_target_image = image('icons/effects/cult_target.dmi', target, "glow", ABOVE_MOB_LAYER) C.cult_team.blood_target_image.appearance_flags = RESET_COLOR - C.cult_team.blood_target_image.pixel_x = -target.pixel_x - C.cult_team.blood_target_image.pixel_y = -target.pixel_y + C.cult_team.blood_target_image.pixel_x = -C.cult_team.blood_target.pixel_x + C.cult_team.blood_target_image.pixel_y = -C.cult_team.blood_target.pixel_y SEND_SOUND(owner, sound(pick('sound/hallucinations/over_here2.ogg','sound/hallucinations/over_here3.ogg'),0,1,75)) owner.client.images += C.cult_team.blood_target_image for(var/datum/mind/B in SSticker.mode.cult) diff --git a/code/modules/clothing/chameleon.dm b/code/modules/clothing/chameleon.dm index f26da5db38..b3030b67ec 100644 --- a/code/modules/clothing/chameleon.dm +++ b/code/modules/clothing/chameleon.dm @@ -212,13 +212,15 @@ UpdateButtons() /datum/action/item_action/chameleon/change/proc/update_item(obj/item/picked_item) - target.name = initial(picked_item.name) - target.desc = initial(picked_item.desc) - target.icon_state = initial(picked_item.icon_state) - if(isitem(target)) - var/obj/item/I = target + var/obj/item/chameleon_item = target + + chameleon_item.name = initial(picked_item.name) + chameleon_item.desc = initial(picked_item.desc) + chameleon_item.icon_state = initial(picked_item.icon_state) + if(isitem(chameleon_item)) + var/obj/item/I = chameleon_item I.item_state = initial(picked_item.item_state) - var/obj/item/clothing/CL = target + var/obj/item/clothing/CL = chameleon_item var/obj/item/clothing/PCL = new picked_item if(istype(CL) && istype(PCL)) CL.flags_cover = PCL.flags_cover @@ -226,7 +228,7 @@ CL.mutantrace_variation = PCL.mutantrace_variation CL.mob_overlay_icon = PCL.mob_overlay_icon qdel(PCL) - target.icon = initial(picked_item.icon) + chameleon_item.icon = initial(picked_item.icon) /datum/action/item_action/chameleon/change/pda/update_item(obj/item/pda/picked_item) if(!istype(target, /obj/item/pda)) diff --git a/code/modules/mining/aux_base_camera.dm b/code/modules/mining/aux_base_camera.dm index 262e776c68..0224ff2769 100644 --- a/code/modules/mining/aux_base_camera.dm +++ b/code/modules/mining/aux_base_camera.dm @@ -39,15 +39,15 @@ networks = list("ss13") var/obj/item/construction/rcd/internal/RCD //Internal RCD. The computer passes user commands to this in order to avoid massive copypaste. circuit = /obj/item/circuitboard/computer/base_construction - off_action = new/datum/action/innate/camera_off/base_construction + off_action = /datum/action/innate/camera_off/base_construction jump_action = null - var/datum/action/innate/aux_base/switch_mode/switch_mode_action = new //Action for switching the RCD's build modes - var/datum/action/innate/aux_base/build/build_action = new //Action for using the RCD - var/datum/action/innate/aux_base/airlock_type/airlock_mode_action = new //Action for setting the airlock type - var/datum/action/innate/aux_base/window_type/window_action = new //Action for setting the window type - var/datum/action/innate/aux_base/place_fan/fan_action = new //Action for spawning fans + var/datum/action/innate/aux_base/switch_mode/switch_mode_action = /datum/action/innate/aux_base/switch_mode //Action for switching the RCD's build modes + var/datum/action/innate/aux_base/build/build_action = /datum/action/innate/aux_base/build //Action for using the RCD + var/datum/action/innate/aux_base/airlock_type/airlock_mode_action = /datum/action/innate/aux_base/airlock_type //Action for setting the airlock type + var/datum/action/innate/aux_base/window_type/window_action = /datum/action/innate/aux_base/window_type //Action for setting the window type + var/datum/action/innate/aux_base/place_fan/fan_action = /datum/action/innate/aux_base/place_fan //Action for spawning fans var/fans_remaining = 0 //Number of fans in stock. - var/datum/action/innate/aux_base/install_turret/turret_action = new //Action for spawning turrets + var/datum/action/innate/aux_base/install_turret/turret_action = /datum/action/innate/aux_base/install_turret //Action for spawning turrets var/turret_stock = 0 //Turrets in stock var/obj/machinery/computer/auxillary_base/found_aux_console //Tracker for the Aux base console, so the eye can always find it. @@ -58,6 +58,9 @@ /obj/machinery/computer/camera_advanced/base_construction/Initialize(mapload) . = ..() + + populate_actions_list() + RCD = new(src) RCD.console = src if(mapload) //Map spawned consoles have a filled RCD and stocked special structures @@ -65,6 +68,20 @@ fans_remaining = 4 turret_stock = 4 +/** + * Fill the construction_actios list with actions + * + * Instantiate each action object that we'll be giving to users of + * this console, and put it in the actions list + */ +/obj/machinery/computer/camera_advanced/base_construction/proc/populate_actions_list() + actions += new switch_mode_action(src) + actions += new build_action(src) + actions += new airlock_mode_action(src) + actions += new window_action(src) + actions += new fan_action(src) + actions += new turret_action(src) + /obj/machinery/computer/camera_advanced/base_construction/CreateEye() var/spawn_spot @@ -94,43 +111,12 @@ return ..() /obj/machinery/computer/camera_advanced/base_construction/GrantActions(mob/living/user) - ..() - - if(switch_mode_action) - switch_mode_action.target = src - switch_mode_action.Grant(user) - actions += switch_mode_action - - if(build_action) - build_action.target = src - build_action.Grant(user) - actions += build_action - - if(airlock_mode_action) - airlock_mode_action.target = src - airlock_mode_action.Grant(user) - actions += airlock_mode_action - - if(window_action) - window_action.target = src - window_action.Grant(user) - actions += window_action - - if(fan_action) - fan_action.target = src - fan_action.Grant(user) - actions += fan_action - - if(turret_action) - turret_action.target = src - turret_action.Grant(user) - actions += turret_action - eyeobj.invisibility = 0 //When the eye is in use, make it visible to players so they know when someone is building. + return ..() /obj/machinery/computer/camera_advanced/base_construction/remove_eye_control(mob/living/user) - ..() eyeobj.invisibility = INVISIBILITY_MAXIMUM //Hide the eye when not in use. + return ..() /datum/action/innate/aux_base //Parent aux base action icon_icon = 'icons/mob/actions/actions_construction.dmi' diff --git a/code/modules/research/xenobiology/xenobio_camera.dm b/code/modules/research/xenobiology/xenobio_camera.dm index 1660feedca..8f8508c412 100644 --- a/code/modules/research/xenobiology/xenobio_camera.dm +++ b/code/modules/research/xenobiology/xenobio_camera.dm @@ -22,13 +22,13 @@ desc = "A computer used for remotely handling slimes." networks = list("ss13") circuit = /obj/item/circuitboard/computer/xenobiology - var/datum/action/innate/slime_place/slime_place_action - var/datum/action/innate/slime_pick_up/slime_up_action - var/datum/action/innate/feed_slime/feed_slime_action - var/datum/action/innate/monkey_recycle/monkey_recycle_action - var/datum/action/innate/slime_scan/scan_action - var/datum/action/innate/feed_potion/potion_action - var/datum/action/innate/hotkey_help/hotkey_help + var/datum/action/innate/slime_place/slime_place_action = /datum/action/innate/slime_place + var/datum/action/innate/slime_pick_up/slime_up_action = /datum/action/innate/slime_pick_up + var/datum/action/innate/feed_slime/feed_slime_action = /datum/action/innate/feed_slime + var/datum/action/innate/monkey_recycle/monkey_recycle_action = /datum/action/innate/monkey_recycle + var/datum/action/innate/slime_scan/scan_action = /datum/action/innate/slime_scan + var/datum/action/innate/feed_potion/potion_action = /datum/action/innate/feed_potion + var/datum/action/innate/hotkey_help/hotkey_help = /datum/action/innate/hotkey_help var/list/stored_slimes var/obj/item/slimepotion/slime/current_potion @@ -43,16 +43,16 @@ /obj/machinery/computer/camera_advanced/xenobio/Initialize(mapload) . = ..() - slime_place_action = new - slime_up_action = new - feed_slime_action = new - monkey_recycle_action = new - scan_action = new - potion_action = new - hotkey_help = new + + generate_actions() + stored_slimes = list() RegisterSignal(src, COMSIG_ATOM_CONTENTS_DEL, PROC_REF(on_contents_del)) +/obj/machinery/computer/camera_advanced/xenobio/proc/generate_actions() + actions += new scan_action(src) + actions += new hotkey_help(src) + /obj/machinery/computer/camera_advanced/xenobio/Destroy() stored_slimes = null QDEL_NULL(current_potion) @@ -72,41 +72,6 @@ /obj/machinery/computer/camera_advanced/xenobio/GrantActions(mob/living/user) ..() - if(slime_up_action && (upgradetier & XENOBIO_UPGRADE_SLIMEBASIC)) //CIT CHANGE - makes slime-related actions require XENOBIO_UPGRADE_SLIMEBASIC - slime_up_action.target = src - slime_up_action.Grant(user) - actions += slime_up_action - - if(slime_place_action && (upgradetier & XENOBIO_UPGRADE_SLIMEBASIC)) //CIT CHANGE - makes slime-related actions require XENOBIO_UPGRADE_SLIMEBASIC - slime_place_action.target = src - slime_place_action.Grant(user) - actions += slime_place_action - - if(feed_slime_action && (upgradetier & XENOBIO_UPGRADE_MONKEYS)) //CIT CHANGE - makes monkey-related actions require XENOBIO_UPGRADE_MONKEYS - feed_slime_action.target = src - feed_slime_action.Grant(user) - actions += feed_slime_action - - if(monkey_recycle_action && (upgradetier & XENOBIO_UPGRADE_MONKEYS)) //CIT CHANGE - makes monkey-related actions require XENOBIO_UPGRADE_MONKEYS - monkey_recycle_action.target = src - monkey_recycle_action.Grant(user) - actions += monkey_recycle_action - - if(scan_action) - scan_action.target = src - scan_action.Grant(user) - actions += scan_action - - if(potion_action && (upgradetier & XENOBIO_UPGRADE_SLIMEADV)) // CIT CHANGE - makes giving slimes potions via console require XENOBIO_UPGRADE_SLIMEADV - potion_action.target = src - potion_action.Grant(user) - actions += potion_action - - if(hotkey_help) - hotkey_help.target = src - hotkey_help.Grant(user) - actions += hotkey_help - RegisterSignal(user, COMSIG_XENO_SLIME_CLICK_CTRL, PROC_REF(XenoSlimeClickCtrl)) RegisterSignal(user, COMSIG_XENO_SLIME_CLICK_ALT, PROC_REF(XenoSlimeClickAlt)) RegisterSignal(user, COMSIG_XENO_SLIME_CLICK_SHIFT, PROC_REF(XenoSlimeClickShift)) @@ -139,10 +104,21 @@ else upgradetier |= I successfulupgrade = TRUE + if(I == XENOBIO_UPGRADE_SLIMEBASIC) + actions += new slime_up_action(src) + actions += new slime_place_action(src) if(I == XENOBIO_UPGRADE_SLIMEADV) + actions += new potion_action(src) max_slimes = 10 + if(I == XENOBIO_UPGRADE_MONKEYS) + actions += new feed_slime_action(src) + actions += new monkey_recycle_action(src) if(successfulupgrade) to_chat(user, "You have successfully upgraded [src] with [O].") + + for(var/datum/action/actions_removed as anything in actions) + actions_removed.Remove(current_user) + GrantActions(current_user) else to_chat(user, "[src] already has the contents of [O] installed!") return diff --git a/code/modules/surgery/dental_implant.dm b/code/modules/surgery/dental_implant.dm index e8d0564c62..b5461da25a 100644 --- a/code/modules/surgery/dental_implant.dm +++ b/code/modules/surgery/dental_implant.dm @@ -33,10 +33,11 @@ /datum/action/item_action/hands_free/activate_pill/Trigger() if(!..()) return FALSE - to_chat(owner, "You grit your teeth and burst the implanted [target.name]!") + var/obj/item/item_target = target + to_chat(owner, span_notice("You grit your teeth and burst the implanted [item_target.name]!")) log_combat(owner, null, "swallowed an implanted pill", target) - if(target.reagents.total_volume) - target.reagents.reaction(owner, INGEST) - target.reagents.trans_to(owner, target.reagents.total_volume, log = "dental pill swallow") + if(item_target.reagents.total_volume) + item_target.reagents.reaction(owner, INGEST) + item_target.reagents.trans_to(owner, item_target.reagents.total_volume, log = "dental pill swallow") qdel(target) return TRUE