mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2026-07-17 11:14:11 +01:00
[MIRROR] cleans up robot gripper code (#12388)
Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com> Co-authored-by: Cameron Lennox <killer65311@gmail.com>
This commit is contained in:
committed by
GitHub
parent
a450bdfcf0
commit
cbb200e0db
@@ -345,14 +345,6 @@ Checks if a list has the same entries and values as an element of big.
|
||||
* Sorting
|
||||
*/
|
||||
|
||||
//Reverses the order of items in the list
|
||||
/proc/reverselist(list/L)
|
||||
var/list/output = list()
|
||||
if(L)
|
||||
for(var/i = L.len; i >= 1; i--)
|
||||
output += L[i]
|
||||
return output
|
||||
|
||||
//Randomize: Return the list in a random order
|
||||
/proc/shuffle(var/list/L)
|
||||
if(!L)
|
||||
@@ -608,7 +600,7 @@ Checks if a list has the same entries and values as an element of big.
|
||||
//to_world_log("descending len input: [L.len]")
|
||||
var/list/out = insertion_sort_numeric_list_ascending(L)
|
||||
//to_world_log(" output: [out.len]")
|
||||
return reverselist(out)
|
||||
return reverseList(out)
|
||||
|
||||
/proc/dd_sortedObjectList(var/list/L, var/cache=list())
|
||||
if(L.len < 2)
|
||||
|
||||
@@ -64,7 +64,7 @@ avoid code duplication. This includes items that may sometimes act as a standard
|
||||
return A.attackby(src, user, attack_modifier, click_parameters)
|
||||
|
||||
// No comment
|
||||
/atom/proc/attackby(obj/item/W, mob/user, var/attack_modifier, var/click_parameters)
|
||||
/atom/proc/attackby(obj/item/W, mob/user, attack_modifier, click_parameters)
|
||||
if(SEND_SIGNAL(src, COMSIG_ATOM_ATTACKBY, W, user, click_parameters) & COMPONENT_CANCEL_ATTACK_CHAIN)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
@@ -171,6 +171,12 @@ handles linking back and forth.
|
||||
if(istype(target, /obj/item/storage/bag/sheetsnatcher))
|
||||
return mat_container.OnSheetSnatcher(source, user, target)
|
||||
|
||||
if(istype(target, /obj/item/gripper))
|
||||
var/obj/item/gripper/robot_gripper = target
|
||||
target = robot_gripper.get_wrapped_item()
|
||||
attempt_insert(user, target)
|
||||
return FALSE
|
||||
|
||||
return attempt_insert(user, target)
|
||||
|
||||
/// Insert mats into silo
|
||||
|
||||
@@ -121,7 +121,7 @@
|
||||
else
|
||||
if(istype(I,/obj/item/gripper)) //Behold, Grippers and their horribleness. If ..() is called by any computers' attackby() now or in the future, this should let grippers work with them appropriately.
|
||||
var/obj/item/gripper/B = I //B, for Borg.
|
||||
var/obj/item/wrapped = B.get_current_pocket()
|
||||
var/obj/item/wrapped = B.get_wrapped_item()
|
||||
if(!wrapped)
|
||||
to_chat(user, "\The [B] is not holding anything.")
|
||||
return
|
||||
|
||||
@@ -294,8 +294,10 @@
|
||||
max_days = 30
|
||||
if(12)
|
||||
max_days = 31
|
||||
|
||||
var/new_day = tgui_input_number(user, "Choose your character's birth day (number, 1-[max_days])", "Birthday Day", pref.read_preference(/datum/preference/numeric/human/bday_day), max_days, 0)
|
||||
var/old_days = pref.read_preference(/datum/preference/numeric/human/bday_day)
|
||||
if(old_days > max_days)
|
||||
old_days = max_days
|
||||
var/new_day = tgui_input_number(user, "Choose your character's birth day (number, 1-[max_days])", "Birthday Day", old_days, max_days, 0)
|
||||
if(new_day)
|
||||
pref.update_preference_by_type(/datum/preference/numeric/human/bday_day, new_day)
|
||||
else if((tgui_alert(user, "Would you like to clear the birthday entry?","Clear?",list("No","Yes")) == "Yes"))
|
||||
|
||||
@@ -271,40 +271,32 @@
|
||||
|
||||
if(istype(I, /obj/item/gripper))
|
||||
var/obj/item/gripper/GR = I
|
||||
var/obj/item/wrap = GR.get_current_pocket()
|
||||
var/obj/item/wrap = GR.get_wrapped_item()
|
||||
if(wrap)
|
||||
wrap.loc = get_turf(src)
|
||||
var/result = can_insert(wrap, user)
|
||||
if(!result)
|
||||
wrap.forceMove(GR)
|
||||
if(!(default_deconstruction_screwdriver(user, I)))
|
||||
default_part_replacement(user, I)
|
||||
return
|
||||
return TRUE
|
||||
add_content(wrap, user)
|
||||
update_icon()
|
||||
return FALSE
|
||||
|
||||
if(QDELETED(wrap))
|
||||
GR.update_ref(null)
|
||||
attack_hand(user)
|
||||
return TRUE
|
||||
|
||||
if(wrap.loc != src)
|
||||
GR.drop_item_nm()
|
||||
var/result = can_insert(I, user)
|
||||
if(!result)
|
||||
if(!(default_deconstruction_screwdriver(user, I)))
|
||||
default_part_replacement(user, I)
|
||||
return
|
||||
|
||||
ToCook = wrap
|
||||
else
|
||||
attack_hand(user)
|
||||
if(result == 2)
|
||||
var/obj/item/grab/G = I
|
||||
if (G && istype(G) && G.affecting)
|
||||
cook_mob(G.affecting, user)
|
||||
return
|
||||
|
||||
else
|
||||
var/result = can_insert(I, user)
|
||||
if(!result)
|
||||
if(!(default_deconstruction_screwdriver(user, I)))
|
||||
default_part_replacement(user, I)
|
||||
return
|
||||
|
||||
if(result == 2)
|
||||
var/obj/item/grab/G = I
|
||||
if (G && istype(G) && G.affecting)
|
||||
cook_mob(G.affecting, user)
|
||||
return
|
||||
|
||||
//From here we can start cooking food
|
||||
add_content(ToCook, user)
|
||||
update_icon()
|
||||
|
||||
@@ -39,17 +39,10 @@
|
||||
/obj/item/reagent_containers/cooking_container/attackby(var/obj/item/I as obj, var/mob/user as mob)
|
||||
if(istype(I, /obj/item/gripper))
|
||||
var/obj/item/gripper/GR = I
|
||||
var/obj/item/wrapped = GR.get_current_pocket()
|
||||
var/obj/item/wrapped = GR.get_wrapped_item()
|
||||
if(wrapped)
|
||||
wrapped.forceMove(get_turf(src))
|
||||
attackby(wrapped, user)
|
||||
if(QDELETED(wrapped))
|
||||
wrapped = null
|
||||
|
||||
else if(wrapped.loc != src)
|
||||
wrapped = null
|
||||
|
||||
return
|
||||
return FALSE
|
||||
|
||||
for (var/possible_type in insertable)
|
||||
if (istype(I, possible_type))
|
||||
|
||||
@@ -155,24 +155,24 @@
|
||||
|
||||
else if(istype(O, /obj/item/gripper)) // Grippers. ~Mechoid.
|
||||
var/obj/item/gripper/B = O //B, for Borg.
|
||||
var/obj/item/wrapped = B.get_current_pocket()
|
||||
var/obj/item/wrapped = B.get_wrapped_item()
|
||||
if(!wrapped)
|
||||
to_chat(user, span_filter_notice("\The [B] is not holding anything."))
|
||||
return
|
||||
return TRUE
|
||||
else
|
||||
to_chat(user, span_filter_notice("You use \the [B] to put \the [wrapped] into \the [src]."))
|
||||
return
|
||||
return FALSE
|
||||
|
||||
else
|
||||
to_chat(user, span_notice("\The [src] smartly refuses [O]."))
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/smartfridge/secure/emag_act(var/remaining_charges, var/mob/user)
|
||||
if(!emagged)
|
||||
emagged = 1
|
||||
locked = -1
|
||||
to_chat(user, span_filter_notice("You short out the product lock on [src]."))
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/smartfridge/proc/find_record(var/obj/item/O)
|
||||
for(var/datum/stored_item/I as anything in item_records)
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
var/mob/living/silicon/robot/robot = user
|
||||
if(istype(robot.module_active, /obj/item/gripper))
|
||||
var/obj/item/gripper/gripper = robot.module_active
|
||||
I = gripper.get_current_pocket()
|
||||
I = gripper.get_wrapped_item()
|
||||
|
||||
else if(!I)
|
||||
return FALSE
|
||||
|
||||
@@ -72,7 +72,7 @@
|
||||
stripping = TRUE
|
||||
if(is_robot_module(held) && istype(held, /obj/item/gripper))
|
||||
var/obj/item/gripper/G = held
|
||||
var/obj/item/wrapped = G.get_current_pocket()
|
||||
var/obj/item/wrapped = G.get_wrapped_item()
|
||||
if(istype(wrapped))
|
||||
stripping = FALSE
|
||||
else
|
||||
@@ -98,7 +98,7 @@
|
||||
visible_message(span_danger("\The [user] is trying to put \a [held] on \the [src]!"))
|
||||
else
|
||||
var/obj/item/gripper/G = held
|
||||
var/obj/item/wrapped = G.get_current_pocket()
|
||||
var/obj/item/wrapped = G.get_wrapped_item()
|
||||
if(slot_to_strip == slot_wear_mask && istype(wrapped, /obj/item/grenade))
|
||||
visible_message(span_danger("\The [user] is trying to put \a [wrapped] in \the [src]'s mouth!"))
|
||||
else
|
||||
@@ -120,12 +120,12 @@
|
||||
unEquip(target_slot)
|
||||
else if(is_robot_module(held) && istype(held, /obj/item/gripper))
|
||||
var/obj/item/gripper/G = held
|
||||
var/obj/item/wrapped = G.get_current_pocket()
|
||||
var/obj/item/wrapped = G.get_wrapped_item()
|
||||
if(istype(wrapped))
|
||||
if(equip_to_slot_if_possible(wrapped, text2num(slot_to_strip), 0, 1, 1))
|
||||
wrapped = null
|
||||
G.generate_icons()
|
||||
G.current_pocket = pick(G.pockets)
|
||||
if(wrapped.loc != src)
|
||||
return
|
||||
G.clear_and_select_item()
|
||||
else if(user.unEquip(held))
|
||||
equip_to_slot_if_possible(held, text2num(slot_to_strip), 0, 1, 1)
|
||||
if(held.loc != src)
|
||||
|
||||
@@ -1351,8 +1351,8 @@
|
||||
|
||||
/mob/living/silicon/robot/drop_item(var/atom/Target)
|
||||
if(module_active && istype(module_active,/obj/item/gripper))
|
||||
var/obj/item/gripper/G = module_active
|
||||
G.drop_item_nm()
|
||||
var/obj/item/gripper/robot_gripper = module_active
|
||||
robot_gripper.drop_item_nm()
|
||||
|
||||
/mob/living/silicon/robot/disable_spoiler_vision()
|
||||
if(sight_mode & (BORGMESON|BORGMATERIAL|BORGXRAY|BORGANOMALOUS)) // Whyyyyyyyy have seperate defines.
|
||||
|
||||
@@ -0,0 +1,439 @@
|
||||
//This is used to check if the gripper is currently being used.
|
||||
//If it is, we don't allow any other actions to be performed.
|
||||
//Returns TRUE if we're in use explaining how.
|
||||
/obj/item/gripper/proc/is_in_use(mob/user, visible = TRUE)
|
||||
if(gripper_in_use)
|
||||
if(visible)
|
||||
to_chat(user, span_danger("You are currently using the gripper on something!"))
|
||||
return TRUE
|
||||
|
||||
if(in_radial_menu)
|
||||
if(visible)
|
||||
to_chat(user, span_danger("You are currently in the radial menu! Close it to use the gripper."))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/item/gripper/proc/update_ref(var/datum/weakref/new_ref)
|
||||
var/had_item = get_wrapped_item()
|
||||
WR = new_ref
|
||||
var/holding_item = get_wrapped_item()
|
||||
// Feedback
|
||||
update_icon()
|
||||
|
||||
if(had_item && !holding_item) // Dropped
|
||||
our_robot.playsound_local(get_turf(our_robot), 'sound/machines/click.ogg', 50)
|
||||
return
|
||||
|
||||
if(holding_item && !had_item || (holding_item != had_item)) // Pickup or change item
|
||||
our_robot.playsound_local(get_turf(our_robot), 'sound/machines/click2.ogg', 50)
|
||||
|
||||
///Stops the gripper from being used multiple times when we're performing a do_after
|
||||
/obj/item/gripper/proc/begin_using()
|
||||
gripper_in_use = TRUE
|
||||
|
||||
///Allows use of the gripper (and clears the weakref) after do_after is completed. Clears the weakref if the wrapped item is no longer in our borg's contents (items get moved into the borgs contents when using the gripper)
|
||||
/obj/item/gripper/proc/end_using()
|
||||
gripper_in_use = FALSE
|
||||
var/obj/item/wrapped = get_wrapped_item()
|
||||
if(!wrapped)
|
||||
return
|
||||
//Checks two things:
|
||||
//Is our wrapped object currently in our borg still?
|
||||
//AND Is it not a gripper pocket? If not, reset WR.
|
||||
if(item_left_gripper(wrapped))
|
||||
update_ref(null)
|
||||
|
||||
//This is the code that updates our pockets and decides if they should have icons or not.
|
||||
//This should be called every time we use the gripper and our wrapped item is used up.
|
||||
/obj/item/gripper/proc/generate_icons()
|
||||
if(LAZYLEN(pockets))
|
||||
|
||||
pockets_by_name = list()
|
||||
|
||||
photo_images = list()
|
||||
|
||||
for(var/obj/item/storage/internal/gripper/pocket_to_check in pockets)
|
||||
if(!LAZYLEN(pocket_to_check.contents))
|
||||
pockets_by_name[pocket_to_check.name] = pocket_to_check
|
||||
photo_images[pocket_to_check.name] = image(icon = 'icons/effects/effects.dmi', icon_state = "nothing")
|
||||
continue
|
||||
var/obj/item/pocket_content = pocket_to_check.contents[1]
|
||||
pockets_by_name["[pocket_to_check.name]" + "[pocket_content.name]"] = pocket_content
|
||||
var/image/pocket_image = image(icon = pocket_content.icon, icon_state = pocket_content.icon_state)
|
||||
if(pocket_content.color)
|
||||
pocket_image.color = pocket_content.color
|
||||
if(pocket_content.overlays)
|
||||
for(var/overlay in pocket_content.overlays)
|
||||
pocket_image.overlays += overlay
|
||||
photo_images["[pocket_to_check.name]" + "[pocket_content.name]"] = pocket_image
|
||||
|
||||
/obj/item/gripper/attack_self(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return TRUE
|
||||
if(special_handling)
|
||||
return FALSE
|
||||
if(is_in_use(user))
|
||||
return FALSE
|
||||
|
||||
generate_icons()
|
||||
|
||||
var/list/options = list()
|
||||
|
||||
for(var/Iname in pockets_by_name)
|
||||
options[Iname] = photo_images[Iname]
|
||||
|
||||
var/list/choice = list()
|
||||
|
||||
in_radial_menu = TRUE
|
||||
choice = show_radial_menu(user, src, options, radius = 40, require_near = TRUE, autopick_single_option = FALSE)
|
||||
in_radial_menu = FALSE
|
||||
|
||||
var/obj/item/wrapped = get_wrapped_item()
|
||||
if(choice)
|
||||
var/obj/item/storage/internal/gripper/selected_pocket = pockets_by_name[choice]
|
||||
if(!isgripperpocket(selected_pocket)) //The pocket we're selecting is NOT a gripper storage
|
||||
if(!isgripperpocket(selected_pocket.loc)) //We kept the radial menu opened, used the item, then selected it again.
|
||||
clear_and_select_pocket() //Pick the next open pocket.
|
||||
return
|
||||
|
||||
update_ref(WEAKREF(selected_pocket))
|
||||
return
|
||||
|
||||
current_pocket = selected_pocket
|
||||
update_ref(null)
|
||||
return
|
||||
|
||||
if(wrapped)
|
||||
return wrapped.attack_self(user)
|
||||
|
||||
/obj/item/gripper/attackby(var/obj/item/O, var/mob/user)
|
||||
if(is_in_use(user))
|
||||
return FALSE
|
||||
|
||||
var/obj/item/wrapped = get_wrapped_item()
|
||||
if(wrapped)
|
||||
wrapped.loc = loc //Place it in to the robot.
|
||||
var/resolved = wrapped.attackby(O, user)
|
||||
wrapped = get_wrapped_item() //We check to see if the object exists after we do attackby.
|
||||
|
||||
//The object has been deleted. Select a new pocket and stop here.
|
||||
if(!wrapped)
|
||||
clear_and_select_pocket()
|
||||
return FALSE
|
||||
|
||||
//Object is not in our contents AND is not in the gripper storage still. AKA, it was moved into something or somewhere. Either way, it's not ours anymore.
|
||||
if(item_left_gripper(wrapped))
|
||||
clear_and_select_pocket()
|
||||
return TRUE
|
||||
|
||||
//We were not given a resolved, the object still exists, AND we hit something. Attack that thing with our wrapped item.
|
||||
if(!resolved && wrapped && O)
|
||||
O.afterattack(wrapped,user,1)
|
||||
wrapped = get_wrapped_item()
|
||||
//The object still exists, but is not in our contents OR back in the gripper storage.
|
||||
if(item_left_gripper(wrapped))
|
||||
clear_and_select_pocket()
|
||||
return TRUE
|
||||
|
||||
//Nothing happened to it. Just put it back into our pocket.
|
||||
wrapped.loc = current_pocket
|
||||
return TRUE
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/item/gripper/afterattack(atom/target, mob/living/user, proximity, params)
|
||||
if(!proximity)
|
||||
return // This will prevent them using guns at range but adminbuse can add them directly to modules, so eh.
|
||||
|
||||
if(is_in_use(user))
|
||||
return
|
||||
|
||||
var/obj/item/wrapped = get_wrapped_item()
|
||||
if(wrapped && item_left_gripper(wrapped)) // This is used for items that are moved out during other attack chains
|
||||
clear_and_select_item()
|
||||
return
|
||||
|
||||
if(use_item(target, user, wrapped)) //Already have an item.
|
||||
return
|
||||
update_ref(WEAKREF(wrapped))
|
||||
|
||||
if(pick_up_item(target, user))
|
||||
return
|
||||
|
||||
if(handle_afterattack_special(target, user))
|
||||
return
|
||||
|
||||
if(item_left_gripper(wrapped))
|
||||
clear_and_select_item()
|
||||
|
||||
/obj/item/gripper/proc/use_item(atom/target, mob/user, obj/item/wrapped)
|
||||
if(!wrapped)
|
||||
return FALSE
|
||||
|
||||
var/obj/item/storage/internal/gripper/previous_pocket
|
||||
if(isgripperpocket(wrapped.loc))
|
||||
previous_pocket = wrapped.loc
|
||||
else
|
||||
previous_pocket = current_pocket
|
||||
|
||||
var/original_amount = 0
|
||||
if(istype(wrapped, /obj/item/reagent_containers))
|
||||
var/obj/item/reagent_containers/wrapped_container = wrapped
|
||||
original_amount = wrapped_container.reagents?.total_volume
|
||||
|
||||
wrapped.loc = user
|
||||
|
||||
var/resolved = target.attackby(wrapped, user)
|
||||
if(!resolved && wrapped && target)
|
||||
wrapped.afterattack(target, user, TRUE)
|
||||
|
||||
if(item_left_gripper(wrapped))
|
||||
clear_and_select_pocket()
|
||||
return TRUE
|
||||
|
||||
if(istype(wrapped, /obj/item/reagent_containers))
|
||||
var/obj/item/reagent_containers/wrapped_container = wrapped
|
||||
if(wrapped_container.reagents?.total_volume != original_amount || (istype(target, /obj/item/reagent_containers)))
|
||||
wrapped.loc = previous_pocket
|
||||
update_ref(WEAKREF(wrapped))
|
||||
return TRUE
|
||||
|
||||
wrapped.loc = previous_pocket
|
||||
update_ref(WEAKREF(wrapped))
|
||||
return FALSE
|
||||
|
||||
/obj/item/gripper/proc/pick_up_item(atom/target, mob/user)
|
||||
if(!isitem(target))
|
||||
return FALSE
|
||||
|
||||
var/obj/item/I = target
|
||||
|
||||
if(!isturf(I.loc))
|
||||
return FALSE
|
||||
|
||||
if(I.anchored)
|
||||
to_chat(user, span_notice("You are unable to lift \the [I]."))
|
||||
return FALSE
|
||||
|
||||
var/obj/item/storage/internal/gripper/selected_pocket = find_empty_pocket()
|
||||
if(!selected_pocket)
|
||||
to_chat(user, "Your gripper is full!")
|
||||
return FALSE
|
||||
|
||||
if(!is_type_in_list(I, can_hold))
|
||||
to_chat(user, span_danger("Your gripper cannot hold \the [I]."))
|
||||
return FALSE
|
||||
|
||||
to_chat(user, "You collect \the [I].")
|
||||
I.loc = selected_pocket
|
||||
current_pocket = selected_pocket
|
||||
update_ref(WEAKREF(I))
|
||||
return TRUE
|
||||
|
||||
/obj/item/gripper/proc/handle_afterattack_special(atom/target, mob/living/user)
|
||||
if(istype(target, /obj/machinery/power/apc))
|
||||
var/obj/machinery/power/apc/A = target
|
||||
if(!A.opened)
|
||||
return TRUE
|
||||
|
||||
if(!A.cell || !is_type_in_list(A.cell, can_hold))
|
||||
return TRUE
|
||||
|
||||
if(!grab_cell(A.cell, user))
|
||||
return TRUE
|
||||
|
||||
A.cell = null
|
||||
A.charging = FALSE
|
||||
A.update_icon()
|
||||
|
||||
user.visible_message(
|
||||
span_danger("[user] removes the power cell from [A]!"),
|
||||
"You remove the power cell."
|
||||
)
|
||||
|
||||
return TRUE
|
||||
|
||||
if(isrobot(target))
|
||||
var/mob/living/silicon/robot/A = target
|
||||
if(!A.opened)
|
||||
return TRUE
|
||||
|
||||
if(!A.cell || !is_type_in_list(A.cell, can_hold))
|
||||
return TRUE
|
||||
|
||||
if(!grab_cell(A.cell, user))
|
||||
return TRUE
|
||||
|
||||
var/datum/robot_component/cell_component = A.components["power cell"]
|
||||
|
||||
|
||||
A.cell = null
|
||||
cell_component.uninstall(TRUE)
|
||||
A.update_icon()
|
||||
|
||||
user.visible_message(
|
||||
span_danger("[user] removes the power cell from [A]!"),
|
||||
"You remove the power cell."
|
||||
)
|
||||
|
||||
return TRUE
|
||||
|
||||
return FALSE
|
||||
|
||||
/// Returns the first empty gripper pocket, or null
|
||||
/obj/item/gripper/proc/find_empty_pocket()
|
||||
for(var/obj/item/storage/internal/gripper/P in pockets)
|
||||
if(!LAZYLEN(P.contents))
|
||||
return P
|
||||
return null
|
||||
|
||||
/// Returns TRUE if item is no longer in the gripper
|
||||
/obj/item/gripper/proc/item_left_gripper(obj/item/I)
|
||||
if(QDELETED(I))
|
||||
return TRUE
|
||||
|
||||
if(isgripperpocket(I.loc))
|
||||
return FALSE
|
||||
|
||||
if(I.loc == loc)
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
|
||||
/// Sets current_pocket to a valid pocket (never an item)
|
||||
/obj/item/gripper/proc/select_pocket(obj/item/storage/internal/gripper/P)
|
||||
if(!P)
|
||||
P = pick(pockets)
|
||||
|
||||
current_pocket = P
|
||||
|
||||
/// Clears the currently wrapped item and selects the pocket
|
||||
/obj/item/gripper/proc/clear_and_select_pocket()
|
||||
update_ref(null)
|
||||
select_empty_pocket()
|
||||
|
||||
/// Clears the currently wrapped item and selects next item
|
||||
/obj/item/gripper/proc/clear_and_select_item()
|
||||
update_ref(null)
|
||||
select_next_item()
|
||||
|
||||
/// Selects the first empty pocket, or a random one
|
||||
/obj/item/gripper/proc/select_empty_pocket()
|
||||
var/obj/item/storage/internal/gripper/P = find_empty_pocket()
|
||||
select_pocket(P)
|
||||
|
||||
/obj/item/gripper/proc/select_next_item()
|
||||
for(var/obj/item/storage/internal/gripper/P in reverseList(pockets))
|
||||
if(!LAZYLEN(P.contents))
|
||||
continue
|
||||
var/obj/item/next_item = P.contents[1]
|
||||
update_ref(WEAKREF(next_item))
|
||||
return
|
||||
|
||||
/obj/item/gripper/proc/drop_item(mob/user)
|
||||
var/obj/item/wrapped = get_wrapped_item()
|
||||
if(!wrapped)
|
||||
to_chat(user, span_warning("You have nothing to drop!"))
|
||||
return
|
||||
|
||||
if(is_in_use(user))
|
||||
return
|
||||
|
||||
if((item_left_gripper(wrapped)))
|
||||
clear_and_select_pocket()
|
||||
generate_icons()
|
||||
return
|
||||
|
||||
to_chat(user, span_notice("You drop \the [wrapped]."))
|
||||
wrapped.forceMove(get_turf(user))
|
||||
clear_and_select_pocket()
|
||||
generate_icons()
|
||||
|
||||
//FORCES the item onto the ground and resets.
|
||||
/obj/item/gripper/proc/drop_item_nm(atom/taget)
|
||||
var/obj/item/wrapped = get_wrapped_item()
|
||||
if(!wrapped)
|
||||
return
|
||||
|
||||
if((item_left_gripper(wrapped)))
|
||||
clear_and_select_pocket()
|
||||
generate_icons()
|
||||
return
|
||||
|
||||
wrapped.forceMove(taget ? taget : get_turf(src))
|
||||
clear_and_select_pocket()
|
||||
generate_icons()
|
||||
|
||||
/obj/item/gripper/attack(mob/living/carbon/M, mob/living/carbon/user)
|
||||
if(is_in_use(user))
|
||||
return FALSE
|
||||
|
||||
var/obj/item/wrapped = get_wrapped_item()
|
||||
//The force of the wrapped obj gets set to zero during the attack() and afterattack().
|
||||
if(!wrapped)
|
||||
return FALSE
|
||||
|
||||
//If our wrapper was deleted OR it's no longer in our internal gripper storage
|
||||
if(item_left_gripper(wrapped))
|
||||
update_ref(null)
|
||||
return FALSE
|
||||
|
||||
wrapped.attack(M, user)
|
||||
//attackby reportedly gets procced by being clicked on, at least according to Anewbe.
|
||||
M.attackby(wrapped, user)
|
||||
|
||||
//If our wrapper was deleted OR it's no longer in our internal gripper storage
|
||||
if(item_left_gripper(wrapped))
|
||||
update_ref(null)
|
||||
|
||||
return TRUE
|
||||
|
||||
/obj/item/gripper/update_icon()
|
||||
cut_overlays()
|
||||
var/obj/item/wrapped = get_wrapped_item()
|
||||
if(!wrapped)
|
||||
return
|
||||
|
||||
// Draw the held item as a mini-image in the gripper itself
|
||||
var/mutable_appearance/item_display = new(wrapped)
|
||||
item_display.SetTransform(0.75, offset_y = -8)
|
||||
item_display.pixel_x = 0
|
||||
item_display.pixel_y = 0
|
||||
item_display.plane = plane
|
||||
item_display.layer = layer + 0.01
|
||||
add_overlay(item_display)
|
||||
|
||||
//HELPER PROCS
|
||||
///Use this to get what the current pocket is. Returns NULL if no
|
||||
/obj/item/gripper/proc/get_wrapped_item() //done as a proc so snowflake code can be found later down the line and consolidated.
|
||||
var/obj/item/wrapped = WR?.resolve()
|
||||
return wrapped
|
||||
|
||||
/// Consolidates material stacks by searching our pockets to see if we currently have any stacks. Done in /obj/item/stack/attackby
|
||||
/obj/item/gripper/proc/consolidate_stacks(var/obj/item/stack/stack_to_consolidate)
|
||||
if(!stack_to_consolidate || !istype(stack_to_consolidate, /obj/item/stack))
|
||||
return
|
||||
|
||||
for(var/obj/item/storage/internal/gripper/pocket in pockets)
|
||||
if(!LAZYLEN(pocket.contents))
|
||||
continue
|
||||
for(var/obj/item/stack/stack in pocket.contents)
|
||||
if(istype(stack_to_consolidate, stack))
|
||||
stack_to_consolidate.transfer_to(stack)
|
||||
return
|
||||
|
||||
/obj/item/gripper/proc/grab_cell(obj/item/cell, mob/user)
|
||||
var/obj/item/storage/internal/gripper/P = find_empty_pocket()
|
||||
if(!P)
|
||||
to_chat(user, "Your gripper is full!")
|
||||
return FALSE
|
||||
|
||||
cell.add_fingerprint(user)
|
||||
cell.update_icon()
|
||||
cell.forceMove(P)
|
||||
|
||||
current_pocket = P
|
||||
update_ref(WEAKREF(cell))
|
||||
return TRUE
|
||||
@@ -693,6 +693,9 @@
|
||||
src.modules += new /obj/item/gun/energy/robotic/taser/xeno(src)
|
||||
src.modules += new /obj/item/xenoarch_multi_tool(src)
|
||||
src.modules += new /obj/item/pickaxe/excavationdrill(src)
|
||||
// Anomaly handling
|
||||
src.modules += new /obj/item/analyzer(src)
|
||||
src.modules += new /obj/item/assembly/signaler(src)
|
||||
|
||||
src.emag += new /obj/item/hand_tele(src)
|
||||
|
||||
|
||||
@@ -543,7 +543,7 @@
|
||||
//Has a list of items that it can hold.
|
||||
var/list/can_hold = list(BASIC_GRIPPER)
|
||||
|
||||
var/datum/weakref/WR = null //We resolve this to get wrapped. Use get_current_pocket when possible.
|
||||
var/datum/weakref/WR = null //We resolve this to get wrapped. Use get_wrapped_item when possible.
|
||||
|
||||
var/total_pockets = 5 //How many total inventory slots we want to have in the gripper
|
||||
|
||||
@@ -603,160 +603,19 @@
|
||||
|
||||
/obj/item/gripper/examine(mob/user)
|
||||
. = ..()
|
||||
var/obj/item/wrapped = get_current_pocket()
|
||||
var/obj/item/wrapped = get_wrapped_item()
|
||||
if(wrapped)
|
||||
. += span_notice("\The [src] is holding \the [wrapped].")
|
||||
. += wrapped.examine(user)
|
||||
|
||||
/obj/item/gripper/item_ctrl_click(mob/user)
|
||||
var/obj/item/wrapped = get_current_pocket()
|
||||
if(wrapped && !is_in_use())
|
||||
var/obj/item/wrapped = get_wrapped_item()
|
||||
if(wrapped && !is_in_use(user, FALSE))
|
||||
wrapped.attack_self(user)
|
||||
return
|
||||
|
||||
/obj/item/gripper/click_alt(mob/user)
|
||||
if(!is_in_use())
|
||||
drop_item()
|
||||
return
|
||||
|
||||
//This is used to check if the gripper is currently being used.
|
||||
//If it is, we don't allow any other actions to be performed.
|
||||
//Returns a string if we're in use explaining how.
|
||||
/obj/item/gripper/proc/is_in_use()
|
||||
if(gripper_in_use)
|
||||
return "You are currently using the gripper on something!"
|
||||
if(in_radial_menu)
|
||||
return "You are currently in the radial menu! Close it to use the gripper."
|
||||
return FALSE
|
||||
|
||||
///Stops the gripper from being used multiple times when we're performing a do_after
|
||||
/obj/item/gripper/proc/begin_using()
|
||||
gripper_in_use = TRUE
|
||||
|
||||
///Allows use of the gripper (and clears the weakref) after do_after is completed. Clears the weakref if the wrapped item is no longer in our borg's contents (items get moved into the borgs contents when using the gripper)
|
||||
/obj/item/gripper/proc/end_using()
|
||||
gripper_in_use = FALSE
|
||||
var/obj/item/wrapped = get_current_pocket()
|
||||
if(!wrapped)
|
||||
return
|
||||
//Checks two things:
|
||||
//Is our wrapped object currently in our borg still?
|
||||
//AND Is it not a gripper pocket? If not, reset WR.
|
||||
if(wrapped.loc != loc && !isgripperpocket(wrapped.loc))
|
||||
update_ref(null)
|
||||
|
||||
//This is the code that updates our pockets and decides if they should have icons or not.
|
||||
//This should be called every time we use the gripper and our wrapped item is used up.
|
||||
/obj/item/gripper/proc/generate_icons()
|
||||
if(LAZYLEN(pockets))
|
||||
|
||||
pockets_by_name = list()
|
||||
|
||||
photo_images = list()
|
||||
|
||||
for(var/obj/item/storage/internal/gripper/pocket_to_check in pockets)
|
||||
if(!LAZYLEN(pocket_to_check.contents))
|
||||
pockets_by_name[pocket_to_check.name] = pocket_to_check
|
||||
photo_images[pocket_to_check.name] = image(icon = 'icons/effects/effects.dmi', icon_state = "nothing")
|
||||
continue
|
||||
var/obj/item/pocket_content = pocket_to_check.contents[1]
|
||||
pockets_by_name["[pocket_to_check.name]" + "[pocket_content.name]"] = pocket_content
|
||||
var/image/pocket_image = image(icon = pocket_content.icon, icon_state = pocket_content.icon_state)
|
||||
if(pocket_content.color)
|
||||
pocket_image.color = pocket_content.color
|
||||
if(pocket_content.overlays)
|
||||
for(var/overlay in pocket_content.overlays)
|
||||
pocket_image.overlays += overlay
|
||||
photo_images["[pocket_to_check.name]" + "[pocket_content.name]"] = pocket_image
|
||||
|
||||
/obj/item/gripper/attack_self(mob/user)
|
||||
. = ..(user)
|
||||
if(.)
|
||||
return TRUE
|
||||
if(special_handling)
|
||||
return FALSE
|
||||
var/busy = is_in_use()
|
||||
if(busy)
|
||||
to_chat(user, span_danger("[busy]"))
|
||||
return
|
||||
generate_icons()
|
||||
var/list/options = list()
|
||||
|
||||
for(var/Iname in pockets_by_name)
|
||||
options[Iname] = photo_images[Iname]
|
||||
|
||||
var/list/choice = list()
|
||||
|
||||
in_radial_menu = TRUE
|
||||
choice = show_radial_menu(user, src, options, radius = 40, require_near = TRUE, autopick_single_option = FALSE)
|
||||
in_radial_menu = FALSE
|
||||
|
||||
var/obj/item/wrapped = get_current_pocket()
|
||||
if(choice)
|
||||
current_pocket = pockets_by_name[choice]
|
||||
if(!isgripperpocket(current_pocket)) //The pocket we're selecting is NOT a gripper storage
|
||||
if(!isgripperpocket(current_pocket.loc)) //We kept the radial menu opened, used the item, then selected it again.
|
||||
get_open_pocket(set_pocket = TRUE, clear_wrapped = TRUE) //Pick the next open pocket.
|
||||
else
|
||||
update_ref(WEAKREF(current_pocket))
|
||||
else
|
||||
update_ref(null)
|
||||
else if(wrapped)
|
||||
return wrapped.attack_self(user)
|
||||
return ..()
|
||||
|
||||
/obj/item/gripper/attackby(var/obj/item/O, var/mob/user)
|
||||
var/busy = is_in_use()
|
||||
if(busy)
|
||||
to_chat(user, span_danger("[busy]"))
|
||||
return FALSE
|
||||
var/obj/item/wrapped = get_current_pocket()
|
||||
if(wrapped)
|
||||
wrapped.loc = src.loc //Place it in to the robot.
|
||||
var/resolved = wrapped.attackby(O, user)
|
||||
wrapped = get_current_pocket() //We check to see if the object exists after we do attackby.
|
||||
|
||||
//The object has been deleted. Select a new pocket and stop here.
|
||||
if(!wrapped)
|
||||
get_open_pocket(set_pocket = TRUE, clear_wrapped = TRUE)
|
||||
|
||||
//Object is not in our contents AND is not in the gripper storage still. AKA, it was moved into something or somewhere. Either way, it's not ours anymore.
|
||||
else if((wrapped.loc != src.loc && !isgripperpocket(wrapped.loc)))
|
||||
get_open_pocket(set_pocket = TRUE, clear_wrapped = TRUE)
|
||||
|
||||
//We were not given a resolved, the object still exists, AND we hit something. Attack that thing with our wrapped item.
|
||||
else if(!resolved && wrapped && O)
|
||||
O.afterattack(wrapped,user,1)
|
||||
wrapped = get_current_pocket()
|
||||
//The object still exists, but is not in our contents OR back in the gripper storage.
|
||||
if((wrapped && wrapped.loc != src.loc && !isgripperpocket(wrapped.loc)))
|
||||
get_open_pocket(set_pocket = TRUE, clear_wrapped = TRUE)
|
||||
else //Nothing happened to it. Just put it back into our pocket.
|
||||
wrapped.loc = current_pocket
|
||||
|
||||
return resolved
|
||||
return ..()
|
||||
|
||||
///Gets an open pocket in the gripper.
|
||||
///ARGS:
|
||||
///set_pocket TRUE/FALSE. If set to TRUE, will set our current_pocket to the first open pocket it finds.
|
||||
///clear_wrapped TRUE/FALSE. If set to TRUE, will set WR to null.
|
||||
/obj/item/gripper/proc/get_open_pocket(set_pocket = FALSE, clear_wrapped = FALSE)
|
||||
var/pocket_to_select
|
||||
for(var/obj/item/storage/internal/gripper/our_pocket in pockets)
|
||||
if(LAZYLEN(our_pocket.contents))
|
||||
continue
|
||||
pocket_to_select = our_pocket
|
||||
break
|
||||
if(clear_wrapped)
|
||||
update_ref(null)
|
||||
if(set_pocket)
|
||||
if(!pocket_to_select)
|
||||
pocket_to_select = pick(pockets) //If we don't have an open pocket, pick a random one.
|
||||
if(!isgripperpocket(pocket_to_select)) //If we picked an item instead of a gripper storage, we need to reset WR.
|
||||
update_ref(WEAKREF(pocket_to_select)) //We set WR to the pocket we selected.
|
||||
current_pocket = pocket_to_select
|
||||
return pocket_to_select
|
||||
if(!is_in_use(user, FALSE))
|
||||
drop_item(user)
|
||||
|
||||
/obj/item/gripper/verb/drop_gripper_item()
|
||||
|
||||
@@ -764,231 +623,7 @@
|
||||
set desc = "Release an item from your magnetic gripper."
|
||||
set category = "Abilities.Silicon"
|
||||
|
||||
drop_item()
|
||||
|
||||
/obj/item/gripper/proc/drop_item()
|
||||
var/obj/item/wrapped = get_current_pocket()
|
||||
var/busy = is_in_use()
|
||||
if(!wrapped)
|
||||
to_chat(src, span_warning("You have nothing to drop!"))
|
||||
return
|
||||
if(busy)
|
||||
to_chat(src, span_danger("[busy]"))
|
||||
return
|
||||
if((wrapped == current_pocket && !isgripperpocket(wrapped.loc))) //We have wrapped selected as our current_pocket AND wrapped is not in a gripper storage
|
||||
get_open_pocket(set_pocket = TRUE, clear_wrapped = TRUE)
|
||||
generate_icons()
|
||||
return
|
||||
|
||||
to_chat(src.loc, span_notice("You drop \the [wrapped]."))
|
||||
wrapped.loc = get_turf(src)
|
||||
get_open_pocket(set_pocket = TRUE, clear_wrapped = TRUE)
|
||||
generate_icons()
|
||||
|
||||
//FORCES the item onto the ground and resets.
|
||||
/obj/item/gripper/proc/drop_item_nm()
|
||||
var/obj/item/wrapped = get_current_pocket()
|
||||
if(!wrapped)
|
||||
return
|
||||
if((wrapped == current_pocket && !isgripperpocket(wrapped.loc))) //We have wrapped selected as our current_pocket AND wrapped is not in a gripper storage
|
||||
update_ref(null)
|
||||
current_pocket = pick(pockets)
|
||||
return
|
||||
|
||||
wrapped.forceMove(get_turf(src))
|
||||
update_ref(null)
|
||||
|
||||
//Reselect our pocket.
|
||||
current_pocket = pick(pockets)
|
||||
|
||||
/obj/item/gripper/attack(mob/living/carbon/M, mob/living/carbon/user)
|
||||
var/busy = is_in_use()
|
||||
if(busy)
|
||||
to_chat(user, span_danger("[busy]"))
|
||||
return FALSE
|
||||
var/obj/item/wrapped = get_current_pocket()
|
||||
if(wrapped) //The force of the wrapped obj gets set to zero during the attack() and afterattack().
|
||||
if((wrapped.loc != src.loc && !isgripperpocket(wrapped.loc))) //If our wrapper was deleted OR it's no longer in our internal gripper storage
|
||||
update_ref(null)
|
||||
return 0
|
||||
|
||||
var/old_loc = wrapped.loc
|
||||
wrapped.attack(M,user)
|
||||
M.attackby(wrapped, user) //attackby reportedly gets procced by being clicked on, at least according to Anewbe.
|
||||
if((wrapped.loc != old_loc && !isgripperpocket(wrapped.loc))) //If our wrapper was deleted OR it's no longer in our internal gripper storage
|
||||
update_ref(null)
|
||||
return 1
|
||||
|
||||
/obj/item/gripper/afterattack(var/atom/target, var/mob/living/user, proximity, params)
|
||||
if(!proximity)
|
||||
return // This will prevent them using guns at range but adminbuse can add them directly to modules, so eh.
|
||||
var/busy = is_in_use()
|
||||
if(busy)
|
||||
to_chat(user, span_danger("[busy]"))
|
||||
return
|
||||
var/current_pocket_full = FALSE
|
||||
var/obj/item/wrapped = get_current_pocket()
|
||||
if(wrapped == current_pocket)
|
||||
current_pocket_full = TRUE
|
||||
if(!wrapped && current_pocket)
|
||||
if(LAZYLEN(current_pocket.contents))
|
||||
wrapped = current_pocket.contents[1]
|
||||
current_pocket_full = TRUE
|
||||
|
||||
if(current_pocket && !LAZYLEN(current_pocket.contents)) //We have a pocket selected and it has no contents! This means we're an item OR we need to null our wrapper!
|
||||
if(isgripperpocket(current_pocket.loc) && !LAZYLEN(current_pocket.loc.contents)) //If our pocket is a gripper, AND we have no contents, WR = null
|
||||
update_ref(null)
|
||||
else if(!isgripperpocket(current_pocket.loc)) //If our pocket is an item and we are not in the gripper, WR = null
|
||||
update_ref(null)
|
||||
|
||||
if(!LAZYLEN(pockets)) //Shouldn't happen, but safety first.
|
||||
to_chat(user, span_danger("Your gripper has nowhere to hold \the [target]."))
|
||||
return
|
||||
|
||||
var/obj/item/storage/internal/gripper/selected_pocket //Find an open pocket to use in case we're trying to pick something up.
|
||||
for(var/obj/item/storage/internal/gripper/available_pocket in pockets)
|
||||
if(LAZYLEN(available_pocket.contents))
|
||||
continue
|
||||
selected_pocket = available_pocket
|
||||
break
|
||||
|
||||
if(wrapped) //Already have an item.
|
||||
//Temporary put wrapped into user so target's attackby() checks pass.
|
||||
var/obj/previous_pocket
|
||||
if(isgripperpocket(wrapped.loc))
|
||||
previous_pocket = wrapped.loc
|
||||
wrapped.loc = user
|
||||
|
||||
//Pass the attack on to the target. This might delete/relocate wrapped.
|
||||
var/resolved = target.attackby(wrapped,user)
|
||||
if(!resolved && wrapped && target)
|
||||
wrapped.afterattack(target,user,1)
|
||||
|
||||
if(!WR) //We put our wrapped thing INTO something!
|
||||
get_open_pocket(set_pocket = TRUE, clear_wrapped = TRUE)
|
||||
return
|
||||
//If we had a previous pocket and the wrapped isn't put into something, put it back in our pocket.
|
||||
else if((previous_pocket && wrapped.loc == user))
|
||||
wrapped.loc = previous_pocket
|
||||
else
|
||||
get_open_pocket(set_pocket = TRUE, clear_wrapped = TRUE)
|
||||
return
|
||||
else if(current_pocket_full) //Pocket is full. No grabbing more things.
|
||||
to_chat(user, "Your gripper is currently full! You can't pick anything else up!")
|
||||
return
|
||||
|
||||
else if(isitem(target)) //Check that we're not pocketing a mob.
|
||||
|
||||
//...and that the item is not in a container.
|
||||
if(!isturf(target.loc))
|
||||
return
|
||||
|
||||
var/obj/item/I = target
|
||||
|
||||
if(I.anchored)
|
||||
to_chat(user,span_notice("You are unable to lift \the [I] from \the [I.loc]."))
|
||||
return
|
||||
|
||||
//Check if the item is blacklisted.
|
||||
var/grab = 0
|
||||
for(var/typepath in can_hold)
|
||||
if(istype(I,typepath))
|
||||
grab = 1
|
||||
break
|
||||
|
||||
//We can grab the item, finally.
|
||||
if(grab)
|
||||
to_chat(user, "You collect \the [I].")
|
||||
I.loc = selected_pocket
|
||||
if(selected_pocket == current_pocket) //If we put the item into our current pocket, we need to set WR to the item.
|
||||
update_ref(WEAKREF(I))
|
||||
current_pocket = I
|
||||
return
|
||||
else
|
||||
to_chat(user, span_danger("Your gripper cannot hold \the [target]."))
|
||||
|
||||
else if(istype(target,/obj/machinery/power/apc))
|
||||
var/obj/machinery/power/apc/A = target
|
||||
if(A.opened)
|
||||
if(A.cell && is_type_in_list(A.cell, can_hold))
|
||||
|
||||
current_pocket = A.cell
|
||||
|
||||
A.cell.add_fingerprint(user)
|
||||
A.cell.update_icon()
|
||||
A.update_icon()
|
||||
A.cell.forceMove(current_pocket)
|
||||
current_pocket = A.cell
|
||||
WR = WEAKREF(current_pocket)
|
||||
A.cell = null
|
||||
|
||||
A.charging = 0
|
||||
A.update_icon()
|
||||
|
||||
user.visible_message(span_danger("[user] removes the power cell from [A]!"), "You remove the power cell.")
|
||||
|
||||
else if(isrobot(target))
|
||||
var/mob/living/silicon/robot/A = target
|
||||
if(A.opened)
|
||||
if(A.cell && is_type_in_list(A.cell, can_hold))
|
||||
var/datum/robot_component/cell_component = A.components["power cell"]
|
||||
A.cell.update_icon()
|
||||
A.cell.add_fingerprint(user)
|
||||
A.cell.forceMove(current_pocket)
|
||||
current_pocket = A.cell
|
||||
WR = WEAKREF(current_pocket)
|
||||
A.cell = null
|
||||
cell_component.uninstall(TRUE)
|
||||
A.update_icon()
|
||||
|
||||
user.visible_message(span_danger("[user] removes the power cell from [A]!"), "You remove the power cell.")
|
||||
|
||||
/obj/item/gripper/proc/update_ref(var/datum/weakref/new_ref)
|
||||
var/had_item = get_current_pocket()
|
||||
WR = new_ref
|
||||
var/holding_item = get_current_pocket()
|
||||
// Feedback
|
||||
update_icon()
|
||||
if(had_item && !holding_item) // Dropped
|
||||
our_robot.playsound_local(get_turf(our_robot), 'sound/machines/click.ogg', 50)
|
||||
else if(holding_item && !had_item || (holding_item != had_item)) // Pickup or change item
|
||||
our_robot.playsound_local(get_turf(our_robot), 'sound/machines/click2.ogg', 50)
|
||||
|
||||
/obj/item/gripper/update_icon()
|
||||
cut_overlays()
|
||||
var/obj/item/wrapped = get_current_pocket()
|
||||
if(!wrapped)
|
||||
return
|
||||
// Draw the held item as a mini-image in the gripper itself
|
||||
var/mutable_appearance/item_display = new(wrapped)
|
||||
item_display.SetTransform(0.75, offset_y = -8)
|
||||
item_display.pixel_x = 0
|
||||
item_display.pixel_y = 0
|
||||
item_display.plane = plane
|
||||
item_display.layer = layer + 0.01
|
||||
add_overlay(item_display)
|
||||
|
||||
//HELPER PROCS
|
||||
///Use this to get what the current pocket is. Returns NULL if no
|
||||
/obj/item/gripper/proc/get_current_pocket() //done as a proc so snowflake code can be found later down the line and consolidated.
|
||||
var/obj/item/wrapped = WR?.resolve()
|
||||
return wrapped
|
||||
|
||||
/// Consolidates material stacks by searching our pockets to see if we currently have any stacks. Done in /obj/item/stack/attackby
|
||||
/obj/item/gripper/proc/consolidate_stacks(var/obj/item/stack/stack_to_consolidate)
|
||||
if(!stack_to_consolidate || !istype(stack_to_consolidate, /obj/item/stack))
|
||||
return
|
||||
var/stacked = FALSE //So we can break the for loop 2 forloops deep.
|
||||
for(var/obj/item/storage/internal/gripper/pocket in pockets)
|
||||
if(stacked) //We've stacked our item, break!
|
||||
break
|
||||
|
||||
if(LAZYLEN(pocket.contents))
|
||||
for(var/obj/item/stack/stack in pocket.contents)
|
||||
if(istype(stack_to_consolidate, stack))
|
||||
stack_to_consolidate.transfer_to(stack)
|
||||
stacked = TRUE
|
||||
break
|
||||
drop_item(src.loc)
|
||||
|
||||
//Different types of grippers!
|
||||
|
||||
|
||||
@@ -177,6 +177,13 @@
|
||||
. += "It has a power rating of [maxcharge]."
|
||||
. += "The charge meter reads [round(src.percent() )]%."
|
||||
|
||||
/obj/item/cell/attack(mob/living/M, mob/living/user, var/target_zone, var/attack_modifier)
|
||||
if(isrobot(M))
|
||||
var/mob/living/silicon/robot/target = M
|
||||
if(target.opened)
|
||||
return FALSE
|
||||
..()
|
||||
|
||||
/obj/item/cell/attackby(obj/item/W, mob/user)
|
||||
..()
|
||||
if(istype(W, /obj/item/reagent_containers/syringe))
|
||||
|
||||
@@ -109,7 +109,7 @@
|
||||
|
||||
if(istype(O,/obj/item/gripper))
|
||||
var/obj/item/gripper/B = O //B, for Borg.
|
||||
var/obj/item/wrapped = B.get_current_pocket()
|
||||
var/obj/item/wrapped = B.get_wrapped_item()
|
||||
if(!wrapped)
|
||||
to_chat(user, "\The [B] is not holding anything.")
|
||||
return 0
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
// Borgos!
|
||||
if(istype(O,/obj/item/gripper))
|
||||
var/obj/item/gripper/B = O //B, for Borg.
|
||||
var/obj/item/wrapped = B.get_current_pocket()
|
||||
var/obj/item/wrapped = B.get_wrapped_item()
|
||||
if(!wrapped)
|
||||
to_chat(user, "\The [B] is not holding anything.")
|
||||
return FALSE
|
||||
|
||||
@@ -135,7 +135,7 @@
|
||||
if(istype(user,/mob/living/silicon/robot))
|
||||
if(istype(tool, /obj/item/gripper))
|
||||
var/obj/item/gripper/gripper = tool
|
||||
var/obj/item/wrapped = gripper.get_current_pocket()
|
||||
var/obj/item/wrapped = gripper.get_wrapped_item()
|
||||
if(wrapped)
|
||||
tool = wrapped
|
||||
else
|
||||
@@ -154,7 +154,7 @@
|
||||
var/obj/item/organ/external/affected = target.get_organ(target_zone)
|
||||
if(isrobot(user) && istype(tool, /obj/item/gripper))
|
||||
var/obj/item/gripper/G = tool
|
||||
tool = G.get_current_pocket()
|
||||
tool = G.get_wrapped_item()
|
||||
user.visible_message(span_notice("[user] starts putting \the [tool] inside [target]'s [get_cavity(affected)] cavity."), \
|
||||
span_notice("You start putting \the [tool] inside [target]'s [get_cavity(affected)] cavity.") ) //Nobody will probably ever see this, but I made these two blue. ~CK
|
||||
user.balloon_alert_visible("starts putting \the [tool] inside [target]'s [get_cavity(affected)]", "putting \the [tool] inside \the [get_cavity(affected)]")
|
||||
@@ -165,7 +165,7 @@
|
||||
var/obj/item/organ/external/chest/affected = target.get_organ(target_zone)
|
||||
if(isrobot(user) && istype(tool, /obj/item/gripper))
|
||||
var/obj/item/gripper/G = tool
|
||||
tool = G.get_current_pocket()
|
||||
tool = G.get_wrapped_item()
|
||||
G.drop_item_nm()
|
||||
else
|
||||
user.drop_item()
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
return ..()
|
||||
|
||||
|
||||
/obj/structure/table/attackby(obj/item/W as obj, mob/user as mob, var/hit_modifier, var/click_parameters)
|
||||
/obj/structure/table/attackby(obj/item/W, mob/user, hit_modifier, click_parameters)
|
||||
if (!W) return
|
||||
|
||||
// Handle harm intent grabbing/tabling.
|
||||
@@ -128,7 +128,13 @@
|
||||
|
||||
// Handle dismantling or placing things on the table from here on.
|
||||
if(isrobot(user))
|
||||
return
|
||||
if(istype(W, /obj/item/gripper))
|
||||
var/obj/item/gripper/robot_gripper = W
|
||||
var/obj/item/item_to_drop = robot_gripper.get_wrapped_item()
|
||||
robot_gripper.drop_item_nm(loc)
|
||||
item_to_drop.do_drop_animation(user)
|
||||
auto_align(item_to_drop, click_parameters)
|
||||
return FALSE
|
||||
|
||||
if(W.loc != user) // This should stop mounted modules ending up outside the module.
|
||||
return
|
||||
|
||||
@@ -3716,6 +3716,7 @@
|
||||
#include "code\modules\mob\living\silicon\robot\robot_animation_vr.dm"
|
||||
#include "code\modules\mob\living\silicon\robot\robot_bellies.dm"
|
||||
#include "code\modules\mob\living\silicon\robot\robot_damage.dm"
|
||||
#include "code\modules\mob\living\silicon\robot\robot_gripper_handling.dm"
|
||||
#include "code\modules\mob\living\silicon\robot\robot_items.dm"
|
||||
#include "code\modules\mob\living\silicon\robot\robot_movement.dm"
|
||||
#include "code\modules\mob\living\silicon\robot\robot_remote_control.dm"
|
||||
|
||||
Reference in New Issue
Block a user