Files
CHOMPStation2StaffMirrorBot e98f29305c [MIRROR] small vac oversights (#12226)
Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com>
2026-01-06 22:46:48 +01:00

349 lines
12 KiB
Plaintext

//Vac attachment
/obj/item/vac_attachment
name = "\improper Vac-Pack attachment"
desc = "Useful for slurping mess off the floors. Even things and stuff depending on settings. Can be connected to a trash bag or vore belly. On-mob sprites can be toggled via verb in Objects tab."
icon = 'icons/mob/vacpack.dmi'
icon_override = 'icons/mob/vacpack.dmi'
icon_state = "sucker_drop"
item_state = "sucker"
slot_flags = SLOT_BELT | SLOT_BACK
var/vac_power = 0
var/output_dest = null
var/list/vac_settings = list(
"power off" = 0,
"dust and grime" = 1,
"tiny objects" = 2,
"pests and small objects" = 3,
"medium objects" = 4,
"large objects" = 5,
"large pests" = 6,
"auto-level" = 7,
"DANGEROUS" = 8,
"output destination" = 9
)
var/vac_owner = null
var/sucksound = 'sound/machines/kitchen/candymaker/candymaker-mid1.ogg'
var/suckverb = "vacuum"
var/suckanim = TRUE
var/pull_range = 1
var/max_items = 20
flags = NOBLUDGEON
/obj/item/vac_attachment/attack_self(mob/user)
. = ..(user)
if(.)
return TRUE
var/set_input = null
if(!output_dest)
set_input = "output destination"
if(!set_input)
set_input = tgui_input_list(user, "Set your [suckverb] attachment's power level or output mode.", "Vac Settings", vac_settings)
if(set_input)
if(set_input == "output destination")
if(vac_owner && user != vac_owner)
to_chat(user, span_warning("Only designated owner can change this setting."))
return
var/vac_options = list("Vore Belly", "Trash Bag") //Dont show option for borg belly if the user isnt even a borg. QOL!
if(isrobot(user))
vac_options = list("Vore Belly", "Borg Belly", "Trash Bag")
var/set_output = tgui_input_list(user, "Set your [suckverb] attachment's connection port", "Vac Settings", vac_options)
switch(set_output)
if("Borg Belly")
if(isrobot(user))
var/mob/living/silicon/robot/R = user
var/obj/item/robot_module/M = R.module
for(var/obj/item/dogborg/sleeper/S in M.modules)
if(istype(S))
output_dest = S
return
to_chat(user, span_warning("Borg belly not found."))
if("Trash Bag")
if(isrobot(user))
var/mob/living/silicon/robot/R = user
var/obj/item/robot_module/M = R.module
for(var/obj/item/storage/bag/trash/T in M.modules)
if(istype(T))
output_dest = T
return
for(var/obj/item/storage/bag/trash/T in user.contents)
if(istype(T))
output_dest = T
return
to_chat(user, span_warning("Trash bag not found."))
if("Vore Belly")
if(user.vore_selected)
output_dest = user.vore_selected
return
else
vac_power = vac_settings[set_input]
icon_state = "sucker-[vac_power]"
/obj/item/vac_attachment/afterattack(atom/target, mob/living/user, proximity)
if(vac_power < 1)
return
if(!proximity)
return
if(!output_dest)
return
if(istype(output_dest,/obj/item/storage/bag/trash))
if(get_turf(output_dest) != get_turf(user))
vac_power = 0
icon_state = "sucker-0"
output_dest = null
to_chat(user, span_warning("Trash bag not found. Shutting down."))
return
var/obj/item/storage/bag/trash/B = output_dest
if(LAZYLEN(B.contents) >= B.max_storage_space) //A bit more lenient than the w_class system to avoid complicated spaghetti.
to_chat(user, span_warning("Trash bag full. Empty trash bag contents to continue."))
return
if(istype(output_dest,/obj/item/dogborg/sleeper))
var/obj/item/dogborg/sleeper/B = output_dest
if(LAZYLEN(B.contents) >= B.max_item_count)
to_chat(user, span_warning("[B.name] full. Empty or process contents to continue."))
return
if(B.ore_storage)
if(B.current_capacity >= B.max_ore_storage)
to_chat(user, span_warning("Ore storage full. Deposit ore contents to a box continue."))
return
if(isbelly(output_dest))
var/turf/T = get_turf(output_dest)
if(!T.Adjacent(user)) //Can still be used as a feeding tube by another adjacent player.
if(vac_owner && user != vac_owner)
return
vac_power = 0
icon_state = "sucker-0"
output_dest = null
to_chat(user, span_warning("Target destination not found. Shutting down."))
return
if(istype(target,/obj/structure/window) || istype(target,/obj/structure/grille))
target = get_turf(target) // Windows can be clicked to clean their turf
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
var/auto_setting = 1
if(isturf(target))
user.visible_message(span_filter_notice("[user] begins [suckverb]ing the mess off \the [target.name]..."), span_notice("You begin [suckverb]ing the mess off \the [target.name]..."))
var/list/suckables = list()
if(vac_power == 8)
playsound(src, 'sound/machines/hiss.ogg', 100, 1, -1)
for(var/obj/item/I in oview(pull_range, target))
if(I.anchored)
continue
I.singularity_pull(target, STAGE_THREE)
suckables += I
for(var/mob/living/L in oview(pull_range, target))
if(L.anchored || !L.devourable || L == user || L.buckled || !L.can_be_drop_prey)
continue
L.singularity_pull(target, STAGE_THREE)
suckables += L
if(vac_power >= 1)
for(var/obj/effect/decal/cleanable/C in target)
suckables += C
if(vac_power >= 2)
for(var/obj/item/I in target)
if(I.anchored || I.w_class > (vac_power - 1) && vac_power < 5 || I.w_class > 5)
continue
suckables += I
for(var/mob/living/L in target)
if(L.anchored || !L.devourable || L == user || L.buckled || !L.can_be_drop_prey)
continue
if(L.size_multiplier < 0.5 || vac_power >= 6)
suckables += L
continue
if(istype(L,/mob/living/simple_mob/animal/passive/mouse) || istype(L,/mob/living/simple_mob/animal/passive/lizard) || istype(L,/mob/living/simple_mob/animal/passive/cockroach))
suckables += L
if(LAZYLEN(suckables))
if(vac_power == 7)
for(var/atom/movable/F in suckables)
if(isitem(F))
auto_setting = max(2, auto_setting)
var/obj/item/I = F
if(I.w_class > auto_setting)
auto_setting = min(I.w_class, 5)
if(isliving(F))
var/mob/living/L = F
if(L.size_multiplier < 0.5 || istype(L,/mob/living/simple_mob/animal/passive/mouse) || istype(L,/mob/living/simple_mob/animal/passive/lizard) || istype(L,/mob/living/simple_mob/animal/passive/cockroach))
if(auto_setting < 3)
auto_setting = 3
else
auto_setting = 6
break
else
auto_setting = vac_power
playsound(src, sucksound, auto_setting * 20, 1, -1)
var/vac_conga = 0
var/sucklimit = max_items
for(var/atom/movable/F in suckables)
if(sucklimit <= 0)
continue
if(is_type_in_list(F, GLOB.item_vore_blacklist))
continue
if(istype(F,/obj/effect/decal/cleanable))
if(isbelly(output_dest))
var/obj/belly/B = output_dest
B.owner_adjust_nutrition(1)
qdel(F)
continue
if(istype(output_dest,/obj/item/storage/bag/trash))
var/obj/item/storage/bag/trash/B = output_dest
if(LAZYLEN(B.contents) >= B.max_storage_space)
to_chat(user, span_warning("Trash bag full. Empty trash bag contents to continue."))
break
sucklimit -= 1
if(suckanim)
if(vac_conga < 100)
vac_conga += 3
addtimer(CALLBACK(src, PROC_REF(prepare_sucking), F, user, auto_setting, target), 0.3 SECONDS + vac_conga)
else
handle_consumption(F, user, auto_setting)
if(vac_conga > 0)
var/obj/effect/vac_visual/V = new(target)
V.ready(0.5 SECONDS + vac_conga)
if(istype(target, /turf/simulated))
var/turf/simulated/T = target
if(isbelly(output_dest) && T.dirt > 50)
var/obj/belly/B = output_dest
B.owner_adjust_nutrition((T.dirt - 50) / 10) //Max tile dirt is 101. so about 5 nutrition from a disgusting floor, I think that's okay.
T.dirt = 0
T.wash(CLEAN_WASH)
return
if(!isturf(target.loc))
return
if(isitem(target))
var/obj/item/I = target
if(is_type_in_list(I, GLOB.item_vore_blacklist) || I.w_class >= ITEMSIZE_HUGE)
return
if(vac_power > I.w_class)
if(vac_power == 7)
auto_setting = min(I.w_class, 5)
else
auto_setting = vac_power
playsound(src, sucksound, auto_setting * 20, 1, -1)
user.visible_message(span_filter_notice("[user] [suckverb]s up \the [target.name]."), span_notice("You [suckverb] up \the [target.name]..."))
if(suckanim)
I.SpinAnimation(5,1)
addtimer(CALLBACK(src, PROC_REF(handle_consumption), I, user, auto_setting), 0.5 SECONDS)
return
if(istype(target,/obj/effect/decal/cleanable))
playsound(src, sucksound, auto_setting * 20, 1, -1)
user.visible_message(span_filter_notice("[user] [suckverb]s up \the [target.name]."), span_notice("You [suckverb] up \the [target.name]..."))
qdel(target)
return
if(isliving(target))
var/mob/living/L = target
var/valid_to_suck = FALSE
if(L.anchored || !L.devourable || L == user || L.buckled || !L.can_be_drop_prey)
return
if(vac_power >= 3)
if(L.size_multiplier > 0.5 || istype(L,/mob/living/simple_mob/animal/passive/mouse) || istype(L,/mob/living/simple_mob/animal/passive/lizard))
valid_to_suck = TRUE
auto_setting = 3
if(vac_power >= 6)
valid_to_suck = TRUE
auto_setting = 6
if(valid_to_suck)
playsound(src, sucksound, auto_setting * 20, 1, -1)
user.visible_message(span_filter_notice("[user] [suckverb]s up \the [target.name]."), span_notice("You [suckverb] up \the [target.name]..."))
if(suckanim)
L.SpinAnimation(5,1)
addtimer(CALLBACK(src, PROC_REF(handle_consumption), L, user, auto_setting), 0.5 SECONDS)
/obj/item/vac_attachment/proc/prepare_sucking(atom/movable/target, mob/user, turf/target_turf)
if(!target.Adjacent(user) || src.loc != user || vac_power < 2 || !output_dest) //Cancel if moved/unpowered/dropped
return
target.SpinAnimation(5,1)
addtimer(CALLBACK(src, PROC_REF(handle_consumption), target, user, target_turf), 0.5 SECONDS)
/obj/item/vac_attachment/proc/handle_consumption(atom/movable/target, mob/user, auto_setting, turf/target_turf)
if(target_turf && target.loc != target_turf)
return
if(!target.Adjacent(user) || src.loc != user || vac_power < 2 || !output_dest) //Cancel if moved/unpowered/dropped
return
if(isitem(target))
var/obj/item/target_item = target
if(target_item.drop_sound)
playsound(src, target_item.drop_sound, vac_power * 5, 1, -1)
playsound(src, 'sound/rakshasa/corrosion3.ogg', auto_setting * 15, 1, -1)
if(isbelly(output_dest))
var/obj/belly/output_belly = output_dest
output_belly.nom_atom(target)
return
target.forceMove(output_dest)
/obj/item/vac_attachment/resolve_attackby(atom/A, mob/user, var/attack_modifier = 1, var/click_parameters)
if(istype(A,/obj/structure) && vac_power > 0)
afterattack(A.loc, user, click_parameters)
return TRUE
return ..()
/obj/item/vac_attachment/pickup(mob/user)
.=..()
icon_state = "sucker-[vac_power]"
/obj/item/vac_attachment/equipped()
.=..()
icon_state = "sucker-[vac_power]"
/obj/item/vac_attachment/dropped(mob/user as mob)
.=..()
icon_state = "sucker_drop"
/obj/item/vac_attachment/verb/hide_pack()
set name = "Toggle Vac-Pack Sprites"
set desc = "Toggle Vac-Pack sprite visibility"
set category = "Object"
var/choice = tgui_input_list(usr, "Vac-Pack Visibility Options", "Vac-Pack Visibility Options", list("Show Pack", "Show Tube", "Hidden"))
if(!choice)
return
switch(choice)
if("Show Pack")
item_state = "sucker"
if("Show Tube")
item_state = "sucker_nobag"
if("Hidden")
item_state = null
usr.update_inv_r_hand()
usr.update_inv_l_hand()
/obj/item/storage/Entered(atom/movable/thing, atom/OldLoc) //Holder the mob so they don't get stuck in trashbags etc.
. = ..()
if(isliving(thing))
var/mob/living/L = thing
var/mob_holder_type = L.holder_type || /obj/item/holder
new mob_holder_type(src, L)
/obj/item/vac_attachment/scoop
name = "\improper Scoop Hopper"
desc = "Useful for scooping clutter off the floors. Even things and stuff depending on settings. Can be connected to a trash bag or vore belly. On-mob sprites can be toggled via verb in Objects tab."
sucksound = 'sound/machines/hatchclose.ogg'
suckverb = "scoop"
suckanim = FALSE
vac_settings = list(
"power off" = 0,
"dust and grime" = 1,
"tiny objects" = 2,
"pests and small objects" = 3,
"medium objects" = 4,
"large objects" = 5,
"large pests" = 6,
"auto-level" = 7,
"output destination" = 8
)
/obj/effect/vac_visual
icon = 'icons/effects/anomalies.dmi'
icon_state = "vortex"
anchored = TRUE
layer = ABOVE_MOB_LAYER
plane = TURF_PLANE
mouse_opacity = 0
blend_mode = BLEND_ADD
/obj/effect/vac_visual/proc/ready(effect_time)
QDEL_IN(src, effect_time)