diff --git a/code/__DEFINES/dcs/signals/signals_mod.dm b/code/__DEFINES/dcs/signals/signals_mod.dm index 2533b698528..c4007d12969 100644 --- a/code/__DEFINES/dcs/signals/signals_mod.dm +++ b/code/__DEFINES/dcs/signals/signals_mod.dm @@ -25,6 +25,8 @@ #define MOD_ABORT_USE (1<<0) /// Called when a module activates, after all checks have passed and cooldown started. #define COMSIG_MODULE_ACTIVATED "mod_module_activated" +/// Called when a module starts a cooldown until its next activation. Passed the cooldown time. +#define COMSIG_MODULE_COOLDOWN_STARTED "mod_module_cooldown_started" /// Called when a module deactivates, after all checks have passed. #define COMSIG_MODULE_DEACTIVATED "mod_module_deactivated" /// Called when a module is used, after all checks have passed and cooldown started. diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index fa29b69bb02..48e7b652c3d 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -639,6 +639,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_MOVE_PHASING "move_phasing" /// Disables the floating animation. See above. #define TRAIT_NO_FLOATING_ANIM "no-floating-animation" +/// Trait applied while you're using a jetpack +#define TRAIT_JETPACKING "using_a_jetpack" /// Weather immunities, also protect mobs inside them. #define TRAIT_LAVA_IMMUNE "lava_immune" //Used by lava turfs and The Floor Is Lava. diff --git a/code/datums/components/jetpack.dm b/code/datums/components/jetpack.dm index f7e1fca70e6..f21b6a5eebf 100644 --- a/code/datums/components/jetpack.dm +++ b/code/datums/components/jetpack.dm @@ -84,6 +84,8 @@ if(!check_on_move.Invoke(TRUE)) return return_flag + ADD_TRAIT(user, TRAIT_JETPACKING, REF(src)) + RegisterSignal(user, COMSIG_MOVABLE_MOVED, PROC_REF(move_react)) RegisterSignal(user, COMSIG_MOVABLE_PRE_MOVE, PROC_REF(pre_move_react)) RegisterSignal(user, COMSIG_MOVABLE_SPACEMOVE, PROC_REF(spacemove_react)) @@ -95,6 +97,8 @@ /datum/component/jetpack/proc/deactivate(datum/source, mob/user) SIGNAL_HANDLER + REMOVE_TRAIT(user, TRAIT_JETPACKING, REF(src)) + UnregisterSignal(user, COMSIG_MOVABLE_MOVED) UnregisterSignal(user, COMSIG_MOVABLE_PRE_MOVE) UnregisterSignal(user, COMSIG_MOVABLE_SPACEMOVE) diff --git a/code/datums/status_effects/buffs.dm b/code/datums/status_effects/buffs.dm index 8ade25a7468..c86da3c8dda 100644 --- a/code/datums/status_effects/buffs.dm +++ b/code/datums/status_effects/buffs.dm @@ -503,3 +503,16 @@ owner.RemoveElement(/datum/element/simple_flying) owner.remove_stun_absorption(id) remove_traits(list(TRAIT_IGNOREDAMAGESLOWDOWN, TRAIT_FREE_HYPERSPACE_MOVEMENT), MAD_WIZARD_TRAIT) + +/// Gives you a brief period of anti-gravity +/datum/status_effect/jump_jet + id = "jump_jet" + alert_type = null + duration = 5 SECONDS + +/datum/status_effect/jump_jet/on_apply() + owner.AddElement(/datum/element/forced_gravity, 0) + return TRUE + +/datum/status_effect/jump_jet/on_remove() + owner.RemoveElement(/datum/element/forced_gravity, 0) diff --git a/code/game/objects/effects/temporary_visuals/miscellaneous.dm b/code/game/objects/effects/temporary_visuals/miscellaneous.dm index 39a10791b71..391e23c820b 100644 --- a/code/game/objects/effects/temporary_visuals/miscellaneous.dm +++ b/code/game/objects/effects/temporary_visuals/miscellaneous.dm @@ -653,6 +653,13 @@ . = ..() animate(src, pixel_y = pixel_y + 16, alpha = 0, time = duration) +/obj/effect/temp_visual/jet_plume + name = "jet plume" + icon_state = "jet_plume" + layer = BELOW_MOB_LAYER + plane = GAME_PLANE + duration = 0.4 SECONDS + /// Plays a dispersing animation on hivelord and legion minions so they don't just vanish /obj/effect/temp_visual/hive_spawn_wither name = "withering spawn" diff --git a/code/modules/mod/mod_actions.dm b/code/modules/mod/mod_actions.dm index d82912055e2..111ea425b6a 100644 --- a/code/modules/mod/mod_actions.dm +++ b/code/modules/mod/mod_actions.dm @@ -125,6 +125,8 @@ var/obj/item/mod/module/module /// A reference to the mob we are pinned to. var/mob/pinner + /// Timer until we remove our cooldown overlay + var/cooldown_timer /datum/action/item_action/mod/pinned_module/New(Target, obj/item/mod/module/linked_module, mob/user) var/obj/item/mod/control/mod = Target @@ -141,11 +143,22 @@ check_flags = NONE name = "Activate [capitalize(linked_module.name)]" desc = "Quickly activate [linked_module]." - RegisterSignals(linked_module, list(COMSIG_MODULE_ACTIVATED, COMSIG_MODULE_DEACTIVATED, COMSIG_MODULE_USED), PROC_REF(module_interacted_with)) + RegisterSignals(linked_module, list( + COMSIG_MODULE_ACTIVATED, + COMSIG_MODULE_DEACTIVATED, + COMSIG_MODULE_USED, + ), PROC_REF(module_interacted_with)) + RegisterSignal(linked_module, COMSIG_MODULE_COOLDOWN_STARTED, PROC_REF(cooldown_started)) RegisterSignal(user, COMSIG_QDELETING, PROC_REF(pinner_deleted)) /datum/action/item_action/mod/pinned_module/Destroy() - UnregisterSignal(module, list(COMSIG_MODULE_ACTIVATED, COMSIG_MODULE_DEACTIVATED, COMSIG_MODULE_USED)) + deltimer(cooldown_timer) + UnregisterSignal(module, list( + COMSIG_MODULE_ACTIVATED, + COMSIG_MODULE_DEACTIVATED, + COMSIG_MODULE_COOLDOWN_STARTED, + COMSIG_MODULE_USED, + )) module.pinned_to -= REF(pinner) module = null pinner = null @@ -178,12 +191,19 @@ else if(module.active) current_button.add_overlay(image(icon = 'icons/hud/radial.dmi', icon_state = "module_active", layer = FLOAT_LAYER-0.1)) if(!COOLDOWN_FINISHED(module, cooldown_timer)) - var/image/cooldown_image = image(icon = 'icons/hud/radial.dmi', icon_state = "module_cooldown") - current_button.add_overlay(cooldown_image) - addtimer(CALLBACK(current_button, TYPE_PROC_REF(/image, cut_overlay), cooldown_image), COOLDOWN_TIMELEFT(module, cooldown_timer)) + current_button.add_overlay(image(icon = 'icons/hud/radial.dmi', icon_state = "module_cooldown")) return ..() /datum/action/item_action/mod/pinned_module/proc/module_interacted_with(datum/source) SIGNAL_HANDLER build_all_button_icons(UPDATE_BUTTON_OVERLAY|UPDATE_BUTTON_STATUS) + +/datum/action/item_action/mod/pinned_module/proc/cooldown_started(datum/source, cooldown_time) + SIGNAL_HANDLER + + deltimer(cooldown_timer) + build_all_button_icons(UPDATE_BUTTON_OVERLAY) + if (cooldown_time == 0) + return + cooldown_timer = addtimer(CALLBACK(src, PROC_REF(build_all_button_icons), UPDATE_BUTTON_OVERLAY), cooldown_time + 1, TIMER_STOPPABLE) diff --git a/code/modules/mod/mod_theme.dm b/code/modules/mod/mod_theme.dm index aa22f8d9950..716860db2de 100644 --- a/code/modules/mod/mod_theme.dm +++ b/code/modules/mod/mod_theme.dm @@ -949,6 +949,7 @@ default_skin = "syndicate" armor_type = /datum/armor/mod_theme_syndicate atom_flags = PREVENT_CONTENTS_EXPLOSION_1 + complexity_max = DEFAULT_MAX_COMPLEXITY + 3 max_heat_protection_temperature = FIRE_SUIT_MAX_TEMP_PROTECT siemens_coefficient = 0 slowdown_inactive = 1 @@ -1043,6 +1044,7 @@ resistance_flags = FIRE_PROOF|ACID_PROOF atom_flags = PREVENT_CONTENTS_EXPLOSION_1 max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT + complexity_max = DEFAULT_MAX_COMPLEXITY + 3 siemens_coefficient = 0 slowdown_inactive = 1 slowdown_active = 0.5 diff --git a/code/modules/mod/mod_types.dm b/code/modules/mod/mod_types.dm index 2f2be1dc86e..f11c6b9b4b9 100644 --- a/code/modules/mod/mod_types.dm +++ b/code/modules/mod/mod_types.dm @@ -231,12 +231,14 @@ /obj/item/mod/module/emp_shield, /obj/item/mod/module/magnetic_harness, /obj/item/mod/module/jetpack/advanced, + /obj/item/mod/module/jump_jet, /obj/item/mod/module/flashlight, /obj/item/mod/module/dna_lock, ) default_pins = list( /obj/item/mod/module/armor_booster, /obj/item/mod/module/jetpack/advanced, + /obj/item/mod/module/jump_jet, ) /obj/item/mod/control/pre_equipped/nuclear @@ -249,11 +251,13 @@ /obj/item/mod/module/emp_shield, /obj/item/mod/module/magnetic_harness, /obj/item/mod/module/jetpack/advanced, + /obj/item/mod/module/jump_jet, /obj/item/mod/module/flashlight, ) default_pins = list( /obj/item/mod/module/armor_booster, /obj/item/mod/module/jetpack/advanced, + /obj/item/mod/module/jump_jet, ) /obj/item/mod/control/pre_equipped/nuclear/plasmaman @@ -275,11 +279,13 @@ /obj/item/mod/module/emp_shield, /obj/item/mod/module/magnetic_harness, /obj/item/mod/module/jetpack/advanced, + /obj/item/mod/module/jump_jet, /obj/item/mod/module/flashlight, ) default_pins = list( /obj/item/mod/module/armor_booster, /obj/item/mod/module/jetpack/advanced, + /obj/item/mod/module/jump_jet, ) /obj/item/mod/control/pre_equipped/elite/flamethrower @@ -289,12 +295,14 @@ /obj/item/mod/module/magnetic_harness, /obj/item/mod/module/thermal_regulator, /obj/item/mod/module/jetpack/advanced, + /obj/item/mod/module/jump_jet, /obj/item/mod/module/flashlight, /obj/item/mod/module/flamethrower, ) default_pins = list( /obj/item/mod/module/armor_booster, /obj/item/mod/module/jetpack/advanced, + /obj/item/mod/module/jump_jet, /obj/item/mod/module/flamethrower, ) diff --git a/code/modules/mod/modules/_module.dm b/code/modules/mod/modules/_module.dm index 882796704bc..070d8127c5e 100644 --- a/code/modules/mod/modules/_module.dm +++ b/code/modules/mod/modules/_module.dm @@ -84,6 +84,13 @@ on_use() SEND_SIGNAL(mod, COMSIG_MOD_MODULE_SELECTED, src) +/// Apply a cooldown until this item can be used again +/obj/item/mod/module/proc/start_cooldown(applied_cooldown) + if (isnull(applied_cooldown)) + applied_cooldown = cooldown_time + COOLDOWN_START(src, cooldown_timer, applied_cooldown) + SEND_SIGNAL(src, COMSIG_MODULE_COOLDOWN_STARTED, applied_cooldown) + /// Called when the module is activated /obj/item/mod/module/proc/on_activation() if(!COOLDOWN_FINISHED(src, cooldown_timer)) @@ -116,8 +123,8 @@ update_signal(used_button) balloon_alert(mod.wearer, "[src] activated, [used_button]-click to use") active = TRUE - COOLDOWN_START(src, cooldown_timer, cooldown_time) mod.wearer.update_clothing(mod.slot_flags) + start_cooldown() SEND_SIGNAL(src, COMSIG_MODULE_ACTIVATED) return TRUE @@ -153,7 +160,7 @@ return FALSE if(SEND_SIGNAL(src, COMSIG_MODULE_TRIGGERED, mod.wearer) & MOD_ABORT_USE) return FALSE - COOLDOWN_START(src, cooldown_timer, cooldown_time) + 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 mod.wearer.update_clothing(mod.slot_flags) SEND_SIGNAL(src, COMSIG_MODULE_USED) diff --git a/code/modules/mod/modules/modules_general.dm b/code/modules/mod/modules/modules_general.dm index f64d808b7a7..e0794511396 100644 --- a/code/modules/mod/modules/modules_general.dm +++ b/code/modules/mod/modules/modules_general.dm @@ -169,12 +169,54 @@ /obj/item/mod/module/jetpack/advanced name = "MOD advanced ion jetpack module" desc = "An improvement on the previous model of electric thrusters. This one achieves higher speeds through \ - mounting of more jets and a red paint applied on it." + mounting of more jets and application of red paint." icon_state = "jetpack_advanced" overlay_state_inactive = "module_jetpackadv" overlay_state_active = "module_jetpackadv_on" full_speed = TRUE +/// Cooldown to use if we didn't actually launch a jump jet +#define FAILED_ACTIVATION_COOLDOWN 3 SECONDS + +///Jump Jet - Briefly removes the effect of gravity and pushes you up one z-level if possible. +/obj/item/mod/module/jump_jet + name = "MOD ionic jump jet module" + desc = "A specialised ionic thruster which provides a short but powerful boost capable of pushing against gravity, \ + after which time it needs to recharge." + icon_state = "jump_jet" + module_type = MODULE_USABLE + complexity = 3 + cooldown_time = 30 SECONDS + use_power_cost = DEFAULT_CHARGE_DRAIN * 5 + incompatible_modules = list(/obj/item/mod/module/jump_jet) + +/obj/item/mod/module/jump_jet/on_use() + . = ..() + if (!.) + return FALSE + if (DOING_INTERACTION(mod.wearer, mod.wearer)) + balloon_alert(mod.wearer, "busy!") + return + balloon_alert(mod.wearer, "launching...") + mod.wearer.Shake(duration = 1 SECONDS) + if (!do_after(mod.wearer, 1 SECONDS, target = mod.wearer)) + start_cooldown(FAILED_ACTIVATION_COOLDOWN) // Don't go on full cooldown if we failed to launch + return FALSE + playsound(mod.wearer, 'sound/vehicles/rocketlaunch.ogg', 100, TRUE) + mod.wearer.apply_status_effect(/datum/status_effect/jump_jet) + var/turf/launch_from = get_turf(mod.wearer) + if (mod.wearer.zMove(UP, z_move_flags = ZMOVE_CHECK_PULLS)) + launch_from.visible_message(span_warning("[mod.wearer] rockets into the air!")) + new /obj/effect/temp_visual/jet_plume(launch_from) + + if (!HAS_TRAIT(mod.wearer, TRAIT_JETPACKING)) + var/obj/item/mod/module/jetpack/linked_jetpack = locate() in mod.modules + if (!isnull(linked_jetpack)) + linked_jetpack.on_activation() + return TRUE + +#undef FAILED_ACTIVATION_COOLDOWN + ///Status Readout - Puts a lot of information including health, nutrition, fingerprints, temperature to the suit TGUI. /obj/item/mod/module/status_readout name = "MOD status readout module" diff --git a/icons/effects/effects.dmi b/icons/effects/effects.dmi index f7615fc045b..bad30238246 100644 Binary files a/icons/effects/effects.dmi and b/icons/effects/effects.dmi differ diff --git a/icons/obj/clothing/modsuit/mod_modules.dmi b/icons/obj/clothing/modsuit/mod_modules.dmi index d548f615c44..f1d19c29da1 100644 Binary files a/icons/obj/clothing/modsuit/mod_modules.dmi and b/icons/obj/clothing/modsuit/mod_modules.dmi differ