mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-01-10 00:43:14 +00:00
This PR ports pockets (from Animus Green) and adds them to some clothing. Shoes that support storing items now use pockets system. Some hats have 1 small pocket. Detective's hat spawns with a flask in it. Clown's mask has a single tiny top-secret pocket. Honk! This PR also includes two or three path fixes. It also fixes internal storages (pockets, storage implant) having less "max depth" than external ones.
371 lines
9.8 KiB
Plaintext
371 lines
9.8 KiB
Plaintext
/*
|
|
Click code cleanup
|
|
~Sayu
|
|
*/
|
|
|
|
// 1 decisecond click delay (above and beyond mob/next_move)
|
|
//This is mainly modified by click code, to modify click delays elsewhere, use next_move and changeNext_move()
|
|
/mob/var/next_click = 0
|
|
|
|
// THESE DO NOT EFFECT THE BASE 1 DECISECOND DELAY OF NEXT_CLICK
|
|
/mob/var/next_move_adjust = 0 //Amount to adjust action/click delays by, + or -
|
|
/mob/var/next_move_modifier = 1 //Value to multiply action/click delays by
|
|
|
|
|
|
//Delays the mob's next click/action by num deciseconds
|
|
// eg: 10-3 = 7 deciseconds of delay
|
|
// eg: 10*0.5 = 5 deciseconds of delay
|
|
// DOES NOT EFFECT THE BASE 1 DECISECOND DELAY OF NEXT_CLICK
|
|
|
|
/mob/proc/changeNext_move(num)
|
|
next_move = world.time + ((num+next_move_adjust)*next_move_modifier)
|
|
|
|
|
|
/*
|
|
Before anything else, defer these calls to a per-mobtype handler. This allows us to
|
|
remove istype() spaghetti code, but requires the addition of other handler procs to simplify it.
|
|
|
|
Alternately, you could hardcode every mob's variation in a flat ClickOn() proc; however,
|
|
that's a lot of code duplication and is hard to maintain.
|
|
|
|
Note that this proc can be overridden, and is in the case of screen objects.
|
|
*/
|
|
/atom/Click(location,control,params)
|
|
usr.ClickOn(src, params)
|
|
/atom/DblClick(location,control,params)
|
|
usr.DblClickOn(src,params)
|
|
|
|
/*
|
|
Standard mob ClickOn()
|
|
Handles exceptions: Buildmode, middle click, modified clicks, mech actions
|
|
|
|
After that, mostly just check your state, check whether you're holding an item,
|
|
check whether you're adjacent to the target, then pass off the click to whoever
|
|
is recieving it.
|
|
The most common are:
|
|
* mob/UnarmedAttack(atom,adjacent) - used here only when adjacent, with no item in hand; in the case of humans, checks gloves
|
|
* atom/attackby(item,user) - used only when adjacent
|
|
* item/afterattack(atom,user,adjacent,params) - used both ranged and adjacent
|
|
* mob/RangedAttack(atom,params) - used only ranged, only used for tk and laser eyes but could be changed
|
|
*/
|
|
/mob/proc/ClickOn( atom/A, params )
|
|
if(world.time <= next_click)
|
|
return
|
|
next_click = world.time + 1
|
|
|
|
if(client.click_intercept)
|
|
if(call(client.click_intercept, "InterceptClickOn")(src, params, A))
|
|
return
|
|
|
|
var/list/modifiers = params2list(params)
|
|
if(modifiers["shift"] && modifiers["middle"])
|
|
ShiftMiddleClickOn(A)
|
|
return
|
|
if(modifiers["shift"] && modifiers["ctrl"])
|
|
CtrlShiftClickOn(A)
|
|
return
|
|
if(modifiers["middle"])
|
|
MiddleClickOn(A)
|
|
return
|
|
if(modifiers["shift"])
|
|
ShiftClickOn(A)
|
|
return
|
|
if(modifiers["alt"]) // alt and alt-gr (rightalt)
|
|
AltClickOn(A)
|
|
return
|
|
if(modifiers["ctrl"])
|
|
CtrlClickOn(A)
|
|
return
|
|
|
|
if(incapacitated(ignore_restraints = 1))
|
|
return
|
|
|
|
face_atom(A)
|
|
|
|
if(next_move > world.time) // in the year 2000...
|
|
return
|
|
|
|
if(istype(loc,/obj/mecha))
|
|
var/obj/mecha/M = loc
|
|
return M.click_action(A,src,params)
|
|
|
|
if(restrained())
|
|
changeNext_move(CLICK_CD_HANDCUFFED) //Doing shit in cuffs shall be vey slow
|
|
RestrainedClickOn(A)
|
|
return
|
|
|
|
if(in_throw_mode)
|
|
throw_item(A)
|
|
return
|
|
|
|
var/obj/item/W = get_active_hand()
|
|
|
|
|
|
if(W == A)
|
|
W.attack_self(src)
|
|
if(hand)
|
|
update_inv_l_hand(0)
|
|
else
|
|
update_inv_r_hand(0)
|
|
return
|
|
|
|
// operate three levels deep here (item in backpack in src; item in box in backpack in src, not any deeper)
|
|
if(A.ClickAccessible(src, depth=INVENTORY_DEPTH))
|
|
// No adjacency needed
|
|
if(W)
|
|
var/resolved = A.attackby(W,src)
|
|
if(!resolved && A && W)
|
|
W.afterattack(A,src,1,params) // 1 indicates adjacency
|
|
else
|
|
if(ismob(A))
|
|
changeNext_move(CLICK_CD_MELEE)
|
|
UnarmedAttack(A)
|
|
return
|
|
|
|
if(!isturf(loc)) // This is going to stop you from telekinesing from inside a closet, but I don't shed many tears for that
|
|
return
|
|
|
|
// Allows you to click on a box's contents, if that box is on the ground, but no deeper than that
|
|
if(isturf(A) || isturf(A.loc) || (A.loc && isturf(A.loc.loc)))
|
|
if(A.Adjacent(src)) // see adjacent.dm
|
|
if(W)
|
|
// Return 1 in attackby() to prevent afterattack() effects (when safely moving items for example)
|
|
var/resolved = A.attackby(W,src,params)
|
|
if(!resolved && A && W)
|
|
W.afterattack(A,src,1,params) // 1: clicking something Adjacent
|
|
else
|
|
if(ismob(A))
|
|
changeNext_move(CLICK_CD_MELEE)
|
|
UnarmedAttack(A, 1)
|
|
return
|
|
else // non-adjacent click
|
|
if(W)
|
|
W.afterattack(A,src,0,params) // 0: not Adjacent
|
|
else
|
|
RangedAttack(A, params)
|
|
|
|
// Default behavior: ignore double clicks (the second click that makes the doubleclick call already calls for a normal click)
|
|
/mob/proc/DblClickOn(atom/A, params)
|
|
return
|
|
|
|
|
|
/*
|
|
Translates into attack_hand, etc.
|
|
|
|
Note: proximity_flag here is used to distinguish between normal usage (flag=1),
|
|
and usage when clicking on things telekinetically (flag=0). This proc will
|
|
not be called at ranged except with telekinesis.
|
|
|
|
proximity_flag is not currently passed to attack_hand, and is instead used
|
|
in human click code to allow glove touches only at melee range.
|
|
*/
|
|
/mob/proc/UnarmedAttack(atom/A, proximity_flag)
|
|
if(ismob(A))
|
|
changeNext_move(CLICK_CD_MELEE)
|
|
return
|
|
|
|
/*
|
|
Ranged unarmed attack:
|
|
|
|
This currently is just a default for all mobs, involving
|
|
laser eyes and telekinesis. You could easily add exceptions
|
|
for things like ranged glove touches, spitting alien acid/neurotoxin,
|
|
animals lunging, etc.
|
|
*/
|
|
/mob/proc/RangedAttack(atom/A, params)
|
|
/*
|
|
Restrained ClickOn
|
|
|
|
Used when you are handcuffed and click things.
|
|
Not currently used by anything but could easily be.
|
|
*/
|
|
/mob/proc/RestrainedClickOn(atom/A)
|
|
return
|
|
|
|
/*
|
|
Middle click
|
|
Only used for swapping hands
|
|
*/
|
|
/mob/proc/MiddleClickOn(atom/A)
|
|
return
|
|
|
|
/mob/living/carbon/MiddleClickOn(atom/A)
|
|
if(!src.stat && src.mind && src.mind.changeling && src.mind.changeling.chosen_sting && (istype(A, /mob/living/carbon)) && (A != src))
|
|
next_click = world.time + 5
|
|
mind.changeling.chosen_sting.try_to_sting(src, A)
|
|
else
|
|
swap_hand()
|
|
|
|
/mob/living/simple_animal/drone/MiddleClickOn(atom/A)
|
|
swap_hand()
|
|
|
|
// In case of use break glass
|
|
/*
|
|
/atom/proc/MiddleClick(mob/M as mob)
|
|
return
|
|
*/
|
|
|
|
/*
|
|
Shift click
|
|
For most mobs, examine.
|
|
This is overridden in ai.dm
|
|
*/
|
|
/mob/proc/ShiftClickOn(atom/A)
|
|
A.ShiftClick(src)
|
|
return
|
|
/atom/proc/ShiftClick(mob/user)
|
|
if(user.client && user.client.eye == user || user.client.eye == user.loc)
|
|
user.examinate(src)
|
|
return
|
|
|
|
/*
|
|
Ctrl click
|
|
For most objects, pull
|
|
*/
|
|
/mob/proc/CtrlClickOn(atom/A)
|
|
A.CtrlClick(src)
|
|
return
|
|
|
|
/atom/proc/CtrlClick(mob/user)
|
|
var/mob/living/ML = user
|
|
if(istype(ML))
|
|
ML.pulled(src)
|
|
|
|
/*
|
|
Alt click
|
|
Unused except for AI
|
|
*/
|
|
/mob/proc/AltClickOn(atom/A)
|
|
A.AltClick(src)
|
|
return
|
|
|
|
/mob/living/carbon/AltClickOn(atom/A)
|
|
if(!src.stat && src.mind && src.mind.changeling && src.mind.changeling.chosen_sting && (istype(A, /mob/living/carbon)) && (A != src))
|
|
next_click = world.time + 5
|
|
mind.changeling.chosen_sting.try_to_sting(src, A)
|
|
else
|
|
..()
|
|
|
|
/atom/proc/AltClick(mob/user)
|
|
var/turf/T = get_turf(src)
|
|
if(T && user.TurfAdjacent(T))
|
|
if(user.listed_turf == T)
|
|
user.listed_turf = null
|
|
else
|
|
user.listed_turf = T
|
|
user.client.statpanel = T.name
|
|
return
|
|
|
|
/mob/proc/TurfAdjacent(turf/T)
|
|
return T.Adjacent(src)
|
|
|
|
/*
|
|
Control+Shift click
|
|
Unused except for AI
|
|
*/
|
|
/mob/proc/CtrlShiftClickOn(atom/A)
|
|
A.CtrlShiftClick(src)
|
|
return
|
|
|
|
/mob/proc/ShiftMiddleClickOn(atom/A)
|
|
src.pointed(A)
|
|
return
|
|
|
|
/atom/proc/CtrlShiftClick(mob/user)
|
|
return
|
|
|
|
/*
|
|
Helper to check can the mob click/access an item.
|
|
Used by mob inventory and storage items.
|
|
*/
|
|
/atom/proc/ClickAccessible(mob/user, depth=1)
|
|
if(src == user.loc || (src in user.contents))
|
|
return TRUE
|
|
|
|
if(loc && depth > 1)
|
|
return loc.ClickAccessible(user, depth-1)
|
|
|
|
/turf/ClickAccessible(mob/user, depth=1)
|
|
return
|
|
|
|
|
|
/*
|
|
Misc helpers
|
|
|
|
Laser Eyes: as the name implies, handles this since nothing else does currently
|
|
face_atom: turns the mob towards what you clicked on
|
|
*/
|
|
/mob/proc/LaserEyes(atom/A)
|
|
return
|
|
|
|
/mob/living/LaserEyes(atom/A)
|
|
changeNext_move(CLICK_CD_RANGE)
|
|
var/turf/T = get_turf(src)
|
|
var/turf/U = get_turf(A)
|
|
|
|
var/obj/item/projectile/beam/LE = new /obj/item/projectile/beam( loc )
|
|
LE.icon = 'icons/effects/genetics.dmi'
|
|
LE.icon_state = "eyelasers"
|
|
playsound(usr.loc, 'sound/weapons/taser2.ogg', 75, 1)
|
|
|
|
LE.firer = src
|
|
LE.def_zone = get_organ_target()
|
|
LE.original = A
|
|
LE.current = T
|
|
LE.yo = U.y - T.y
|
|
LE.xo = U.x - T.x
|
|
LE.fire()
|
|
|
|
// Simple helper to face what you clicked on, in case it should be needed in more than one place
|
|
/mob/proc/face_atom(atom/A)
|
|
if( buckled || stat != CONSCIOUS || !A || !x || !y || !A.x || !A.y )
|
|
return
|
|
var/dx = A.x - x
|
|
var/dy = A.y - y
|
|
if(!dx && !dy) // Wall items are graphically shifted but on the floor
|
|
if(A.pixel_y > 16)
|
|
setDir(NORTH)
|
|
else if(A.pixel_y < -16)
|
|
setDir(SOUTH)
|
|
else if(A.pixel_x > 16)
|
|
setDir(EAST)
|
|
else if(A.pixel_x < -16)
|
|
setDir(WEST)
|
|
return
|
|
|
|
if(abs(dx) < abs(dy))
|
|
if(dy > 0)
|
|
setDir(NORTH)
|
|
else
|
|
setDir(SOUTH)
|
|
else
|
|
if(dx > 0)
|
|
setDir(EAST)
|
|
else
|
|
setDir(WEST)
|
|
|
|
/obj/screen/click_catcher
|
|
icon = 'icons/mob/screen_gen.dmi'
|
|
icon_state = "click_catcher"
|
|
plane = CLICKCATCHER_PLANE
|
|
mouse_opacity = 2
|
|
screen_loc = "CENTER-7,CENTER-7"
|
|
|
|
/obj/screen/click_catcher/proc/MakeGreed()
|
|
. = list()
|
|
for(var/i = 0, i<15, i++)
|
|
for(var/j = 0, j<15, j++)
|
|
var/obj/screen/click_catcher/CC = new()
|
|
CC.screen_loc = "NORTH-[i],EAST-[j]"
|
|
. += CC
|
|
|
|
/obj/screen/click_catcher/Click(location, control, params)
|
|
var/list/modifiers = params2list(params)
|
|
if(modifiers["middle"] && istype(usr, /mob/living/carbon))
|
|
var/mob/living/carbon/C = usr
|
|
C.swap_hand()
|
|
else
|
|
var/turf/T = screen_loc2turf(screen_loc, get_turf(usr))
|
|
if(T)
|
|
T.Click(location, control, params)
|
|
. = 1 |