From b4b9c6776d978b048dfa1297142d8c864196851b Mon Sep 17 00:00:00 2001 From: Ghom <42542238+Ghommie@users.noreply.github.com> Date: Thu, 28 Jul 2022 02:40:34 +0200 Subject: [PATCH] Ladders take left/right clicks to go up or down (+ extra balance and QOL) (#67913) You now left click to climb up and right click to climb down a ladder. A delay of 1 second has also been added, since otherwise it'd take only one click to immediately move vertically and would be much more spammable. Ghosts still use the old radials, because their right clicks are bound to the default byond popup menu. --- code/__DEFINES/do_afters.dm | 1 + code/_onclick/other_mobs.dm | 129 ++++++++--- .../objects/items/devices/chameleonproj.dm | 2 +- code/game/objects/obj_defense.dm | 2 +- code/game/objects/structures/ladders.dm | 211 ++++++++++++++---- .../awaymissions/mission_code/Cabin.dm | 19 +- code/modules/awaymissions/signpost.dm | 4 +- .../modules/awaymissions/super_secret_room.dm | 4 +- .../ruins/spaceruin_code/hilbertshotel.dm | 4 +- .../modules/mob/living/basic/basic_defense.dm | 9 +- .../mob/living/carbon/alien/alien_defense.dm | 4 +- .../mob/living/carbon/carbon_defense.dm | 5 +- .../mob/living/carbon/human/human_defense.dm | 4 +- code/modules/mob/living/living_defense.dm | 4 +- .../mob/living/silicon/ai/ai_defense.dm | 2 +- .../mob/living/silicon/robot/robot_defense.dm | 2 +- .../mob/living/silicon/silicon_defense.dm | 7 +- .../living/simple_animal/animal_defense.dm | 9 +- .../friendly/drone/interaction.dm | 3 + .../mob/living/simple_animal/slime/slime.dm | 4 +- 20 files changed, 319 insertions(+), 110 deletions(-) diff --git a/code/__DEFINES/do_afters.dm b/code/__DEFINES/do_afters.dm index 456cf940400..5b35e69d0fc 100644 --- a/code/__DEFINES/do_afters.dm +++ b/code/__DEFINES/do_afters.dm @@ -2,3 +2,4 @@ #define DOAFTER_SOURCE_MECHADRILL "doafter_mechadrill" #define DOAFTER_SOURCE_SURVIVALPEN "doafter_survivalpen" #define DOAFTER_SOURCE_GETTING_UP "doafter_gettingup" +#define DOAFTER_SOURCE_CLIMBING_LADDER "doafter_climbingladder" diff --git a/code/_onclick/other_mobs.dm b/code/_onclick/other_mobs.dm index ae0f7a89b00..2882139d7a4 100644 --- a/code/_onclick/other_mobs.dm +++ b/code/_onclick/other_mobs.dm @@ -1,13 +1,13 @@ -/// Checks for RIGHT_CLICK in modifiers and runs attack_hand_secondary if so. Returns TRUE if normal chain blocked +/// Checks for RIGHT_CLICK in modifiers and runs resolve_right_click_attack if so. Returns TRUE if normal chain blocked. /mob/living/proc/right_click_attack_chain(atom/target, list/modifiers) if (!LAZYACCESS(modifiers, RIGHT_CLICK)) return - var/secondary_result = target.attack_hand_secondary(src, modifiers) + var/secondary_result = resolve_right_click_attack(target, modifiers) if (secondary_result == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN || secondary_result == SECONDARY_ATTACK_CONTINUE_CHAIN) return TRUE else if (secondary_result != SECONDARY_ATTACK_CALL_NORMAL) - CRASH("attack_hand_secondary did not return a SECONDARY_ATTACK_* define.") + CRASH("resolve_right_click_attack (probably attack_hand_secondary) did not return a SECONDARY_ATTACK_* define.") /* Humans: @@ -37,7 +37,8 @@ if(!right_click_attack_chain(A, modifiers) && !dna?.species?.spec_unarmedattack(src, A, modifiers)) //Because species like monkeys dont use attack hand A.attack_hand(src, modifiers) - +/mob/living/carbon/human/resolve_right_click_attack(atom/target, list/modifiers) + return target.attack_hand_secondary(src, modifiers) /// Return TRUE to cancel other attack hand effects that respect it. Modifiers is the assoc list for click info such as if it was a right click. /atom/proc/attack_hand(mob/user, list/modifiers) @@ -124,16 +125,43 @@ /mob/living/UnarmedAttack(atom/attack_target, proximity_flag, list/modifiers) if(LIVING_UNARMED_ATTACK_BLOCKED(attack_target)) - return + return FALSE + if(!right_click_attack_chain(attack_target, modifiers)) + resolve_unarmed_attack(attack_target, modifiers) + return TRUE + +/** + * Called when the unarmed attack hasn't been stopped by the LIVING_UNARMED_ATTACK_BLOCKED macro or the right_click_attack_chain proc. + * This will call an attack proc that can vary from mob type to mob type on the target. + */ +/mob/living/proc/resolve_unarmed_attack(atom/attack_target, list/modifiers) attack_target.attack_animal(src, modifiers) +/** + * Called when an unarmed attack performed with right click hasn't been stopped by the LIVING_UNARMED_ATTACK_BLOCKED macro. + * This will call a secondary attack proc that can vary from mob type to mob type on the target. + * Sometimes, a target is interacted differently when right_clicked, in that case the secondary attack proc should return + * a SECONDARY_ATTACK_* value that's not SECONDARY_ATTACK_CALL_NORMAL. + * Otherwise, it should just return SECONDARY_ATTACK_CALL_NORMAL. Failure to do so will result in an exception (runtime error). + */ +/mob/living/proc/resolve_right_click_attack(atom/target, list/modifiers) + return target.attack_animal_secondary(src, modifiers) + /atom/proc/attack_animal(mob/user, list/modifiers) SEND_SIGNAL(src, COMSIG_ATOM_ATTACK_ANIMAL, user) +/** + * Called when a simple animal or basic mob right clicks an atom. + * Returns a SECONDARY_ATTACK_* value. + */ +/atom/proc/attack_animal_secondary(mob/user, list/modifiers) + return SECONDARY_ATTACK_CALL_NORMAL + +///Apparently this is only used by AI datums for basic mobs. A player controlling a basic mob will call attack_animal() when clicking another atom. /atom/proc/attack_basic_mob(mob/user, list/modifiers) SEND_SIGNAL(src, COMSIG_ATOM_ATTACK_BASIC_MOB, user) -///Attacked by monkey +///Attacked by monkey. It doesn't need its own *_secondary proc as it just uses attack_hand_secondary instead. /atom/proc/attack_paw(mob/user, list/modifiers) if(SEND_SIGNAL(src, COMSIG_ATOM_ATTACK_PAW, user, modifiers) & COMPONENT_CANCEL_ATTACK_CHAIN) return TRUE @@ -144,54 +172,85 @@ Aliens Defaults to same as monkey in most places */ -/mob/living/carbon/alien/UnarmedAttack(atom/attack_target, proximity_flag, list/modifiers) - if(LIVING_UNARMED_ATTACK_BLOCKED(attack_target)) - return +/mob/living/carbon/alien/resolve_unarmed_attack(atom/attack_target, list/modifiers) attack_target.attack_alien(src, modifiers) +/mob/living/carbon/alien/resolve_right_click_attack(atom/target, list/modifiers) + return target.attack_alien_secondary(src, modifiers) + /atom/proc/attack_alien(mob/living/carbon/alien/user, list/modifiers) attack_paw(user, modifiers) - return +/** + * Called when an alien right clicks an atom. + * Returns a SECONDARY_ATTACK_* value. + */ +/atom/proc/attack_alien_secondary(mob/living/carbon/alien/user, list/modifiers) + return SECONDARY_ATTACK_CALL_NORMAL // Babby aliens -/mob/living/carbon/alien/larva/UnarmedAttack(atom/attack_target, proximity_flag, list/modifiers) - if(LIVING_UNARMED_ATTACK_BLOCKED(attack_target)) - return - attack_target.attack_larva(src) +/mob/living/carbon/alien/larva/resolve_unarmed_attack(atom/attack_target, list/modifiers) + attack_target.attack_larva(src, modifiers) -/atom/proc/attack_larva(mob/user) +/mob/living/carbon/alien/larva/resolve_right_click_attack(atom/target, list/modifiers) + return target.attack_larva_secondary(src, modifiers) + +/atom/proc/attack_larva(mob/user, list/modifiers) return +/** + * Called when an alien larva right clicks an atom. + * Returns a SECONDARY_ATTACK_* value. + */ +/atom/proc/attack_larva_secondary(mob/user, list/modifiers) + return SECONDARY_ATTACK_CALL_NORMAL + /* Slimes Nothing happening here */ -/mob/living/simple_animal/slime/UnarmedAttack(atom/attack_target, proximity_flag, list/modifiers) - if(LIVING_UNARMED_ATTACK_BLOCKED(attack_target)) - return +/mob/living/simple_animal/slime/resolve_unarmed_attack(atom/attack_target, proximity_flag, list/modifiers) if(isturf(attack_target)) return ..() - attack_target.attack_slime(src) + attack_target.attack_slime(src, modifiers) -/atom/proc/attack_slime(mob/user) +/mob/living/simple_animal/slime/resolve_right_click_attack(atom/target, list/modifiers) + if(isturf(target)) + return ..() + return target.attack_slime_secondary(src, modifiers) + +/atom/proc/attack_slime(mob/user, list/modifiers) return +/** + * Called when a slime mob right clicks an atom (that is not a turf). + * Returns a SECONDARY_ATTACK_* value. + */ +/atom/proc/attack_slime_secondary(mob/user, list/modifiers) + return SECONDARY_ATTACK_CALL_NORMAL /* Drones */ -/mob/living/simple_animal/drone/UnarmedAttack(atom/attack_target, proximity_flag, list/modifiers) - if(LIVING_UNARMED_ATTACK_BLOCKED(attack_target)) - return + +/mob/living/simple_animal/drone/resolve_unarmed_attack(atom/attack_target, proximity_flag, list/modifiers) attack_target.attack_drone(src, modifiers) -/// Defaults to attack_hand or attack_hand_secondary. Override it when you don't want drones to do same stuff as humans. -/atom/proc/attack_drone(mob/living/simple_animal/drone/user, list/modifiers) - if(!user.right_click_attack_chain(src, modifiers)) - attack_hand(user, modifiers) +/mob/living/simple_animal/drone/resolve_right_click_attack(atom/target, list/modifiers) + return target.attack_drone_secondary(src, modifiers) +/// Defaults to attack_hand. Override it when you don't want drones to do same stuff as humans. +/atom/proc/attack_drone(mob/living/simple_animal/drone/user, list/modifiers) + attack_hand(user, modifiers) + +/** + * Called when a maintenance drone right clicks an atom. + * Defaults to attack_hand_secondary. + * When overriding it, remember that it ought to return a SECONDARY_ATTACK_* value. + */ +/atom/proc/attack_drone_secondary(mob/living/simple_animal/drone/user, list/modifiers) + return attack_hand_secondary(user, modifiers) /* Brain @@ -213,26 +272,28 @@ Simple animals */ -/mob/living/simple_animal/UnarmedAttack(atom/attack_target, proximity_flag, list/modifiers) - if(LIVING_UNARMED_ATTACK_BLOCKED(attack_target)) - return +/mob/living/simple_animal/resolve_unarmed_attack(atom/attack_target, list/modifiers) if(dextrous && (isitem(attack_target) || !combat_mode)) attack_target.attack_hand(src, modifiers) update_inv_hands() else return ..() +/mob/living/simple_animal/resolve_right_click_attack(atom/target, list/modifiers) + if(dextrous && (isitem(target) || !combat_mode)) + . = target.attack_hand_secondary(src, modifiers) + update_inv_hands() + else + return ..() /* Hostile animals */ -/mob/living/simple_animal/hostile/UnarmedAttack(atom/attack_target, proximity_flag, list/modifiers) - if(LIVING_UNARMED_ATTACK_BLOCKED(attack_target)) - return +/mob/living/simple_animal/hostile/resolve_unarmed_attack(atom/attack_target, list/modifiers) GiveTarget(attack_target) if(dextrous && (isitem(attack_target) || !combat_mode)) - ..() + return ..() else AttackingTarget(attack_target) diff --git a/code/game/objects/items/devices/chameleonproj.dm b/code/game/objects/items/devices/chameleonproj.dm index 343cabad61c..0d73b7b8613 100644 --- a/code/game/objects/items/devices/chameleonproj.dm +++ b/code/game/objects/items/devices/chameleonproj.dm @@ -136,7 +136,7 @@ /obj/effect/dummy/chameleon/attack_animal(mob/user, list/modifiers) master.disrupt() -/obj/effect/dummy/chameleon/attack_slime() +/obj/effect/dummy/chameleon/attack_slime(mob/user, list/modifiers) master.disrupt() /obj/effect/dummy/chameleon/attack_alien(mob/user, list/modifiers) diff --git a/code/game/objects/obj_defense.dm b/code/game/objects/obj_defense.dm index 9282f261896..5daee514f69 100644 --- a/code/game/objects/obj_defense.dm +++ b/code/game/objects/obj_defense.dm @@ -93,7 +93,7 @@ var/amt = max(0, ((force - (move_resist * MOVE_FORCE_CRUSH_RATIO)) / (move_resist * MOVE_FORCE_CRUSH_RATIO)) * 10) take_damage(amt, BRUTE) -/obj/attack_slime(mob/living/simple_animal/slime/user) +/obj/attack_slime(mob/living/simple_animal/slime/user, list/modifiers) if(!user.is_adult) return attack_generic(user, rand(10, 15), BRUTE, MELEE, 1) diff --git a/code/game/objects/structures/ladders.dm b/code/game/objects/structures/ladders.dm index c737d7f4143..b24df6bfea2 100644 --- a/code/game/objects/structures/ladders.dm +++ b/code/game/objects/structures/ladders.dm @@ -9,8 +9,8 @@ var/obj/structure/ladder/down //the ladder below this one var/obj/structure/ladder/up //the ladder above this one var/crafted = FALSE - /// Optional travel time for ladder in deciseconds - var/travel_time = 0 + /// travel time for ladder in deciseconds + var/travel_time = 1 SECONDS /obj/structure/ladder/Initialize(mapload, obj/structure/ladder/up, obj/structure/ladder/down) ..() @@ -23,8 +23,22 @@ src.down = down down.up = src down.update_appearance() + + register_context() + return INITIALIZE_HINT_LATELOAD +/obj/structure/ladder/add_context(atom/source, list/context, obj/item/held_item, mob/user) + if(up) + context[SCREENTIP_CONTEXT_LMB] = "Climb up" + if(down) + context[SCREENTIP_CONTEXT_RMB] = "Climb down" + return CONTEXTUAL_SCREENTIP_SET + +/obj/structure/ladder/examine(mob/user) + . = ..() + . += span_info("Left-click it to start moving up; Right-click to start moving down.") + /obj/structure/ladder/Destroy(force) GLOB.ladders -= src disconnect() @@ -70,50 +84,89 @@ visible_message(span_danger("[src] is torn to pieces by the gravitational pull!")) qdel(src) -/obj/structure/ladder/proc/travel(going_up, mob/user, is_ghost, obj/structure/ladder/ladder) +/obj/structure/ladder/proc/use(mob/user, going_up = TRUE) + if(!in_range(src, user) || DOING_INTERACTION(user, DOAFTER_SOURCE_CLIMBING_LADDER)) + return + + if(!up && !down) + balloon_alert(user, "doesn't lead anywhere!") + return + if(going_up ? !up : !down) + balloon_alert(user, "can't go any further [going_up ? "up" : "down"]") + return + if(travel_time) + INVOKE_ASYNC(src, .proc/start_travelling, user, going_up) + else + travel(user, going_up) + add_fingerprint(user) + +/obj/structure/ladder/proc/start_travelling(mob/user, going_up) + show_initial_fluff_message(user, going_up) + if(do_after(user, travel_time, target = src, interaction_key = DOAFTER_SOURCE_CLIMBING_LADDER)) + travel(user, going_up) + +/// The message shown when the player starts climbing the ladder +/obj/structure/ladder/proc/show_initial_fluff_message(mob/user, going_up) + var/up_down = going_up ? "up" : "down" + user.balloon_alert_to_viewers("climbing [up_down]...") + +/obj/structure/ladder/proc/travel(mob/user, going_up = TRUE, is_ghost = FALSE) + var/obj/structure/ladder/ladder = going_up ? up : down + if(!ladder) + balloon_alert(user, "there's nothing that way!") + return var/response = SEND_SIGNAL(user, COMSIG_LADDER_TRAVEL, src, ladder, going_up) if(response & LADDER_TRAVEL_BLOCK) return - if(!is_ghost) - ladder.add_fingerprint(user) - if(!do_after(user, travel_time, target = src)) - return - show_fluff_message(going_up, user) - var/turf/target = get_turf(ladder) user.zMove(target = target, z_move_flags = ZMOVE_CHECK_PULLEDBY|ZMOVE_ALLOW_BUCKLED|ZMOVE_INCLUDE_PULLED) - ladder.use(user) //reopening ladder radial menu ahead -/obj/structure/ladder/proc/use(mob/user, is_ghost=FALSE) - if (!is_ghost && !in_range(src, user)) - return + if(!is_ghost) + show_final_fluff_message(user, ladder, going_up) + // to avoid having players hunt for the pixels of a ladder that goes through several stories and is + // partially covered by the sprites of their mobs, a radial menu will be displayed over them. + // this way players can keep climbing up or down with ease until they reach an end. + if(ladder.up && ladder.down) + ladder.show_options(user, is_ghost) + +/// The messages shown after the player has finished climbing. Players can see this happen from either src or the destination so we've 2 POVs here +/obj/structure/ladder/proc/show_final_fluff_message(mob/user, obj/structure/ladder/destination, going_up) + var/up_down = going_up ? "up" : "down" + + //POV of players around the source + visible_message(span_notice("[user] climbs [up_down] [src].")) + //POV of players around the destination + user.balloon_alert_to_viewers("climbed [up_down]") + +/// Shows a radial menu that players can use to climb up and down a stair. +/obj/structure/ladder/proc/show_options(mob/user, is_ghost = FALSE) var/list/tool_list = list() - if (up) - tool_list["Up"] = image(icon = 'icons/testing/turf_analysis.dmi', icon_state = "red_arrow", dir = NORTH) - if (down) - tool_list["Down"] = image(icon = 'icons/testing/turf_analysis.dmi', icon_state = "red_arrow", dir = SOUTH) - if (!length(tool_list)) - to_chat(user, span_warning("[src] doesn't seem to lead anywhere!")) - return + tool_list["Up"] = image(icon = 'icons/testing/turf_analysis.dmi', icon_state = "red_arrow", dir = NORTH) + tool_list["Down"] = image(icon = 'icons/testing/turf_analysis.dmi', icon_state = "red_arrow", dir = SOUTH) - var/result = show_radial_menu(user, src, tool_list, custom_check = CALLBACK(src, .proc/check_menu, user, is_ghost), require_near = !is_ghost, tooltips = TRUE) - if (!is_ghost && !in_range(src, user)) - return // nice try + var/datum/callback/check_menu + if(!is_ghost) + check_menu = CALLBACK(src, .proc/check_menu, user) + var/result = show_radial_menu(user, src, tool_list, custom_check = check_menu, require_near = !is_ghost, tooltips = TRUE) + + var/going_up switch(result) if("Up") - travel(TRUE, user, is_ghost, up) + going_up = TRUE if("Down") - travel(FALSE, user, is_ghost, down) + going_up = FALSE if("Cancel") return - if(!is_ghost) - add_fingerprint(user) + if(is_ghost || !travel_time) + travel(user, going_up, is_ghost) + else + INVOKE_ASYNC(src, .proc/start_travelling, user, going_up) /obj/structure/ladder/proc/check_menu(mob/user, is_ghost) - if(user.incapacitated() || (!user.Adjacent(src) && !is_ghost)) + if(user.incapacitated() || (!user.Adjacent(src))) return FALSE return TRUE @@ -123,39 +176,101 @@ return use(user) +/obj/structure/ladder/attack_hand_secondary(mob/user, list/modifiers) + . = ..() + if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN) + return + use(user, going_up = FALSE) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + +//Not be called when right clicking as a monkey. attack_hand_secondary() handles that. /obj/structure/ladder/attack_paw(mob/user, list/modifiers) - return use(user) + use(user) + return TRUE /obj/structure/ladder/attack_alien(mob/user, list/modifiers) - return use(user) + use(user) + return TRUE -/obj/structure/ladder/attack_larva(mob/user) - return use(user) +/obj/structure/ladder/attack_alien_secondary(mob/user, list/modifiers) + . = ..() + if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN) + return + use(user, going_up = FALSE) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN -/obj/structure/ladder/attack_animal(mob/user) - return use(user) +/obj/structure/ladder/attack_larva(mob/user, list/modifiers) + use(user) + return TRUE -/obj/structure/ladder/attack_slime(mob/user) - return use(user) +/obj/structure/ladder/attack_larva_secondary(mob/user, list/modifiers) + . = ..() + if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN) + return + use(user, going_up = FALSE) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN -/obj/structure/ladder/attackby(obj/item/W, mob/user, params) - return use(user) +/obj/structure/ladder/attack_animal(mob/user, list/modifiers) + use(user) + return TRUE -/obj/structure/ladder/attack_robot(mob/living/silicon/robot/R) - if(R.Adjacent(src)) - return use(R) +/obj/structure/ladder/attack_animal_secondary(mob/user, list/modifiers) + . = ..() + if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN) + return + use(user, going_up = FALSE) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + +/obj/structure/ladder/attack_slime(mob/user, list/modifiers) + use(user) + return TRUE + +/obj/structure/ladder/attack_slime_secondary(mob/user, list/modifiers) + . = ..() + if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN) + return + use(user, going_up = FALSE) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + +/obj/structure/ladder/attackby(obj/item/item, mob/user, params) + use(user) + return TRUE + +/obj/structure/ladder/attackby_secondary(obj/item/item, mob/user, params) + . = ..() + if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN) + return + use(user, going_up = FALSE) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + +/obj/structure/ladder/attack_robot(mob/living/silicon/robot/user) + if(user.Adjacent(src)) + use(user) + return TRUE + +/obj/structure/ladder/attack_robot_secondary(mob/living/silicon/robot/user) + . = ..() + if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN || !user.Adjacent(src)) + return SECONDARY_ATTACK_CONTINUE_CHAIN + use(user, going_up = FALSE) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN //ATTACK GHOST IGNORING PARENT RETURN VALUE /obj/structure/ladder/attack_ghost(mob/dead/observer/user) - use(user, TRUE) + ghost_use(user) return ..() -/obj/structure/ladder/proc/show_fluff_message(going_up, mob/user) - if(going_up) - user.visible_message(span_notice("[user] climbs up [src]."), span_notice("You climb up [src].")) - else - user.visible_message(span_notice("[user] climbs down [src]."), span_notice("You climb down [src].")) - +///Ghosts use the byond default popup menu function on right click, so this is going to work a little differently for them. +/obj/structure/ladder/proc/ghost_use(mob/user) + if (!up && !down) + balloon_alert(user, "doesn't lead anywhere!") + return + if(!up) //only goes down + travel(user, going_up = FALSE, is_ghost = TRUE) + else if(!down) //only goes up + travel(user, going_up = TRUE, is_ghost = TRUE) + else //goes both ways + show_options(user, is_ghost = TRUE) // Indestructible away mission ladders which link based on a mapped ID and height value rather than X/Y/Z. /obj/structure/ladder/unbreakable diff --git a/code/modules/awaymissions/mission_code/Cabin.dm b/code/modules/awaymissions/mission_code/Cabin.dm index 560942117a6..de3c1010f7e 100644 --- a/code/modules/awaymissions/mission_code/Cabin.dm +++ b/code/modules/awaymissions/mission_code/Cabin.dm @@ -114,11 +114,22 @@ . = ..() AddElement(/datum/element/update_icon_blocker) -/obj/structure/ladder/unbreakable/rune/show_fluff_message(up,mob/user) - user.visible_message(span_notice("[user] activates \the [src]."), span_notice("You activate \the [src].")) +/obj/structure/ladder/add_context(atom/source, list/context, obj/item/held_item, mob/user) + if(up) + context[SCREENTIP_CONTEXT_LMB] = "Warp up" + if(down) + context[SCREENTIP_CONTEXT_RMB] = "Warp down" + return CONTEXTUAL_SCREENTIP_SET -/obj/structure/ladder/unbreakable/rune/use(mob/user, is_ghost=FALSE) - if(is_ghost || !IS_WIZARD(user)) +/obj/structure/ladder/unbreakable/rune/show_initial_fluff_message(mob/user, going_up) + user.balloon_alert_to_viewers("activating...") + +/obj/structure/ladder/unbreakable/rune/show_final_fluff_message(mob/user, going_up) + visible_message(span_notice("[user] activates [src] and teleports away.")) + user.balloon_alert_to_viewers("warped in") + +/obj/structure/ladder/unbreakable/rune/use(mob/user, going_up = TRUE) + if(!IS_WIZARD(user)) ..() /*Cabin's forest. Removed in the new cabin map since it was buggy and I prefer manual placement.*/ diff --git a/code/modules/awaymissions/signpost.dm b/code/modules/awaymissions/signpost.dm index ea0d22ac39f..64aaca7aa99 100644 --- a/code/modules/awaymissions/signpost.dm +++ b/code/modules/awaymissions/signpost.dm @@ -39,14 +39,14 @@ /obj/structure/signpost/attack_hulk(mob/user) return -/obj/structure/signpost/attack_larva(mob/user) +/obj/structure/signpost/attack_larva(mob/user, list/modifiers) return interact(user) /obj/structure/signpost/attack_robot(mob/user) if (Adjacent(user)) return interact(user) -/obj/structure/signpost/attack_slime(mob/user) +/obj/structure/signpost/attack_slime(mob/user, list/modifiers) return interact(user) /obj/structure/signpost/attack_animal(mob/user, list/modifiers) diff --git a/code/modules/awaymissions/super_secret_room.dm b/code/modules/awaymissions/super_secret_room.dm index 83c85808256..fa29e662bc3 100644 --- a/code/modules/awaymissions/super_secret_room.dm +++ b/code/modules/awaymissions/super_secret_room.dm @@ -99,13 +99,13 @@ /obj/structure/speaking_tile/attack_hulk(mob/user) return -/obj/structure/speaking_tile/attack_larva(mob/user) +/obj/structure/speaking_tile/attack_larva(mob/user, list/modifiers) return interact(user) /obj/structure/speaking_tile/attack_ai(mob/user) return interact(user) -/obj/structure/speaking_tile/attack_slime(mob/user) +/obj/structure/speaking_tile/attack_slime(mob/user, list/modifiers) return interact(user) /obj/structure/speaking_tile/attack_animal(mob/user, list/modifiers) diff --git a/code/modules/mapfluff/ruins/spaceruin_code/hilbertshotel.dm b/code/modules/mapfluff/ruins/spaceruin_code/hilbertshotel.dm index c9d36928a65..383d78d76d5 100644 --- a/code/modules/mapfluff/ruins/spaceruin_code/hilbertshotel.dm +++ b/code/modules/mapfluff/ruins/spaceruin_code/hilbertshotel.dm @@ -307,10 +307,10 @@ GLOBAL_VAR_INIT(hhMysteryRoomNumber, rand(1, 999999)) /turf/closed/indestructible/hoteldoor/attack_hulk(mob/living/carbon/human/user) promptExit(user) -/turf/closed/indestructible/hoteldoor/attack_larva(mob/user) +/turf/closed/indestructible/hoteldoor/attack_larva(mob/user, list/modifiers) promptExit(user) -/turf/closed/indestructible/hoteldoor/attack_slime(mob/user) +/turf/closed/indestructible/hoteldoor/attack_slime(mob/user, list/modifiers) promptExit(user) /turf/closed/indestructible/hoteldoor/attack_robot(mob/user) diff --git a/code/modules/mob/living/basic/basic_defense.dm b/code/modules/mob/living/basic/basic_defense.dm index 06993b1d1ea..16bf15d46fd 100644 --- a/code/modules/mob/living/basic/basic_defense.dm +++ b/code/modules/mob/living/basic/basic_defense.dm @@ -87,7 +87,7 @@ log_combat(user, src, "attacked") return 1 -/mob/living/basic/attack_larva(mob/living/carbon/alien/larva/L) +/mob/living/basic/attack_larva(mob/living/carbon/alien/larva/L, list/modifiers) . = ..() if(. && stat != DEAD) //successful larva bite var/damage = rand(5, 10) @@ -107,7 +107,7 @@ var/damage = rand(user.melee_damage_lower, user.melee_damage_upper) return attack_threshold_check(damage, user.melee_damage_type) -/mob/living/basic/attack_slime(mob/living/simple_animal/slime/M) +/mob/living/basic/attack_slime(mob/living/simple_animal/slime/M, list/modifiers) if(..()) //successful slime attack var/damage = rand(15, 25) if(M.is_adult) @@ -119,6 +119,11 @@ return return ..() +/mob/living/basic/attack_drone_secondary(mob/living/simple_animal/drone/M) + if(M.combat_mode) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + return ..() + /mob/living/basic/proc/attack_threshold_check(damage, damagetype = BRUTE, armorcheck = MELEE, actuallydamage = TRUE) var/temp_damage = damage if(!damage_coeff[damagetype]) diff --git a/code/modules/mob/living/carbon/alien/alien_defense.dm b/code/modules/mob/living/carbon/alien/alien_defense.dm index 2b2ede04d64..fe613aaaa63 100644 --- a/code/modules/mob/living/carbon/alien/alien_defense.dm +++ b/code/modules/mob/living/carbon/alien/alien_defense.dm @@ -43,7 +43,7 @@ In all, this is a lot like the monkey code. /N -/mob/living/carbon/alien/attack_larva(mob/living/carbon/alien/larva/L) +/mob/living/carbon/alien/attack_larva(mob/living/carbon/alien/larva/L, list/modifiers) return attack_alien(L) @@ -91,7 +91,7 @@ In all, this is a lot like the monkey code. /N if(STAMINA) adjustStaminaLoss(damage) -/mob/living/carbon/alien/attack_slime(mob/living/simple_animal/slime/M) +/mob/living/carbon/alien/attack_slime(mob/living/simple_animal/slime/M, list/modifiers) if(..()) //successful slime attack var/damage = rand(5, 35) if(M.is_adult) diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm index f1270a9f3e9..48b527a4b8c 100644 --- a/code/modules/mob/living/carbon/carbon_defense.dm +++ b/code/modules/mob/living/carbon/carbon_defense.dm @@ -144,6 +144,9 @@ /mob/living/carbon/attack_drone(mob/living/simple_animal/drone/user) return //so we don't call the carbon's attack_hand(). +/mob/living/carbon/attack_drone_secondary(mob/living/simple_animal/drone/user) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + //ATTACK HAND IGNORING PARENT RETURN VALUE /mob/living/carbon/attack_hand(mob/living/carbon/human/user, list/modifiers) @@ -199,7 +202,7 @@ return TRUE -/mob/living/carbon/attack_slime(mob/living/simple_animal/slime/M) +/mob/living/carbon/attack_slime(mob/living/simple_animal/slime/M, list/modifiers) if(..()) //successful slime attack if(M.powerlevel > 0) var/stunprob = M.powerlevel * 7 + 10 // 17 at level 1, 80 at level 10 diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 3005e0dc511..3cecdb6350c 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -321,7 +321,7 @@ -/mob/living/carbon/human/attack_larva(mob/living/carbon/alien/larva/L) +/mob/living/carbon/human/attack_larva(mob/living/carbon/alien/larva/L, list/modifiers) . = ..() if(!.) return //successful larva bite. @@ -375,7 +375,7 @@ apply_damage(damage, user.melee_damage_type, affecting, armor, wound_bonus = user.wound_bonus, bare_wound_bonus = user.bare_wound_bonus, sharpness = user.sharpness, attack_direction = attack_direction) -/mob/living/carbon/human/attack_slime(mob/living/simple_animal/slime/M) +/mob/living/carbon/human/attack_slime(mob/living/simple_animal/slime/M, list/modifiers) . = ..() if(!.) // slime attack failed return diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index e080475e1af..6d99a50b09a 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -208,7 +208,7 @@ return TRUE -/mob/living/attack_slime(mob/living/simple_animal/slime/M) +/mob/living/attack_slime(mob/living/simple_animal/slime/M, list/modifiers) if(!SSticker.HasRoundStarted()) to_chat(M, "You cannot attack people before the game has started.") return @@ -315,7 +315,7 @@ return FALSE -/mob/living/attack_larva(mob/living/carbon/alien/larva/L) +/mob/living/attack_larva(mob/living/carbon/alien/larva/L, list/modifiers) if(L.combat_mode) if(HAS_TRAIT(L, TRAIT_PACIFISM)) to_chat(L, span_warning("You don't want to hurt anyone!")) diff --git a/code/modules/mob/living/silicon/ai/ai_defense.dm b/code/modules/mob/living/silicon/ai/ai_defense.dm index 17e894ccc9f..5124f5c221e 100644 --- a/code/modules/mob/living/silicon/ai/ai_defense.dm +++ b/code/modules/mob/living/silicon/ai/ai_defense.dm @@ -17,7 +17,7 @@ return ..() -/mob/living/silicon/ai/attack_slime(mob/living/simple_animal/slime/user) +/mob/living/silicon/ai/attack_slime(mob/living/simple_animal/slime/user, list/modifiers) return //immune to slimes /mob/living/silicon/ai/blob_act(obj/structure/blob/B) diff --git a/code/modules/mob/living/silicon/robot/robot_defense.dm b/code/modules/mob/living/silicon/robot/robot_defense.dm index 721ab6422f7..f24136d4757 100644 --- a/code/modules/mob/living/silicon/robot/robot_defense.dm +++ b/code/modules/mob/living/silicon/robot/robot_defense.dm @@ -204,7 +204,7 @@ GLOBAL_LIST_INIT(blacklisted_borg_hats, typecacheof(list( //Hats that don't real ..() return -/mob/living/silicon/robot/attack_slime(mob/living/simple_animal/slime/M) +/mob/living/silicon/robot/attack_slime(mob/living/simple_animal/slime/M, list/modifiers) if(..()) //successful slime shock flash_act() var/stunprob = M.powerlevel * 7 + 10 diff --git a/code/modules/mob/living/silicon/silicon_defense.dm b/code/modules/mob/living/silicon/silicon_defense.dm index 7370930b811..587d3410cb3 100644 --- a/code/modules/mob/living/silicon/silicon_defense.dm +++ b/code/modules/mob/living/silicon/silicon_defense.dm @@ -45,7 +45,7 @@ /mob/living/silicon/attack_paw(mob/living/user, list/modifiers) return attack_hand(user, modifiers) -/mob/living/silicon/attack_larva(mob/living/carbon/alien/larva/L) +/mob/living/silicon/attack_larva(mob/living/carbon/alien/larva/L, list/modifiers) if(!L.combat_mode) visible_message(span_notice("[L.name] rubs its head against [src].")) @@ -85,6 +85,11 @@ return return ..() +/mob/living/silicon/attack_drone_secondary(mob/living/simple_animal/drone/M) + if(M.combat_mode) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + return ..() + /mob/living/silicon/electrocute_act(shock_damage, source, siemens_coeff = 1, flags = NONE) if(buckled_mobs) for(var/mob/living/M in buckled_mobs) diff --git a/code/modules/mob/living/simple_animal/animal_defense.dm b/code/modules/mob/living/simple_animal/animal_defense.dm index 3610bc8633a..7301344cc71 100644 --- a/code/modules/mob/living/simple_animal/animal_defense.dm +++ b/code/modules/mob/living/simple_animal/animal_defense.dm @@ -84,7 +84,7 @@ log_combat(user, src, "attacked") return 1 -/mob/living/simple_animal/attack_larva(mob/living/carbon/alien/larva/L) +/mob/living/simple_animal/attack_larva(mob/living/carbon/alien/larva/L, list/modifiers) . = ..() if(. && stat != DEAD) //successful larva bite var/damage = rand(5, 10) @@ -104,7 +104,7 @@ var/damage = rand(user.melee_damage_lower, user.melee_damage_upper) return attack_threshold_check(damage, user.melee_damage_type) -/mob/living/simple_animal/attack_slime(mob/living/simple_animal/slime/M) +/mob/living/simple_animal/attack_slime(mob/living/simple_animal/slime/M, list/modifiers) if(..()) //successful slime attack var/damage = rand(15, 25) if(M.is_adult) @@ -116,6 +116,11 @@ return return ..() +/mob/living/simple_animal/attack_drone_secondary(mob/living/simple_animal/drone/M) + if(M.combat_mode) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + return ..() + /mob/living/simple_animal/proc/attack_threshold_check(damage, damagetype = BRUTE, armorcheck = MELEE, actuallydamage = TRUE) var/temp_damage = damage if(!damage_coeff[damagetype]) diff --git a/code/modules/mob/living/simple_animal/friendly/drone/interaction.dm b/code/modules/mob/living/simple_animal/friendly/drone/interaction.dm index 305c221f319..effd7faa3b0 100644 --- a/code/modules/mob/living/simple_animal/friendly/drone/interaction.dm +++ b/code/modules/mob/living/simple_animal/friendly/drone/interaction.dm @@ -28,6 +28,9 @@ else to_chat(drone, span_warning("You need to remain still to cannibalize [src]!")) +/mob/living/simple_animal/drone/attack_drone_secondary(mob/living/simple_animal/drone/drone) + return SECONDARY_ATTACK_CALL_NORMAL + //ATTACK HAND IGNORING PARENT RETURN VALUE /mob/living/simple_animal/drone/attack_hand(mob/user, list/modifiers) if(ishuman(user)) diff --git a/code/modules/mob/living/simple_animal/slime/slime.dm b/code/modules/mob/living/simple_animal/slime/slime.dm index 6e4c0cf8539..754e5e73d15 100644 --- a/code/modules/mob/living/simple_animal/slime/slime.dm +++ b/code/modules/mob/living/simple_animal/slime/slime.dm @@ -277,7 +277,7 @@ /mob/living/simple_animal/slime/attack_ui(slot, params) return -/mob/living/simple_animal/slime/attack_slime(mob/living/simple_animal/slime/M) +/mob/living/simple_animal/slime/attack_slime(mob/living/simple_animal/slime/M, list/modifiers) if(..()) //successful slime attack if(M == src) return @@ -304,7 +304,7 @@ if(..()) //successful monkey bite. attacked += 10 -/mob/living/simple_animal/slime/attack_larva(mob/living/carbon/alien/larva/L) +/mob/living/simple_animal/slime/attack_larva(mob/living/carbon/alien/larva/L, list/modifiers) if(..()) //successful larva bite. attacked += 10