This commit is contained in:
Putnam
2020-01-15 15:57:32 -08:00
1186 changed files with 197837 additions and 199067 deletions
+105 -105
View File
@@ -1,105 +1,105 @@
/*
Adjacency proc for determining touch range
This is mostly to determine if a user can enter a square for the purposes of touching something.
Examples include reaching a square diagonally or reaching something on the other side of a glass window.
This is calculated by looking for border items, or in the case of clicking diagonally from yourself, dense items.
This proc will NOT notice if you are trying to attack a window on the other side of a dense object in its turf. There is a window helper for that.
Note that in all cases the neighbor is handled simply; this is usually the user's mob, in which case it is up to you
to check that the mob is not inside of something
*/
/atom/proc/Adjacent(atom/neighbor) // basic inheritance, unused
return 0
// Not a sane use of the function and (for now) indicative of an error elsewhere
/area/Adjacent(var/atom/neighbor)
CRASH("Call to /area/Adjacent(), unimplemented proc")
/*
Adjacency (to turf):
* If you are in the same turf, always true
* If you are vertically/horizontally adjacent, ensure there are no border objects
* If you are diagonally adjacent, ensure you can pass through at least one of the mutually adjacent square.
* Passing through in this case ignores anything with the LETPASSTHROW pass flag, such as tables, racks, and morgue trays.
*/
/turf/Adjacent(atom/neighbor, atom/target = null, atom/movable/mover = null)
var/turf/T0 = get_turf(neighbor)
if(T0 == src) //same turf
return TRUE
if(get_dist(src, T0) > 1 || z != T0.z) //too far
return FALSE
// Non diagonal case
if(T0.x == x || T0.y == y)
// Check for border blockages
return T0.ClickCross(get_dir(T0,src), border_only = 1, target_atom = target, mover = mover) && src.ClickCross(get_dir(src,T0), border_only = 1, target_atom = target, mover = mover)
// Diagonal case
var/in_dir = get_dir(T0,src) // eg. northwest (1+8) = 9 (00001001)
var/d1 = in_dir&3 // eg. north (1+8)&3 (0000 0011) = 1 (0000 0001)
var/d2 = in_dir&12 // eg. west (1+8)&12 (0000 1100) = 8 (0000 1000)
for(var/d in list(d1,d2))
if(!T0.ClickCross(d, border_only = 1, target_atom = target, mover = mover))
continue // could not leave T0 in that direction
var/turf/T1 = get_step(T0,d)
if(!T1 || T1.density)
continue
if(!T1.ClickCross(get_dir(T1,src), border_only = 0, target_atom = target, mover = mover) || !T1.ClickCross(get_dir(T1,T0), border_only = 0, target_atom = target, mover = mover))
continue // couldn't enter or couldn't leave T1
if(!src.ClickCross(get_dir(src,T1), border_only = 1, target_atom = target, mover = mover))
continue // could not enter src
return 1 // we don't care about our own density
return 0
/*
Adjacency (to anything else):
* Must be on a turf
*/
/atom/movable/Adjacent(var/atom/neighbor)
if(neighbor == loc)
return TRUE
var/turf/T = loc
if(!istype(T))
return FALSE
if(T.Adjacent(neighbor, neighbor, src))
return TRUE
return FALSE
// This is necessary for storage items not on your person.
/obj/item/Adjacent(var/atom/neighbor, var/recurse = 1)
if(neighbor == loc)
return 1
if(isitem(loc))
if(recurse > 0)
return loc.Adjacent(neighbor,recurse - 1)
return 0
return ..()
/*
This checks if you there is uninterrupted airspace between that turf and this one.
This is defined as any dense ON_BORDER_1 object, or any dense object without LETPASSTHROW.
The border_only flag allows you to not objects (for source and destination squares)
*/
/turf/proc/ClickCross(target_dir, border_only, target_atom = null, atom/movable/mover = null)
for(var/obj/O in src)
if((mover && O.CanPass(mover,get_step(src,target_dir))) || (!mover && !O.density))
continue
if(O == target_atom || O == mover || (O.pass_flags & LETPASSTHROW)) //check if there's a dense object present on the turf
continue // LETPASSTHROW is used for anything you can click through (or the firedoor special case, see above)
if( O.flags_1&ON_BORDER_1) // windows are on border, check them first
if( O.dir & target_dir || O.dir & (O.dir-1) ) // full tile windows are just diagonals mechanically
return 0 //O.dir&(O.dir-1) is false for any cardinal direction, but true for diagonal ones
else if( !border_only ) // dense, not on border, cannot pass over
return 0
return 1
/*
Adjacency proc for determining touch range
This is mostly to determine if a user can enter a square for the purposes of touching something.
Examples include reaching a square diagonally or reaching something on the other side of a glass window.
This is calculated by looking for border items, or in the case of clicking diagonally from yourself, dense items.
This proc will NOT notice if you are trying to attack a window on the other side of a dense object in its turf. There is a window helper for that.
Note that in all cases the neighbor is handled simply; this is usually the user's mob, in which case it is up to you
to check that the mob is not inside of something
*/
/atom/proc/Adjacent(atom/neighbor) // basic inheritance, unused
return 0
// Not a sane use of the function and (for now) indicative of an error elsewhere
/area/Adjacent(var/atom/neighbor)
CRASH("Call to /area/Adjacent(), unimplemented proc")
/*
Adjacency (to turf):
* If you are in the same turf, always true
* If you are vertically/horizontally adjacent, ensure there are no border objects
* If you are diagonally adjacent, ensure you can pass through at least one of the mutually adjacent square.
* Passing through in this case ignores anything with the LETPASSTHROW pass flag, such as tables, racks, and morgue trays.
*/
/turf/Adjacent(atom/neighbor, atom/target = null, atom/movable/mover = null)
var/turf/T0 = get_turf(neighbor)
if(T0 == src) //same turf
return TRUE
if(get_dist(src, T0) > 1 || z != T0.z) //too far
return FALSE
// Non diagonal case
if(T0.x == x || T0.y == y)
// Check for border blockages
return T0.ClickCross(get_dir(T0,src), border_only = 1, target_atom = target, mover = mover) && src.ClickCross(get_dir(src,T0), border_only = 1, target_atom = target, mover = mover)
// Diagonal case
var/in_dir = get_dir(T0,src) // eg. northwest (1+8) = 9 (00001001)
var/d1 = in_dir&3 // eg. north (1+8)&3 (0000 0011) = 1 (0000 0001)
var/d2 = in_dir&12 // eg. west (1+8)&12 (0000 1100) = 8 (0000 1000)
for(var/d in list(d1,d2))
if(!T0.ClickCross(d, border_only = 1, target_atom = target, mover = mover))
continue // could not leave T0 in that direction
var/turf/T1 = get_step(T0,d)
if(!T1 || T1.density)
continue
if(!T1.ClickCross(get_dir(T1,src), border_only = 0, target_atom = target, mover = mover) || !T1.ClickCross(get_dir(T1,T0), border_only = 0, target_atom = target, mover = mover))
continue // couldn't enter or couldn't leave T1
if(!src.ClickCross(get_dir(src,T1), border_only = 1, target_atom = target, mover = mover))
continue // could not enter src
return 1 // we don't care about our own density
return 0
/*
Adjacency (to anything else):
* Must be on a turf
*/
/atom/movable/Adjacent(var/atom/neighbor)
if(neighbor == loc)
return TRUE
var/turf/T = loc
if(!istype(T))
return FALSE
if(T.Adjacent(neighbor, neighbor, src))
return TRUE
return FALSE
// This is necessary for storage items not on your person.
/obj/item/Adjacent(var/atom/neighbor, var/recurse = 1)
if(neighbor == loc)
return 1
if(isitem(loc))
if(recurse > 0)
return loc.Adjacent(neighbor,recurse - 1)
return 0
return ..()
/*
This checks if you there is uninterrupted airspace between that turf and this one.
This is defined as any dense ON_BORDER_1 object, or any dense object without LETPASSTHROW.
The border_only flag allows you to not objects (for source and destination squares)
*/
/turf/proc/ClickCross(target_dir, border_only, target_atom = null, atom/movable/mover = null)
for(var/obj/O in src)
if((mover && O.CanPass(mover,get_step(src,target_dir))) || (!mover && !O.density))
continue
if(O == target_atom || O == mover || (O.pass_flags & LETPASSTHROW)) //check if there's a dense object present on the turf
continue // LETPASSTHROW is used for anything you can click through (or the firedoor special case, see above)
if( O.flags_1&ON_BORDER_1) // windows are on border, check them first
if( O.dir & target_dir || O.dir & (O.dir-1) ) // full tile windows are just diagonals mechanically
return 0 //O.dir&(O.dir-1) is false for any cardinal direction, but true for diagonal ones
else if( !border_only ) // dense, not on border, cannot pass over
return 0
return 1
+520 -520
View File
File diff suppressed because it is too large Load Diff
+185 -185
View File
@@ -1,185 +1,185 @@
/*
Cyborg ClickOn()
Cyborgs have no range restriction on attack_robot(), because it is basically an AI click.
However, they do have a range restriction on item use, so they cannot do without the
adjacency code.
*/
/mob/living/silicon/robot/ClickOn(var/atom/A, var/params)
if(world.time <= next_click)
return
next_click = world.time + 1
if(check_click_intercept(params,A))
return
if(stat || lockcharge || IsKnockdown() || IsStun() || IsUnconscious())
return
var/list/modifiers = params2list(params)
if(modifiers["shift"] && modifiers["ctrl"])
CtrlShiftClickOn(A)
return
if(modifiers["shift"] && modifiers["middle"])
ShiftMiddleClickOn(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(next_move >= world.time)
return
face_atom(A) // change direction to face what you clicked on
/*
cyborg restrained() currently does nothing
if(restrained())
RestrainedClickOn(A)
return
*/
if(aicamera.in_camera_mode) //Cyborg picture taking
aicamera.camera_mode_off()
aicamera.captureimage(A, usr)
return
var/obj/item/W = get_active_held_item()
if(!W && A.Adjacent(src) && (isobj(A) || ismob(A)))
var/atom/movable/C = A
if(C.can_buckle && C.has_buckled_mobs())
if(C.buckled_mobs.len > 1)
var/unbuckled = input(src, "Who do you wish to unbuckle?","Unbuckle Who?") as null|mob in C.buckled_mobs
if(C.user_unbuckle_mob(unbuckled,src))
return
else
if(C.user_unbuckle_mob(C.buckled_mobs[1],src))
return
if(!W && get_dist(src,A) <= interaction_range)
A.attack_robot(src)
return
if(W)
// buckled cannot prevent machine interlinking but stops arm movement
if( buckled || incapacitated())
return
if(W == A)
W.attack_self(src)
return
// cyborgs are prohibited from using storage items so we can I think safely remove (A.loc in contents)
if(A == loc || (A in loc) || (A in contents))
W.melee_attack_chain(src, A, params)
return
if(!isturf(loc))
return
// cyborgs are prohibited from using storage items so we can I think safely remove (A.loc && isturf(A.loc.loc))
if(isturf(A) || isturf(A.loc))
if(A.Adjacent(src)) // see adjacent.dm
W.melee_attack_chain(src, A, params)
return
else
W.afterattack(A, src, 0, params)
return
//Middle click cycles through selected modules.
/mob/living/silicon/robot/MiddleClickOn(atom/A)
cycle_modules()
return
//Give cyborgs hotkey clicks without breaking existing uses of hotkey clicks
// for non-doors/apcs
/mob/living/silicon/robot/CtrlShiftClickOn(atom/A)
A.BorgCtrlShiftClick(src)
/mob/living/silicon/robot/ShiftClickOn(atom/A)
A.BorgShiftClick(src)
/mob/living/silicon/robot/CtrlClickOn(atom/A)
A.BorgCtrlClick(src)
/mob/living/silicon/robot/AltClickOn(atom/A)
if(!A.BorgAltClick(src))
altclick_listed_turf(A)
/atom/proc/BorgCtrlShiftClick(mob/living/silicon/robot/user) //forward to human click if not overridden
CtrlShiftClick(user)
/obj/machinery/door/airlock/BorgCtrlShiftClick(mob/living/silicon/robot/user) // Sets/Unsets Emergency Access Override Forwards to AI code.
if(get_dist(src,user) <= user.interaction_range)
AICtrlShiftClick()
else
..()
/atom/proc/BorgShiftClick(mob/living/silicon/robot/user) //forward to human click if not overridden
ShiftClick(user)
/obj/machinery/door/airlock/BorgShiftClick(mob/living/silicon/robot/user) // Opens and closes doors! Forwards to AI code.
if(get_dist(src,user) <= user.interaction_range)
AIShiftClick()
else
..()
/atom/proc/BorgCtrlClick(mob/living/silicon/robot/user) //forward to human click if not overridden
CtrlClick(user)
/obj/machinery/door/airlock/BorgCtrlClick(mob/living/silicon/robot/user) // Bolts doors. Forwards to AI code.
if(get_dist(src,user) <= user.interaction_range)
AICtrlClick()
else
..()
/obj/machinery/power/apc/BorgCtrlClick(mob/living/silicon/robot/user) // turns off/on APCs. Forwards to AI code.
if(get_dist(src,user) <= user.interaction_range)
AICtrlClick()
else
..()
/obj/machinery/turretid/BorgCtrlClick(mob/living/silicon/robot/user) //turret control on/off. Forwards to AI code.
if(get_dist(src,user) <= user.interaction_range)
AICtrlClick()
else
..()
/atom/proc/BorgAltClick(mob/living/silicon/robot/user)
return AltClick(user)
/obj/machinery/door/airlock/BorgAltClick(mob/living/silicon/robot/user) // Eletrifies doors. Forwards to AI code.
if(get_dist(src,user) <= user.interaction_range)
return AIAltClick()
return ..()
/obj/machinery/turretid/BorgAltClick(mob/living/silicon/robot/user) //turret lethal on/off. Forwards to AI code.
if(get_dist(src,user) <= user.interaction_range)
return AIAltClick()
return ..()
/*
As with AI, these are not used in click code,
because the code for robots is specific, not generic.
If you would like to add advanced features to robot
clicks, you can do so here, but you will have to
change attack_robot() above to the proper function
*/
/mob/living/silicon/robot/UnarmedAttack(atom/A)
A.attack_robot(src)
/mob/living/silicon/robot/RangedAttack(atom/A)
A.attack_robot(src)
/atom/proc/attack_robot(mob/user)
attack_ai(user)
return
/*
Cyborg ClickOn()
Cyborgs have no range restriction on attack_robot(), because it is basically an AI click.
However, they do have a range restriction on item use, so they cannot do without the
adjacency code.
*/
/mob/living/silicon/robot/ClickOn(var/atom/A, var/params)
if(world.time <= next_click)
return
next_click = world.time + 1
if(check_click_intercept(params,A))
return
if(stat || lockcharge || IsKnockdown() || IsStun() || IsUnconscious())
return
var/list/modifiers = params2list(params)
if(modifiers["shift"] && modifiers["ctrl"])
CtrlShiftClickOn(A)
return
if(modifiers["shift"] && modifiers["middle"])
ShiftMiddleClickOn(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(next_move >= world.time)
return
face_atom(A) // change direction to face what you clicked on
/*
cyborg restrained() currently does nothing
if(restrained())
RestrainedClickOn(A)
return
*/
if(aicamera.in_camera_mode) //Cyborg picture taking
aicamera.camera_mode_off()
aicamera.captureimage(A, usr)
return
var/obj/item/W = get_active_held_item()
if(!W && A.Adjacent(src) && (isobj(A) || ismob(A)))
var/atom/movable/C = A
if(C.can_buckle && C.has_buckled_mobs())
if(C.buckled_mobs.len > 1)
var/unbuckled = input(src, "Who do you wish to unbuckle?","Unbuckle Who?") as null|mob in C.buckled_mobs
if(C.user_unbuckle_mob(unbuckled,src))
return
else
if(C.user_unbuckle_mob(C.buckled_mobs[1],src))
return
if(!W && get_dist(src,A) <= interaction_range)
A.attack_robot(src)
return
if(W)
// buckled cannot prevent machine interlinking but stops arm movement
if( buckled || incapacitated())
return
if(W == A)
W.attack_self(src)
return
// cyborgs are prohibited from using storage items so we can I think safely remove (A.loc in contents)
if(A == loc || (A in loc) || (A in contents))
W.melee_attack_chain(src, A, params)
return
if(!isturf(loc))
return
// cyborgs are prohibited from using storage items so we can I think safely remove (A.loc && isturf(A.loc.loc))
if(isturf(A) || isturf(A.loc))
if(A.Adjacent(src)) // see adjacent.dm
W.melee_attack_chain(src, A, params)
return
else
W.afterattack(A, src, 0, params)
return
//Middle click cycles through selected modules.
/mob/living/silicon/robot/MiddleClickOn(atom/A)
cycle_modules()
return
//Give cyborgs hotkey clicks without breaking existing uses of hotkey clicks
// for non-doors/apcs
/mob/living/silicon/robot/CtrlShiftClickOn(atom/A)
A.BorgCtrlShiftClick(src)
/mob/living/silicon/robot/ShiftClickOn(atom/A)
A.BorgShiftClick(src)
/mob/living/silicon/robot/CtrlClickOn(atom/A)
A.BorgCtrlClick(src)
/mob/living/silicon/robot/AltClickOn(atom/A)
if(!A.BorgAltClick(src))
altclick_listed_turf(A)
/atom/proc/BorgCtrlShiftClick(mob/living/silicon/robot/user) //forward to human click if not overridden
CtrlShiftClick(user)
/obj/machinery/door/airlock/BorgCtrlShiftClick(mob/living/silicon/robot/user) // Sets/Unsets Emergency Access Override Forwards to AI code.
if(get_dist(src,user) <= user.interaction_range)
AICtrlShiftClick()
else
..()
/atom/proc/BorgShiftClick(mob/living/silicon/robot/user) //forward to human click if not overridden
ShiftClick(user)
/obj/machinery/door/airlock/BorgShiftClick(mob/living/silicon/robot/user) // Opens and closes doors! Forwards to AI code.
if(get_dist(src,user) <= user.interaction_range)
AIShiftClick()
else
..()
/atom/proc/BorgCtrlClick(mob/living/silicon/robot/user) //forward to human click if not overridden
CtrlClick(user)
/obj/machinery/door/airlock/BorgCtrlClick(mob/living/silicon/robot/user) // Bolts doors. Forwards to AI code.
if(get_dist(src,user) <= user.interaction_range)
AICtrlClick()
else
..()
/obj/machinery/power/apc/BorgCtrlClick(mob/living/silicon/robot/user) // turns off/on APCs. Forwards to AI code.
if(get_dist(src,user) <= user.interaction_range)
AICtrlClick()
else
..()
/obj/machinery/turretid/BorgCtrlClick(mob/living/silicon/robot/user) //turret control on/off. Forwards to AI code.
if(get_dist(src,user) <= user.interaction_range)
AICtrlClick()
else
..()
/atom/proc/BorgAltClick(mob/living/silicon/robot/user)
return AltClick(user)
/obj/machinery/door/airlock/BorgAltClick(mob/living/silicon/robot/user) // Eletrifies doors. Forwards to AI code.
if(get_dist(src,user) <= user.interaction_range)
return AIAltClick()
return ..()
/obj/machinery/turretid/BorgAltClick(mob/living/silicon/robot/user) //turret lethal on/off. Forwards to AI code.
if(get_dist(src,user) <= user.interaction_range)
return AIAltClick()
return ..()
/*
As with AI, these are not used in click code,
because the code for robots is specific, not generic.
If you would like to add advanced features to robot
clicks, you can do so here, but you will have to
change attack_robot() above to the proper function
*/
/mob/living/silicon/robot/UnarmedAttack(atom/A)
A.attack_robot(src)
/mob/living/silicon/robot/RangedAttack(atom/A)
A.attack_robot(src)
/atom/proc/attack_robot(mob/user)
attack_ai(user)
return
+147 -147
View File
@@ -1,148 +1,148 @@
/*
MouseDrop:
Called on the atom you're dragging. In a lot of circumstances we want to use the
receiving object instead, so that's the default action. This allows you to drag
almost anything into a trash can.
*/
/atom/MouseDrop(atom/over, src_location, over_location, src_control, over_control, params)
if(!usr || !over)
return
if(SEND_SIGNAL(src, COMSIG_MOUSEDROP_ONTO, over, usr) & COMPONENT_NO_MOUSEDROP) //Whatever is receiving will verify themselves for adjacency.
return
if(over == src)
return usr.client.Click(src, src_location, src_control, params)
if(!Adjacent(usr) || !over.Adjacent(usr))
return // should stop you from dragging through windows
over.MouseDrop_T(src,usr)
return
// receive a mousedrop
/atom/proc/MouseDrop_T(atom/dropping, mob/user)
SEND_SIGNAL(src, COMSIG_MOUSEDROPPED_ONTO, dropping, user)
return
/client
var/list/atom/selected_target[2]
var/obj/item/active_mousedown_item = null
var/mouseParams = ""
var/mouseLocation = null
var/mouseObject = null
var/mouseControlObject = null
var/middragtime = 0
var/atom/middragatom
/client/MouseDown(object, location, control, params)
if (mouse_down_icon)
mouse_pointer_icon = mouse_down_icon
var/delay = mob.CanMobAutoclick(object, location, params)
if(delay)
selected_target[1] = object
selected_target[2] = params
while(selected_target[1])
Click(selected_target[1], location, control, selected_target[2])
sleep(delay)
active_mousedown_item = mob.canMobMousedown(object, location, params)
if(active_mousedown_item)
active_mousedown_item.onMouseDown(object, location, params, mob)
/client/MouseUp(object, location, control, params)
if (mouse_up_icon)
mouse_pointer_icon = mouse_up_icon
selected_target[1] = null
if(active_mousedown_item)
active_mousedown_item.onMouseUp(object, location, params, mob)
active_mousedown_item = null
/mob/proc/CanMobAutoclick(object, location, params)
/mob/living/carbon/CanMobAutoclick(atom/object, location, params)
if(!object.IsAutoclickable())
return
var/obj/item/h = get_active_held_item()
if(h)
. = h.CanItemAutoclick(object, location, params)
/mob/proc/canMobMousedown(atom/object, location, params)
/mob/living/carbon/canMobMousedown(atom/object, location, params)
var/obj/item/H = get_active_held_item()
if(H)
. = H.canItemMouseDown(object, location, params)
/obj/item/proc/CanItemAutoclick(object, location, params)
/obj/item/proc/canItemMouseDown(object, location, params)
if(canMouseDown)
return src
/obj/item/proc/onMouseDown(object, location, params, mob)
return
/obj/item/proc/onMouseUp(object, location, params, mob)
return
/obj/item
var/canMouseDown = FALSE
/obj/item/gun
var/automatic = 0 //can gun use it, 0 is no, anything above 0 is the delay between clicks in ds
/obj/item/gun/CanItemAutoclick(object, location, params)
. = automatic
/atom/proc/IsAutoclickable()
. = 1
/obj/screen/IsAutoclickable()
. = 0
/obj/screen/click_catcher/IsAutoclickable()
. = 1
//Please don't roast me too hard
/client/MouseMove(object,location,control,params)
mouseParams = params
mouseLocation = location
mouseObject = object
mouseControlObject = control
if(mob && LAZYLEN(mob.mousemove_intercept_objects))
for(var/datum/D in mob.mousemove_intercept_objects)
D.onMouseMove(object, location, control, params)
if(!show_popup_menus && mob) //CIT CHANGE - passes onmousemove() to mobs
mob.onMouseMove(object, location, control, params) //CIT CHANGE - ditto
..()
/datum/proc/onMouseMove(object, location, control, params)
return
/client/MouseDrag(src_object,atom/over_object,src_location,over_location,src_control,over_control,params)
var/list/L = params2list(params)
if (L["middle"])
if (src_object && src_location != over_location)
middragtime = world.time
middragatom = src_object
else
middragtime = 0
middragatom = null
mouseParams = params
mouseLocation = over_location
mouseObject = over_object
mouseControlObject = over_control
if(selected_target[1] && over_object && over_object.IsAutoclickable())
selected_target[1] = over_object
selected_target[2] = params
if(active_mousedown_item)
active_mousedown_item.onMouseDrag(src_object, over_object, src_location, over_location, params, mob)
/obj/item/proc/onMouseDrag(src_object, over_object, src_location, over_location, params, mob)
return
/client/MouseDrop(src_object, over_object, src_location, over_location, src_control, over_control, params)
if (middragatom == src_object)
middragtime = 0
middragatom = null
/*
MouseDrop:
Called on the atom you're dragging. In a lot of circumstances we want to use the
receiving object instead, so that's the default action. This allows you to drag
almost anything into a trash can.
*/
/atom/MouseDrop(atom/over, src_location, over_location, src_control, over_control, params)
if(!usr || !over)
return
if(SEND_SIGNAL(src, COMSIG_MOUSEDROP_ONTO, over, usr) & COMPONENT_NO_MOUSEDROP) //Whatever is receiving will verify themselves for adjacency.
return
if(over == src)
return usr.client.Click(src, src_location, src_control, params)
if(!Adjacent(usr) || !over.Adjacent(usr))
return // should stop you from dragging through windows
over.MouseDrop_T(src,usr)
return
// receive a mousedrop
/atom/proc/MouseDrop_T(atom/dropping, mob/user)
SEND_SIGNAL(src, COMSIG_MOUSEDROPPED_ONTO, dropping, user)
return
/client
var/list/atom/selected_target[2]
var/obj/item/active_mousedown_item = null
var/mouseParams = ""
var/mouseLocation = null
var/mouseObject = null
var/mouseControlObject = null
var/middragtime = 0
var/atom/middragatom
/client/MouseDown(object, location, control, params)
if (mouse_down_icon)
mouse_pointer_icon = mouse_down_icon
var/delay = mob.CanMobAutoclick(object, location, params)
if(delay)
selected_target[1] = object
selected_target[2] = params
while(selected_target[1])
Click(selected_target[1], location, control, selected_target[2])
sleep(delay)
active_mousedown_item = mob.canMobMousedown(object, location, params)
if(active_mousedown_item)
active_mousedown_item.onMouseDown(object, location, params, mob)
/client/MouseUp(object, location, control, params)
if (mouse_up_icon)
mouse_pointer_icon = mouse_up_icon
selected_target[1] = null
if(active_mousedown_item)
active_mousedown_item.onMouseUp(object, location, params, mob)
active_mousedown_item = null
/mob/proc/CanMobAutoclick(object, location, params)
/mob/living/carbon/CanMobAutoclick(atom/object, location, params)
if(!object.IsAutoclickable())
return
var/obj/item/h = get_active_held_item()
if(h)
. = h.CanItemAutoclick(object, location, params)
/mob/proc/canMobMousedown(atom/object, location, params)
/mob/living/carbon/canMobMousedown(atom/object, location, params)
var/obj/item/H = get_active_held_item()
if(H)
. = H.canItemMouseDown(object, location, params)
/obj/item/proc/CanItemAutoclick(object, location, params)
/obj/item/proc/canItemMouseDown(object, location, params)
if(canMouseDown)
return src
/obj/item/proc/onMouseDown(object, location, params, mob)
return
/obj/item/proc/onMouseUp(object, location, params, mob)
return
/obj/item
var/canMouseDown = FALSE
/obj/item/gun
var/automatic = 0 //can gun use it, 0 is no, anything above 0 is the delay between clicks in ds
/obj/item/gun/CanItemAutoclick(object, location, params)
. = automatic
/atom/proc/IsAutoclickable()
. = 1
/obj/screen/IsAutoclickable()
. = 0
/obj/screen/click_catcher/IsAutoclickable()
. = 1
//Please don't roast me too hard
/client/MouseMove(object,location,control,params)
mouseParams = params
mouseLocation = location
mouseObject = object
mouseControlObject = control
if(mob && LAZYLEN(mob.mousemove_intercept_objects))
for(var/datum/D in mob.mousemove_intercept_objects)
D.onMouseMove(object, location, control, params)
if(!show_popup_menus && mob) //CIT CHANGE - passes onmousemove() to mobs
mob.onMouseMove(object, location, control, params) //CIT CHANGE - ditto
..()
/datum/proc/onMouseMove(object, location, control, params)
return
/client/MouseDrag(src_object,atom/over_object,src_location,over_location,src_control,over_control,params)
var/list/L = params2list(params)
if (L["middle"])
if (src_object && src_location != over_location)
middragtime = world.time
middragatom = src_object
else
middragtime = 0
middragatom = null
mouseParams = params
mouseLocation = over_location
mouseObject = over_object
mouseControlObject = over_control
if(selected_target[1] && over_object && over_object.IsAutoclickable())
selected_target[1] = over_object
selected_target[2] = params
if(active_mousedown_item)
active_mousedown_item.onMouseDrag(src_object, over_object, src_location, over_location, params, mob)
/obj/item/proc/onMouseDrag(src_object, over_object, src_location, over_location, params, mob)
return
/client/MouseDrop(src_object, over_object, src_location, over_location, src_control, over_control, params)
if (middragatom == src_object)
middragtime = 0
middragatom = null
..()
+165 -165
View File
@@ -1,165 +1,165 @@
/*
These defines specificy screen locations. For more information, see the byond documentation on the screen_loc var.
The short version:
Everything is encoded as strings because apparently that's how Byond rolls.
"1,1" is the bottom left square of the user's screen. This aligns perfectly with the turf grid.
"1:2,3:4" is the square (1,3) with pixel offsets (+2, +4); slightly right and slightly above the turf grid.
Pixel offsets are used so you don't perfectly hide the turf under them, that would be crappy.
In addition, the keywords NORTH, SOUTH, EAST, WEST and CENTER can be used to represent their respective
screen borders. NORTH-1, for example, is the row just below the upper edge. Useful if you want your
UI to scale with screen size.
The size of the user's screen is defined by client.view (indirectly by world.view), in our case "15x15".
Therefore, the top right corner (except during admin shenanigans) is at "15,15"
*/
//Lower left, persistent menu
#define ui_inventory "WEST:6,SOUTH:5"
//Middle left indicators
#define ui_lingchemdisplay "WEST,CENTER-1:15"
#define ui_lingstingdisplay "WEST:6,CENTER-3:11"
#define ui_devilsouldisplay "WEST:6,CENTER-1:15"
//Lower center, persistent menu
#define ui_sstore1 "CENTER-5:10,SOUTH:5"
#define ui_id "CENTER-4:12,SOUTH:5"
#define ui_belt "CENTER-3:14,SOUTH:5"
#define ui_back "CENTER-2:14,SOUTH:5"
/proc/ui_hand_position(i) //values based on old hand ui positions (CENTER:-/+16,SOUTH:5)
var/x_off = -(!(i % 2))
var/y_off = round((i-1) / 2)
return"CENTER+[x_off]:16,SOUTH+[y_off]:5"
/proc/ui_equip_position(mob/M)
var/y_off = round((M.held_items.len-1) / 2) //values based on old equip ui position (CENTER: +/-16,SOUTH+1:5)
return "CENTER:-16,SOUTH+[y_off+1]:5"
/proc/ui_swaphand_position(mob/M, which = 1) //values based on old swaphand ui positions (CENTER: +/-16,SOUTH+1:5)
var/x_off = which == 1 ? -1 : 0
var/y_off = round((M.held_items.len-1) / 2)
return "CENTER+[x_off]:16,SOUTH+[y_off+1]:5"
#define ui_storage1 "CENTER+1:18,SOUTH:5"
#define ui_storage2 "CENTER+2:20,SOUTH:5"
#define ui_borg_sensor "CENTER-3:15, SOUTH:5" //borgs
#define ui_borg_lamp "CENTER-4:15, SOUTH:5" //borgs
#define ui_borg_thrusters "CENTER-5:15, SOUTH:5" //borgs
#define ui_inv1 "CENTER-2:16,SOUTH:5" //borgs
#define ui_inv2 "CENTER-1 :16,SOUTH:5" //borgs
#define ui_inv3 "CENTER :16,SOUTH:5" //borgs
#define ui_borg_module "CENTER+1:16,SOUTH:5" //borgs
#define ui_borg_store "CENTER+2:16,SOUTH:5" //borgs
#define ui_borg_camera "CENTER+3:21,SOUTH:5" //borgs
#define ui_borg_album "CENTER+4:21,SOUTH:5" //borgs
#define ui_borg_language_menu "EAST-1:27,SOUTH+2:8" //borgs
#define ui_monkey_head "CENTER-5:13,SOUTH:5" //monkey
#define ui_monkey_mask "CENTER-4:14,SOUTH:5" //monkey
#define ui_monkey_neck "CENTER-3:15,SOUTH:5" //monkey
#define ui_monkey_back "CENTER-2:16,SOUTH:5" //monkey
//#define ui_alien_storage_l "CENTER-2:14,SOUTH:5"//alien
#define ui_alien_storage_r "CENTER+1:18,SOUTH:5"//alien
#define ui_alien_language_menu "EAST-3:26,SOUTH:5" //alien
#define ui_drone_drop "CENTER+1:18,SOUTH:5" //maintenance drones
#define ui_drone_pull "CENTER+2:2,SOUTH:5" //maintenance drones
#define ui_drone_storage "CENTER-2:14,SOUTH:5" //maintenance drones
#define ui_drone_head "CENTER-3:14,SOUTH:5" //maintenance drones
//Lower right, persistent menu
#define ui_drop_throw "EAST-1:28,SOUTH+1:7"
#define ui_pull_resist "EAST-2:26,SOUTH+1:7"
#define ui_movi "EAST-2:26,SOUTH:5"
#define ui_sprintbufferloc "EAST-2:26,SOUTH:18"
#define ui_acti "EAST-3:24,SOUTH:5"
#define ui_zonesel "EAST-1:28,SOUTH:5"
#define ui_acti_alt "EAST-1:28,SOUTH:5" //alternative intent switcher for when the interface is hidden (F12)
#define ui_crafting "EAST-5:20,SOUTH:5"//CIT CHANGE - moves this over one tile to accommodate for combat mode toggle
#define ui_building "EAST-5:20,SOUTH:21"//CIT CHANGE - ditto
#define ui_language_menu "EAST-5:4,SOUTH:21"//CIT CHANGE - ditto
#define ui_voremode "EAST-5:20,SOUTH:5"
#define ui_borg_pull "EAST-2:26,SOUTH+1:7"
#define ui_borg_radio "EAST-1:28,SOUTH+1:7"
#define ui_borg_intents "EAST-2:26,SOUTH:5"
//Upper-middle right (alerts)
#define ui_alert1 "EAST-1:28,CENTER+5:27"
#define ui_alert2 "EAST-1:28,CENTER+4:25"
#define ui_alert3 "EAST-1:28,CENTER+3:23"
#define ui_alert4 "EAST-1:28,CENTER+2:21"
#define ui_alert5 "EAST-1:28,CENTER+1:19"
//Middle right (status indicators)
#define ui_healthdoll "EAST-1:28,CENTER-2:13"
#define ui_health "EAST-1:28,CENTER-1:15"
#define ui_internal "EAST-1:28,CENTER+1:19"//CIT CHANGE - moves internal icon up a little bit to accommodate for the stamina meter
#define ui_mood "EAST-1:28,CENTER-3:10"
//living
#define ui_living_pull "EAST-1:28,CENTER-2:15"
#define ui_living_health "EAST-1:28,CENTER:15"
//borgs
#define ui_borg_health "EAST-1:28,CENTER-1:15" //borgs have the health display where humans have the pressure damage indicator.
//aliens
#define ui_alien_health "EAST,CENTER-1:15" //aliens have the health display where humans have the pressure damage indicator.
#define ui_alienplasmadisplay "EAST,CENTER-2:15"
#define ui_alien_queen_finder "EAST,CENTER-3:15"
//constructs
#define ui_construct_pull "EAST,CENTER-2:15"
#define ui_construct_health "EAST,CENTER:15" //same as borgs and humans
// AI
#define ui_ai_core "SOUTH:6,WEST"
#define ui_ai_camera_list "SOUTH:6,WEST+1"
#define ui_ai_track_with_camera "SOUTH:6,WEST+2"
#define ui_ai_camera_light "SOUTH:6,WEST+3"
#define ui_ai_crew_monitor "SOUTH:6,WEST+4"
#define ui_ai_crew_manifest "SOUTH:6,WEST+5"
#define ui_ai_alerts "SOUTH:6,WEST+6"
#define ui_ai_announcement "SOUTH:6,WEST+7"
#define ui_ai_shuttle "SOUTH:6,WEST+8"
#define ui_ai_state_laws "SOUTH:6,WEST+9"
#define ui_ai_pda_send "SOUTH:6,WEST+10"
#define ui_ai_pda_log "SOUTH:6,WEST+11"
#define ui_ai_take_picture "SOUTH:6,WEST+12"
#define ui_ai_view_images "SOUTH:6,WEST+13"
#define ui_ai_sensor "SOUTH:6,WEST+14"
#define ui_ai_multicam "SOUTH+1:6,WEST+13"
#define ui_ai_add_multicam "SOUTH+1:6,WEST+14"
//Pop-up inventory
#define ui_shoes "WEST+1:8,SOUTH:5"
#define ui_iclothing "WEST:6,SOUTH+1:7"
#define ui_oclothing "WEST+1:8,SOUTH+1:7"
#define ui_gloves "WEST+2:10,SOUTH+1:7"
#define ui_glasses "WEST:6,SOUTH+3:11"
#define ui_mask "WEST+1:8,SOUTH+2:9"
#define ui_ears "WEST+2:10,SOUTH+2:9"
#define ui_neck "WEST:6,SOUTH+2:9"
#define ui_head "WEST+1:8,SOUTH+3:11"
//Ghosts
#define ui_ghost_jumptomob "SOUTH:6,CENTER-2:24"
#define ui_ghost_orbit "SOUTH:6,CENTER-1:24"
#define ui_ghost_reenter_corpse "SOUTH:6,CENTER:24"
#define ui_ghost_teleport "SOUTH:6,CENTER+1:24"
#define ui_ghost_pai "SOUTH: 6, CENTER+2:24"
/*
These defines specificy screen locations. For more information, see the byond documentation on the screen_loc var.
The short version:
Everything is encoded as strings because apparently that's how Byond rolls.
"1,1" is the bottom left square of the user's screen. This aligns perfectly with the turf grid.
"1:2,3:4" is the square (1,3) with pixel offsets (+2, +4); slightly right and slightly above the turf grid.
Pixel offsets are used so you don't perfectly hide the turf under them, that would be crappy.
In addition, the keywords NORTH, SOUTH, EAST, WEST and CENTER can be used to represent their respective
screen borders. NORTH-1, for example, is the row just below the upper edge. Useful if you want your
UI to scale with screen size.
The size of the user's screen is defined by client.view (indirectly by world.view), in our case "15x15".
Therefore, the top right corner (except during admin shenanigans) is at "15,15"
*/
//Lower left, persistent menu
#define ui_inventory "WEST:6,SOUTH:5"
//Middle left indicators
#define ui_lingchemdisplay "WEST,CENTER-1:15"
#define ui_lingstingdisplay "WEST:6,CENTER-3:11"
#define ui_devilsouldisplay "WEST:6,CENTER-1:15"
//Lower center, persistent menu
#define ui_sstore1 "CENTER-5:10,SOUTH:5"
#define ui_id "CENTER-4:12,SOUTH:5"
#define ui_belt "CENTER-3:14,SOUTH:5"
#define ui_back "CENTER-2:14,SOUTH:5"
/proc/ui_hand_position(i) //values based on old hand ui positions (CENTER:-/+16,SOUTH:5)
var/x_off = -(!(i % 2))
var/y_off = round((i-1) / 2)
return"CENTER+[x_off]:16,SOUTH+[y_off]:5"
/proc/ui_equip_position(mob/M)
var/y_off = round((M.held_items.len-1) / 2) //values based on old equip ui position (CENTER: +/-16,SOUTH+1:5)
return "CENTER:-16,SOUTH+[y_off+1]:5"
/proc/ui_swaphand_position(mob/M, which = 1) //values based on old swaphand ui positions (CENTER: +/-16,SOUTH+1:5)
var/x_off = which == 1 ? -1 : 0
var/y_off = round((M.held_items.len-1) / 2)
return "CENTER+[x_off]:16,SOUTH+[y_off+1]:5"
#define ui_storage1 "CENTER+1:18,SOUTH:5"
#define ui_storage2 "CENTER+2:20,SOUTH:5"
#define ui_borg_sensor "CENTER-3:15, SOUTH:5" //borgs
#define ui_borg_lamp "CENTER-4:15, SOUTH:5" //borgs
#define ui_borg_thrusters "CENTER-5:15, SOUTH:5" //borgs
#define ui_inv1 "CENTER-2:16,SOUTH:5" //borgs
#define ui_inv2 "CENTER-1 :16,SOUTH:5" //borgs
#define ui_inv3 "CENTER :16,SOUTH:5" //borgs
#define ui_borg_module "CENTER+1:16,SOUTH:5" //borgs
#define ui_borg_store "CENTER+2:16,SOUTH:5" //borgs
#define ui_borg_camera "CENTER+3:21,SOUTH:5" //borgs
#define ui_borg_album "CENTER+4:21,SOUTH:5" //borgs
#define ui_borg_language_menu "EAST-1:27,SOUTH+2:8" //borgs
#define ui_monkey_head "CENTER-5:13,SOUTH:5" //monkey
#define ui_monkey_mask "CENTER-4:14,SOUTH:5" //monkey
#define ui_monkey_neck "CENTER-3:15,SOUTH:5" //monkey
#define ui_monkey_back "CENTER-2:16,SOUTH:5" //monkey
//#define ui_alien_storage_l "CENTER-2:14,SOUTH:5"//alien
#define ui_alien_storage_r "CENTER+1:18,SOUTH:5"//alien
#define ui_alien_language_menu "EAST-3:26,SOUTH:5" //alien
#define ui_drone_drop "CENTER+1:18,SOUTH:5" //maintenance drones
#define ui_drone_pull "CENTER+2:2,SOUTH:5" //maintenance drones
#define ui_drone_storage "CENTER-2:14,SOUTH:5" //maintenance drones
#define ui_drone_head "CENTER-3:14,SOUTH:5" //maintenance drones
//Lower right, persistent menu
#define ui_drop_throw "EAST-1:28,SOUTH+1:7"
#define ui_pull_resist "EAST-2:26,SOUTH+1:7"
#define ui_movi "EAST-2:26,SOUTH:5"
#define ui_sprintbufferloc "EAST-2:26,SOUTH:18"
#define ui_acti "EAST-3:24,SOUTH:5"
#define ui_zonesel "EAST-1:28,SOUTH:5"
#define ui_acti_alt "EAST-1:28,SOUTH:5" //alternative intent switcher for when the interface is hidden (F12)
#define ui_crafting "EAST-5:20,SOUTH:5"//CIT CHANGE - moves this over one tile to accommodate for combat mode toggle
#define ui_building "EAST-5:20,SOUTH:21"//CIT CHANGE - ditto
#define ui_language_menu "EAST-5:4,SOUTH:21"//CIT CHANGE - ditto
#define ui_voremode "EAST-5:20,SOUTH:5"
#define ui_borg_pull "EAST-2:26,SOUTH+1:7"
#define ui_borg_radio "EAST-1:28,SOUTH+1:7"
#define ui_borg_intents "EAST-2:26,SOUTH:5"
//Upper-middle right (alerts)
#define ui_alert1 "EAST-1:28,CENTER+5:27"
#define ui_alert2 "EAST-1:28,CENTER+4:25"
#define ui_alert3 "EAST-1:28,CENTER+3:23"
#define ui_alert4 "EAST-1:28,CENTER+2:21"
#define ui_alert5 "EAST-1:28,CENTER+1:19"
//Middle right (status indicators)
#define ui_healthdoll "EAST-1:28,CENTER-2:13"
#define ui_health "EAST-1:28,CENTER-1:15"
#define ui_internal "EAST-1:28,CENTER+1:19"//CIT CHANGE - moves internal icon up a little bit to accommodate for the stamina meter
#define ui_mood "EAST-1:28,CENTER-3:10"
//living
#define ui_living_pull "EAST-1:28,CENTER-2:15"
#define ui_living_health "EAST-1:28,CENTER:15"
//borgs
#define ui_borg_health "EAST-1:28,CENTER-1:15" //borgs have the health display where humans have the pressure damage indicator.
//aliens
#define ui_alien_health "EAST,CENTER-1:15" //aliens have the health display where humans have the pressure damage indicator.
#define ui_alienplasmadisplay "EAST,CENTER-2:15"
#define ui_alien_queen_finder "EAST,CENTER-3:15"
//constructs
#define ui_construct_pull "EAST,CENTER-2:15"
#define ui_construct_health "EAST,CENTER:15" //same as borgs and humans
// AI
#define ui_ai_core "SOUTH:6,WEST"
#define ui_ai_camera_list "SOUTH:6,WEST+1"
#define ui_ai_track_with_camera "SOUTH:6,WEST+2"
#define ui_ai_camera_light "SOUTH:6,WEST+3"
#define ui_ai_crew_monitor "SOUTH:6,WEST+4"
#define ui_ai_crew_manifest "SOUTH:6,WEST+5"
#define ui_ai_alerts "SOUTH:6,WEST+6"
#define ui_ai_announcement "SOUTH:6,WEST+7"
#define ui_ai_shuttle "SOUTH:6,WEST+8"
#define ui_ai_state_laws "SOUTH:6,WEST+9"
#define ui_ai_pda_send "SOUTH:6,WEST+10"
#define ui_ai_pda_log "SOUTH:6,WEST+11"
#define ui_ai_take_picture "SOUTH:6,WEST+12"
#define ui_ai_view_images "SOUTH:6,WEST+13"
#define ui_ai_sensor "SOUTH:6,WEST+14"
#define ui_ai_multicam "SOUTH+1:6,WEST+13"
#define ui_ai_add_multicam "SOUTH+1:6,WEST+14"
//Pop-up inventory
#define ui_shoes "WEST+1:8,SOUTH:5"
#define ui_iclothing "WEST:6,SOUTH+1:7"
#define ui_oclothing "WEST+1:8,SOUTH+1:7"
#define ui_gloves "WEST+2:10,SOUTH+1:7"
#define ui_glasses "WEST:6,SOUTH+3:11"
#define ui_mask "WEST+1:8,SOUTH+2:9"
#define ui_ears "WEST+2:10,SOUTH+2:9"
#define ui_neck "WEST:6,SOUTH+2:9"
#define ui_head "WEST+1:8,SOUTH+3:11"
//Ghosts
#define ui_ghost_jumptomob "SOUTH:6,CENTER-2:24"
#define ui_ghost_orbit "SOUTH:6,CENTER-1:24"
#define ui_ghost_reenter_corpse "SOUTH:6,CENTER:24"
#define ui_ghost_teleport "SOUTH:6,CENTER+1:24"
#define ui_ghost_pai "SOUTH: 6, CENTER+2:24"
+69 -69
View File
@@ -1,69 +1,69 @@
#define CREDIT_ROLL_SPEED 125
#define CREDIT_SPAWN_SPEED 10
#define CREDIT_ANIMATE_HEIGHT (14 * world.icon_size)
#define CREDIT_EASE_DURATION 22
#define CREDITS_PATH "[global.config.directory]/contributors.dmi"
/client/proc/RollCredits()
set waitfor = FALSE
if(!fexists(CREDITS_PATH))
return
var/icon/credits_icon = new(CREDITS_PATH)
LAZYINITLIST(credits)
var/list/_credits = credits
verbs += /client/proc/ClearCredits
var/static/list/credit_order_for_this_round
if(isnull(credit_order_for_this_round))
credit_order_for_this_round = list("Thanks for playing!") + (shuffle(icon_states(credits_icon)) - "Thanks for playing!")
for(var/I in credit_order_for_this_round)
if(!credits)
return
_credits += new /obj/screen/credit(null, I, src, credits_icon)
sleep(CREDIT_SPAWN_SPEED)
sleep(CREDIT_ROLL_SPEED - CREDIT_SPAWN_SPEED)
verbs -= /client/proc/ClearCredits
qdel(credits_icon)
/client/proc/ClearCredits()
set name = "Hide Credits"
set category = "OOC"
verbs -= /client/proc/ClearCredits
QDEL_LIST(credits)
credits = null
/obj/screen/credit
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
alpha = 0
screen_loc = "12,1"
layer = SPLASHSCREEN_LAYER
var/client/parent
var/matrix/target
/obj/screen/credit/Initialize(mapload, credited, client/P, icon/I)
. = ..()
icon = I
parent = P
icon_state = credited
maptext = credited
maptext_x = world.icon_size + 8
maptext_y = (world.icon_size / 2) - 4
maptext_width = world.icon_size * 3
var/matrix/M = matrix(transform)
M.Translate(0, CREDIT_ANIMATE_HEIGHT)
animate(src, transform = M, time = CREDIT_ROLL_SPEED)
target = M
animate(src, alpha = 255, time = CREDIT_EASE_DURATION, flags = ANIMATION_PARALLEL)
addtimer(CALLBACK(src, .proc/FadeOut), CREDIT_ROLL_SPEED - CREDIT_EASE_DURATION)
QDEL_IN(src, CREDIT_ROLL_SPEED)
P.screen += src
/obj/screen/credit/Destroy()
var/client/P = parent
P.screen -= src
icon = null
LAZYREMOVE(P.credits, src)
parent = null
return ..()
/obj/screen/credit/proc/FadeOut()
animate(src, alpha = 0, transform = target, time = CREDIT_EASE_DURATION)
#define CREDIT_ROLL_SPEED 125
#define CREDIT_SPAWN_SPEED 10
#define CREDIT_ANIMATE_HEIGHT (14 * world.icon_size)
#define CREDIT_EASE_DURATION 22
#define CREDITS_PATH "[global.config.directory]/contributors.dmi"
/client/proc/RollCredits()
set waitfor = FALSE
if(!fexists(CREDITS_PATH))
return
var/icon/credits_icon = new(CREDITS_PATH)
LAZYINITLIST(credits)
var/list/_credits = credits
verbs += /client/proc/ClearCredits
var/static/list/credit_order_for_this_round
if(isnull(credit_order_for_this_round))
credit_order_for_this_round = list("Thanks for playing!") + (shuffle(icon_states(credits_icon)) - "Thanks for playing!")
for(var/I in credit_order_for_this_round)
if(!credits)
return
_credits += new /obj/screen/credit(null, I, src, credits_icon)
sleep(CREDIT_SPAWN_SPEED)
sleep(CREDIT_ROLL_SPEED - CREDIT_SPAWN_SPEED)
verbs -= /client/proc/ClearCredits
qdel(credits_icon)
/client/proc/ClearCredits()
set name = "Hide Credits"
set category = "OOC"
verbs -= /client/proc/ClearCredits
QDEL_LIST(credits)
credits = null
/obj/screen/credit
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
alpha = 0
screen_loc = "12,1"
layer = SPLASHSCREEN_LAYER
var/client/parent
var/matrix/target
/obj/screen/credit/Initialize(mapload, credited, client/P, icon/I)
. = ..()
icon = I
parent = P
icon_state = credited
maptext = credited
maptext_x = world.icon_size + 8
maptext_y = (world.icon_size / 2) - 4
maptext_width = world.icon_size * 3
var/matrix/M = matrix(transform)
M.Translate(0, CREDIT_ANIMATE_HEIGHT)
animate(src, transform = M, time = CREDIT_ROLL_SPEED)
target = M
animate(src, alpha = 255, time = CREDIT_EASE_DURATION, flags = ANIMATION_PARALLEL)
addtimer(CALLBACK(src, .proc/FadeOut), CREDIT_ROLL_SPEED - CREDIT_EASE_DURATION)
QDEL_IN(src, CREDIT_ROLL_SPEED)
P.screen += src
/obj/screen/credit/Destroy()
var/client/P = parent
P.screen -= src
icon = null
LAZYREMOVE(P.credits, src)
parent = null
return ..()
/obj/screen/credit/proc/FadeOut()
animate(src, alpha = 0, transform = target, time = CREDIT_EASE_DURATION)
+181 -181
View File
@@ -1,181 +1,181 @@
/mob
var/list/screens = list()
/mob/proc/overlay_fullscreen(category, type, severity)
var/obj/screen/fullscreen/screen = screens[category]
if (!screen || screen.type != type)
// needs to be recreated
clear_fullscreen(category, FALSE)
screens[category] = screen = new type()
else if ((!severity || severity == screen.severity) && (!client || screen.screen_loc != "CENTER-7,CENTER-7" || screen.view == client.view))
// doesn't need to be updated
return screen
screen.icon_state = "[initial(screen.icon_state)][severity]"
screen.severity = severity
if (client && screen.should_show_to(src))
screen.update_for_view(client.view)
client.screen += screen
return screen
/mob/proc/clear_fullscreen(category, animated = 10)
var/obj/screen/fullscreen/screen = screens[category]
if(!screen)
return
screens -= category
if(animated)
animate(screen, alpha = 0, time = animated)
addtimer(CALLBACK(src, .proc/clear_fullscreen_after_animate, screen), animated, TIMER_CLIENT_TIME)
else
if(client)
client.screen -= screen
qdel(screen)
/mob/proc/clear_fullscreen_after_animate(obj/screen/fullscreen/screen)
if(client)
client.screen -= screen
qdel(screen)
/mob/proc/clear_fullscreens()
for(var/category in screens)
clear_fullscreen(category)
/mob/proc/hide_fullscreens()
if(client)
for(var/category in screens)
client.screen -= screens[category]
/mob/proc/reload_fullscreen()
if(client)
var/obj/screen/fullscreen/screen
for(var/category in screens)
screen = screens[category]
if(screen.should_show_to(src))
screen.update_for_view(client.view)
client.screen |= screen
else
client.screen -= screen
/obj/screen/fullscreen
icon = 'icons/mob/screen_full.dmi'
icon_state = "default"
screen_loc = "CENTER-7,CENTER-7"
layer = FULLSCREEN_LAYER
plane = FULLSCREEN_PLANE
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
var/view = 7
var/severity = 0
var/show_when_dead = FALSE
/obj/screen/fullscreen/proc/update_for_view(client_view)
if (screen_loc == "CENTER-7,CENTER-7" && view != client_view)
var/list/actualview = getviewsize(client_view)
view = client_view
transform = matrix(actualview[1]/FULLSCREEN_OVERLAY_RESOLUTION_X, 0, 0, 0, actualview[2]/FULLSCREEN_OVERLAY_RESOLUTION_Y, 0)
/obj/screen/fullscreen/proc/should_show_to(mob/mymob)
if(!show_when_dead && mymob.stat == DEAD)
return FALSE
return TRUE
/obj/screen/fullscreen/Destroy()
severity = 0
. = ..()
/obj/screen/fullscreen/brute
icon_state = "brutedamageoverlay"
layer = UI_DAMAGE_LAYER
plane = FULLSCREEN_PLANE
/obj/screen/fullscreen/oxy
icon_state = "oxydamageoverlay"
layer = UI_DAMAGE_LAYER
plane = FULLSCREEN_PLANE
/obj/screen/fullscreen/crit
icon_state = "passage"
layer = CRIT_LAYER
plane = FULLSCREEN_PLANE
/obj/screen/fullscreen/crit/vision
icon_state = "oxydamageoverlay"
layer = BLIND_LAYER
/obj/screen/fullscreen/blind
icon_state = "blackimageoverlay"
layer = BLIND_LAYER
plane = FULLSCREEN_PLANE
/obj/screen/fullscreen/curse
icon_state = "curse"
layer = CURSE_LAYER
plane = FULLSCREEN_PLANE
/obj/screen/fullscreen/impaired
icon_state = "impairedoverlay"
/obj/screen/fullscreen/blurry
icon = 'icons/mob/screen_gen.dmi'
screen_loc = "WEST,SOUTH to EAST,NORTH"
icon_state = "blurry"
/obj/screen/fullscreen/flash
icon = 'icons/mob/screen_gen.dmi'
screen_loc = "WEST,SOUTH to EAST,NORTH"
icon_state = "flash"
/obj/screen/fullscreen/flash/static
icon = 'icons/mob/screen_gen.dmi'
screen_loc = "WEST,SOUTH to EAST,NORTH"
icon_state = "noise"
/obj/screen/fullscreen/high
icon = 'icons/mob/screen_gen.dmi'
screen_loc = "WEST,SOUTH to EAST,NORTH"
icon_state = "druggy"
/obj/screen/fullscreen/color_vision
icon = 'icons/mob/screen_gen.dmi'
screen_loc = "WEST,SOUTH to EAST,NORTH"
icon_state = "flash"
alpha = 80
/obj/screen/fullscreen/color_vision/green
color = "#00ff00"
/obj/screen/fullscreen/color_vision/red
color = "#ff0000"
/obj/screen/fullscreen/color_vision/blue
color = "#0000ff"
/obj/screen/fullscreen/lighting_backdrop
icon = 'icons/mob/screen_gen.dmi'
icon_state = "flash"
transform = matrix(200, 0, 0, 0, 200, 0)
plane = LIGHTING_PLANE
blend_mode = BLEND_OVERLAY
show_when_dead = TRUE
//Provides darkness to the back of the lighting plane
/obj/screen/fullscreen/lighting_backdrop/lit
invisibility = INVISIBILITY_LIGHTING
layer = BACKGROUND_LAYER+21
color = "#000"
show_when_dead = TRUE
//Provides whiteness in case you don't see lights so everything is still visible
/obj/screen/fullscreen/lighting_backdrop/unlit
layer = BACKGROUND_LAYER+20
show_when_dead = TRUE
/obj/screen/fullscreen/see_through_darkness
icon_state = "nightvision"
plane = LIGHTING_PLANE
layer = LIGHTING_LAYER
blend_mode = BLEND_ADD
show_when_dead = TRUE
/mob
var/list/screens = list()
/mob/proc/overlay_fullscreen(category, type, severity)
var/obj/screen/fullscreen/screen = screens[category]
if (!screen || screen.type != type)
// needs to be recreated
clear_fullscreen(category, FALSE)
screens[category] = screen = new type()
else if ((!severity || severity == screen.severity) && (!client || screen.screen_loc != "CENTER-7,CENTER-7" || screen.view == client.view))
// doesn't need to be updated
return screen
screen.icon_state = "[initial(screen.icon_state)][severity]"
screen.severity = severity
if (client && screen.should_show_to(src))
screen.update_for_view(client.view)
client.screen += screen
return screen
/mob/proc/clear_fullscreen(category, animated = 10)
var/obj/screen/fullscreen/screen = screens[category]
if(!screen)
return
screens -= category
if(animated)
animate(screen, alpha = 0, time = animated)
addtimer(CALLBACK(src, .proc/clear_fullscreen_after_animate, screen), animated, TIMER_CLIENT_TIME)
else
if(client)
client.screen -= screen
qdel(screen)
/mob/proc/clear_fullscreen_after_animate(obj/screen/fullscreen/screen)
if(client)
client.screen -= screen
qdel(screen)
/mob/proc/clear_fullscreens()
for(var/category in screens)
clear_fullscreen(category)
/mob/proc/hide_fullscreens()
if(client)
for(var/category in screens)
client.screen -= screens[category]
/mob/proc/reload_fullscreen()
if(client)
var/obj/screen/fullscreen/screen
for(var/category in screens)
screen = screens[category]
if(screen.should_show_to(src))
screen.update_for_view(client.view)
client.screen |= screen
else
client.screen -= screen
/obj/screen/fullscreen
icon = 'icons/mob/screen_full.dmi'
icon_state = "default"
screen_loc = "CENTER-7,CENTER-7"
layer = FULLSCREEN_LAYER
plane = FULLSCREEN_PLANE
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
var/view = 7
var/severity = 0
var/show_when_dead = FALSE
/obj/screen/fullscreen/proc/update_for_view(client_view)
if (screen_loc == "CENTER-7,CENTER-7" && view != client_view)
var/list/actualview = getviewsize(client_view)
view = client_view
transform = matrix(actualview[1]/FULLSCREEN_OVERLAY_RESOLUTION_X, 0, 0, 0, actualview[2]/FULLSCREEN_OVERLAY_RESOLUTION_Y, 0)
/obj/screen/fullscreen/proc/should_show_to(mob/mymob)
if(!show_when_dead && mymob.stat == DEAD)
return FALSE
return TRUE
/obj/screen/fullscreen/Destroy()
severity = 0
. = ..()
/obj/screen/fullscreen/brute
icon_state = "brutedamageoverlay"
layer = UI_DAMAGE_LAYER
plane = FULLSCREEN_PLANE
/obj/screen/fullscreen/oxy
icon_state = "oxydamageoverlay"
layer = UI_DAMAGE_LAYER
plane = FULLSCREEN_PLANE
/obj/screen/fullscreen/crit
icon_state = "passage"
layer = CRIT_LAYER
plane = FULLSCREEN_PLANE
/obj/screen/fullscreen/crit/vision
icon_state = "oxydamageoverlay"
layer = BLIND_LAYER
/obj/screen/fullscreen/blind
icon_state = "blackimageoverlay"
layer = BLIND_LAYER
plane = FULLSCREEN_PLANE
/obj/screen/fullscreen/curse
icon_state = "curse"
layer = CURSE_LAYER
plane = FULLSCREEN_PLANE
/obj/screen/fullscreen/impaired
icon_state = "impairedoverlay"
/obj/screen/fullscreen/blurry
icon = 'icons/mob/screen_gen.dmi'
screen_loc = "WEST,SOUTH to EAST,NORTH"
icon_state = "blurry"
/obj/screen/fullscreen/flash
icon = 'icons/mob/screen_gen.dmi'
screen_loc = "WEST,SOUTH to EAST,NORTH"
icon_state = "flash"
/obj/screen/fullscreen/flash/static
icon = 'icons/mob/screen_gen.dmi'
screen_loc = "WEST,SOUTH to EAST,NORTH"
icon_state = "noise"
/obj/screen/fullscreen/high
icon = 'icons/mob/screen_gen.dmi'
screen_loc = "WEST,SOUTH to EAST,NORTH"
icon_state = "druggy"
/obj/screen/fullscreen/color_vision
icon = 'icons/mob/screen_gen.dmi'
screen_loc = "WEST,SOUTH to EAST,NORTH"
icon_state = "flash"
alpha = 80
/obj/screen/fullscreen/color_vision/green
color = "#00ff00"
/obj/screen/fullscreen/color_vision/red
color = "#ff0000"
/obj/screen/fullscreen/color_vision/blue
color = "#0000ff"
/obj/screen/fullscreen/lighting_backdrop
icon = 'icons/mob/screen_gen.dmi'
icon_state = "flash"
transform = matrix(200, 0, 0, 0, 200, 0)
plane = LIGHTING_PLANE
blend_mode = BLEND_OVERLAY
show_when_dead = TRUE
//Provides darkness to the back of the lighting plane
/obj/screen/fullscreen/lighting_backdrop/lit
invisibility = INVISIBILITY_LIGHTING
layer = BACKGROUND_LAYER+21
color = "#000"
show_when_dead = TRUE
//Provides whiteness in case you don't see lights so everything is still visible
/obj/screen/fullscreen/lighting_backdrop/unlit
layer = BACKGROUND_LAYER+20
show_when_dead = TRUE
/obj/screen/fullscreen/see_through_darkness
icon_state = "nightvision"
plane = LIGHTING_PLANE
layer = LIGHTING_LAYER
blend_mode = BLEND_ADD
show_when_dead = TRUE
+95 -95
View File
@@ -1,95 +1,95 @@
/obj/screen/ghost
icon = 'icons/mob/screen_ghost.dmi'
/obj/screen/ghost/MouseEntered()
flick(icon_state + "_anim", src)
/obj/screen/ghost/jumptomob
name = "Jump to mob"
icon_state = "jumptomob"
/obj/screen/ghost/jumptomob/Click()
var/mob/dead/observer/G = usr
G.jumptomob()
/obj/screen/ghost/orbit
name = "Orbit"
icon_state = "orbit"
/obj/screen/ghost/orbit/Click()
var/mob/dead/observer/G = usr
G.follow()
/obj/screen/ghost/reenter_corpse
name = "Reenter corpse"
icon_state = "reenter_corpse"
/obj/screen/ghost/reenter_corpse/Click()
var/mob/dead/observer/G = usr
G.reenter_corpse()
/obj/screen/ghost/teleport
name = "Teleport"
icon_state = "teleport"
/obj/screen/ghost/teleport/Click()
var/mob/dead/observer/G = usr
G.dead_tele()
/obj/screen/ghost/pai
name = "pAI Candidate"
icon_state = "pai"
/obj/screen/ghost/pai/Click()
var/mob/dead/observer/G = usr
G.register_pai()
/datum/hud/ghost/New(mob/owner)
..()
var/obj/screen/using
using = new /obj/screen/ghost/jumptomob()
using.screen_loc = ui_ghost_jumptomob
using.hud = src
static_inventory += using
using = new /obj/screen/ghost/orbit()
using.screen_loc = ui_ghost_orbit
using.hud = src
static_inventory += using
using = new /obj/screen/ghost/reenter_corpse()
using.screen_loc = ui_ghost_reenter_corpse
using.hud = src
static_inventory += using
using = new /obj/screen/ghost/teleport()
using.screen_loc = ui_ghost_teleport
using.hud = src
static_inventory += using
using = new /obj/screen/ghost/pai()
using.screen_loc = ui_ghost_pai
using.hud = src
static_inventory += using
using = new /obj/screen/language_menu
using.icon = ui_style
using.hud = src
static_inventory += using
/datum/hud/ghost/show_hud(version = 0, mob/viewmob)
// don't show this HUD if observing; show the HUD of the observee
var/mob/dead/observer/O = mymob
if (istype(O) && O.observetarget)
plane_masters_update()
return FALSE
. = ..()
if(!.)
return
var/mob/screenmob = viewmob || mymob
if(!screenmob.client.prefs.ghost_hud)
screenmob.client.screen -= static_inventory
else
screenmob.client.screen += static_inventory
/obj/screen/ghost
icon = 'icons/mob/screen_ghost.dmi'
/obj/screen/ghost/MouseEntered()
flick(icon_state + "_anim", src)
/obj/screen/ghost/jumptomob
name = "Jump to mob"
icon_state = "jumptomob"
/obj/screen/ghost/jumptomob/Click()
var/mob/dead/observer/G = usr
G.jumptomob()
/obj/screen/ghost/orbit
name = "Orbit"
icon_state = "orbit"
/obj/screen/ghost/orbit/Click()
var/mob/dead/observer/G = usr
G.follow()
/obj/screen/ghost/reenter_corpse
name = "Reenter corpse"
icon_state = "reenter_corpse"
/obj/screen/ghost/reenter_corpse/Click()
var/mob/dead/observer/G = usr
G.reenter_corpse()
/obj/screen/ghost/teleport
name = "Teleport"
icon_state = "teleport"
/obj/screen/ghost/teleport/Click()
var/mob/dead/observer/G = usr
G.dead_tele()
/obj/screen/ghost/pai
name = "pAI Candidate"
icon_state = "pai"
/obj/screen/ghost/pai/Click()
var/mob/dead/observer/G = usr
G.register_pai()
/datum/hud/ghost/New(mob/owner)
..()
var/obj/screen/using
using = new /obj/screen/ghost/jumptomob()
using.screen_loc = ui_ghost_jumptomob
using.hud = src
static_inventory += using
using = new /obj/screen/ghost/orbit()
using.screen_loc = ui_ghost_orbit
using.hud = src
static_inventory += using
using = new /obj/screen/ghost/reenter_corpse()
using.screen_loc = ui_ghost_reenter_corpse
using.hud = src
static_inventory += using
using = new /obj/screen/ghost/teleport()
using.screen_loc = ui_ghost_teleport
using.hud = src
static_inventory += using
using = new /obj/screen/ghost/pai()
using.screen_loc = ui_ghost_pai
using.hud = src
static_inventory += using
using = new /obj/screen/language_menu
using.icon = ui_style
using.hud = src
static_inventory += using
/datum/hud/ghost/show_hud(version = 0, mob/viewmob)
// don't show this HUD if observing; show the HUD of the observee
var/mob/dead/observer/O = mymob
if (istype(O) && O.observetarget)
plane_masters_update()
return FALSE
. = ..()
if(!.)
return
var/mob/screenmob = viewmob || mymob
if(!screenmob.client.prefs.ghost_hud)
screenmob.client.screen -= static_inventory
else
screenmob.client.screen += static_inventory
+294 -294
View File
@@ -1,294 +1,294 @@
/*
The hud datum
Used to show and hide huds for all the different mob types,
including inventories and item quick actions.
*/
// The default UI style is the first one in the list
GLOBAL_LIST_INIT(available_ui_styles, list(
"Midnight" = 'icons/mob/screen_midnight.dmi',
"Retro" = 'icons/mob/screen_retro.dmi',
"Plasmafire" = 'icons/mob/screen_plasmafire.dmi',
"Slimecore" = 'icons/mob/screen_slimecore.dmi',
"Operative" = 'icons/mob/screen_operative.dmi',
"Clockwork" = 'icons/mob/screen_clockwork.dmi'
))
/proc/ui_style2icon(ui_style)
return GLOB.available_ui_styles[ui_style] || GLOB.available_ui_styles[GLOB.available_ui_styles[1]]
/datum/hud
var/mob/mymob
var/hud_shown = TRUE //Used for the HUD toggle (F12)
var/hud_version = HUD_STYLE_STANDARD //Current displayed version of the HUD
var/inventory_shown = FALSE //Equipped item inventory
var/hotkey_ui_hidden = FALSE //This is to hide the buttons that can be used via hotkeys. (hotkeybuttons list of buttons)
var/obj/screen/ling/chems/lingchemdisplay
var/obj/screen/ling/sting/lingstingdisplay
var/obj/screen/blobpwrdisplay
var/obj/screen/alien_plasma_display
var/obj/screen/alien_queen_finder
var/obj/screen/devil/soul_counter/devilsouldisplay
var/obj/screen/action_intent
var/obj/screen/zone_select
var/obj/screen/pull_icon
var/obj/screen/rest_icon
var/obj/screen/throw_icon
var/obj/screen/module_store_icon
var/list/static_inventory = list() //the screen objects which are static
var/list/toggleable_inventory = list() //the screen objects which can be hidden
var/list/obj/screen/hotkeybuttons = list() //the buttons that can be used via hotkeys
var/list/infodisplay = list() //the screen objects that display mob info (health, alien plasma, etc...)
var/list/screenoverlays = list() //the screen objects used as whole screen overlays (flash, damageoverlay, etc...)
var/list/inv_slots[SLOTS_AMT] // /obj/screen/inventory objects, ordered by their slot ID.
var/list/hand_slots // /obj/screen/inventory/hand objects, assoc list of "[held_index]" = object
var/list/obj/screen/plane_master/plane_masters = list() // see "appearance_flags" in the ref, assoc list of "[plane]" = object
var/obj/screen/movable/action_button/hide_toggle/hide_actions_toggle
var/action_buttons_hidden = FALSE
var/obj/screen/healths
var/obj/screen/healthdoll
var/obj/screen/internals
// subtypes can override this to force a specific UI style
var/ui_style
/datum/hud/New(mob/owner)
mymob = owner
if (!ui_style)
// will fall back to the default if any of these are null
ui_style = ui_style2icon(owner.client && owner.client.prefs && owner.client.prefs.UI_style)
hide_actions_toggle = new
hide_actions_toggle.InitialiseIcon(src)
if(mymob.client)
hide_actions_toggle.locked = mymob.client.prefs.buttons_locked
hand_slots = list()
for(var/mytype in subtypesof(/obj/screen/plane_master))
var/obj/screen/plane_master/instance = new mytype()
plane_masters["[instance.plane]"] = instance
instance.backdrop(mymob)
/datum/hud/Destroy()
if(mymob.hud_used == src)
mymob.hud_used = null
QDEL_NULL(hide_actions_toggle)
QDEL_NULL(module_store_icon)
QDEL_LIST(static_inventory)
inv_slots.Cut()
action_intent = null
zone_select = null
pull_icon = null
QDEL_LIST(toggleable_inventory)
QDEL_LIST(hotkeybuttons)
throw_icon = null
QDEL_LIST(infodisplay)
healths = null
healthdoll = null
internals = null
lingchemdisplay = null
devilsouldisplay = null
lingstingdisplay = null
blobpwrdisplay = null
alien_plasma_display = null
alien_queen_finder = null
QDEL_LIST_ASSOC_VAL(plane_masters)
QDEL_LIST(screenoverlays)
mymob = null
return ..()
/mob
var/hud_type = /datum/hud
/mob/proc/create_mob_hud()
if(!client || hud_used)
return
hud_used = new hud_type(src)
update_sight()
SEND_SIGNAL(src, COMSIG_MOB_HUD_CREATED)
//Version denotes which style should be displayed. blank or 0 means "next version"
/datum/hud/proc/show_hud(version = 0, mob/viewmob)
if(!ismob(mymob))
return FALSE
var/mob/screenmob = viewmob || mymob
if(!screenmob.client)
return FALSE
screenmob.client.screen = list()
screenmob.client.apply_clickcatcher()
var/display_hud_version = version
if(!display_hud_version) //If 0 or blank, display the next hud version
display_hud_version = hud_version + 1
if(display_hud_version > HUD_VERSIONS) //If the requested version number is greater than the available versions, reset back to the first version
display_hud_version = 1
switch(display_hud_version)
if(HUD_STYLE_STANDARD) //Default HUD
hud_shown = TRUE //Governs behavior of other procs
if(static_inventory.len)
screenmob.client.screen += static_inventory
if(toggleable_inventory.len && screenmob.hud_used && screenmob.hud_used.inventory_shown)
screenmob.client.screen += toggleable_inventory
if(hotkeybuttons.len && !hotkey_ui_hidden)
screenmob.client.screen += hotkeybuttons
if(infodisplay.len)
screenmob.client.screen += infodisplay
screenmob.client.screen += hide_actions_toggle
if(action_intent)
action_intent.screen_loc = initial(action_intent.screen_loc) //Restore intent selection to the original position
if(HUD_STYLE_REDUCED) //Reduced HUD
hud_shown = FALSE //Governs behavior of other procs
if(static_inventory.len)
screenmob.client.screen -= static_inventory
if(toggleable_inventory.len)
screenmob.client.screen -= toggleable_inventory
if(hotkeybuttons.len)
screenmob.client.screen -= hotkeybuttons
if(infodisplay.len)
screenmob.client.screen += infodisplay
//These ones are a part of 'static_inventory', 'toggleable_inventory' or 'hotkeybuttons' but we want them to stay
for(var/h in hand_slots)
var/obj/screen/hand = hand_slots[h]
if(hand)
screenmob.client.screen += hand
if(action_intent)
screenmob.client.screen += action_intent //we want the intent switcher visible
action_intent.screen_loc = ui_acti_alt //move this to the alternative position, where zone_select usually is.
if(HUD_STYLE_NOHUD) //No HUD
hud_shown = FALSE //Governs behavior of other procs
if(static_inventory.len)
screenmob.client.screen -= static_inventory
if(toggleable_inventory.len)
screenmob.client.screen -= toggleable_inventory
if(hotkeybuttons.len)
screenmob.client.screen -= hotkeybuttons
if(infodisplay.len)
screenmob.client.screen -= infodisplay
hud_version = display_hud_version
persistent_inventory_update(screenmob)
screenmob.update_action_buttons(1)
reorganize_alerts()
screenmob.reload_fullscreen()
update_parallax_pref(screenmob)
// ensure observers get an accurate and up-to-date view
if (!viewmob)
plane_masters_update()
for(var/M in mymob.observers)
show_hud(hud_version, M)
else if (viewmob.hud_used)
viewmob.hud_used.plane_masters_update()
return TRUE
/datum/hud/proc/plane_masters_update()
// Plane masters are always shown to OUR mob, never to observers
for(var/thing in plane_masters)
var/obj/screen/plane_master/PM = plane_masters[thing]
PM.backdrop(mymob)
mymob.client.screen += PM
/datum/hud/human/show_hud(version = 0,mob/viewmob)
. = ..()
if(!.)
return
var/mob/screenmob = viewmob || mymob
hidden_inventory_update(screenmob)
/datum/hud/robot/show_hud(version = 0, mob/viewmob)
. = ..()
if(!.)
return
update_robot_modules_display()
/datum/hud/proc/hidden_inventory_update()
return
/datum/hud/proc/persistent_inventory_update(mob/viewer)
if(!mymob)
return
/datum/hud/proc/update_ui_style(new_ui_style)
// do nothing if overridden by a subtype or already on that style
if (initial(ui_style) || ui_style == new_ui_style)
return
for(var/atom/item in static_inventory + toggleable_inventory + hotkeybuttons + infodisplay + screenoverlays + inv_slots)
if (item.icon == ui_style)
item.icon = new_ui_style
ui_style = new_ui_style
build_hand_slots()
hide_actions_toggle.InitialiseIcon(src)
//Triggered when F12 is pressed (Unless someone changed something in the DMF)
/mob/verb/button_pressed_F12()
set name = "F12"
set hidden = TRUE
if(hud_used && client)
hud_used.show_hud() //Shows the next hud preset
to_chat(usr, "<span class ='info'>Switched HUD mode. Press F12 to toggle.</span>")
else
to_chat(usr, "<span class ='warning'>This mob type does not use a HUD.</span>")
//(re)builds the hand ui slots, throwing away old ones
//not really worth jugglying existing ones so we just scrap+rebuild
//9/10 this is only called once per mob and only for 2 hands
/datum/hud/proc/build_hand_slots()
for(var/h in hand_slots)
var/obj/screen/inventory/hand/H = hand_slots[h]
if(H)
static_inventory -= H
hand_slots = list()
var/obj/screen/inventory/hand/hand_box
for(var/i in 1 to mymob.held_items.len)
hand_box = new /obj/screen/inventory/hand()
hand_box.name = mymob.get_held_index_name(i)
hand_box.icon = ui_style
hand_box.icon_state = "hand_[mymob.held_index_to_dir(i)]"
hand_box.screen_loc = ui_hand_position(i)
hand_box.held_index = i
hand_slots["[i]"] = hand_box
hand_box.hud = src
static_inventory += hand_box
hand_box.update_icon()
var/i = 1
for(var/obj/screen/swap_hand/SH in static_inventory)
SH.screen_loc = ui_swaphand_position(mymob,!(i % 2) ? 2: 1)
i++
for(var/obj/screen/human/equip/E in static_inventory)
E.screen_loc = ui_equip_position(mymob)
if(ismob(mymob) && mymob.hud_used == src)
show_hud(hud_version)
/datum/hud/proc/update_locked_slots()
return
/*
The hud datum
Used to show and hide huds for all the different mob types,
including inventories and item quick actions.
*/
// The default UI style is the first one in the list
GLOBAL_LIST_INIT(available_ui_styles, list(
"Midnight" = 'icons/mob/screen_midnight.dmi',
"Retro" = 'icons/mob/screen_retro.dmi',
"Plasmafire" = 'icons/mob/screen_plasmafire.dmi',
"Slimecore" = 'icons/mob/screen_slimecore.dmi',
"Operative" = 'icons/mob/screen_operative.dmi',
"Clockwork" = 'icons/mob/screen_clockwork.dmi'
))
/proc/ui_style2icon(ui_style)
return GLOB.available_ui_styles[ui_style] || GLOB.available_ui_styles[GLOB.available_ui_styles[1]]
/datum/hud
var/mob/mymob
var/hud_shown = TRUE //Used for the HUD toggle (F12)
var/hud_version = HUD_STYLE_STANDARD //Current displayed version of the HUD
var/inventory_shown = FALSE //Equipped item inventory
var/hotkey_ui_hidden = FALSE //This is to hide the buttons that can be used via hotkeys. (hotkeybuttons list of buttons)
var/obj/screen/ling/chems/lingchemdisplay
var/obj/screen/ling/sting/lingstingdisplay
var/obj/screen/blobpwrdisplay
var/obj/screen/alien_plasma_display
var/obj/screen/alien_queen_finder
var/obj/screen/devil/soul_counter/devilsouldisplay
var/obj/screen/action_intent
var/obj/screen/zone_select
var/obj/screen/pull_icon
var/obj/screen/rest_icon
var/obj/screen/throw_icon
var/obj/screen/module_store_icon
var/list/static_inventory = list() //the screen objects which are static
var/list/toggleable_inventory = list() //the screen objects which can be hidden
var/list/obj/screen/hotkeybuttons = list() //the buttons that can be used via hotkeys
var/list/infodisplay = list() //the screen objects that display mob info (health, alien plasma, etc...)
var/list/screenoverlays = list() //the screen objects used as whole screen overlays (flash, damageoverlay, etc...)
var/list/inv_slots[SLOTS_AMT] // /obj/screen/inventory objects, ordered by their slot ID.
var/list/hand_slots // /obj/screen/inventory/hand objects, assoc list of "[held_index]" = object
var/list/obj/screen/plane_master/plane_masters = list() // see "appearance_flags" in the ref, assoc list of "[plane]" = object
var/obj/screen/movable/action_button/hide_toggle/hide_actions_toggle
var/action_buttons_hidden = FALSE
var/obj/screen/healths
var/obj/screen/healthdoll
var/obj/screen/internals
// subtypes can override this to force a specific UI style
var/ui_style
/datum/hud/New(mob/owner)
mymob = owner
if (!ui_style)
// will fall back to the default if any of these are null
ui_style = ui_style2icon(owner.client && owner.client.prefs && owner.client.prefs.UI_style)
hide_actions_toggle = new
hide_actions_toggle.InitialiseIcon(src)
if(mymob.client)
hide_actions_toggle.locked = mymob.client.prefs.buttons_locked
hand_slots = list()
for(var/mytype in subtypesof(/obj/screen/plane_master))
var/obj/screen/plane_master/instance = new mytype()
plane_masters["[instance.plane]"] = instance
instance.backdrop(mymob)
/datum/hud/Destroy()
if(mymob.hud_used == src)
mymob.hud_used = null
QDEL_NULL(hide_actions_toggle)
QDEL_NULL(module_store_icon)
QDEL_LIST(static_inventory)
inv_slots.Cut()
action_intent = null
zone_select = null
pull_icon = null
QDEL_LIST(toggleable_inventory)
QDEL_LIST(hotkeybuttons)
throw_icon = null
QDEL_LIST(infodisplay)
healths = null
healthdoll = null
internals = null
lingchemdisplay = null
devilsouldisplay = null
lingstingdisplay = null
blobpwrdisplay = null
alien_plasma_display = null
alien_queen_finder = null
QDEL_LIST_ASSOC_VAL(plane_masters)
QDEL_LIST(screenoverlays)
mymob = null
return ..()
/mob
var/hud_type = /datum/hud
/mob/proc/create_mob_hud()
if(!client || hud_used)
return
hud_used = new hud_type(src)
update_sight()
SEND_SIGNAL(src, COMSIG_MOB_HUD_CREATED)
//Version denotes which style should be displayed. blank or 0 means "next version"
/datum/hud/proc/show_hud(version = 0, mob/viewmob)
if(!ismob(mymob))
return FALSE
var/mob/screenmob = viewmob || mymob
if(!screenmob.client)
return FALSE
screenmob.client.screen = list()
screenmob.client.apply_clickcatcher()
var/display_hud_version = version
if(!display_hud_version) //If 0 or blank, display the next hud version
display_hud_version = hud_version + 1
if(display_hud_version > HUD_VERSIONS) //If the requested version number is greater than the available versions, reset back to the first version
display_hud_version = 1
switch(display_hud_version)
if(HUD_STYLE_STANDARD) //Default HUD
hud_shown = TRUE //Governs behavior of other procs
if(static_inventory.len)
screenmob.client.screen += static_inventory
if(toggleable_inventory.len && screenmob.hud_used && screenmob.hud_used.inventory_shown)
screenmob.client.screen += toggleable_inventory
if(hotkeybuttons.len && !hotkey_ui_hidden)
screenmob.client.screen += hotkeybuttons
if(infodisplay.len)
screenmob.client.screen += infodisplay
screenmob.client.screen += hide_actions_toggle
if(action_intent)
action_intent.screen_loc = initial(action_intent.screen_loc) //Restore intent selection to the original position
if(HUD_STYLE_REDUCED) //Reduced HUD
hud_shown = FALSE //Governs behavior of other procs
if(static_inventory.len)
screenmob.client.screen -= static_inventory
if(toggleable_inventory.len)
screenmob.client.screen -= toggleable_inventory
if(hotkeybuttons.len)
screenmob.client.screen -= hotkeybuttons
if(infodisplay.len)
screenmob.client.screen += infodisplay
//These ones are a part of 'static_inventory', 'toggleable_inventory' or 'hotkeybuttons' but we want them to stay
for(var/h in hand_slots)
var/obj/screen/hand = hand_slots[h]
if(hand)
screenmob.client.screen += hand
if(action_intent)
screenmob.client.screen += action_intent //we want the intent switcher visible
action_intent.screen_loc = ui_acti_alt //move this to the alternative position, where zone_select usually is.
if(HUD_STYLE_NOHUD) //No HUD
hud_shown = FALSE //Governs behavior of other procs
if(static_inventory.len)
screenmob.client.screen -= static_inventory
if(toggleable_inventory.len)
screenmob.client.screen -= toggleable_inventory
if(hotkeybuttons.len)
screenmob.client.screen -= hotkeybuttons
if(infodisplay.len)
screenmob.client.screen -= infodisplay
hud_version = display_hud_version
persistent_inventory_update(screenmob)
screenmob.update_action_buttons(1)
reorganize_alerts()
screenmob.reload_fullscreen()
update_parallax_pref(screenmob)
// ensure observers get an accurate and up-to-date view
if (!viewmob)
plane_masters_update()
for(var/M in mymob.observers)
show_hud(hud_version, M)
else if (viewmob.hud_used)
viewmob.hud_used.plane_masters_update()
return TRUE
/datum/hud/proc/plane_masters_update()
// Plane masters are always shown to OUR mob, never to observers
for(var/thing in plane_masters)
var/obj/screen/plane_master/PM = plane_masters[thing]
PM.backdrop(mymob)
mymob.client.screen += PM
/datum/hud/human/show_hud(version = 0,mob/viewmob)
. = ..()
if(!.)
return
var/mob/screenmob = viewmob || mymob
hidden_inventory_update(screenmob)
/datum/hud/robot/show_hud(version = 0, mob/viewmob)
. = ..()
if(!.)
return
update_robot_modules_display()
/datum/hud/proc/hidden_inventory_update()
return
/datum/hud/proc/persistent_inventory_update(mob/viewer)
if(!mymob)
return
/datum/hud/proc/update_ui_style(new_ui_style)
// do nothing if overridden by a subtype or already on that style
if (initial(ui_style) || ui_style == new_ui_style)
return
for(var/atom/item in static_inventory + toggleable_inventory + hotkeybuttons + infodisplay + screenoverlays + inv_slots)
if (item.icon == ui_style)
item.icon = new_ui_style
ui_style = new_ui_style
build_hand_slots()
hide_actions_toggle.InitialiseIcon(src)
//Triggered when F12 is pressed (Unless someone changed something in the DMF)
/mob/verb/button_pressed_F12()
set name = "F12"
set hidden = TRUE
if(hud_used && client)
hud_used.show_hud() //Shows the next hud preset
to_chat(usr, "<span class ='info'>Switched HUD mode. Press F12 to toggle.</span>")
else
to_chat(usr, "<span class ='warning'>This mob type does not use a HUD.</span>")
//(re)builds the hand ui slots, throwing away old ones
//not really worth jugglying existing ones so we just scrap+rebuild
//9/10 this is only called once per mob and only for 2 hands
/datum/hud/proc/build_hand_slots()
for(var/h in hand_slots)
var/obj/screen/inventory/hand/H = hand_slots[h]
if(H)
static_inventory -= H
hand_slots = list()
var/obj/screen/inventory/hand/hand_box
for(var/i in 1 to mymob.held_items.len)
hand_box = new /obj/screen/inventory/hand()
hand_box.name = mymob.get_held_index_name(i)
hand_box.icon = ui_style
hand_box.icon_state = "hand_[mymob.held_index_to_dir(i)]"
hand_box.screen_loc = ui_hand_position(i)
hand_box.held_index = i
hand_slots["[i]"] = hand_box
hand_box.hud = src
static_inventory += hand_box
hand_box.update_icon()
var/i = 1
for(var/obj/screen/swap_hand/SH in static_inventory)
SH.screen_loc = ui_swaphand_position(mymob,!(i % 2) ? 2: 1)
i++
for(var/obj/screen/human/equip/E in static_inventory)
E.screen_loc = ui_equip_position(mymob)
if(ismob(mymob) && mymob.hud_used == src)
show_hud(hud_version)
/datum/hud/proc/update_locked_slots()
return
+523 -523
View File
File diff suppressed because it is too large Load Diff
+165 -165
View File
@@ -1,165 +1,165 @@
/datum/hud/monkey/New(mob/living/carbon/monkey/owner)
..()
var/obj/screen/using
var/obj/screen/inventory/inv_box
action_intent = new /obj/screen/act_intent()
action_intent.icon = ui_style
action_intent.icon_state = mymob.a_intent
action_intent.screen_loc = ui_acti
action_intent.hud = src
static_inventory += action_intent
using = new /obj/screen/mov_intent()
using.icon = ui_style
using.icon_state = (mymob.m_intent == MOVE_INTENT_RUN ? "running" : "walking")
using.screen_loc = ui_movi
using.hud = src
static_inventory += using
using = new/obj/screen/language_menu
using.icon = ui_style
using.hud = src
static_inventory += using
using = new /obj/screen/drop()
using.icon = ui_style
using.screen_loc = ui_drop_throw
using.hud = src
static_inventory += using
build_hand_slots()
using = new /obj/screen/swap_hand()
using.icon = ui_style
using.icon_state = "swap_1_m" //extra wide!
using.screen_loc = ui_swaphand_position(owner,1)
using.hud = src
static_inventory += using
using = new /obj/screen/swap_hand()
using.icon = ui_style
using.icon_state = "swap_2"
using.screen_loc = ui_swaphand_position(owner,2)
using.hud = src
static_inventory += using
inv_box = new /obj/screen/inventory()
inv_box.name = "mask"
inv_box.icon = ui_style
inv_box.icon_state = "mask"
// inv_box.icon_full = "template"
inv_box.screen_loc = ui_monkey_mask
inv_box.slot_id = SLOT_WEAR_MASK
static_inventory += inv_box
inv_box = new /obj/screen/inventory()
inv_box.name = "neck"
inv_box.icon = ui_style
inv_box.icon_state = "neck"
// inv_box.icon_full = "template"
inv_box.screen_loc = ui_monkey_neck
inv_box.slot_id = SLOT_NECK
static_inventory += inv_box
inv_box = new /obj/screen/inventory()
inv_box.name = "head"
inv_box.icon = ui_style
inv_box.icon_state = "head"
// inv_box.icon_full = "template"
inv_box.screen_loc = ui_monkey_head
inv_box.slot_id = SLOT_HEAD
static_inventory += inv_box
inv_box = new /obj/screen/inventory()
inv_box.name = "back"
inv_box.icon = ui_style
inv_box.icon_state = "back"
inv_box.screen_loc = ui_monkey_back
inv_box.slot_id = SLOT_BACK
static_inventory += inv_box
throw_icon = new /obj/screen/throw_catch()
throw_icon.icon = ui_style
throw_icon.screen_loc = ui_drop_throw
throw_icon.hud = src
hotkeybuttons += throw_icon
internals = new /obj/screen/internals()
internals.hud = src
infodisplay += internals
healths = new /obj/screen/healths()
healths.hud = src
infodisplay += healths
pull_icon = new /obj/screen/pull()
pull_icon.icon = ui_style
pull_icon.screen_loc = ui_pull_resist
pull_icon.hud = src
pull_icon.update_icon()
static_inventory += pull_icon
lingchemdisplay = new /obj/screen/ling/chems()
lingchemdisplay.hud = src
infodisplay += lingchemdisplay
lingstingdisplay = new /obj/screen/ling/sting()
lingstingdisplay.hud = src
infodisplay += lingstingdisplay
zone_select = new /obj/screen/zone_sel()
zone_select.icon = ui_style
zone_select.hud = src
zone_select.update_icon()
static_inventory += zone_select
mymob.client.screen = list()
using = new /obj/screen/resist()
using.icon = ui_style
using.screen_loc = ui_pull_resist
using.hud = src
hotkeybuttons += using
for(var/obj/screen/inventory/inv in (static_inventory + toggleable_inventory))
if(inv.slot_id)
inv.hud = src
inv_slots[inv.slot_id] = inv
inv.update_icon()
/datum/hud/monkey/persistent_inventory_update()
if(!mymob)
return
var/mob/living/carbon/monkey/M = mymob
if(hud_shown)
if(M.back)
M.back.screen_loc = ui_monkey_back
M.client.screen += M.back
if(M.wear_mask)
M.wear_mask.screen_loc = ui_monkey_mask
M.client.screen += M.wear_mask
if(M.wear_neck)
M.wear_neck.screen_loc = ui_monkey_neck
M.client.screen += M.wear_neck
if(M.head)
M.head.screen_loc = ui_monkey_head
M.client.screen += M.head
else
if(M.back)
M.back.screen_loc = null
if(M.wear_mask)
M.wear_mask.screen_loc = null
if(M.head)
M.head.screen_loc = null
if(hud_version != HUD_STYLE_NOHUD)
for(var/obj/item/I in M.held_items)
I.screen_loc = ui_hand_position(M.get_held_index_of_item(I))
M.client.screen += I
else
for(var/obj/item/I in M.held_items)
I.screen_loc = null
M.client.screen -= I
/datum/hud/monkey/New(mob/living/carbon/monkey/owner)
..()
var/obj/screen/using
var/obj/screen/inventory/inv_box
action_intent = new /obj/screen/act_intent()
action_intent.icon = ui_style
action_intent.icon_state = mymob.a_intent
action_intent.screen_loc = ui_acti
action_intent.hud = src
static_inventory += action_intent
using = new /obj/screen/mov_intent()
using.icon = ui_style
using.icon_state = (mymob.m_intent == MOVE_INTENT_RUN ? "running" : "walking")
using.screen_loc = ui_movi
using.hud = src
static_inventory += using
using = new/obj/screen/language_menu
using.icon = ui_style
using.hud = src
static_inventory += using
using = new /obj/screen/drop()
using.icon = ui_style
using.screen_loc = ui_drop_throw
using.hud = src
static_inventory += using
build_hand_slots()
using = new /obj/screen/swap_hand()
using.icon = ui_style
using.icon_state = "swap_1_m" //extra wide!
using.screen_loc = ui_swaphand_position(owner,1)
using.hud = src
static_inventory += using
using = new /obj/screen/swap_hand()
using.icon = ui_style
using.icon_state = "swap_2"
using.screen_loc = ui_swaphand_position(owner,2)
using.hud = src
static_inventory += using
inv_box = new /obj/screen/inventory()
inv_box.name = "mask"
inv_box.icon = ui_style
inv_box.icon_state = "mask"
// inv_box.icon_full = "template"
inv_box.screen_loc = ui_monkey_mask
inv_box.slot_id = SLOT_WEAR_MASK
static_inventory += inv_box
inv_box = new /obj/screen/inventory()
inv_box.name = "neck"
inv_box.icon = ui_style
inv_box.icon_state = "neck"
// inv_box.icon_full = "template"
inv_box.screen_loc = ui_monkey_neck
inv_box.slot_id = SLOT_NECK
static_inventory += inv_box
inv_box = new /obj/screen/inventory()
inv_box.name = "head"
inv_box.icon = ui_style
inv_box.icon_state = "head"
// inv_box.icon_full = "template"
inv_box.screen_loc = ui_monkey_head
inv_box.slot_id = SLOT_HEAD
static_inventory += inv_box
inv_box = new /obj/screen/inventory()
inv_box.name = "back"
inv_box.icon = ui_style
inv_box.icon_state = "back"
inv_box.screen_loc = ui_monkey_back
inv_box.slot_id = SLOT_BACK
static_inventory += inv_box
throw_icon = new /obj/screen/throw_catch()
throw_icon.icon = ui_style
throw_icon.screen_loc = ui_drop_throw
throw_icon.hud = src
hotkeybuttons += throw_icon
internals = new /obj/screen/internals()
internals.hud = src
infodisplay += internals
healths = new /obj/screen/healths()
healths.hud = src
infodisplay += healths
pull_icon = new /obj/screen/pull()
pull_icon.icon = ui_style
pull_icon.screen_loc = ui_pull_resist
pull_icon.hud = src
pull_icon.update_icon()
static_inventory += pull_icon
lingchemdisplay = new /obj/screen/ling/chems()
lingchemdisplay.hud = src
infodisplay += lingchemdisplay
lingstingdisplay = new /obj/screen/ling/sting()
lingstingdisplay.hud = src
infodisplay += lingstingdisplay
zone_select = new /obj/screen/zone_sel()
zone_select.icon = ui_style
zone_select.hud = src
zone_select.update_icon()
static_inventory += zone_select
mymob.client.screen = list()
using = new /obj/screen/resist()
using.icon = ui_style
using.screen_loc = ui_pull_resist
using.hud = src
hotkeybuttons += using
for(var/obj/screen/inventory/inv in (static_inventory + toggleable_inventory))
if(inv.slot_id)
inv.hud = src
inv_slots[inv.slot_id] = inv
inv.update_icon()
/datum/hud/monkey/persistent_inventory_update()
if(!mymob)
return
var/mob/living/carbon/monkey/M = mymob
if(hud_shown)
if(M.back)
M.back.screen_loc = ui_monkey_back
M.client.screen += M.back
if(M.wear_mask)
M.wear_mask.screen_loc = ui_monkey_mask
M.client.screen += M.wear_mask
if(M.wear_neck)
M.wear_neck.screen_loc = ui_monkey_neck
M.client.screen += M.wear_neck
if(M.head)
M.head.screen_loc = ui_monkey_head
M.client.screen += M.head
else
if(M.back)
M.back.screen_loc = null
if(M.wear_mask)
M.wear_mask.screen_loc = null
if(M.head)
M.head.screen_loc = null
if(hud_version != HUD_STYLE_NOHUD)
for(var/obj/item/I in M.held_items)
I.screen_loc = ui_hand_position(M.get_held_index_of_item(I))
M.client.screen += I
else
for(var/obj/item/I in M.held_items)
I.screen_loc = null
M.client.screen -= I
+307 -307
View File
@@ -1,307 +1,307 @@
/obj/screen/robot
icon = 'icons/mob/screen_cyborg.dmi'
/obj/screen/robot/module
name = "cyborg module"
icon_state = "nomod"
/obj/screen/robot/Click()
if(isobserver(usr))
return 1
/obj/screen/robot/module/Click()
if(..())
return
var/mob/living/silicon/robot/R = usr
if(R.module.type != /obj/item/robot_module)
R.hud_used.toggle_show_robot_modules()
return 1
R.pick_module()
/obj/screen/robot/module1
name = "module1"
icon_state = "inv1"
/obj/screen/robot/module1/Click()
if(..())
return
var/mob/living/silicon/robot/R = usr
R.toggle_module(1)
/obj/screen/robot/module2
name = "module2"
icon_state = "inv2"
/obj/screen/robot/module2/Click()
if(..())
return
var/mob/living/silicon/robot/R = usr
R.toggle_module(2)
/obj/screen/robot/module3
name = "module3"
icon_state = "inv3"
/obj/screen/robot/module3/Click()
if(..())
return
var/mob/living/silicon/robot/R = usr
R.toggle_module(3)
/obj/screen/robot/radio
name = "radio"
icon_state = "radio"
/obj/screen/robot/radio/Click()
if(..())
return
var/mob/living/silicon/robot/R = usr
R.radio.interact(R)
/obj/screen/robot/store
name = "store"
icon_state = "store"
/obj/screen/robot/store/Click()
if(..())
return
var/mob/living/silicon/robot/R = usr
R.uneq_active()
/obj/screen/robot/lamp
name = "headlamp"
icon_state = "lamp0"
/obj/screen/robot/lamp/Click()
if(..())
return
var/mob/living/silicon/robot/R = usr
R.control_headlamp()
/obj/screen/robot/thrusters
name = "ion thrusters"
icon_state = "ionpulse0"
/obj/screen/robot/thrusters/Click()
if(..())
return
var/mob/living/silicon/robot/R = usr
R.toggle_ionpulse()
/obj/screen/robot/sensors
name = "Sensor Augmentation"
icon_state = "cyborg_sensor"
/obj/screen/robot/sensors/Click()
if(..())
return
var/mob/living/silicon/S = usr
S.toggle_sensors()
/obj/screen/robot/language_menu
name = "silicon language selection"
icon_state = "talk_wheel"
/obj/screen/robot/language_menu/Click()
if(..())
return
var/mob/living/silicon/S = usr
S.open_language_menu(usr)
/datum/hud/robot
ui_style = 'icons/mob/screen_cyborg.dmi'
/datum/hud/robot/New(mob/owner)
..()
var/mob/living/silicon/robot/mymobR = mymob
var/obj/screen/using
using = new/obj/screen/robot/language_menu
using.screen_loc = ui_borg_language_menu
using.hud = src
static_inventory += using
//Radio
using = new /obj/screen/robot/radio()
using.screen_loc = ui_borg_radio
using.hud = src
static_inventory += using
//Module select
using = new /obj/screen/robot/module1()
using.screen_loc = ui_inv1
using.hud = src
static_inventory += using
mymobR.inv1 = using
using = new /obj/screen/robot/module2()
using.screen_loc = ui_inv2
using.hud = src
static_inventory += using
mymobR.inv2 = using
using = new /obj/screen/robot/module3()
using.screen_loc = ui_inv3
using.hud = src
static_inventory += using
mymobR.inv3 = using
//End of module select
//Photography stuff
using = new /obj/screen/ai/image_take()
using.screen_loc = ui_borg_camera
using.hud = src
static_inventory += using
using = new /obj/screen/ai/image_view()
using.screen_loc = ui_borg_album
using.hud = src
static_inventory += using
//Sec/Med HUDs
using = new /obj/screen/robot/sensors()
using.screen_loc = ui_borg_sensor
using.hud = src
static_inventory += using
//Headlamp control
using = new /obj/screen/robot/lamp()
using.screen_loc = ui_borg_lamp
using.hud = src
static_inventory += using
mymobR.lamp_button = using
//Thrusters
using = new /obj/screen/robot/thrusters()
using.screen_loc = ui_borg_thrusters
using.hud = src
static_inventory += using
mymobR.thruster_button = using
//Intent
action_intent = new /obj/screen/act_intent/robot()
action_intent.icon_state = mymob.a_intent
action_intent.hud = src
static_inventory += action_intent
//Health
healths = new /obj/screen/healths/robot()
healths.hud = src
infodisplay += healths
//Installed Module
mymobR.hands = new /obj/screen/robot/module()
mymobR.hands.screen_loc = ui_borg_module
static_inventory += mymobR.hands
//Store
module_store_icon = new /obj/screen/robot/store()
module_store_icon.hud = src
module_store_icon.screen_loc = ui_borg_store
pull_icon = new /obj/screen/pull()
pull_icon.icon = 'icons/mob/screen_cyborg.dmi'
pull_icon.hud = src
pull_icon.update_icon()
pull_icon.screen_loc = ui_borg_pull
hotkeybuttons += pull_icon
zone_select = new /obj/screen/zone_sel/robot()
zone_select.hud = src
zone_select.update_icon()
static_inventory += zone_select
/datum/hud/proc/toggle_show_robot_modules()
if(!iscyborg(mymob))
return
var/mob/living/silicon/robot/R = mymob
R.shown_robot_modules = !R.shown_robot_modules
update_robot_modules_display()
/datum/hud/proc/update_robot_modules_display(mob/viewer)
if(!iscyborg(mymob))
return
var/mob/living/silicon/robot/R = mymob
var/mob/screenmob = viewer || R
if(!R.module)
return
if(!R.client)
return
if(R.shown_robot_modules && screenmob.hud_used.hud_shown)
//Modules display is shown
screenmob.client.screen += module_store_icon //"store" icon
if(!R.module.modules)
to_chat(usr, "<span class='danger'>Selected module has no modules to select</span>")
return
if(!R.robot_modules_background)
return
var/display_rows = CEILING(length(R.module.get_inactive_modules()) / 8, 1)
R.robot_modules_background.screen_loc = "CENTER-4:16,SOUTH+1:7 to CENTER+3:16,SOUTH+[display_rows]:7"
screenmob.client.screen += R.robot_modules_background
var/x = -4 //Start at CENTER-4,SOUTH+1
var/y = 1
for(var/atom/movable/A in R.module.get_inactive_modules())
//Module is not currently active
screenmob.client.screen += A
if(x < 0)
A.screen_loc = "CENTER[x]:16,SOUTH+[y]:7"
else
A.screen_loc = "CENTER+[x]:16,SOUTH+[y]:7"
A.layer = ABOVE_HUD_LAYER
A.plane = ABOVE_HUD_PLANE
x++
if(x == 4)
x = -4
y++
else
//Modules display is hidden
screenmob.client.screen -= module_store_icon //"store" icon
for(var/atom/A in R.module.get_inactive_modules())
//Module is not currently active
screenmob.client.screen -= A
R.shown_robot_modules = 0
screenmob.client.screen -= R.robot_modules_background
/datum/hud/robot/persistent_inventory_update(mob/viewer)
if(!mymob)
return
var/mob/living/silicon/robot/R = mymob
var/mob/screenmob = viewer || R
if(screenmob.hud_used)
if(screenmob.hud_used.hud_shown)
for(var/i in 1 to R.held_items.len)
var/obj/item/I = R.held_items[i]
if(I)
switch(i)
if(1)
I.screen_loc = ui_inv1
if(2)
I.screen_loc = ui_inv2
if(3)
I.screen_loc = ui_inv3
else
return
screenmob.client.screen += I
else
for(var/obj/item/I in R.held_items)
screenmob.client.screen -= I
/obj/screen/robot
icon = 'icons/mob/screen_cyborg.dmi'
/obj/screen/robot/module
name = "cyborg module"
icon_state = "nomod"
/obj/screen/robot/Click()
if(isobserver(usr))
return 1
/obj/screen/robot/module/Click()
if(..())
return
var/mob/living/silicon/robot/R = usr
if(R.module.type != /obj/item/robot_module)
R.hud_used.toggle_show_robot_modules()
return 1
R.pick_module()
/obj/screen/robot/module1
name = "module1"
icon_state = "inv1"
/obj/screen/robot/module1/Click()
if(..())
return
var/mob/living/silicon/robot/R = usr
R.toggle_module(1)
/obj/screen/robot/module2
name = "module2"
icon_state = "inv2"
/obj/screen/robot/module2/Click()
if(..())
return
var/mob/living/silicon/robot/R = usr
R.toggle_module(2)
/obj/screen/robot/module3
name = "module3"
icon_state = "inv3"
/obj/screen/robot/module3/Click()
if(..())
return
var/mob/living/silicon/robot/R = usr
R.toggle_module(3)
/obj/screen/robot/radio
name = "radio"
icon_state = "radio"
/obj/screen/robot/radio/Click()
if(..())
return
var/mob/living/silicon/robot/R = usr
R.radio.interact(R)
/obj/screen/robot/store
name = "store"
icon_state = "store"
/obj/screen/robot/store/Click()
if(..())
return
var/mob/living/silicon/robot/R = usr
R.uneq_active()
/obj/screen/robot/lamp
name = "headlamp"
icon_state = "lamp0"
/obj/screen/robot/lamp/Click()
if(..())
return
var/mob/living/silicon/robot/R = usr
R.control_headlamp()
/obj/screen/robot/thrusters
name = "ion thrusters"
icon_state = "ionpulse0"
/obj/screen/robot/thrusters/Click()
if(..())
return
var/mob/living/silicon/robot/R = usr
R.toggle_ionpulse()
/obj/screen/robot/sensors
name = "Sensor Augmentation"
icon_state = "cyborg_sensor"
/obj/screen/robot/sensors/Click()
if(..())
return
var/mob/living/silicon/S = usr
S.toggle_sensors()
/obj/screen/robot/language_menu
name = "silicon language selection"
icon_state = "talk_wheel"
/obj/screen/robot/language_menu/Click()
if(..())
return
var/mob/living/silicon/S = usr
S.open_language_menu(usr)
/datum/hud/robot
ui_style = 'icons/mob/screen_cyborg.dmi'
/datum/hud/robot/New(mob/owner)
..()
var/mob/living/silicon/robot/mymobR = mymob
var/obj/screen/using
using = new/obj/screen/robot/language_menu
using.screen_loc = ui_borg_language_menu
using.hud = src
static_inventory += using
//Radio
using = new /obj/screen/robot/radio()
using.screen_loc = ui_borg_radio
using.hud = src
static_inventory += using
//Module select
using = new /obj/screen/robot/module1()
using.screen_loc = ui_inv1
using.hud = src
static_inventory += using
mymobR.inv1 = using
using = new /obj/screen/robot/module2()
using.screen_loc = ui_inv2
using.hud = src
static_inventory += using
mymobR.inv2 = using
using = new /obj/screen/robot/module3()
using.screen_loc = ui_inv3
using.hud = src
static_inventory += using
mymobR.inv3 = using
//End of module select
//Photography stuff
using = new /obj/screen/ai/image_take()
using.screen_loc = ui_borg_camera
using.hud = src
static_inventory += using
using = new /obj/screen/ai/image_view()
using.screen_loc = ui_borg_album
using.hud = src
static_inventory += using
//Sec/Med HUDs
using = new /obj/screen/robot/sensors()
using.screen_loc = ui_borg_sensor
using.hud = src
static_inventory += using
//Headlamp control
using = new /obj/screen/robot/lamp()
using.screen_loc = ui_borg_lamp
using.hud = src
static_inventory += using
mymobR.lamp_button = using
//Thrusters
using = new /obj/screen/robot/thrusters()
using.screen_loc = ui_borg_thrusters
using.hud = src
static_inventory += using
mymobR.thruster_button = using
//Intent
action_intent = new /obj/screen/act_intent/robot()
action_intent.icon_state = mymob.a_intent
action_intent.hud = src
static_inventory += action_intent
//Health
healths = new /obj/screen/healths/robot()
healths.hud = src
infodisplay += healths
//Installed Module
mymobR.hands = new /obj/screen/robot/module()
mymobR.hands.screen_loc = ui_borg_module
static_inventory += mymobR.hands
//Store
module_store_icon = new /obj/screen/robot/store()
module_store_icon.hud = src
module_store_icon.screen_loc = ui_borg_store
pull_icon = new /obj/screen/pull()
pull_icon.icon = 'icons/mob/screen_cyborg.dmi'
pull_icon.hud = src
pull_icon.update_icon()
pull_icon.screen_loc = ui_borg_pull
hotkeybuttons += pull_icon
zone_select = new /obj/screen/zone_sel/robot()
zone_select.hud = src
zone_select.update_icon()
static_inventory += zone_select
/datum/hud/proc/toggle_show_robot_modules()
if(!iscyborg(mymob))
return
var/mob/living/silicon/robot/R = mymob
R.shown_robot_modules = !R.shown_robot_modules
update_robot_modules_display()
/datum/hud/proc/update_robot_modules_display(mob/viewer)
if(!iscyborg(mymob))
return
var/mob/living/silicon/robot/R = mymob
var/mob/screenmob = viewer || R
if(!R.module)
return
if(!R.client)
return
if(R.shown_robot_modules && screenmob.hud_used.hud_shown)
//Modules display is shown
screenmob.client.screen += module_store_icon //"store" icon
if(!R.module.modules)
to_chat(usr, "<span class='danger'>Selected module has no modules to select</span>")
return
if(!R.robot_modules_background)
return
var/display_rows = CEILING(length(R.module.get_inactive_modules()) / 8, 1)
R.robot_modules_background.screen_loc = "CENTER-4:16,SOUTH+1:7 to CENTER+3:16,SOUTH+[display_rows]:7"
screenmob.client.screen += R.robot_modules_background
var/x = -4 //Start at CENTER-4,SOUTH+1
var/y = 1
for(var/atom/movable/A in R.module.get_inactive_modules())
//Module is not currently active
screenmob.client.screen += A
if(x < 0)
A.screen_loc = "CENTER[x]:16,SOUTH+[y]:7"
else
A.screen_loc = "CENTER+[x]:16,SOUTH+[y]:7"
A.layer = ABOVE_HUD_LAYER
A.plane = ABOVE_HUD_PLANE
x++
if(x == 4)
x = -4
y++
else
//Modules display is hidden
screenmob.client.screen -= module_store_icon //"store" icon
for(var/atom/A in R.module.get_inactive_modules())
//Module is not currently active
screenmob.client.screen -= A
R.shown_robot_modules = 0
screenmob.client.screen -= R.robot_modules_background
/datum/hud/robot/persistent_inventory_update(mob/viewer)
if(!mymob)
return
var/mob/living/silicon/robot/R = mymob
var/mob/screenmob = viewer || R
if(screenmob.hud_used)
if(screenmob.hud_used.hud_shown)
for(var/i in 1 to R.held_items.len)
var/obj/item/I = R.held_items[i]
if(I)
switch(i)
if(1)
I.screen_loc = ui_inv1
if(2)
I.screen_loc = ui_inv2
if(3)
I.screen_loc = ui_inv3
else
return
screenmob.client.screen += I
else
for(var/obj/item/I in R.held_items)
screenmob.client.screen -= I
File diff suppressed because it is too large Load Diff
+167 -167
View File
@@ -1,167 +1,167 @@
/obj/item/proc/melee_attack_chain(mob/user, atom/target, params)
if(!tool_attack_chain(user, target) && pre_attack(target, user, params))
// Return 1 in attackby() to prevent afterattack() effects (when safely moving items for example)
var/resolved = target.attackby(src, user, params)
if(!resolved && target && !QDELETED(src))
afterattack(target, user, 1, params) // 1: clicking something Adjacent
//Checks if the item can work as a tool, calling the appropriate tool behavior on the target
/obj/item/proc/tool_attack_chain(mob/user, atom/target)
if(!tool_behaviour)
return FALSE
return target.tool_act(user, src, tool_behaviour)
// Called when the item is in the active hand, and clicked; alternately, there is an 'activate held object' verb or you can hit pagedown.
/obj/item/proc/attack_self(mob/user)
if(SEND_SIGNAL(src, COMSIG_ITEM_ATTACK_SELF, user) & COMPONENT_NO_INTERACT)
return
interact(user)
/obj/item/proc/pre_attack(atom/A, mob/living/user, params) //do stuff before attackby!
if(SEND_SIGNAL(src, COMSIG_ITEM_PRE_ATTACK, A, user, params) & COMPONENT_NO_ATTACK)
return FALSE
return TRUE //return FALSE to avoid calling attackby after this proc does stuff
// No comment
/atom/proc/attackby(obj/item/W, mob/user, params)
if(SEND_SIGNAL(src, COMSIG_PARENT_ATTACKBY, W, user, params) & COMPONENT_NO_AFTERATTACK)
return TRUE
return FALSE
/obj/attackby(obj/item/I, mob/living/user, params)
return ..() || ((obj_flags & CAN_BE_HIT) && I.attack_obj(src, user))
/mob/living/attackby(obj/item/I, mob/living/user, params)
if(..())
return TRUE
user.changeNext_move(CLICK_CD_MELEE)
return I.attack(src, user)
/obj/item/proc/attack(mob/living/M, mob/living/user)
if(SEND_SIGNAL(src, COMSIG_ITEM_ATTACK, M, user) & COMPONENT_ITEM_NO_ATTACK)
return
SEND_SIGNAL(user, COMSIG_MOB_ITEM_ATTACK, M, user)
if(item_flags & NOBLUDGEON)
return
if(user.getStaminaLoss() >= STAMINA_SOFTCRIT) // CIT CHANGE - makes it impossible to attack in stamina softcrit
to_chat(user, "<span class='warning'>You're too exhausted.</span>") // CIT CHANGE - ditto
return // CIT CHANGE - ditto
if(force && damtype != STAMINA && HAS_TRAIT(user, TRAIT_PACIFISM))
to_chat(user, "<span class='warning'>You don't want to harm other living beings!</span>")
return
if(!force)
playsound(loc, 'sound/weapons/tap.ogg', get_clamped_volume(), 1, -1)
else if(hitsound)
playsound(loc, hitsound, get_clamped_volume(), 1, -1)
M.lastattacker = user.real_name
M.lastattackerckey = user.ckey
user.do_attack_animation(M)
M.attacked_by(src, user)
log_combat(user, M, "attacked", src.name, "(INTENT: [uppertext(user.a_intent)]) (DAMTYPE: [uppertext(damtype)])")
add_fingerprint(user)
user.adjustStaminaLossBuffered(getweight()*0.8)//CIT CHANGE - makes attacking things cause stamina loss
//the equivalent of the standard version of attack() but for object targets.
/obj/item/proc/attack_obj(obj/O, mob/living/user)
if(SEND_SIGNAL(src, COMSIG_ITEM_ATTACK_OBJ, O, user) & COMPONENT_NO_ATTACK_OBJ)
return
if(item_flags & NOBLUDGEON)
return
if(user.getStaminaLoss() >= STAMINA_SOFTCRIT) // CIT CHANGE - makes it impossible to attack in stamina softcrit
to_chat(user, "<span class='warning'>You're too exhausted.</span>") // CIT CHANGE - ditto
return // CIT CHANGE - ditto
user.adjustStaminaLossBuffered(getweight()*1.2)//CIT CHANGE - makes attacking things cause stamina loss
user.changeNext_move(CLICK_CD_MELEE)
user.do_attack_animation(O)
O.attacked_by(src, user)
/atom/movable/proc/attacked_by()
return
/obj/attacked_by(obj/item/I, mob/living/user)
if(I.force)
visible_message("<span class='danger'>[user] has hit [src] with [I]!</span>", null, null, COMBAT_MESSAGE_RANGE)
//only witnesses close by and the victim see a hit message.
log_combat(user, src, "attacked", I)
take_damage(I.force, I.damtype, "melee", 1)
/mob/living/attacked_by(obj/item/I, mob/living/user)
//CIT CHANGES START HERE - combatmode and resting checks
var/totitemdamage = I.force
if(iscarbon(user))
var/mob/living/carbon/tempcarb = user
if(!tempcarb.combatmode)
totitemdamage *= 0.5
if(user.resting)
totitemdamage *= 0.5
//CIT CHANGES END HERE
if(user != src && check_shields(I, totitemdamage, "the [I.name]", MELEE_ATTACK, I.armour_penetration))
return FALSE
send_item_attack_message(I, user)
if(I.force)
apply_damage(totitemdamage, I.damtype) //CIT CHANGE - replaces I.force with totitemdamage
if(I.damtype == BRUTE && !HAS_TRAIT(src, TRAIT_NOMARROW))
if(prob(33))
I.add_mob_blood(src)
var/turf/location = get_turf(src)
if(iscarbon(src))
var/mob/living/carbon/C = src
C.bleed(totitemdamage)
else
add_splatter_floor(location)
if(totitemdamage >= 10 && get_dist(user, src) <= 1) //people with TK won't get smeared with blood
user.add_mob_blood(src)
return TRUE //successful attack
/mob/living/simple_animal/attacked_by(obj/item/I, mob/living/user)
if(I.force < force_threshold || I.damtype == STAMINA)
playsound(loc, 'sound/weapons/tap.ogg', I.get_clamped_volume(), 1, -1)
else
return ..()
// Proximity_flag is 1 if this afterattack was called on something adjacent, in your square, or on your person.
// Click parameters is the params string from byond Click() code, see that documentation.
/obj/item/proc/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
SEND_SIGNAL(src, COMSIG_ITEM_AFTERATTACK, target, user, proximity_flag, click_parameters)
SEND_SIGNAL(user, COMSIG_MOB_ITEM_AFTERATTACK, target, user, proximity_flag, click_parameters)
/obj/item/proc/get_clamped_volume()
if(w_class)
if(force)
return CLAMP((force + w_class) * 4, 30, 100)// Add the item's force to its weight class and multiply by 4, then clamp the value between 30 and 100
else
return CLAMP(w_class * 6, 10, 100) // Multiply the item's weight class by 6, then clamp the value between 10 and 100
/mob/living/proc/send_item_attack_message(obj/item/I, mob/living/user, hit_area)
var/message_verb = "attacked"
if(I.attack_verb && I.attack_verb.len)
message_verb = "[pick(I.attack_verb)]"
else if(!I.force)
return
var/message_hit_area = ""
if(hit_area)
message_hit_area = " in the [hit_area]"
var/attack_message = "[src] has been [message_verb][message_hit_area] with [I]."
if(user in viewers(src, null))
attack_message = "[user] has [message_verb] [src][message_hit_area] with [I]!"
visible_message("<span class='danger'>[attack_message]</span>",\
"<span class='userdanger'>[attack_message]</span>", null, COMBAT_MESSAGE_RANGE)
if(hit_area == BODY_ZONE_HEAD)
if(prob(2))
playsound(src, 'sound/weapons/dink.ogg', 30, 1)
return 1
/obj/item/proc/getweight()
return total_mass || w_class * 1.25
/obj/item/proc/melee_attack_chain(mob/user, atom/target, params)
if(!tool_attack_chain(user, target) && pre_attack(target, user, params))
// Return 1 in attackby() to prevent afterattack() effects (when safely moving items for example)
var/resolved = target.attackby(src, user, params)
if(!resolved && target && !QDELETED(src))
afterattack(target, user, 1, params) // 1: clicking something Adjacent
//Checks if the item can work as a tool, calling the appropriate tool behavior on the target
/obj/item/proc/tool_attack_chain(mob/user, atom/target)
if(!tool_behaviour)
return FALSE
return target.tool_act(user, src, tool_behaviour)
// Called when the item is in the active hand, and clicked; alternately, there is an 'activate held object' verb or you can hit pagedown.
/obj/item/proc/attack_self(mob/user)
if(SEND_SIGNAL(src, COMSIG_ITEM_ATTACK_SELF, user) & COMPONENT_NO_INTERACT)
return
interact(user)
/obj/item/proc/pre_attack(atom/A, mob/living/user, params) //do stuff before attackby!
if(SEND_SIGNAL(src, COMSIG_ITEM_PRE_ATTACK, A, user, params) & COMPONENT_NO_ATTACK)
return FALSE
return TRUE //return FALSE to avoid calling attackby after this proc does stuff
// No comment
/atom/proc/attackby(obj/item/W, mob/user, params)
if(SEND_SIGNAL(src, COMSIG_PARENT_ATTACKBY, W, user, params) & COMPONENT_NO_AFTERATTACK)
return TRUE
return FALSE
/obj/attackby(obj/item/I, mob/living/user, params)
return ..() || ((obj_flags & CAN_BE_HIT) && I.attack_obj(src, user))
/mob/living/attackby(obj/item/I, mob/living/user, params)
if(..())
return TRUE
user.changeNext_move(CLICK_CD_MELEE)
return I.attack(src, user)
/obj/item/proc/attack(mob/living/M, mob/living/user)
if(SEND_SIGNAL(src, COMSIG_ITEM_ATTACK, M, user) & COMPONENT_ITEM_NO_ATTACK)
return
SEND_SIGNAL(user, COMSIG_MOB_ITEM_ATTACK, M, user)
if(item_flags & NOBLUDGEON)
return
if(user.getStaminaLoss() >= STAMINA_SOFTCRIT) // CIT CHANGE - makes it impossible to attack in stamina softcrit
to_chat(user, "<span class='warning'>You're too exhausted.</span>") // CIT CHANGE - ditto
return // CIT CHANGE - ditto
if(force && damtype != STAMINA && HAS_TRAIT(user, TRAIT_PACIFISM))
to_chat(user, "<span class='warning'>You don't want to harm other living beings!</span>")
return
if(!force)
playsound(loc, 'sound/weapons/tap.ogg', get_clamped_volume(), 1, -1)
else if(hitsound)
playsound(loc, hitsound, get_clamped_volume(), 1, -1)
M.lastattacker = user.real_name
M.lastattackerckey = user.ckey
user.do_attack_animation(M)
M.attacked_by(src, user)
log_combat(user, M, "attacked", src.name, "(INTENT: [uppertext(user.a_intent)]) (DAMTYPE: [uppertext(damtype)])")
add_fingerprint(user)
user.adjustStaminaLossBuffered(getweight()*0.8)//CIT CHANGE - makes attacking things cause stamina loss
//the equivalent of the standard version of attack() but for object targets.
/obj/item/proc/attack_obj(obj/O, mob/living/user)
if(SEND_SIGNAL(src, COMSIG_ITEM_ATTACK_OBJ, O, user) & COMPONENT_NO_ATTACK_OBJ)
return
if(item_flags & NOBLUDGEON)
return
if(user.getStaminaLoss() >= STAMINA_SOFTCRIT) // CIT CHANGE - makes it impossible to attack in stamina softcrit
to_chat(user, "<span class='warning'>You're too exhausted.</span>") // CIT CHANGE - ditto
return // CIT CHANGE - ditto
user.adjustStaminaLossBuffered(getweight()*1.2)//CIT CHANGE - makes attacking things cause stamina loss
user.changeNext_move(CLICK_CD_MELEE)
user.do_attack_animation(O)
O.attacked_by(src, user)
/atom/movable/proc/attacked_by()
return
/obj/attacked_by(obj/item/I, mob/living/user)
if(I.force)
visible_message("<span class='danger'>[user] has hit [src] with [I]!</span>", null, null, COMBAT_MESSAGE_RANGE)
//only witnesses close by and the victim see a hit message.
log_combat(user, src, "attacked", I)
take_damage(I.force, I.damtype, "melee", 1)
/mob/living/attacked_by(obj/item/I, mob/living/user)
//CIT CHANGES START HERE - combatmode and resting checks
var/totitemdamage = I.force
if(iscarbon(user))
var/mob/living/carbon/tempcarb = user
if(!tempcarb.combatmode)
totitemdamage *= 0.5
if(user.resting)
totitemdamage *= 0.5
//CIT CHANGES END HERE
if(user != src && check_shields(I, totitemdamage, "the [I.name]", MELEE_ATTACK, I.armour_penetration))
return FALSE
send_item_attack_message(I, user)
if(I.force)
apply_damage(totitemdamage, I.damtype) //CIT CHANGE - replaces I.force with totitemdamage
if(I.damtype == BRUTE && !HAS_TRAIT(src, TRAIT_NOMARROW))
if(prob(33))
I.add_mob_blood(src)
var/turf/location = get_turf(src)
if(iscarbon(src))
var/mob/living/carbon/C = src
C.bleed(totitemdamage)
else
add_splatter_floor(location)
if(totitemdamage >= 10 && get_dist(user, src) <= 1) //people with TK won't get smeared with blood
user.add_mob_blood(src)
return TRUE //successful attack
/mob/living/simple_animal/attacked_by(obj/item/I, mob/living/user)
if(I.force < force_threshold || I.damtype == STAMINA)
playsound(loc, 'sound/weapons/tap.ogg', I.get_clamped_volume(), 1, -1)
else
return ..()
// Proximity_flag is 1 if this afterattack was called on something adjacent, in your square, or on your person.
// Click parameters is the params string from byond Click() code, see that documentation.
/obj/item/proc/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
SEND_SIGNAL(src, COMSIG_ITEM_AFTERATTACK, target, user, proximity_flag, click_parameters)
SEND_SIGNAL(user, COMSIG_MOB_ITEM_AFTERATTACK, target, user, proximity_flag, click_parameters)
/obj/item/proc/get_clamped_volume()
if(w_class)
if(force)
return CLAMP((force + w_class) * 4, 30, 100)// Add the item's force to its weight class and multiply by 4, then clamp the value between 30 and 100
else
return CLAMP(w_class * 6, 10, 100) // Multiply the item's weight class by 6, then clamp the value between 10 and 100
/mob/living/proc/send_item_attack_message(obj/item/I, mob/living/user, hit_area)
var/message_verb = "attacked"
if(I.attack_verb && I.attack_verb.len)
message_verb = "[pick(I.attack_verb)]"
else if(!I.force)
return
var/message_hit_area = ""
if(hit_area)
message_hit_area = " in the [hit_area]"
var/attack_message = "[src] has been [message_verb][message_hit_area] with [I]."
if(user in viewers(src, null))
attack_message = "[user] has [message_verb] [src][message_hit_area] with [I]!"
visible_message("<span class='danger'>[attack_message]</span>",\
"<span class='userdanger'>[attack_message]</span>", null, COMBAT_MESSAGE_RANGE)
if(hit_area == BODY_ZONE_HEAD)
if(prob(2))
playsound(src, 'sound/weapons/dink.ogg', 30, 1)
return 1
/obj/item/proc/getweight()
return total_mass || w_class * 1.25
+83 -83
View File
@@ -1,83 +1,83 @@
/mob/dead/observer/DblClickOn(var/atom/A, var/params)
if(can_reenter_corpse && mind && mind.current)
if(A == mind.current || (mind.current in A)) // double click your corpse or whatever holds it
reenter_corpse() // (cloning scanner, body bag, closet, mech, etc)
return // seems legit.
// Things you might plausibly want to follow
if(ismovableatom(A))
ManualFollow(A)
// Otherwise jump
else if(A.loc)
forceMove(get_turf(A))
update_parallax_contents()
/mob/dead/observer/ClickOn(var/atom/A, var/params)
if(check_click_intercept(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"])
altclick_listed_turf(A)
return
if(modifiers["ctrl"])
CtrlClickOn(A)
return
if(world.time <= next_move)
return
// You are responsible for checking config.ghost_interaction when you override this function
// Not all of them require checking, see below
A.attack_ghost(src)
// Oh by the way this didn't work with old click code which is why clicking shit didn't spam you
/atom/proc/attack_ghost(mob/dead/observer/user)
if(SEND_SIGNAL(src, COMSIG_ATOM_ATTACK_GHOST, user) & COMPONENT_NO_ATTACK_HAND)
return TRUE
if(user.client)
if(IsAdminGhost(user))
attack_ai(user)
else if(user.client.prefs.inquisitive_ghost)
user.examinate(src)
return FALSE
/mob/living/attack_ghost(mob/dead/observer/user)
if(user.client && user.health_scan)
healthscan(user, src, 1, TRUE)
return ..()
// ---------------------------------------
// And here are some good things for free:
// Now you can click through portals, wormholes, gateways, and teleporters while observing. -Sayu
/obj/machinery/gateway/centerstation/attack_ghost(mob/user)
if(awaygate)
user.forceMove(awaygate.loc)
else
to_chat(user, "[src] has no destination.")
return ..()
/obj/machinery/gateway/centeraway/attack_ghost(mob/user)
if(stationgate)
user.forceMove(stationgate.loc)
else
to_chat(user, "[src] has no destination.")
return ..()
/obj/machinery/teleport/hub/attack_ghost(mob/user)
if(power_station && power_station.engaged && power_station.teleporter_console && power_station.teleporter_console.target)
user.forceMove(get_turf(power_station.teleporter_console.target))
return ..()
/mob/dead/observer/DblClickOn(var/atom/A, var/params)
if(can_reenter_corpse && mind && mind.current)
if(A == mind.current || (mind.current in A)) // double click your corpse or whatever holds it
reenter_corpse() // (cloning scanner, body bag, closet, mech, etc)
return // seems legit.
// Things you might plausibly want to follow
if(ismovableatom(A))
ManualFollow(A)
// Otherwise jump
else if(A.loc)
forceMove(get_turf(A))
update_parallax_contents()
/mob/dead/observer/ClickOn(var/atom/A, var/params)
if(check_click_intercept(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"])
altclick_listed_turf(A)
return
if(modifiers["ctrl"])
CtrlClickOn(A)
return
if(world.time <= next_move)
return
// You are responsible for checking config.ghost_interaction when you override this function
// Not all of them require checking, see below
A.attack_ghost(src)
// Oh by the way this didn't work with old click code which is why clicking shit didn't spam you
/atom/proc/attack_ghost(mob/dead/observer/user)
if(SEND_SIGNAL(src, COMSIG_ATOM_ATTACK_GHOST, user) & COMPONENT_NO_ATTACK_HAND)
return TRUE
if(user.client)
if(IsAdminGhost(user))
attack_ai(user)
else if(user.client.prefs.inquisitive_ghost)
user.examinate(src)
return FALSE
/mob/living/attack_ghost(mob/dead/observer/user)
if(user.client && user.health_scan)
healthscan(user, src, 1, TRUE)
return ..()
// ---------------------------------------
// And here are some good things for free:
// Now you can click through portals, wormholes, gateways, and teleporters while observing. -Sayu
/obj/machinery/gateway/centerstation/attack_ghost(mob/user)
if(awaygate)
user.forceMove(awaygate.loc)
else
to_chat(user, "[src] has no destination.")
return ..()
/obj/machinery/gateway/centeraway/attack_ghost(mob/user)
if(stationgate)
user.forceMove(stationgate.loc)
else
to_chat(user, "[src] has no destination.")
return ..()
/obj/machinery/teleport/hub/attack_ghost(mob/user)
if(power_station && power_station.engaged && power_station.teleporter_console && power_station.teleporter_console.target)
user.forceMove(get_turf(power_station.teleporter_console.target))
return ..()
+260 -260
View File
@@ -1,260 +1,260 @@
/*
Humans:
Adds an exception for gloves, to allow special glove types like the ninja ones.
Otherwise pretty standard.
*/
/mob/living/carbon/human/UnarmedAttack(atom/A, proximity)
if(!has_active_hand()) //can't attack without a hand.
to_chat(src, "<span class='notice'>You look at your arm and sigh.</span>")
return
// Special glove functions:
// If the gloves do anything, have them return 1 to stop
// normal attack_hand() here.
var/obj/item/clothing/gloves/G = gloves // not typecast specifically enough in defines
if(proximity && istype(G) && G.Touch(A,1))
return
var/override = 0
for(var/datum/mutation/human/HM in dna.mutations)
override += HM.on_attack_hand(src, A, proximity)
if(override)
return
SEND_SIGNAL(src, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, A)
A.attack_hand(src)
//Return TRUE to cancel other attack hand effects that respect it.
/atom/proc/attack_hand(mob/user)
. = FALSE
if(!(interaction_flags_atom & INTERACT_ATOM_NO_FINGERPRINT_ATTACK_HAND))
add_fingerprint(user)
if(SEND_SIGNAL(src, COMSIG_ATOM_ATTACK_HAND, user) & COMPONENT_NO_ATTACK_HAND)
. = TRUE
if(interaction_flags_atom & INTERACT_ATOM_ATTACK_HAND)
. = _try_interact(user)
//Return a non FALSE value to cancel whatever called this from propagating, if it respects it.
/atom/proc/_try_interact(mob/user)
if(IsAdminGhost(user)) //admin abuse
return interact(user)
if(can_interact(user))
return interact(user)
return FALSE
/atom/proc/can_interact(mob/user)
if(!user.can_interact_with(src))
return FALSE
if((interaction_flags_atom & INTERACT_ATOM_REQUIRES_DEXTERITY) && !user.IsAdvancedToolUser())
to_chat(user, "<span class='warning'>You don't have the dexterity to do this!</span>")
return FALSE
if(!(interaction_flags_atom & INTERACT_ATOM_IGNORE_INCAPACITATED) && user.incapacitated((interaction_flags_atom & INTERACT_ATOM_IGNORE_RESTRAINED), !(interaction_flags_atom & INTERACT_ATOM_CHECK_GRAB)))
return FALSE
return TRUE
/atom/ui_status(mob/user)
. = ..()
if(!can_interact(user))
. = min(., UI_UPDATE)
/atom/movable/can_interact(mob/user)
. = ..()
if(!.)
return
if(!anchored && (interaction_flags_atom & INTERACT_ATOM_REQUIRES_ANCHORED))
return FALSE
/atom/proc/interact(mob/user)
if(interaction_flags_atom & INTERACT_ATOM_NO_FINGERPRINT_INTERACT)
add_hiddenprint(user)
else
add_fingerprint(user)
if(interaction_flags_atom & INTERACT_ATOM_UI_INTERACT)
return ui_interact(user)
return FALSE
/*
/mob/living/carbon/human/RestrainedClickOn(var/atom/A) ---carbons will handle this
return
*/
/mob/living/carbon/RestrainedClickOn(atom/A)
return 0
/mob/living/carbon/human/RangedAttack(atom/A, mouseparams)
. = ..()
if(gloves)
var/obj/item/clothing/gloves/G = gloves
if(istype(G) && G.Touch(A,0)) // for magic gloves
return
if (istype(glasses) && glasses.ranged_attack(src,A,mouseparams))
return
for(var/datum/mutation/human/HM in dna.mutations)
HM.on_ranged_attack(src, A, mouseparams)
if(isturf(A) && get_dist(src,A) <= 1)
src.Move_Pulled(A)
return
/*
Animals & All Unspecified
*/
/mob/living/UnarmedAttack(atom/A)
A.attack_animal(src)
/atom/proc/attack_animal(mob/user)
return
/mob/living/RestrainedClickOn(atom/A)
return
/*
Monkeys
*/
/mob/living/carbon/monkey/UnarmedAttack(atom/A)
A.attack_paw(src)
/atom/proc/attack_paw(mob/user)
if(SEND_SIGNAL(src, COMSIG_ATOM_ATTACK_PAW, user) & COMPONENT_NO_ATTACK_HAND)
return TRUE
return FALSE
/*
Monkey RestrainedClickOn() was apparently the
one and only use of all of the restrained click code
(except to stop you from doing things while handcuffed);
moving it here instead of various hand_p's has simplified
things considerably
*/
/mob/living/carbon/monkey/RestrainedClickOn(atom/A)
if(..())
return
if(a_intent != INTENT_HARM || !ismob(A))
return
if(is_muzzled())
return
var/mob/living/carbon/ML = A
if(istype(ML))
var/dam_zone = pick(BODY_ZONE_CHEST, BODY_ZONE_PRECISE_L_HAND, BODY_ZONE_PRECISE_R_HAND, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
var/obj/item/bodypart/affecting = null
if(ishuman(ML))
var/mob/living/carbon/human/H = ML
affecting = H.get_bodypart(ran_zone(dam_zone))
var/armor = ML.run_armor_check(affecting, "melee")
if(prob(75))
ML.apply_damage(rand(1,3), BRUTE, affecting, armor)
ML.visible_message("<span class='danger'>[name] bites [ML]!</span>", \
"<span class='userdanger'>[name] bites [ML]!</span>")
if(armor >= 2)
return
for(var/thing in diseases)
var/datum/disease/D = thing
ML.ForceContractDisease(D)
else
ML.visible_message("<span class='danger'>[src] has attempted to bite [ML]!</span>")
/*
Aliens
Defaults to same as monkey in most places
*/
/mob/living/carbon/alien/UnarmedAttack(atom/A)
A.attack_alien(src)
/atom/proc/attack_alien(mob/living/carbon/alien/user)
attack_paw(user)
return
/mob/living/carbon/alien/RestrainedClickOn(atom/A)
return
// Babby aliens
/mob/living/carbon/alien/larva/UnarmedAttack(atom/A)
A.attack_larva(src)
/atom/proc/attack_larva(mob/user)
return
/*
Slimes
Nothing happening here
*/
/mob/living/simple_animal/slime/UnarmedAttack(atom/A)
A.attack_slime(src)
/atom/proc/attack_slime(mob/user)
return
/mob/living/simple_animal/slime/RestrainedClickOn(atom/A)
return
/*
Drones
*/
/mob/living/simple_animal/drone/UnarmedAttack(atom/A)
A.attack_drone(src)
/atom/proc/attack_drone(mob/living/simple_animal/drone/user)
attack_hand(user) //defaults to attack_hand. Override it when you don't want drones to do same stuff as humans.
/mob/living/simple_animal/slime/RestrainedClickOn(atom/A)
return
/*
True Devil
*/
/mob/living/carbon/true_devil/UnarmedAttack(atom/A, proximity)
A.attack_hand(src)
/*
Brain
*/
/mob/living/brain/UnarmedAttack(atom/A)//Stops runtimes due to attack_animal being the default
return
/*
pAI
*/
/mob/living/silicon/pai/UnarmedAttack(atom/A)//Stops runtimes due to attack_animal being the default
return
/*
Simple animals
*/
/mob/living/simple_animal/UnarmedAttack(atom/A, proximity)
if(!dextrous)
return ..()
if(!ismob(A))
A.attack_hand(src)
update_inv_hands()
/*
Hostile animals
*/
/mob/living/simple_animal/hostile/UnarmedAttack(atom/A)
target = A
if(dextrous && !ismob(A))
..()
else
AttackingTarget()
/*
New Players:
Have no reason to click on anything at all.
*/
/mob/dead/new_player/ClickOn()
return
/*
Humans:
Adds an exception for gloves, to allow special glove types like the ninja ones.
Otherwise pretty standard.
*/
/mob/living/carbon/human/UnarmedAttack(atom/A, proximity)
if(!has_active_hand()) //can't attack without a hand.
to_chat(src, "<span class='notice'>You look at your arm and sigh.</span>")
return
// Special glove functions:
// If the gloves do anything, have them return 1 to stop
// normal attack_hand() here.
var/obj/item/clothing/gloves/G = gloves // not typecast specifically enough in defines
if(proximity && istype(G) && G.Touch(A,1))
return
var/override = 0
for(var/datum/mutation/human/HM in dna.mutations)
override += HM.on_attack_hand(src, A, proximity)
if(override)
return
SEND_SIGNAL(src, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, A)
A.attack_hand(src)
//Return TRUE to cancel other attack hand effects that respect it.
/atom/proc/attack_hand(mob/user)
. = FALSE
if(!(interaction_flags_atom & INTERACT_ATOM_NO_FINGERPRINT_ATTACK_HAND))
add_fingerprint(user)
if(SEND_SIGNAL(src, COMSIG_ATOM_ATTACK_HAND, user) & COMPONENT_NO_ATTACK_HAND)
. = TRUE
if(interaction_flags_atom & INTERACT_ATOM_ATTACK_HAND)
. = _try_interact(user)
//Return a non FALSE value to cancel whatever called this from propagating, if it respects it.
/atom/proc/_try_interact(mob/user)
if(IsAdminGhost(user)) //admin abuse
return interact(user)
if(can_interact(user))
return interact(user)
return FALSE
/atom/proc/can_interact(mob/user)
if(!user.can_interact_with(src))
return FALSE
if((interaction_flags_atom & INTERACT_ATOM_REQUIRES_DEXTERITY) && !user.IsAdvancedToolUser())
to_chat(user, "<span class='warning'>You don't have the dexterity to do this!</span>")
return FALSE
if(!(interaction_flags_atom & INTERACT_ATOM_IGNORE_INCAPACITATED) && user.incapacitated((interaction_flags_atom & INTERACT_ATOM_IGNORE_RESTRAINED), !(interaction_flags_atom & INTERACT_ATOM_CHECK_GRAB)))
return FALSE
return TRUE
/atom/ui_status(mob/user)
. = ..()
if(!can_interact(user))
. = min(., UI_UPDATE)
/atom/movable/can_interact(mob/user)
. = ..()
if(!.)
return
if(!anchored && (interaction_flags_atom & INTERACT_ATOM_REQUIRES_ANCHORED))
return FALSE
/atom/proc/interact(mob/user)
if(interaction_flags_atom & INTERACT_ATOM_NO_FINGERPRINT_INTERACT)
add_hiddenprint(user)
else
add_fingerprint(user)
if(interaction_flags_atom & INTERACT_ATOM_UI_INTERACT)
return ui_interact(user)
return FALSE
/*
/mob/living/carbon/human/RestrainedClickOn(var/atom/A) ---carbons will handle this
return
*/
/mob/living/carbon/RestrainedClickOn(atom/A)
return 0
/mob/living/carbon/human/RangedAttack(atom/A, mouseparams)
. = ..()
if(gloves)
var/obj/item/clothing/gloves/G = gloves
if(istype(G) && G.Touch(A,0)) // for magic gloves
return
if (istype(glasses) && glasses.ranged_attack(src,A,mouseparams))
return
for(var/datum/mutation/human/HM in dna.mutations)
HM.on_ranged_attack(src, A, mouseparams)
if(isturf(A) && get_dist(src,A) <= 1)
src.Move_Pulled(A)
return
/*
Animals & All Unspecified
*/
/mob/living/UnarmedAttack(atom/A)
A.attack_animal(src)
/atom/proc/attack_animal(mob/user)
return
/mob/living/RestrainedClickOn(atom/A)
return
/*
Monkeys
*/
/mob/living/carbon/monkey/UnarmedAttack(atom/A)
A.attack_paw(src)
/atom/proc/attack_paw(mob/user)
if(SEND_SIGNAL(src, COMSIG_ATOM_ATTACK_PAW, user) & COMPONENT_NO_ATTACK_HAND)
return TRUE
return FALSE
/*
Monkey RestrainedClickOn() was apparently the
one and only use of all of the restrained click code
(except to stop you from doing things while handcuffed);
moving it here instead of various hand_p's has simplified
things considerably
*/
/mob/living/carbon/monkey/RestrainedClickOn(atom/A)
if(..())
return
if(a_intent != INTENT_HARM || !ismob(A))
return
if(is_muzzled())
return
var/mob/living/carbon/ML = A
if(istype(ML))
var/dam_zone = pick(BODY_ZONE_CHEST, BODY_ZONE_PRECISE_L_HAND, BODY_ZONE_PRECISE_R_HAND, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
var/obj/item/bodypart/affecting = null
if(ishuman(ML))
var/mob/living/carbon/human/H = ML
affecting = H.get_bodypart(ran_zone(dam_zone))
var/armor = ML.run_armor_check(affecting, "melee")
if(prob(75))
ML.apply_damage(rand(1,3), BRUTE, affecting, armor)
ML.visible_message("<span class='danger'>[name] bites [ML]!</span>", \
"<span class='userdanger'>[name] bites [ML]!</span>")
if(armor >= 2)
return
for(var/thing in diseases)
var/datum/disease/D = thing
ML.ForceContractDisease(D)
else
ML.visible_message("<span class='danger'>[src] has attempted to bite [ML]!</span>")
/*
Aliens
Defaults to same as monkey in most places
*/
/mob/living/carbon/alien/UnarmedAttack(atom/A)
A.attack_alien(src)
/atom/proc/attack_alien(mob/living/carbon/alien/user)
attack_paw(user)
return
/mob/living/carbon/alien/RestrainedClickOn(atom/A)
return
// Babby aliens
/mob/living/carbon/alien/larva/UnarmedAttack(atom/A)
A.attack_larva(src)
/atom/proc/attack_larva(mob/user)
return
/*
Slimes
Nothing happening here
*/
/mob/living/simple_animal/slime/UnarmedAttack(atom/A)
A.attack_slime(src)
/atom/proc/attack_slime(mob/user)
return
/mob/living/simple_animal/slime/RestrainedClickOn(atom/A)
return
/*
Drones
*/
/mob/living/simple_animal/drone/UnarmedAttack(atom/A)
A.attack_drone(src)
/atom/proc/attack_drone(mob/living/simple_animal/drone/user)
attack_hand(user) //defaults to attack_hand. Override it when you don't want drones to do same stuff as humans.
/mob/living/simple_animal/slime/RestrainedClickOn(atom/A)
return
/*
True Devil
*/
/mob/living/carbon/true_devil/UnarmedAttack(atom/A, proximity)
A.attack_hand(src)
/*
Brain
*/
/mob/living/brain/UnarmedAttack(atom/A)//Stops runtimes due to attack_animal being the default
return
/*
pAI
*/
/mob/living/silicon/pai/UnarmedAttack(atom/A)//Stops runtimes due to attack_animal being the default
return
/*
Simple animals
*/
/mob/living/simple_animal/UnarmedAttack(atom/A, proximity)
if(!dextrous)
return ..()
if(!ismob(A))
A.attack_hand(src)
update_inv_hands()
/*
Hostile animals
*/
/mob/living/simple_animal/hostile/UnarmedAttack(atom/A)
target = A
if(dextrous && !ismob(A))
..()
else
AttackingTarget()
/*
New Players:
Have no reason to click on anything at all.
*/
/mob/dead/new_player/ClickOn()
return