From ba6c2ffa4c93806aa4696de8f3a45019c05dce90 Mon Sep 17 00:00:00 2001 From: Fikou <23585223+Fikou@users.noreply.github.com> Date: Wed, 2 Aug 2023 21:47:57 +0200 Subject: [PATCH] kinesis changes + smaller misc modsuit stuff (#77241) ## About The Pull Request renames plasmaman helmet exempt flag to stackable helmet exempt. hat stabilizer now cares about this instead of letting you stack eva helmets on top of modsuit helmets improves some code that dripped in quality when i was on break kinesis has some tweaks previously it used to stun for a set amount of time - i think this is because the creator couldnt figure out how to stop movement while being held? this is changed, now as long as youre holding someone they are immobilized you can cancel your kinesis without throwing or moving out of range by using right click on the click catcher adds an admin version of kinesis just for the admin suit. it can grab (almost) ANYTHING and config menu lets you enable phasing, which makes it so the atom you grabbed phases through everything. pick up that can. ## Why It's Good For The Game its fun ## Changelog :cl: balance: hat stabilizer module can now hold what plasmaman helmets can hold qol: kinesis module can be stopped without launching an object with right click balance: kinesis module stuns last until the kinesis stops add: admin suit has a version of kinesis that can pick up anything at any range and can be configured to make grabbed mobs phase through walls :) /:cl: --- code/__DEFINES/obj_flags.dm | 4 +- code/_globalvars/bitfields.dm | 2 +- code/modules/antagonists/cult/cult_items.dm | 2 +- code/modules/clothing/head/costume.dm | 2 +- code/modules/clothing/head/hardhat.dm | 12 +- code/modules/clothing/head/hat.dm | 2 +- code/modules/clothing/head/helmet.dm | 8 +- code/modules/clothing/head/welding.dm | 2 +- .../clothing/spacesuits/_spacesuits.dm | 2 +- code/modules/clothing/spacesuits/plasmamen.dm | 4 +- code/modules/clothing/suits/bio.dm | 2 +- code/modules/clothing/suits/costume.dm | 2 +- .../mob/living/basic/vermin/butterfly.dm | 2 + code/modules/mod/mod_construction.dm | 12 +- code/modules/mod/mod_core.dm | 57 +++---- code/modules/mod/mod_theme.dm | 6 +- code/modules/mod/mod_types.dm | 6 +- code/modules/mod/modules/module_kinesis.dm | 150 ++++++++++++++---- code/modules/mod/modules/module_pathfinder.dm | 14 +- code/modules/mod/modules/modules_general.dm | 10 +- code/modules/mod/modules/modules_security.dm | 2 +- 21 files changed, 203 insertions(+), 100 deletions(-) diff --git a/code/__DEFINES/obj_flags.dm b/code/__DEFINES/obj_flags.dm index be0da9a61ff..660d05854fd 100644 --- a/code/__DEFINES/obj_flags.dm +++ b/code/__DEFINES/obj_flags.dm @@ -77,8 +77,8 @@ #define LARGE_WORN_ICON (1<<12) /// Clothes that block speech (i.e the muzzle). Can be applied to any clothing piece. #define BLOCKS_SPEECH (1<<13) -/// prevents from placing on plasmaman helmet -#define PLASMAMAN_HELMET_EXEMPT (1<<14) +/// prevents from placing on plasmaman helmet or modsuit hat holder +#define STACKABLE_HELMET_EXEMPT (1<<14) /// Prevents plasmamen from igniting when wearing this #define PLASMAMAN_PREVENT_IGNITION (1<<15) /// Usable as casting clothes by wizards (matters for suits, glasses and headwear) diff --git a/code/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm index 29e2a791229..092830751d3 100644 --- a/code/_globalvars/bitfields.dm +++ b/code/_globalvars/bitfields.dm @@ -93,7 +93,7 @@ DEFINE_BITFIELD(clothing_flags, list( "LARGE_WORN_ICON" = LARGE_WORN_ICON, "LAVAPROTECT" = LAVAPROTECT, "MASKINTERNALS" = MASKINTERNALS, - "PLASMAMAN_HELMET_EXEMPT" = PLASMAMAN_HELMET_EXEMPT, + "STACKABLE_HELMET_EXEMPT" = STACKABLE_HELMET_EXEMPT, "PLASMAMAN_PREVENT_IGNITION" = PLASMAMAN_PREVENT_IGNITION, "SNUG_FIT" = SNUG_FIT, "STOPSPRESSUREDAMAGE" = STOPSPRESSUREDAMAGE, diff --git a/code/modules/antagonists/cult/cult_items.dm b/code/modules/antagonists/cult/cult_items.dm index 19d45880655..a0beb89254a 100644 --- a/code/modules/antagonists/cult/cult_items.dm +++ b/code/modules/antagonists/cult/cult_items.dm @@ -326,7 +326,7 @@ Striking a noncultist, however, will tear their flesh."} icon_state = "cult_helmet" inhand_icon_state = null armor_type = /datum/armor/cult_hoodie_hardened - clothing_flags = STOPSPRESSUREDAMAGE | THICKMATERIAL | SNUG_FIT | PLASMAMAN_HELMET_EXEMPT | HEADINTERNALS + clothing_flags = STOPSPRESSUREDAMAGE | THICKMATERIAL | SNUG_FIT | STACKABLE_HELMET_EXEMPT | HEADINTERNALS flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT min_cold_protection_temperature = SPACE_HELM_MIN_TEMP_PROTECT max_heat_protection_temperature = SPACE_HELM_MAX_TEMP_PROTECT diff --git a/code/modules/clothing/head/costume.dm b/code/modules/clothing/head/costume.dm index 0331cf412e3..ec5ee81741f 100644 --- a/code/modules/clothing/head/costume.dm +++ b/code/modules/clothing/head/costume.dm @@ -22,7 +22,7 @@ icon_state = "syndicate-helm-black-red" inhand_icon_state = "syndicate-helm-black-red" desc = "A plastic replica of a Syndicate agent's space helmet. You'll look just like a real murderous Syndicate agent in this! This is a toy, it is not made for use in space!" - clothing_flags = SNUG_FIT + clothing_flags = SNUG_FIT | STACKABLE_HELMET_EXEMPT flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT /obj/item/clothing/head/costume/cueball diff --git a/code/modules/clothing/head/hardhat.dm b/code/modules/clothing/head/hardhat.dm index 5552688e991..71be68036bf 100644 --- a/code/modules/clothing/head/hardhat.dm +++ b/code/modules/clothing/head/hardhat.dm @@ -10,7 +10,7 @@ armor_type = /datum/armor/utility_hardhat flags_inv = 0 actions_types = list(/datum/action/item_action/toggle_helmet_light) - clothing_flags = SNUG_FIT | PLASMAMAN_HELMET_EXEMPT + clothing_flags = SNUG_FIT | STACKABLE_HELMET_EXEMPT resistance_flags = FIRE_PROOF light_system = MOVABLE_LIGHT_DIRECTIONAL @@ -73,7 +73,7 @@ hat_type = "red" dog_fashion = null name = "firefighter helmet" - clothing_flags = STOPSPRESSUREDAMAGE | PLASMAMAN_HELMET_EXEMPT + clothing_flags = STOPSPRESSUREDAMAGE | STACKABLE_HELMET_EXEMPT heat_protection = HEAD max_heat_protection_temperature = FIRE_HELM_MAX_TEMP_PROTECT cold_protection = HEAD @@ -93,7 +93,7 @@ icon_state = "hardhat0_white" inhand_icon_state = null hat_type = "white" - clothing_flags = STOPSPRESSUREDAMAGE | PLASMAMAN_HELMET_EXEMPT + clothing_flags = STOPSPRESSUREDAMAGE | STACKABLE_HELMET_EXEMPT heat_protection = HEAD max_heat_protection_temperature = FIRE_HELM_MAX_TEMP_PROTECT cold_protection = HEAD @@ -166,7 +166,7 @@ inhand_icon_state = null light_range = 4 //Boss always takes the best stuff hat_type = "white" - clothing_flags = STOPSPRESSUREDAMAGE | PLASMAMAN_HELMET_EXEMPT + clothing_flags = STOPSPRESSUREDAMAGE | STACKABLE_HELMET_EXEMPT heat_protection = HEAD max_heat_protection_temperature = FIRE_HELM_MAX_TEMP_PROTECT cold_protection = HEAD @@ -184,7 +184,7 @@ dog_fashion = null name = "atmospheric firefighter helmet" desc = "A firefighter's helmet, able to keep the user cool in any situation. Comes with a light and a welding visor." - clothing_flags = STOPSPRESSUREDAMAGE | THICKMATERIAL | BLOCK_GAS_SMOKE_EFFECT | PLASMAMAN_HELMET_EXEMPT | HEADINTERNALS + clothing_flags = STOPSPRESSUREDAMAGE | THICKMATERIAL | BLOCK_GAS_SMOKE_EFFECT | STACKABLE_HELMET_EXEMPT | HEADINTERNALS heat_protection = HEAD max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT cold_protection = HEAD @@ -208,7 +208,7 @@ icon_state = "hardhat0_pumpkin" inhand_icon_state = null hat_type = "pumpkin" - clothing_flags = SNUG_FIT | PLASMAMAN_HELMET_EXEMPT + clothing_flags = SNUG_FIT | STACKABLE_HELMET_EXEMPT flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT armor_type = /datum/armor/none light_range = 2 //luminosity when on diff --git a/code/modules/clothing/head/hat.dm b/code/modules/clothing/head/hat.dm index fac31c43206..ccc8e903f33 100644 --- a/code/modules/clothing/head/hat.dm +++ b/code/modules/clothing/head/hat.dm @@ -55,7 +55,7 @@ name = "plague doctor's hat" desc = "These were once used by plague doctors. Will protect you from exposure to the Pestilence." icon_state = "plaguedoctor" - clothing_flags = THICKMATERIAL | BLOCK_GAS_SMOKE_EFFECT | SNUG_FIT | PLASMAMAN_HELMET_EXEMPT + clothing_flags = THICKMATERIAL | BLOCK_GAS_SMOKE_EFFECT | SNUG_FIT | STACKABLE_HELMET_EXEMPT armor_type = /datum/armor/bio_hood_plague flags_inv = NONE diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm index 7c0b53fc7a6..488bd7448a7 100644 --- a/code/modules/clothing/head/helmet.dm +++ b/code/modules/clothing/head/helmet.dm @@ -11,7 +11,7 @@ heat_protection = HEAD max_heat_protection_temperature = HELMET_MAX_TEMP_PROTECT strip_delay = 60 - clothing_flags = SNUG_FIT | PLASMAMAN_HELMET_EXEMPT + clothing_flags = SNUG_FIT | STACKABLE_HELMET_EXEMPT flags_cover = HEADCOVERSEYES flags_inv = HIDEHAIR dog_fashion = /datum/dog_fashion/head/helmet @@ -89,7 +89,7 @@ inhand_icon_state = "marine_helmet" armor_type = /datum/armor/helmet_marine min_cold_protection_temperature = SPACE_HELM_MIN_TEMP_PROTECT - clothing_flags = STOPSPRESSUREDAMAGE | PLASMAMAN_HELMET_EXEMPT + clothing_flags = STOPSPRESSUREDAMAGE | STACKABLE_HELMET_EXEMPT resistance_flags = FIRE_PROOF | ACID_PROOF dog_fashion = null @@ -243,7 +243,7 @@ min_cold_protection_temperature = SPACE_HELM_MIN_TEMP_PROTECT heat_protection = HEAD max_heat_protection_temperature = SPACE_HELM_MAX_TEMP_PROTECT - clothing_flags = STOPSPRESSUREDAMAGE | PLASMAMAN_HELMET_EXEMPT + clothing_flags = STOPSPRESSUREDAMAGE | STACKABLE_HELMET_EXEMPT strip_delay = 80 resistance_flags = FIRE_PROOF | ACID_PROOF dog_fashion = null @@ -264,7 +264,7 @@ desc = "An extremely robust helmet with the Nanotrasen logo emblazoned on the top." icon_state = "swat" inhand_icon_state = "swat_helmet" - clothing_flags = PLASMAMAN_HELMET_EXEMPT + clothing_flags = STACKABLE_HELMET_EXEMPT cold_protection = HEAD min_cold_protection_temperature = SPACE_HELM_MIN_TEMP_PROTECT heat_protection = HEAD diff --git a/code/modules/clothing/head/welding.dm b/code/modules/clothing/head/welding.dm index 287ab800c1f..bccb1d4524d 100644 --- a/code/modules/clothing/head/welding.dm +++ b/code/modules/clothing/head/welding.dm @@ -15,7 +15,7 @@ visor_flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDESNOUT visor_flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH | PEPPERPROOF resistance_flags = FIRE_PROOF - clothing_flags = SNUG_FIT | PLASMAMAN_HELMET_EXEMPT + clothing_flags = SNUG_FIT | STACKABLE_HELMET_EXEMPT /datum/armor/utility_welding melee = 10 diff --git a/code/modules/clothing/spacesuits/_spacesuits.dm b/code/modules/clothing/spacesuits/_spacesuits.dm index d26a8f08400..c765d6b2fb4 100644 --- a/code/modules/clothing/spacesuits/_spacesuits.dm +++ b/code/modules/clothing/spacesuits/_spacesuits.dm @@ -9,7 +9,7 @@ icon_state = "spaceold" inhand_icon_state = "space_helmet" desc = "A special helmet with solar UV shielding to protect your eyes from harmful rays." - clothing_flags = STOPSPRESSUREDAMAGE | THICKMATERIAL | SNUG_FIT | PLASMAMAN_HELMET_EXEMPT | HEADINTERNALS + clothing_flags = STOPSPRESSUREDAMAGE | THICKMATERIAL | SNUG_FIT | STACKABLE_HELMET_EXEMPT | HEADINTERNALS armor_type = /datum/armor/helmet_space flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT diff --git a/code/modules/clothing/spacesuits/plasmamen.dm b/code/modules/clothing/spacesuits/plasmamen.dm index 7b73e5b3383..1e75acacca6 100644 --- a/code/modules/clothing/spacesuits/plasmamen.dm +++ b/code/modules/clothing/spacesuits/plasmamen.dm @@ -44,7 +44,7 @@ desc = "A special containment helmet that allows plasma-based lifeforms to exist safely in an oxygenated environment. It is space-worthy, and may be worn in tandem with other EVA gear." icon = 'icons/obj/clothing/head/plasmaman_hats.dmi' worn_icon = 'icons/mob/clothing/head/plasmaman_head.dmi' - clothing_flags = STOPSPRESSUREDAMAGE | THICKMATERIAL | SNUG_FIT | PLASMAMAN_HELMET_EXEMPT | PLASMAMAN_PREVENT_IGNITION | HEADINTERNALS + clothing_flags = STOPSPRESSUREDAMAGE | THICKMATERIAL | SNUG_FIT | STACKABLE_HELMET_EXEMPT | PLASMAMAN_PREVENT_IGNITION | HEADINTERNALS icon_state = "plasmaman-helm" inhand_icon_state = "plasmaman-helm" strip_delay = 80 @@ -126,7 +126,7 @@ return if(istype(hitting_item, /obj/item/clothing/head)) var/obj/item/clothing/hitting_clothing = hitting_item - if(hitting_clothing.clothing_flags & PLASMAMAN_HELMET_EXEMPT) + if(hitting_clothing.clothing_flags & STACKABLE_HELMET_EXEMPT) to_chat(user, span_notice("You cannot place [hitting_clothing.name] on helmet!")) return if(attached_hat) diff --git a/code/modules/clothing/suits/bio.dm b/code/modules/clothing/suits/bio.dm index ffbef12d1ef..4ddfd31631d 100644 --- a/code/modules/clothing/suits/bio.dm +++ b/code/modules/clothing/suits/bio.dm @@ -6,7 +6,7 @@ worn_icon = 'icons/mob/clothing/head/bio.dmi' icon_state = "bio" inhand_icon_state = "bio_hood" - clothing_flags = THICKMATERIAL | BLOCK_GAS_SMOKE_EFFECT | SNUG_FIT | PLASMAMAN_HELMET_EXEMPT | HEADINTERNALS + clothing_flags = THICKMATERIAL | BLOCK_GAS_SMOKE_EFFECT | SNUG_FIT | STACKABLE_HELMET_EXEMPT | HEADINTERNALS armor_type = /datum/armor/head_bio_hood flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEHAIR|HIDEFACIALHAIR|HIDEFACE|HIDESNOUT resistance_flags = ACID_PROOF diff --git a/code/modules/clothing/suits/costume.dm b/code/modules/clothing/suits/costume.dm index 129042e0cd8..55b8b96e00a 100644 --- a/code/modules/clothing/suits/costume.dm +++ b/code/modules/clothing/suits/costume.dm @@ -304,7 +304,7 @@ min_cold_protection_temperature = SPACE_HELM_MIN_TEMP_PROTECT heat_protection = HEAD max_heat_protection_temperature = SPACE_HELM_MAX_TEMP_PROTECT - clothing_flags = STOPSPRESSUREDAMAGE|THICKMATERIAL|SNUG_FIT|PLASMAMAN_HELMET_EXEMPT + clothing_flags = STOPSPRESSUREDAMAGE|THICKMATERIAL|SNUG_FIT|STACKABLE_HELMET_EXEMPT body_parts_covered = HEAD resistance_flags = NONE flash_protect = FLASH_PROTECTION_WELDER diff --git a/code/modules/mob/living/basic/vermin/butterfly.dm b/code/modules/mob/living/basic/vermin/butterfly.dm index 77f89d4d4d1..cbc847aa9e8 100644 --- a/code/modules/mob/living/basic/vermin/butterfly.dm +++ b/code/modules/mob/living/basic/vermin/butterfly.dm @@ -80,6 +80,8 @@ /// Checks whether the butterfly should be despawned after the next check, based on distance from source /mob/living/basic/butterfly/lavaland/temporary/proc/should_despawn() + if(QDELETED(source)) + return TRUE if(get_dist(source, src) > max_distance) return TRUE return FALSE diff --git a/code/modules/mod/mod_construction.dm b/code/modules/mod/mod_construction.dm index a79d216039c..398ba2f216e 100644 --- a/code/modules/mod/mod_construction.dm +++ b/code/modules/mod/mod_construction.dm @@ -46,7 +46,9 @@ /obj/item/mod/construction/broken_core/screwdriver_act(mob/living/user, obj/item/tool) . = ..() + balloon_alert(user, "repairing...") if(!tool.use_tool(src, user, 5 SECONDS, volume = 30)) + balloon_alert(user, "interrupted!") return new /obj/item/mod/core/standard(drop_location()) qdel(src) @@ -66,20 +68,16 @@ /obj/item/mod/construction/lavalandcore/attackby(obj/item/weapon, mob/user, params) if(!istype(weapon, /obj/item/stack/cable_coil)) - return - + return ..() if(!weapon.tool_start_check(user, amount=2)) return - - to_chat(user, span_notice("You start pushing the wires into the core...")) + balloon_alert(user, "installing wires...") if(!weapon.use_tool(src, user, 5 SECONDS, amount = 2, volume = 30)) + balloon_alert(user, "interrupted!") return - - to_chat(user, span_notice("You add the wires to the core.")) new /obj/item/mod/core/plasma/lavaland(drop_location()) qdel(src) - /obj/item/mod/construction/plating name = "MOD external plating" desc = "External plating used to finish a MOD control unit." diff --git a/code/modules/mod/mod_core.dm b/code/modules/mod/mod_core.dm index 06dace8b5b0..45fa61677b2 100644 --- a/code/modules/mod/mod_core.dm +++ b/code/modules/mod/mod_core.dm @@ -370,49 +370,23 @@ light_system = MOVABLE_LIGHT light_color = "#cc00cc" light_range = 2 - // Slightly better than the normal plasma core. // Not super sure if this should just be the same, but will see. maxcharge = 15000 charge = 15000 - /// The mob to be spawned by the core var/mob/living/spawned_mob_type = /mob/living/basic/butterfly/lavaland/temporary /// Max number of mobs it can spawn var/max_spawns = 3 - /// Mob spawner for the core var/datum/component/spawner/mob_spawner - + /// Particle holder for pollen particles + var/obj/effect/abstract/particle_holder/particle_effect /obj/item/mod/core/plasma/lavaland/Destroy() - if(mod?.wearer) - mod.wearer.particles = null + QDEL_NULL(particle_effect) return ..() -/obj/item/mod/core/plasma/lavaland/proc/new_mob(spawner, mob/living/basic/butterfly/lavaland/temporary/spawned) - SIGNAL_HANDLER - if(spawned) - spawned.source = src - -/obj/item/mod/core/plasma/lavaland/proc/on_toggle() - SIGNAL_HANDLER - if(mod.active) - START_PROCESSING(SSprocessing, src) - mod.wearer.particles = new /particles/pollen() - mob_spawner = mod.wearer.AddComponent(/datum/component/spawner, spawn_types=list(spawned_mob_type), spawn_time=5 SECONDS, max_spawned=3) - RegisterSignal(mob_spawner, COMSIG_SPAWNER_SPAWNED, PROC_REF(new_mob)) - RegisterSignal(mod.wearer, COMSIG_MOVABLE_PRE_MOVE, PROC_REF(flowas)) - - else - STOP_PROCESSING(SSprocessing, src) - mod.wearer.particles = null - UnregisterSignal(mob_spawner, COMSIG_SPAWNER_SPAWNED) - UnregisterSignal(mod.wearer, COMSIG_MOVABLE_PRE_MOVE) - for(var/datum/mob in mob_spawner.spawned_things) - qdel(mob) - qdel(mob_spawner) - /obj/item/mod/core/plasma/lavaland/install(obj/item/mod/control/mod_unit) . = ..() RegisterSignal(mod_unit, COMSIG_MOD_TOGGLED, PROC_REF(on_toggle)) @@ -421,7 +395,28 @@ . = ..() UnregisterSignal(mod_unit, COMSIG_MOD_TOGGLED) -/obj/item/mod/core/plasma/lavaland/proc/flowas(mob/living/wearer) +/obj/item/mod/core/plasma/lavaland/proc/on_toggle() + SIGNAL_HANDLER + if(mod.active) + particle_effect = new(mod.wearer, /particles/pollen, PARTICLE_ATTACH_MOB) + mob_spawner = mod.wearer.AddComponent(/datum/component/spawner, spawn_types=list(spawned_mob_type), spawn_time=5 SECONDS, max_spawned=3) + RegisterSignal(mob_spawner, COMSIG_SPAWNER_SPAWNED, PROC_REF(new_mob)) + RegisterSignal(mod.wearer, COMSIG_MOVABLE_MOVED, PROC_REF(spread_flowers)) + + else + QDEL_NULL(particle_effect) + UnregisterSignal(mob_spawner, COMSIG_SPAWNER_SPAWNED) + UnregisterSignal(mod.wearer, COMSIG_MOVABLE_MOVED) + for(var/datum/mob in mob_spawner.spawned_things) + qdel(mob) + qdel(mob_spawner) + +/obj/item/mod/core/plasma/lavaland/proc/new_mob(spawner, mob/living/basic/butterfly/lavaland/temporary/spawned) + SIGNAL_HANDLER + if(spawned) + spawned.source = src + +/obj/item/mod/core/plasma/lavaland/proc/spread_flowers(atom/source, atom/oldloc, dir, forced) SIGNAL_HANDLER var/static/list/possible_flower_types = list( /obj/structure/flora/bush/lavendergrass/style_random, @@ -430,6 +425,6 @@ /obj/structure/flora/bush/flowers_pp/style_random, ) var/chosen_type = pick(possible_flower_types) - var/flower_boots = new chosen_type(get_turf(wearer)) + var/flower_boots = new chosen_type(get_turf(mod.wearer)) animate(flower_boots, alpha = 0, 1 SECONDS) QDEL_IN(flower_boots, 1 SECONDS) diff --git a/code/modules/mod/mod_theme.dm b/code/modules/mod/mod_theme.dm index 9f989ce4c96..209bb40ac35 100644 --- a/code/modules/mod/mod_theme.dm +++ b/code/modules/mod/mod_theme.dm @@ -1389,7 +1389,7 @@ slowdown_inactive = 1.5 slowdown_active = 1 ui_theme = "hackerman" - inbuilt_modules = list(/obj/item/mod/module/anomaly_locked/kinesis/prebuilt/prototype) + inbuilt_modules = list(/obj/item/mod/module/anomaly_locked/kinesis/prototype) allowed_suit_storage = list( /obj/item/analyzer, /obj/item/t_scanner, @@ -1717,7 +1717,7 @@ siemens_coefficient = 0 slowdown_inactive = 0.5 slowdown_active = 0 - activation_step_time = 0.4 SECONDS + activation_step_time = MOD_ACTIVATION_STEP_TIME * 0.2 allowed_suit_storage = list( /obj/item/gun, ) @@ -1777,7 +1777,7 @@ siemens_coefficient = 0 slowdown_inactive = 0 slowdown_active = 0 - activation_step_time = 0.1 SECONDS + activation_step_time = MOD_ACTIVATION_STEP_TIME * 0.01 allowed_suit_storage = list( /obj/item/gun, ) diff --git a/code/modules/mod/mod_types.dm b/code/modules/mod/mod_types.dm index b5de82895ac..e820525ff9a 100644 --- a/code/modules/mod/mod_types.dm +++ b/code/modules/mod/mod_types.dm @@ -344,7 +344,7 @@ ) default_pins = list( /obj/item/mod/module/tether, - /obj/item/mod/module/anomaly_locked/kinesis/prebuilt/prototype, + /obj/item/mod/module/anomaly_locked/kinesis/prototype, ) /obj/item/mod/control/pre_equipped/responsory @@ -505,13 +505,13 @@ /obj/item/mod/module/quick_carry/advanced, /obj/item/mod/module/magboot/advanced, /obj/item/mod/module/jetpack/advanced, - /obj/item/mod/module/anomaly_locked/kinesis/plus, + /obj/item/mod/module/anomaly_locked/kinesis/admin, ) default_pins = list( /obj/item/mod/module/stealth/ninja, /obj/item/mod/module/magboot/advanced, /obj/item/mod/module/jetpack/advanced, - /obj/item/mod/module/anomaly_locked/kinesis/plus, + /obj/item/mod/module/anomaly_locked/kinesis/admin, ) //these exist for the prefs menu diff --git a/code/modules/mod/modules/module_kinesis.dm b/code/modules/mod/modules/module_kinesis.dm index 8fe4ba9f07c..84dc503af1f 100644 --- a/code/modules/mod/modules/module_kinesis.dm +++ b/code/modules/mod/modules/module_kinesis.dm @@ -21,8 +21,6 @@ var/hit_cooldown_time = 1 SECONDS /// Stat required for us to grab a mob. var/stat_required = DEAD - /// How long we stun a mob for. - var/mob_stun_time = 5 SECONDS /// Atom we grabbed with kinesis. var/atom/movable/grabbed_atom /// Ref of the beam following the grabbed atom. @@ -51,8 +49,9 @@ if(!mod.wearer.client) return if(grabbed_atom) - launch() + var/launched_object = grabbed_atom clear_grab(playsound = FALSE) + launch(launched_object) return if(!range_check(target)) balloon_alert(mod.wearer, "too far!") @@ -61,20 +60,7 @@ balloon_alert(mod.wearer, "can't grab!") return drain_power(use_power_cost) - grabbed_atom = target - if(isliving(grabbed_atom)) - var/mob/living/grabbed_mob = grabbed_atom - grabbed_mob.Stun(mob_stun_time) - playsound(grabbed_atom, 'sound/effects/contractorbatonhit.ogg', 75, TRUE) - kinesis_icon = mutable_appearance(icon = 'icons/effects/effects.dmi', icon_state = "kinesis", layer = grabbed_atom.layer - 0.1) - kinesis_icon.appearance_flags = RESET_ALPHA|RESET_COLOR|RESET_TRANSFORM - kinesis_icon.overlays += emissive_appearance(icon = 'icons/effects/effects.dmi', icon_state = "kinesis", offset_spokesman = grabbed_atom) - grabbed_atom.add_overlay(kinesis_icon) - kinesis_beam = mod.wearer.Beam(grabbed_atom, "kinesis") - kinesis_catcher = mod.wearer.overlay_fullscreen("kinesis", /atom/movable/screen/fullscreen/cursor_catcher/kinesis, 0) - kinesis_catcher.assign_to_mob(mod.wearer) - soundloop.start() - START_PROCESSING(SSfastprocess, src) + grab_atom(target) /obj/item/mod/module/anomaly_locked/kinesis/on_deactivation(display_message = TRUE, deleting = FALSE) . = ..() @@ -158,6 +144,8 @@ if(!isliving(movable_target)) return FALSE var/mob/living/living_target = movable_target + if(living_target.buckled) + return FALSE if(living_target.stat < stat_required) return FALSE else if(isitem(movable_target)) @@ -168,9 +156,29 @@ return FALSE return TRUE +/obj/item/mod/module/anomaly_locked/kinesis/proc/grab_atom(atom/movable/target) + grabbed_atom = target + if(isliving(grabbed_atom)) + add_traits(grabbed_atom, list(TRAIT_IMMOBILIZED, TRAIT_HANDS_BLOCKED), REF(src)) + RegisterSignal(grabbed_atom, COMSIG_MOB_STATCHANGE, PROC_REF(on_statchange)) + ADD_TRAIT(grabbed_atom, TRAIT_NO_FLOATING_ANIM, REF(src)) + RegisterSignal(grabbed_atom, COMSIG_MOVABLE_SET_ANCHORED, PROC_REF(on_setanchored)) + playsound(grabbed_atom, 'sound/effects/contractorbatonhit.ogg', 75, TRUE) + kinesis_icon = mutable_appearance(icon = 'icons/effects/effects.dmi', icon_state = "kinesis", layer = grabbed_atom.layer - 0.1) + kinesis_icon.appearance_flags = RESET_ALPHA|RESET_COLOR|RESET_TRANSFORM + kinesis_icon.overlays += emissive_appearance(icon = 'icons/effects/effects.dmi', icon_state = "kinesis", offset_spokesman = grabbed_atom) + grabbed_atom.add_overlay(kinesis_icon) + kinesis_beam = mod.wearer.Beam(grabbed_atom, "kinesis") + kinesis_catcher = mod.wearer.overlay_fullscreen("kinesis", /atom/movable/screen/fullscreen/cursor_catcher/kinesis, 0) + kinesis_catcher.assign_to_mob(mod.wearer) + RegisterSignal(kinesis_catcher, COMSIG_CLICK, PROC_REF(on_catcher_click)) + soundloop.start() + START_PROCESSING(SSfastprocess, src) + /obj/item/mod/module/anomaly_locked/kinesis/proc/clear_grab(playsound = TRUE) if(!grabbed_atom) return + . = grabbed_atom if(playsound) playsound(grabbed_atom, 'sound/effects/empulse.ogg', 75, TRUE) STOP_PROCESSING(SSfastprocess, src) @@ -178,6 +186,9 @@ mod.wearer.clear_fullscreen("kinesis") grabbed_atom.cut_overlay(kinesis_icon) QDEL_NULL(kinesis_beam) + if(isliving(grabbed_atom)) + remove_traits(grabbed_atom, list(TRAIT_IMMOBILIZED, TRAIT_HANDS_BLOCKED), REF(src)) + REMOVE_TRAIT(grabbed_atom, TRAIT_NO_FLOATING_ANIM, REF(src)) if(!isitem(grabbed_atom)) animate(grabbed_atom, 0.2 SECONDS, pixel_x = grabbed_atom.base_pixel_x, pixel_y = grabbed_atom.base_pixel_y) grabbed_atom = null @@ -192,11 +203,31 @@ return FALSE return TRUE -/obj/item/mod/module/anomaly_locked/kinesis/proc/launch() - playsound(grabbed_atom, 'sound/magic/repulse.ogg', 100, TRUE) - RegisterSignal(grabbed_atom, COMSIG_MOVABLE_IMPACT, PROC_REF(launch_impact)) - var/turf/target_turf = get_turf_in_angle(get_angle(mod.wearer, grabbed_atom), get_turf(src), 10) - grabbed_atom.throw_at(target_turf, range = grab_range, speed = grabbed_atom.density ? 3 : 4, thrower = mod.wearer, spin = isitem(grabbed_atom)) + +/obj/item/mod/module/anomaly_locked/kinesis/proc/on_catcher_click(atom/source, location, control, params, user) + SIGNAL_HANDLER + + var/list/modifiers = params2list(params) + if(LAZYACCESS(modifiers, RIGHT_CLICK)) + clear_grab() + +/obj/item/mod/module/anomaly_locked/kinesis/proc/on_statchange(mob/grabbed_mob, new_stat) + SIGNAL_HANDLER + + if(new_stat < stat_required) + clear_grab() + +/obj/item/mod/module/anomaly_locked/kinesis/proc/on_setanchored(atom/movable/grabbed_atom, anchorvalue) + SIGNAL_HANDLER + + if(grabbed_atom.anchored) + clear_grab() + +/obj/item/mod/module/anomaly_locked/kinesis/proc/launch(atom/movable/launched_object) + playsound(launched_object, 'sound/magic/repulse.ogg', 100, TRUE) + RegisterSignal(launched_object, COMSIG_MOVABLE_IMPACT, PROC_REF(launch_impact)) + var/turf/target_turf = get_turf_in_angle(get_angle(mod.wearer, launched_object), get_turf(src), 10) + launched_object.throw_at(target_turf, range = grab_range, speed = launched_object.density ? 3 : 4, thrower = mod.wearer, spin = isitem(launched_object)) /obj/item/mod/module/anomaly_locked/kinesis/proc/launch_impact(atom/movable/source, atom/hit_atom, datum/thrownthing/thrownthing) UnregisterSignal(source, COMSIG_MOVABLE_IMPACT) @@ -215,25 +246,88 @@ if(damage_self && source.uses_integrity) source.take_damage(source.max_integrity/5, BRUTE, MELEE) +/atom/movable/screen/fullscreen/cursor_catcher/kinesis + icon_state = "kinesis" + /obj/item/mod/module/anomaly_locked/kinesis/prebuilt prebuilt = TRUE -/obj/item/mod/module/anomaly_locked/kinesis/prebuilt/prototype +/obj/item/mod/module/anomaly_locked/kinesis/prototype name = "MOD prototype kinesis module" + prebuilt = TRUE complexity = 0 use_power_cost = DEFAULT_CHARGE_DRAIN * 5 removable = FALSE -/atom/movable/screen/fullscreen/cursor_catcher/kinesis - icon_state = "kinesis" - /obj/item/mod/module/anomaly_locked/kinesis/plus name = "MOD kinesis+ module" desc = "A modular plug-in to the forearm, this module was recently redeveloped in secret. \ The bane of all ne'er-do-wells, the kinesis+ module is a powerful tool that allows the user \ to manipulate the world around them. Like it's older counterpart, it's capable of manipulating \ - structures, machinery, vehicles, and, thanks to the fruitful efforts of it's creators - living \ - beings. They can, however, still struggle after an initial burst of inertia." + structures, machinery, vehicles, and, thanks to the fruitful efforts of its creators - living beings." complexity = 0 prebuilt = TRUE stat_required = CONSCIOUS + +/// Admin suit version of kinesis. Can grab anything at any range, may enable phasing through walls. +/obj/item/mod/module/anomaly_locked/kinesis/admin + name = "MOD kinesis++ module" + desc = "A modular plug-in to the forearm, this module was recently reredeveloped in super secret. \ + This one can force some of the grasped objects to phase through walls. Oh no." + complexity = 0 + grab_range = INFINITY + use_power_cost = DEFAULT_CHARGE_DRAIN * 0 + prebuilt = TRUE + stat_required = CONSCIOUS + /// Does our object phase through stuff? + var/phasing = FALSE + +/obj/item/mod/module/anomaly_locked/kinesis/admin/grab_atom(atom/movable/target) + . = ..() + if(phasing) + ADD_TRAIT(grabbed_atom, TRAIT_MOVE_PHASING, REF(src)) + +/obj/item/mod/module/anomaly_locked/kinesis/admin/clear_grab(playsound) + . = ..() + if(!.) + return + var/atom/movable/previous_grab = . + if(phasing) + REMOVE_TRAIT(previous_grab, TRAIT_MOVE_PHASING, REF(src)) + +/obj/item/mod/module/anomaly_locked/kinesis/admin/can_grab(atom/target) + if(mod.wearer == target) + return FALSE + if(!ismovable(target)) + return FALSE + var/atom/movable/movable_target = target + if(movable_target.throwing) + return FALSE + return TRUE + +/obj/item/mod/module/anomaly_locked/kinesis/admin/range_check(atom/target) + if(!isturf(mod.wearer.loc)) + return FALSE + if(ismovable(target) && !isturf(target.loc)) + return FALSE + if(target.z != mod.wearer.z) + return FALSE + return TRUE + +/obj/item/mod/module/anomaly_locked/kinesis/admin/on_setanchored(atom/movable/grabbed_atom, anchorvalue) + return //thog dont care + +/obj/item/mod/module/anomaly_locked/kinesis/admin/get_configuration() + . = ..() + .["phasing"] = add_ui_configuration("Phasing", "bool", phasing) + +/obj/item/mod/module/anomaly_locked/kinesis/admin/configure_edit(key, value) + switch(key) + if("phasing") + phasing = value + if(!grabbed_atom) + return + if(phasing) + ADD_TRAIT(grabbed_atom, TRAIT_MOVE_PHASING, REF(src)) + else + REMOVE_TRAIT(grabbed_atom, TRAIT_MOVE_PHASING, REF(src)) diff --git a/code/modules/mod/modules/module_pathfinder.dm b/code/modules/mod/modules/module_pathfinder.dm index 2b4f9c70f5f..85d1ce7a00a 100644 --- a/code/modules/mod/modules/module_pathfinder.dm +++ b/code/modules/mod/modules/module_pathfinder.dm @@ -21,9 +21,19 @@ implant = new(src) /obj/item/mod/module/pathfinder/Destroy() - implant = null + QDEL_NULL(implant) return ..() +/obj/item/mod/module/pathfinder/Exited(atom/movable/gone, direction) + if(gone == implant) + implant = null + update_icon_state() + return ..() + +/obj/item/mod/module/pathfinder/update_icon_state() + . = ..() + icon_state = implant ? "pathfinder" : "pathfinder_empty" + /obj/item/mod/module/pathfinder/examine(mob/user) . = ..() if(implant) @@ -45,8 +55,6 @@ 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) - icon_state = "pathfinder_empty" - implant = null /obj/item/mod/module/pathfinder/proc/attach(mob/living/user) if(!ishuman(user)) diff --git a/code/modules/mod/modules/modules_general.dm b/code/modules/mod/modules/modules_general.dm index e297aeb1851..133bf25b833 100644 --- a/code/modules/mod/modules/modules_general.dm +++ b/code/modules/mod/modules/modules_general.dm @@ -105,7 +105,9 @@ overlay_state_active = "module_jetpack_on" /// Do we give the wearer a speed buff. var/full_speed = FALSE + /// Do we have stabilizers? If yes the user won't move from inertia. var/stabilize = TRUE + /// Callback to see if we can thrust the user. var/thrust_callback /obj/item/mod/module/jetpack/Initialize(mapload) @@ -585,7 +587,7 @@ incompatible_modules = list(/obj/item/mod/module/hat_stabilizer) /*Intentionally left inheriting 0 complexity and removable = TRUE; even though it comes inbuilt into the Magnate/Corporate MODS and spawns in maints, I like the idea of stealing them*/ - /// Currently "stored" hat. No armor or function will be inherited, ONLY the icon. + /// Currently "stored" hat. No armor or function will be inherited, only the icon and cover flags. var/obj/item/clothing/head/attached_hat /// Original cover flags for the MOD helmet, before a hat is placed var/former_flags @@ -616,14 +618,18 @@ SIGNAL_HANDLER if(!istype(hitting_item, /obj/item/clothing/head)) return + var/obj/item/clothing/hat = hitting_item if(!mod.active) balloon_alert(user, "suit must be active!") return if(attached_hat) balloon_alert(user, "hat already attached!") return + if(hat.clothing_flags & STACKABLE_HELMET_EXEMPT) + balloon_alert(user, "invalid hat!") + return if(mod.wearer.transferItemToLoc(hitting_item, src, force = FALSE, silent = TRUE)) - attached_hat = hitting_item + attached_hat = hat former_flags = mod.helmet.flags_cover former_visor_flags = mod.helmet.visor_flags_cover mod.helmet.flags_cover |= attached_hat.flags_cover diff --git a/code/modules/mod/modules/modules_security.dm b/code/modules/mod/modules/modules_security.dm index 38cb4736aa5..c2b77b2650e 100644 --- a/code/modules/mod/modules/modules_security.dm +++ b/code/modules/mod/modules/modules_security.dm @@ -137,9 +137,9 @@ holstered.forceMove(drop_location()) /obj/item/mod/module/holster/Exited(atom/movable/gone, direction) - . = ..() if(gone == holstered) holstered = null + return ..() /obj/item/mod/module/holster/Destroy() QDEL_NULL(holstered)