Some minor Big Manipulator refactors (#90240)

## About The Pull Request

guh

I accidentally broke the manipulator while refactoring the UI because
ALL OF A SUDDEN, one of three options is actually two options that are
not in any way connected although they should be. And also there are
three variables for storing action delays (???). I believe it's not
about GBP in the first place, it's about taking responsibility for your
own fuck-ups, so here I am.

Removed some reused value variables, better autodoc readability, renamed
some procs and variables, made more things into constants.

## Why It's Good For The Game


![image](https://github.com/user-attachments/assets/e850b3e5-441e-45c6-a25e-2bf28c958885)

## Changelog

🆑
refactor: Minor Big Manipulator code refactoring
/🆑

---------

Co-authored-by: SmArtKar <44720187+SmArtKar@users.noreply.github.com>
This commit is contained in:
mcbalaam
2025-03-26 16:44:54 +07:00
committed by GitHub
parent c4280e1fb7
commit fab5943719
4 changed files with 222 additions and 212 deletions

View File

@@ -3,7 +3,7 @@
icon_file = 'icons/effects/96x96.dmi'
json_config = 'code/datums/greyscale/json_configs/heretic_rune.json'
/datum/greyscale_config/manipulator_hand
name = "Manipulator Hand"
/datum/greyscale_config/manipulator_arm
name = "Manipulator Arm"
icon_file = 'icons/obj/machines/big_manipulator_parts/big_manipulator_hand.dmi'
json_config = 'code/datums/greyscale/json_configs/manipulator_hand.json'

View File

@@ -21,11 +21,11 @@
/datum/wires/big_manipulator/get_status()
var/obj/machinery/big_manipulator/manipulator_big = holder
var/list/status = list()
status += "The big light bulb is [manipulator_big.on_button_cutted ? "went out" : manipulator_big.on ? "green" : "red"]."
status += "The big light bulb [manipulator_big.power_access_wire_cut ? "has went out" : "is glowing [manipulator_big.on ? "green" : "red"]"]."
status += "The small red light shows: [isnull(manipulator_big.containment_obj) ? "empty" : "full"]."
status += "Text on the yellow board shows: [manipulator_big.selected_type.name]."
status += "There are [manipulator_big.manipulate_mode] text on the small blue panel."
status += "The purple light is [manipulator_big.only_highest_priority ? "on" : "off"]."
status += "There are [manipulator_big.interaction_mode] text on the small blue panel."
status += "The purple light is [manipulator_big.override_priority ? "on" : "off"]."
status += "The number on small white panel shows [manipulator_big.manipulator_throw_range]."
return status
@@ -35,20 +35,20 @@
if(WIRE_ON)
manipulator_big.try_press_on(usr)
if(WIRE_DROP)
manipulator_big.drop_containment_item()
manipulator_big.drop_held_object()
if(WIRE_ITEM_TYPE)
manipulator_big.change_what_take_type()
manipulator_big.cycle_pickup_type()
if(WIRE_CHANGE_MODE)
manipulator_big.change_mode()
if(WIRE_ONE_PRIORITY_BUTTON)
manipulator_big.only_highest_priority = !manipulator_big.only_highest_priority
manipulator_big.override_priority = !manipulator_big.override_priority
if(WIRE_THROW_RANGE)
manipulator_big.change_throw_range()
manipulator_big.cycle_throw_range()
/datum/wires/big_manipulator/on_cut(wire, mend, source)
var/obj/machinery/big_manipulator/manipulator_big = holder
if(wire == WIRE_ON)
if(mend)
manipulator_big.on_button_cutted = FALSE
manipulator_big.power_access_wire_cut = FALSE
return
manipulator_big.on_button_cutted = TRUE
manipulator_big.power_access_wire_cut = TRUE

View File

@@ -1,6 +1,6 @@
#define DROP_ITEM_MODE "drop"
#define USE_ITEM_MODE "use"
#define THROW_ITEM_MODE "throw"
#define INTERACT_DROP "drop"
#define INTERACT_USE "use"
#define INTERACT_THROW "throw"
#define TAKE_ITEMS 1
#define TAKE_CLOSETS 2
@@ -9,10 +9,22 @@
#define DELAY_STEP 0.1
#define MAX_DELAY 30
/// Manipulator Core. Main part of the mechanism that carries out the entire process.
#define MIN_DELAY_TIER_1 2
#define MIN_DELAY_TIER_2 1.4
#define MIN_DELAY_TIER_3 0.8
#define MIN_DELAY_TIER_4 0.2
#define STATUS_BUSY TRUE
#define STATUS_IDLE FALSE
#define WORKER_SINGLE_USE "single"
#define WORKER_EMPTY_USE "empty"
#define WORKER_NORMAL_USE "normal"
/// The Big Manipulator's core. Main part of the mechanism that carries out the entire process.
/obj/machinery/big_manipulator
name = "Big Manipulator"
desc = "Take and drop objects. Innovation..."
desc = "Operates different objects. Truly, a groundbreaking innovation..."
icon = 'icons/obj/machines/big_manipulator_parts/big_manipulator_core.dmi'
icon_state = "core"
density = TRUE
@@ -20,27 +32,24 @@
greyscale_colors = "#d8ce13"
greyscale_config = /datum/greyscale_config/big_manipulator
/// Min time manipulator can have in delay. Changing on upgrade.
var/min_working_speed = 2
/// Ui number that shows manipulator delay.
var/delay_value = 2
/// How many time manipulator need to take and drop item.
var/working_speed = 2 SECONDS
var/minimal_delay = MIN_DELAY_TIER_1
/// The time it takes for the manipulator to complete the action cycle.
var/interaction_delay = MIN_DELAY_TIER_1
/// Using high tier manipulators speeds up big manipulator and requires more energy.
var/power_use_lvl = 0.2
/// When manipulator already working with item inside he don't take any new items.
var/on_work = FALSE
/// Activate mechanism.
/// The status of the manipulator - `IDLE` or `BUSY`.
var/status = STATUS_IDLE
/// Is the manipulator turned on?
var/on = FALSE
/// Dir to get turf where we take items.
/// The direction the manipulator arm will take items from.
var/take_here = NORTH
/// Dir to get turf where we drop items.
/// The direction the manipulator arm will drop items to.
var/drop_here = SOUTH
/// Turf where we take items.
/// The turf where the manipulator arm will take items from.
var/turf/take_turf
/// Turf where we drop items.
/// The turf where the manipulator arm will drop items to.
var/turf/drop_turf
/// How will manipulator manipulate the object? drop it out by default.
var/manipulate_mode = DROP_ITEM_MODE
/// Priority settings depending on the manipulator drop mode that are available to this manipulator. Filled during Initialize.
var/list/priority_settings_for_drop = list()
/// Priority settings depending on the manipulator use mode that are available to this manipulator. Filled during Initialize.
@@ -48,33 +57,31 @@
/// What priority settings are available to use at the moment.
/// We also use this list to sort priorities from ascending to descending.
var/list/allowed_priority_settings = list()
/// Obj inside manipulator.
/// The object inside the manipulator.
var/datum/weakref/containment_obj
/// Obj used as filter
/// The object used as a filter.
var/datum/weakref/filter_obj
/// Poor monkey that needs to use mode works.
/// The poor monkey that needs to use mode works.
var/datum/weakref/monkey_worker
/// weakref to id that locked this manipualtor.
var/datum/weakref/locked_by_this_id
/// Is manipulator locked by identity id.
var/id_locked = FALSE
/// Other manipulator component.
var/obj/effect/big_manipulator_hand/manipulator_hand
/// Here some ui setting we can on/off:
/// If activated: after item was used manipulator will also drop it.
var/drop_item_after_use = TRUE
/// Allowe monkey to do use mode with empty hand.
var/use_with_empty_hand = FALSE
/// If activated: will select only 1 priority and will not continue to look at the priorities below.
var/only_highest_priority = FALSE
/// Var for throw item mode: changes the range from which the manipulator throws an object.
/// The manipulator's arm.
var/obj/effect/big_manipulator_arm/manipulator_arm
/// How should the manipulator interact with the object?
var/interaction_mode = INTERACT_DROP
/// How should the worker interact with the object?
var/worker_interaction = WORKER_NORMAL_USE
/// The distance the thrown object should travel when thrown.
var/manipulator_throw_range = 1
/// Selected type that manipulator will take for take and drop loop.
/// Overrides the priority selection, only accessing the top priority list element.
var/override_priority = FALSE
/// The `type` the manipulator will interact with only.
var/atom/selected_type
/// Just a lazy number to change selected_type type in array.
var/selected_type_by_number = 1
/// Variable for the wire that disables the power button if the wire is cut.
var/on_button_cutted = FALSE
/// Is the power access wire cut? Disables the power button if `TRUE`.
var/power_access_wire_cut = FALSE
/// List where we can set selected type. Taking items by Initialize.
var/list/allowed_types_to_pick_up = list(
/obj/item,
@@ -84,11 +91,11 @@
/obj/machinery/big_manipulator/Initialize(mapload)
. = ..()
take_and_drop_turfs_check()
create_manipulator_hand()
RegisterSignal(manipulator_hand, COMSIG_QDELETING, PROC_REF(on_hand_qdel))
create_manipulator_arm()
RegisterSignal(manipulator_arm, COMSIG_QDELETING, PROC_REF(on_hand_qdel))
manipulator_lvl()
set_up_priority_settings()
selected_type = allowed_types_to_pick_up[selected_type_by_number]
selected_type = allowed_types_to_pick_up[1]
if(on)
press_on(pressed_by = null)
set_wires(new /datum/wires/big_manipulator(src))
@@ -133,7 +140,7 @@
/obj/machinery/big_manipulator/Destroy(force)
. = ..()
qdel(manipulator_hand)
qdel(manipulator_arm)
if(!isnull(containment_obj))
var/obj/containment_resolve = containment_obj?.resolve()
containment_resolve?.forceMove(get_turf(containment_resolve))
@@ -151,10 +158,10 @@
var/mob/living/carbon/human/species/monkey/poor_monkey = monkey_worker.resolve()
if(gone != poor_monkey)
return
if(!is_type_in_list(poor_monkey, manipulator_hand.vis_contents))
if(!is_type_in_list(poor_monkey, manipulator_arm.vis_contents))
return
manipulator_hand.vis_contents -= poor_monkey
if(manipulate_mode == USE_ITEM_MODE)
manipulator_arm.vis_contents -= poor_monkey
if(interaction_mode == INTERACT_USE)
change_mode()
poor_monkey.remove_offsets(type)
monkey_worker = null
@@ -163,10 +170,10 @@
. = ..()
take_and_drop_turfs_check()
if(isnull(get_turf(src)))
qdel(manipulator_hand)
qdel(manipulator_arm)
return
if(!manipulator_hand)
create_manipulator_hand()
if(!manipulator_arm)
create_manipulator_arm()
/obj/machinery/big_manipulator/emag_act(mob/user, obj/item/card/emag/emag_card)
. = ..()
@@ -184,7 +191,7 @@
/obj/machinery/big_manipulator/wrench_act_secondary(mob/living/user, obj/item/tool)
. = ..()
if(on_work || on)
if(status == STATUS_BUSY || on)
to_chat(user, span_warning("[src] is activated!"))
return ITEM_INTERACT_BLOCKING
rotate_big_hand()
@@ -192,7 +199,7 @@
return ITEM_INTERACT_SUCCESS
/obj/machinery/big_manipulator/can_be_unfasten_wrench(mob/user, silent)
if(on_work || on)
if(status == STATUS_BUSY || on)
to_chat(user, span_warning("[src] is activated!"))
return FAILED_UNFASTEN
return ..()
@@ -229,7 +236,7 @@
/obj/machinery/big_manipulator/mouse_drop_dragged(atom/drop_point, mob/user, src_location, over_location, params)
if(isnull(monkey_worker))
return
if(on_work)
if(status == STATUS_BUSY)
balloon_alert(user, "turn it off first!")
return
var/mob/living/carbon/human/species/monkey/poor_monkey = monkey_worker.resolve()
@@ -248,7 +255,7 @@
return
if(!isnull(monkey_worker))
return
if(on_work)
if(status == STATUS_BUSY)
balloon_alert(user, "turn it off first!")
return
var/mob/living/carbon/human/species/monkey/poor_monkey = monkey
@@ -263,12 +270,12 @@
monkey_worker = WEAKREF(poor_monkey)
poor_monkey.drop_all_held_items()
poor_monkey.forceMove(src)
manipulator_hand.vis_contents += poor_monkey
poor_monkey.dir = manipulator_hand.dir
manipulator_arm.vis_contents += poor_monkey
poor_monkey.dir = manipulator_arm.dir
poor_monkey.add_offsets(
type,
x_add = 32 + manipulator_hand.calculate_item_offset(TRUE, pixels_to_offset = 16),
y_add = 32 + manipulator_hand.calculate_item_offset(FALSE, pixels_to_offset = 16)
x_add = 32 + manipulator_arm.calculate_item_offset(TRUE, pixels_to_offset = 16),
y_add = 32 + manipulator_arm.calculate_item_offset(FALSE, pixels_to_offset = 16)
)
/obj/machinery/big_manipulator/attackby(obj/item/is_card, mob/user, params)
@@ -292,10 +299,10 @@
balloon_alert(user, "successfully [!id_locked ? "un" : ""]locked")
/// Creat manipulator hand effect on manipulator core.
/obj/machinery/big_manipulator/proc/create_manipulator_hand()
manipulator_hand = new/obj/effect/big_manipulator_hand(src)
manipulator_hand.dir = take_here
vis_contents += manipulator_hand
/obj/machinery/big_manipulator/proc/create_manipulator_arm()
manipulator_arm = new/obj/effect/big_manipulator_arm(src)
manipulator_arm.dir = take_here
vis_contents += manipulator_arm
/// Check servo tier and change manipulator speed, power_use and colour.
/obj/machinery/big_manipulator/proc/manipulator_lvl()
@@ -304,29 +311,25 @@
return
switch(locate_servo.tier)
if(-INFINITY to 1)
min_working_speed = delay_value = 2
working_speed = 2 SECONDS
minimal_delay = interaction_delay = MIN_DELAY_TIER_1
power_use_lvl = 0.2
set_greyscale(COLOR_YELLOW)
manipulator_hand?.set_greyscale(COLOR_YELLOW)
manipulator_arm?.set_greyscale(COLOR_YELLOW)
if(2)
min_working_speed = delay_value = 1.4
working_speed = 1.4 SECONDS
minimal_delay = interaction_delay = MIN_DELAY_TIER_2
power_use_lvl = 0.4
set_greyscale(COLOR_ORANGE)
manipulator_hand?.set_greyscale(COLOR_ORANGE)
manipulator_arm?.set_greyscale(COLOR_ORANGE)
if(3)
min_working_speed = delay_value = 0.8
working_speed = 0.8 SECONDS
minimal_delay = interaction_delay = MIN_DELAY_TIER_3
power_use_lvl = 0.6
set_greyscale(COLOR_RED)
manipulator_hand?.set_greyscale(COLOR_RED)
manipulator_arm?.set_greyscale(COLOR_RED)
if(4 to INFINITY)
min_working_speed = delay_value = 0.2
working_speed = 0.2 SECONDS
minimal_delay = interaction_delay = MIN_DELAY_TIER_4
power_use_lvl = 0.8
set_greyscale(COLOR_PURPLE)
manipulator_hand?.set_greyscale(COLOR_PURPLE)
manipulator_arm?.set_greyscale(COLOR_PURPLE)
active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * power_use_lvl
@@ -354,10 +357,10 @@
if(WEST)
take_here = NORTH
drop_here = SOUTH
manipulator_hand.dir = take_here
manipulator_arm.dir = take_here
var/mob/monkey = monkey_worker?.resolve()
if(!isnull(monkey))
monkey.dir = manipulator_hand.dir
monkey.dir = manipulator_arm.dir
take_and_drop_turfs_check()
/// Deliting hand will destroy our manipulator core.
@@ -367,9 +370,9 @@
deconstruct(TRUE)
/// Pre take and drop proc from [take and drop procs loop]:
/// Check if we can start take and drop loop
/obj/machinery/big_manipulator/proc/is_work_check()
if(use_with_empty_hand)
/// Can we begin the `take-and-drop` loop?
/obj/machinery/big_manipulator/proc/is_ready_to_work()
if(worker_interaction == WORKER_EMPTY_USE)
try_take_thing()
return TRUE
if(isclosedturf(drop_turf))
@@ -381,7 +384,6 @@
continue
try_take_thing(take_turf, take_item)
break
return TRUE
/// First take and drop proc from [take and drop procs loop]:
@@ -389,13 +391,13 @@
/obj/machinery/big_manipulator/proc/try_take_thing(datum/source, atom/movable/target)
SIGNAL_HANDLER
var/empty_hand_check = use_with_empty_hand && manipulate_mode == USE_ITEM_MODE
var/empty_hand_check = worker_interaction == WORKER_EMPTY_USE && interaction_mode == INTERACT_USE
if(!on)
return
if(!anchored)
return
if(on_work)
if(status == STATUS_BUSY)
return
if(!empty_hand_check)
if(QDELETED(source) || QDELETED(target))
@@ -416,24 +418,24 @@
if(!hand_is_empty)
target.forceMove(src)
containment_obj = WEAKREF(target)
manipulator_hand.update_claw(containment_obj)
on_work = TRUE
manipulator_arm.update_claw(containment_obj)
status = STATUS_BUSY
do_rotate_animation(1)
check_next_move(target, hand_is_empty)
/// 2.5 take and drop proc from [take and drop procs loop]:
/// Choose what we will do with our item by checking the manipulate_mode.
/// Choose what we will do with our item by checking the interaction_mode.
/obj/machinery/big_manipulator/proc/check_next_move(atom/movable/target, hand_is_empty = FALSE)
if(hand_is_empty)
addtimer(CALLBACK(src, PROC_REF(use_thing_with_empty_hand)), working_speed)
addtimer(CALLBACK(src, PROC_REF(use_thing_with_empty_hand)), interaction_delay SECONDS)
return
switch(manipulate_mode)
if(DROP_ITEM_MODE)
addtimer(CALLBACK(src, PROC_REF(drop_thing), target), working_speed)
if(USE_ITEM_MODE)
addtimer(CALLBACK(src, PROC_REF(use_thing), target), working_speed)
if(THROW_ITEM_MODE)
addtimer(CALLBACK(src, PROC_REF(throw_thing), target), working_speed)
switch(interaction_mode)
if(INTERACT_DROP)
addtimer(CALLBACK(src, PROC_REF(drop_thing), target), interaction_delay SECONDS)
if(INTERACT_USE)
addtimer(CALLBACK(src, PROC_REF(use_thing), target), interaction_delay SECONDS)
if(INTERACT_THROW)
addtimer(CALLBACK(src, PROC_REF(throw_thing), target), interaction_delay SECONDS)
/// 3.1 take and drop proc from [take and drop procs loop]:
/// Drop our item.
@@ -441,7 +443,7 @@
/obj/machinery/big_manipulator/proc/drop_thing(atom/movable/target)
var/where_we_drop = search_type_by_priority_in_drop_turf(allowed_priority_settings)
if(isnull(where_we_drop))
addtimer(CALLBACK(src, PROC_REF(drop_thing), target), working_speed)
addtimer(CALLBACK(src, PROC_REF(drop_thing), target), interaction_delay SECONDS)
return
if((where_we_drop == drop_turf) || !isitem(target))
target.forceMove(drop_turf)
@@ -482,14 +484,14 @@
var/obj/item/im_item = target
var/atom/type_to_use = search_type_by_priority_in_drop_turf(allowed_priority_settings)
if(isnull(type_to_use))
check_end_of_use(im_item, target, item_was_used = FALSE)
check_end_of_use(im_item, item_was_used = FALSE)
return
monkey_resolve.put_in_active_hand(im_item)
if(im_item.GetComponent(/datum/component/two_handed)) /// Using two-handed items in two hands.
im_item.attack_self(monkey_resolve)
im_item.melee_attack_chain(monkey_resolve, type_to_use)
do_attack_animation(drop_turf)
manipulator_hand.do_attack_animation(drop_turf)
manipulator_arm.do_attack_animation(drop_turf)
check_end_of_use(im_item, item_was_used = TRUE)
/obj/machinery/big_manipulator/proc/use_thing_with_empty_hand()
@@ -497,7 +499,7 @@
if(isnull(monkey_resolve))
finish_manipulation()
return
var/atom/type_to_use = search_type_by_priority_in_drop_turf(allowed_priority_settings, use_with_empty_hand && manipulate_mode == USE_ITEM_MODE)
var/atom/type_to_use = search_type_by_priority_in_drop_turf(allowed_priority_settings)
if(isnull(type_to_use))
check_end_of_use_for_use_with_empty_hand()
return
@@ -511,14 +513,14 @@
else
monkey_resolve.UnarmedAttack(type_to_use)
do_attack_animation(drop_turf)
manipulator_hand.do_attack_animation(drop_turf)
manipulator_arm.do_attack_animation(drop_turf)
check_end_of_use_for_use_with_empty_hand()
/obj/machinery/big_manipulator/proc/check_end_of_use_for_use_with_empty_hand(obj/item/my_item, item_was_used)
if(!on || (!use_with_empty_hand && manipulate_mode == USE_ITEM_MODE))
if(!on || (worker_interaction != WORKER_EMPTY_USE && interaction_mode == INTERACT_USE))
finish_manipulation()
return
addtimer(CALLBACK(src, PROC_REF(use_thing_with_empty_hand), my_item), working_speed)
addtimer(CALLBACK(src, PROC_REF(use_thing_with_empty_hand), my_item), interaction_delay SECONDS)
/// Check what we gonna do next with our item. Drop it or use again.
/obj/machinery/big_manipulator/proc/check_end_of_use(obj/item/my_item, item_was_used)
@@ -527,12 +529,12 @@
my_item.dir = get_dir(get_turf(my_item), get_turf(src))
finish_manipulation()
return
if(drop_item_after_use && item_was_used)
if(worker_interaction == WORKER_SINGLE_USE && item_was_used)
my_item.forceMove(drop_turf)
my_item.dir = get_dir(get_turf(my_item), get_turf(src))
finish_manipulation()
return
addtimer(CALLBACK(src, PROC_REF(use_thing), my_item), working_speed)
addtimer(CALLBACK(src, PROC_REF(use_thing), my_item), interaction_delay SECONDS)
/// 3.3 take and drop proc from [take and drop procs loop]:
/// Throw item away!!!
@@ -546,31 +548,31 @@
im_item.forceMove(drop_turf)
im_item.throw_at(get_edge_target_turf(get_turf(src), drop_here), manipulator_throw_range - 1, 2)
src.do_attack_animation(drop_turf)
manipulator_hand.do_attack_animation(drop_turf)
manipulator_arm.do_attack_animation(drop_turf)
finish_manipulation()
/// End of thirds take and drop proc from [take and drop procs loop]:
/// Starts manipulator hand backward animation.
/obj/machinery/big_manipulator/proc/finish_manipulation()
containment_obj = null
manipulator_hand.update_claw(null)
manipulator_arm.update_claw(null)
do_rotate_animation(0)
addtimer(CALLBACK(src, PROC_REF(end_work)), working_speed)
addtimer(CALLBACK(src, PROC_REF(end_work)), interaction_delay SECONDS)
/// Fourth and last take and drop proc from [take and drop procs loop]:
/// Finishes work and begins to look for a new item for [take and drop procs loop].
/obj/machinery/big_manipulator/proc/end_work()
on_work = FALSE
is_work_check()
status = STATUS_IDLE
is_ready_to_work()
/// Rotates manipulator hand 90 degrees.
/obj/machinery/big_manipulator/proc/do_rotate_animation(backward)
animate(manipulator_hand, transform = matrix(90, MATRIX_ROTATE), working_speed*0.5)
addtimer(CALLBACK(src, PROC_REF(finish_rotate_animation), backward), working_speed*0.5)
animate(manipulator_arm, transform = matrix(90, MATRIX_ROTATE), interaction_delay SECONDS * 0.5)
addtimer(CALLBACK(src, PROC_REF(finish_rotate_animation), backward), interaction_delay SECONDS * 0.5)
/// Rotates manipulator hand from 90 degrees to 180 or 0 if backward.
/obj/machinery/big_manipulator/proc/finish_rotate_animation(backward)
animate(manipulator_hand, transform = matrix(180 * backward, MATRIX_ROTATE), working_speed*0.5)
animate(manipulator_arm, transform = matrix(180 * backward, MATRIX_ROTATE), interaction_delay SECONDS * 0.5)
/obj/machinery/big_manipulator/proc/check_filter(atom/movable/target)
if (target.anchored || HAS_TRAIT(target, TRAIT_NODROP))
@@ -590,26 +592,22 @@
/// Proc called when we changing item interaction mode.
/obj/machinery/big_manipulator/proc/change_mode()
switch(manipulate_mode)
if(DROP_ITEM_MODE)
if(!isnull(monkey_worker))
manipulate_mode = USE_ITEM_MODE
else
manipulate_mode = THROW_ITEM_MODE
if(USE_ITEM_MODE)
manipulate_mode = THROW_ITEM_MODE
if(THROW_ITEM_MODE)
manipulate_mode = DROP_ITEM_MODE
var/list/available_modes = list(INTERACT_DROP, INTERACT_USE, INTERACT_THROW)
if(isnull(monkey_worker))
available_modes = list(INTERACT_DROP, INTERACT_THROW)
interaction_mode = cycle_value(interaction_mode, available_modes)
update_priority_list()
is_work_check()
is_ready_to_work()
/// Update priority list in ui. Creating new list and sort it by priority number.
/obj/machinery/big_manipulator/proc/update_priority_list()
allowed_priority_settings = list()
var/list/priority_mode_list
if(manipulate_mode == DROP_ITEM_MODE)
if(interaction_mode == INTERACT_DROP)
priority_mode_list = priority_settings_for_drop.Copy()
if(manipulate_mode == USE_ITEM_MODE)
if(interaction_mode == INTERACT_USE)
priority_mode_list = priority_settings_for_use.Copy()
if(isnull(priority_mode_list))
return
@@ -619,12 +617,12 @@
continue
allowed_priority_settings += what_priority
/// Proc thet return item by type in priority list. Selects item and increasing priority number if don't found req type.
/obj/machinery/big_manipulator/proc/search_type_by_priority_in_drop_turf(list/priority_list, empty_hand = FALSE)
/// Proc that return item by type in priority list. Selects item and increasing priority number if don't found req type.
/obj/machinery/big_manipulator/proc/search_type_by_priority_in_drop_turf(list/priority_list)
var/lazy_counter = 1
for(var/datum/manipulator_priority/take_type in priority_list)
/// If we set only_highest_priority on TRUE we don't go to priority below.
if(lazy_counter > 1 && only_highest_priority)
/// If we set override_priority on TRUE we don't go to priority below.
if(lazy_counter > 1 && override_priority)
return null
/// If we need turf we don't check turf.contents and just return drop_turf.
if(take_type.what_type == /turf)
@@ -639,7 +637,7 @@
/obj/machinery/big_manipulator/proc/press_on(pressed_by)
if(pressed_by)
on = !on
if(!is_work_check())
if(!is_ready_to_work())
return
if(on)
RegisterSignal(take_turf, COMSIG_ATOM_ENTERED, PROC_REF(try_take_thing))
@@ -650,37 +648,22 @@
/// Proc that check if button not cutted when we press on button.
/obj/machinery/big_manipulator/proc/try_press_on(mob/user)
if(on_button_cutted)
if(power_access_wire_cut)
balloon_alert(user, "button is cut off!")
return
press_on(pressed_by = TRUE)
/// Drop item that manipulator is manipulating.
/obj/machinery/big_manipulator/proc/drop_containment_item()
/obj/machinery/big_manipulator/proc/drop_held_object()
if(isnull(containment_obj))
return
var/obj/obj_resolve = containment_obj?.resolve()
obj_resolve?.forceMove(get_turf(obj_resolve))
finish_manipulation()
/// Changes the type of objects that the manipulator will pick up
/obj/machinery/big_manipulator/proc/change_what_take_type()
selected_type_by_number++
if(selected_type_by_number > allowed_types_to_pick_up.len)
selected_type_by_number = 1
selected_type = allowed_types_to_pick_up[selected_type_by_number]
is_work_check()
/// Changes range with which the manipulator throws objects, from 1 to 7.
/obj/machinery/big_manipulator/proc/change_throw_range()
manipulator_throw_range++
if(manipulator_throw_range > 7)
manipulator_throw_range = 1
/// Changes manipulator working speed time.
/obj/machinery/big_manipulator/proc/change_delay(new_delay)
delay_value = round(clamp(new_delay, min_working_speed, MAX_DELAY), DELAY_STEP)
working_speed = delay_value SECONDS
interaction_delay = round(clamp(new_delay, minimal_delay, MAX_DELAY), DELAY_STEP)
/obj/machinery/big_manipulator/ui_interact(mob/user, datum/tgui/ui)
if(id_locked)
@@ -701,10 +684,9 @@
data["active"] = on
data["item_as_filter"] = filter_obj?.resolve()
data["selected_type"] = selected_type.name
data["manipulate_mode"] = manipulate_mode
data["drop_after_use"] = drop_item_after_use
data["empty_hand_use"] = use_with_empty_hand
data["highest_priority"] = only_highest_priority
data["interaction_mode"] = interaction_mode
data["worker_interaction"] = worker_interaction
data["highest_priority"] = override_priority
data["throw_range"] = manipulator_throw_range
var/list/priority_list = list()
data["settings_list"] = list()
@@ -714,8 +696,8 @@
priority_data["priority_width"] = allowed_setting.number
priority_list += list(priority_data)
data["settings_list"] = priority_list
data["min_delay"] = min_working_speed
data["delay_value"] = delay_value
data["min_delay"] = minimal_delay
data["interaction_delay"] = interaction_delay
return data
/obj/machinery/big_manipulator/ui_static_data(mob/user)
@@ -733,10 +715,10 @@
try_press_on(ui.user)
return TRUE
if("drop")
drop_containment_item()
drop_held_object()
return TRUE
if("change_take_item_type")
change_what_take_type()
cycle_pickup_type()
return TRUE
if("change_mode")
change_mode()
@@ -749,7 +731,7 @@
if(give_obj_back)
give_obj_back.forceMove(get_turf(src))
filter_obj = null
is_work_check()
is_ready_to_work()
to_chat(living_user, span_warning("Filter removed"))
return TRUE
var/obj/item/get_active_held_item = living_user.get_active_held_item()
@@ -758,17 +740,13 @@
return FALSE
filter_obj = WEAKREF(get_active_held_item)
get_active_held_item.forceMove(src)
is_work_check()
is_ready_to_work()
return TRUE
if("highest_priority_change")
only_highest_priority = !only_highest_priority
override_priority = !override_priority
return TRUE
if("drop_use_change")
drop_item_after_use = !drop_item_after_use
return TRUE
if("empty_use_change")
use_with_empty_hand = !use_with_empty_hand
is_work_check()
if("worker_interaction_change")
cycle_worker_interaction()
return TRUE
if("change_priority")
var/new_priority_number = params["priority"]
@@ -780,8 +758,8 @@
break
update_priority_list()
return TRUE
if("change_throw_range")
change_throw_range()
if("cycle_throw_range")
cycle_throw_range()
return TRUE
if("changeDelay")
change_delay(text2num(params["new_delay"]))
@@ -796,15 +774,15 @@
break
/// Manipulator hand. Effect we animate to show that the manipulator is working and moving something.
/obj/effect/big_manipulator_hand
name = "Manipulator claw"
desc = "Take and drop objects. Innovation..."
/obj/effect/big_manipulator_arm
name = "mechanical claw"
desc = "Takes and drops objects."
icon = 'icons/obj/machines/big_manipulator_parts/big_manipulator_hand.dmi'
icon_state = "hand"
layer = LOW_ITEM_LAYER
appearance_flags = KEEP_TOGETHER | LONG_GLIDE | TILE_BOUND | PIXEL_SCALE
anchored = TRUE
greyscale_config = /datum/greyscale_config/manipulator_hand
greyscale_config = /datum/greyscale_config/manipulator_arm
pixel_x = -32
pixel_y = -32
/// We get item from big manipulator and takes its icon to create overlay.
@@ -812,11 +790,11 @@
/// Var to icon that used as overlay on manipulator claw to show what item it grabs.
var/mutable_appearance/icon_overlay
/obj/effect/big_manipulator_hand/update_overlays()
/obj/effect/big_manipulator_arm/update_overlays()
. = ..()
. += update_item_overlay()
/obj/effect/big_manipulator_hand/proc/update_item_overlay()
/obj/effect/big_manipulator_arm/proc/update_item_overlay()
if(isnull(item_in_my_claw))
return icon_overlay = null
var/atom/movable/item_data = item_in_my_claw.resolve()
@@ -828,12 +806,12 @@
return icon_overlay
/// Updates item that is in the claw.
/obj/effect/big_manipulator_hand/proc/update_claw(clawed_item)
/obj/effect/big_manipulator_arm/proc/update_claw(clawed_item)
item_in_my_claw = clawed_item
update_appearance()
/// Calculate x and y coordinates so that the item icon appears in the claw and not somewhere in the corner.
/obj/effect/big_manipulator_hand/proc/calculate_item_offset(is_x = TRUE, pixels_to_offset = 32)
/obj/effect/big_manipulator_arm/proc/calculate_item_offset(is_x = TRUE, pixels_to_offset = 32)
var/offset
switch(dir)
if(NORTH)
@@ -854,45 +832,66 @@
var/what_type
/**
* Place in the priority queue. The lower the number, the more important the priority.
* Doesnt really matter what number you enter, user can set priority for themselves,
* Doesn't really matter what number you enter, user can set priority for themselves,
* BUT!!!
* Don't write the same numbers in the same parent otherwise something may go wrong.
*/
var/number
/datum/manipulator_priority/for_drop/on_floor
name = "Drop on Floor"
name = "DROP ON FLOOR"
what_type = /turf
number = 1
/datum/manipulator_priority/for_drop/in_storage
name = "Drop in Storage"
name = "DROP IN STORAGE"
what_type = /obj/item/storage
number = 2
/datum/manipulator_priority/for_use/on_living
name = "Use on Living"
name = "USE ON LIVING"
what_type = /mob/living
number = 1
/datum/manipulator_priority/for_use/on_structure
name = "Use on Structure"
name = "USE ON STRUCTURE"
what_type = /obj/structure
number = 2
/datum/manipulator_priority/for_use/on_machinery
name = "Use on Machinery"
name = "USE ON MACHINERY"
what_type = /obj/machinery
number = 3
/datum/manipulator_priority/for_use/on_items
name = "Use on Items"
name = "USE ON ITEM"
what_type = /obj/item
number = 4
#undef DROP_ITEM_MODE
#undef USE_ITEM_MODE
#undef THROW_ITEM_MODE
/// Cycles the given value in the given list. Retuns the next value in the list, or the first one if the list isn't long enough.
/obj/machinery/big_manipulator/proc/cycle_value(current_value, list/possible_values)
var/current_index = possible_values.Find(current_value)
if(current_index == null)
return possible_values[1]
var/next_index = (current_index % possible_values.len) + 1
return possible_values[next_index]
/obj/machinery/big_manipulator/proc/cycle_worker_interaction()
var/list/worker_modes = list(WORKER_NORMAL_USE, WORKER_SINGLE_USE, WORKER_EMPTY_USE)
worker_interaction = cycle_value(worker_interaction, worker_modes)
/obj/machinery/big_manipulator/proc/cycle_throw_range()
var/list/possible_ranges = list(1, 2, 3, 4, 5, 6, 7)
manipulator_throw_range = cycle_value(manipulator_throw_range, possible_ranges)
/obj/machinery/big_manipulator/proc/cycle_pickup_type()
selected_type = cycle_value(selected_type, allowed_types_to_pick_up)
is_ready_to_work()
#undef INTERACT_DROP
#undef INTERACT_USE
#undef INTERACT_THROW
#undef TAKE_ITEMS
#undef TAKE_CLOSETS
@@ -900,3 +899,15 @@
#undef DELAY_STEP
#undef MAX_DELAY
#undef WORKER_NORMAL_USE
#undef WORKER_SINGLE_USE
#undef WORKER_EMPTY_USE
#undef STATUS_IDLE
#undef STATUS_BUSY
#undef MIN_DELAY_TIER_1
#undef MIN_DELAY_TIER_2
#undef MIN_DELAY_TIER_3
#undef MIN_DELAY_TIER_4

View File

@@ -13,16 +13,15 @@ import { Window } from '../layouts';
type ManipulatorData = {
active: BooleanLike;
drop_after_use: BooleanLike;
empty_hand_use: BooleanLike;
interaction_delay: number;
worker_interaction: string;
highest_priority: BooleanLike;
manipulate_mode: string;
interaction_mode: string;
settings_list: PrioritySettings[];
throw_range: number;
item_as_filter: string;
selected_type: string;
delay_step: number;
delay_value: number;
min_delay: number;
max_delay: number;
};
@@ -34,7 +33,7 @@ type PrioritySettings = {
const MasterControls = () => {
const { act, data } = useBackend<ManipulatorData>();
const { delay_step, delay_value, min_delay, max_delay } = data;
const { delay_step, interaction_delay, min_delay, max_delay } = data;
return (
<Stack>
<Stack.Item>Delay:</Stack.Item>
@@ -54,7 +53,7 @@ const MasterControls = () => {
style={{ marginTop: '-5px' }}
step={delay_step}
my={1}
value={delay_value}
value={interaction_delay}
minValue={min_delay}
maxValue={max_delay}
unit="sec."
@@ -133,10 +132,9 @@ export const BigManipulator = () => {
const { data, act } = useBackend<ManipulatorData>();
const {
active,
manipulate_mode,
interaction_mode,
settings_list,
drop_after_use,
empty_hand_use,
worker_interaction,
highest_priority,
throw_range,
item_as_filter,
@@ -171,12 +169,12 @@ export const BigManipulator = () => {
<Table>
<ConfigRow
label="Interaction Mode"
content={manipulate_mode.toUpperCase()}
content={interaction_mode.toUpperCase()}
onClick={() => act('change_mode')}
tooltip="Cycle through interaction modes"
/>
{manipulate_mode === 'throw' && (
{interaction_mode === 'throw' && (
<ConfigRow
label="Throwing Range"
content={`${throw_range} TILE${throw_range > 1 ? 'S' : ''}`}
@@ -191,17 +189,18 @@ export const BigManipulator = () => {
onClick={() => act('change_take_item_type')}
tooltip="Cycle through types of items to filter"
/>
{manipulate_mode === 'use' && (
{interaction_mode === 'use' && (
<ConfigRow
label="Worker Interactions"
content={empty_hand_use ? 'EMPTY' : 'SINGLE'}
onClick={() => act('empty_use_change')}
content={worker_interaction.toUpperCase()}
onClick={() => act('worker_interaction_change')}
tooltip={
empty_hand_use
? 'Interact with an empty hand'
: 'Drop the item after a single interaction cycle'
worker_interaction === 'normal'
? 'Interact using the held item'
: worker_interaction === 'single'
? 'Drop the item after a single cycle'
: 'Interact with an empty hand'
}
selected={!!empty_hand_use}
/>
)}
<ConfigRow
@@ -211,9 +210,9 @@ export const BigManipulator = () => {
tooltip="Click while holding an item to set filtering type"
/>
{manipulate_mode !== 'throw' && (
{interaction_mode !== 'throw' && (
<ConfigRow
label="Use First Dropoff Point Only"
label="Override List Priority"
content={highest_priority ? 'TRUE' : 'FALSE'}
onClick={() => act('highest_priority_change')}
tooltip="Only interact with the highest dropoff point in the list"
@@ -223,7 +222,7 @@ export const BigManipulator = () => {
</Table>
</Section>
{manipulate_mode !== 'throw' && (
{interaction_mode !== 'throw' && (
<Section>
<Table>
{settings_list.map((setting) => (