mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-11 10:43:20 +00:00
Merge remote-tracking branch 'upstream/dev' into span_class=notice
Conflicts: code/game/antagonist/station/rogue_ai.dm code/game/machinery/OpTable.dm code/game/machinery/floodlight.dm code/game/machinery/spaceheater.dm
This commit is contained in:
@@ -13,13 +13,6 @@
|
||||
Therefore, the top right corner (except during admin shenanigans) is at "15,15"
|
||||
*/
|
||||
|
||||
//Upper left action buttons, displayed when you pick up an item that has this enabled.
|
||||
#define ui_action_slot1 "1:6,14:26"
|
||||
#define ui_action_slot2 "2:8,14:26"
|
||||
#define ui_action_slot3 "3:10,14:26"
|
||||
#define ui_action_slot4 "4:12,14:26"
|
||||
#define ui_action_slot5 "5:14,14:26"
|
||||
|
||||
//Lower left, persistant menu
|
||||
#define ui_inventory "1:6,1:5"
|
||||
|
||||
|
||||
222
code/_onclick/hud/action.dm
Normal file
222
code/_onclick/hud/action.dm
Normal file
@@ -0,0 +1,222 @@
|
||||
#define AB_ITEM 1
|
||||
#define AB_SPELL 2
|
||||
#define AB_INNATE 3
|
||||
#define AB_GENERIC 4
|
||||
|
||||
#define AB_CHECK_RESTRAINED 1
|
||||
#define AB_CHECK_STUNNED 2
|
||||
#define AB_CHECK_LYING 4
|
||||
#define AB_CHECK_ALIVE 8
|
||||
#define AB_CHECK_INSIDE 16
|
||||
|
||||
|
||||
/datum/action
|
||||
var/name = "Generic Action"
|
||||
var/action_type = AB_ITEM
|
||||
var/procname = null
|
||||
var/atom/movable/target = null
|
||||
var/check_flags = 0
|
||||
var/processing = 0
|
||||
var/active = 0
|
||||
var/obj/screen/movable/action_button/button = null
|
||||
var/button_icon = 'icons/mob/actions.dmi'
|
||||
var/button_icon_state = "default"
|
||||
var/background_icon_state = "bg_default"
|
||||
var/mob/living/owner
|
||||
|
||||
/datum/action/New(var/Target)
|
||||
target = Target
|
||||
|
||||
/datum/action/Destroy()
|
||||
if(owner)
|
||||
Remove(owner)
|
||||
|
||||
/datum/action/proc/Grant(mob/living/T)
|
||||
if(owner)
|
||||
if(owner == T)
|
||||
return
|
||||
Remove(owner)
|
||||
owner = T
|
||||
owner.actions.Add(src)
|
||||
owner.update_action_buttons()
|
||||
return
|
||||
|
||||
/datum/action/proc/Remove(mob/living/T)
|
||||
if(button)
|
||||
if(T.client)
|
||||
T.client.screen -= button
|
||||
del(button)
|
||||
T.actions.Remove(src)
|
||||
T.update_action_buttons()
|
||||
owner = null
|
||||
return
|
||||
|
||||
/datum/action/proc/Trigger()
|
||||
if(!Checks())
|
||||
return
|
||||
switch(action_type)
|
||||
if(AB_ITEM)
|
||||
if(target)
|
||||
var/obj/item/item = target
|
||||
item.ui_action_click()
|
||||
//if(AB_SPELL)
|
||||
// if(target)
|
||||
// var/obj/effect/proc_holder/spell = target
|
||||
// spell.Click()
|
||||
if(AB_INNATE)
|
||||
if(!active)
|
||||
Activate()
|
||||
else
|
||||
Deactivate()
|
||||
if(AB_GENERIC)
|
||||
if(target && procname)
|
||||
call(target,procname)(usr)
|
||||
return
|
||||
|
||||
/datum/action/proc/Activate()
|
||||
return
|
||||
|
||||
/datum/action/proc/Deactivate()
|
||||
return
|
||||
|
||||
/datum/action/proc/Process()
|
||||
return
|
||||
|
||||
/datum/action/proc/CheckRemoval(mob/living/user) // 1 if action is no longer valid for this mob and should be removed
|
||||
return 0
|
||||
|
||||
/datum/action/proc/IsAvailable()
|
||||
return Checks()
|
||||
|
||||
/datum/action/proc/Checks()// returns 1 if all checks pass
|
||||
if(!owner)
|
||||
return 0
|
||||
if(check_flags & AB_CHECK_RESTRAINED)
|
||||
if(owner.restrained())
|
||||
return 0
|
||||
if(check_flags & AB_CHECK_STUNNED)
|
||||
if(owner.stunned)
|
||||
return 0
|
||||
if(check_flags & AB_CHECK_LYING)
|
||||
if(owner.lying)
|
||||
return 0
|
||||
if(check_flags & AB_CHECK_ALIVE)
|
||||
if(owner.stat)
|
||||
return 0
|
||||
if(check_flags & AB_CHECK_INSIDE)
|
||||
if(!(target in owner))
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/datum/action/proc/UpdateName()
|
||||
return name
|
||||
|
||||
/obj/screen/movable/action_button
|
||||
var/datum/action/owner
|
||||
screen_loc = "WEST,NORTH"
|
||||
|
||||
/obj/screen/movable/action_button/Click(location,control,params)
|
||||
var/list/modifiers = params2list(params)
|
||||
if(modifiers["shift"])
|
||||
moved = 0
|
||||
return 1
|
||||
if(usr.next_move >= world.time) // Is this needed ?
|
||||
return
|
||||
owner.Trigger()
|
||||
return 1
|
||||
|
||||
/obj/screen/movable/action_button/proc/UpdateIcon()
|
||||
if(!owner)
|
||||
return
|
||||
icon = owner.button_icon
|
||||
icon_state = owner.background_icon_state
|
||||
|
||||
overlays.Cut()
|
||||
var/image/img
|
||||
if(owner.action_type == AB_ITEM && owner.target)
|
||||
var/obj/item/I = owner.target
|
||||
img = image(I.icon, src , I.icon_state)
|
||||
else if(owner.button_icon && owner.button_icon_state)
|
||||
img = image(owner.button_icon,src,owner.button_icon_state)
|
||||
img.pixel_x = 0
|
||||
img.pixel_y = 0
|
||||
overlays += img
|
||||
|
||||
if(!owner.IsAvailable())
|
||||
color = rgb(128,0,0,128)
|
||||
else
|
||||
color = rgb(255,255,255,255)
|
||||
|
||||
//Hide/Show Action Buttons ... Button
|
||||
/obj/screen/movable/action_button/hide_toggle
|
||||
name = "Hide Buttons"
|
||||
icon = 'icons/mob/actions.dmi'
|
||||
icon_state = "bg_default"
|
||||
var/hidden = 0
|
||||
|
||||
/obj/screen/movable/action_button/hide_toggle/Click()
|
||||
usr.hud_used.action_buttons_hidden = !usr.hud_used.action_buttons_hidden
|
||||
|
||||
hidden = usr.hud_used.action_buttons_hidden
|
||||
if(hidden)
|
||||
name = "Show Buttons"
|
||||
else
|
||||
name = "Hide Buttons"
|
||||
UpdateIcon()
|
||||
usr.update_action_buttons()
|
||||
|
||||
|
||||
/obj/screen/movable/action_button/hide_toggle/proc/InitialiseIcon(var/mob/living/user)
|
||||
if(isalien(user))
|
||||
icon_state = "bg_alien"
|
||||
else
|
||||
icon_state = "bg_default"
|
||||
UpdateIcon()
|
||||
return
|
||||
|
||||
/obj/screen/movable/action_button/hide_toggle/UpdateIcon()
|
||||
overlays.Cut()
|
||||
var/image/img = image(icon,src,hidden?"show":"hide")
|
||||
overlays += img
|
||||
return
|
||||
|
||||
//This is the proc used to update all the action buttons. Properly defined in /mob/living/
|
||||
/mob/proc/update_action_buttons()
|
||||
return
|
||||
|
||||
#define AB_WEST_OFFSET 4
|
||||
#define AB_NORTH_OFFSET 26
|
||||
#define AB_MAX_COLUMNS 10
|
||||
|
||||
/datum/hud/proc/ButtonNumberToScreenCoords(var/number) // TODO : Make this zero-indexed for readabilty
|
||||
var/row = round((number-1)/AB_MAX_COLUMNS)
|
||||
var/col = ((number - 1)%(AB_MAX_COLUMNS)) + 1
|
||||
var/coord_col = "+[col-1]"
|
||||
var/coord_col_offset = AB_WEST_OFFSET+2*col
|
||||
var/coord_row = "[-1 - row]"
|
||||
var/coord_row_offset = AB_NORTH_OFFSET
|
||||
return "WEST[coord_col]:[coord_col_offset],NORTH[coord_row]:[coord_row_offset]"
|
||||
|
||||
/datum/hud/proc/SetButtonCoords(var/obj/screen/button,var/number)
|
||||
var/row = round((number-1)/AB_MAX_COLUMNS)
|
||||
var/col = ((number - 1)%(AB_MAX_COLUMNS)) + 1
|
||||
var/x_offset = 32*(col-1) + AB_WEST_OFFSET + 2*col
|
||||
var/y_offset = -32*(row+1) + AB_NORTH_OFFSET
|
||||
|
||||
var/matrix/M = matrix()
|
||||
M.Translate(x_offset,y_offset)
|
||||
button.transform = M
|
||||
|
||||
//Presets for item actions
|
||||
/datum/action/item_action
|
||||
check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUNNED|AB_CHECK_LYING|AB_CHECK_ALIVE|AB_CHECK_INSIDE
|
||||
|
||||
/datum/action/item_action/CheckRemoval(mob/living/user)
|
||||
return !(target in user)
|
||||
|
||||
/datum/action/item_action/hands_free
|
||||
check_flags = AB_CHECK_ALIVE|AB_CHECK_INSIDE
|
||||
|
||||
#undef AB_WEST_OFFSET
|
||||
#undef AB_NORTH_OFFSET
|
||||
#undef AB_MAX_COLUMNS
|
||||
@@ -133,7 +133,8 @@ var/list/global_huds = list(
|
||||
var/list/other
|
||||
var/list/obj/screen/hotkeybuttons
|
||||
|
||||
var/list/obj/screen/item_action/item_action_list = list() //Used for the item action ui buttons.
|
||||
var/obj/screen/movable/action_button/hide_toggle/hide_actions_toggle
|
||||
var/action_buttons_hidden = 0
|
||||
|
||||
datum/hud/New(mob/owner)
|
||||
mymob = owner
|
||||
@@ -279,8 +280,6 @@ datum/hud/New(mob/owner)
|
||||
src.client.screen -= src.hud_used.other
|
||||
if(src.hud_used.hotkeybuttons)
|
||||
src.client.screen -= src.hud_used.hotkeybuttons
|
||||
if(src.hud_used.item_action_list)
|
||||
src.client.screen -= src.hud_used.item_action_list
|
||||
|
||||
//Due to some poor coding some things need special treatment:
|
||||
//These ones are a part of 'adding', 'other' or 'hotkeybuttons' but we want them to stay
|
||||
@@ -338,8 +337,6 @@ datum/hud/New(mob/owner)
|
||||
src.client.screen -= src.hud_used.other
|
||||
if(src.hud_used.hotkeybuttons)
|
||||
src.client.screen -= src.hud_used.hotkeybuttons
|
||||
if(src.hud_used.item_action_list)
|
||||
src.client.screen -= src.hud_used.item_action_list
|
||||
src.client.screen -= src.internals
|
||||
src.client.screen += src.hud_used.action_intent //we want the intent swticher visible
|
||||
else
|
||||
|
||||
@@ -385,52 +385,6 @@
|
||||
client.screen -= hud_used.hotkeybuttons
|
||||
hud_used.hotkey_ui_hidden = 1
|
||||
|
||||
|
||||
/mob/living/carbon/human/update_action_buttons()
|
||||
var/num = 1
|
||||
if(!hud_used) return
|
||||
if(!client) return
|
||||
|
||||
if(!hud_used.hud_shown) //Hud toggled to minimal
|
||||
return
|
||||
|
||||
client.screen -= hud_used.item_action_list
|
||||
|
||||
hud_used.item_action_list = list()
|
||||
for(var/obj/item/I in src)
|
||||
if(I.icon_action_button)
|
||||
var/obj/screen/item_action/A = new(hud_used)
|
||||
|
||||
//A.icon = 'icons/mob/screen1_action.dmi'
|
||||
//A.icon_state = I.icon_action_button
|
||||
A.icon = ui_style2icon(client.prefs.UI_style)
|
||||
A.icon_state = "template"
|
||||
var/image/img = image(I.icon, A, I.icon_state)
|
||||
img.pixel_x = 0
|
||||
img.pixel_y = 0
|
||||
A.overlays += img
|
||||
|
||||
if(I.action_button_name)
|
||||
A.name = I.action_button_name
|
||||
else
|
||||
A.name = "Use [I.name]"
|
||||
A.owner = I
|
||||
hud_used.item_action_list += A
|
||||
switch(num)
|
||||
if(1)
|
||||
A.screen_loc = ui_action_slot1
|
||||
if(2)
|
||||
A.screen_loc = ui_action_slot2
|
||||
if(3)
|
||||
A.screen_loc = ui_action_slot3
|
||||
if(4)
|
||||
A.screen_loc = ui_action_slot4
|
||||
if(5)
|
||||
A.screen_loc = ui_action_slot5
|
||||
break //5 slots available, so no more can be added.
|
||||
num++
|
||||
src.client.screen += src.hud_used.item_action_list
|
||||
|
||||
//Used for new human mobs created by cloning/goleming/etc.
|
||||
/mob/living/carbon/human/proc/set_cloned_appearance()
|
||||
f_style = "Shaved"
|
||||
|
||||
84
code/_onclick/hud/movable_screen_objects.dm
Normal file
84
code/_onclick/hud/movable_screen_objects.dm
Normal file
@@ -0,0 +1,84 @@
|
||||
//////////////////////////
|
||||
//Movable Screen Objects//
|
||||
// By RemieRichards //
|
||||
//////////////////////////
|
||||
|
||||
|
||||
//Movable Screen Object
|
||||
//Not tied to the grid, places it's center where the cursor is
|
||||
|
||||
/obj/screen/movable
|
||||
var/snap2grid = FALSE
|
||||
var/moved = FALSE
|
||||
|
||||
//Snap Screen Object
|
||||
//Tied to the grid, snaps to the nearest turf
|
||||
|
||||
/obj/screen/movable/snap
|
||||
snap2grid = TRUE
|
||||
|
||||
|
||||
/obj/screen/movable/MouseDrop(over_object, src_location, over_location, src_control, over_control, params)
|
||||
var/list/PM = params2list(params)
|
||||
|
||||
//No screen-loc information? abort.
|
||||
if(!PM || !PM["screen-loc"])
|
||||
return
|
||||
|
||||
//Split screen-loc up into X+Pixel_X and Y+Pixel_Y
|
||||
var/list/screen_loc_params = text2list(PM["screen-loc"], ",")
|
||||
|
||||
//Split X+Pixel_X up into list(X, Pixel_X)
|
||||
var/list/screen_loc_X = text2list(screen_loc_params[1],":")
|
||||
|
||||
//Split Y+Pixel_Y up into list(Y, Pixel_Y)
|
||||
var/list/screen_loc_Y = text2list(screen_loc_params[2],":")
|
||||
|
||||
if(snap2grid) //Discard Pixel Values
|
||||
screen_loc = "[screen_loc_X[1]],[screen_loc_Y[1]]"
|
||||
|
||||
else //Normalise Pixel Values (So the object drops at the center of the mouse, not 16 pixels off)
|
||||
var/pix_X = text2num(screen_loc_X[2]) - 16
|
||||
var/pix_Y = text2num(screen_loc_Y[2]) - 16
|
||||
screen_loc = "[screen_loc_X[1]]:[pix_X],[screen_loc_Y[1]]:[pix_Y]"
|
||||
|
||||
moved = TRUE
|
||||
|
||||
|
||||
//Debug procs
|
||||
/client/proc/test_movable_UI()
|
||||
set category = "Debug"
|
||||
set name = "Spawn Movable UI Object"
|
||||
|
||||
var/obj/screen/movable/M = new()
|
||||
M.name = "Movable UI Object"
|
||||
M.icon_state = "block"
|
||||
M.maptext = "Movable"
|
||||
M.maptext_width = 64
|
||||
|
||||
var/screen_l = input(usr,"Where on the screen? (Formatted as 'X,Y' e.g: '1,1' for bottom left)","Spawn Movable UI Object") as text
|
||||
if(!screen_l)
|
||||
return
|
||||
|
||||
M.screen_loc = screen_l
|
||||
|
||||
screen += M
|
||||
|
||||
|
||||
/client/proc/test_snap_UI()
|
||||
set category = "Debug"
|
||||
set name = "Spawn Snap UI Object"
|
||||
|
||||
var/obj/screen/movable/snap/S = new()
|
||||
S.name = "Snap UI Object"
|
||||
S.icon_state = "block"
|
||||
S.maptext = "Snap"
|
||||
S.maptext_width = 64
|
||||
|
||||
var/screen_l = input(usr,"Where on the screen? (Formatted as 'X,Y' e.g: '1,1' for bottom left)","Spawn Snap UI Object") as text
|
||||
if(!screen_l)
|
||||
return
|
||||
|
||||
S.screen_loc = screen_l
|
||||
|
||||
screen += S
|
||||
@@ -61,11 +61,6 @@
|
||||
owner.ui_action_click()
|
||||
return 1
|
||||
|
||||
//This is the proc used to update all the action buttons. It just returns for all mob types except humans.
|
||||
/mob/proc/update_action_buttons()
|
||||
return
|
||||
|
||||
|
||||
/obj/screen/grab
|
||||
name = "grab"
|
||||
|
||||
|
||||
@@ -34,23 +34,6 @@ attacked_by() will handle hitting/missing/logging as it does now, and will call
|
||||
|
||||
if(!istype(M) || (can_operate(M) && do_surgery(M,user,src))) return 0
|
||||
|
||||
// Knifing
|
||||
if(edge)
|
||||
for(var/obj/item/weapon/grab/G in M.grabbed_by)
|
||||
if(G.assailant == user && G.state >= GRAB_NECK && world.time >= (G.last_action + 20))
|
||||
//TODO: better alternative for applying damage multiple times? Nice knifing sound?
|
||||
M.apply_damage(20, BRUTE, "head", 0, sharp=sharp, edge=edge)
|
||||
M.apply_damage(20, BRUTE, "head", 0, sharp=sharp, edge=edge)
|
||||
M.apply_damage(20, BRUTE, "head", 0, sharp=sharp, edge=edge)
|
||||
M.adjustOxyLoss(60) // Brain lacks oxygen immediately, pass out
|
||||
flick(G.hud.icon_state, G.hud)
|
||||
G.last_action = world.time
|
||||
user.visible_message("<span class='danger'>[user] slit [M]'s throat open with \the [name]!</span>")
|
||||
user.attack_log += "\[[time_stamp()]\]<font color='red'> Knifed [M.name] ([M.ckey]) with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])</font>"
|
||||
M.attack_log += "\[[time_stamp()]\]<font color='orange'> Got knifed by [user.name] ([user.ckey]) with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])</font>"
|
||||
msg_admin_attack("[key_name(user)] knifed [key_name(M)] with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])" )
|
||||
return
|
||||
|
||||
/////////////////////////
|
||||
user.lastattacked = M
|
||||
M.lastattacker = user
|
||||
@@ -61,6 +44,12 @@ attacked_by() will handle hitting/missing/logging as it does now, and will call
|
||||
msg_admin_attack("[key_name(user)] attacked [key_name(M)] with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])" )
|
||||
/////////////////////////
|
||||
|
||||
// Attacking someone with a weapon while they are neck-grabbed
|
||||
if(user.a_intent == I_HURT)
|
||||
for(var/obj/item/weapon/grab/G in M.grabbed_by)
|
||||
if(G.assailant == user && G.state >= GRAB_NECK)
|
||||
M.attack_throat(src, G, user)
|
||||
|
||||
var/power = force
|
||||
if(HULK in user.mutations)
|
||||
power *= 2
|
||||
@@ -72,7 +61,7 @@ attacked_by() will handle hitting/missing/logging as it does now, and will call
|
||||
|
||||
// Handle striking to cripple.
|
||||
var/dislocation_str
|
||||
if(user.a_intent == "disarm")
|
||||
if(user.a_intent == I_DISARM)
|
||||
dislocation_str = H.attack_joint(src, user, def_zone)
|
||||
if(H.attacked_by(src, user, def_zone) && hitsound)
|
||||
playsound(loc, hitsound, 50, 1, -1)
|
||||
|
||||
Reference in New Issue
Block a user