mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-27 15:17:01 +01:00
Refactor: Moves throwing and giving items from /mob/living/carbon to /mob/living (#91049)
Given the existence of basic mobs with hand slots, it feels like throwing and giving items shouldn't be something exclusive to carbon mobs, so I've pulled things around to make this happen. The only basic mobs with hands at time of writing are gorillas and dextrous holoparasites, but the inability to throw things when you're a gorilla just doesn't seem right to me. Some more details about what I've done here: - Made the dextrous component optionally enable throwing for the mob it's added to. - Moved offer/give item functionality to /mob/living (I can't see any reason why only carbon mobs should have this option) - Moved throwing and give item hotkeys from carbon to "human" (where all the other /mob/living hotkeys go) and, as a result, removed carbon hotkeys (nothing is left in them). - Moved throwing code and item offering code to its own file because living.dm is 3000+ lines long and should probably be broken up some day (I'm not brave enough for that) - Cleaned up an unused global signal that hasn't been used since dogs got moved to basic mobs. - Other miscellaneous cleanup where I noticed it. - In terms of testing: Tested using gorillas (only checked the dextrous holoparasite to confirm the button and hotkeys worked). Things that were working: - Can throw items if the mob is set up to allow it. - Can give items as a gorilla to a human, as a human to a gorilla, and as a human to a human. - Can give a high five to a gorilla (and the gorilla can receive it). Gorillas can't give a high five back, though (they don't have the emote), this already ballooned in scope, someone else can make that happen. - There are an alarmingly high amount of niche emote-into-item-into-giving behaviours I suspect half the playerbase or more aren't even aware of (does anyone offer their hand to someone to get them up off of the ground?) and I don't know if I broke any of them with this, but the fact high fives work gives me some hope they're probably still fine. Lets gorillas and dextrous holoparasites throw things and give things, but most importantly sets up more framework for any future dextrous basic mobs to also be able to do this. There's no real reason to keep this functionality confined to carbon mobs when dextrous basic mobs are a thing. 🆑 add: Gorillas can now throw things and offer items to players. refactor: Moved throwing and offering item code to be based on living mobs, not just carbon mobs. /🆑 --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com>
This commit is contained in:
committed by
Roxy
co-authored by
Copilot
Ghom
parent
0060c53767
commit
fb69fbb8a2
@@ -43,8 +43,6 @@
|
||||
#define COMSIG_GLOB_RANDOM_EVENT "!random_event"
|
||||
/// Do not allow this random event to continue.
|
||||
#define CANCEL_RANDOM_EVENT (1<<0)
|
||||
/// a person somewhere has thrown something : (mob/living/carbon/carbon_thrower, target)
|
||||
#define COMSIG_GLOB_CARBON_THROW_THING "!throw_thing"
|
||||
/// a trapdoor remote has sent out a signal to link with a trapdoor
|
||||
#define COMSIG_GLOB_TRAPDOOR_LINK "!trapdoor_link"
|
||||
///successfully linked to a trapdoor!
|
||||
|
||||
@@ -146,9 +146,6 @@
|
||||
///from base of /mob/living/carbon/regenerate_limbs(): (excluded_limbs)
|
||||
#define COMSIG_CARBON_REGENERATE_LIMBS "living_regen_limbs"
|
||||
|
||||
///from /atom/movable/screen/alert/give/proc/handle_transfer(): (taker, item)
|
||||
#define COMSIG_CARBON_ITEM_GIVEN "carbon_item_given"
|
||||
|
||||
/// Sent from /mob/living/carbon/human/handle_blood(): (seconds_per_tick, times_fired)
|
||||
#define COMSIG_HUMAN_ON_HANDLE_BLOOD "human_on_handle_blood"
|
||||
/// Return to prevent all default blood handling
|
||||
|
||||
@@ -293,8 +293,10 @@
|
||||
///cancel post eating
|
||||
#define COMSIG_MOB_TERMINATE_EAT (1<<0)
|
||||
|
||||
///From mob/living/carbon/proc/throw_mode_on and throw_mode_off
|
||||
///From mob/living/proc/throw_mode_on and throw_mode_off
|
||||
#define COMSIG_LIVING_THROW_MODE_TOGGLE "living_throw_mode_toggle"
|
||||
///from /atom/movable/screen/alert/give/proc/handle_transfer(): (taker, item)
|
||||
#define COMSIG_LIVING_ITEM_GIVEN "living_item_given"
|
||||
/// From mob/living/proc/on_fall
|
||||
#define COMSIG_LIVING_THUD "living_thud"
|
||||
///From /datum/component/happiness()
|
||||
|
||||
@@ -179,11 +179,11 @@
|
||||
#define COMSIG_ARMOR_PLATED "armor_plated"
|
||||
///Called when an item gets recharged by the ammo powerup
|
||||
#define COMSIG_ITEM_RECHARGED "item_recharged"
|
||||
///Called when an item is being offered, from [/obj/item/proc/on_offered(mob/living/carbon/offerer)]
|
||||
///Called when an item is being offered, from [/obj/item/proc/on_offered(mob/living/offerer)]
|
||||
#define COMSIG_ITEM_OFFERING "item_offering"
|
||||
///Interrupts the offer proc
|
||||
#define COMPONENT_OFFER_INTERRUPT (1<<0)
|
||||
///Called when an someone tries accepting an offered item, from [/obj/item/proc/on_offer_taken(mob/living/carbon/offerer, mob/living/carbon/taker)]
|
||||
///Called when an someone tries accepting an offered item, from [/obj/item/proc/on_offer_taken(mob/living/offerer, mob/living/taker)]
|
||||
#define COMSIG_ITEM_OFFER_TAKEN "item_offer_taken"
|
||||
///Interrupts the offer acceptance
|
||||
#define COMPONENT_OFFER_TAKE_INTERRUPT (1<<0)
|
||||
|
||||
@@ -22,9 +22,6 @@
|
||||
//Carbon
|
||||
#define COMSIG_KB_CARBON_HOLDRUNMOVEINTENT_DOWN "keybinding_carbon_holdrunmoveintent_down"
|
||||
#define COMSIG_KB_CARBON_HOLDRUNMOVEINTENT_UP "keybinding_carbon_holdrunmoveintent_up"
|
||||
#define COMSIG_KB_CARBON_TOGGLETHROWMODE_DOWN "keybinding_carbon_togglethrowmode_down"
|
||||
#define COMSIG_KB_CARBON_HOLDTHROWMODE_DOWN "keybinding_carbon_holdthrowmode_down"
|
||||
#define COMSIG_KB_CARBON_GIVEITEM_DOWN "keybinding_carbon_giveitem_down"
|
||||
|
||||
//Client
|
||||
#define COMSIG_KB_CLIENT_GETHELP_DOWN "keybinding_client_gethelp_down"
|
||||
@@ -57,6 +54,9 @@
|
||||
#define COMSIG_KB_LIVING_DISABLE_COMBAT_DOWN "keybinding_living_disable_combat_down"
|
||||
#define COMSIG_KB_LIVING_TOGGLEMOVEINTENT_DOWN "keybinding_mob_togglemoveintent_down"
|
||||
#define COMSIG_KB_LIVING_TOGGLEMOVEINTENTALT_DOWN "keybinding_mob_togglemoveintentalt_down"
|
||||
#define COMSIG_KB_LIVING_TOGGLETHROWMODE_DOWN "keybinding_living_togglethrowmode_down"
|
||||
#define COMSIG_KB_LIVING_HOLDTHROWMODE_DOWN "keybinding_living_holdthrowmode_down"
|
||||
#define COMSIG_KB_LIVING_GIVEITEM_DOWN "keybinding_living_giveitem_down"
|
||||
#define COMSIG_KB_LIVING_VIEW_PET_COMMANDS "keybinding_living_view_pet_commands"
|
||||
|
||||
//Mob
|
||||
|
||||
@@ -60,6 +60,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
|
||||
#define TRAIT_CLUMSY "clumsy"
|
||||
/// Trait that means you are capable of holding items in some form
|
||||
#define TRAIT_CAN_HOLD_ITEMS "can_hold_items"
|
||||
/// Trait that means you're capable of throwing things
|
||||
#define TRAIT_CAN_THROW_ITEMS "can_throw_items"
|
||||
/// Trait which lets you clamber over a barrier
|
||||
#define TRAIT_FENCE_CLIMBER "can_climb_fences"
|
||||
/// means that you can't use weapons with normal trigger guards.
|
||||
|
||||
@@ -210,6 +210,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
|
||||
"TRAIT_CAN_MOUNT_HUMANS" = TRAIT_CAN_MOUNT_HUMANS,
|
||||
"TRAIT_CAN_SIGN_ON_COMMS" = TRAIT_CAN_SIGN_ON_COMMS,
|
||||
"TRAIT_CAN_STRIP" = TRAIT_CAN_STRIP,
|
||||
"TRAIT_CAN_THROW_ITEMS" = TRAIT_CAN_THROW_ITEMS,
|
||||
"TRAIT_CAN_USE_NUKE" = TRAIT_CAN_USE_NUKE,
|
||||
"TRAIT_CATLIKE_GRACE" = TRAIT_CATLIKE_GRACE,
|
||||
"TRAIT_CHANGELING_HIVEMIND_MUTE" = TRAIT_CHANGELING_HIVEMIND_MUTE,
|
||||
|
||||
@@ -62,6 +62,7 @@ GLOBAL_LIST_INIT(admin_visible_traits, list(
|
||||
"TRAIT_BYPASS_MEASURES" = TRAIT_BYPASS_MEASURES,
|
||||
"TRAIT_CAN_HOLD_ITEMS" = TRAIT_CAN_HOLD_ITEMS,
|
||||
"TRAIT_CAN_STRIP" = TRAIT_CAN_STRIP,
|
||||
"TRAIT_CAN_THROW_ITEMS" = TRAIT_CAN_THROW_ITEMS,
|
||||
"TRAIT_CAN_USE_NUKE" = TRAIT_CAN_USE_NUKE,
|
||||
"TRAIT_CANNOT_BE_UNBUCKLED" = TRAIT_CANNOT_BE_UNBUCKLED,
|
||||
"TRAIT_CANNOT_OPEN_PRESENTS" = TRAIT_CANNOT_OPEN_PRESENTS,
|
||||
|
||||
+15
-16
@@ -343,14 +343,13 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
|
||||
/**
|
||||
* Handles assigning most of the variables for the alert that pops up when an item is offered
|
||||
*
|
||||
* Handles setting the name, description and icon of the alert and tracking the person giving
|
||||
* Handles setting the name, description and icon of the alert and tracking the living mob giving
|
||||
* and the item being offered.
|
||||
* Arguments:
|
||||
* * taker - The person receiving the alert
|
||||
* * offerer - The person giving the alert and item
|
||||
* * receiving - The item being given by the offerer
|
||||
* * taker - The living mob receiving the alert
|
||||
* * offer - The status effect connected to the offer being made
|
||||
*/
|
||||
/atom/movable/screen/alert/give/proc/setup(mob/living/carbon/taker, datum/status_effect/offering/offer)
|
||||
/atom/movable/screen/alert/give/proc/setup(mob/living/taker, datum/status_effect/offering/offer)
|
||||
src.offer = offer
|
||||
|
||||
var/mob/living/offerer = offer.owner
|
||||
@@ -377,7 +376,7 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
|
||||
* Returns a string that will be displayed in the alert, which is `receiving.name`
|
||||
* by default.
|
||||
*/
|
||||
/atom/movable/screen/alert/give/proc/get_receiving_name(mob/living/carbon/taker, mob/living/carbon/offerer, obj/item/receiving)
|
||||
/atom/movable/screen/alert/give/proc/get_receiving_name(mob/living/taker, mob/living/offerer, obj/item/receiving)
|
||||
return receiving.name
|
||||
|
||||
/atom/movable/screen/alert/give/Click(location, control, params)
|
||||
@@ -385,7 +384,7 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
|
||||
if(!.)
|
||||
return
|
||||
|
||||
if(!iscarbon(usr))
|
||||
if(!isliving(usr))
|
||||
CRASH("User for [src] is of type \[[usr.type]\]. This should never happen.")
|
||||
|
||||
handle_transfer()
|
||||
@@ -402,11 +401,11 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
|
||||
|
||||
/// An overrideable proc used simply to hand over the item when claimed, this is a proc so that high-fives can override them since nothing is actually transferred
|
||||
/atom/movable/screen/alert/give/proc/handle_transfer()
|
||||
var/mob/living/carbon/taker = owner
|
||||
var/mob/living/taker = owner
|
||||
var/mob/living/offerer = offer.owner
|
||||
var/obj/item/receiving = offer.offered_item
|
||||
taker.take(offerer, receiving)
|
||||
SEND_SIGNAL(offerer, COMSIG_CARBON_ITEM_GIVEN, taker, receiving)
|
||||
SEND_SIGNAL(offerer, COMSIG_LIVING_ITEM_GIVEN, taker, receiving)
|
||||
|
||||
/atom/movable/screen/alert/give/highfive
|
||||
additional_desc_text = "Click this alert to slap it."
|
||||
@@ -415,10 +414,10 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
|
||||
/// Tracks active "to slow"ing so we can't spam click
|
||||
var/too_slowing_this_guy = FALSE
|
||||
|
||||
/atom/movable/screen/alert/give/highfive/get_receiving_name(mob/living/carbon/taker, mob/living/carbon/offerer, obj/item/receiving)
|
||||
/atom/movable/screen/alert/give/highfive/get_receiving_name(mob/living/taker, mob/living/offerer, obj/item/receiving)
|
||||
return "a high-five"
|
||||
|
||||
/atom/movable/screen/alert/give/highfive/setup(mob/living/carbon/taker, datum/status_effect/offering/offer)
|
||||
/atom/movable/screen/alert/give/highfive/setup(mob/living/taker, datum/status_effect/offering/offer)
|
||||
. = ..()
|
||||
RegisterSignal(offer.owner, COMSIG_ATOM_EXAMINE_MORE, PROC_REF(check_fake_out))
|
||||
|
||||
@@ -426,7 +425,7 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
|
||||
if(too_slowing_this_guy)
|
||||
return
|
||||
|
||||
var/mob/living/carbon/taker = owner
|
||||
var/mob/living/taker = owner
|
||||
var/mob/living/offerer = offer.owner
|
||||
var/obj/item/receiving = offer.offered_item
|
||||
if(!QDELETED(receiving) && offerer.is_holding(receiving))
|
||||
@@ -437,7 +436,7 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
|
||||
|
||||
/// If the person who offered the high five no longer has it when we try to accept it, we get pranked hard
|
||||
/atom/movable/screen/alert/give/highfive/proc/too_slow_p1()
|
||||
var/mob/living/carbon/rube = owner
|
||||
var/mob/living/rube = owner
|
||||
var/mob/living/offerer = offer?.owner
|
||||
if(QDELETED(rube) || QDELETED(offerer))
|
||||
qdel(src)
|
||||
@@ -450,7 +449,7 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
|
||||
|
||||
/// Part two of the ultimate prank
|
||||
/atom/movable/screen/alert/give/highfive/proc/too_slow_p2()
|
||||
var/mob/living/carbon/rube = owner
|
||||
var/mob/living/rube = owner
|
||||
var/mob/living/offerer = offer?.owner
|
||||
if(!QDELETED(rube) && !QDELETED(offerer))
|
||||
offerer.visible_message(span_danger("[offerer] pulls away from [rube]'s slap at the last second, dodging the high-five entirely!"), span_nicegreen("[rube] fails to make contact with your hand, making an utter fool of [rube.p_them()]self!"), span_hear("You hear a disappointing sound of flesh not hitting flesh!"), ignored_mobs=rube)
|
||||
@@ -474,13 +473,13 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
|
||||
screentip_override_text = "Take Hand"
|
||||
examinable = FALSE
|
||||
|
||||
/atom/movable/screen/alert/give/hand/get_receiving_name(mob/living/carbon/taker, mob/living/carbon/offerer, obj/item/receiving)
|
||||
/atom/movable/screen/alert/give/hand/get_receiving_name(mob/living/taker, mob/living/offerer, obj/item/receiving)
|
||||
additional_desc_text = "Click this alert to take it and let [offerer.p_them()] pull you around!"
|
||||
return "[offerer.p_their()] [receiving.name]"
|
||||
|
||||
/atom/movable/screen/alert/give/hand/helping
|
||||
|
||||
/atom/movable/screen/alert/give/hand/helping/get_receiving_name(mob/living/carbon/taker, mob/living/carbon/offerer, obj/item/receiving)
|
||||
/atom/movable/screen/alert/give/hand/helping/get_receiving_name(mob/living/taker, mob/living/offerer, obj/item/receiving)
|
||||
. = ..()
|
||||
additional_desc_text = "Click this alert to let them help you up!"
|
||||
|
||||
|
||||
@@ -31,6 +31,11 @@
|
||||
floor_change.icon = 'icons/hud/screen_midnight.dmi'
|
||||
static_inventory += floor_change
|
||||
|
||||
if(HAS_TRAIT(owner, TRAIT_CAN_THROW_ITEMS))
|
||||
throw_icon = new /atom/movable/screen/throw_catch(null, src)
|
||||
throw_icon.icon = ui_style
|
||||
throw_icon.screen_loc = ui_drop_throw
|
||||
static_inventory += throw_icon
|
||||
|
||||
zone_select = new /atom/movable/screen/zone_sel(null, src)
|
||||
zone_select.icon = ui_style
|
||||
|
||||
@@ -544,9 +544,9 @@
|
||||
mouse_over_pointer = MOUSE_HAND_POINTER
|
||||
|
||||
/atom/movable/screen/throw_catch/Click()
|
||||
if(iscarbon(usr))
|
||||
var/mob/living/carbon/C = usr
|
||||
C.toggle_throw_mode()
|
||||
if(isliving(usr))
|
||||
var/mob/living/user = usr
|
||||
user.toggle_throw_mode()
|
||||
|
||||
/atom/movable/screen/zone_sel
|
||||
name = "damage zone"
|
||||
|
||||
@@ -4,13 +4,15 @@
|
||||
*/
|
||||
/datum/element/dextrous
|
||||
|
||||
/datum/element/dextrous/Attach(datum/target, hands_count = 2, hud_type = /datum/hud/dextrous)
|
||||
/datum/element/dextrous/Attach(datum/target, hands_count = 2, hud_type = /datum/hud/dextrous, can_throw = FALSE)
|
||||
. = ..()
|
||||
if (!isliving(target) || iscarbon(target))
|
||||
return ELEMENT_INCOMPATIBLE // Incompatible with the carbon typepath because that already has its own hand handling and doesn't need hand holding
|
||||
|
||||
var/mob/living/mob_parent = target
|
||||
set_available_hands(mob_parent, hands_count)
|
||||
if(can_throw)
|
||||
ADD_TRAIT(target, TRAIT_CAN_THROW_ITEMS, REF(src)) // need to add before hud setup
|
||||
mob_parent.hud_type = hud_type
|
||||
if (mob_parent.hud_used)
|
||||
mob_parent.set_hud_used(new hud_type(target))
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
UnregisterSignal(source, list(COMSIG_ITEM_OFFERING, COMSIG_ITEM_OFFER_TAKEN))
|
||||
|
||||
/// Signal proc for [COMSIG_ITEM_OFFERING] to set up the high-five on offer
|
||||
/datum/element/high_fiver/proc/on_offer(obj/item/source, mob/living/carbon/offerer)
|
||||
/datum/element/high_fiver/proc/on_offer(obj/item/source, mob/living/offerer)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
offerer.visible_message(
|
||||
@@ -31,7 +31,7 @@
|
||||
return COMPONENT_OFFER_INTERRUPT
|
||||
|
||||
/// Signal proc for [COMSIG_ITEM_OFFER_TAKEN] to continue through with the high-five on take
|
||||
/datum/element/high_fiver/proc/on_offer_taken(obj/item/source, mob/living/carbon/offerer, mob/living/carbon/taker)
|
||||
/datum/element/high_fiver/proc/on_offer_taken(obj/item/source, mob/living/offerer, mob/living/taker)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
var/open_hands_taker = 0
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
/datum/keybinding/carbon
|
||||
category = CATEGORY_CARBON
|
||||
weight = WEIGHT_MOB
|
||||
|
||||
/datum/keybinding/carbon/can_use(client/user)
|
||||
return iscarbon(user.mob)
|
||||
|
||||
/datum/keybinding/carbon/toggle_throw_mode
|
||||
hotkey_keys = list("R", "Southwest") // END
|
||||
name = "toggle_throw_mode"
|
||||
full_name = "Toggle throw mode"
|
||||
description = "Toggle throwing the current item or not."
|
||||
category = CATEGORY_CARBON
|
||||
keybind_signal = COMSIG_KB_CARBON_TOGGLETHROWMODE_DOWN
|
||||
|
||||
/datum/keybinding/carbon/toggle_throw_mode/down(client/user, turf/target)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
var/mob/living/carbon/C = user.mob
|
||||
C.toggle_throw_mode()
|
||||
return TRUE
|
||||
|
||||
/datum/keybinding/carbon/hold_throw_mode
|
||||
hotkey_keys = list("Space")
|
||||
name = "hold_throw_mode"
|
||||
full_name = "Hold throw mode"
|
||||
description = "Hold this to turn on throw mode, and release it to turn off throw mode"
|
||||
category = CATEGORY_CARBON
|
||||
keybind_signal = COMSIG_KB_CARBON_HOLDTHROWMODE_DOWN
|
||||
|
||||
/datum/keybinding/carbon/hold_throw_mode/down(client/user, turf/target)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
var/mob/living/carbon/carbon_user = user.mob
|
||||
carbon_user.throw_mode_on(THROW_MODE_HOLD)
|
||||
|
||||
/datum/keybinding/carbon/hold_throw_mode/up(client/user, turf/target)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
var/mob/living/carbon/carbon_user = user.mob
|
||||
carbon_user.throw_mode_off(THROW_MODE_HOLD)
|
||||
/datum/keybinding/carbon/give
|
||||
hotkey_keys = list("G")
|
||||
name = "Give_Item"
|
||||
full_name = "Give item"
|
||||
description = "Give the item you're currently holding"
|
||||
keybind_signal = COMSIG_KB_CARBON_GIVEITEM_DOWN
|
||||
|
||||
/datum/keybinding/carbon/give/down(client/user, turf/target)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
var/mob/living/carbon/carbon_user = user.mob
|
||||
carbon_user.give()
|
||||
return TRUE
|
||||
@@ -167,3 +167,65 @@
|
||||
var/mob/living/M = user.mob
|
||||
M.toggle_move_intent()
|
||||
return TRUE
|
||||
|
||||
/datum/keybinding/living/toggle_throw_mode
|
||||
hotkey_keys = list("R", "Southwest") // END
|
||||
name = "toggle_throw_mode"
|
||||
full_name = "Toggle throw mode"
|
||||
description = "Toggle throwing the current item or not."
|
||||
keybind_signal = COMSIG_KB_LIVING_TOGGLETHROWMODE_DOWN
|
||||
|
||||
/datum/keybinding/living/toggle_throw_mode/down(client/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
var/mob/living/living_user = user.mob
|
||||
living_user.toggle_throw_mode()
|
||||
return TRUE
|
||||
|
||||
/datum/keybinding/living/hold_throw_mode
|
||||
hotkey_keys = list("Space")
|
||||
name = "hold_throw_mode"
|
||||
full_name = "Hold throw mode"
|
||||
description = "Hold this to turn on throw mode, and release it to turn off throw mode"
|
||||
keybind_signal = COMSIG_KB_LIVING_HOLDTHROWMODE_DOWN
|
||||
|
||||
/datum/keybinding/living/hold_throw_mode/down(client/user, turf/target)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
var/mob/living/living_user = user.mob
|
||||
living_user.throw_mode_on(THROW_MODE_HOLD)
|
||||
|
||||
/datum/keybinding/living/hold_throw_mode/up(client/user, turf/target)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
var/mob/living/living_user = user.mob
|
||||
living_user.throw_mode_off(THROW_MODE_HOLD)
|
||||
|
||||
/datum/keybinding/living/give
|
||||
hotkey_keys = list("G")
|
||||
name = "Give_Item"
|
||||
full_name = "Give item"
|
||||
description = "Give the item you're currently holding"
|
||||
keybind_signal = COMSIG_KB_LIVING_GIVEITEM_DOWN
|
||||
|
||||
/datum/keybinding/living/give/can_use(client/user)
|
||||
. = ..()
|
||||
if (!.)
|
||||
return FALSE
|
||||
if(!user.mob)
|
||||
return FALSE
|
||||
if(!HAS_TRAIT(user.mob, TRAIT_CAN_HOLD_ITEMS))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/keybinding/living/give/down(client/user, turf/target)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
var/mob/living/living_user = user.mob
|
||||
if(!HAS_TRAIT(living_user, TRAIT_CAN_HOLD_ITEMS))
|
||||
return
|
||||
living_user.give()
|
||||
|
||||
@@ -200,7 +200,7 @@
|
||||
/// The type of alert given to people when offered, in case you need to override some behavior (like for high-fives)
|
||||
var/give_alert_type = /atom/movable/screen/alert/give
|
||||
|
||||
/datum/status_effect/offering/on_creation(mob/living/new_owner, obj/item/offer, give_alert_override, mob/living/carbon/offered)
|
||||
/datum/status_effect/offering/on_creation(mob/living/new_owner, obj/item/offer, give_alert_override, mob/living/offered)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
@@ -211,7 +211,7 @@
|
||||
if(offered && is_taker_elligible(offered))
|
||||
register_candidate(offered)
|
||||
else
|
||||
for(var/mob/living/carbon/possible_taker in orange(1, owner))
|
||||
for(var/mob/living/possible_taker in orange(1, owner))
|
||||
if(!is_taker_elligible(possible_taker))
|
||||
continue
|
||||
|
||||
@@ -225,14 +225,14 @@
|
||||
RegisterSignals(offered_item, list(COMSIG_QDELETING, COMSIG_ITEM_DROPPED), PROC_REF(dropped_item))
|
||||
|
||||
/datum/status_effect/offering/Destroy()
|
||||
for(var/mob/living/carbon/removed_taker as anything in possible_takers)
|
||||
for(var/mob/living/removed_taker as anything in possible_takers)
|
||||
remove_candidate(removed_taker)
|
||||
LAZYCLEARLIST(possible_takers)
|
||||
offered_item = null
|
||||
return ..()
|
||||
|
||||
/// Hook up the specified carbon mob to be offered the item in question, give them the alert and signals and all
|
||||
/datum/status_effect/offering/proc/register_candidate(mob/living/carbon/possible_candidate)
|
||||
/// Hook up the specified living mob to be offered the item in question, give them the alert and signals and all
|
||||
/datum/status_effect/offering/proc/register_candidate(mob/living/possible_candidate)
|
||||
var/atom/movable/screen/alert/give/G = possible_candidate.throw_alert("[owner]", give_alert_type)
|
||||
if(!G)
|
||||
return
|
||||
@@ -240,8 +240,8 @@
|
||||
RegisterSignal(possible_candidate, COMSIG_MOVABLE_MOVED, PROC_REF(check_taker_in_range))
|
||||
G.setup(possible_candidate, src)
|
||||
|
||||
/// Remove the alert and signals for the specified carbon mob. Automatically removes the status effect when we lost the last taker
|
||||
/datum/status_effect/offering/proc/remove_candidate(mob/living/carbon/removed_candidate)
|
||||
/// Remove the alert and signals for the specified living mob. Automatically removes the status effect when we lost the last taker
|
||||
/datum/status_effect/offering/proc/remove_candidate(mob/living/removed_candidate)
|
||||
removed_candidate.clear_alert("[owner]")
|
||||
LAZYREMOVE(possible_takers, removed_candidate)
|
||||
UnregisterSignal(removed_candidate, COMSIG_MOVABLE_MOVED)
|
||||
@@ -249,7 +249,7 @@
|
||||
qdel(src)
|
||||
|
||||
/// One of our possible takers moved, see if they left us hanging
|
||||
/datum/status_effect/offering/proc/check_taker_in_range(mob/living/carbon/taker)
|
||||
/datum/status_effect/offering/proc/check_taker_in_range(mob/living/taker)
|
||||
SIGNAL_HANDLER
|
||||
if(owner.CanReach(taker) && !IS_DEAD_OR_INCAP(taker))
|
||||
return
|
||||
@@ -258,10 +258,10 @@
|
||||
remove_candidate(taker)
|
||||
|
||||
/// The offerer moved, see if anyone is out of range now
|
||||
/datum/status_effect/offering/proc/check_owner_in_range(mob/living/carbon/source)
|
||||
/datum/status_effect/offering/proc/check_owner_in_range(mob/living/source)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
for(var/mob/living/carbon/checking_taker as anything in possible_takers)
|
||||
for(var/mob/living/checking_taker as anything in possible_takers)
|
||||
if(!istype(checking_taker) || !owner.CanReach(checking_taker) || IS_DEAD_OR_INCAP(checking_taker))
|
||||
remove_candidate(checking_taker)
|
||||
|
||||
@@ -276,7 +276,7 @@
|
||||
*
|
||||
* Returns `TRUE` if the taker is valid as a target for the offering.
|
||||
*/
|
||||
/datum/status_effect/offering/proc/is_taker_elligible(mob/living/carbon/taker)
|
||||
/datum/status_effect/offering/proc/is_taker_elligible(mob/living/taker)
|
||||
return owner.CanReach(taker) && !IS_DEAD_OR_INCAP(taker) && additional_taker_check(taker)
|
||||
|
||||
/**
|
||||
@@ -287,7 +287,7 @@
|
||||
* Returns `TRUE` if the taker is valid as a target for the offering based on these
|
||||
* additional checks.
|
||||
*/
|
||||
/datum/status_effect/offering/proc/additional_taker_check(mob/living/carbon/taker)
|
||||
/datum/status_effect/offering/proc/additional_taker_check(mob/living/taker)
|
||||
return taker.can_hold_items()
|
||||
|
||||
/**
|
||||
@@ -296,7 +296,7 @@
|
||||
*/
|
||||
/datum/status_effect/offering/no_item_received
|
||||
|
||||
/datum/status_effect/offering/no_item_received/additional_taker_check(mob/living/carbon/taker)
|
||||
/datum/status_effect/offering/no_item_received/additional_taker_check(mob/living/taker)
|
||||
return taker.usable_hands > 0
|
||||
|
||||
/**
|
||||
@@ -307,23 +307,23 @@
|
||||
*/
|
||||
/datum/status_effect/offering/no_item_received/needs_resting
|
||||
|
||||
/datum/status_effect/offering/no_item_received/needs_resting/additional_taker_check(mob/living/carbon/taker)
|
||||
/datum/status_effect/offering/no_item_received/needs_resting/additional_taker_check(mob/living/taker)
|
||||
return taker.body_position == LYING_DOWN
|
||||
|
||||
/datum/status_effect/offering/no_item_received/needs_resting/on_creation(mob/living/new_owner, obj/item/offer, give_alert_override, mob/living/carbon/offered)
|
||||
/datum/status_effect/offering/no_item_received/needs_resting/on_creation(mob/living/new_owner, obj/item/offer, give_alert_override, mob/living/offered)
|
||||
. = ..()
|
||||
RegisterSignal(owner, COMSIG_LIVING_SET_BODY_POSITION, PROC_REF(check_owner_standing))
|
||||
|
||||
/datum/status_effect/offering/no_item_received/needs_resting/register_candidate(mob/living/carbon/possible_candidate)
|
||||
/datum/status_effect/offering/no_item_received/needs_resting/register_candidate(mob/living/possible_candidate)
|
||||
. = ..()
|
||||
RegisterSignal(possible_candidate, COMSIG_LIVING_SET_BODY_POSITION, PROC_REF(check_candidate_resting))
|
||||
|
||||
/datum/status_effect/offering/no_item_received/needs_resting/remove_candidate(mob/living/carbon/removed_candidate)
|
||||
/datum/status_effect/offering/no_item_received/needs_resting/remove_candidate(mob/living/removed_candidate)
|
||||
UnregisterSignal(removed_candidate, COMSIG_LIVING_SET_BODY_POSITION)
|
||||
return ..()
|
||||
|
||||
/// Simple signal handler that ensures that, if the owner stops standing, the offer no longer stands either!
|
||||
/datum/status_effect/offering/no_item_received/needs_resting/proc/check_owner_standing(mob/living/carbon/owner)
|
||||
/datum/status_effect/offering/no_item_received/needs_resting/proc/check_owner_standing(mob/living/owner)
|
||||
if(src.owner.body_position == STANDING_UP)
|
||||
return
|
||||
|
||||
@@ -331,7 +331,7 @@
|
||||
qdel(src)
|
||||
|
||||
/// Simple signal handler that ensures that, should a candidate now be standing up, the offer won't be standing for them anymore!
|
||||
/datum/status_effect/offering/no_item_received/needs_resting/proc/check_candidate_resting(mob/living/carbon/candidate)
|
||||
/datum/status_effect/offering/no_item_received/needs_resting/proc/check_candidate_resting(mob/living/candidate)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(candidate.body_position == LYING_DOWN)
|
||||
|
||||
@@ -113,11 +113,11 @@
|
||||
|
||||
/obj/item/organ/tongue/rat/on_mob_insert(mob/living/carbon/tongue_owner, special, movement_flags)
|
||||
. = ..()
|
||||
RegisterSignal(tongue_owner, COMSIG_CARBON_ITEM_GIVEN, PROC_REF(its_on_the_mouse))
|
||||
RegisterSignal(tongue_owner, COMSIG_LIVING_ITEM_GIVEN, PROC_REF(its_on_the_mouse))
|
||||
|
||||
/obj/item/organ/tongue/rat/on_mob_remove(mob/living/carbon/tongue_owner)
|
||||
. = ..()
|
||||
UnregisterSignal(tongue_owner, COMSIG_CARBON_ITEM_GIVEN)
|
||||
UnregisterSignal(tongue_owner, COMSIG_LIVING_ITEM_GIVEN)
|
||||
|
||||
/obj/item/organ/tongue/rat/proc/on_item_given(mob/living/carbon/offerer, mob/living/taker, obj/item/given)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
@@ -1482,28 +1482,35 @@
|
||||
stack_trace("Undefined handle_openspace_click() behaviour. Ascertain the openspace_item_click_handler element has been attached to the right item and that its proc override doesn't call parent.")
|
||||
|
||||
/**
|
||||
* * An interrupt for offering an item to other people, called mainly from [/mob/living/carbon/proc/give], in case you want to run your own offer behavior instead.
|
||||
* * An interrupt for offering an item to other people, called mainly from [/mob/living/proc/give], in case you want to run your own offer behavior instead.
|
||||
*
|
||||
* * Return TRUE if you want to interrupt the offer.
|
||||
*
|
||||
* * Arguments:
|
||||
* * offerer - The person offering the item.
|
||||
* * offered - The person being offered the item.
|
||||
* * offerer - The living mob offering the item.
|
||||
* * offered - The living mob being offered the item.
|
||||
*/
|
||||
/obj/item/proc/on_offered(mob/living/carbon/offerer, mob/living/carbon/offered)
|
||||
/obj/item/proc/on_offered(mob/living/offerer, mob/living/offered)
|
||||
if(!offered) // item has just been offered to anyone around
|
||||
if(!(HAS_TRAIT(offerer, TRAIT_CAN_HOLD_ITEMS)))
|
||||
return TRUE
|
||||
else if(!(HAS_TRAIT(offerer, TRAIT_CAN_HOLD_ITEMS) && HAS_TRAIT(offered, TRAIT_CAN_HOLD_ITEMS)))
|
||||
return TRUE // both must be able to hold items for this to make sense
|
||||
if(SEND_SIGNAL(src, COMSIG_ITEM_OFFERING, offerer) & COMPONENT_OFFER_INTERRUPT)
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* * An interrupt for someone trying to accept an offered item, called mainly from [/mob/living/carbon/proc/take], in case you want to run your own take behavior instead.
|
||||
* * An interrupt for someone trying to accept an offered item, called mainly from [/mob/living/proc/take], in case you want to run your own take behavior instead.
|
||||
*
|
||||
* * Return TRUE if you want to interrupt the taking.
|
||||
*
|
||||
* * Arguments:
|
||||
* * offerer - the person offering the item
|
||||
* * taker - the person trying to accept the offer
|
||||
* * offerer - the living mob offering the item
|
||||
* * taker - the living mob trying to accept the offer
|
||||
*/
|
||||
/obj/item/proc/on_offer_taken(mob/living/carbon/offerer, mob/living/carbon/taker)
|
||||
/obj/item/proc/on_offer_taken(mob/living/offerer, mob/living/taker)
|
||||
if(!(HAS_TRAIT(offerer, TRAIT_CAN_HOLD_ITEMS) && HAS_TRAIT(taker, TRAIT_CAN_HOLD_ITEMS)))
|
||||
return TRUE // both must be able to hold items for this to make sense
|
||||
if(SEND_SIGNAL(src, COMSIG_ITEM_OFFER_TAKEN, offerer, taker) & COMPONENT_OFFER_INTERRUPT)
|
||||
return TRUE
|
||||
|
||||
|
||||
@@ -341,7 +341,7 @@
|
||||
// Successful takes will qdel our hand after
|
||||
/obj/item/hand_item/slapper/on_offer_taken(mob/living/carbon/offerer, mob/living/carbon/taker)
|
||||
. = ..()
|
||||
if(!.)
|
||||
if(.)
|
||||
return
|
||||
|
||||
qdel(src)
|
||||
@@ -408,7 +408,11 @@
|
||||
|
||||
|
||||
/obj/item/hand_item/hand/on_offer_taken(mob/living/carbon/offerer, mob/living/carbon/taker)
|
||||
. = TRUE
|
||||
. = ..()
|
||||
if(!offerer || !taker)
|
||||
return TRUE // this doesn't make sense unless both are carbons
|
||||
if(.)
|
||||
return
|
||||
|
||||
if(taker.body_position == LYING_DOWN)
|
||||
taker.help_shake_act(offerer)
|
||||
@@ -518,6 +522,10 @@
|
||||
return TRUE
|
||||
|
||||
/obj/item/hand_item/kisser/on_offer_taken(mob/living/carbon/offerer, mob/living/carbon/taker)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
var/obj/projectile/blown_kiss = new kiss_type(get_turf(offerer))
|
||||
offerer.visible_message("<b>[offerer]</b> gives [taker] \a [blown_kiss][cheek_kiss ? " on the cheek" : ""]!!", span_notice("You give [taker] \a [blown_kiss][cheek_kiss ? " on the cheek" : ""]!"), ignored_mobs = taker)
|
||||
to_chat(taker, span_nicegreen("[offerer] gives you \a [blown_kiss][cheek_kiss ? " on the cheek" : ""]!"))
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
// unlike on_equip, this signal is triggered after the ball is removed from hands
|
||||
// so we can just use is_holding_item_of_type() proc to check for multiple balls
|
||||
if(!wielder.is_holding_item_of_type(/obj/item/toy/basketball))
|
||||
UnregisterSignal(wielder, list(COMSIG_MOVABLE_MOVED, COMSIG_MOB_EMOTED("spin"), COMSIG_LIVING_DISARM_HIT, COMSIG_LIVING_STATUS_KNOCKDOWN, COMSIG_MOB_THROW))
|
||||
UnregisterSignal(wielder, list(COMSIG_MOVABLE_MOVED, COMSIG_MOB_EMOTED("spin"), COMSIG_LIVING_DISARM_HIT, COMSIG_LIVING_STATUS_KNOCKDOWN))
|
||||
|
||||
wielder = null
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
. = ..()
|
||||
add_traits(list(TRAIT_ADVANCEDTOOLUSER, TRAIT_CAN_STRIP, TRAIT_CHUNKYFINGERS), ROUNDSTART_TRAIT)
|
||||
AddElement(/datum/element/wall_tearer, allow_reinforced = FALSE)
|
||||
AddElement(/datum/element/dextrous)
|
||||
AddElement(/datum/element/dextrous, can_throw = TRUE)
|
||||
AddElement(/datum/element/footstep, FOOTSTEP_MOB_BAREFOOT)
|
||||
AddElement(/datum/element/basic_eating, heal_amt = 10, food_types = gorilla_food)
|
||||
AddComponent(
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
/mob/living/basic/guardian/dextrous/Initialize(mapload, datum/guardian_fluff/theme)
|
||||
. = ..()
|
||||
add_traits(list(TRAIT_ADVANCEDTOOLUSER, TRAIT_CAN_STRIP), ROUNDSTART_TRAIT)
|
||||
AddElement(/datum/element/dextrous, hud_type = hud_type)
|
||||
AddElement(/datum/element/dextrous, hud_type = hud_type, can_throw = TRUE)
|
||||
AddComponent(/datum/component/personal_crafting)
|
||||
AddComponent(/datum/component/basic_inhands)
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
GLOB.carbon_list += src
|
||||
ADD_TRAIT(src, TRAIT_CAN_HOLD_ITEMS, INNATE_TRAIT) // Carbons are assumed to be innately capable of having arms, we check their arms count instead
|
||||
ADD_TRAIT(src, TRAIT_CAN_THROW_ITEMS, INNATE_TRAIT) // same here
|
||||
breathing_loop = new(src, _direct = TRUE)
|
||||
|
||||
/mob/living/carbon/Destroy()
|
||||
@@ -39,11 +40,6 @@
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
return .
|
||||
|
||||
/mob/living/carbon/click_ctrl_shift(mob/user)
|
||||
if(iscarbon(user))
|
||||
var/mob/living/carbon/carbon_user = user
|
||||
carbon_user.give(src)
|
||||
|
||||
/mob/living/carbon/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
|
||||
. = ..()
|
||||
var/hurt = TRUE
|
||||
@@ -105,123 +101,6 @@
|
||||
if(oof_noise)
|
||||
playsound(src,'sound/items/weapons/punch1.ogg',50,TRUE)
|
||||
|
||||
//Throwing stuff
|
||||
/mob/living/carbon/proc/toggle_throw_mode()
|
||||
if(stat)
|
||||
return
|
||||
if(throw_mode)
|
||||
throw_mode_off(THROW_MODE_TOGGLE)
|
||||
else
|
||||
throw_mode_on(THROW_MODE_TOGGLE)
|
||||
|
||||
|
||||
/mob/living/carbon/proc/throw_mode_off(method)
|
||||
if(throw_mode > method) //A toggle doesnt affect a hold
|
||||
return
|
||||
throw_mode = THROW_MODE_DISABLED
|
||||
if(hud_used)
|
||||
hud_used.throw_icon.icon_state = "act_throw"
|
||||
SEND_SIGNAL(src, COMSIG_LIVING_THROW_MODE_TOGGLE, throw_mode)
|
||||
|
||||
|
||||
/mob/living/carbon/proc/throw_mode_on(mode = THROW_MODE_TOGGLE)
|
||||
throw_mode = mode
|
||||
if(hud_used)
|
||||
hud_used.throw_icon.icon_state = "act_throw_on"
|
||||
SEND_SIGNAL(src, COMSIG_LIVING_THROW_MODE_TOGGLE, throw_mode)
|
||||
|
||||
/mob/proc/throw_item(atom/target)
|
||||
SEND_SIGNAL(src, COMSIG_MOB_THROW, target)
|
||||
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_CARBON_THROW_THING, src, target)
|
||||
return TRUE
|
||||
|
||||
/mob/living/carbon/throw_item(atom/target)
|
||||
. = ..()
|
||||
throw_mode_off(THROW_MODE_TOGGLE)
|
||||
if(!target || !isturf(loc))
|
||||
return FALSE
|
||||
if(istype(target, /atom/movable/screen))
|
||||
return FALSE
|
||||
var/atom/movable/thrown_thing
|
||||
var/obj/item/held_item = get_active_held_item()
|
||||
var/verb_text = pick("throw", "toss", "hurl", "chuck", "fling")
|
||||
if(prob(0.5))
|
||||
verb_text = "yeet"
|
||||
var/neckgrab_throw = FALSE // we can't check for if it's a neckgrab throw when totaling up power_throw since we've already stopped pulling them by then, so get it early
|
||||
var/frequency_number = 1 //We assign a default frequency number for the sound of the throw.
|
||||
if(!held_item)
|
||||
if(pulling && isliving(pulling) && grab_state >= GRAB_AGGRESSIVE)
|
||||
var/mob/living/throwable_mob = pulling
|
||||
if(!throwable_mob.buckled)
|
||||
thrown_thing = throwable_mob
|
||||
if(grab_state >= GRAB_NECK)
|
||||
neckgrab_throw = TRUE
|
||||
stop_pulling()
|
||||
if(HAS_TRAIT(src, TRAIT_PACIFISM) || HAS_TRAIT(src, TRAIT_NO_THROWING))
|
||||
to_chat(src, span_notice("You gently let go of [throwable_mob]."))
|
||||
return FALSE
|
||||
else
|
||||
thrown_thing = held_item.on_thrown(src, target)
|
||||
if(!thrown_thing)
|
||||
return FALSE
|
||||
if(isliving(thrown_thing))
|
||||
var/turf/start_T = get_turf(loc) //Get the start and target tile for the descriptors
|
||||
var/turf/end_T = get_turf(target)
|
||||
if(start_T && end_T)
|
||||
log_combat(src, thrown_thing, "thrown", addition="grab from tile in [AREACOORD(start_T)] towards tile at [AREACOORD(end_T)]")
|
||||
var/power_throw = 0
|
||||
var/extra_throw_range = HAS_TRAIT(src, TRAIT_THROWINGARM) ? 2 : 0
|
||||
|
||||
var/obj/item/organ/cyberimp/chest/spine/potential_spine = get_organ_slot(ORGAN_SLOT_SPINE)
|
||||
if(istype(potential_spine))
|
||||
power_throw += potential_spine.added_throw_speed
|
||||
extra_throw_range += potential_spine.added_throw_range
|
||||
|
||||
if(HAS_TRAIT(src, TRAIT_HULK))
|
||||
power_throw++
|
||||
if(HAS_TRAIT(src, TRAIT_DWARF))
|
||||
power_throw--
|
||||
if(HAS_TRAIT(thrown_thing, TRAIT_DWARF))
|
||||
power_throw++
|
||||
//SKYRAT EDIT ADDITION
|
||||
if(HAS_TRAIT(src, TRAIT_OVERSIZED))
|
||||
power_throw++
|
||||
if(HAS_TRAIT(thrown_thing, TRAIT_OVERSIZED))
|
||||
power_throw--
|
||||
//SKYRAT EDIT END
|
||||
if(neckgrab_throw)
|
||||
power_throw++
|
||||
if(HAS_TRAIT(src, TRAIT_TOSS_GUN_HARD) && isgun(thrown_thing))
|
||||
power_throw++
|
||||
if(isitem(thrown_thing))
|
||||
var/obj/item/thrown_item = thrown_thing
|
||||
frequency_number = 1-(thrown_item.w_class-3)/8 //At normal weight, the frequency is at 1. For tiny, it is 1.25. For huge, it is 0.75.
|
||||
if(thrown_item.throw_verb)
|
||||
verb_text = thrown_item.throw_verb
|
||||
do_attack_animation(target, no_effect = 1)
|
||||
var/sound/throwsound = 'sound/items/weapons/throw.ogg'
|
||||
var/power_throw_text = "."
|
||||
if(power_throw > 0) //If we have anything that boosts our throw power like hulk, we use the rougher heavier variant.
|
||||
throwsound = 'sound/items/weapons/throwhard.ogg'
|
||||
power_throw_text = " really hard!"
|
||||
if(power_throw < 0) //if we have anything that weakens our throw power like dward, we use a slower variant.
|
||||
throwsound = 'sound/items/weapons/throwsoft.ogg'
|
||||
power_throw_text = " flimsily."
|
||||
frequency_number = frequency_number + (rand(-5,5)/100); //Adds a bit of randomness in the frequency to not sound exactly the same.
|
||||
//The volume of the sound takes the minimum between the distance thrown or the max range an item, but no more than 50. Short throws are quieter. A fast throwing speed also makes the noise sharper.
|
||||
playsound(src, throwsound, clamp(8*min(get_dist(loc,target),thrown_thing.throw_range), 10, 50), vary = TRUE, extrarange = -1, frequency = frequency_number)
|
||||
visible_message(span_danger("[src] [verb_text][plural_s(verb_text)] [thrown_thing][power_throw_text]"), \
|
||||
span_danger("You [verb_text] [thrown_thing][power_throw_text]"))
|
||||
log_message("has thrown [thrown_thing] [power_throw_text]", LOG_ATTACK)
|
||||
|
||||
var/drift_force = max(0.5 NEWTONS, 1 NEWTONS + power_throw)
|
||||
if (isitem(thrown_thing))
|
||||
var/obj/item/thrown_item = thrown_thing
|
||||
drift_force *= WEIGHT_TO_NEWTONS(thrown_item.w_class)
|
||||
|
||||
newtonian_move(get_angle(target, src), drift_force = drift_force)
|
||||
thrown_thing.safe_throw_at(target, thrown_thing.throw_range + extra_throw_range, max(1,thrown_thing.throw_speed + power_throw), src, null, null, null, move_force)
|
||||
|
||||
/mob/living/carbon/proc/canBeHandcuffed()
|
||||
return FALSE
|
||||
|
||||
|
||||
@@ -417,95 +417,6 @@
|
||||
var/index = get_held_index_of_item(I)
|
||||
return index && hand_bodyparts[index]
|
||||
|
||||
/**
|
||||
* Proc called when offering an item to another player
|
||||
*
|
||||
* This handles creating an alert and adding an overlay to it
|
||||
*/
|
||||
/mob/living/carbon/proc/give(mob/living/carbon/offered)
|
||||
if(has_status_effect(/datum/status_effect/offering))
|
||||
to_chat(src, span_warning("You're already offering something!"))
|
||||
return
|
||||
|
||||
if(IS_DEAD_OR_INCAP(src))
|
||||
to_chat(src, span_warning("You're unable to offer anything in your current state!"))
|
||||
return
|
||||
|
||||
var/obj/item/offered_item = get_active_held_item()
|
||||
// if it's an abstract item, should consider it to be non-existent (unless it's a HAND_ITEM, which means it's an obj/item that is just a representation of our hand)
|
||||
if(!offered_item || ((offered_item.item_flags & ABSTRACT) && !(offered_item.item_flags & HAND_ITEM)))
|
||||
to_chat(src, span_warning("You're not holding anything to offer!"))
|
||||
return
|
||||
|
||||
if(offered)
|
||||
if(offered == src)
|
||||
if(!swap_hand(get_inactive_hand_index())) //have to swap hands first to take something
|
||||
to_chat(src, span_warning("You try to take [offered_item] from yourself, but fail."))
|
||||
return
|
||||
if(!put_in_active_hand(offered_item))
|
||||
to_chat(src, span_warning("You try to take [offered_item] from yourself, but fail."))
|
||||
return
|
||||
else
|
||||
to_chat(src, span_notice("You take [offered_item] from yourself."))
|
||||
return
|
||||
|
||||
if(IS_DEAD_OR_INCAP(offered))
|
||||
to_chat(src, span_warning("[offered.p_Theyre()] unable to take anything in [offered.p_their()] current state!"))
|
||||
return
|
||||
|
||||
if(!CanReach(offered))
|
||||
to_chat(src, span_warning("You have to be beside [offered.p_them()]!"))
|
||||
return
|
||||
else
|
||||
if(!(locate(/mob/living/carbon) in orange(1, src)))
|
||||
to_chat(src, span_warning("There's nobody beside you to take it!"))
|
||||
return
|
||||
|
||||
if(offered_item.on_offered(src)) // see if the item interrupts with its own behavior
|
||||
return
|
||||
|
||||
balloon_alert_to_viewers("offers something")
|
||||
visible_message(span_notice("[src] is offering [offered ? "[offered] " : ""][offered_item]."), \
|
||||
span_notice("You offer [offered ? "[offered] " : ""][offered_item]."), null, 2)
|
||||
|
||||
apply_status_effect(/datum/status_effect/offering, offered_item, null, offered)
|
||||
|
||||
/**
|
||||
* Proc called when the player clicks the give alert
|
||||
*
|
||||
* Handles checking if the player taking the item has open slots and is in range of the offerer
|
||||
* Also deals with the actual transferring of the item to the players hands
|
||||
* Arguments:
|
||||
* * offerer - The person giving the original item
|
||||
* * I - The item being given by the offerer
|
||||
*/
|
||||
/mob/living/carbon/proc/take(mob/living/carbon/offerer, obj/item/I)
|
||||
clear_alert("[offerer]")
|
||||
if(IS_DEAD_OR_INCAP(src))
|
||||
to_chat(src, span_warning("You're unable to take anything in your current state!"))
|
||||
return
|
||||
if(get_dist(src, offerer) > 1)
|
||||
to_chat(src, span_warning("[offerer] is out of range!"))
|
||||
return
|
||||
if(!I || offerer.get_active_held_item() != I)
|
||||
to_chat(src, span_warning("[offerer] is no longer holding the item they were offering!"))
|
||||
return
|
||||
if(!get_empty_held_indexes())
|
||||
to_chat(src, span_warning("You have no empty hands!"))
|
||||
return
|
||||
|
||||
if(I.on_offer_taken(offerer, src)) // see if the item has special behavior for being accepted
|
||||
return
|
||||
|
||||
if(!offerer.temporarilyRemoveItemFromInventory(I))
|
||||
visible_message(span_notice("[offerer] tries to hand over [I] but it's stuck to them...."))
|
||||
return
|
||||
|
||||
visible_message(span_notice("[src] takes [I] from [offerer]."), \
|
||||
span_notice("You take [I] from [offerer]."))
|
||||
I.do_pickup_animation(src, offerer)
|
||||
put_in_hands(I)
|
||||
|
||||
///Returns a list of all body_zones covered by clothing
|
||||
/mob/living/carbon/proc/get_covered_body_zones()
|
||||
RETURN_TYPE(/list)
|
||||
|
||||
@@ -0,0 +1,227 @@
|
||||
// Throwing stuff
|
||||
/mob/living/proc/toggle_throw_mode()
|
||||
if(stat)
|
||||
return
|
||||
if(!HAS_TRAIT(src, TRAIT_CAN_THROW_ITEMS))
|
||||
return
|
||||
if(throw_mode)
|
||||
throw_mode_off(THROW_MODE_TOGGLE)
|
||||
else
|
||||
throw_mode_on(THROW_MODE_TOGGLE)
|
||||
|
||||
|
||||
/mob/living/proc/throw_mode_off(method)
|
||||
if(!HAS_TRAIT(src, TRAIT_CAN_THROW_ITEMS))
|
||||
return
|
||||
if(throw_mode > method) //A toggle doesnt affect a hold
|
||||
return
|
||||
throw_mode = THROW_MODE_DISABLED
|
||||
if(hud_used)
|
||||
hud_used.throw_icon.icon_state = "act_throw"
|
||||
SEND_SIGNAL(src, COMSIG_LIVING_THROW_MODE_TOGGLE, throw_mode)
|
||||
|
||||
|
||||
/mob/living/proc/throw_mode_on(mode = THROW_MODE_TOGGLE)
|
||||
if(!HAS_TRAIT(src, TRAIT_CAN_THROW_ITEMS))
|
||||
return
|
||||
throw_mode = mode
|
||||
if(hud_used)
|
||||
hud_used.throw_icon.icon_state = "act_throw_on"
|
||||
SEND_SIGNAL(src, COMSIG_LIVING_THROW_MODE_TOGGLE, throw_mode)
|
||||
|
||||
/mob/proc/throw_item(atom/target)
|
||||
if(!HAS_TRAIT(src, TRAIT_CAN_THROW_ITEMS))
|
||||
return FALSE
|
||||
SEND_SIGNAL(src, COMSIG_MOB_THROW, target)
|
||||
return TRUE
|
||||
|
||||
/mob/living/throw_item(atom/target)
|
||||
. = ..()
|
||||
throw_mode_off(THROW_MODE_TOGGLE)
|
||||
if(!HAS_TRAIT(src, TRAIT_CAN_THROW_ITEMS))
|
||||
stack_trace("[src] tried to throw [target], but they shouldn't be able to throw things")
|
||||
return FALSE
|
||||
if(!target || !isturf(loc))
|
||||
return FALSE
|
||||
if(istype(target, /atom/movable/screen))
|
||||
return FALSE
|
||||
var/atom/movable/thrown_thing
|
||||
var/obj/item/held_item = get_active_held_item()
|
||||
var/verb_text = pick("throw", "toss", "hurl", "chuck", "fling")
|
||||
if(prob(0.5))
|
||||
verb_text = "yeet"
|
||||
var/neckgrab_throw = FALSE // we can't check for if it's a neckgrab throw when totaling up power_throw since we've already stopped pulling them by then, so get it early
|
||||
var/frequency_number = 1 //We assign a default frequency number for the sound of the throw.
|
||||
if(!held_item)
|
||||
if(pulling && isliving(pulling) && grab_state >= GRAB_AGGRESSIVE)
|
||||
var/mob/living/throwable_mob = pulling
|
||||
if(!throwable_mob.buckled)
|
||||
thrown_thing = throwable_mob
|
||||
if(grab_state >= GRAB_NECK)
|
||||
neckgrab_throw = TRUE
|
||||
stop_pulling()
|
||||
if(HAS_TRAIT(src, TRAIT_PACIFISM) || HAS_TRAIT(src, TRAIT_NO_THROWING))
|
||||
to_chat(src, span_notice("You gently let go of [throwable_mob]."))
|
||||
return FALSE
|
||||
else
|
||||
thrown_thing = held_item.on_thrown(src, target)
|
||||
if(!thrown_thing)
|
||||
return FALSE
|
||||
if(isliving(thrown_thing))
|
||||
var/turf/start_T = get_turf(loc) //Get the start and target tile for the descriptors
|
||||
var/turf/end_T = get_turf(target)
|
||||
if(start_T && end_T)
|
||||
log_combat(src, thrown_thing, "thrown", addition="grab from tile in [AREACOORD(start_T)] towards tile at [AREACOORD(end_T)]")
|
||||
var/power_throw = 0
|
||||
var/extra_throw_range = HAS_TRAIT(src, TRAIT_THROWINGARM) ? 2 : 0
|
||||
|
||||
var/obj/item/organ/cyberimp/chest/spine/potential_spine = get_organ_slot(ORGAN_SLOT_SPINE)
|
||||
if(istype(potential_spine))
|
||||
power_throw += potential_spine.added_throw_speed
|
||||
extra_throw_range += potential_spine.added_throw_range
|
||||
|
||||
if(HAS_TRAIT(src, TRAIT_HULK))
|
||||
power_throw++
|
||||
if(HAS_TRAIT(src, TRAIT_DWARF))
|
||||
power_throw--
|
||||
if(HAS_TRAIT(thrown_thing, TRAIT_DWARF))
|
||||
power_throw++
|
||||
//SKYRAT EDIT ADDITION
|
||||
if(HAS_TRAIT(src, TRAIT_OVERSIZED))
|
||||
power_throw++
|
||||
if(HAS_TRAIT(thrown_thing, TRAIT_OVERSIZED))
|
||||
power_throw--
|
||||
//SKYRAT EDIT END
|
||||
if(neckgrab_throw)
|
||||
power_throw++
|
||||
if(HAS_TRAIT(src, TRAIT_TOSS_GUN_HARD) && isgun(thrown_thing))
|
||||
power_throw++
|
||||
if(isitem(thrown_thing))
|
||||
var/obj/item/thrown_item = thrown_thing
|
||||
frequency_number = 1-(thrown_item.w_class-3)/8 //At normal weight, the frequency is at 1. For tiny, it is 1.25. For huge, it is 0.75.
|
||||
if(thrown_item.throw_verb)
|
||||
verb_text = thrown_item.throw_verb
|
||||
do_attack_animation(target, no_effect = 1)
|
||||
var/sound/throwsound = 'sound/items/weapons/throw.ogg'
|
||||
var/power_throw_text = "."
|
||||
if(power_throw > 0) //If we have anything that boosts our throw power like hulk, we use the rougher heavier variant.
|
||||
throwsound = 'sound/items/weapons/throwhard.ogg'
|
||||
power_throw_text = " really hard!"
|
||||
if(power_throw < 0) //if we have anything that weakens our throw power like dward, we use a slower variant.
|
||||
throwsound = 'sound/items/weapons/throwsoft.ogg'
|
||||
power_throw_text = " flimsily."
|
||||
frequency_number = frequency_number + (rand(-5,5)/100); //Adds a bit of randomness in the frequency to not sound exactly the same.
|
||||
//The volume of the sound takes the minimum between the distance thrown or the max range an item, but no more than 50. Short throws are quieter. A fast throwing speed also makes the noise sharper.
|
||||
playsound(src, throwsound, clamp(8*min(get_dist(loc,target),thrown_thing.throw_range), 10, 50), vary = TRUE, extrarange = -1, frequency = frequency_number)
|
||||
visible_message(span_danger("[src] [verb_text][plural_s(verb_text)] [thrown_thing][power_throw_text]"), \
|
||||
span_danger("You [verb_text] [thrown_thing][power_throw_text]"))
|
||||
log_message("has thrown [thrown_thing] [power_throw_text]", LOG_ATTACK)
|
||||
|
||||
var/drift_force = max(0.5 NEWTONS, 1 NEWTONS + power_throw)
|
||||
if (isitem(thrown_thing))
|
||||
var/obj/item/thrown_item = thrown_thing
|
||||
drift_force *= WEIGHT_TO_NEWTONS(thrown_item.w_class)
|
||||
|
||||
newtonian_move(get_angle(target, src), drift_force = drift_force)
|
||||
thrown_thing.safe_throw_at(target, thrown_thing.throw_range + extra_throw_range, max(1,thrown_thing.throw_speed + power_throw), src, null, null, null, move_force)
|
||||
|
||||
// Giving stuff
|
||||
/**
|
||||
* Proc called when offering an item to another player
|
||||
*
|
||||
* This handles creating an alert and adding an overlay to it
|
||||
* Arguments:
|
||||
* * offered - The player being offered the item (optional, if null the offer is to everyone around)
|
||||
*/
|
||||
/mob/living/proc/give(mob/living/offered)
|
||||
if(has_status_effect(/datum/status_effect/offering))
|
||||
to_chat(src, span_warning("You're already offering something!"))
|
||||
return
|
||||
|
||||
if(IS_DEAD_OR_INCAP(src))
|
||||
to_chat(src, span_warning("You're unable to offer anything in your current state!"))
|
||||
return
|
||||
|
||||
var/obj/item/offered_item = get_active_held_item()
|
||||
// if it's an abstract item, should consider it to be non-existent (unless it's a HAND_ITEM, which means it's an obj/item that is just a representation of our hand)
|
||||
if(!offered_item || ((offered_item.item_flags & ABSTRACT) && !(offered_item.item_flags & HAND_ITEM)))
|
||||
to_chat(src, span_warning("You're not holding anything to offer!"))
|
||||
return
|
||||
|
||||
if(offered)
|
||||
if(offered == src)
|
||||
if(!swap_hand(get_inactive_hand_index())) //have to swap hands first to take something
|
||||
to_chat(src, span_warning("You try to take [offered_item] from yourself, but fail."))
|
||||
return
|
||||
if(!put_in_active_hand(offered_item))
|
||||
to_chat(src, span_warning("You try to take [offered_item] from yourself, but fail."))
|
||||
return
|
||||
else
|
||||
to_chat(src, span_notice("You take [offered_item] from yourself."))
|
||||
return
|
||||
|
||||
if(IS_DEAD_OR_INCAP(offered))
|
||||
to_chat(src, span_warning("[offered.p_Theyre()] unable to take anything in [offered.p_their()] current state!"))
|
||||
return
|
||||
|
||||
if(!CanReach(offered))
|
||||
to_chat(src, span_warning("You have to be beside [offered.p_them()]!"))
|
||||
return
|
||||
|
||||
if(!HAS_TRAIT(offered, TRAIT_CAN_HOLD_ITEMS))
|
||||
to_chat(src, span_warning("[offered.p_They()] can't hold anything you offer!"))
|
||||
return
|
||||
else if(!(locate(/mob/living) in orange(1, src)))
|
||||
to_chat(src, span_warning("There's nobody beside you to take it!"))
|
||||
return
|
||||
|
||||
if(offered_item.on_offered(src)) // see if the item interrupts with its own behavior
|
||||
return
|
||||
|
||||
balloon_alert_to_viewers("offers something")
|
||||
visible_message(span_notice("[src] is offering [offered ? "[offered] " : ""][offered_item]."), \
|
||||
span_notice("You offer [offered ? "[offered] " : ""][offered_item]."), null, 2)
|
||||
|
||||
apply_status_effect(/datum/status_effect/offering, offered_item, null, offered)
|
||||
|
||||
/**
|
||||
* Proc called when the player clicks the give alert
|
||||
*
|
||||
* Handles checking if the player taking the item has open slots and is in range of the offerer
|
||||
* Also deals with the actual transferring of the item to the players hands
|
||||
* Arguments:
|
||||
* * offerer - The living mob giving the original item
|
||||
* * offered_item - The item being given by the offerer
|
||||
*/
|
||||
/mob/living/proc/take(mob/living/offerer, obj/item/offered_item)
|
||||
clear_alert("[offerer]")
|
||||
if(IS_DEAD_OR_INCAP(src))
|
||||
to_chat(src, span_warning("You're unable to take anything in your current state!"))
|
||||
return
|
||||
if(get_dist(src, offerer) > 1)
|
||||
to_chat(src, span_warning("[offerer] is out of range!"))
|
||||
return
|
||||
if(!offered_item || offerer.get_active_held_item() != offered_item)
|
||||
to_chat(src, span_warning("[offerer] is no longer holding the item they were offering!"))
|
||||
return
|
||||
if(!get_empty_held_indexes())
|
||||
to_chat(src, span_warning("You have no empty hands!"))
|
||||
return
|
||||
|
||||
if(offered_item.on_offer_taken(offerer, src)) // see if the item has special behavior for being accepted
|
||||
return
|
||||
|
||||
if(!offerer.temporarilyRemoveItemFromInventory(offered_item))
|
||||
visible_message(span_notice("[offerer] tries to hand over [offered_item] but it's stuck to them...."))
|
||||
return
|
||||
|
||||
visible_message(span_notice("[src] takes [offered_item] from [offerer]."), \
|
||||
span_notice("You take [offered_item] from [offerer]."))
|
||||
offered_item.do_pickup_animation(src, offerer)
|
||||
put_in_hands(offered_item)
|
||||
|
||||
|
||||
/mob/living/click_ctrl_shift(mob/user)
|
||||
if(HAS_TRAIT(src, TRAIT_CAN_HOLD_ITEMS))
|
||||
var/mob/living/living_user = user
|
||||
living_user.give(src)
|
||||
+1
-1
@@ -1835,7 +1835,6 @@
|
||||
#include "code\datums\keybinding\_keybindings.dm"
|
||||
#include "code\datums\keybinding\admin.dm"
|
||||
#include "code\datums\keybinding\artificial_intelligence.dm"
|
||||
#include "code\datums\keybinding\carbon.dm"
|
||||
#include "code\datums\keybinding\client.dm"
|
||||
#include "code\datums\keybinding\communication.dm"
|
||||
#include "code\datums\keybinding\emote.dm"
|
||||
@@ -5083,6 +5082,7 @@
|
||||
#include "code\modules\mob\living\living_defense.dm"
|
||||
#include "code\modules\mob\living\living_defines.dm"
|
||||
#include "code\modules\mob\living\living_fov.dm"
|
||||
#include "code\modules\mob\living\living_item_handling.dm"
|
||||
#include "code\modules\mob\living\living_movement.dm"
|
||||
#include "code\modules\mob\living\living_say.dm"
|
||||
#include "code\modules\mob\living\living_update_icons.dm"
|
||||
|
||||
Reference in New Issue
Block a user