mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-10 01:34:01 +00:00
Saddles, saddlebags, calvary (#2291)
<!-- Write **BELOW** The Headers and **ABOVE** The comments else it may not be viewable. --> <!-- You can view Contributing.MD for a detailed description of the pull request process. --> ## About The Pull Request Port of https://github.com/NovaSector/NovaSector/pull/3112, which is a continuation of a work I stopped development on Adds saddles, saddlebags, both of which can only be worn by quadruped taurs in the backslot Saddles allow taurs to be piggybacked with the rider having both hands free, saddlebags allow riders to have ONE hand free, have sueprior storage, but you can altclick the wearer to access the storage Saddles can be made from leather, saddles are avaialble in the secvend, and both saddles and saddlebags are in loadout Part of a taur rework thingy magig I originally made for nova Main design doc: https://hackmd.io/@NikoTheGuyDUde/rJ7C9HPe0 Quadruped design doc: https://hackmd.io/@NikoTheGuyDUde/rJzJiBPgC <!-- Describe The Pull Request. Please be sure every change is documented or this can delay review and even discourage maintainers from merging your PR! --> <!-- Please make sure to actually test your PRs. If you have not tested your PR mention it. --> ## Why It's Good For The Game Read the main design doc. In short, taurs have very exotic anatomy that isnt explored much, and the game would be greatly diversified if we added some mechanical differences. <!-- Argue for the merits of your changes and how they benefit the game, especially if they are controversial and/or far reaching. If you can't actually explain WHY what you are doing will improve the game, then it probably isn't good for the game in the first place. --> ## Proof Of Testing <!-- Compile and run your code locally. Make sure it works. This is the place to show off your changes! We are not responsible for testing your features. --> <details> <summary>Screenshots/Videos</summary> https://github.com/user-attachments/assets/c3a48127-0c54-4b62-a450-e14e210d1f56 </details> ## Changelog <!-- If your PR modifies aspects of the game that can be concretely observed by players or admins you should add a changelog. If your change does NOT meet this description, remove this section. Be sure to properly mark your PRs to prevent unnecessary GBP loss. You can read up on GBP and its effects on PRs in the tgstation guides for contributors. Please note that maintainers freely reserve the right to remove and add tags should they deem it appropriate. You can attempt to finagle the system all you want, but it's best to shoot for clear communication right off the bat. --> 🆑 add: Quadruped taurs can now wear saddles, which allow anyone to clickdrag themselves onto them to ride with free hands add: Saddlebags for quadruped taurs, which are one-handed saddles that allow anyone to access their storage by alt clicking the wearer /🆑 <!-- Both 🆑's are required for the changelog to work! You can put your name to the right of the first 🆑 if you want to overwrite your GitHub username as author ingame. --> <!-- You can use multiple of the same prefix (they're only used for the icon ingame) and delete the unneeded ones. Despite some of the tags, changelogs should generally represent how a player might be affected by the changes rather than a summary of the PR's contents. --> <!-- By opening a pull request. You have read and understood the repository rules located on the main README.md on this project. --> Co-authored-by: Waterpig <49160555+Majkl-J@users.noreply.github.com> Co-authored-by: The Sharkening <95130227+StrangeWeirdKitten@users.noreply.github.com>
This commit is contained in:
@@ -57,12 +57,12 @@
|
||||
#define HEADSMASH_BLOCK_ARMOR 20
|
||||
#define SUPLEX_TIMER 3 SECONDS
|
||||
|
||||
// alt-clicking a human as another human while grappling them tightly makes you try for grappling-based maneuvers.
|
||||
/// alt-clicking a human as another human while grappling them tightly makes you try for grappling-based maneuvers.
|
||||
/mob/living/carbon/human/click_alt(mob/user)
|
||||
if(!ishuman(user))
|
||||
return ..()
|
||||
var/mob/living/carbon/human/human_user = user
|
||||
if(human_user == src || !human_user.combat_mode || !human_user.dna.species.try_grab_maneuver(user, src))
|
||||
if(human_user != src && human_user.combat_mode && !human_user.dna.species.try_grab_maneuver(user, src))
|
||||
return CLICK_ACTION_BLOCKING
|
||||
|
||||
/// State check for grab maneuver - because you can't logically suplex a man if you've stopped grappling them.
|
||||
|
||||
4
code/__DEFINES/~~bubber_defines/item.dm
Normal file
4
code/__DEFINES/~~bubber_defines/item.dm
Normal file
@@ -0,0 +1,4 @@
|
||||
/// From base of /obj/item/mob_can_equip. (mob/living/M, slot, disable_warning, bypass_equip_delay_self, ignore_equipped, indirect_action)
|
||||
#define COMSIG_ITEM_MOB_CAN_EQUIP "item_mob_can_equip"
|
||||
/// Forces mob_can_equip to return FALSE.
|
||||
#define COMPONENT_ITEM_CANT_EQUIP (1<<10) // high to avoid flag conflict
|
||||
21
code/__DEFINES/~~bubber_defines/vehicles.dm
Normal file
21
code/__DEFINES/~~bubber_defines/vehicles.dm
Normal file
@@ -0,0 +1,21 @@
|
||||
// Defines for the vehicle component
|
||||
|
||||
/// For use in ride_check_flags. Prevents the piggyback slowdown, causes the riding offsets to be applied.
|
||||
#define RIDING_TAUR (1<<10) // high, to avoid flag conflict with tg)
|
||||
|
||||
// Vehicle offset defines
|
||||
|
||||
/// Applied when the ridee is oversized. Applied to front offsets.
|
||||
#define OVERSIZED_OFFSET 18
|
||||
/// Applied when the ridee is oversized. Applied to side offsets.
|
||||
#define OVERSIZED_SIDE_OFFSET 11
|
||||
/// Applied when the ridee is normal sized. Applies to front offsets.
|
||||
#define REGULAR_OFFSET 6
|
||||
/// Applied when the ridee is normal sized. Applies to side offsets.
|
||||
#define REGULAR_SIDE_OFFSET 4
|
||||
|
||||
/// Sent when a mob attempts to ride our saddle. Should return a bitfield containing riding flags, ex. RIDER_NEEDS_ARMS (mob/living/carbon)
|
||||
#define COMSIG_HUMAN_SADDLE_RIDE_ATTEMPT "human_saddle_ride_attempt"
|
||||
|
||||
/// If true, the saddled mob can have someone clickdragged onto them to be ridden.
|
||||
#define TRAIT_SADDLED "trait_saddled"
|
||||
@@ -1,11 +1,5 @@
|
||||
// For any mob that can be ridden
|
||||
|
||||
//SKYRAT EDIT START: Human Riding Defines
|
||||
#define OVERSIZED_OFFSET 18
|
||||
#define OVERSIZED_SIDE_OFFSET 11
|
||||
#define REGULAR_OFFSET 6
|
||||
#define REGULAR_SIDE_OFFSET 4
|
||||
//SKYRAT EDIT END
|
||||
/datum/component/riding/creature
|
||||
/// If TRUE, this creature's movements can be controlled by the rider while mounted (as opposed to riding cyborgs and humans, which is passive)
|
||||
var/can_be_driven = TRUE
|
||||
@@ -214,9 +208,13 @@
|
||||
/datum/component/riding/creature/human/Initialize(mob/living/riding_mob, force = FALSE, ride_check_flags = NONE, potion_boost = FALSE)
|
||||
. = ..()
|
||||
var/mob/living/carbon/human/human_parent = parent
|
||||
human_parent.add_movespeed_modifier(/datum/movespeed_modifier/human_carry)
|
||||
//human_parent.add_movespeed_modifier(/datum/movespeed_modifier/human_carry) // BUBBER EDIT REMOVAL
|
||||
// BUBBER EDIT ADDITION START - Taur saddles
|
||||
if (!(ride_check_flags & RIDING_TAUR))
|
||||
human_parent.add_movespeed_modifier(/datum/movespeed_modifier/human_carry)
|
||||
// BUBBER EDIT ADDITION END
|
||||
|
||||
if(ride_check_flags & RIDER_NEEDS_ARMS) // piggyback
|
||||
if(ride_check_flags & RIDER_NEEDS_ARMS || (ride_check_flags & RIDING_TAUR)) // BUBBER CHANGE - ORIGINAL: if(ride_check_flags & RIDER_NEEDS_ARMS) // piggyback
|
||||
human_parent.buckle_lying = 0
|
||||
// the riding mob is made nondense so they don't bump into any dense atoms the carrier is pulling,
|
||||
// since pulled movables are moved before buckled movables
|
||||
@@ -299,7 +297,13 @@
|
||||
|
||||
/datum/component/riding/creature/human/get_offsets(pass_index)
|
||||
var/mob/living/carbon/human/H = parent
|
||||
//SKYRAT EDIT BEGIN - Oversized Overhaul
|
||||
/* BUBBER EDIT REMOVAL START
|
||||
if(H.buckle_lying)
|
||||
return list(TEXT_NORTH = list(0, 6), TEXT_SOUTH = list(0, 6), TEXT_EAST = list(0, 6), TEXT_WEST = list(0, 6))
|
||||
else
|
||||
return list(TEXT_NORTH = list(0, 6), TEXT_SOUTH = list(0, 6), TEXT_EAST = list(-6, 4), TEXT_WEST = list( 6, 4))
|
||||
*/ // BUBBER EDIT REMOVAL END
|
||||
// BUBBER EDIT ADDITION BEGIN - Oversized Overhaul, Taur riding
|
||||
if(H.buckle_lying)
|
||||
return HAS_TRAIT(H, TRAIT_OVERSIZED) ? list(
|
||||
TEXT_NORTH = list(0, OVERSIZED_OFFSET),
|
||||
@@ -312,7 +316,7 @@
|
||||
TEXT_EAST = list(0, REGULAR_OFFSET),
|
||||
TEXT_WEST = list(0, REGULAR_OFFSET),
|
||||
)
|
||||
else
|
||||
else if (!(ride_check_flags & RIDING_TAUR)) // BUBBER EDIT CHANGE - ORIGINAL: else
|
||||
return HAS_TRAIT(H, TRAIT_OVERSIZED) ? list(
|
||||
TEXT_NORTH = list(0, OVERSIZED_OFFSET),
|
||||
TEXT_SOUTH = list(0, OVERSIZED_OFFSET),
|
||||
@@ -324,7 +328,12 @@
|
||||
TEXT_EAST = list(-REGULAR_OFFSET, REGULAR_SIDE_OFFSET),
|
||||
TEXT_WEST = list(REGULAR_OFFSET, REGULAR_SIDE_OFFSET)
|
||||
)
|
||||
//SKYRAT EDIT END
|
||||
|
||||
if (ride_check_flags & RIDING_TAUR)
|
||||
var/obj/item/organ/external/taur_body/taur_body = H.get_organ_slot(ORGAN_SLOT_EXTERNAL_TAUR)
|
||||
return taur_body.get_riding_offset(oversized = HAS_TRAIT(H, TRAIT_OVERSIZED))
|
||||
//BUBBER EDIT END
|
||||
|
||||
/datum/component/riding/creature/human/force_dismount(mob/living/dismounted_rider)
|
||||
var/atom/movable/AM = parent
|
||||
AM.unbuckle_mob(dismounted_rider)
|
||||
|
||||
@@ -901,12 +901,12 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches)
|
||||
return open_storage_on_signal(source, user) ? CLICK_ACTION_SUCCESS : NONE
|
||||
|
||||
/// Opens the storage to the mob, showing them the contents to their UI.
|
||||
/datum/storage/proc/open_storage(mob/to_show)
|
||||
/datum/storage/proc/open_storage(mob/to_show, can_reach_target = parent) // BUBBER EDIT CHANGE - ORIGINAL: /datum/storage/proc/open_storage(mob/to_show)
|
||||
if(isobserver(to_show))
|
||||
show_contents(to_show)
|
||||
return FALSE
|
||||
|
||||
if(!isliving(to_show) || !to_show.can_perform_action(parent, ALLOW_RESTING | FORBID_TELEKINESIS_REACH))
|
||||
if(!isliving(to_show) || !to_show.can_perform_action(can_reach_target, ALLOW_RESTING | FORBID_TELEKINESIS_REACH)) // BUBBER EDIT CHANGE -- ORIGINAL: if(!isliving(to_show) || !to_show.can_perform_action(parent, ALLOW_RESTING | FORBID_TELEKINESIS_REACH))
|
||||
return FALSE
|
||||
|
||||
if(locked)
|
||||
|
||||
@@ -103,6 +103,7 @@ GLOBAL_LIST_INIT(skyrat_cloth_recipes, list(
|
||||
new/datum/stack_recipe("eyepatch wrap", /obj/item/clothing/glasses/eyepatch/wrap, 2, category = CAT_CLOTHING),
|
||||
new/datum/stack_recipe("eyepatch", /obj/item/clothing/glasses/eyepatch, 2, category = CAT_CLOTHING),
|
||||
new/datum/stack_recipe("xenoarch bag", /obj/item/storage/bag/xenoarch, 4, category = CAT_CONTAINERS),
|
||||
new/datum/stack_recipe("saddlebags", /obj/item/storage/backpack/saddlebags, 5, category = CAT_CONTAINERS),
|
||||
))
|
||||
|
||||
/obj/item/stack/sheet/cloth/get_main_recipes()
|
||||
@@ -119,6 +120,10 @@ GLOBAL_LIST_INIT(skyrat_leather_belt_recipes, list(
|
||||
new/datum/stack_recipe("medical bandolier", /obj/item/storage/belt/medbandolier, 5, category = CAT_CONTAINERS),
|
||||
new/datum/stack_recipe("gear harness", /obj/item/clothing/under/misc/skyrat/gear_harness, 6, category = CAT_CLOTHING),
|
||||
new/datum/stack_recipe("ammo pouch", /obj/item/storage/pouch/ammo, 4, category = CAT_CONTAINERS),
|
||||
new/datum/stack_recipe_list("saddles", list(
|
||||
new/datum/stack_recipe("riding saddle (normal)", /obj/item/riding_saddle/leather, 5, category = CAT_CLOTHING),
|
||||
new/datum/stack_recipe("riding saddle (peacekeeper)", /obj/item/riding_saddle/leather/peacekeeper, 5, category = CAT_CLOTHING),
|
||||
)),
|
||||
))
|
||||
|
||||
/obj/item/stack/sheet/leather/get_main_recipes()
|
||||
|
||||
@@ -85,6 +85,7 @@
|
||||
icon_state = "deer"
|
||||
taur_mode = STYLE_TAUR_HOOF
|
||||
alt_taur_mode = STYLE_TAUR_PAW
|
||||
organ_type = /obj/item/organ/external/taur_body/horselike/deer
|
||||
|
||||
/datum/sprite_accessory/taur/drake
|
||||
name = "Drake"
|
||||
|
||||
@@ -23,11 +23,46 @@
|
||||
/// If true, our sprite accessory will not render.
|
||||
var/hide_self
|
||||
|
||||
/// If true, this taur body allows a saddle to be equipped and used.
|
||||
var/can_use_saddle = FALSE
|
||||
|
||||
/// If true, can ride saddled taurs and be ridden by other taurs with this set to TRUE.
|
||||
var/can_ride_saddled_taurs = FALSE
|
||||
|
||||
/// When being ridden via saddle, how much the rider is offset on the x axis when facing west or east.
|
||||
var/riding_offset_side_x = 12
|
||||
/// When being ridden via saddle, how much the rider is offset on the y axis when facing west or east.
|
||||
var/riding_offset_side_y = 2
|
||||
|
||||
/// When being ridden via saddle, how much the rider is offset on the x axis when facing north or south.
|
||||
var/riding_offset_front_x = 0
|
||||
/// When being ridden via saddle, how much the rider is offset on the y axis when facing north or south.
|
||||
var/riding_offset_front_y = 5
|
||||
|
||||
/// Lazylist of (TEXT_DIR -> y offset) to be applied to taur-specific clothing that isn't specifically made for this sprite.
|
||||
var/list/taur_specific_clothing_y_offsets
|
||||
|
||||
/// When considering how much to offset our rider, we multiply size scaling against this.
|
||||
var/riding_offset_scaling_mult = 0.8
|
||||
|
||||
/obj/item/organ/external/taur_body/horselike
|
||||
can_use_saddle = TRUE
|
||||
|
||||
/obj/item/organ/external/taur_body/horselike/synth
|
||||
organ_flags = ORGAN_ROBOTIC
|
||||
|
||||
/obj/item/organ/external/taur_body/horselike/deer
|
||||
|
||||
/obj/item/organ/external/taur_body/horselike/deer/Initialize(mapload)
|
||||
. = ..()
|
||||
|
||||
taur_specific_clothing_y_offsets = list(
|
||||
TEXT_EAST = 3,
|
||||
TEXT_WEST = 3,
|
||||
TEXT_NORTH = 0,
|
||||
TEXT_SOUTH = 0,
|
||||
)
|
||||
|
||||
/obj/item/organ/external/taur_body/serpentine
|
||||
left_leg_name = "upper serpentine body"
|
||||
right_leg_name = "lower serpentine body"
|
||||
@@ -51,6 +86,8 @@
|
||||
left_leg_name = null
|
||||
right_leg_name = null
|
||||
|
||||
can_ride_saddled_taurs = TRUE
|
||||
|
||||
/obj/item/organ/external/taur_body/anthro/synth
|
||||
organ_flags = ORGAN_ROBOTIC
|
||||
|
||||
@@ -145,3 +182,14 @@
|
||||
|
||||
if(old_right_leg)
|
||||
QDEL_NULL(old_right_leg)
|
||||
|
||||
/obj/item/organ/external/taur_body/proc/get_riding_offset(oversized = FALSE)
|
||||
var/size_scaling = (owner.dna.features["body_size"] / BODY_SIZE_NORMAL) - 1
|
||||
var/scaling_mult = 1 + (size_scaling * riding_offset_scaling_mult)
|
||||
|
||||
return list(
|
||||
TEXT_NORTH = list(riding_offset_front_x, round((riding_offset_front_y + taur_specific_clothing_y_offsets?[TEXT_NORTH]) * scaling_mult, 1)),
|
||||
TEXT_SOUTH = list(riding_offset_front_x, round((riding_offset_front_y + taur_specific_clothing_y_offsets?[TEXT_SOUTH]) * scaling_mult, 1)),
|
||||
TEXT_EAST = list(round(-riding_offset_side_x * scaling_mult, 1), round((riding_offset_side_y + taur_specific_clothing_y_offsets?[TEXT_EAST]) * scaling_mult, 1)),
|
||||
TEXT_WEST = list(round(riding_offset_side_x * scaling_mult, 1), round((riding_offset_side_y + taur_specific_clothing_y_offsets?[TEXT_WEST]) * scaling_mult, 1)),
|
||||
)
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
// Any item with this component can have its storage accessed by alt clicking the wearer.
|
||||
/datum/component/accessable_storage
|
||||
|
||||
/datum/component/accessable_storage/Initialize()
|
||||
if (!isitem(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
/datum/component/accessable_storage/RegisterWithParent()
|
||||
RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, PROC_REF(parent_equipped))
|
||||
RegisterSignal(parent, COMSIG_STORAGE_STORED_ITEM, PROC_REF(parent_stored_item))
|
||||
RegisterSignal(parent, COMSIG_STORAGE_REMOVED_ITEM, PROC_REF(parent_removed_item))
|
||||
|
||||
/datum/component/accessable_storage/UnregisterFromParent()
|
||||
UnregisterSignal(parent, list(COMSIG_ITEM_EQUIPPED, COMSIG_STORAGE_STORED_ITEM, COMSIG_STORAGE_REMOVED_ITEM))
|
||||
|
||||
/// Signal handler for COMSIG_ITEM_EQUIPPED. Handles registering signals.
|
||||
/datum/component/accessable_storage/proc/parent_equipped(datum/signal_source, mob/equipper, slot)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if (isliving(equipper) && !(equipper.get_slot_by_item(parent) & (ITEM_SLOT_HANDS|ITEM_SLOT_POCKETS)))
|
||||
RegisterSignal(equipper, COMSIG_MOB_UNEQUIPPED_ITEM, PROC_REF(mob_unequipped_item))
|
||||
RegisterSignal(equipper, COMSIG_CLICK_ALT, PROC_REF(mob_alt_clicked_on))
|
||||
|
||||
/// Signal handler for COMSIG_CLICK_ALT. Handles the actual opening of storage.
|
||||
/datum/component/accessable_storage/proc/mob_alt_clicked_on(mob/signal_source, mob/clicker)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
var/obj/item/item_parent = parent
|
||||
item_parent.atom_storage?.open_storage(clicker, signal_source)
|
||||
animate_target(signal_source)
|
||||
|
||||
/// Signal handler for COMSIG_MOB_UNEQUIPPED_ITEM. Handles unregistering signals.
|
||||
/datum/component/accessable_storage/proc/mob_unequipped_item(mob/signal_source, obj/item/item, force, atom/newloc, no_move, invdrop, silent)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if (item == parent)
|
||||
UnregisterSignal(signal_source, list(COMSIG_MOB_UNEQUIPPED_ITEM, COMSIG_CLICK_ALT))
|
||||
|
||||
/// Signal handler for COMSIG_STORAGE_STORED_ITEM. Handles animating our parent's wearer.
|
||||
/datum/component/accessable_storage/proc/parent_stored_item(obj/item/signal_source, obj/item/inserted, mob/user, force)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if (isliving(signal_source.loc))
|
||||
animate_target(signal_source.loc)
|
||||
|
||||
/// Signal handler for COMSIG_STORAGE_REMOVED_ITEM. Handles animating our parent's wearer.
|
||||
/datum/component/accessable_storage/proc/parent_removed_item(obj/item/signal_source, obj/item/thing, atom/remove_to_loc, silent)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if (isliving(signal_source.loc))
|
||||
animate_target(signal_source.loc)
|
||||
|
||||
/// Gives a spiffy animation to the target to represent opening and closing. Copy pasted from storage.dm, please change if that proc ever changes
|
||||
/datum/component/accessable_storage/proc/animate_target(atom/target = parent)
|
||||
var/matrix/old_matrix = target.transform
|
||||
animate(target, time = 1.5, loop = 0, transform = target.transform.Scale(1.07, 0.9))
|
||||
animate(time = 2, transform = old_matrix)
|
||||
98
modular_skyrat/modules/taur_mechanics/code/human.dm
Normal file
98
modular_skyrat/modules/taur_mechanics/code/human.dm
Normal file
@@ -0,0 +1,98 @@
|
||||
/mob/living/carbon/human/mouse_buckle_handling(mob/living/buckling, mob/living/user)
|
||||
if (!ride_saddle(buckling, user))
|
||||
return ..()
|
||||
|
||||
/// The amount of time it takes to mount a mob with a saddle on.
|
||||
#define SADDLE_MOUNTING_TIME 1.5 SECONDS
|
||||
/// The mult to be applied to SADDLE_MOUNTING_TIME if the user is mounting someone else onto the saddled mob.
|
||||
#define SADDLE_MOUNTING_OTHER_MULT 3
|
||||
|
||||
/// Attempts to have buckling ride on our saddle, if we have one.
|
||||
/mob/living/carbon/human/proc/ride_saddle(mob/living/buckling, mob/living/user)
|
||||
if (!can_be_ridden_by(buckling, user))
|
||||
return FALSE
|
||||
|
||||
var/delay = SADDLE_MOUNTING_TIME
|
||||
var/ridee_string = ""
|
||||
var/list/mobs_with_special_messages = list(src)
|
||||
if (buckling != user)
|
||||
ridee_string = " [buckling] onto"
|
||||
mobs_with_special_messages += buckling
|
||||
delay *= SADDLE_MOUNTING_OTHER_MULT
|
||||
|
||||
user.visible_message(span_warning("[user] starts to mount[ridee_string] [src]..."), span_notice("You start to mount[ridee_string] [src]..."), ignored_mobs = mobs_with_special_messages)
|
||||
to_chat(src, span_warning("[user] starts to mount[ridee_string] you!"))
|
||||
if (buckling != user)
|
||||
to_chat(buckling, span_boldwarning("[user] starts to mount you onto [src]!"))
|
||||
|
||||
if (!do_after(user, SADDLE_MOUNTING_TIME, target = src))
|
||||
user.visible_message(span_warning("[user] fails to mount[ridee_string] [src]!"), span_warning("You fail to mount[ridee_string] [src]!"), ignored_mobs = mobs_with_special_messages)
|
||||
to_chat(src, span_warning("[user] fails to mount[ridee_string] you!"))
|
||||
if (buckling != user)
|
||||
to_chat(buckling, span_warning("[user] fails to mount you onto [src]!"))
|
||||
return FALSE
|
||||
|
||||
if (!can_be_ridden_by(buckling, user)) // because we slept
|
||||
return FALSE // no feedback. this already gives some
|
||||
|
||||
var/saddle_flags = SEND_SIGNAL(src, COMSIG_HUMAN_SADDLE_RIDE_ATTEMPT, buckling)
|
||||
if (!saddle_flags)
|
||||
saddle_flags = RIDER_NEEDS_ARMS
|
||||
|
||||
return buckle_mob(buckling, force = TRUE, check_loc = TRUE, buckle_mob_flags = saddle_flags)
|
||||
|
||||
#undef SADDLE_MOUNTING_TIME
|
||||
#undef SADDLE_MOUNTING_OTHER_MULT
|
||||
|
||||
/**
|
||||
* Determines if src can be ridden by to_buckle.
|
||||
*
|
||||
* Args:
|
||||
* * to_buckle: The mob trying to mount us. Non-nullable.
|
||||
* * user: The mob mounting to_buckle onto us, most likely to_buckle itself. Non-nullable.
|
||||
* * silent = FALSE: If FALSE, we do not send feedback messages. Boolean.
|
||||
* Returns:
|
||||
* * FALSE if we have no saddle, if we're trying to mount ourself, or if to_buckle can't be mounted. TRUE otherwise.
|
||||
*/
|
||||
/mob/living/carbon/human/proc/can_be_ridden_by(mob/living/to_buckle, mob/living/user, silent = FALSE)
|
||||
if (!HAS_TRAIT(src, TRAIT_SADDLED))
|
||||
return FALSE // no feedback as it's very very common
|
||||
|
||||
if (user == src) // would open the inventory screen otherwise
|
||||
return FALSE // no feedback as you get your answer via the inventory screen
|
||||
|
||||
/// Conditions that prevent riding, with a balloon alert
|
||||
var/cant_buckle_message
|
||||
if (to_buckle == src)
|
||||
cant_buckle_message = "can't ride self!"
|
||||
else if (body_position == LYING_DOWN)
|
||||
cant_buckle_message = "can't ride resting!"
|
||||
else if (incapacitated)
|
||||
cant_buckle_message = "can't mount incapacitated mobs!"
|
||||
else if (INCAPACITATED_IGNORING(user, INCAPABLE_GRAB))
|
||||
cant_buckle_message = "you are incapacitated!"
|
||||
else if (INCAPACITATED_IGNORING(to_buckle, INCAPABLE_GRAB))
|
||||
cant_buckle_message = "rider incapacitated!"
|
||||
else if (length(buckled_mobs))
|
||||
cant_buckle_message = "already being ridden!"
|
||||
|
||||
if (cant_buckle_message)
|
||||
if (!silent)
|
||||
balloon_alert(user, cant_buckle_message)
|
||||
return FALSE
|
||||
|
||||
if (!ishuman(to_buckle))
|
||||
return TRUE // no more checks need to be made
|
||||
|
||||
var/mob/living/carbon/human/human_target = to_buckle
|
||||
|
||||
var/obj/item/organ/external/taur_body/taur_body = get_organ_slot(ORGAN_SLOT_EXTERNAL_TAUR)
|
||||
var/obj/item/organ/external/taur_body/other_taur_body = human_target.get_organ_slot(ORGAN_SLOT_EXTERNAL_TAUR)
|
||||
|
||||
if (isnull(taur_body) || isnull(other_taur_body))
|
||||
return TRUE
|
||||
|
||||
if (!other_taur_body.can_ride_saddled_taurs) // no stacking, sorry
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
10
modular_skyrat/modules/taur_mechanics/code/item.dm
Normal file
10
modular_skyrat/modules/taur_mechanics/code/item.dm
Normal file
@@ -0,0 +1,10 @@
|
||||
/obj/item/mob_can_equip(mob/living/M, slot, disable_warning, bypass_equip_delay_self, ignore_equipped, indirect_action)
|
||||
. = ..()
|
||||
|
||||
if (!.)
|
||||
return FALSE
|
||||
|
||||
if (SEND_SIGNAL(src, COMSIG_ITEM_MOB_CAN_EQUIP, M, slot, disable_warning, bypass_equip_delay_self, ignore_equipped, indirect_action) & COMPONENT_ITEM_CANT_EQUIP)
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
@@ -0,0 +1,83 @@
|
||||
/// Allows the attached item to enable saddle mechanics on the mob wearing it.
|
||||
/datum/component/carbon_saddle
|
||||
/// The piggyback flags to apply to any mob that wears parent.
|
||||
var/saddle_flags = RIDER_NEEDS_ARM|RIDING_TAUR
|
||||
|
||||
/datum/component/carbon_saddle/Initialize(saddle_flags)
|
||||
if (!isitem(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
if (!isnull(saddle_flags))
|
||||
src.saddle_flags = saddle_flags
|
||||
|
||||
/datum/component/carbon_saddle/RegisterWithParent()
|
||||
RegisterSignal(parent, COMSIG_ITEM_POST_EQUIPPED, PROC_REF(parent_equipped))
|
||||
RegisterSignal(parent, COMSIG_ITEM_MOB_CAN_EQUIP, PROC_REF(parent_can_equip))
|
||||
|
||||
/datum/component/carbon_saddle/UnregisterFromParent()
|
||||
var/obj/item/item_parent = parent
|
||||
UnregisterSignal(item_parent, COMSIG_ITEM_EQUIPPED)
|
||||
|
||||
/// Signal handler for COMSIG_ITEM_POST_EQUIPPED. Handles registering signals and traits on the equipper.
|
||||
/datum/component/carbon_saddle/proc/parent_equipped(datum/signal_source, mob/equipper, slot)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if (!isliving(equipper) || (slot & (ITEM_SLOT_HANDS|ITEM_SLOT_POCKETS)))
|
||||
return
|
||||
var/mob/living/living_equipper = equipper
|
||||
|
||||
RegisterSignal(living_equipper, COMSIG_MOB_UNEQUIPPED_ITEM, PROC_REF(mob_unequipped_item))
|
||||
RegisterSignal(living_equipper, COMSIG_CARBON_LOSE_ORGAN, PROC_REF(wearer_lost_organ))
|
||||
RegisterSignal(living_equipper, COMSIG_HUMAN_SADDLE_RIDE_ATTEMPT, PROC_REF(wearer_ridden))
|
||||
|
||||
ADD_TRAIT(living_equipper, TRAIT_SADDLED, REF(src))
|
||||
|
||||
/// Signal handler for COMSIG_MOB_UNEQUIPPED_ITEM.
|
||||
/datum/component/carbon_saddle/proc/mob_unequipped_item(mob/signal_source, obj/item/item, force, atom/newloc, no_move, invdrop, silent)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if (item == parent)
|
||||
mob_unequipped_parent(signal_source)
|
||||
|
||||
/// Called when our parent is inequipped. Handles unsetting signals and traits.
|
||||
/datum/component/carbon_saddle/proc/mob_unequipped_parent(mob/target)
|
||||
UnregisterSignal(target, list(COMSIG_MOB_UNEQUIPPED_ITEM, COMSIG_CARBON_LOSE_ORGAN, COMSIG_HUMAN_SADDLE_RIDE_ATTEMPT))
|
||||
REMOVE_TRAIT(target, TRAIT_SADDLED, REF(src))
|
||||
|
||||
/// Signal handler for COMSIG_CARBON_LOSE_ORGAN. Handles unequipping if the requisite organ is removed.
|
||||
/datum/component/carbon_saddle/proc/wearer_lost_organ(mob/living/carbon/signal_source, obj/item/organ/lost)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if (!wearer_has_requisite_organ(signal_source))
|
||||
var/obj/item/item_parent = parent
|
||||
item_parent.forceMove(get_turf(item_parent)) // force unequip
|
||||
|
||||
/// Signal handler for COMSIG_HUMAN_SADDLE_RIDE_ATTEMPT. Returns saddle_flags into the signal bitfield.
|
||||
/datum/component/carbon_saddle/proc/wearer_ridden(mob/living/carbon/human/wearer, mob/living/carbon/rider)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
return saddle_flags
|
||||
|
||||
/// Signal handler for COMSIG_ITEM_MOB_CAN_EQUIP. If equipped into a non-hands and pockets slot, returns COMPONENT_ITEM_CANT_EQUIP if our owner doesnt have our required organ.
|
||||
/datum/component/carbon_saddle/proc/parent_can_equip(obj/item/signal_source, mob/living/target, slot, disable_warning, bypass_equip_delay_self, ignore_equipped, indirect_action)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if (slot & (ITEM_SLOT_HANDS|ITEM_SLOT_POCKETS))
|
||||
return
|
||||
|
||||
if (!wearer_has_requisite_organ(target))
|
||||
return COMPONENT_ITEM_CANT_EQUIP
|
||||
|
||||
/// Determines if our wearer, target, has our required organ.
|
||||
/datum/component/carbon_saddle/proc/wearer_has_requisite_organ(mob/living/carbon/target)
|
||||
if (!istype(target))
|
||||
return TRUE
|
||||
|
||||
for (var/obj/item/organ/iter_organ as anything in target.organs)
|
||||
if (!istype(iter_organ, /obj/item/organ/external/taur_body))
|
||||
continue
|
||||
var/obj/item/organ/external/taur_body/taur_body = iter_organ
|
||||
if (taur_body.can_use_saddle)
|
||||
return TRUE
|
||||
|
||||
return FALSE
|
||||
74
modular_skyrat/modules/taur_mechanics/code/saddles.dm
Normal file
74
modular_skyrat/modules/taur_mechanics/code/saddles.dm
Normal file
@@ -0,0 +1,74 @@
|
||||
/obj/item/riding_saddle
|
||||
name = "generic riding saddle"
|
||||
desc = "someone spawned a basetype!"
|
||||
slot_flags = ITEM_SLOT_BACK // no storage
|
||||
|
||||
icon = 'modular_skyrat/modules/taur_mechanics/sprites/saddles.dmi'
|
||||
worn_icon = 'modular_skyrat/modules/taur_mechanics/sprites/saddles.dmi'
|
||||
worn_icon_taur_snake = 'modular_skyrat/modules/taur_mechanics/sprites/saddles.dmi'
|
||||
supports_variations_flags = STYLE_TAUR_HOOF|STYLE_TAUR_PAW
|
||||
|
||||
/obj/item/riding_saddle/Initialize(mapload)
|
||||
. = ..()
|
||||
if(type == /obj/item/riding_saddle) // don't even let these prototypes exist
|
||||
return INITIALIZE_HINT_QDEL
|
||||
|
||||
AddComponent(/datum/component/carbon_saddle, RIDING_TAUR) // FREE HANDS
|
||||
AddComponent(/datum/component/taur_clothing_offset)
|
||||
|
||||
/obj/item/riding_saddle/leather
|
||||
name = "riding saddle"
|
||||
desc = "A thick leather riding saddle. Typically used for animals, this one has been designed for use by the taurs of the galaxy. \n\
|
||||
This saddle has specialized footrests that will allow a rider to <b>use both their hands</b> while riding."
|
||||
|
||||
icon_state = "saddle_leather_item"
|
||||
worn_icon_state = "saddle_leather"
|
||||
|
||||
inhand_icon_state = "syringe_kit" // placeholder
|
||||
lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
|
||||
|
||||
/obj/item/riding_saddle/leather/Initialize(mapload)
|
||||
. = ..()
|
||||
|
||||
/obj/item/riding_saddle/leather/peacekeeper
|
||||
name = "peacekeeper saddle"
|
||||
|
||||
icon_state = "saddle_sec_item"
|
||||
worn_icon_state = "saddle_sec"
|
||||
|
||||
/obj/item/riding_saddle/leather/peacekeeper/Initialize(mapload)
|
||||
. = ..()
|
||||
|
||||
desc += " This one is painted in peacekeeper livery."
|
||||
|
||||
/obj/item/storage/backpack/saddlebags
|
||||
name = "saddlebags"
|
||||
desc = "A collection of small pockets bound together by belt, typically used on caravan animals due to their superior storage capacity. This one has been designed for use by the taurs of the galaxy. \n\
|
||||
These saddlebags can be accessed by anyone if they <b>alt-click</b> the wearer.\n\
|
||||
Additionally, they have been modified with a hand grip that would allow <b>one free hand</b> during riding."
|
||||
gender = PLURAL
|
||||
|
||||
slot_flags = ITEM_SLOT_BACK
|
||||
|
||||
icon = 'modular_skyrat/modules/taur_mechanics/sprites/saddles.dmi'
|
||||
worn_icon = 'modular_skyrat/modules/taur_mechanics/sprites/saddles.dmi'
|
||||
worn_icon_taur_snake = 'modular_skyrat/modules/taur_mechanics/sprites/saddles.dmi'
|
||||
supports_variations_flags = STYLE_TAUR_HOOF|STYLE_TAUR_PAW
|
||||
|
||||
storage_type = /datum/storage/saddlebags
|
||||
|
||||
icon_state = "saddle_satchel_item"
|
||||
worn_icon_state = "saddle_satchel"
|
||||
|
||||
// slightly better than a backpack, but accessable_storage counterbalances this
|
||||
/datum/storage/saddlebags
|
||||
max_total_storage = 26
|
||||
max_slots = 21
|
||||
|
||||
/obj/item/storage/backpack/saddlebags/Initialize(mapload)
|
||||
. = ..()
|
||||
|
||||
AddComponent(/datum/component/carbon_saddle, RIDING_TAUR|RIDER_NEEDS_ARM) // one arm
|
||||
AddComponent(/datum/component/accessable_storage)
|
||||
AddComponent(/datum/component/taur_clothing_offset)
|
||||
@@ -0,0 +1,73 @@
|
||||
/// Offsets parent's worn overlay based on their wearer's taur body.
|
||||
/datum/component/taur_clothing_offset
|
||||
|
||||
/datum/component/taur_clothing_offset/RegisterWithParent()
|
||||
. = ..()
|
||||
|
||||
if (!isitem(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
RegisterSignal(parent, COMSIG_ITEM_GET_WORN_OVERLAYS, PROC_REF(modify_overlays))
|
||||
RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, PROC_REF(parent_equipped))
|
||||
|
||||
/datum/component/taur_clothing_offset/UnregisterFromParent()
|
||||
. = ..()
|
||||
|
||||
UnregisterSignal(parent, list(COMSIG_ITEM_GET_WORN_OVERLAYS, COMSIG_ITEM_EQUIPPED))
|
||||
|
||||
/// Signal handler for COMSIG_ITEM_GET_WORN_OVERLAYS. Offsets parent's worn overlay based on their wearer's taur body.
|
||||
/datum/component/taur_clothing_offset/proc/modify_overlays(obj/item/signal_source, list/overlays, mutable_appearance/standing, isinhands, icon_file)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if (!iscarbon(signal_source.loc))
|
||||
return
|
||||
|
||||
if (isinhands)
|
||||
return
|
||||
|
||||
var/mob/living/carbon/target_carbon = signal_source.loc
|
||||
var/obj/item/organ/external/taur_body/taur_body = target_carbon.get_organ_slot(ORGAN_SLOT_EXTERNAL_TAUR)
|
||||
if (!istype(taur_body))
|
||||
return
|
||||
var/icon_dir = target_carbon.dir
|
||||
if(ISDIAGONALDIR(icon_dir))
|
||||
icon_dir &= ~(NORTH | SOUTH)
|
||||
var/offset = taur_body.taur_specific_clothing_y_offsets?["[icon_dir]"]
|
||||
if (!offset)
|
||||
return
|
||||
standing.pixel_y += offset
|
||||
|
||||
/// Signal handler for COMSIG_ITEM_EQUIPPED. Handles registering signals.
|
||||
/datum/component/taur_clothing_offset/proc/parent_equipped(datum/signal_source, mob/equipper, slot)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if (ishuman(equipper) && !(equipper.get_slot_by_item(parent) & (ITEM_SLOT_HANDS|ITEM_SLOT_POCKETS)))
|
||||
RegisterSignal(equipper, COMSIG_MOB_UNEQUIPPED_ITEM, PROC_REF(mob_unequipped_item))
|
||||
RegisterSignal(equipper, COMSIG_ATOM_POST_DIR_CHANGE, PROC_REF(wearer_dir_changed))
|
||||
|
||||
/// Signal handler for COMSIG_MOB_UNEQUIPPED_ITEM. Handles unregistering signals.
|
||||
/datum/component/taur_clothing_offset/proc/mob_unequipped_item(mob/signal_source, obj/item/item, force, atom/newloc, no_move, invdrop, silent)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if (item == parent)
|
||||
UnregisterSignal(signal_source, list(COMSIG_MOB_UNEQUIPPED_ITEM, COMSIG_ATOM_POST_DIR_CHANGE))
|
||||
|
||||
/// Signal handler for COMSIG_ATOM_POST_DIR_CHANGE. Handles updating the offset based on dir.
|
||||
/datum/component/taur_clothing_offset/proc/wearer_dir_changed(mob/living/carbon/human/signal_source, old_dir, new_dir)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
var/obj/item/organ/external/taur_body/taur_body = signal_source.get_organ_slot(ORGAN_SLOT_EXTERNAL_TAUR)
|
||||
if (isnull(taur_body))
|
||||
return
|
||||
|
||||
if(ISDIAGONALDIR(new_dir))
|
||||
new_dir &= ~(NORTH | SOUTH) //remove diagonal for lookup, matching how directional player sprites are selected
|
||||
if(ISDIAGONALDIR(old_dir))
|
||||
old_dir &= ~(NORTH | SOUTH)
|
||||
if(new_dir == old_dir)
|
||||
return
|
||||
|
||||
var/obj/item/item_parent = parent
|
||||
if (taur_body.taur_specific_clothing_y_offsets?["[new_dir]"] || taur_body.taur_specific_clothing_y_offsets?["[old_dir]"]) // discounts null and 0
|
||||
// if the last dir had a offset, we need to reset if the new dir has NO offset
|
||||
signal_source.update_clothing(item_parent.slot_flags)
|
||||
BIN
modular_skyrat/modules/taur_mechanics/sprites/saddles.dmi
Normal file
BIN
modular_skyrat/modules/taur_mechanics/sprites/saddles.dmi
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.8 KiB |
@@ -11,3 +11,16 @@
|
||||
name = "Mr. Fluff"
|
||||
item_path = /obj/item/clothing/head/mob_holder/pet/donator/centralsmith
|
||||
|
||||
/datum/loadout_item/inhand/saddlebags
|
||||
name = "saddlebags"
|
||||
item_path = /obj/item/storage/backpack/saddlebags
|
||||
|
||||
/datum/loadout_item/inhand/saddle // these should be in the other category but apparantly those are "pocket" loadout items so idk?
|
||||
name = "riding saddle (leather)"
|
||||
item_path = /obj/item/riding_saddle/leather
|
||||
|
||||
/datum/loadout_item/inhand/saddle_peacekeeper
|
||||
name = "riding saddle (peacekeeper)"
|
||||
item_path = /obj/item/riding_saddle/leather/peacekeeper
|
||||
|
||||
restricted_roles = list(JOB_SECURITY_OFFICER, JOB_WARDEN, JOB_DETECTIVE, JOB_CORRECTIONS_OFFICER, JOB_HEAD_OF_SECURITY)
|
||||
|
||||
@@ -119,6 +119,7 @@
|
||||
/obj/item/clothing/accessory/badge/holo/cord = 10,
|
||||
/obj/item/clothing/head/helmet/blueshirt = 3,
|
||||
/obj/item/clothing/suit/armor/vest/blueshirt = 3,
|
||||
/obj/item/riding_saddle/leather/peacekeeper = 3,
|
||||
)
|
||||
|
||||
//CONTRABAND: Basically for less serious/hard to cat stuff like the Cowboy and Bluecoat stuff. And for stuff that shouldn't be easy to get like HUD varients.
|
||||
|
||||
@@ -499,6 +499,7 @@
|
||||
#include "code\__DEFINES\~~bubber_defines\economy.dm"
|
||||
#include "code\__DEFINES\~~bubber_defines\experisci.dm"
|
||||
#include "code\__DEFINES\~~bubber_defines\footsteps.dm"
|
||||
#include "code\__DEFINES\~~bubber_defines\item.dm"
|
||||
#include "code\__DEFINES\~~bubber_defines\jobs.dm"
|
||||
#include "code\__DEFINES\~~bubber_defines\loadout.dm"
|
||||
#include "code\__DEFINES\~~bubber_defines\misc.dm"
|
||||
@@ -511,6 +512,7 @@
|
||||
#include "code\__DEFINES\~~bubber_defines\status_indicator_defines.dm"
|
||||
#include "code\__DEFINES\~~bubber_defines\storyteller_defines.dm"
|
||||
#include "code\__DEFINES\~~bubber_defines\transport.dm"
|
||||
#include "code\__DEFINES\~~bubber_defines\vehicles.dm"
|
||||
#include "code\__DEFINES\~~bubber_defines\___HELPERS\global_lists.dm"
|
||||
#include "code\__DEFINES\~~bubber_defines\research\techweb_nodes.dm"
|
||||
#include "code\__DEFINES\~~bubber_defines\traits\declarations.dm"
|
||||
@@ -8557,11 +8559,17 @@
|
||||
#include "modular_skyrat\modules\tarkon\code\misc-fluff\research.dm"
|
||||
#include "modular_skyrat\modules\tarkon\code\misc-fluff\spawner.dm"
|
||||
#include "modular_skyrat\modules\tarkon\code\misc-fluff\tools.dm"
|
||||
#include "modular_skyrat\modules\taur_mechanics\code\accessible_storage.dm"
|
||||
#include "modular_skyrat\modules\taur_mechanics\code\constrict.dm"
|
||||
#include "modular_skyrat\modules\taur_mechanics\code\human.dm"
|
||||
#include "modular_skyrat\modules\taur_mechanics\code\item.dm"
|
||||
#include "modular_skyrat\modules\taur_mechanics\code\mod.dm"
|
||||
#include "modular_skyrat\modules\taur_mechanics\code\preferences.dm"
|
||||
#include "modular_skyrat\modules\taur_mechanics\code\saddle_component.dm"
|
||||
#include "modular_skyrat\modules\taur_mechanics\code\saddles.dm"
|
||||
#include "modular_skyrat\modules\taur_mechanics\code\serpentine_taur.dm"
|
||||
#include "modular_skyrat\modules\taur_mechanics\code\species.dm"
|
||||
#include "modular_skyrat\modules\taur_mechanics\code\taur_clothing_offset.dm"
|
||||
#include "modular_skyrat\modules\telecomms_specialist\telecomms_specialist.dm"
|
||||
#include "modular_skyrat\modules\tesh_augments\code\all_nodes.dm"
|
||||
#include "modular_skyrat\modules\tesh_augments\code\limbs.dm"
|
||||
|
||||
Reference in New Issue
Block a user