Files
CHOMPStation2/code/_onclick/click.dm
Zuhayr ebbb9b36b5 Moved everything to a module-based hardsuit system.
Generalized all ninja power and gear code to work with new rig system.
Added shurikens, weapon mount, more work on deployable items.
Readded energy nets and energy blades.
Grenade launcher/charge stuff, interface stuff.
Renamed previously existing rigs to voidsuits, restructured rig and voidsuit files.
Refactored the energy net and teleportation proc.
Totally rewrote AI core/intellicard transfer procs.
Added rig sprites by Mordeth221, added step by steap suit sealing/inability to interfere with suit sealing process.
Updated map paths to use voidsuits.
Added chemical dispenser functionality, added power sink, added atom/drain_power() proc for later use.
Added rigsuit verbs, added voice changer.
Renamed MASKINTERNALS to AIRTIGHT, added internals checks for airtight helmets.
Added drain_power() procs to vulnerable machinery.
Reimplemented data theft.
Added suit maluses for losing your cell while wearing one.
Transitioned the rig suits to a back-mounted item that also controls a chestpiece.
Converted rig module to a storage item, convert ERT voidsuits to hardsuits.
2014-11-14 22:57:26 +10:30

342 lines
8.3 KiB
Plaintext

/*
Click code cleanup
~Sayu
*/
// 1 decisecond click delay (above and beyond mob/next_move)
/mob/var/next_click = 0
/*
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)
if(src)
usr.ClickOn(src, params)
/atom/DblClick(location,control,params)
if(src)
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( var/atom/A, var/params )
if(world.time <= next_click)
return
next_click = world.time + 1
if(client.buildmode)
build_click(src, client.buildmode, params, A)
return
var/list/modifiers = params2list(params)
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(stat || paralysis || stunned || weakened)
return
face_atom(A) // change direction to face what you clicked on
if(next_move > world.time) // in the year 2000...
return
if(istype(loc,/obj/mecha))
if(!locate(/turf) in list(A,A.loc)) // Prevents inventory from being drilled
return
var/obj/mecha/M = loc
return M.click_action(A,src)
if(restrained())
RestrainedClickOn(A)
return
if(in_throw_mode)
throw_item(A)
return
if(!istype(A,/obj/item/weapon/gun) && !isturf(A) && !istype(A,/obj/screen))
last_target_click = world.time
var/obj/item/W = get_active_hand()
if(W == A)
next_move = world.time + 6
if(W.flags&USEDELAY)
next_move += 5
W.attack_self(src)
if(hand)
update_inv_l_hand(0)
else
update_inv_r_hand(0)
return
// operate two STORAGE levels deep here (item in backpack in src; NOT item in box in backpack in src)
var/sdepth = A.storage_depth(src)
if(A == loc || (A in loc) || (sdepth != -1 && sdepth <= 1))
// faster access to objects already on you
if(A in contents)
next_move = world.time + 6 // on your person
else
next_move = world.time + 8 // in a box/bag or in your square
// No adjacency needed
if(W)
if(W.flags&USEDELAY)
next_move += 5
var/resolved = A.attackby(W,src)
if(!resolved && A && W)
W.afterattack(A,src,1,params) // 1 indicates adjacency
else
UnarmedAttack(A, 1)
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
sdepth = A.storage_depth_turf()
if(isturf(A) || isturf(A.loc) || (sdepth != -1 && sdepth <= 1))
next_move = world.time + 10
if(A.Adjacent(src)) // see adjacent.dm
if(W)
if(W.flags&USEDELAY)
next_move += 5
// Return 1 in attackby() to prevent afterattack() effects (when safely moving items for example)
var/resolved = A.attackby(W,src)
if(!resolved && A && W)
W.afterattack(A,src,1,params) // 1: clicking something Adjacent
else
UnarmedAttack(A, 1)
return
else // non-adjacent click
if(W)
W.afterattack(A,src,0,params) // 0: not Adjacent
else
RangedAttack(A, params)
return
/mob/proc/changeNext_move(num)
next_move = world.time + num
// Default behavior: ignore double clicks, consider them normal clicks instead
/mob/proc/DblClickOn(var/atom/A, var/params)
ClickOn(A,params)
/*
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(var/atom/A, var/proximity_flag)
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(var/atom/A, var/params)
if(!mutations.len) return
if((LASER in mutations) && a_intent == "harm")
LaserEyes(A) // moved into a proc below
else if(TK in mutations)
switch(get_dist(src,A))
if(0)
;
if(1 to 5) // not adjacent may mean blocked by window
next_move += 2
if(5 to 7)
next_move += 5
if(8 to tk_maxrange)
next_move += 10
else
return
A.attack_tk(src)
/*
Restrained ClickOn
Used when you are handcuffed and click things.
Not currently used by anything but could easily be.
*/
/mob/proc/RestrainedClickOn(var/atom/A)
return
/*
Middle click
Only used for swapping hands
*/
/mob/proc/MiddleClickOn(var/atom/A)
return
/mob/living/carbon/MiddleClickOn(var/atom/A)
swap_hand()
/mob/living/carbon/human/MiddleClickOn(var/atom/A)
if(back)
var/obj/item/weapon/storage/rig/rig = back
if(istype(rig) && rig.selected_module)
if(world.time <= next_move) return
next_move = world.time + 8
rig.selected_module.engage(A)
return
swap_hand()
// In case of use break glass
/*
/atom/proc/MiddleClick(var/mob/M as mob)
return
*/
/*
Shift click
For most mobs, examine.
This is overridden in ai.dm
*/
/mob/proc/ShiftClickOn(var/atom/A)
A.ShiftClick(src)
return
/atom/proc/ShiftClick(var/mob/user)
if(user.client && user.client.eye == user)
user.examinate(src)
return
/*
Ctrl click
For most objects, pull
*/
/mob/proc/CtrlClickOn(var/atom/A)
A.CtrlClick(src)
return
/atom/proc/CtrlClick(var/mob/user)
return
/atom/movable/CtrlClick(var/mob/user)
if(Adjacent(user))
user.start_pulling(src)
/*
Alt click
Unused except for AI
*/
/mob/proc/AltClickOn(var/atom/A)
A.AltClick(src)
return
/atom/proc/AltClick(var/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(var/turf/T)
return T.AdjacentQuick(src)
/*
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)
next_move = world.time + 6
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
spawn( 1 )
LE.process()
/mob/living/carbon/human/LaserEyes()
if(nutrition>0)
..()
nutrition = max(nutrition - rand(1,5),0)
handle_regular_hud_updates()
else
src << "\red You're out of energy! You need food!"
// Simple helper to face what you clicked on, in case it should be needed in more than one place
/mob/proc/face_atom(var/atom/A)
// Snowflake for space vines.
var/is_buckled = 0
if(buckled)
if(istype(buckled))
if(!buckled.movable)
is_buckled = 1
else
is_buckled = 0
if( is_buckled || !A || !x || !y || !A.x || !A.y || (stat && !isobserver(src))) return
var/dx = A.x - x
var/dy = A.y - y
if(!dx && !dy) return
var/direction
if(abs(dx) < abs(dy))
if(dy > 0) direction = NORTH
else direction = SOUTH
else
if(dx > 0) direction = EAST
else direction = WEST
dir = direction
if(buckled && buckled.movable)
buckled.dir = direction
buckled.handle_rotation()