diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm index 267b328fcf37..38d0e6035e89 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm @@ -151,3 +151,7 @@ /// Sent at the very end of human character setup #define COMSIG_HUMAN_CHARACTER_SETUP "after_human_setup" + +/// from /datum/status_effect/limp/proc/check_step() +#define COMSIG_CARBON_LIMPING "mob_limp_check" + #define COMPONENT_CANCEL_LIMP (1<<0) diff --git a/code/__DEFINES/living.dm b/code/__DEFINES/living.dm index d256bb7de448..fe79f7064cf1 100644 --- a/code/__DEFINES/living.dm +++ b/code/__DEFINES/living.dm @@ -66,6 +66,11 @@ /// The trait that determines if someone has the robotic limb reattachment quirk. #define TRAIT_ROBOTIC_LIMBATTACHMENT "trait_robotic_limbattachment" +/// Mob can walk despite having two disabled/missing legs so long as they have two of this trait. +/// Kind of jank, refactor at a later day when I can think of a better solution. +/// Just be sure to call update_limbless_locomotion() after applying / removal +#define TRAIT_NO_LEG_AID "no_leg_aid" + #define COLOR_BLOOD "#c90000" // Used in ready menu anominity diff --git a/code/datums/status_effects/wound_effects.dm b/code/datums/status_effects/wound_effects.dm index f7d640a6d1cf..afda360acbdd 100644 --- a/code/datums/status_effects/wound_effects.dm +++ b/code/datums/status_effects/wound_effects.dm @@ -70,6 +70,9 @@ if(!owner.client || owner.body_position == LYING_DOWN || !owner.has_gravity() || (owner.movement_type & (FLYING|FLOATING)) || forced || owner.buckled) return + if(SEND_SIGNAL(owner, COMSIG_CARBON_LIMPING, (next_leg || right || left)) & COMPONENT_CANCEL_LIMP) + return + // less limping while we have determination still var/determined_mod = owner.has_status_effect(/datum/status_effect/determined) ? 0.5 : 1 diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm index c33d482d345c..e97c3d9ba498 100644 --- a/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -329,6 +329,7 @@ GLOBAL_LIST_INIT(wood_recipes, list ( \ new/datum/stack_recipe("ore box", /obj/structure/ore_box, 4, time = 5 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_CONTAINERS),\ new/datum/stack_recipe("wooden crate", /obj/structure/closet/crate/wooden, 6, time = 5 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_FURNITURE),\ new/datum/stack_recipe("baseball bat", /obj/item/melee/baseball_bat, 5, time = 1.5 SECONDS, check_density = FALSE, category = CAT_WEAPON_MELEE),\ + new/datum/stack_recipe("wooden crutch", /obj/item/cane/crutch/wood, 5, time = 1.5 SECONDS, check_density = FALSE, category = CAT_WEAPON_MELEE),\ new/datum/stack_recipe("loom", /obj/structure/loom, 10, time = 1.5 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_TOOLS), \ new/datum/stack_recipe("mortar", /obj/item/reagent_containers/cup/mortar, 3, check_density = FALSE, category = CAT_CHEMISTRY), \ new/datum/stack_recipe("firebrand", /obj/item/match/firebrand, 2, time = 10 SECONDS, check_density = FALSE, category = CAT_TOOLS), \ diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm index 8209c47536e1..a8dd52a274b9 100644 --- a/code/game/objects/items/weaponry.dm +++ b/code/game/objects/items/weaponry.dm @@ -519,6 +519,28 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 playsound(src, 'sound/weapons/batonextend.ogg', 50, TRUE) return COMPONENT_NO_DEFAULT_MESSAGE +/obj/item/cane/crutch + name = "medical crutch" + desc = "A medical crutch used by people missing a leg. Not all that useful if you're missing both of them, though." + icon = 'icons/obj/weapons/staff.dmi' + icon_state = "crutch_med" + inhand_icon_state = "crutch_med" + lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi' + force = 12 + throwforce = 8 + w_class = WEIGHT_CLASS_BULKY + custom_materials = list(/datum/material/iron = SMALL_MATERIAL_AMOUNT * 0.5) + attack_verb_continuous = list("bludgeons", "whacks", "thrashes") + attack_verb_simple = list("bludgeon", "whack", "thrash") + +/obj/item/cane/crutch/wood + name = "wooden crutch" + desc = "A handmade crutch. Also makes a decent bludgeon if you need it." + icon_state = "crutch_wood" + inhand_icon_state = "crutch_wood" + custom_materials = list(/datum/material/wood = SMALL_MATERIAL_AMOUNT * 0.5) + /obj/item/staff name = "wizard staff" desc = "Apparently a staff used by the wizard." diff --git a/code/game/turfs/closed/walls.dm b/code/game/turfs/closed/walls.dm index 02e04557f420..df20ee846a79 100644 --- a/code/game/turfs/closed/walls.dm +++ b/code/game/turfs/closed/walls.dm @@ -51,6 +51,7 @@ return leaner.start_leaning(src) +// NON-MODULE CHANGE START /mob/living/proc/start_leaning(turf/closed/wall/wall) var/new_y = base_pixel_y + pixel_y var/new_x = base_pixel_x + pixel_x @@ -65,7 +66,7 @@ new_x -= LEANING_OFFSET animate(src, 0.2 SECONDS, pixel_x = new_x, pixel_y = new_y) - add_traits(list(TRAIT_UNDENSE, TRAIT_EXPANDED_FOV), LEANING_TRAIT) + add_traits(list(TRAIT_UNDENSE, TRAIT_EXPANDED_FOV, TRAIT_NO_LEG_AID), LEANING_TRAIT) visible_message( span_notice("[src] leans against [wall]."), span_notice("You lean against [wall]."), @@ -75,9 +76,16 @@ COMSIG_LIVING_DISARM_HIT, COMSIG_LIVING_GET_PULLED, COMSIG_MOVABLE_TELEPORTING, - COMSIG_ATOM_DIR_CHANGE, + COMSIG_LIVING_RESIST, ), PROC_REF(stop_leaning)) + RegisterSignal(src, COMSIG_ATOM_POST_DIR_CHANGE, PROC_REF(stop_leaning_dir)) update_fov() + update_limbless_locomotion() + +/mob/living/proc/stop_leaning_dir(datum/source, old_dir, new_dir) + SIGNAL_HANDLER + if(new_dir != old_dir) + stop_leaning() /mob/living/proc/stop_leaning() SIGNAL_HANDLER @@ -86,11 +94,14 @@ COMSIG_LIVING_DISARM_HIT, COMSIG_LIVING_GET_PULLED, COMSIG_MOVABLE_TELEPORTING, - COMSIG_ATOM_DIR_CHANGE, + COMSIG_ATOM_POST_DIR_CHANGE, + COMSIG_LIVING_RESIST, )) animate(src, 0.2 SECONDS, pixel_x = base_pixel_x, pixel_y = base_pixel_y) - remove_traits(list(TRAIT_UNDENSE, TRAIT_EXPANDED_FOV), LEANING_TRAIT) + remove_traits(list(TRAIT_UNDENSE, TRAIT_EXPANDED_FOV, TRAIT_NO_LEG_AID), LEANING_TRAIT) update_fov() + update_limbless_locomotion() +// NON-MODULE CHANGE END /turf/closed/wall/Initialize(mapload) . = ..() diff --git a/code/modules/mob/living/carbon/carbon_movement.dm b/code/modules/mob/living/carbon/carbon_movement.dm index 1a5b79bd86ab..5331a891362b 100644 --- a/code/modules/mob/living/carbon/carbon_movement.dm +++ b/code/modules/mob/living/carbon/carbon_movement.dm @@ -33,52 +33,25 @@ has_momentum = FALSE // NON-MODULE CHANGE END -/mob/living/carbon/set_usable_legs(new_value) - . = ..() - if(isnull(.)) - return - if(. == 0) - if(usable_legs != 0) //From having no usable legs to having some. - REMOVE_TRAIT(src, TRAIT_FLOORED, LACKING_LOCOMOTION_APPENDAGES_TRAIT) - REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, LACKING_LOCOMOTION_APPENDAGES_TRAIT) - else if(usable_legs == 0 && !(movement_type & (FLYING | FLOATING))) //From having usable legs to no longer having them. - ADD_TRAIT(src, TRAIT_FLOORED, LACKING_LOCOMOTION_APPENDAGES_TRAIT) - if(!usable_hands) - ADD_TRAIT(src, TRAIT_IMMOBILIZED, LACKING_LOCOMOTION_APPENDAGES_TRAIT) - - +// NON-MODULE CHANGE START /mob/living/carbon/set_usable_hands(new_value) . = ..() if(isnull(.)) return if(. == 0) REMOVE_TRAIT(src, TRAIT_HANDS_BLOCKED, LACKING_MANIPULATION_APPENDAGES_TRAIT) - if(usable_hands != 0) //From having no usable hands to having some. - REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, LACKING_LOCOMOTION_APPENDAGES_TRAIT) else if(usable_hands == 0 && default_num_hands > 0) //From having usable hands to no longer having them. ADD_TRAIT(src, TRAIT_HANDS_BLOCKED, LACKING_MANIPULATION_APPENDAGES_TRAIT) - if(!usable_legs && !(movement_type & (FLYING | FLOATING))) - ADD_TRAIT(src, TRAIT_IMMOBILIZED, LACKING_LOCOMOTION_APPENDAGES_TRAIT) /mob/living/carbon/on_movement_type_flag_enabled(datum/source, flag, old_movement_type) . = ..() if(movement_type & (FLYING | FLOATING) && !(old_movement_type & (FLYING | FLOATING))) - remove_movespeed_modifier(/datum/movespeed_modifier/limbless) - remove_traits(list(TRAIT_FLOORED, TRAIT_IMMOBILIZED), LACKING_LOCOMOTION_APPENDAGES_TRAIT) + update_limbless_locomotion() + update_limbless_movespeed_mod() /mob/living/carbon/on_movement_type_flag_disabled(datum/source, flag, old_movement_type) . = ..() if(old_movement_type & (FLYING | FLOATING) && !(movement_type & (FLYING | FLOATING))) - var/limbless_slowdown = 0 - if(usable_legs < default_num_legs) - limbless_slowdown += (default_num_legs - usable_legs) * 3 - if(!usable_legs) - ADD_TRAIT(src, TRAIT_FLOORED, LACKING_LOCOMOTION_APPENDAGES_TRAIT) - if(usable_hands < default_num_hands) - limbless_slowdown += (default_num_hands - usable_hands) * 3 - if(!usable_hands) - ADD_TRAIT(src, TRAIT_IMMOBILIZED, LACKING_LOCOMOTION_APPENDAGES_TRAIT) - if(limbless_slowdown) - add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/limbless, multiplicative_slowdown = limbless_slowdown) - else - remove_movespeed_modifier(/datum/movespeed_modifier/limbless) + update_limbless_locomotion() + update_limbless_movespeed_mod() +// NON-MODULE CHANGE END diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 6b28e33c06b4..5fc589f278d9 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -166,7 +166,7 @@ damage_text = "limp and lifeless" else damage_text = (body_part.brute_dam >= body_part.burn_dam) ? body_part.heavy_brute_msg : body_part.heavy_burn_msg - msg += "[capitalize(t_his)] [body_part.name] is [damage_text]!\n" + msg += "[capitalize(t_his)] [body_part.plaintext_zone] is [damage_text]!\n" //stores missing limbs var/l_limbs_missing = 0 diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 11d84be746a9..c910ba0f54ea 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -2269,6 +2269,7 @@ GLOBAL_LIST_EMPTY(fire_appearances) num_legs = new_value +// NON-MODULE CHANGE START ///Proc to modify the value of usable_legs and hook behavior associated to this event. /mob/living/proc/set_usable_legs(new_value) if(usable_legs == new_value) @@ -2277,19 +2278,23 @@ GLOBAL_LIST_EMPTY(fire_appearances) stack_trace("[src] had set_usable_legs() called on them with a negative value!") new_value = 0 - . = usable_legs + var/old_value = usable_legs usable_legs = new_value - if(new_value > .) // Gained leg usage. + update_limbless_locomotion() + update_limbless_movespeed_mod() + + return old_value + +/// Updates whether the mob is floored or immobilized based on how many limbs they have or are missing. +/mob/living/proc/update_limbless_locomotion() + if(usable_legs > 0 || (movement_type & (FLYING|FLOATING)) || COUNT_TRAIT_SOURCES(src, TRAIT_NO_LEG_AID) >= 2) REMOVE_TRAIT(src, TRAIT_FLOORED, LACKING_LOCOMOTION_APPENDAGES_TRAIT) REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, LACKING_LOCOMOTION_APPENDAGES_TRAIT) - else if(!(movement_type & (FLYING | FLOATING))) //Lost leg usage, not flying. - if(!usable_legs) - ADD_TRAIT(src, TRAIT_FLOORED, LACKING_LOCOMOTION_APPENDAGES_TRAIT) - if(!usable_hands) - ADD_TRAIT(src, TRAIT_IMMOBILIZED, LACKING_LOCOMOTION_APPENDAGES_TRAIT) - - update_limbless_movespeed_mod() + return + ADD_TRAIT(src, TRAIT_FLOORED, LACKING_LOCOMOTION_APPENDAGES_TRAIT) + if(usable_hands == 0) + ADD_TRAIT(src, TRAIT_IMMOBILIZED, LACKING_LOCOMOTION_APPENDAGES_TRAIT) /// Updates the mob's movespeed based on how many limbs they have or are missing. /mob/living/proc/update_limbless_movespeed_mod() @@ -2305,6 +2310,7 @@ GLOBAL_LIST_EMPTY(fire_appearances) add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/limbless, multiplicative_slowdown = limbless_slowdown) else remove_movespeed_modifier(/datum/movespeed_modifier/limbless) +// NON-MODULE CHANGE END ///Proc to modify the value of num_hands and hook behavior associated to this event. /mob/living/proc/set_num_hands(new_value) @@ -2314,18 +2320,24 @@ GLOBAL_LIST_EMPTY(fire_appearances) num_hands = new_value +// NON-MODULE CHANGE START ///Proc to modify the value of usable_hands and hook behavior associated to this event. /mob/living/proc/set_usable_hands(new_value) if(usable_hands == new_value) return - . = usable_hands + if(new_value < 0) // Sanity check + stack_trace("[src] had set_usable_hands() called on them with a negative value!") + new_value = 0 + + var/old_value = usable_hands usable_hands = new_value - if(new_value > .) // Gained hand usage. - REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, LACKING_LOCOMOTION_APPENDAGES_TRAIT) - else if(!(movement_type & (FLYING | FLOATING)) && !usable_hands && !usable_legs) //Lost a hand, not flying, no hands left, no legs. - ADD_TRAIT(src, TRAIT_IMMOBILIZED, LACKING_LOCOMOTION_APPENDAGES_TRAIT) + if(usable_legs < default_num_legs) + update_limbless_locomotion() + update_limbless_movespeed_mod() + return old_value +// NON-MODULE CHANGE END /// Whether or not this mob will escape from storages while being picked up/held. /mob/living/proc/will_escape_storage() diff --git a/icons/mob/inhands/weapons/melee_lefthand.dmi b/icons/mob/inhands/weapons/melee_lefthand.dmi index 79a362a00900..b2a0cd8a8d3a 100644 Binary files a/icons/mob/inhands/weapons/melee_lefthand.dmi and b/icons/mob/inhands/weapons/melee_lefthand.dmi differ diff --git a/icons/mob/inhands/weapons/melee_righthand.dmi b/icons/mob/inhands/weapons/melee_righthand.dmi index 222f8955396c..b04ce88aa257 100644 Binary files a/icons/mob/inhands/weapons/melee_righthand.dmi and b/icons/mob/inhands/weapons/melee_righthand.dmi differ diff --git a/icons/obj/weapons/staff.dmi b/icons/obj/weapons/staff.dmi index da97e484df96..88668654a75f 100644 Binary files a/icons/obj/weapons/staff.dmi and b/icons/obj/weapons/staff.dmi differ diff --git a/maplestation.dme b/maplestation.dme index d01fed6c5662..06937bed9c94 100644 --- a/maplestation.dme +++ b/maplestation.dme @@ -6259,6 +6259,7 @@ #include "maplestation_modules\code\modules\client\preferences\loadout_preference.dm" #include "maplestation_modules\code\modules\client\preferences\multiline_preferences.dm" #include "maplestation_modules\code\modules\client\preferences\name_preferences.dm" +#include "maplestation_modules\code\modules\client\preferences\paraplegic_aid.dm" #include "maplestation_modules\code\modules\client\preferences\ready_anominity.dm" #include "maplestation_modules\code\modules\client\preferences\runechat_color.dm" #include "maplestation_modules\code\modules\client\preferences\sound_frequency.dm" diff --git a/maplestation_modules/code/datums/components/limbless_aid.dm b/maplestation_modules/code/datums/components/limbless_aid.dm index fcd0be2f8ff0..9b035914afbb 100644 --- a/maplestation_modules/code/datums/components/limbless_aid.dm +++ b/maplestation_modules/code/datums/components/limbless_aid.dm @@ -1,9 +1,9 @@ /// Attach to items that help mobs missing limbs move faster when held. /datum/component/limbless_aid /// What slot flags must the parent item have to provide the bonus? - var/required_slot = ITEM_SLOT_HANDS + var/required_slot /// How much should the movespeed be modified? - var/movespeed_mod = 0.5 + var/movespeed_mod /datum/component/limbless_aid/Initialize(required_slot = ITEM_SLOT_HANDS, movespeed_mod = 0.5) if(!isitem(parent)) @@ -15,6 +15,7 @@ /datum/component/limbless_aid/RegisterWithParent() RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, PROC_REF(on_equip)) RegisterSignal(parent, COMSIG_ITEM_DROPPED, PROC_REF(on_drop)) + RegisterSignal(parent, COMSIG_ATOM_EXAMINE, PROC_REF(examined)) var/obj/item/item_parent = parent if(isliving(item_parent.loc)) @@ -22,13 +23,19 @@ on_equip(parent, wearer, wearer.get_slot_by_item(parent)) /datum/component/limbless_aid/UnregisterFromParent() - UnregisterSignal(parent, list(COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED)) + UnregisterSignal(parent, list(COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED, COMSIG_ATOM_EXAMINE)) var/obj/item/item_parent = parent if(isliving(item_parent.loc)) - var/mob/living/wearer = item_parent.loc - UnregisterSignal(wearer, COMSIG_LIVING_LIMBLESS_MOVESPEED_UPDATE) - wearer.update_limbless_movespeed_mod() + on_drop(item_parent, item_parent.loc) + +/datum/component/limbless_aid/proc/examined(obj/item/source, mob/living/user, list/examine_list) + SIGNAL_HANDLER + + examine_list += span_info("It will support your weight, allowing you to move faster with a wounded, disabled, or missing leg.") + examine_list += span_info("Holding two will allow you to walk despite having two missing or disabled legs.") + examine_list += span_info("Resisting will brace you, allowing you to stand on one support, \ + despite having two missing or disabled legs. Moving will cancel this effect.") /datum/component/limbless_aid/proc/on_equip(obj/item/source, mob/living/user, slot) SIGNAL_HANDLER @@ -36,16 +43,88 @@ if(!(slot & required_slot)) return + add_support(user) + +/datum/component/limbless_aid/proc/add_support(mob/living/user) + ADD_TRAIT(user, TRAIT_NO_LEG_AID, "[REF(src)]_aid") RegisterSignal(user, COMSIG_LIVING_LIMBLESS_MOVESPEED_UPDATE, PROC_REF(modify_movespeed), override = TRUE) + RegisterSignal(user, COMSIG_CARBON_LIMPING, PROC_REF(limp_check), override = TRUE) + RegisterSignal(user, COMSIG_LIVING_RESIST, PROC_REF(self_brace), override = TRUE) + user.update_limbless_locomotion() user.update_limbless_movespeed_mod() /datum/component/limbless_aid/proc/on_drop(obj/item/source, mob/living/user) SIGNAL_HANDLER + lose_support(user) + +/datum/component/limbless_aid/proc/lose_support(mob/living/user) + REMOVE_TRAIT(user, TRAIT_NO_LEG_AID, "[REF(src)]_aid") + un_self_brace(user) UnregisterSignal(user, COMSIG_LIVING_LIMBLESS_MOVESPEED_UPDATE) + UnregisterSignal(user, COMSIG_CARBON_LIMPING) + UnregisterSignal(user, COMSIG_LIVING_RESIST) + user.update_limbless_locomotion() user.update_limbless_movespeed_mod() /datum/component/limbless_aid/proc/modify_movespeed(mob/living/source, list/modifiers) SIGNAL_HANDLER - modifiers += movespeed_mod + var/obj/item/bodypart/leg = get_braced_leg(source) + if(isnull(leg) || leg.bodypart_disabled) + modifiers += movespeed_mod + +/datum/component/limbless_aid/proc/limp_check(mob/living/source, obj/item/bodypart/next_leg) + SIGNAL_HANDLER + + var/obj/item/bodypart/leg = get_braced_leg(source) + if(isnull(leg) || leg == next_leg) + return COMPONENT_CANCEL_LIMP + +#define IS_RIGHT_ARM(index) (index % 2 == 0) + +/// Checks what side the item is equipped on +/datum/component/limbless_aid/proc/get_braced_leg(mob/living/who) + if(required_slot & ITEM_SLOT_HANDS) + // note this is backwards intentionally: + // right arm braces the left leg, and left arm braces right leg + var/side = IS_RIGHT_ARM(who.get_held_index_of_item(parent)) ? BODY_ZONE_L_LEG : BODY_ZONE_R_LEG + return who.get_bodypart(side) + + return null // unimplemented + +#undef IS_RIGHT_ARM + +/datum/component/limbless_aid/proc/self_brace(mob/living/source) + SIGNAL_HANDLER + + INVOKE_ASYNC(src, PROC_REF(self_brace_async), source) + +/datum/component/limbless_aid/proc/un_self_brace(mob/living/source) + REMOVE_TRAIT(source, TRAIT_NO_LEG_AID, "[REF(src)]_brace") + UnregisterSignal(source, COMSIG_MOVABLE_MOVED) + +/datum/component/limbless_aid/proc/self_brace_async(mob/living/source) + if((required_slot & ITEM_SLOT_HANDS) && parent != source.get_active_held_item()) + return + if(HAS_TRAIT_FROM(source, TRAIT_NO_LEG_AID, "[REF(src)]_brace")) + return + if(DOING_INTERACTION_WITH_TARGET(source, source)) + return + // lying down is a lot harder to get up from + if(!do_after(source, (source.body_position == LYING_DOWN ? 2.4 SECONDS : 0.8 SECONDS), source)) + return + + source.balloon_alert(source, "braced") + ADD_TRAIT(source, TRAIT_NO_LEG_AID, "[REF(src)]_brace") + RegisterSignal(source, COMSIG_MOVABLE_MOVED, PROC_REF(brace_moved)) + source.update_limbless_locomotion() + +/datum/component/limbless_aid/proc/brace_moved(mob/living/source, atom/old_loc) + SIGNAL_HANDLER + + if(source.loc == old_loc) + return + + un_self_brace(source) + source.update_limbless_locomotion() diff --git a/maplestation_modules/code/modules/client/preferences/paraplegic_aid.dm b/maplestation_modules/code/modules/client/preferences/paraplegic_aid.dm new file mode 100644 index 000000000000..5d5fcbfffbc3 --- /dev/null +++ b/maplestation_modules/code/modules/client/preferences/paraplegic_aid.dm @@ -0,0 +1,87 @@ +#define WHEELCHAIR_PREFERENCE "Wheelchair" +#define CRUTCHES_MED_PREFERENCE "Crutches (Medical)" +#define CRUTCHES_WOOD_PREFERENCE "Crutches (Wooden)" +#define NONE_PREFERENCE "None" + +/// Preference for paraplegics to choose how they get around. +/datum/preference/choiced/paraplegic_aid + category = PREFERENCE_CATEGORY_MANUALLY_RENDERED + savefile_key = "paraplegic_aid" + savefile_identifier = PREFERENCE_CHARACTER + can_randomize = FALSE + should_generate_icons = TRUE + +/datum/preference/choiced/paraplegic_aid/create_default_value() + return WHEELCHAIR_PREFERENCE + +/datum/preference/choiced/paraplegic_aid/init_possible_values() + return list(WHEELCHAIR_PREFERENCE, CRUTCHES_MED_PREFERENCE, CRUTCHES_WOOD_PREFERENCE, NONE_PREFERENCE) + +/datum/preference/choiced/paraplegic_aid/icon_for(value) + switch(value) + if(WHEELCHAIR_PREFERENCE) + return icon(/obj/item/wheelchair::icon, /obj/item/wheelchair::icon_state) + if(CRUTCHES_MED_PREFERENCE) + return icon(/obj/item/cane/crutch::icon, /obj/item/cane/crutch::icon_state) + if(CRUTCHES_WOOD_PREFERENCE) + return icon(/obj/item/cane/crutch/wood::icon, /obj/item/cane/crutch/wood::icon_state) + if(NONE_PREFERENCE) + return icon('icons/hud/screen_gen.dmi', "x") + + return icon('icons/effects/random_spawners.dmi', "questionmark") + +/datum/preference/choiced/paraplegic_aid/is_accessible(datum/preferences/preferences) + if(!..(preferences)) + return FALSE + + return /datum/quirk/paraplegic::name in preferences.all_quirks + +/datum/preference/choiced/paraplegic_aid/apply_to_human(mob/living/carbon/human/target, value) + return + +/datum/quirk_constant_data/paraplegic + associated_typepath = /datum/quirk/paraplegic + customization_options = list(/datum/preference/choiced/paraplegic_aid) + +// Overrides paraplegic normal add unique to do our own thing +/datum/quirk/paraplegic/add_unique(client/client_source) + + var/wheelchair_type = client_source?.prefs?.read_preference(/datum/preference/choiced/paraplegic_aid) || NONE_PREFERENCE + + switch(wheelchair_type) + if(WHEELCHAIR_PREFERENCE) + // Handle late joins being buckled to arrival shuttle chairs. + quirk_holder.buckled?.unbuckle_mob(quirk_holder) + + var/turf/holder_turf = get_turf(quirk_holder) + var/obj/structure/chair/spawn_chair = locate() in holder_turf + + var/obj/vehicle/ridden/wheelchair/wheels + // More than 5k score? you unlock the gamer wheelchair. + if(client_source?.get_award_status(/datum/award/score/hardcore_random) >= 5000) + wheels = new /obj/vehicle/ridden/wheelchair/gold(holder_turf) + else + wheels = new /obj/vehicle/ridden/wheelchair(holder_turf) + + // Makes spawning on the arrivals shuttle more consistent looking + if(spawn_chair) + wheels.setDir(spawn_chair.dir) + + wheels.buckle_mob(quirk_holder) + + // During the spawning process, they may have dropped what they were holding, due to the paralysis + // So put the things back in their hands. + for(var/obj/item/dropped_item in holder_turf) + if(dropped_item.fingerprintslast == quirk_holder.ckey) + quirk_holder.put_in_hands(dropped_item) + + if(CRUTCHES_MED_PREFERENCE, CRUTCHES_WOOD_PREFERENCE) + var/crutch_type = wheelchair_type == CRUTCHES_MED_PREFERENCE ? /obj/item/cane/crutch : /obj/item/cane/crutch/wood + var/turf/holder_turf = get_turf(quirk_holder) + for(var/hand in quirk_holder.held_items) + quirk_holder.put_in_hands(new crutch_type(holder_turf)) + +#undef WHEELCHAIR_PREFERENCE +#undef CRUTCHES_MED_PREFERENCE +#undef CRUTCHES_WOOD_PREFERENCE +#undef NONE_PREFERENCE diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/paraplegic_aid.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/paraplegic_aid.tsx new file mode 100644 index 000000000000..1a46a4c4b9cd --- /dev/null +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/paraplegic_aid.tsx @@ -0,0 +1,6 @@ +import { FeatureIconnedDropdownInput, FeatureWithIcons } from '../base'; + +export const paraplegic_aid: FeatureWithIcons = { + name: 'Paraplegia Aid', + component: FeatureIconnedDropdownInput, +};