From 72841c9e70e360c859d1de729d8bd569a13c9a6d Mon Sep 17 00:00:00 2001 From: Crazylemon64 Date: Mon, 1 May 2017 04:22:13 -0700 Subject: [PATCH] Refactors TK to work a bit more consistently Also allows remote stack manipulation shenanigans --- code/_onclick/telekinesis.dm | 49 ++++++++++++++----- code/game/objects/items.dm | 7 +++ code/game/objects/items/crayons.dm | 6 +-- code/game/objects/items/stacks/rods.dm | 2 +- code/game/objects/items/stacks/stack.dm | 34 ++++++++++--- code/game/objects/items/weapons/RCD.dm | 3 ++ code/game/objects/items/weapons/explosives.dm | 2 +- .../objects/items/weapons/flamethrower.dm | 2 +- .../objects/items/weapons/grenades/grenade.dm | 2 +- .../objects/items/weapons/storage/storage.dm | 2 +- .../objects/items/weapons/teleportation.dm | 2 +- code/modules/food_and_drinks/food/snacks.dm | 2 +- .../mining/lavaland/loot/hierophant_loot.dm | 2 +- code/modules/mob/inventory.dm | 14 ++++++ code/modules/mob/living/carbon/carbon.dm | 13 ++--- code/modules/mob/mob.dm | 3 ++ code/modules/mob/mob_defines.dm | 2 + code/modules/nano/interaction/inventory.dm | 2 +- code/modules/paperwork/paper_bundle.dm | 2 +- code/modules/paperwork/photography.dm | 2 +- 20 files changed, 114 insertions(+), 39 deletions(-) diff --git a/code/_onclick/telekinesis.dm b/code/_onclick/telekinesis.dm index 637c5650f3a..86f37b17c07 100644 --- a/code/_onclick/telekinesis.dm +++ b/code/_onclick/telekinesis.dm @@ -32,21 +32,15 @@ var/const/tk_maxrange = 15 return var/obj/item/tk_grab/O = new(src) - user.put_in_active_hand(O) - O.host = user - O.focus_object(src) - return + O.form_grab(user, src) /obj/item/attack_tk(mob/user) if(user.stat || !isturf(loc)) return if((TK in user.mutations) && !user.get_active_hand()) // both should already be true to get here var/obj/item/tk_grab/O = new(src) - user.put_in_active_hand(O) - O.host = user - O.focus_object(src) + O.form_grab(user, src) else warning("Strange attack_tk(): TK([TK in user.mutations]) empty hand([!user.get_active_hand()])") - return /mob/attack_tk(mob/user) @@ -75,6 +69,12 @@ var/const/tk_maxrange = 15 var/atom/movable/focus = null var/mob/living/host = null +/obj/item/tk_grab/Destroy() + if(focus) + release_object() + // Focus is null now + host = null + return ..() /obj/item/tk_grab/dropped(mob/user as mob) if(focus && user && loc != user && loc != user.loc) // drop_item() gets called when you tk-attack a table/closet with an item @@ -94,6 +94,10 @@ var/const/tk_maxrange = 15 if(focus) focus.attack_self_tk(user) +/obj/item/tk_grab/override_throw(mob/user, atom/target) + afterattack(target, user) + return TRUE + /obj/item/tk_grab/afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, proximity, params)//TODO: go over this if(!target || !user) return if(last_throw+3 > world.time) return @@ -122,7 +126,7 @@ var/const/tk_maxrange = 15 return // todo: something like attack_self not laden with assumptions inherent to attack_self - if(!istype(target, /turf) && istype(focus,/obj/item) && target.Adjacent(focus)) + if(istype(focus,/obj/item) && target.Adjacent(focus) && !user.in_throw_mode) var/obj/item/I = focus var/resolved = target.attackby(I, user, params) if(!resolved && target && I) @@ -137,8 +141,12 @@ var/const/tk_maxrange = 15 /obj/item/tk_grab/attack(mob/living/M as mob, mob/living/user as mob, def_zone) return +/obj/item/tk_grab/is_equivalent(obj/item/I) + . = ..() + if(!.) + return I == focus -/obj/item/tk_grab/proc/focus_object(var/obj/target, var/mob/living/user) +/obj/item/tk_grab/proc/focus_object(var/obj/target, var/mob/user) if(!istype(target,/obj)) return//Cant throw non objects atm might let it do mobs later if(target.anchored || !isturf(target.loc)) qdel(src) @@ -146,11 +154,25 @@ var/const/tk_maxrange = 15 focus = target update_icon() apply_focus_overlay() - return + // Make it behave like other equipment + if(istype(target, /obj/item)) + if(target in user.tkgrabbed_objects) + // Release the old grab first + user.unEquip(user.tkgrabbed_objects[target]) + user.tkgrabbed_objects[target] = src +/obj/item/tk_grab/proc/release_object() + if(!focus) + return + if(istype(focus, /obj/item)) + // Delete the key/value pair of item to TK grab + host.tkgrabbed_objects -= focus + focus = null + update_icon() /obj/item/tk_grab/proc/apply_focus_overlay() if(!focus) return + // Oh jeez ow var/obj/effect/overlay/O = new /obj/effect/overlay(locate(focus.x,focus.y,focus.z)) O.name = "sparkles" O.anchored = 1 @@ -163,6 +185,11 @@ var/const/tk_maxrange = 15 spawn(5) qdel(O) +/obj/item/tk_grab/proc/form_grab(mob/user, obj/target) + user.put_in_active_hand(src) + host = user + focus_object(target, user) + /obj/item/tk_grab/update_icon() overlays.Cut() diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 00eb1bd6884..ae198664806 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -558,3 +558,10 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d /obj/item/proc/is_crutch() //Does an item prop up a human mob and allow them to stand if they are missing a leg/foot? return 0 + +// Return true if you don't want regular throw handling +/obj/item/proc/override_throw(mob/user, atom/target) + return FALSE + +/obj/item/proc/is_equivalent(obj/item/I) + return I == src diff --git a/code/game/objects/items/crayons.dm b/code/game/objects/items/crayons.dm index 63c00e1a5ad..62f8071eac7 100644 --- a/code/game/objects/items/crayons.dm +++ b/code/game/objects/items/crayons.dm @@ -73,7 +73,7 @@ temp = pick(graffiti) else temp = href_list["type"] - if((usr.restrained() || usr.stat || usr.get_active_hand() != src)) + if((usr.restrained() || usr.stat || !usr.is_in_active_hand(src))) return drawtype = temp update_window(usr) @@ -167,7 +167,7 @@ ..() /obj/item/toy/crayon/mime/Topic(href,href_list) - if((usr.restrained() || usr.stat || usr.get_active_hand() != src)) + if((usr.restrained() || usr.stat || usr.is_in_active_hand(src))) return if(href_list["color"]) if(colour != "#FFFFFF") @@ -195,7 +195,7 @@ if(href_list["color"]) var/temp = input(usr, "Please select colour.", "Crayon colour") as color - if((usr.restrained() || usr.stat || usr.get_active_hand() != src)) + if((usr.restrained() || usr.stat || usr.is_in_active_hand(src))) return colour = temp update_window(usr) diff --git a/code/game/objects/items/stacks/rods.dm b/code/game/objects/items/stacks/rods.dm index 96d5d381a72..9de205d483c 100644 --- a/code/game/objects/items/stacks/rods.dm +++ b/code/game/objects/items/stacks/rods.dm @@ -55,7 +55,7 @@ var/global/list/datum/stack_recipe/rod_recipes = list ( \ "You shape [src] into metal with the welding tool.", \ "You hear welding.") - var/replace = user.get_inactive_hand() == src + var/replace = user.is_in_inactive_hand(src) use(2) if(get_amount() <= 0 && replace) user.unEquip(src, 1) diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm index d4d4ae7f48c..eeacb71e9b3 100644 --- a/code/game/objects/items/stacks/stack.dm +++ b/code/game/objects/items/stacks/stack.dm @@ -36,6 +36,23 @@ /obj/item/stack/attack_self(mob/user) list_recipes(user) +/obj/item/stack/attack_self_tk(mob/user) + list_recipes(user) + +/obj/item/stack/attack_tk(mob/user) + if(user.stat || !isturf(loc)) return + // Allow remote stack splitting, because telekinetic inventory managing + // is really cool + if(src in user.tkgrabbed_objects) + var/obj/item/stack/F = split(user, 1) + F.attack_tk(user) + if(src && user.machine == src) + spawn(0) + interact(user) + else + ..() + + /obj/item/stack/proc/list_recipes(mob/user, recipes_sublist) if(!recipes) return @@ -107,7 +124,7 @@ /obj/item/stack/Topic(href, href_list) ..() - if(usr.incapacitated() || usr.get_active_hand() != src) + if(usr.incapacitated() || !usr.is_in_active_hand(src)) return 0 if(href_list["sublist"] && !href_list["make"]) @@ -124,6 +141,7 @@ var/datum/stack_recipe/R = recipes_list[text2num(href_list["make"])] var/multiplier = text2num(href_list["multiplier"]) + var/atom/creation_loc = (loc == usr) ? usr.loc : loc if(!multiplier) multiplier = 1 @@ -134,11 +152,11 @@ to_chat(usr, "You haven't got enough [src] to build \the [R.title]!") return 0 - if(R.one_per_turf && (locate(R.result_type) in usr.loc)) + if(R.one_per_turf && (locate(R.result_type) in creation_loc)) to_chat(usr, "There is another [R.title] here!") return 0 - if(R.on_floor && !istype(usr.loc, /turf/simulated)) + if(R.on_floor && !istype(creation_loc, /turf/simulated)) to_chat(usr, "\The [R.title] must be constructed on the floor!") return 0 @@ -150,7 +168,7 @@ if(amount < R.req_amount * multiplier) return - var/atom/O = new R.result_type(usr.loc) + var/atom/O = new R.result_type(creation_loc) O.dir = usr.dir if(R.max_res_amount > 1) var/obj/item/stack/new_item = O @@ -215,7 +233,7 @@ return max_amount /obj/item/stack/proc/split(mob/user, amt) - var/obj/item/stack/F = new type(user, amt) + var/obj/item/stack/F = new type(loc, amt) F.copy_evidences(src) if(isliving(user)) add_fingerprint(user) @@ -224,7 +242,7 @@ return F /obj/item/stack/attack_hand(mob/user) - if(user.get_inactive_hand() == src) + if(user.is_in_inactive_hand(src)) var/obj/item/stack/F = split(user, 1) user.put_in_hands(F) if(src && usr.machine == src) @@ -241,7 +259,7 @@ return 1 var/to_transfer - if(user.get_inactive_hand() == src) + if(user.is_in_inactive_hand(src)) var/desired = input("How much would you like to transfer from this stack?", "How much?", 1) as null|num if(!desired) return @@ -267,4 +285,4 @@ fingerprints = from.fingerprints fingerprintshidden = from.fingerprintshidden fingerprintslast = from.fingerprintslast - //TODO bloody overlay \ No newline at end of file + //TODO bloody overlay diff --git a/code/game/objects/items/weapons/RCD.dm b/code/game/objects/items/weapons/RCD.dm index 21bfc03c700..3e79df2c213 100644 --- a/code/game/objects/items/weapons/RCD.dm +++ b/code/game/objects/items/weapons/RCD.dm @@ -84,6 +84,9 @@ RCD //Change the mode ui_interact(user) +/obj/item/weapon/rcd/attack_self_tk(mob/user) + ui_interact(user) + /obj/item/weapon/rcd/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = inventory_state) ui = nanomanager.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) diff --git a/code/game/objects/items/weapons/explosives.dm b/code/game/objects/items/weapons/explosives.dm index ea89aab651c..58de51085de 100644 --- a/code/game/objects/items/weapons/explosives.dm +++ b/code/game/objects/items/weapons/explosives.dm @@ -61,7 +61,7 @@ nadeassembly.attack_self(user) return var/newtime = input(usr, "Please set the timer.", "Timer", 10) as num - if(user.get_active_hand() == src) + if(user.is_in_active_hand(src)) newtime = Clamp(newtime, 10, 60000) det_time = newtime to_chat(user, "Timer set for [det_time] seconds.") diff --git a/code/game/objects/items/weapons/flamethrower.dm b/code/game/objects/items/weapons/flamethrower.dm index f02eb57ae8b..024783359b5 100644 --- a/code/game/objects/items/weapons/flamethrower.dm +++ b/code/game/objects/items/weapons/flamethrower.dm @@ -62,7 +62,7 @@ /obj/item/weapon/flamethrower/afterattack(atom/target, mob/user, flag) if(flag) return // too close // Make sure our user is still holding us - if(user && user.get_active_hand() == src) + if(user && user.is_in_active_hand(src)) var/turf/target_turf = get_turf(target) if(target_turf) var/turflist = getline(user, target_turf) diff --git a/code/game/objects/items/weapons/grenades/grenade.dm b/code/game/objects/items/weapons/grenades/grenade.dm index 88abd66913f..a5998591d08 100644 --- a/code/game/objects/items/weapons/grenades/grenade.dm +++ b/code/game/objects/items/weapons/grenades/grenade.dm @@ -32,7 +32,7 @@ /*/obj/item/weapon/grenade/afterattack(atom/target as mob|obj|turf|area, mob/user as mob) if(istype(target, /obj/item/weapon/storage)) return ..() // Trying to put it in a full container if(istype(target, /obj/item/weapon/gun/grenadelauncher)) return ..() - if((user.get_active_hand() == src) && (!active) && (clown_check(user)) && target.loc != src.loc) + if((user.is_in_active_hand(src)) && (!active) && (clown_check(user)) && target.loc != src.loc) to_chat(user, "You prime the [name]! [det_time/10] seconds!") active = 1 icon_state = initial(icon_state) + "_active" diff --git a/code/game/objects/items/weapons/storage/storage.dm b/code/game/objects/items/weapons/storage/storage.dm index 21ea7c33993..5931696b599 100644 --- a/code/game/objects/items/weapons/storage/storage.dm +++ b/code/game/objects/items/weapons/storage/storage.dm @@ -478,7 +478,7 @@ /obj/item/weapon/storage/attack_self(mob/user as mob) //Clicking on itself will empty it, if it has the verb to do that. - if(user.get_active_hand() == src) + if(user.is_in_active_hand(src)) if(src.verbs.Find(/obj/item/weapon/storage/verb/quick_empty)) src.quick_empty() return diff --git a/code/game/objects/items/weapons/teleportation.dm b/code/game/objects/items/weapons/teleportation.dm index 0a984821fad..c07c658a7bf 100644 --- a/code/game/objects/items/weapons/teleportation.dm +++ b/code/game/objects/items/weapons/teleportation.dm @@ -128,7 +128,7 @@ Frequency: if(turfs.len) L["None (Dangerous)"] = pick(turfs) var/t1 = input(user, "Please select a teleporter to lock in on.", "Hand Teleporter") as null|anything in L - if(!t1 || (user.get_active_hand() != src || user.stat || user.restrained())) + if(!t1 || (user.is_in_active_hand(src) || user.stat || user.restrained())) return if(active_portals >= 3) user.show_message("\The [src] is recharging!") diff --git a/code/modules/food_and_drinks/food/snacks.dm b/code/modules/food_and_drinks/food/snacks.dm index f98f870ed79..dff9db46582 100644 --- a/code/modules/food_and_drinks/food/snacks.dm +++ b/code/modules/food_and_drinks/food/snacks.dm @@ -2097,7 +2097,7 @@ return if(boxes.len > 0) - if(user.get_inactive_hand() != src) + if(user.is_in_inactive_hand(src)) ..() return diff --git a/code/modules/mining/lavaland/loot/hierophant_loot.dm b/code/modules/mining/lavaland/loot/hierophant_loot.dm index 64689a3a535..e613b2ab276 100644 --- a/code/modules/mining/lavaland/loot/hierophant_loot.dm +++ b/code/modules/mining/lavaland/loot/hierophant_loot.dm @@ -52,7 +52,7 @@ friendly_fire_check = !friendly_fire_check to_chat(user, "You toggle friendly fire [friendly_fire_check ? "off":"on"]!") return - if(user.get_active_hand() != src && user.get_inactive_hand() != src) //you need to hold the staff to teleport + if(user.is_in_active_hand(src) && user.is_in_inactive_hand(src)) //you need to hold the staff to teleport to_chat(user, "You need to hold the staff in your hands to [rune ? "teleport with it" : "create a rune"]!") return if(!rune) diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm index 5d746603418..7236fe57fde 100644 --- a/code/modules/mob/inventory.dm +++ b/code/modules/mob/inventory.dm @@ -6,11 +6,22 @@ if(hand) return l_hand else return r_hand +/mob/proc/is_in_active_hand(obj/item/I) + var/obj/item/item_to_test = get_active_hand() + + return item_to_test && item_to_test.is_equivalent(I) + + //Returns the thing in our inactive hand /mob/proc/get_inactive_hand() if(hand) return r_hand else return l_hand +/mob/proc/is_in_inactive_hand(obj/item/I) + var/obj/item/item_to_test = get_inactive_hand() + + return item_to_test && item_to_test.is_equivalent(I) + //Returns if a certain item can be equipped to a certain slot. // Currently invalid for two-handed items - call obj/item/mob_can_equip() instead. /mob/proc/can_equip(obj/item/I, slot, disable_warning = 0) @@ -119,6 +130,9 @@ else if(I == l_hand) l_hand = null update_inv_l_hand() + else if(I in tkgrabbed_objects) + var/obj/item/tk_grab/tkgrab = tkgrabbed_objects[I] + unEquip(tkgrab, force) if(I) if(client) diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 0848a90e8c0..5d027c8eab1 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -535,18 +535,19 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump, return /mob/living/carbon/throw_item(atom/target) - throw_mode_off() - if(!target || !isturf(loc)) - return - if(istype(target, /obj/screen)) + if(!target || !isturf(loc) || istype(target, /obj/screen)) + throw_mode_off() return - var/atom/movable/thrown_thing var/obj/item/I = src.get_active_hand() - if(!I || (I.flags & NODROP)) + if(!I || I.override_throw(src, target) || (I.flags & NODROP)) + throw_mode_off() return + throw_mode_off() + var/atom/movable/thrown_thing + if(istype(I, /obj/item/weapon/grab)) var/obj/item/weapon/grab/G = I var/mob/throwable_mob = G.get_mob_if_throwable() //throw the person instead of the grab diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index cb86d417fbc..1d8c0aa840a 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -11,6 +11,9 @@ for(var/mob/dead/observer/M in following_mobs) M.following = null following_mobs = null + for(var/I in tkgrabbed_objects) + qdel(tkgrabbed_objects[I]) + tkgrabbed_objects = null if(buckled) buckled.unbuckle_mob() if(viewing_alternate_appearances) diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 959913972fa..700e5d912e7 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -198,3 +198,5 @@ var/list/actions = list() var/list/progressbars = null //for stacking do_after bars + + var/list/tkgrabbed_objects = list() // Assoc list of items to TK grabs diff --git a/code/modules/nano/interaction/inventory.dm b/code/modules/nano/interaction/inventory.dm index ccfbb695a99..cbe5165e5ff 100644 --- a/code/modules/nano/interaction/inventory.dm +++ b/code/modules/nano/interaction/inventory.dm @@ -4,7 +4,7 @@ /var/global/datum/topic_state/inventory_state/inventory_state = new() /datum/topic_state/inventory_state/can_use_topic(var/src_object, var/mob/user) - if(!(src_object in user)) + if(!((src_object in user) || user.is_in_active_hand(src_object) || user.is_in_inactive_hand(src_object))) return STATUS_CLOSE return user.shared_nano_interaction() diff --git a/code/modules/paperwork/paper_bundle.dm b/code/modules/paperwork/paper_bundle.dm index 2a7c7e113e1..f5d10cef156 100644 --- a/code/modules/paperwork/paper_bundle.dm +++ b/code/modules/paperwork/paper_bundle.dm @@ -87,7 +87,7 @@ user.visible_message("[class][user] burns right through \the [src], turning it to ash. It flutters through the air before settling on the floor in a heap.", \ "[class]You burn right through \the [src], turning it to ash. It flutters through the air before settling on the floor in a heap.") - if(user.get_inactive_hand() == src) + if(user.is_in_inactive_hand(src)) user.unEquip(src) new /obj/effect/decal/cleanable/ash(get_turf(src)) diff --git a/code/modules/paperwork/photography.dm b/code/modules/paperwork/photography.dm index dc86ce2299a..5797107e502 100644 --- a/code/modules/paperwork/photography.dm +++ b/code/modules/paperwork/photography.dm @@ -64,7 +64,7 @@ user.visible_message("[class][user] burns right through \the [src], turning it to ash. It flutters through the air before settling on the floor in a heap.", \ "[class]You burn right through \the [src], turning it to ash. It flutters through the air before settling on the floor in a heap.") - if(user.get_inactive_hand() == src) + if(user.is_in_inactive_hand(src)) user.unEquip(src) new /obj/effect/decal/cleanable/ash(get_turf(src))