mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-09 07:46:20 +00:00
MODSuit procs now pass who clicked the UI button + misc code cleanup (#92424)
## About The Pull Request Most of these changes are centered around removing `mod.wearer` references in module function bubble alerts. However, I cleaned up a few other things that I thought were easy fixes. ~~This PR should be testmerged~~ nah send it. I think I did a pretty good job testing, but there might be a bug or two I missed. (debug modsuit should allow conflicting modules and have unlimited complexity btw) ### Track who clicks the activate button * Adds `mob/activator` to `on_select()`, `activate()`, `deactivate()`, `used()`, `on_activation()`, `on_deactivation()` and `on_use()` * `mod_ui` now passes `ui.user`, which is who actually clicked the button in the UI.1 * module action proc now passes the person clicking. * **Alert bubbles:** Modifies many module code bubbles to pass the activation bubble text to `mob/activator` instead of `mob.wearer` so that pAIs get feedback on why clicking the button isn't working. ### Cargo clamp * **Clamp code cleanup:** The cargo clamp now has a variable for the max creature weight it can support, and the logic is changed around a bit to support this. * The cargo clamp uses an `accepted_items` typecache. ### Code cleanup * **Button malfunction chance** is controlled by a `MOD_MALFUNCTION_PROB` define. * **Pathfinder runtime:** `mod_control`'s `GetAccess()` now checks if there is an access before returning it. (This previously caused runtimes when using the pathfinder module if you didn't swipe your ID) * **Pathfinder code tweaks:** Reworks the code for the pathfinder module a bit. Activation logic is now stored in the module instead of the implant. The suit is prevented from being recalled by pAIs, which is controlled by a variable. * Adds `MODULE_ALLOW_UNWORN`, which lets you activate modules in suits that aren't currently being worn. Module activation code now smoothly supports modules being activated while not worn. * Chameleon module now works when unworn. This will probably be a Part 1, with a Part 2 to follow. Actions are kinda funky and could probably be cleaned up a little better. Plus, I want to make selectable modules theoretically usable by the AI, even if I leave it disabled. ## Why It's Good For The Game This PR doesn't contain any balance changes, and I manually disabled any new serious functionality that pAIs might gain. (Such as being able to activate the pathfinder implant) They *can* use the chameleon module with no wearer- but I'm going to consider this a bug that they couldn't before. Paves the way for more pAI modsuit nonsense I'm doing downsteam. ## Changelog 🆑 Stonetear refactor: MODsuit module code now knows who clicked the activation button. /🆑 --------- Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com>
This commit is contained in:
@@ -171,8 +171,8 @@
|
||||
|
||||
///Mob the MOD is trying to attach to
|
||||
#define BB_MOD_TARGET "BB_mod_target"
|
||||
///The implant the AI was created from
|
||||
#define BB_MOD_IMPLANT "BB_mod_implant"
|
||||
///The module the AI was created from
|
||||
#define BB_MOD_MODULE "BB_mod_module"
|
||||
///Range for a MOD AI controller.
|
||||
#define MOD_AI_RANGE 200
|
||||
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
/// Default time for a part of the suit to seal.
|
||||
#define MOD_ACTIVATION_STEP_TIME (1 SECONDS)
|
||||
|
||||
/// How likely the UI is to fail when malfunctioning
|
||||
#define MOD_MALFUNCTION_PROB 75
|
||||
|
||||
/// Passive module, just acts when put in naturally.
|
||||
#define MODULE_PASSIVE 0
|
||||
/// Usable module, does something when you press a button.
|
||||
@@ -22,6 +25,8 @@
|
||||
#define MODULE_ALLOW_INCAPACITATED (1<<1)
|
||||
/// This module can be used while the suit is off
|
||||
#define MODULE_ALLOW_INACTIVE (1<<2)
|
||||
/// This module can be used (by button) while the suit is unworn
|
||||
#define MODULE_ALLOW_UNWORN (1<<3)
|
||||
|
||||
#define UNSEALED_LAYER "unsealed_layer"
|
||||
#define SEALED_LAYER "sealed_layer"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/// An AI controller for the MODsuit pathfinder module. It's activated by implant and attaches itself to the user.
|
||||
/// An AI controller for the MODsuit pathfinder module. It's activated by module and attaches itself to the user.
|
||||
/datum/ai_controller/mod
|
||||
blackboard = list(
|
||||
BB_MOD_TARGET,
|
||||
BB_MOD_IMPLANT,
|
||||
BB_MOD_MODULE,
|
||||
)
|
||||
can_idle = FALSE
|
||||
max_target_distance = MOD_AI_RANGE //a little spicy but its one specific item that summons it, and it doesn't run otherwise
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
/datum/ai_controller/mod/SelectBehaviors(seconds_per_tick)
|
||||
current_behaviors = list()
|
||||
if(blackboard[BB_MOD_TARGET] && blackboard[BB_MOD_IMPLANT])
|
||||
if(blackboard[BB_MOD_TARGET] && blackboard[BB_MOD_MODULE])
|
||||
queue_behavior(/datum/ai_behavior/mod_attach)
|
||||
|
||||
/datum/ai_controller/mod/get_access()
|
||||
@@ -37,12 +37,12 @@
|
||||
/datum/ai_behavior/mod_attach/perform(seconds_per_tick, datum/ai_controller/controller)
|
||||
if(!controller.pawn.Adjacent(controller.blackboard[BB_MOD_TARGET]))
|
||||
return AI_BEHAVIOR_DELAY
|
||||
var/obj/item/implant/mod/implant = controller.blackboard[BB_MOD_IMPLANT]
|
||||
implant.module.attach(controller.blackboard[BB_MOD_TARGET])
|
||||
var/obj/item/mod/module/pathfinder/module = controller.blackboard[BB_MOD_MODULE]
|
||||
module.attach(controller.blackboard[BB_MOD_TARGET])
|
||||
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED
|
||||
|
||||
/datum/ai_behavior/mod_attach/finish_action(datum/ai_controller/controller, succeeded)
|
||||
. = ..()
|
||||
controller.clear_blackboard_key(BB_MOD_TARGET)
|
||||
var/obj/item/implant/mod/implant = controller.blackboard[BB_MOD_IMPLANT]
|
||||
implant.end_recall(succeeded)
|
||||
var/obj/item/mod/module/pathfinder/module = controller.blackboard[BB_MOD_MODULE]
|
||||
module.end_recall(succeeded)
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
/datum/action/item_action/mod/do_effect(trigger_flags)
|
||||
var/obj/item/mod/control/mod = target
|
||||
if(mod.malfunctioning && prob(75))
|
||||
if(mod.malfunctioning && prob(MOD_MALFUNCTION_PROB))
|
||||
mod.balloon_alert(usr, "button malfunctions!")
|
||||
return FALSE
|
||||
return TRUE
|
||||
@@ -182,7 +182,7 @@
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
module.on_select()
|
||||
module.on_select(owner)
|
||||
|
||||
/datum/action/item_action/mod/pinnable/module/apply_button_overlay(atom/movable/screen/movable/action_button/current_button, force)
|
||||
current_button.cut_overlays()
|
||||
|
||||
@@ -378,7 +378,7 @@
|
||||
return cell
|
||||
|
||||
/obj/item/mod/control/GetAccess()
|
||||
if(ai_controller)
|
||||
if(ai_controller && req_access)
|
||||
return req_access.Copy()
|
||||
else
|
||||
return ..()
|
||||
|
||||
@@ -86,7 +86,7 @@
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
if(malfunctioning && prob(75))
|
||||
if(malfunctioning && prob(MOD_MALFUNCTION_PROB))
|
||||
balloon_alert(ui.user, "button malfunctions!")
|
||||
return
|
||||
switch(action)
|
||||
@@ -108,7 +108,7 @@
|
||||
var/obj/item/mod/module/module = locate(params["ref"]) in modules
|
||||
if(!module)
|
||||
return
|
||||
module.on_select()
|
||||
module.on_select(ui.user) // We can now
|
||||
if("configure")
|
||||
var/obj/item/mod/module/module = locate(params["ref"]) in modules
|
||||
if(!module)
|
||||
|
||||
@@ -105,32 +105,29 @@
|
||||
return TRUE
|
||||
|
||||
/// Called when the module is selected from the TGUI, radial or the action button
|
||||
/obj/item/mod/module/proc/on_select()
|
||||
if(!mod.wearer)
|
||||
if(ismob(mod.loc))
|
||||
balloon_alert(mod.loc, "not equipped!")
|
||||
/obj/item/mod/module/proc/on_select(mob/activator)
|
||||
if(!mod.wearer && !(allow_flags & MODULE_ALLOW_UNWORN)) //No wearer and cannot be used unworn
|
||||
balloon_alert(activator, "not equipped!")
|
||||
return
|
||||
if(((!mod.active || mod.activating) && !(allow_flags & MODULE_ALLOW_INACTIVE)) || module_type == MODULE_PASSIVE)
|
||||
if(mod.wearer)
|
||||
balloon_alert(mod.wearer, "not active!")
|
||||
if(((!mod.active || mod.activating) && !(allow_flags & (MODULE_ALLOW_INACTIVE | MODULE_ALLOW_UNWORN))) || module_type == MODULE_PASSIVE) // not active
|
||||
balloon_alert(activator, "not active!")
|
||||
return
|
||||
if(!has_required_parts(mod.mod_parts, need_active = TRUE))
|
||||
if(mod.wearer)
|
||||
balloon_alert(mod.wearer, "required parts inactive!")
|
||||
var/list/slot_strings = list()
|
||||
for(var/slot in required_slots)
|
||||
var/list/slot_list = parse_slot_flags(slot)
|
||||
slot_strings += (length(slot_list) == 1 ? "" : "one of ") + english_list(slot_list, and_text = " or ")
|
||||
to_chat(mod.wearer, span_warning("[src] requires these slots to be deployed: [english_list(slot_strings)]"))
|
||||
playsound(src, 'sound/machines/scanner/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE)
|
||||
if(!has_required_parts(mod.mod_parts, need_active = TRUE) && !(allow_flags & MODULE_ALLOW_UNWORN)) // Doesn't have parts
|
||||
balloon_alert(activator, "required parts inactive!")
|
||||
var/list/slot_strings = list()
|
||||
for(var/slot in required_slots)
|
||||
var/list/slot_list = parse_slot_flags(slot)
|
||||
slot_strings += (length(slot_list) == 1 ? "" : "one of ") + english_list(slot_list, and_text = " or ")
|
||||
to_chat(activator, span_warning("[src] requires these slots to be deployed: [english_list(slot_strings)]"))
|
||||
playsound(src, 'sound/machines/scanner/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE)
|
||||
return
|
||||
if(module_type != MODULE_USABLE)
|
||||
if(active)
|
||||
deactivate()
|
||||
deactivate(activator)
|
||||
else
|
||||
activate()
|
||||
activate(activator)
|
||||
else
|
||||
used()
|
||||
used(activator)
|
||||
SEND_SIGNAL(mod, COMSIG_MOD_MODULE_SELECTED, src)
|
||||
|
||||
/// Apply a cooldown until this item can be used again
|
||||
@@ -141,16 +138,16 @@
|
||||
SEND_SIGNAL(src, COMSIG_MODULE_COOLDOWN_STARTED, applied_cooldown)
|
||||
|
||||
/// Called when the module is activated
|
||||
/obj/item/mod/module/proc/activate()
|
||||
/obj/item/mod/module/proc/activate(mob/activator)
|
||||
if(!COOLDOWN_FINISHED(src, cooldown_timer))
|
||||
balloon_alert(mod.wearer, "on cooldown!")
|
||||
balloon_alert(activator, "on cooldown!")
|
||||
return FALSE
|
||||
if(!mod.active || mod.activating || !mod.get_charge())
|
||||
balloon_alert(mod.wearer, "unpowered!")
|
||||
balloon_alert(activator, "unpowered!")
|
||||
return FALSE
|
||||
if(!(allow_flags & MODULE_ALLOW_PHASEOUT) && istype(mod.wearer.loc, /obj/effect/dummy/phased_mob))
|
||||
//specifically a to_chat because the user is phased out.
|
||||
to_chat(mod.wearer, span_warning("You cannot activate this right now."))
|
||||
to_chat(activator, span_warning("You cannot activate this right now."))
|
||||
return FALSE
|
||||
if(SEND_SIGNAL(src, COMSIG_MODULE_TRIGGERED, mod.wearer) & MOD_ABORT_USE)
|
||||
return FALSE
|
||||
@@ -160,25 +157,25 @@
|
||||
mod.selected_module = src
|
||||
if(device)
|
||||
if(mod.wearer.put_in_hands(device))
|
||||
balloon_alert(mod.wearer, "[device] extended")
|
||||
balloon_alert(activator, "[device] extended")
|
||||
RegisterSignal(mod.wearer, COMSIG_ATOM_EXITED, PROC_REF(on_exit))
|
||||
RegisterSignal(mod.wearer, COMSIG_KB_MOB_DROPITEM_DOWN, PROC_REF(dropkey))
|
||||
else
|
||||
balloon_alert(mod.wearer, "can't extend [device]!")
|
||||
balloon_alert(activator, "can't extend [device]!")
|
||||
mod.wearer.transferItemToLoc(device, src, force = TRUE)
|
||||
return FALSE
|
||||
else
|
||||
var/used_button = mod.wearer.client?.prefs.read_preference(/datum/preference/choiced/mod_select) || MIDDLE_CLICK
|
||||
update_signal(used_button)
|
||||
balloon_alert(mod.wearer, "[src] activated, [used_button]-click to use")
|
||||
balloon_alert(mod.wearer, "[src] activated, [used_button]-click to use") // As of now, only wearers can "use" mods
|
||||
active = TRUE
|
||||
SEND_SIGNAL(src, COMSIG_MODULE_ACTIVATED)
|
||||
on_activation()
|
||||
on_activation(activator)
|
||||
update_clothing_slots()
|
||||
return TRUE
|
||||
|
||||
/// Called when the module is deactivated
|
||||
/obj/item/mod/module/proc/deactivate(display_message = TRUE, deleting = FALSE)
|
||||
/obj/item/mod/module/proc/deactivate(mob/activator, display_message = TRUE, deleting = FALSE)
|
||||
active = FALSE
|
||||
if(module_type == MODULE_ACTIVE)
|
||||
mod.selected_module = null
|
||||
@@ -192,12 +189,15 @@
|
||||
UnregisterSignal(mod.wearer, used_signal)
|
||||
used_signal = null
|
||||
SEND_SIGNAL(src, COMSIG_MODULE_DEACTIVATED, mod.wearer)
|
||||
on_deactivation(display_message = TRUE, deleting = FALSE)
|
||||
on_deactivation(activator, display_message = TRUE, deleting = FALSE)
|
||||
update_clothing_slots()
|
||||
return TRUE
|
||||
|
||||
/// Call to update all slots visually affected by this module
|
||||
/obj/item/mod/module/proc/update_clothing_slots()
|
||||
if(!mod.wearer)
|
||||
return
|
||||
|
||||
var/updated_slots = mod.slot_flags
|
||||
if (mask_worn_overlay)
|
||||
for (var/obj/item/part as anything in mod.get_parts())
|
||||
@@ -208,24 +208,25 @@
|
||||
mod.wearer.update_clothing(updated_slots)
|
||||
|
||||
/// Called when the module is used
|
||||
/obj/item/mod/module/proc/used()
|
||||
/obj/item/mod/module/proc/used(mob/activator)
|
||||
if(!COOLDOWN_FINISHED(src, cooldown_timer))
|
||||
balloon_alert(mod.wearer, "on cooldown!")
|
||||
balloon_alert(activator, "on cooldown!")
|
||||
return FALSE
|
||||
if(!check_power(use_energy_cost))
|
||||
balloon_alert(mod.wearer, "not enough charge!")
|
||||
balloon_alert(activator, "not enough charge!")
|
||||
return FALSE
|
||||
if(!(allow_flags & MODULE_ALLOW_PHASEOUT) && istype(mod.wearer.loc, /obj/effect/dummy/phased_mob))
|
||||
//specifically a to_chat because the user is phased out.
|
||||
to_chat(mod.wearer, span_warning("You cannot activate this right now."))
|
||||
to_chat(activator, span_warning("You cannot activate this right now."))
|
||||
return FALSE
|
||||
if(SEND_SIGNAL(src, COMSIG_MODULE_TRIGGERED, mod.wearer) & MOD_ABORT_USE)
|
||||
return FALSE
|
||||
start_cooldown()
|
||||
addtimer(CALLBACK(mod.wearer, TYPE_PROC_REF(/mob, update_clothing), mod.slot_flags), cooldown_time+1) //need to run it a bit after the cooldown starts to avoid conflicts
|
||||
if(mod.wearer)
|
||||
addtimer(CALLBACK(mod.wearer, TYPE_PROC_REF(/mob, update_clothing), mod.slot_flags), cooldown_time+1) //need to run it a bit after the cooldown starts to avoid conflicts
|
||||
update_clothing_slots()
|
||||
SEND_SIGNAL(src, COMSIG_MODULE_USED)
|
||||
on_use()
|
||||
on_use(activator)
|
||||
return TRUE
|
||||
|
||||
/// Called when an activated module without a device is used
|
||||
@@ -257,15 +258,15 @@
|
||||
return TRUE
|
||||
|
||||
/// Called from the module's activate()
|
||||
/obj/item/mod/module/proc/on_activation()
|
||||
/obj/item/mod/module/proc/on_activation(mob/activator)
|
||||
return
|
||||
|
||||
/// Called from the module's deactivate()
|
||||
/obj/item/mod/module/proc/on_deactivation(display_message = TRUE, deleting = FALSE)
|
||||
/obj/item/mod/module/proc/on_deactivation(mob/activator, display_message = TRUE, deleting = FALSE)
|
||||
return
|
||||
|
||||
/// Called from the module's used()
|
||||
/obj/item/mod/module/proc/on_use()
|
||||
/obj/item/mod/module/proc/on_use(mob/activator)
|
||||
return
|
||||
|
||||
/// Called on the MODsuit's process if it is an active module
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
drain_power(use_energy_cost)
|
||||
grab_atom(target)
|
||||
|
||||
/obj/item/mod/module/anomaly_locked/kinesis/on_deactivation(display_message = TRUE, deleting = FALSE)
|
||||
/obj/item/mod/module/anomaly_locked/kinesis/on_deactivation(mob/activator, display_message = TRUE, deleting = FALSE)
|
||||
clear_grab(playsound = !deleting)
|
||||
|
||||
/obj/item/mod/module/anomaly_locked/kinesis/process(seconds_per_tick)
|
||||
|
||||
@@ -15,12 +15,22 @@
|
||||
use_energy_cost = DEFAULT_CHARGE_DRAIN * 10
|
||||
incompatible_modules = list(/obj/item/mod/module/pathfinder)
|
||||
required_slots = list(ITEM_SLOT_BACK|ITEM_SLOT_BELT)
|
||||
allow_flags = list(MODULE_ALLOW_INACTIVE|MODULE_ALLOW_UNWORN)
|
||||
/// The pathfinding implant.
|
||||
var/obj/item/implant/mod/implant
|
||||
/// Whether the implant has been used or not
|
||||
var/implant_inside = TRUE
|
||||
/// The jet icon we apply to the MOD.
|
||||
var/image/jet_icon
|
||||
/// Allow suit activation - Lets this module be recalled from the MOD.
|
||||
var/allow_suit_activation = FALSE // I'm not here to argue about balance
|
||||
|
||||
|
||||
/obj/item/mod/module/pathfinder/Initialize(mapload)
|
||||
. = ..()
|
||||
implant = new(src)
|
||||
jet_icon = image(icon = 'icons/obj/clothing/modsuit/mod_modules.dmi', icon_state = "mod_jet", layer = LOW_ITEM_LAYER)
|
||||
|
||||
|
||||
/obj/item/mod/module/pathfinder/Destroy()
|
||||
QDEL_NULL(implant)
|
||||
@@ -28,28 +38,28 @@
|
||||
|
||||
/obj/item/mod/module/pathfinder/Exited(atom/movable/gone, direction)
|
||||
if(gone == implant)
|
||||
implant = null
|
||||
implant_inside = FALSE
|
||||
update_icon_state()
|
||||
return ..()
|
||||
|
||||
/obj/item/mod/module/pathfinder/update_icon_state()
|
||||
. = ..()
|
||||
icon_state = implant ? "pathfinder" : "pathfinder_empty"
|
||||
icon_state = implant_inside ? "pathfinder" : "pathfinder_empty"
|
||||
|
||||
/obj/item/mod/module/pathfinder/examine(mob/user)
|
||||
. = ..()
|
||||
if(implant)
|
||||
if(implant_inside)
|
||||
. += span_notice("Use it on a human to implant them.")
|
||||
else
|
||||
. += span_warning("The implant is missing.")
|
||||
|
||||
/obj/item/mod/module/pathfinder/attack(mob/living/target, mob/living/user, list/modifiers, list/attack_modifiers)
|
||||
if(!ishuman(target) || !implant)
|
||||
if(!ishuman(target) || !implant_inside) // Not human, or no implant in module
|
||||
return
|
||||
if(!do_after(user, 1.5 SECONDS, target = target))
|
||||
balloon_alert(user, "interrupted!")
|
||||
return
|
||||
if(!implant.implant(target, user))
|
||||
if(!implant.implant(target, user)) // If implant fails
|
||||
balloon_alert(user, "can't implant!")
|
||||
return
|
||||
if(target == user)
|
||||
@@ -57,21 +67,29 @@
|
||||
else
|
||||
target.visible_message(span_notice("[user] implants [target]."), span_notice("[user] implants you with [implant]."))
|
||||
playsound(src, 'sound/effects/spray.ogg', 30, TRUE, -6)
|
||||
module_type = MODULE_PASSIVE
|
||||
|
||||
/obj/item/mod/module/pathfinder/on_use()
|
||||
/obj/item/mod/module/pathfinder/on_use(mob/activator)
|
||||
. = ..()
|
||||
if (!ishuman(mod.wearer) || !implant)
|
||||
if(mod.wearer && implant_inside) // implant them
|
||||
try_implant(activator)
|
||||
return
|
||||
if(mod.wearer)
|
||||
balloon_alert(activator, "suit already worn!")
|
||||
else
|
||||
recall(activator)
|
||||
|
||||
|
||||
/// Assuming we have a wearer, attempt to implant them.
|
||||
/obj/item/mod/module/pathfinder/proc/try_implant(mob/activator)
|
||||
if(!ishuman(mod.wearer)) // Wearer isn't human
|
||||
return
|
||||
if(!implant.implant(mod.wearer, mod.wearer))
|
||||
balloon_alert(mod.wearer, "can't implant!")
|
||||
balloon_alert(activator, "can't implant!")
|
||||
return
|
||||
balloon_alert(mod.wearer, "implanted")
|
||||
balloon_alert(activator, "implanted")
|
||||
if(!(activator == mod.wearer)) // someone else implanted you
|
||||
balloon_alert(mod.wearer, "pathfinder MOD tracker implanted!")
|
||||
playsound(src, 'sound/effects/spray.ogg', 30, TRUE, -6)
|
||||
module_type = MODULE_PASSIVE
|
||||
var/datum/action/item_action/mod/pinnable/module/existing_action = pinned_to[REF(mod.wearer)]
|
||||
if(existing_action)
|
||||
mod.remove_item_action(existing_action)
|
||||
|
||||
/obj/item/mod/module/pathfinder/proc/attach(mob/living/user)
|
||||
if(!ishuman(user))
|
||||
@@ -87,27 +105,86 @@
|
||||
playsound(mod, 'sound/machines/ping.ogg', 50, TRUE)
|
||||
drain_power(use_energy_cost)
|
||||
|
||||
/obj/item/mod/module/pathfinder/proc/recall(mob/recaller)
|
||||
if(!implant)
|
||||
balloon_alert(recaller, "no target implant!")
|
||||
return FALSE
|
||||
if(recaller != implant.imp_in && !allow_suit_activation) // No pAI recalling
|
||||
balloon_alert(recaller, "sector safety regulations prevent MOD-side recalling!")
|
||||
return FALSE
|
||||
if(mod.open)
|
||||
balloon_alert(recaller, "cover open!")
|
||||
return FALSE
|
||||
if(mod.ai_controller)
|
||||
balloon_alert(recaller, "already moving!")
|
||||
return FALSE
|
||||
if(ismob(get_atom_on_turf(mod)))
|
||||
balloon_alert(recaller, "already on someone!")
|
||||
return FALSE
|
||||
if(mod.z != implant.imp_in.z || get_dist(implant.imp_in, mod) > MOD_AI_RANGE)
|
||||
balloon_alert(recaller, "too far!")
|
||||
return FALSE
|
||||
var/datum/ai_controller/mod_ai = new /datum/ai_controller/mod(mod)
|
||||
mod.ai_controller = mod_ai
|
||||
mod_ai.set_movement_target(type, implant.imp_in)
|
||||
mod_ai.set_blackboard_key(BB_MOD_TARGET, implant.imp_in)
|
||||
mod_ai.set_blackboard_key(BB_MOD_MODULE, src)
|
||||
mod.interaction_flags_item &= ~INTERACT_ITEM_ATTACK_HAND_PICKUP
|
||||
mod.AddElement(/datum/element/movetype_handler)
|
||||
ADD_TRAIT(mod, TRAIT_MOVE_FLYING, MOD_TRAIT)
|
||||
animate(mod, 0.2 SECONDS, pixel_x = base_pixel_y, pixel_y = base_pixel_y)
|
||||
mod.add_overlay(jet_icon)
|
||||
RegisterSignal(mod, COMSIG_MOVABLE_MOVED, PROC_REF(on_move))
|
||||
balloon_alert(recaller, "suit recalled")
|
||||
if(!(recaller == mod.wearer))
|
||||
balloon_alert(mod.wearer, "suit recalled")
|
||||
return TRUE
|
||||
|
||||
/obj/item/mod/module/pathfinder/proc/on_move(atom/movable/source, atom/old_loc, dir, forced)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
var/matrix/mod_matrix = matrix()
|
||||
mod_matrix.Turn(get_angle(source, implant.imp_in))
|
||||
source.transform = mod_matrix
|
||||
|
||||
/obj/item/mod/module/pathfinder/proc/end_recall(successful = TRUE)
|
||||
if(!mod)
|
||||
return
|
||||
QDEL_NULL(mod.ai_controller)
|
||||
mod.interaction_flags_item |= INTERACT_ITEM_ATTACK_HAND_PICKUP
|
||||
REMOVE_TRAIT(mod, TRAIT_MOVE_FLYING, MOD_TRAIT)
|
||||
mod.RemoveElement(/datum/element/movetype_handler)
|
||||
mod.cut_overlay(jet_icon)
|
||||
mod.transform = matrix()
|
||||
UnregisterSignal(mod, COMSIG_MOVABLE_MOVED)
|
||||
if(!successful)
|
||||
balloon_alert(implant.imp_in, "suit lost connection!")
|
||||
|
||||
// ###########
|
||||
// THE INPLANT
|
||||
// ###########
|
||||
|
||||
|
||||
/obj/item/implant/mod
|
||||
name = "MOD pathfinder implant"
|
||||
desc = "Lets you recall a MODsuit to you at any time."
|
||||
actions_types = list(/datum/action/item_action/mod_recall)
|
||||
allow_multiple = TRUE // Surgrey is annoying if you loose your MOD
|
||||
/// The pathfinder module we are linked to.
|
||||
var/obj/item/mod/module/pathfinder/module
|
||||
/// The jet icon we apply to the MOD.
|
||||
var/image/jet_icon
|
||||
|
||||
|
||||
|
||||
/obj/item/implant/mod/Initialize(mapload)
|
||||
. = ..()
|
||||
if(!istype(loc, /obj/item/mod/module/pathfinder))
|
||||
return INITIALIZE_HINT_QDEL
|
||||
module = loc
|
||||
jet_icon = image(icon = 'icons/obj/clothing/modsuit/mod_modules.dmi', icon_state = "mod_jet", layer = LOW_ITEM_LAYER)
|
||||
|
||||
/obj/item/implant/mod/Destroy()
|
||||
if(module?.mod?.ai_controller)
|
||||
end_recall(successful = FALSE)
|
||||
module.end_recall(successful = FALSE)
|
||||
module = null
|
||||
jet_icon = null
|
||||
return ..()
|
||||
|
||||
/obj/item/implant/mod/get_data()
|
||||
@@ -115,55 +192,6 @@
|
||||
<b>Name:</b> Nakamura Engineering Pathfinder Implant<BR> \
|
||||
<b>Implant Details:</b> Allows for the recall of a Modular Outerwear Device by the implant owner at any time.<BR>"
|
||||
|
||||
/obj/item/implant/mod/proc/recall()
|
||||
if(!module?.mod)
|
||||
balloon_alert(imp_in, "no connected unit!")
|
||||
return FALSE
|
||||
if(module.mod.open)
|
||||
balloon_alert(imp_in, "cover open!")
|
||||
return FALSE
|
||||
if(module.mod.ai_controller)
|
||||
balloon_alert(imp_in, "already moving!")
|
||||
return FALSE
|
||||
if(ismob(get_atom_on_turf(module.mod)))
|
||||
balloon_alert(imp_in, "already on someone!")
|
||||
return FALSE
|
||||
if(module.z != z || get_dist(imp_in, module.mod) > MOD_AI_RANGE)
|
||||
balloon_alert(imp_in, "too far!")
|
||||
return FALSE
|
||||
var/datum/ai_controller/mod_ai = new /datum/ai_controller/mod(module.mod)
|
||||
module.mod.ai_controller = mod_ai
|
||||
mod_ai.set_movement_target(type, imp_in)
|
||||
mod_ai.set_blackboard_key(BB_MOD_TARGET, imp_in)
|
||||
mod_ai.set_blackboard_key(BB_MOD_IMPLANT, src)
|
||||
module.mod.interaction_flags_item &= ~INTERACT_ITEM_ATTACK_HAND_PICKUP
|
||||
module.mod.AddElement(/datum/element/movetype_handler)
|
||||
ADD_TRAIT(module.mod, TRAIT_MOVE_FLYING, MOD_TRAIT)
|
||||
animate(module.mod, 0.2 SECONDS, pixel_x = base_pixel_y, pixel_y = base_pixel_y)
|
||||
module.mod.add_overlay(jet_icon)
|
||||
RegisterSignal(module.mod, COMSIG_MOVABLE_MOVED, PROC_REF(on_move))
|
||||
balloon_alert(imp_in, "suit recalled")
|
||||
return TRUE
|
||||
|
||||
/obj/item/implant/mod/proc/end_recall(successful = TRUE)
|
||||
if(!module?.mod)
|
||||
return
|
||||
QDEL_NULL(module.mod.ai_controller)
|
||||
module.mod.interaction_flags_item |= INTERACT_ITEM_ATTACK_HAND_PICKUP
|
||||
REMOVE_TRAIT(module.mod, TRAIT_MOVE_FLYING, MOD_TRAIT)
|
||||
module.mod.RemoveElement(/datum/element/movetype_handler)
|
||||
module.mod.cut_overlay(jet_icon)
|
||||
module.mod.transform = matrix()
|
||||
UnregisterSignal(module.mod, COMSIG_MOVABLE_MOVED)
|
||||
if(!successful)
|
||||
balloon_alert(imp_in, "suit lost connection!")
|
||||
|
||||
/obj/item/implant/mod/proc/on_move(atom/movable/source, atom/old_loc, dir, forced)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
var/matrix/mod_matrix = matrix()
|
||||
mod_matrix.Turn(get_angle(source, imp_in))
|
||||
source.transform = mod_matrix
|
||||
|
||||
/datum/action/item_action/mod_recall
|
||||
name = "Recall MOD"
|
||||
@@ -185,7 +213,7 @@
|
||||
/datum/action/item_action/mod_recall/do_effect(trigger_flags)
|
||||
var/obj/item/implant/mod/implant = target
|
||||
if(!COOLDOWN_FINISHED(src, recall_cooldown))
|
||||
implant.balloon_alert(implant.imp_in, "on cooldown!")
|
||||
implant.balloon_alert(owner, "on cooldown!")
|
||||
return
|
||||
if(implant.recall())
|
||||
if(implant.module.recall(owner)) // change this
|
||||
COOLDOWN_START(src, recall_cooldown, 15 SECONDS)
|
||||
|
||||
@@ -292,7 +292,7 @@
|
||||
complexity = 2
|
||||
incompatible_modules = list(/obj/item/mod/module/chameleon)
|
||||
cooldown_time = 0.5 SECONDS
|
||||
allow_flags = MODULE_ALLOW_INACTIVE
|
||||
allow_flags = list(MODULE_ALLOW_INACTIVE|MODULE_ALLOW_UNWORN)
|
||||
/// A list of all the items the suit can disguise as.
|
||||
var/list/possible_disguises = list()
|
||||
/// The path of the item we're disguised as.
|
||||
@@ -314,17 +314,17 @@
|
||||
return_look()
|
||||
possible_disguises = null
|
||||
|
||||
/obj/item/mod/module/chameleon/used()
|
||||
/obj/item/mod/module/chameleon/used(mob/activator)
|
||||
if(mod.active || mod.activating)
|
||||
balloon_alert(mod.wearer, "unit active!")
|
||||
balloon_alert(activator, "unit active!")
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/obj/item/mod/module/chameleon/on_use()
|
||||
/obj/item/mod/module/chameleon/on_use(mob/activator)
|
||||
if(current_disguise)
|
||||
return_look()
|
||||
return
|
||||
var/picked_name = tgui_input_list(mod.wearer, "Select look to change into", "Chameleon Settings", possible_disguises)
|
||||
var/picked_name = tgui_input_list(activator, "Select look to change into", "Chameleon Settings", possible_disguises)
|
||||
if(!possible_disguises[picked_name] || mod.active || mod.activating)
|
||||
return
|
||||
current_disguise = possible_disguises[picked_name]
|
||||
@@ -506,10 +506,10 @@
|
||||
if(disrupted.on_saboteur(src, 1 MINUTES))
|
||||
mod.add_charge(DEFAULT_CHARGE_DRAIN * 250)
|
||||
|
||||
/obj/item/mod/module/stealth/wraith/on_activation()
|
||||
/obj/item/mod/module/stealth/wraith/on_activation(mob/activator)
|
||||
return // Don't activate stealth when the module is activated because the stealth portion of the module is fully passive
|
||||
|
||||
/obj/item/mod/module/stealth/wraith/on_deactivation(display_message = TRUE, deleting = FALSE)
|
||||
/obj/item/mod/module/stealth/wraith/on_deactivation(mob/activator, display_message = TRUE, deleting = FALSE)
|
||||
. = ..()
|
||||
UnregisterSignal(mod.wearer, list(COMSIG_LIVING_MOB_BUMP, COMSIG_ATOM_BUMPED, COMSIG_MOB_FIRED_GUN))
|
||||
|
||||
|
||||
@@ -81,11 +81,11 @@
|
||||
. = ..()
|
||||
UnregisterSignal(mod, COMSIG_MOD_UPDATE_SPEED)
|
||||
|
||||
/obj/item/mod/module/magboot/on_activation()
|
||||
/obj/item/mod/module/magboot/on_activation(mob/activator)
|
||||
mod.wearer.add_traits(active_traits, REF(src))
|
||||
mod.update_speed()
|
||||
|
||||
/obj/item/mod/module/magboot/on_deactivation(display_message = TRUE, deleting = FALSE)
|
||||
/obj/item/mod/module/magboot/on_deactivation(mob/activator, display_message = TRUE, deleting = FALSE)
|
||||
mod.wearer.remove_traits(active_traits, REF(src))
|
||||
mod.update_speed()
|
||||
|
||||
@@ -140,7 +140,7 @@
|
||||
if (key == "cut_tethers")
|
||||
SEND_SIGNAL(src, COMSIG_MOD_TETHER_SNAP)
|
||||
|
||||
/obj/item/mod/module/tether/on_deactivation(display_message, deleting)
|
||||
/obj/item/mod/module/tether/on_deactivation(mob/activator, display_message = TRUE, deleting = FALSE)
|
||||
SEND_SIGNAL(src, COMSIG_MOD_TETHER_SNAP)
|
||||
|
||||
/obj/projectile/tether
|
||||
@@ -394,7 +394,7 @@
|
||||
/obj/item/mod/module/constructor/on_part_deactivation(deleting = FALSE)
|
||||
REMOVE_TRAIT(mod.wearer, TRAIT_QUICK_BUILD, REF(src))
|
||||
|
||||
/obj/item/mod/module/constructor/on_use()
|
||||
/obj/item/mod/module/constructor/on_use(mob/activator)
|
||||
rcd_scan(src, fade_time = 10 SECONDS)
|
||||
drain_power(use_energy_cost)
|
||||
|
||||
|
||||
@@ -171,12 +171,12 @@
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/item/mod/module/jetpack/on_activation()
|
||||
/obj/item/mod/module/jetpack/on_activation(mob/activator)
|
||||
mod.wearer.add_movespeed_modifier(/datum/movespeed_modifier/jetpack/full_speed)
|
||||
if (!stabilize)
|
||||
ADD_TRAIT(mod.wearer, TRAIT_NOGRAV_ALWAYS_DRIFT, REF(src))
|
||||
|
||||
/obj/item/mod/module/jetpack/on_deactivation(display_message = TRUE, deleting = FALSE)
|
||||
/obj/item/mod/module/jetpack/on_deactivation(mob/activator, display_message = TRUE, deleting = FALSE)
|
||||
mod.wearer.remove_movespeed_modifier(/datum/movespeed_modifier/jetpack/full_speed)
|
||||
REMOVE_TRAIT(mod.wearer, TRAIT_NOGRAV_ALWAYS_DRIFT, REF(src))
|
||||
|
||||
@@ -206,9 +206,9 @@
|
||||
incompatible_modules = list(/obj/item/mod/module/jump_jet)
|
||||
required_slots = list(ITEM_SLOT_BACK)
|
||||
|
||||
/obj/item/mod/module/jump_jet/on_use()
|
||||
/obj/item/mod/module/jump_jet/on_use(mob/activator)
|
||||
if (DOING_INTERACTION(mod.wearer, mod.wearer))
|
||||
balloon_alert(mod.wearer, "busy!")
|
||||
balloon_alert(activator, "busy!")
|
||||
return
|
||||
balloon_alert(mod.wearer, "launching...")
|
||||
mod.wearer.Shake(duration = 1 SECONDS)
|
||||
@@ -438,12 +438,12 @@
|
||||
/// Maximum range we can set.
|
||||
var/max_range = 5
|
||||
|
||||
/obj/item/mod/module/flashlight/on_activation()
|
||||
/obj/item/mod/module/flashlight/on_activation(mob/activator)
|
||||
set_light_flags(light_flags | LIGHT_ATTACHED)
|
||||
set_light_on(active)
|
||||
active_power_cost = base_power * light_range
|
||||
|
||||
/obj/item/mod/module/flashlight/on_deactivation(display_message = TRUE, deleting = FALSE)
|
||||
/obj/item/mod/module/flashlight/on_deactivation(mob/activator, display_message = TRUE, deleting = FALSE)
|
||||
set_light_flags(light_flags & ~LIGHT_ATTACHED)
|
||||
set_light_on(active)
|
||||
|
||||
@@ -518,13 +518,13 @@
|
||||
/// Time it takes for us to dispense.
|
||||
var/dispense_time = 0 SECONDS
|
||||
|
||||
/obj/item/mod/module/dispenser/on_use()
|
||||
/obj/item/mod/module/dispenser/on_use(mob/activator)
|
||||
if(dispense_time && !do_after(mod.wearer, dispense_time, target = mod))
|
||||
balloon_alert(mod.wearer, "interrupted!")
|
||||
return FALSE
|
||||
var/obj/item/dispensed = new dispense_type(mod.wearer.loc)
|
||||
mod.wearer.put_in_hands(dispensed)
|
||||
balloon_alert(mod.wearer, "[dispensed] dispensed")
|
||||
balloon_alert(activator, "[dispensed] dispensed")
|
||||
playsound(src, 'sound/machines/click.ogg', 100, TRUE)
|
||||
drain_power(use_energy_cost)
|
||||
return dispensed
|
||||
@@ -627,9 +627,9 @@
|
||||
UnregisterSignal(mod, COMSIG_ATOM_EMP_ACT)
|
||||
UnregisterSignal(mod, COMSIG_ATOM_EMAG_ACT)
|
||||
|
||||
/obj/item/mod/module/dna_lock/on_use()
|
||||
/obj/item/mod/module/dna_lock/on_use(mob/activator)
|
||||
dna = mod.wearer.dna.unique_enzymes
|
||||
balloon_alert(mod.wearer, "dna updated")
|
||||
balloon_alert(activator, "dna updated")
|
||||
drain_power(use_energy_cost)
|
||||
|
||||
/obj/item/mod/module/dna_lock/emp_act(severity)
|
||||
@@ -855,11 +855,11 @@
|
||||
container = null
|
||||
return ..()
|
||||
|
||||
/obj/item/mod/module/recycler/on_activation()
|
||||
/obj/item/mod/module/recycler/on_activation(mob/activator)
|
||||
connector = AddComponent(/datum/component/connect_loc_behalf, mod.wearer, loc_connections)
|
||||
RegisterSignal(mod.wearer, COMSIG_MOVABLE_MOVED, PROC_REF(on_wearer_moved))
|
||||
|
||||
/obj/item/mod/module/recycler/on_deactivation(display_message, deleting = FALSE)
|
||||
/obj/item/mod/module/recycler/on_deactivation(mob/activator, display_message, deleting = FALSE)
|
||||
QDEL_NULL(connector)
|
||||
UnregisterSignal(mod.wearer, COMSIG_MOVABLE_MOVED, PROC_REF(on_wearer_moved))
|
||||
|
||||
|
||||
@@ -136,12 +136,12 @@
|
||||
QDEL_NULL(rave_screen)
|
||||
return ..()
|
||||
|
||||
/obj/item/mod/module/visor/rave/on_activation()
|
||||
/obj/item/mod/module/visor/rave/on_activation(mob/activator)
|
||||
rave_screen = mod.wearer.add_client_colour(/datum/client_colour/rave, REF(src))
|
||||
rave_screen.update_color(rainbow_order[rave_number])
|
||||
music_player.start_music(mod.wearer)
|
||||
|
||||
/obj/item/mod/module/visor/rave/on_deactivation(display_message = TRUE, deleting = FALSE)
|
||||
/obj/item/mod/module/visor/rave/on_deactivation(mob/activator, display_message = TRUE, deleting = FALSE)
|
||||
QDEL_NULL(rave_screen)
|
||||
if(isnull(music_player.active_song_sound))
|
||||
return
|
||||
@@ -199,7 +199,7 @@
|
||||
cooldown_time = 30 SECONDS
|
||||
required_slots = list(ITEM_SLOT_OCLOTHING|ITEM_SLOT_ICLOTHING)
|
||||
|
||||
/obj/item/mod/module/tanner/on_use()
|
||||
/obj/item/mod/module/tanner/on_use(mob/activator)
|
||||
playsound(src, 'sound/machines/microwave/microwave-end.ogg', 50, TRUE)
|
||||
var/datum/reagents/holder = new()
|
||||
holder.add_reagent(/datum/reagent/spraytan, 10)
|
||||
@@ -223,7 +223,7 @@
|
||||
var/blowing_time = 10 SECONDS
|
||||
var/oxygen_damage = 20
|
||||
|
||||
/obj/item/mod/module/balloon/on_use()
|
||||
/obj/item/mod/module/balloon/on_use(mob/activator)
|
||||
if(!do_after(mod.wearer, blowing_time, target = mod))
|
||||
return FALSE
|
||||
mod.wearer.adjustOxyLoss(oxygen_damage)
|
||||
@@ -247,7 +247,7 @@
|
||||
/// The total number of sheets created by this MOD. The more sheets, them more likely they set on fire.
|
||||
var/num_sheets_dispensed = 0
|
||||
|
||||
/obj/item/mod/module/paper_dispenser/on_use()
|
||||
/obj/item/mod/module/paper_dispenser/on_use(mob/activator)
|
||||
if(!do_after(mod.wearer, 1 SECONDS, target = mod))
|
||||
return FALSE
|
||||
|
||||
@@ -316,7 +316,7 @@
|
||||
/// If you use the module on a planetary turf, you fly up. To the sky.
|
||||
var/you_fucked_up = FALSE
|
||||
|
||||
/obj/item/mod/module/atrocinator/on_activation()
|
||||
/obj/item/mod/module/atrocinator/on_activation(mob/activator)
|
||||
playsound(src, 'sound/effects/curse/curseattack.ogg', 50)
|
||||
mod.wearer.AddElement(/datum/element/forced_gravity, NEGATIVE_GRAVITY)
|
||||
RegisterSignal(mod.wearer, COMSIG_MOVABLE_MOVED, PROC_REF(check_upstairs))
|
||||
@@ -325,13 +325,13 @@
|
||||
passtable_on(mod.wearer, REF(src))
|
||||
check_upstairs() //todo at some point flip your screen around
|
||||
|
||||
/obj/item/mod/module/atrocinator/deactivate(display_message = TRUE, deleting = FALSE)
|
||||
/obj/item/mod/module/atrocinator/deactivate(mob/activator, display_message = TRUE, deleting = FALSE)
|
||||
if(you_fucked_up && !deleting)
|
||||
to_chat(mod.wearer, span_danger("It's too late."))
|
||||
to_chat(activator, span_danger("It's too late."))
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/obj/item/mod/module/atrocinator/on_deactivation(display_message = TRUE, deleting = FALSE)
|
||||
/obj/item/mod/module/atrocinator/on_deactivation(mob/activator, display_message = TRUE, deleting = FALSE)
|
||||
if(!deleting)
|
||||
playsound(src, 'sound/effects/curse/curseattack.ogg', 50)
|
||||
qdel(mod.wearer.RemoveElement(/datum/element/forced_gravity, NEGATIVE_GRAVITY))
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
/// The alpha applied when the cloak is on.
|
||||
var/stealth_alpha = 50
|
||||
|
||||
/obj/item/mod/module/stealth/on_activation()
|
||||
/obj/item/mod/module/stealth/on_activation(mob/activator)
|
||||
if(bumpoff)
|
||||
RegisterSignal(mod.wearer, COMSIG_LIVING_MOB_BUMP, PROC_REF(unstealth))
|
||||
RegisterSignal(mod.wearer, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(on_unarmed_attack))
|
||||
@@ -28,7 +28,7 @@
|
||||
animate(mod.wearer, alpha = stealth_alpha, time = 1.5 SECONDS)
|
||||
drain_power(use_energy_cost)
|
||||
|
||||
/obj/item/mod/module/stealth/on_deactivation(display_message = TRUE, deleting = FALSE)
|
||||
/obj/item/mod/module/stealth/on_deactivation(mob/activator, display_message = TRUE, deleting = FALSE)
|
||||
if(bumpoff)
|
||||
UnregisterSignal(mod.wearer, COMSIG_LIVING_MOB_BUMP)
|
||||
UnregisterSignal(mod.wearer, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_MOB_ITEM_ATTACK, COMSIG_ATOM_ATTACKBY, COMSIG_ATOM_ATTACK_HAND, COMSIG_ATOM_BULLET_ACT, COMSIG_ATOM_HITBY, COMSIG_ATOM_HULK_ATTACK, COMSIG_ATOM_ATTACK_PAW, COMSIG_CARBON_CUFF_ATTEMPTED))
|
||||
@@ -72,11 +72,11 @@
|
||||
cooldown_time = 3 SECONDS
|
||||
|
||||
|
||||
/obj/item/mod/module/stealth/ninja/on_activation()
|
||||
/obj/item/mod/module/stealth/ninja/on_activation(mob/activator)
|
||||
. = ..()
|
||||
ADD_TRAIT(mod.wearer, TRAIT_SILENT_FOOTSTEPS, REF(src))
|
||||
|
||||
/obj/item/mod/module/stealth/ninja/on_deactivation(display_message = TRUE, deleting = FALSE)
|
||||
/obj/item/mod/module/stealth/ninja/on_deactivation(mob/activator, display_message = TRUE, deleting = FALSE)
|
||||
. = ..()
|
||||
REMOVE_TRAIT(mod.wearer, TRAIT_SILENT_FOOTSTEPS, REF(src))
|
||||
|
||||
@@ -287,7 +287,7 @@
|
||||
use_energy_cost = DEFAULT_CHARGE_DRAIN * 10
|
||||
cooldown_time = 8 SECONDS
|
||||
|
||||
/obj/item/mod/module/emp_shield/pulse/on_use()
|
||||
/obj/item/mod/module/emp_shield/pulse/on_use(mob/activator)
|
||||
playsound(src, 'sound/effects/empulse.ogg', 60, TRUE)
|
||||
empulse(src, heavy_range = 4, light_range = 6)
|
||||
drain_power(use_energy_cost)
|
||||
@@ -420,7 +420,7 @@
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/obj/item/mod/module/adrenaline_boost/on_use()
|
||||
/obj/item/mod/module/adrenaline_boost/on_use(mob/activator)
|
||||
if(IS_SPACE_NINJA(mod.wearer))
|
||||
mod.wearer.say(pick_list_replacements(NINJA_FILE, "lines"), forced = type)
|
||||
to_chat(mod.wearer, span_notice("You have used the adrenaline boost."))
|
||||
|
||||
@@ -13,10 +13,10 @@
|
||||
incompatible_modules = list(/obj/item/mod/module/reagent_scanner)
|
||||
required_slots = list(ITEM_SLOT_HEAD|ITEM_SLOT_EYES|ITEM_SLOT_MASK)
|
||||
|
||||
/obj/item/mod/module/reagent_scanner/on_activation()
|
||||
/obj/item/mod/module/reagent_scanner/on_activation(mob/activator)
|
||||
ADD_TRAIT(mod.wearer, TRAIT_REAGENT_SCANNER, REF(src))
|
||||
|
||||
/obj/item/mod/module/reagent_scanner/on_deactivation(display_message = TRUE, deleting = FALSE)
|
||||
/obj/item/mod/module/reagent_scanner/on_deactivation(mob/activator, display_message = TRUE, deleting = FALSE)
|
||||
REMOVE_TRAIT(mod.wearer, TRAIT_REAGENT_SCANNER, REF(src))
|
||||
|
||||
/obj/item/mod/module/reagent_scanner/advanced
|
||||
@@ -29,12 +29,12 @@
|
||||
removable = FALSE
|
||||
var/explosion_detection_dist = 21
|
||||
|
||||
/obj/item/mod/module/reagent_scanner/advanced/on_activation()
|
||||
/obj/item/mod/module/reagent_scanner/advanced/on_activation(mob/activator)
|
||||
. = ..()
|
||||
ADD_TRAIT(mod.wearer, TRAIT_RESEARCH_SCANNER, REF(src))
|
||||
RegisterSignal(SSdcs, COMSIG_GLOB_EXPLOSION, PROC_REF(sense_explosion))
|
||||
|
||||
/obj/item/mod/module/reagent_scanner/advanced/on_deactivation(display_message = TRUE, deleting = FALSE)
|
||||
/obj/item/mod/module/reagent_scanner/advanced/on_deactivation(mob/activator, display_message = TRUE, deleting = FALSE)
|
||||
. = ..()
|
||||
REMOVE_TRAIT(mod.wearer, TRAIT_RESEARCH_SCANNER, REF(src))
|
||||
UnregisterSignal(SSdcs, COMSIG_GLOB_EXPLOSION)
|
||||
@@ -61,13 +61,13 @@
|
||||
accepted_anomalies = list(/obj/item/assembly/signaler/anomaly/grav)
|
||||
required_slots = list(ITEM_SLOT_BACK|ITEM_SLOT_BELT)
|
||||
|
||||
/obj/item/mod/module/anomaly_locked/antigrav/on_activation()
|
||||
/obj/item/mod/module/anomaly_locked/antigrav/on_activation(mob/activator)
|
||||
if(mod.wearer.has_gravity())
|
||||
new /obj/effect/temp_visual/mook_dust(get_turf(src))
|
||||
mod.wearer.AddElement(/datum/element/forced_gravity, 0)
|
||||
playsound(src, 'sound/effects/gravhit.ogg', 50)
|
||||
|
||||
/obj/item/mod/module/anomaly_locked/antigrav/on_deactivation(display_message = TRUE, deleting = FALSE)
|
||||
/obj/item/mod/module/anomaly_locked/antigrav/on_deactivation(mob/activator, display_message = TRUE, deleting = FALSE)
|
||||
mod.wearer.RemoveElement(/datum/element/forced_gravity, 0)
|
||||
if(deleting)
|
||||
return
|
||||
|
||||
@@ -82,7 +82,7 @@
|
||||
/obj/item/mod/module/pepper_shoulders/on_part_deactivation(deleting = FALSE)
|
||||
UnregisterSignal(mod.wearer, COMSIG_LIVING_CHECK_BLOCK)
|
||||
|
||||
/obj/item/mod/module/pepper_shoulders/on_use()
|
||||
/obj/item/mod/module/pepper_shoulders/on_use(mob/activator)
|
||||
playsound(src, 'sound/effects/spray.ogg', 30, TRUE, -6)
|
||||
var/datum/reagents/capsaicin_holder = new(10)
|
||||
capsaicin_holder.add_reagent(/datum/reagent/consumable/condensedcapsaicin, 10)
|
||||
@@ -117,7 +117,7 @@
|
||||
/// Gun we have holstered.
|
||||
var/obj/item/gun/holstered
|
||||
|
||||
/obj/item/mod/module/holster/on_use()
|
||||
/obj/item/mod/module/holster/on_use(mob/activator)
|
||||
if(!holstered)
|
||||
var/obj/item/gun/holding = mod.wearer.get_active_held_item()
|
||||
if(!holding)
|
||||
@@ -163,10 +163,10 @@
|
||||
/// List of spans we add to the speaker.
|
||||
var/list/voicespan = list(SPAN_COMMAND)
|
||||
|
||||
/obj/item/mod/module/megaphone/on_activation()
|
||||
/obj/item/mod/module/megaphone/on_activation(mob/activator)
|
||||
RegisterSignal(mod.wearer, COMSIG_MOB_SAY, PROC_REF(handle_speech))
|
||||
|
||||
/obj/item/mod/module/megaphone/on_deactivation(display_message = TRUE, deleting = FALSE)
|
||||
/obj/item/mod/module/megaphone/on_deactivation(mob/activator, display_message = TRUE, deleting = FALSE)
|
||||
UnregisterSignal(mod.wearer, COMSIG_MOB_SAY)
|
||||
|
||||
/obj/item/mod/module/megaphone/proc/handle_speech(datum/source, list/speech_args)
|
||||
@@ -203,7 +203,7 @@
|
||||
idle_power_cost = linked_bodybag ? (DEFAULT_CHARGE_DRAIN * 3) : 0
|
||||
return ..()
|
||||
|
||||
/obj/item/mod/module/criminalcapture/on_deactivation(display_message = TRUE, deleting = FALSE)
|
||||
/obj/item/mod/module/criminalcapture/on_deactivation(mob/activator, display_message = TRUE, deleting = FALSE)
|
||||
if(!linked_bodybag)
|
||||
return
|
||||
packup()
|
||||
@@ -269,7 +269,7 @@
|
||||
overlay_state_inactive = "module_mirage_grenade"
|
||||
dispense_type = /obj/item/grenade/mirage
|
||||
|
||||
/obj/item/mod/module/dispenser/mirage/on_use()
|
||||
/obj/item/mod/module/dispenser/mirage/on_use(mob/activator)
|
||||
var/obj/item/grenade/mirage/grenade = ..()
|
||||
grenade.arm_grenade(mod.wearer)
|
||||
|
||||
@@ -324,12 +324,12 @@
|
||||
. = ..()
|
||||
projectile_effect = image('icons/effects/fields.dmi', "projectile_dampen_effect")
|
||||
|
||||
/obj/item/mod/module/projectile_dampener/on_activation()
|
||||
/obj/item/mod/module/projectile_dampener/on_activation(mob/activator)
|
||||
if(istype(dampening_field))
|
||||
QDEL_NULL(dampening_field)
|
||||
dampening_field = new(mod.wearer, field_radius, TRUE, src)
|
||||
|
||||
/obj/item/mod/module/projectile_dampener/on_deactivation(display_message, deleting = FALSE)
|
||||
/obj/item/mod/module/projectile_dampener/on_deactivation(mob/activator, display_message, deleting = FALSE)
|
||||
QDEL_NULL(dampening_field)
|
||||
|
||||
///Active Sonar - Displays a hud circle on the turf of any living creatures in the given radius
|
||||
@@ -429,12 +429,12 @@
|
||||
scanned_slice = 1
|
||||
COOLDOWN_START(src, scan_cooldown, scan_cooldown_time)
|
||||
|
||||
/obj/item/mod/module/active_sonar/on_use()
|
||||
balloon_alert(mod.wearer, "readying sonar...")
|
||||
/obj/item/mod/module/active_sonar/on_use(mob/activator)
|
||||
balloon_alert(activator, "readying sonar...")
|
||||
playsound(mod.wearer, 'sound/vehicles/mecha/skyfall_power_up.ogg', vol = 20, vary = TRUE, extrarange = SHORT_RANGE_SOUND_EXTRARANGE)
|
||||
if(!do_after(mod.wearer, 1.1 SECONDS, target = mod))
|
||||
return
|
||||
playsound(mod.wearer, 'sound/effects/ping_hit.ogg', vol = 75, vary = TRUE) // Should be audible for the radius of the sonar
|
||||
playsound(src, 'sound/effects/ping_hit.ogg', vol = 75, vary = TRUE) // Should be audible for the radius of the sonar
|
||||
to_chat(mod.wearer, span_notice("You slam your fist into the ground, sending out a sonic wave that detects [detect_living_creatures()] living beings nearby!"))
|
||||
for(var/mob/living/creature as anything in keyed_creatures)
|
||||
new /obj/effect/temp_visual/sonar_ping(mod.wearer.loc, mod.wearer, creature)
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
incompatible_modules = list(/obj/item/mod/module/bikehorn)
|
||||
cooldown_time = 1 SECONDS
|
||||
|
||||
/obj/item/mod/module/bikehorn/on_use()
|
||||
/obj/item/mod/module/bikehorn/on_use(mob/activator)
|
||||
playsound(src, 'sound/items/bikehorn.ogg', 100, FALSE)
|
||||
drain_power(use_energy_cost)
|
||||
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
. = ..()
|
||||
AddComponent(/datum/component/gps/item, "MOD0", state = GLOB.deep_inventory_state, overlay_state = FALSE)
|
||||
|
||||
/obj/item/mod/module/gps/on_use()
|
||||
attack_self(mod.wearer)
|
||||
/obj/item/mod/module/gps/on_use(mob/activator)
|
||||
attack_self(mod.wearer) // todo: refactor to make compatable with pAIs. Maybe ui_interact(activator)
|
||||
|
||||
///Hydraulic Clamp - Lets you pick up and drop crates.
|
||||
/obj/item/mod/module/clamp
|
||||
@@ -40,16 +40,28 @@
|
||||
var/load_time = 3 SECONDS
|
||||
/// The max amount of crates you can carry.
|
||||
var/max_crates = 3
|
||||
/// Disallow mobs larger than this size in containers
|
||||
var/max_mob_size = MOB_SIZE_SMALL
|
||||
/// Items that allowed to be picked up by this module
|
||||
var/list/accepted_items
|
||||
/// The crates stored in the module.
|
||||
var/list/stored_crates = list()
|
||||
|
||||
|
||||
/obj/item/mod/module/clamp/Initialize(mapload)
|
||||
. = ..()
|
||||
accepted_items = typecacheof(list(
|
||||
/obj/structure/closet/crate,
|
||||
/obj/item/delivery/big
|
||||
))
|
||||
|
||||
/obj/item/mod/module/clamp/on_select_use(atom/target)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
if(!mod.wearer.Adjacent(target))
|
||||
return
|
||||
if(istype(target, /obj/structure/closet/crate) || istype(target, /obj/item/delivery/big))
|
||||
if(is_type_in_typecache(target, accepted_items))
|
||||
var/atom/movable/picked_crate = target
|
||||
if(!check_crate_pickup(picked_crate))
|
||||
return
|
||||
@@ -92,7 +104,7 @@
|
||||
balloon_alert(mod.wearer, "too many crates!")
|
||||
return FALSE
|
||||
for(var/mob/living/mob in target.get_all_contents())
|
||||
if(mob.mob_size < MOB_SIZE_HUMAN)
|
||||
if(mob.mob_size <= max_mob_size)
|
||||
continue
|
||||
balloon_alert(mod.wearer, "crate too heavy!")
|
||||
return FALSE
|
||||
@@ -124,10 +136,10 @@
|
||||
overlay_state_active = "module_drill"
|
||||
required_slots = list(ITEM_SLOT_GLOVES)
|
||||
|
||||
/obj/item/mod/module/drill/on_activation()
|
||||
/obj/item/mod/module/drill/on_activation(mob/activator)
|
||||
RegisterSignal(mod.wearer, COMSIG_MOVABLE_BUMP, PROC_REF(bump_mine))
|
||||
|
||||
/obj/item/mod/module/drill/on_deactivation(display_message = TRUE, deleting = FALSE)
|
||||
/obj/item/mod/module/drill/on_deactivation(mob/activator, display_message = TRUE, deleting = FALSE)
|
||||
UnregisterSignal(mod.wearer, COMSIG_MOVABLE_BUMP)
|
||||
|
||||
/obj/item/mod/module/drill/on_select_use(atom/target)
|
||||
@@ -202,7 +214,7 @@
|
||||
ore.forceMove(src)
|
||||
ores += ore
|
||||
|
||||
/obj/item/mod/module/orebag/on_use()
|
||||
/obj/item/mod/module/orebag/on_use(mob/activator)
|
||||
for(var/obj/item/ore as anything in ores)
|
||||
ore.forceMove(drop_location())
|
||||
ores -= ore
|
||||
@@ -333,7 +345,7 @@
|
||||
locker.throw_at(mod.wearer, range = 7, speed = 3, force = MOVE_FORCE_WEAK, \
|
||||
callback = CALLBACK(src, PROC_REF(check_locker), locker))
|
||||
|
||||
/obj/item/mod/module/magnet/on_deactivation(display_message = TRUE, deleting = FALSE)
|
||||
/obj/item/mod/module/magnet/on_deactivation(mob/activator, display_message = TRUE, deleting = FALSE)
|
||||
if(istype(mod.wearer.pulling, /obj/structure/closet))
|
||||
mod.wearer.stop_pulling()
|
||||
|
||||
@@ -483,13 +495,13 @@
|
||||
TRAIT_NO_SLIP_ALL,
|
||||
)
|
||||
|
||||
/obj/item/mod/module/sphere_transform/activate()
|
||||
/obj/item/mod/module/sphere_transform/activate(mob/activator)
|
||||
if(!mod.wearer.has_gravity())
|
||||
balloon_alert(mod.wearer, "no gravity!")
|
||||
balloon_alert(activator, "no gravity!")
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/obj/item/mod/module/sphere_transform/on_activation()
|
||||
/obj/item/mod/module/sphere_transform/on_activation(mob/activator)
|
||||
playsound(src, 'sound/items/modsuit/ballin.ogg', 100, TRUE)
|
||||
mod.wearer.add_filter("mod_ball", 1, alpha_mask_filter(icon = icon('icons/mob/clothing/modsuit/mod_modules.dmi', "ball_mask"), flags = MASK_INVERSE))
|
||||
mod.wearer.add_filter("mod_blur", 2, angular_blur_filter(size = 15))
|
||||
@@ -503,7 +515,7 @@
|
||||
mod.wearer.add_movespeed_modifier(/datum/movespeed_modifier/sphere)
|
||||
RegisterSignal(mod.wearer, COMSIG_MOB_STATCHANGE, PROC_REF(on_statchange))
|
||||
|
||||
/obj/item/mod/module/sphere_transform/on_deactivation(display_message = TRUE, deleting = FALSE)
|
||||
/obj/item/mod/module/sphere_transform/on_deactivation(mob/activator, display_message = TRUE, deleting = FALSE)
|
||||
if(!deleting)
|
||||
playsound(src, 'sound/items/modsuit/ballin.ogg', 100, TRUE, frequency = -1)
|
||||
mod.wearer.remove_offsets(REF(src))
|
||||
@@ -516,9 +528,9 @@
|
||||
mod.wearer.remove_movespeed_modifier(/datum/movespeed_modifier/sphere)
|
||||
UnregisterSignal(mod.wearer, COMSIG_MOB_STATCHANGE)
|
||||
|
||||
/obj/item/mod/module/sphere_transform/used()
|
||||
/obj/item/mod/module/sphere_transform/used(mob/activator)
|
||||
if(!lavaland_equipment_pressure_check(get_turf(src)))
|
||||
balloon_alert(mod.wearer, "too much pressure!")
|
||||
balloon_alert(activator, "too much pressure!")
|
||||
playsound(src, 'sound/items/weapons/gun/general/dry_fire.ogg', 25, TRUE)
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
@@ -29,9 +29,10 @@
|
||||
UnregisterSignal(mod, COMSIG_MOD_ACTIVATE)
|
||||
UnregisterSignal(mod, COMSIG_MOD_MODULE_REMOVAL)
|
||||
|
||||
/obj/item/mod/module/eradication_lock/on_use()
|
||||
/obj/item/mod/module/eradication_lock/on_use(mob/activator)
|
||||
true_owner_ckey = mod.wearer.ckey
|
||||
balloon_alert(mod.wearer, "user remembered")
|
||||
balloon_alert(activator, "user remembered")
|
||||
playsound(src, 'sound/items/pshoom/pshoom.ogg', 25, TRUE)
|
||||
drain_power(use_energy_cost)
|
||||
|
||||
///Signal fired when the modsuit tries activating
|
||||
@@ -66,8 +67,8 @@
|
||||
cooldown_time = 20 SECONDS
|
||||
required_slots = list(ITEM_SLOT_BACK)
|
||||
|
||||
/obj/item/mod/module/rewinder/on_use()
|
||||
balloon_alert(mod.wearer, "anchor point set")
|
||||
/obj/item/mod/module/rewinder/on_use(mob/activator)
|
||||
balloon_alert(activator, "anchor point set")
|
||||
playsound(src, 'sound/items/modsuit/time_anchor_set.ogg', 50, TRUE)
|
||||
//stops all mods from triggering during rewinding
|
||||
for(var/obj/item/mod/module/module as anything in mod.modules)
|
||||
@@ -110,13 +111,13 @@
|
||||
///The current timestop in progress.
|
||||
var/obj/effect/timestop/channelled/timestop
|
||||
|
||||
/obj/item/mod/module/timestopper/used()
|
||||
/obj/item/mod/module/timestopper/used(mob/activator)
|
||||
if(timestop)
|
||||
mod.balloon_alert(mod.wearer, "already freezing time!")
|
||||
mod.balloon_alert(activator, "already freezing time!")
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/obj/item/mod/module/timestopper/on_use()
|
||||
/obj/item/mod/module/timestopper/on_use(mob/activator)
|
||||
//stops all mods from triggering during timestop- including timestop itself
|
||||
for(var/obj/item/mod/module/module as anything in mod.modules)
|
||||
RegisterSignal(module, COMSIG_MODULE_TRIGGERED, PROC_REF(on_module_triggered))
|
||||
@@ -159,14 +160,14 @@
|
||||
///The dummy for phasing from this module, the wearer is phased out while this exists.
|
||||
var/obj/effect/dummy/phased_mob/chrono/phased_mob
|
||||
|
||||
/obj/item/mod/module/timeline_jumper/used()
|
||||
/obj/item/mod/module/timeline_jumper/used(mob/activator)
|
||||
var/area/noteleport_check = get_area(mod.wearer)
|
||||
if(noteleport_check && !check_teleport_valid(mod.wearer, get_turf(mod.wearer)))
|
||||
to_chat(mod.wearer, span_danger("Some dull, universal force is between you and the [phased_mob ? "current timeline" : "stream between timelines"]."))
|
||||
to_chat(activator, span_danger("Some dull, universal force is between you and the [phased_mob ? "current timeline" : "stream between timelines"]."))
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/obj/item/mod/module/timeline_jumper/on_use()
|
||||
/obj/item/mod/module/timeline_jumper/on_use(mob/activator)
|
||||
if(!phased_mob)
|
||||
//phasing out
|
||||
mod.visible_message(span_warning("[mod.wearer] leaps out of the timeline!"))
|
||||
|
||||
@@ -12,12 +12,12 @@
|
||||
/// The traits given by the visor.
|
||||
var/list/visor_traits = list()
|
||||
|
||||
/obj/item/mod/module/visor/on_activation()
|
||||
/obj/item/mod/module/visor/on_activation(mob/activator)
|
||||
if(length(visor_traits))
|
||||
mod.wearer.add_traits(visor_traits, REF(src))
|
||||
mod.wearer.update_sight()
|
||||
|
||||
/obj/item/mod/module/visor/on_deactivation(display_message = TRUE, deleting = FALSE)
|
||||
/obj/item/mod/module/visor/on_deactivation(mob/activator, display_message = TRUE, deleting = FALSE)
|
||||
if(length(visor_traits))
|
||||
mod.wearer.remove_traits(visor_traits, REF(src))
|
||||
mod.wearer.update_sight()
|
||||
@@ -91,10 +91,10 @@
|
||||
incompatible_modules = list(/obj/item/mod/module/night, /obj/item/mod/module/visor/night)
|
||||
required_slots = list(ITEM_SLOT_HEAD|ITEM_SLOT_EYES|ITEM_SLOT_MASK)
|
||||
|
||||
/obj/item/mod/module/night/on_activation()
|
||||
ADD_TRAIT(mod.wearer, TRAIT_TRUE_NIGHT_VISION, REF(src))
|
||||
/obj/item/mod/module/night/on_activation(mob/activator)
|
||||
mod.wearer.add_traits(mod.wearer, TRAIT_TRUE_NIGHT_VISION, REF(src))
|
||||
mod.wearer.update_sight()
|
||||
|
||||
/obj/item/mod/module/night/on_deactivation(display_message = TRUE, deleting = FALSE)
|
||||
REMOVE_TRAIT(mod.wearer, TRAIT_TRUE_NIGHT_VISION, REF(src))
|
||||
/obj/item/mod/module/night/on_deactivation(mob/activator, display_message = TRUE, deleting = FALSE)
|
||||
mod.wearer.remove_traits(mod.wearer, TRAIT_TRUE_NIGHT_VISION, REF(src))
|
||||
mod.wearer.update_sight()
|
||||
|
||||
Reference in New Issue
Block a user