diff --git a/code/_onclick/hud/_defines.dm b/code/_onclick/hud/_defines.dm
index 17616801b76..832a822202f 100644
--- a/code/_onclick/hud/_defines.dm
+++ b/code/_onclick/hud/_defines.dm
@@ -13,29 +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,16:26"
-#define ui_action_slot2 "2:8,16:26"
-#define ui_action_slot3 "3:10,16:26"
-#define ui_action_slot4 "4:12,16:26"
-#define ui_action_slot5 "5:14,16:26"
-#define ui_action_slot6 "6:16,16:26"
-#define ui_action_slot7 "7:18,16:26"
-#define ui_action_slot8 "8:20,16:26"
-#define ui_action_slot9 "9:22,16:26"
-#define ui_action_slot10 "10:24,16:26"
-
-#define ui_power_slot1 "1:6,15:24"
-#define ui_power_slot2 "2:8,15:24"
-#define ui_power_slot3 "3:10,15:24"
-#define ui_power_slot4 "4:12,15:24"
-#define ui_power_slot5 "5:14,15:24"
-#define ui_power_slot6 "6:16,15:24"
-#define ui_power_slot7 "7:18,15:24"
-#define ui_power_slot8 "8:20,15:24"
-#define ui_power_slot9 "9:22,15:24"
-#define ui_power_slot10 "10:24,15:24"
-
//Middle left indicators
#define ui_alienplasmadisplay "1,6:15"
diff --git a/code/_onclick/hud/action.dm b/code/_onclick/hud/action.dm
new file mode 100644
index 00000000000..c44db2eb120
--- /dev/null
+++ b/code/_onclick/hud/action.dm
@@ -0,0 +1,247 @@
+#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 = 4+2*col
+ var/coord_row = "[-1 - row]"
+ var/coord_row_offset = 26
+ 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) + 4 + 2*col
+ var/y_offset = -32*(row+1) + 26
+
+ 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
+
+
+//Preset for spells
+/datum/action/spell_action
+ action_type = AB_SPELL
+ check_flags = 0
+ background_icon_state = "bg_spell"
+
+/datum/action/spell_action/UpdateName()
+ var/obj/effect/proc_holder/spell/spell = target
+ return spell.name
+
+/datum/action/spell_action/IsAvailable()
+ if(!target)
+ return 0
+ var/obj/effect/proc_holder/spell/spell = target
+
+ if(usr)
+ return spell.can_cast(usr)
+ else
+ if(owner)
+ return spell.can_cast(owner)
+ return 1
+
+/datum/action/spell_action/CheckRemoval()
+ if(owner.mind)
+ if(target in owner.mind.spell_list)
+ return 0
+ return !(target in owner.spell_list)
\ No newline at end of file
diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm
index 9e64de0697b..dc93941ac6b 100644
--- a/code/_onclick/hud/hud.dm
+++ b/code/_onclick/hud/hud.dm
@@ -108,8 +108,8 @@ var/datum/global_hud/global_hud = new()
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/list/obj/screen/item_action/power_action_list = list() //Used for the power 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
@@ -218,8 +218,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
diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm
index 38aae40c51b..2fc752e3eaf 100644
--- a/code/_onclick/hud/human.dm
+++ b/code/_onclick/hud/human.dm
@@ -502,62 +502,4 @@
hud_used.hotkey_ui_hidden = 0
else
client.screen -= hud_used.hotkeybuttons
- hud_used.hotkey_ui_hidden = 1
-
-
-/mob/living/carbon/human/update_action_buttons()
- var/num = 1
- var/list/to_update = list()
- 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(istype(I,/obj/item/clothing/under))
- var/obj/item/clothing/under/U = I
- if(U.accessories)
- for(var/obj/item/clothing/accessory/AC in U.accessories)
- if(AC.icon_action_button)
- to_update += AC
- continue
- if(I.icon_action_button)
- to_update += I
- continue
-
- for(var/obj/item/I in to_update)
- 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
+ hud_used.hotkey_ui_hidden = 1
\ No newline at end of file
diff --git a/code/_onclick/hud/movable_screen_objects.dm b/code/_onclick/hud/movable_screen_objects.dm
new file mode 100644
index 00000000000..a0dc4827ba9
--- /dev/null
+++ b/code/_onclick/hud/movable_screen_objects.dm
@@ -0,0 +1,85 @@
+
+//////////////////////////
+//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
\ No newline at end of file
diff --git a/code/_onclick/hud/other_mobs.dm b/code/_onclick/hud/other_mobs.dm
index f84cfd6c232..fb2f7e8a27f 100644
--- a/code/_onclick/hud/other_mobs.dm
+++ b/code/_onclick/hud/other_mobs.dm
@@ -65,65 +65,4 @@
mymob.client.screen = null
- mymob.client.screen += list(blobpwrdisplay, blobhealthdisplay)
-
-
-/mob/proc/update_power_buttons() // These spell buttons will be used for all sorts of abilities from ghost abilities to simple_mob abilities. It shouldn't be human only
- var/num = 1
- if(!hud_used) return
- if(!client) return
-
- if(!hud_used.hud_shown) //Hud toggled to minimal
- return
-
- client.screen -= hud_used.power_action_list
-
- hud_used.power_action_list = list()
- for(var/obj/effect/proc_holder/spell/wizard/S in spell_list)
- if(S.icon_power_button)
- var/obj/screen/power_action/P = new(hud_used)
- P.icon = 'icons/mob/screen1_action.dmi'
- P.icon_state = S.icon_power_button
- if(S.charge_counter != S.charge_max)
- P.icon = 'icons/mob/screen1_action.dmi'
- P.icon_state = S.icon_power_button
- var/icon/newicon = new(P.icon, P.icon_state)
- newicon.GrayScale()
- P.icon = newicon
- else
- P.icon = 'icons/mob/screen1_action.dmi'
- P.icon_state = S.icon_power_button
-
-
- if(S.power_button_name)
- P.name = S.power_button_name
- else
- P.name = "Use [S.name]"
- P.owner = S
-
- hud_used.power_action_list += P
-
- switch(num)
- if(1)
- P.screen_loc = ui_power_slot1
- if(2)
- P.screen_loc = ui_power_slot2
- if(3)
- P.screen_loc = ui_power_slot3
- if(4)
- P.screen_loc = ui_power_slot4
- if(5)
- P.screen_loc = ui_power_slot5
- if(6)
- P.screen_loc = ui_power_slot6
- if(7)
- P.screen_loc = ui_power_slot7
- if(8)
- P.screen_loc = ui_power_slot8
- if(9)
- P.screen_loc = ui_power_slot9
- if(10)
- P.screen_loc = ui_power_slot10
- break //5 slots available, so no more can be added.
- num++
- src.client.screen += src.hud_used.power_action_list
\ No newline at end of file
+ mymob.client.screen += list(blobpwrdisplay, blobhealthdisplay)
\ No newline at end of file
diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm
index 813cc9f3f46..74692bd2aaf 100644
--- a/code/_onclick/hud/screen_objects.dm
+++ b/code/_onclick/hud/screen_objects.dm
@@ -38,36 +38,6 @@
S.close(usr)
return 1
-/obj/screen/power_action
- var/obj/effect/proc_holder/spell/wizard/owner
-
-/obj/screen/power_action/Click()
- owner.Click()
-
-/obj/screen/item_action
- var/obj/item/owner
-
-/obj/screen/item_action/Click()
- if(!usr || !owner)
- return 1
- if(usr.next_move >= world.time)
- return
-
- if(usr.stat || usr.restrained() || usr.stunned || usr.lying)
- return 1
-
-
- if(!(owner in usr) && !(owner.loc.loc == usr))
- return 1
-
-
- 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"
@@ -278,7 +248,7 @@
return 1
if(C.wear_mask.mask_adjusted)
C << "Put your mask on first."
- return 1
+ return 1
else
var/list/nicename = null
var/list/tankcheck = null
@@ -407,8 +377,8 @@
if("Toggle Sensor Augmentation")
if(isrobot(usr))
var/mob/living/silicon/robot/R = usr
- R.sensor_mode()
-
+ R.sensor_mode()
+
if("module1")
if(istype(usr, /mob/living/silicon/robot))
usr:toggle_module(1)
@@ -550,22 +520,22 @@
if(isAI(usr))
var/mob/living/silicon/ai/AI = usr
AI.aiCamera.viewpictures()
-
+
if("Set Sensor Augmentation")
if(isAI(usr))
var/mob/living/silicon/ai/AI = usr
AI.sensor_mode()
-
+
// Alien
if("night vision")
var/mob/living/carbon/alien/humanoid/A = usr
A.nightvisiontoggle()
-
+
if("toggle leap")
if(istype(usr, /mob/living/carbon/alien/humanoid))
var/mob/living/carbon/alien/humanoid/hunter/AH = usr
AH.toggle_leap()
-
+
else
return 0
return 1
diff --git a/code/datums/mind.dm b/code/datums/mind.dm
index 268f0b4d02b..08a735648a7 100644
--- a/code/datums/mind.dm
+++ b/code/datums/mind.dm
@@ -41,6 +41,8 @@ datum/mind
var/assigned_role
var/special_role
+ var/list/spell_list = list() // Wizard mode & "Give Spell" badmin button.
+
var/role_alt_title
var/datum/job/assigned_job
@@ -79,6 +81,7 @@ datum/mind
current = new_character //link ourself to our new body
new_character.mind = src //and link our new body to ourself
+ transfer_actions(new_character)
if(active)
new_character.key = key //now transfer the key to link the client to our new body
@@ -1345,6 +1348,36 @@ datum/mind
return (duration <= world.time - brigged_since)
+/datum/mind/proc/AddSpell(var/obj/effect/proc_holder/spell/spell)
+ spell_list += spell
+ if(!spell.action)
+ spell.action = new/datum/action/spell_action
+ spell.action.target = spell
+ spell.action.name = spell.name
+ spell.action.button_icon = spell.action_icon
+ spell.action.button_icon_state = spell.action_icon_state
+ spell.action.background_icon_state = spell.action_background_icon_state
+ spell.action.Grant(current)
+ return
+
+/datum/mind/proc/transfer_actions(var/mob/living/new_character)
+ if(current && current.actions)
+ for(var/datum/action/A in current.actions)
+ A.Grant(new_character)
+ transfer_mindbound_actions(new_character)
+
+/datum/mind/proc/transfer_mindbound_actions(var/mob/living/new_character)
+ for(var/obj/effect/proc_holder/spell/spell in spell_list)
+ if(!spell.action) // Unlikely but whatever
+ spell.action = new/datum/action/spell_action
+ spell.action.target = spell
+ spell.action.name = spell.name
+ spell.action.button_icon = spell.action_icon
+ spell.action.button_icon_state = spell.action_icon_state
+ spell.action.background_icon_state = spell.action_background_icon_state
+ spell.action.Grant(new_character)
+ return
+
//Initialisation procs
/mob/proc/mind_initialize()
if(mind)
diff --git a/code/datums/spell.dm b/code/datums/spell.dm
index 7aeee98f92e..dbe98647575 100644
--- a/code/datums/spell.dm
+++ b/code/datums/spell.dm
@@ -48,12 +48,14 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin
var/critfailchance = 0
var/centcom_cancast = 1 //Whether or not the spell should be allowed on z2
- var/icon_power_button
- var/power_button_name
+ var/datum/action/spell_action/action = null
+ var/action_icon = 'icons/mob/actions.dmi'
+ var/action_icon_state = "spell_default"
+ var/action_background_icon_state = "bg_spell"
/obj/effect/proc_holder/spell/wizard/proc/cast_check(skipcharge = 0, mob/living/user = usr) //checks if the spell can be cast based on its settings; skipcharge is used when an additional cast_check is called inside the spell
- if(!(src in user.spell_list))
+ if(((!user.mind) || !(src in user.mind.spell_list)) && !(src in user.spell_list))
user << "You shouldn't have this spell! Something's wrong."
return 0
if (istype(user, /mob/living/carbon/human))
@@ -142,7 +144,6 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin
while(charge_counter < charge_max)
sleep(1)
charge_counter++
- usr.update_power_buttons()
/obj/effect/proc_holder/spell/wizard/proc/perform(list/targets, recharge = 1, mob/user = usr) //if recharge is started is important for the trigger spells
before_cast(targets)
@@ -195,7 +196,6 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin
var/datum/effect/effect/system/bad_smoke_spread/smoke = new /datum/effect/effect/system/bad_smoke_spread()
smoke.set_up(smoke_amt, 0, location) //no idea what the 0 is
smoke.start()
- usr.update_power_buttons()
/obj/effect/proc_holder/spell/wizard/proc/cast(list/targets)
return
@@ -337,4 +337,50 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin
qdel(dummy)
return 0
qdel(dummy)
+ return 1
+
+/obj/effect/proc_holder/spell/proc/can_cast(mob/user = usr)
+ if(((!user.mind) || !(src in user.mind.spell_list)) && !(src in user.spell_list))
+ return 0
+
+ if(user.z == 2 && !centcom_cancast) //Certain spells are not allowed on the centcom zlevel
+ return 0
+ if(user.z == 2 && ticker.mode.name == "ragin' mages")
+ return 0
+
+ switch(charge_type)
+ if("recharge")
+ if(charge_counter < charge_max)
+ return 0
+ if("charges")
+ if(!charge_counter)
+ return 0
+
+ if(user.stat && !stat_allowed)
+ return 0
+
+ if(ishuman(user))
+
+ var/mob/living/carbon/human/H = user
+
+ if((invocation_type == "whisper" || invocation_type == "shout") && H.is_muzzled())
+ return 0
+
+ var/obj/effect/proc_holder/spell/wizard/noclothes/clothcheck = locate() in user.spell_list
+ var/obj/effect/proc_holder/spell/wizard/noclothes/clothcheck2 = locate() in user.mind.spell_list
+ if(clothes_req && !(clothcheck && istype(clothcheck)) && !(clothcheck2 && istype(clothcheck2)))//clothes check
+ if(!istype(H.wear_suit, /obj/item/clothing/suit/wizrobe) && !istype(H.wear_suit, /obj/item/clothing/suit/space/rig/wizard))
+ user << "I don't feel strong enough without my robe."
+ return 0
+ if(!istype(H.shoes, /obj/item/clothing/shoes/sandal))
+ user << "I don't feel strong enough without my sandals."
+ return 0
+ if(!istype(H.head, /obj/item/clothing/head/wizard) && !istype(H.head, /obj/item/clothing/head/helmet/space/rig/wizard))
+ user << "I don't feel strong enough without my hat."
+ return 0
+ else
+ if(clothes_req)
+ return 0
+ if(isbrain(user) || ispAI(user))
+ return 0
return 1
\ No newline at end of file
diff --git a/code/datums/spells/area_teleport.dm b/code/datums/spells/area_teleport.dm
index a623b5a967e..985dc76acba 100644
--- a/code/datums/spells/area_teleport.dm
+++ b/code/datums/spells/area_teleport.dm
@@ -4,7 +4,6 @@
var/randomise_selection = 0 //if it lets the usr choose the teleport loc or picks it from the list
var/invocation_area = 1 //if the invocation appends the selected area
-
/obj/effect/proc_holder/spell/wizard/targeted/area_teleport/perform(list/targets, recharge = 1)
var/thearea = before_cast(targets)
if(!thearea || !cast_check(1))
diff --git a/code/datums/spells/emplosion.dm b/code/datums/spells/emplosion.dm
index 44636d00303..87aafaa85d8 100644
--- a/code/datums/spells/emplosion.dm
+++ b/code/datums/spells/emplosion.dm
@@ -5,6 +5,8 @@
var/emp_heavy = 2
var/emp_light = 3
+ action_icon_state = "emp"
+
/obj/effect/proc_holder/spell/wizard/targeted/emplosion/cast(list/targets)
for(var/mob/living/target in targets)
diff --git a/code/datums/spells/ethereal_jaunt.dm b/code/datums/spells/ethereal_jaunt.dm
index fc8ac705369..878aeea8dcd 100644
--- a/code/datums/spells/ethereal_jaunt.dm
+++ b/code/datums/spells/ethereal_jaunt.dm
@@ -15,7 +15,7 @@
var phaseshift = 0
var/jaunt_duration = 50 //in deciseconds
- icon_power_button = "spell_jaunt"
+ action_icon_state = "jaunt"
/obj/effect/proc_holder/spell/wizard/targeted/ethereal_jaunt/cast(list/targets) //magnets, so mostly hardcoded
for(var/mob/living/target in targets)
diff --git a/code/datums/spells/fake_gib.dm b/code/datums/spells/fake_gib.dm
index 275bdef67bf..1b196d970ee 100644
--- a/code/datums/spells/fake_gib.dm
+++ b/code/datums/spells/fake_gib.dm
@@ -14,4 +14,4 @@
sparks_spread = 3
sparks_amt = 1
- icon_power_button = "spell_disintegrate"
\ No newline at end of file
+ action_icon_state = "spell_disintegrate"
\ No newline at end of file
diff --git a/code/datums/spells/horsemask.dm b/code/datums/spells/horsemask.dm
index 5f45dc41aaa..d8f7fec621e 100644
--- a/code/datums/spells/horsemask.dm
+++ b/code/datums/spells/horsemask.dm
@@ -14,7 +14,7 @@
selection_type = "range"
var/list/compatible_mobs = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
- icon_power_button = "spell_horse"
+ action_icon_state = "spell_horse"
/obj/effect/proc_holder/spell/wizard/targeted/horsemask/cast(list/targets, mob/user = usr)
if(!targets.len)
diff --git a/code/datums/spells/knock.dm b/code/datums/spells/knock.dm
index 98d1b3b0fa9..8d3d4026b7d 100644
--- a/code/datums/spells/knock.dm
+++ b/code/datums/spells/knock.dm
@@ -10,7 +10,7 @@
range = 3
cooldown_min = 20 //20 deciseconds reduction per rank
- icon_power_button = "spell_knock"
+ action_icon_state = "knock"
/obj/effect/proc_holder/spell/wizard/aoe_turf/knock/cast(list/targets)
for(var/turf/T in targets)
diff --git a/code/datums/spells/lightning.dm b/code/datums/spells/lightning.dm
index 32c30d777c6..0778be8cd2d 100644
--- a/code/datums/spells/lightning.dm
+++ b/code/datums/spells/lightning.dm
@@ -13,7 +13,7 @@
var/energy = 0
var/ready = 0
var/image/halo = null
- icon_power_button = "spell_tech"
+ action_icon_state = "lightning"
/obj/effect/proc_holder/spell/wizard/targeted/lightning/lightnian
clothes_req = 0
diff --git a/code/datums/spells/magnet.dm b/code/datums/spells/magnet.dm
index dbb4b572bbc..243ef9957c7 100644
--- a/code/datums/spells/magnet.dm
+++ b/code/datums/spells/magnet.dm
@@ -13,7 +13,7 @@
var/energy = 0
var/ready = 0
var/image/halo = null
- icon_power_button = "spell_tech"
+ action_icon_state = "tech"
/obj/effect/proc_holder/spell/wizard/targeted/magnet/Click()
diff --git a/code/datums/spells/mind_transfer.dm b/code/datums/spells/mind_transfer.dm
index 389091da2c8..b10d7b17e47 100644
--- a/code/datums/spells/mind_transfer.dm
+++ b/code/datums/spells/mind_transfer.dm
@@ -12,7 +12,7 @@
var/list/protected_roles = list("Wizard","Changeling","Cultist") //which roles are immune to the spell
var/paralysis_amount_caster = 20 //how much the caster is paralysed for after the spell
var/paralysis_amount_victim = 20 //how much the victim is paralysed for after the spell
- icon_power_button = "spell_mind"
+ action_icon_state = "mindswap"
/*
Urist: I don't feel like figuring out how you store object spells so I'm leaving this for you to do.
diff --git a/code/datums/spells/summonitem.dm b/code/datums/spells/summonitem.dm
index da1a2aeb6d9..259f51a0930 100644
--- a/code/datums/spells/summonitem.dm
+++ b/code/datums/spells/summonitem.dm
@@ -13,6 +13,8 @@
var/obj/marked_item
+ action_icon_state = "summons"
+
/obj/effect/proc_holder/spell/wizard/targeted/summonitem/cast(list/targets)
for(var/mob/living/user in targets)
var/list/hand_items = list(user.get_active_hand(),user.get_inactive_hand())
diff --git a/code/datums/spells/wizard.dm b/code/datums/spells/wizard.dm
index ae507556181..7d503cc357d 100644
--- a/code/datums/spells/wizard.dm
+++ b/code/datums/spells/wizard.dm
@@ -24,7 +24,7 @@
proj_trail_lifespan = 5
proj_trail_icon_state = "magicmd"
- icon_power_button = "spell_missile"
+ action_icon_state = "magicm"
/obj/effect/proc_holder/spell/wizard/targeted/inflict_handler/magic_missile
amt_weakened = 3
@@ -52,6 +52,8 @@
duration = 300
cooldown_min = 300 //25 deciseconds reduction per rank
+ action_icon_state = "mutate"
+
/obj/effect/proc_holder/spell/wizard/targeted/inflict_handler/disintegrate
name = "Disintegrate"
desc = "This spell instantly kills somebody adjacent to you with the vilest of magick."
@@ -69,7 +71,7 @@
sparks_spread = 1
sparks_amt = 4
- icon_power_button = "spell_disintegrate"
+ action_icon_state = "gib"
/obj/effect/proc_holder/spell/wizard/targeted/smoke
name = "Smoke"
@@ -87,7 +89,7 @@
smoke_spread = 2
smoke_amt = 10
- icon_power_button = "spell_smoke"
+ action_icon_state = "smoke"
/obj/effect/proc_holder/spell/wizard/targeted/emplosion/disable_tech
name = "Disable Tech"
@@ -103,7 +105,7 @@
emp_heavy = 6
emp_light = 10
- icon_power_button = "spell_tech"
+ action_icon_state = "tech"
/obj/effect/proc_holder/spell/wizard/targeted/turf_teleport/blink
name = "Blink"
@@ -127,7 +129,7 @@
centcom_cancast = 0 //prevent people from getting to centcom
- icon_power_button = "spell_blink"
+ action_icon_state = "blink"
/obj/effect/proc_holder/spell/wizard/targeted/area_teleport/teleport
name = "Teleport"
@@ -145,7 +147,7 @@
smoke_spread = 1
smoke_amt = 5
- icon_power_button = "spell_teleport"
+ action_icon_state = "teleport"
/obj/effect/proc_holder/spell/wizard/aoe_turf/conjure/forcewall
name = "Forcewall"
@@ -162,7 +164,7 @@
summon_type = list("/obj/effect/forcefield")
summon_lifespan = 300
- icon_power_button = "spell_forcewall"
+ action_icon_state = "shield"
/obj/effect/proc_holder/spell/wizard/aoe_turf/conjure/carp
name = "Summon Carp"
@@ -191,6 +193,7 @@
summon_type = list(/obj/structure/constructshell)
+ action_icon_state = "artificer"
/obj/effect/proc_holder/spell/wizard/aoe_turf/conjure/creature
name = "Summon Creature Swarm"
@@ -220,7 +223,7 @@
starting_spells = list("/obj/effect/proc_holder/spell/wizard/targeted/inflict_handler/blind","/obj/effect/proc_holder/spell/wizard/targeted/genetic/blind")
- icon_power_button = "spell_blind"
+ action_icon_state = "blind"
/obj/effect/proc_holder/spell/wizard/targeted/inflict_handler/blind
amt_eye_blind = 10
@@ -245,7 +248,7 @@
summon_type = "/obj/structure/closet/statue"
- icon_power_button = "spell_stone"
+ action_icon_state = "statue"
/obj/effect/proc_holder/spell/wizard/dumbfire/fireball
name = "Fireball"
@@ -266,7 +269,7 @@
proj_lifespan = 200
proj_step_delay = 1
- icon_power_button = "spell_fireball"
+ action_icon_state = "fireball"
/obj/effect/proc_holder/spell/wizard/turf/fireball/cast(var/turf/T)
explosion(T, -1, 0, 2, 3, 0)
@@ -293,6 +296,8 @@
selection_type = "view"
var/maxthrow = 5
+ action_icon_state = "repulse"
+
/obj/effect/proc_holder/spell/wizard/aoe_turf/repulse/cast(list/targets)
var/mob/user = usr
var/list/thrownatoms = list()
diff --git a/code/game/dna/genes/gene.dm b/code/game/dna/genes/gene.dm
index 1d521dc6b4f..87dbf20108e 100644
--- a/code/game/dna/genes/gene.dm
+++ b/code/game/dna/genes/gene.dm
@@ -117,11 +117,9 @@
if(activation_messages.len)
var/msg = pick(activation_messages)
M << "\blue [msg]"
- M.update_power_buttons()
/datum/dna/gene/basic/deactivate(var/mob/M)
M.mutations.Remove(mutation)
if(deactivation_messages.len)
var/msg = pick(deactivation_messages)
- M << "\red [msg]"
- M.update_power_buttons()
\ No newline at end of file
+ M << "\red [msg]"
\ No newline at end of file
diff --git a/code/game/dna/genes/goon_disabilities.dm b/code/game/dna/genes/goon_disabilities.dm
index 3e355212d0e..9d22fff859b 100644
--- a/code/game/dna/genes/goon_disabilities.dm
+++ b/code/game/dna/genes/goon_disabilities.dm
@@ -318,7 +318,7 @@
var/list/compatible_mobs = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
include_user = 0
- icon_power_button = "genetic_incendiary"
+ action_icon_state = "genetic_incendiary"
/obj/effect/proc_holder/spell/wizard/targeted/immolate/cast(list/targets)
diff --git a/code/game/dna/genes/goon_powers.dm b/code/game/dna/genes/goon_powers.dm
index a98313eefdb..127028dd126 100644
--- a/code/game/dna/genes/goon_powers.dm
+++ b/code/game/dna/genes/goon_powers.dm
@@ -84,7 +84,7 @@
var/obj/effect/proc_holder/spell/wizard/spelltype
activate(var/mob/M, var/connected, var/flags)
- M.spell_list += new spelltype(M)
+ M.AddSpell(new spelltype(M))
..()
return 1
@@ -138,7 +138,7 @@
// centcomm_cancast = 0
var/list/compatible_mobs = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
- icon_power_button = "genetic_cryo"
+ action_icon_state = "genetic_cryo"
/obj/effect/proc_holder/spell/wizard/targeted/cryokinesis/cast(list/targets)
if(!targets.len)
@@ -232,7 +232,7 @@
range = 1
selection_type = "view"
- icon_power_button = "genetic_eat"
+ action_icon_state = "genetic_eat"
var/list/types_allowed=list(/obj/item,/mob/living/simple_animal, /mob/living/carbon/monkey, /mob/living/carbon/human)
@@ -354,7 +354,7 @@
stat_allowed = 0
invocation_type = "none"
- icon_power_button = "genetic_jump"
+ action_icon_state = "genetic_jump"
/obj/effect/proc_holder/spell/wizard/targeted/leap/cast(list/targets)
var/failure = 0
@@ -451,7 +451,7 @@
range = 1
selection_type = "range"
- icon_power_button = "genetic_poly"
+ action_icon_state = "genetic_poly"
/obj/effect/proc_holder/spell/wizard/targeted/polymorph/cast(list/targets)
var/mob/living/M=targets[1]
@@ -499,7 +499,7 @@
range = -2
selection_type = "range"
- icon_power_button = "genetic_empath"
+ action_icon_state = "genetic_empath"
/obj/effect/proc_holder/spell/wizard/targeted/empath/choose_targets(mob/user = usr)
var/list/targets = new /list()
diff --git a/code/game/dna/genes/vg_powers.dm b/code/game/dna/genes/vg_powers.dm
index f0a5d1dbd18..7410abd2445 100644
--- a/code/game/dna/genes/vg_powers.dm
+++ b/code/game/dna/genes/vg_powers.dm
@@ -66,7 +66,7 @@ Obviously, requires DNA2.
invocation_type = "none"
- icon_power_button = "genetic_hulk"
+ action_icon_state = "genetic_hulk"
/obj/effect/proc_holder/spell/wizard/targeted/hulk/New()
desc = "Get mad! For [HULK_DURATION/10] seconds, anyway."
@@ -118,7 +118,7 @@ Obviously, requires DNA2.
include_user = 1
selection_type = "range"
- icon_power_button = "genetic_morph"
+ action_icon_state = "genetic_morph"
/obj/effect/proc_holder/spell/wizard/targeted/morph/cast(list/targets)
if(!ishuman(usr)) return
@@ -217,7 +217,7 @@ Obviously, requires DNA2.
range = -2
selection_type = "range"
- icon_power_button = "genetic_project"
+ action_icon_state = "genetic_project"
/obj/effect/proc_holder/spell/wizard/targeted/remotetalk/choose_targets(mob/user = usr)
var/list/targets = new /list()
@@ -277,7 +277,7 @@ Obviously, requires DNA2.
range = -2
selection_type = "range"
- icon_power_button = "genetic_view"
+ action_icon_state = "genetic_view"
/obj/effect/proc_holder/spell/wizard/targeted/remoteview/choose_targets(mob/user = usr)
var/list/targets = living_mob_list
diff --git a/code/game/gamemodes/shadowling/shadowling.dm b/code/game/gamemodes/shadowling/shadowling.dm
index 1f6d926520f..bf7a19b5bbf 100644
--- a/code/game/gamemodes/shadowling/shadowling.dm
+++ b/code/game/gamemodes/shadowling/shadowling.dm
@@ -137,7 +137,7 @@ Made by Xhuis
/datum/game_mode/proc/finalize_shadowling(var/datum/mind/shadow_mind)
var/mob/living/carbon/human/S = shadow_mind.current
shadow_mind.current.verbs += /mob/living/carbon/human/proc/shadowling_hatch
- S.spell_list += new /obj/effect/proc_holder/spell/wizard/targeted/enthrall
+ S.mind.AddSpell(new /obj/effect/proc_holder/spell/wizard/targeted/enthrall)
spawn(0)
shadow_mind.current.add_language("Shadowling Hivemind")
update_shadow_icons_added(shadow_mind)
diff --git a/code/game/gamemodes/shadowling/shadowling_abilities.dm b/code/game/gamemodes/shadowling/shadowling_abilities.dm
index f59c579f969..f0f68094056 100644
--- a/code/game/gamemodes/shadowling/shadowling_abilities.dm
+++ b/code/game/gamemodes/shadowling/shadowling_abilities.dm
@@ -255,23 +255,23 @@
blind_smoke_acquired = 1
user << "The power of your thralls has granted you the Blinding Smoke ability. It will create a choking cloud that will blind any non-thralls who enter. \
"
- user.spell_list += new /obj/effect/proc_holder/spell/wizard/targeted/blindness_smoke
+ user.mind.AddSpell(new /obj/effect/proc_holder/spell/wizard/targeted/blindness_smoke)
if(thralls >= 5 && !drain_thrall_acquired)
drain_thrall_acquired = 1
user << "The power of your thralls has granted you the Drain Thrall ability. You can now drain nearby thralls to heal yourself."
- user.spell_list += new /obj/effect/proc_holder/spell/wizard/aoe_turf/drain_thralls
+ user.mind.AddSpell(new /obj/effect/proc_holder/spell/wizard/aoe_turf/drain_thralls)
if(thralls >= 7 && !screech_acquired)
screech_acquired = 1
user << "The power of your thralls has granted you the Sonic Screech ability. This ability will shatter nearby windows and deafen enemies."
- user.spell_list += new /obj/effect/proc_holder/spell/wizard/aoe_turf/unearthly_screech
+ user.mind.AddSpell(new /obj/effect/proc_holder/spell/wizard/aoe_turf/unearthly_screech)
if(thralls >= 9 && !thrall_swap_acquired)
thrall_swap_acquired = 1
user << "The power of your thralls has granted you the Spatial Relocation ability. This will, allow you to instantly swap places with one of your thralls in \
addition to shattering nearby lights."
- user.spell_list += new /obj/effect/proc_holder/spell/wizard/targeted/spatial_relocation
+ user.mind.AddSpell(new /obj/effect/proc_holder/spell/wizard/targeted/spatial_relocation)
if(thralls < victory_threshold)
user << "You do not have the power to ascend. You require [victory_threshold] thralls, but only [thralls] living thralls are present."
diff --git a/code/game/gamemodes/shadowling/special_shadowling_abilities.dm b/code/game/gamemodes/shadowling/special_shadowling_abilities.dm
index 42d7a5d04eb..1f88f350c4c 100644
--- a/code/game/gamemodes/shadowling/special_shadowling_abilities.dm
+++ b/code/game/gamemodes/shadowling/special_shadowling_abilities.dm
@@ -81,11 +81,11 @@
sleep(10)
usr << "Your powers are awoken. You may now live to your fullest extent. Remember your goal. Cooperate with your thralls and allies."
- usr.spell_list += new /obj/effect/proc_holder/spell/wizard/targeted/glare
- usr.spell_list += new /obj/effect/proc_holder/spell/wizard/aoe_turf/veil
- usr.spell_list += new /obj/effect/proc_holder/spell/wizard/targeted/shadow_walk
- usr.spell_list += new /obj/effect/proc_holder/spell/wizard/aoe_turf/flashfreeze
- usr.spell_list += new /obj/effect/proc_holder/spell/wizard/targeted/collective_mind
+ usr.mind.AddSpell(new /obj/effect/proc_holder/spell/wizard/targeted/glare)
+ usr.mind.AddSpell(new /obj/effect/proc_holder/spell/wizard/aoe_turf/veil)
+ usr.mind.AddSpell(new /obj/effect/proc_holder/spell/wizard/targeted/shadow_walk)
+ usr.mind.AddSpell(new /obj/effect/proc_holder/spell/wizard/aoe_turf/flashfreeze)
+ usr.mind.AddSpell(new /obj/effect/proc_holder/spell/wizard/targeted/collective_mind)
@@ -143,11 +143,11 @@
A.overload_lighting()
var/mob/A = new /mob/living/simple_animal/ascendant_shadowling(usr.loc)
usr.spell_list = list()
- usr.spell_list += new /obj/effect/proc_holder/spell/wizard/targeted/annihilate
- usr.spell_list += new /obj/effect/proc_holder/spell/wizard/targeted/hypnosis
- usr.spell_list += new /obj/effect/proc_holder/spell/wizard/targeted/shadowling_phase_shift
- usr.spell_list += new /obj/effect/proc_holder/spell/wizard/aoe_turf/glacial_blast
- usr.spell_list += new /obj/effect/proc_holder/spell/wizard/targeted/vortex
+ usr.mind.AddSpell(new /obj/effect/proc_holder/spell/wizard/targeted/annihilate)
+ usr.mind.AddSpell(new /obj/effect/proc_holder/spell/wizard/targeted/hypnosis)
+ usr.mind.AddSpell(new /obj/effect/proc_holder/spell/wizard/targeted/shadowling_phase_shift)
+ usr.mind.AddSpell(new /obj/effect/proc_holder/spell/wizard/aoe_turf/glacial_blast)
+ usr.mind.AddSpell(new /obj/effect/proc_holder/spell/wizard/targeted/vortex)
usr.mind.transfer_to(A)
A.spell_list = usr.spell_list
A.name = usr.real_name
diff --git a/code/game/gamemodes/wizard/artefact.dm b/code/game/gamemodes/wizard/artefact.dm
index 4c185e8f628..d4c1841a507 100644
--- a/code/game/gamemodes/wizard/artefact.dm
+++ b/code/game/gamemodes/wizard/artefact.dm
@@ -59,23 +59,23 @@
M << "You are the [H.real_name]'s apprentice! You are bound by magic contract to follow their orders and help them in accomplishing their goals."
switch(href_list["school"])
if("destruction")
- M.spell_list += new /obj/effect/proc_holder/spell/wizard/targeted/projectile/magic_missile(M)
- M.spell_list += new /obj/effect/proc_holder/spell/wizard/dumbfire/fireball(M)
+ M.mind.AddSpell(new /obj/effect/proc_holder/spell/wizard/targeted/projectile/magic_missile(M))
+ M.mind.AddSpell(new /obj/effect/proc_holder/spell/wizard/dumbfire/fireball(M))
M << "Your service has not gone unrewarded, however. Studying under [H.real_name], you have learned powerful, destructive spells. You are able to cast magic missile and fireball."
if("bluespace")
- M.spell_list += new /obj/effect/proc_holder/spell/wizard/targeted/area_teleport/teleport(M)
- M.spell_list += new /obj/effect/proc_holder/spell/wizard/targeted/ethereal_jaunt(M)
+ M.mind.AddSpell(new /obj/effect/proc_holder/spell/wizard/targeted/area_teleport/teleport(M))
+ M.mind.AddSpell(new /obj/effect/proc_holder/spell/wizard/targeted/ethereal_jaunt(M))
M << "Your service has not gone unrewarded, however. Studying under [H.real_name], you have learned reality bending mobility spells. You are able to cast teleport and ethereal jaunt."
if("healing")
- M.spell_list += new /obj/effect/proc_holder/spell/wizard/targeted/charge(M)
- M.spell_list += new /obj/effect/proc_holder/spell/wizard/aoe_turf/conjure/forcewall(M)
+ M.mind.AddSpell(new /obj/effect/proc_holder/spell/wizard/targeted/charge(M))
+ M.mind.AddSpell(new /obj/effect/proc_holder/spell/wizard/aoe_turf/conjure/forcewall(M))
M.equip_to_slot_or_del(new /obj/item/weapon/gun/magic/staff/healing(M), slot_r_hand)
M << "Your service has not gone unrewarded, however. Studying under [H.real_name], you have learned livesaving survival spells. You are able to cast charge and forcewall."
if("robeless")
- M.spell_list += new /obj/effect/proc_holder/spell/wizard/aoe_turf/knock(M)
- M.spell_list += new /obj/effect/proc_holder/spell/wizard/targeted/mind_transfer(M)
+ M.mind.AddSpell(new /obj/effect/proc_holder/spell/wizard/aoe_turf/knock(M))
+ M.mind.AddSpell(new /obj/effect/proc_holder/spell/wizard/targeted/mind_transfer(M))
M << "Your service has not gone unrewarded, however. Studying under [H.real_name], you have learned stealthy, robeless spells. You are able to cast knock and mindswap."
- M.update_power_buttons()
+
M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_l_ear)
M.equip_to_slot_or_del(new /obj/item/clothing/under/color/lightpurple(M), slot_w_uniform)
M.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(M), slot_shoes)
diff --git a/code/game/gamemodes/wizard/spellbook.dm b/code/game/gamemodes/wizard/spellbook.dm
index 486a65763fc..a203fa197d3 100644
--- a/code/game/gamemodes/wizard/spellbook.dm
+++ b/code/game/gamemodes/wizard/spellbook.dm
@@ -241,80 +241,80 @@
switch(href_list["spell_choice"])
if("noclothes")
feedback_add_details("wizard_spell_learned","NC")
- H.spell_list += new /obj/effect/proc_holder/spell/wizard/noclothes
+ H.mind.AddSpell(new /obj/effect/proc_holder/spell/wizard/noclothes)
temp = "This teaches you how to use your spells without your magical garb, truely you are the wizardest."
uses--
if("magicmissile")
feedback_add_details("wizard_spell_learned","MM") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
- H.spell_list += new /obj/effect/proc_holder/spell/wizard/targeted/projectile/magic_missile(H)
+ H.mind.AddSpell(new /obj/effect/proc_holder/spell/wizard/targeted/projectile/magic_missile(H))
temp = "You have learned magic missile."
if("fireball")
feedback_add_details("wizard_spell_learned","FB") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
- H.spell_list += new /obj/effect/proc_holder/spell/wizard/dumbfire/fireball(H)
+ H.mind.AddSpell(new /obj/effect/proc_holder/spell/wizard/dumbfire/fireball(H))
temp = "You have learned fireball."
if("disintegrate")
feedback_add_details("wizard_spell_learned","DG") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
- H.spell_list += new /obj/effect/proc_holder/spell/wizard/targeted/inflict_handler/disintegrate(H)
+ H.mind.AddSpell(new /obj/effect/proc_holder/spell/wizard/targeted/inflict_handler/disintegrate(H))
temp = "You have learned disintegrate."
if("disabletech")
feedback_add_details("wizard_spell_learned","DT") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
- H.spell_list += new /obj/effect/proc_holder/spell/wizard/targeted/emplosion/disable_tech(H)
+ H.mind.AddSpell(new /obj/effect/proc_holder/spell/wizard/targeted/emplosion/disable_tech(H))
temp = "You have learned disable technology."
if("repulse")
feedback_add_details("wizard_spell_learned","RP") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
- H.spell_list += new /obj/effect/proc_holder/spell/wizard/aoe_turf/repulse(null)
+ H.mind.AddSpell(new /obj/effect/proc_holder/spell/wizard/aoe_turf/repulse(null))
temp = "You have learned repulse."
if("smoke")
feedback_add_details("wizard_spell_learned","SM") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
- H.spell_list += new /obj/effect/proc_holder/spell/wizard/targeted/smoke(H)
+ H.mind.AddSpell(new /obj/effect/proc_holder/spell/wizard/targeted/smoke(H))
temp = "You have learned smoke."
if("blind")
feedback_add_details("wizard_spell_learned","BD") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
- H.spell_list += new /obj/effect/proc_holder/spell/wizard/targeted/trigger/blind(H)
+ H.mind.AddSpell(new /obj/effect/proc_holder/spell/wizard/targeted/trigger/blind(H))
temp = "You have learned blind."
if("mindswap")
feedback_add_details("wizard_spell_learned","MT") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
- H.spell_list += new /obj/effect/proc_holder/spell/wizard/targeted/mind_transfer(H)
+ H.mind.AddSpell(new /obj/effect/proc_holder/spell/wizard/targeted/mind_transfer(H))
temp = "You have learned mindswap."
if("forcewall")
feedback_add_details("wizard_spell_learned","FW") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
- H.spell_list += new /obj/effect/proc_holder/spell/wizard/aoe_turf/conjure/forcewall(H)
+ H.mind.AddSpell(new /obj/effect/proc_holder/spell/wizard/aoe_turf/conjure/forcewall(H))
temp = "You have learned forcewall."
if("blink")
feedback_add_details("wizard_spell_learned","BL") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
- H.spell_list += new /obj/effect/proc_holder/spell/wizard/targeted/turf_teleport/blink(H)
+ H.mind.AddSpell(new /obj/effect/proc_holder/spell/wizard/targeted/turf_teleport/blink(H))
temp = "You have learned blink."
if("teleport")
feedback_add_details("wizard_spell_learned","TP") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
- H.spell_list += new /obj/effect/proc_holder/spell/wizard/targeted/area_teleport/teleport(H)
+ H.mind.AddSpell(new /obj/effect/proc_holder/spell/wizard/targeted/area_teleport/teleport(H))
temp = "You have learned teleport."
if("mutate")
feedback_add_details("wizard_spell_learned","MU") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
- H.spell_list += new /obj/effect/proc_holder/spell/wizard/targeted/genetic/mutate(H)
+ H.mind.AddSpell(new /obj/effect/proc_holder/spell/wizard/targeted/genetic/mutate(H))
temp = "You have learned mutate."
if("etherealjaunt")
feedback_add_details("wizard_spell_learned","EJ") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
- H.spell_list += new /obj/effect/proc_holder/spell/wizard/targeted/ethereal_jaunt(H)
+ H.mind.AddSpell(new /obj/effect/proc_holder/spell/wizard/targeted/ethereal_jaunt(H))
temp = "You have learned ethereal jaunt."
if("knock")
feedback_add_details("wizard_spell_learned","KN") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
- H.spell_list += new /obj/effect/proc_holder/spell/wizard/aoe_turf/knock(H)
+ H.mind.AddSpell(new /obj/effect/proc_holder/spell/wizard/aoe_turf/knock(H))
temp = "You have learned knock."
if("horseman")
feedback_add_details("wizard_spell_learned","HH") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
- H.spell_list += new /obj/effect/proc_holder/spell/wizard/targeted/horsemask(H)
+ H.mind.AddSpell(new /obj/effect/proc_holder/spell/wizard/targeted/horsemask(H))
temp = "You have learned curse of the horseman."
if("fleshtostone")
feedback_add_details("wizard_spell_learned","FS") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
- H.spell_list += new /obj/effect/proc_holder/spell/wizard/targeted/inflict_handler/flesh_to_stone(H)
+ H.mind.AddSpell(new /obj/effect/proc_holder/spell/wizard/targeted/inflict_handler/flesh_to_stone(H))
temp = "You have learned flesh to stone."
if("lightningbolt")
feedback_add_details("wizard_spell_learned","LB") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
- H.spell_list += new /obj/effect/proc_holder/spell/wizard/targeted/lightning(null)
+ H.mind.AddSpell(new /obj/effect/proc_holder/spell/wizard/targeted/lightning(null))
temp = "You have learned lightning bolt."
if("summonitem")
feedback_add_details("wizard_spell_learned","IS") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
- H.spell_list += new /obj/effect/proc_holder/spell/wizard/targeted/summonitem(null)
+ H.mind.AddSpell(new /obj/effect/proc_holder/spell/wizard/targeted/summonitem(null))
temp = "You have learned instant summons."
if("summonguns")
feedback_add_details("wizard_spell_learned","SG") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
@@ -334,7 +334,7 @@
if("soulstone")
feedback_add_details("wizard_spell_learned","SS") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
new /obj/item/weapon/storage/belt/soulstone/full(get_turf(H))
- H.spell_list += new /obj/effect/proc_holder/spell/wizard/aoe_turf/conjure/construct(H)
+ H.mind.AddSpell(new /obj/effect/proc_holder/spell/wizard/aoe_turf/conjure/construct(H))
temp = "You have purchased a belt full of soulstones and have learned the artificer spell."
max_uses--
if("armor")
@@ -381,7 +381,7 @@
H << "\blue The walls suddenly disappear."
temp = "You have purchased a scrying orb, and gained x-ray vision."
max_uses--
- H.update_power_buttons()
+
else
if(href_list["temp"])
temp = null
@@ -418,11 +418,11 @@
if(used)
recoil(user)
else
- user.spell_list += S
+ user.mind.AddSpell(S)
user <<"you rapidly read through the arcane book. Suddenly you realize you understand [spellname]!"
user.attack_log += text("\[[time_stamp()]\] [user.real_name] ([user.ckey]) learned the spell [spellname] ([S]).")
onlearned(user)
- user.update_power_buttons()
+
/obj/item/weapon/spellbook/oneuse/proc/recoil(mob/user as mob)
user.visible_message("[src] glows in a black light!")
diff --git a/code/game/gamemodes/wizard/wizard.dm b/code/game/gamemodes/wizard/wizard.dm
index 78be858d796..ea68cec863d 100644
--- a/code/game/gamemodes/wizard/wizard.dm
+++ b/code/game/gamemodes/wizard/wizard.dm
@@ -277,7 +277,6 @@
for(var/obj/effect/proc_holder/spell/wizard/spell_to_remove in src.spell_list)
if (spell_to_remove.name == "Artificer" && !removeallspells) continue
del(spell_to_remove)
- update_power_buttons()
/*Checks if the wizard can cast spells.
Made a proc so this is not repeated 14 (or more) times.*/
diff --git a/code/game/jobs/jobprocs.dm b/code/game/jobs/jobprocs.dm
index 8955f135b4b..4a885005c78 100644
--- a/code/game/jobs/jobprocs.dm
+++ b/code/game/jobs/jobprocs.dm
@@ -41,4 +41,5 @@
H << "You'll have to wait if you want to atone for your sins."
spawn(3000)
H.miming = 1
- return
\ No newline at end of file
+ return
+
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index f7c42003809..a6879546e11 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -21,8 +21,10 @@
var/max_heat_protection_temperature //Set this variable to determine up to which temperature (IN KELVIN) the item protects against heat damage. Keep at null to disable protection. Only protects areas set by heat_protection flags
var/min_cold_protection_temperature //Set this variable to determine down to which temperature (IN KELVIN) the item protects against cold damage. 0 is NOT an acceptable number due to if(varname) tests!! Keep at null to disable protection. Only protects areas set by cold_protection flags
- var/icon_action_button //If this is set, The item will make an action button on the player's HUD when picked up. The button will have the icon_action_button sprite from the screen1_action.dmi file.
- var/action_button_name //This is the text which gets displayed on the action button. If not set it defaults to 'Use [name]'. Note that icon_action_button needs to be set in order for the action button to appear.
+ //If this is set, The item will make an action button on the player's HUD when picked up.
+ var/action_button_name //It is also the text which gets displayed on the action button. If not set it defaults to 'Use [name]'. If it's not set, there'll be no button.
+ var/action_button_is_hands_free = 0 //If 1, bypass the restrained, lying, and stunned checks action buttons normally test for
+ var/datum/action/item_action/action = null
//Since any item can now be a piece of clothing, this has to be put here so all items share it.
var/flags_inv //This flag is used to determine when items in someone's inventory cover others. IE helmets making it so you can't see glasses, etc.
@@ -557,13 +559,7 @@
//The default action is attack_self().
//Checks before we get to here are: mob is alive, mob is not restrained, paralyzed, asleep, resting, laying, item is on the mob.
/obj/item/proc/ui_action_click()
- if( src in usr )
- attack_self(usr)
- return
- else if(istype(src, /obj/item/clothing/accessory))
- if(istype(src.loc,/obj/item/clothing/under))
- attack_self(usr)
-
+ attack_self(usr)
/obj/item/proc/IsShield()
return 0
diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm
index 05a851b0d28..829ae641901 100644
--- a/code/game/objects/items/devices/flashlight.dm
+++ b/code/game/objects/items/devices/flashlight.dm
@@ -9,7 +9,7 @@
slot_flags = SLOT_BELT
m_amt = 50
g_amt = 20
- icon_action_button = "action_flashlight"
+ action_button_name = "Flashlight"
var/on = 0
var/brightness_on = 4 //luminosity when on
@@ -138,7 +138,6 @@
brightness_on = 7 // Pretty bright.
icon_state = "flare"
item_state = "flare"
- icon_action_button = null //just pull it manually, neckbeard.
var/fuel = 0
var/on_damage = 7
var/produce_heat = 1500
diff --git a/code/game/objects/items/weapons/chrono_eraser.dm b/code/game/objects/items/weapons/chrono_eraser.dm
index 15640ba0670..e2b85f1069a 100644
--- a/code/game/objects/items/weapons/chrono_eraser.dm
+++ b/code/game/objects/items/weapons/chrono_eraser.dm
@@ -10,7 +10,6 @@
slot_flags = SLOT_BACK
slowdown = 1
action_button_name = "Equip/Unequip TED Gun"
- icon_action_button = "action_chronobackpack"
var/obj/item/weapon/gun/energy/chrono_gun/PA = null
var/list/erased_minds = list() //a collection of minds from the dead
diff --git a/code/game/objects/items/weapons/defib.dm b/code/game/objects/items/weapons/defib.dm
index 4c4dcfe4b4a..b0ef2bb03db 100644
--- a/code/game/objects/items/weapons/defib.dm
+++ b/code/game/objects/items/weapons/defib.dm
@@ -13,7 +13,6 @@
w_class = 4
origin_tech = "biotech=4"
action_button_name = "Toggle Paddles"
- icon_action_button = "action_defibunit"
var/on = 0 //if the paddles are equipped (1) or on the defib (0)
var/safety = 1 //if you can zap people with the defibs on harm mode
diff --git a/code/game/objects/items/weapons/tanks/jetpack.dm b/code/game/objects/items/weapons/tanks/jetpack.dm
index 74ab6d991ac..54d03fabd4c 100644
--- a/code/game/objects/items/weapons/tanks/jetpack.dm
+++ b/code/game/objects/items/weapons/tanks/jetpack.dm
@@ -11,7 +11,7 @@
var/on = 0.0
var/stabilization_on = 0
var/volume_rate = 500 //Needed for borg jetpack transfer
- icon_action_button = "action_jetpack"
+ action_button_name = "Toggle Jetpack"
New()
..()
diff --git a/code/game/objects/items/weapons/tanks/watertank.dm b/code/game/objects/items/weapons/tanks/watertank.dm
index afaebdc4fe4..afbfd61a95c 100644
--- a/code/game/objects/items/weapons/tanks/watertank.dm
+++ b/code/game/objects/items/weapons/tanks/watertank.dm
@@ -9,7 +9,6 @@
slot_flags = SLOT_BACK
slowdown = 1
action_button_name = "Toggle Mister"
- icon_action_button = "action_waterbackpack"
var/obj/item/weapon/noz
var/on = 0
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index ae3f2c2a5d9..24fddb2e288 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -145,7 +145,9 @@ var/list/admin_verbs_debug = list(
/client/proc/qdel_toggle, // /vg/
/client/proc/gc_dump_hdl,
/client/proc/debugNatureMapGenerator,
- /client/proc/check_bomb_impacts
+ /client/proc/check_bomb_impacts,
+ /client/proc/test_movable_UI,
+ /client/proc/test_snap_UI
)
var/list/admin_verbs_possess = list(
/proc/possess,
@@ -401,8 +403,10 @@ var/list/admin_verbs_mentor = list(
set desc = "Gives a spell to a mob."
var/obj/effect/proc_holder/spell/wizard/S = input("Choose the spell to give to that guy", "ABRAKADABRA") as null|anything in spells
if(!S) return
- T.spell_list += new S
- T.update_power_buttons()
+ if(T.mind)
+ T.mind.AddSpell(new S)
+ else
+ T.AddSpell(new S)
feedback_add_details("admin_verb","GS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
log_admin("[key_name(usr)] gave [key_name(T)] the spell [S].")
message_admins("\blue [key_name_admin(usr)] gave [key_name(T)] the spell [S].", 1)
diff --git a/code/modules/clothing/glasses/glasses.dm b/code/modules/clothing/glasses/glasses.dm
index 74e19d7b1d7..c2d333dd849 100644
--- a/code/modules/clothing/glasses/glasses.dm
+++ b/code/modules/clothing/glasses/glasses.dm
@@ -162,7 +162,7 @@
desc = "Protects the eyes from welders, approved by the mad scientist association."
icon_state = "welding-g"
item_state = "welding-g"
- icon_action_button = "action_welding_g"
+ action_button_name = "Flip welding goggles"
var/up = 0
flash_protect = 2
tint = 2
@@ -210,7 +210,7 @@
item_state = "rwelding-g"
flash_protect = 2
tint = 0
- icon_action_button = "action_welding_g"
+ action_button_name = "Flip welding goggles"
species_fit = list("Vox")
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/eyes.dmi'
diff --git a/code/modules/clothing/head/hardhat.dm b/code/modules/clothing/head/hardhat.dm
index 42b985289a7..b46f07ce038 100644
--- a/code/modules/clothing/head/hardhat.dm
+++ b/code/modules/clothing/head/hardhat.dm
@@ -9,7 +9,7 @@
_color = "yellow" //Determines used sprites: hardhat[on]_[color] and hardhat[on]_[color]2 (lying down sprite)
armor = list(melee = 30, bullet = 5, laser = 20,energy = 10, bomb = 20, bio = 10, rad = 20)
flags_inv = 0
- icon_action_button = "action_hardhat"
+ action_button_name = "Toggle Helmet Light"
siemens_coefficient = 0.9
loose = 4
diff --git a/code/modules/clothing/head/misc.dm b/code/modules/clothing/head/misc.dm
index 1cd2a19525e..0a1af75c802 100644
--- a/code/modules/clothing/head/misc.dm
+++ b/code/modules/clothing/head/misc.dm
@@ -350,7 +350,6 @@
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE
var/cooldown = 0
action_button_name = "Caw"
- icon_action_button = "action_griffin"
/obj/item/clothing/head/griffin/attack_self()
caw()
diff --git a/code/modules/clothing/head/misc_special.dm b/code/modules/clothing/head/misc_special.dm
index d5420a8bd4d..c7378b0bb73 100644
--- a/code/modules/clothing/head/misc_special.dm
+++ b/code/modules/clothing/head/misc_special.dm
@@ -24,7 +24,7 @@
tint = 2
armor = list(melee = 10, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0)
flags_inv = (HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE)
- icon_action_button = "action_welding"
+ action_button_name = "flip welding helmet"
siemens_coefficient = 0.9
loose = 4
species_fit = list("Vox")
diff --git a/code/modules/clothing/masks/boxing.dm b/code/modules/clothing/masks/boxing.dm
index a461e0cf845..4225bb8d3f0 100644
--- a/code/modules/clothing/masks/boxing.dm
+++ b/code/modules/clothing/masks/boxing.dm
@@ -6,17 +6,16 @@
flags = BLOCKHAIR
flags_inv = HIDEFACE
w_class = 2
- icon_action_button = "action_balaclava"
action_button_name = "Adjust Balaclava"
ignore_maskadjust = 0
species_fit = list("Vox")
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/mask.dmi'
)
-
+
/obj/item/clothing/mask/balaclava/attack_self(var/mob/user)
- adjustmask(user)
-
+ adjustmask(user)
+
/obj/item/clothing/mask/luchador
name = "Luchador Mask"
desc = "Worn by robust fighters, flying high to defeat their foes!"
diff --git a/code/modules/clothing/masks/breath.dm b/code/modules/clothing/masks/breath.dm
index f3064e9f17b..616fcfea38e 100644
--- a/code/modules/clothing/masks/breath.dm
+++ b/code/modules/clothing/masks/breath.dm
@@ -8,7 +8,6 @@
gas_transfer_coefficient = 0.10
permeability_coefficient = 0.50
species_fit = list("Vox")
- icon_action_button = "action_breath"
action_button_name = "Adjust Breath Mask"
ignore_maskadjust = 0
species_fit = list("Vox", "Vox Armalis")
@@ -35,6 +34,5 @@
item_state = "voxmask"
permeability_coefficient = 0.01
species_restricted = list("Vox")
- icon_action_button = null
action_button_name = null
ignore_maskadjust = 1
diff --git a/code/modules/clothing/masks/gasmask.dm b/code/modules/clothing/masks/gasmask.dm
index eac240c5073..438e456c9dc 100644
--- a/code/modules/clothing/masks/gasmask.dm
+++ b/code/modules/clothing/masks/gasmask.dm
@@ -138,7 +138,6 @@
flags = MASKCOVERSMOUTH | MASKCOVERSEYES | BLOCK_GAS_SMOKE_EFFECT | MASKINTERNALS | NODROP
var/cooldown = 0
action_button_name = "Hoot"
- icon_action_button = "action_owlman"
/obj/item/clothing/mask/gas/owl_mask/attack_self()
hoot()
@@ -170,7 +169,6 @@
ignore_maskadjust = 0
species_fit = list()
action_button_name = "HALT!"
- icon_action_button = "action_sechailer"
/obj/item/clothing/mask/gas/sechailer/swat
name = "\improper SWAT mask"
diff --git a/code/modules/clothing/masks/miscellaneous.dm b/code/modules/clothing/masks/miscellaneous.dm
index a7a2ec07130..cd3e75e4ce5 100644
--- a/code/modules/clothing/masks/miscellaneous.dm
+++ b/code/modules/clothing/masks/miscellaneous.dm
@@ -36,7 +36,6 @@
permeability_coefficient = 0.01
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 25, rad = 0)
action_button_name = "Adjust Sterile Mask"
- icon_action_button = "action_sterile"
ignore_maskadjust = 0
species_fit = list("Vox")
sprite_sheets = list(
@@ -176,7 +175,6 @@
ignore_maskadjust = 0
adjusted_flags = SLOT_HEAD
icon_state = "bandbotany"
- icon_action_button = "action_bandbotany"
action_button_name = "Adjust Bandana"
/obj/item/clothing/mask/bandana/attack_self(var/mob/user)
diff --git a/code/modules/clothing/shoes/magboots.dm b/code/modules/clothing/shoes/magboots.dm
index 5981d880a16..d274f24815c 100644
--- a/code/modules/clothing/shoes/magboots.dm
+++ b/code/modules/clothing/shoes/magboots.dm
@@ -6,7 +6,6 @@
var/magpulse = 0
var/slowdown_active = 2
action_button_name = "Toggle Magboots"
- icon_action_button = "action_magboots"
species_restricted = null
/obj/item/clothing/shoes/magboots/attack_self(mob/user)
diff --git a/code/modules/clothing/spacesuits/chronosuit.dm b/code/modules/clothing/spacesuits/chronosuit.dm
index 4d6035ba2fe..ce52c7525a5 100644
--- a/code/modules/clothing/spacesuits/chronosuit.dm
+++ b/code/modules/clothing/spacesuits/chronosuit.dm
@@ -23,7 +23,6 @@
icon_state = "chronosuit"
item_state = "chronosuit"
action_button_name = "Toggle Chronosuit"
- icon_action_button = "action_chronosuit"
slowdown = 2
armor = list(melee = 60, bullet = 60, laser = 60, energy = 60, bomb = 30, bio = 90, rad = 90)
var/obj/item/clothing/head/helmet/space/chronos/helmet = null
diff --git a/code/modules/clothing/spacesuits/rig.dm b/code/modules/clothing/spacesuits/rig.dm
index e54b737584f..7202259c0ab 100644
--- a/code/modules/clothing/spacesuits/rig.dm
+++ b/code/modules/clothing/spacesuits/rig.dm
@@ -10,7 +10,7 @@
var/brightness_on = 4 //luminosity when on
var/on = 0
_color = "engineering" //Determines used sprites: rig[on]-[color] and rig[on]-[color]2 (lying down sprite)
- icon_action_button = "action_hardhat"
+ action_button_name = "Toggle Helmet Light"
//Species-specific stuff.
species_restricted = list("exclude","Unathi","Tajaran","Skrell","Diona","Vox")
@@ -374,7 +374,6 @@
on = 1
flags = HEADCOVERSEYES | BLOCKHAIR | HEADCOVERSMOUTH | STOPSPRESSUREDMAGE | THICKMATERIAL
action_button_name = "Toggle Helmet Mode"
- icon_action_button = "Action_hardsuit1-syndi"
species_restricted = null
sprite_sheets = null
@@ -417,7 +416,6 @@
w_class = 3
var/on = 1
action_button_name = "Toggle Hardsuit Mode"
- icon_action_button = "Action_hardsuit1-syndi"
armor = list(melee = 60, bullet = 50, laser = 30, energy = 15, bomb = 35, bio = 100, rad = 50)
allowed = list(/obj/item/weapon/gun,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/melee/energy/sword,/obj/item/weapon/restraints/handcuffs,/obj/item/weapon/tank)
species_restricted = null
diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm
index c5d1c020564..721f64b9367 100644
--- a/code/modules/clothing/suits/armor.dm
+++ b/code/modules/clothing/suits/armor.dm
@@ -165,7 +165,7 @@
icon_state = "reactiveoff"
item_state = "reactiveoff"
blood_overlay_type = "armor"
- icon_action_button = "reactiveoff"
+ action_button_name = "Toggle Reactive Armor"
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0)
/obj/item/clothing/suit/armor/reactive/IsShield()
diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm
index 9f819f9985b..381d0820287 100644
--- a/code/modules/clothing/suits/miscellaneous.dm
+++ b/code/modules/clothing/suits/miscellaneous.dm
@@ -474,7 +474,6 @@
armor = list(melee = 5, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0)
allowed = list(/obj/item/weapon/gun/energy,/obj/item/weapon/reagent_containers/spray/pepper,/obj/item/weapon/gun/projectile,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/restraints/handcuffs,/obj/item/device/flashlight/seclite)
action_button_name = "Toggle Owl Wings"
- icon_action_button = "action_wings"
flags = NODROP
/obj/item/clothing/suit/toggle/owlwings/griffinwings
diff --git a/code/modules/clothing/under/accessories/holster.dm b/code/modules/clothing/under/accessories/holster.dm
index 3d61a789742..0417a8ce0c5 100644
--- a/code/modules/clothing/under/accessories/holster.dm
+++ b/code/modules/clothing/under/accessories/holster.dm
@@ -6,7 +6,7 @@
slot = "utility"
var/holster_allow = /obj/item/weapon/gun
var/obj/item/weapon/gun/holstered = null
- icon_action_button = "action_holster"
+ action_button_name = "Holster"
w_class = 3.0 // so it doesn't fit in pockets
//subtypes can override this to specify what can be holstered
diff --git a/code/modules/clothing/under/accessories/storage.dm b/code/modules/clothing/under/accessories/storage.dm
index d33d5e9a263..fc560f47476 100644
--- a/code/modules/clothing/under/accessories/storage.dm
+++ b/code/modules/clothing/under/accessories/storage.dm
@@ -6,7 +6,7 @@
slot = "utility"
var/slots = 3
var/obj/item/weapon/storage/internal/hold
- icon_action_button = "action_storage"
+ action_button_name = "View Storage"
w_class = 3.0 // so it doesn't fit in pockets
/obj/item/clothing/accessory/storage/New()
diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm
index 22af8b0bedc..5948c79d981 100644
--- a/code/modules/mob/dead/observer/observer.dm
+++ b/code/modules/mob/dead/observer/observer.dm
@@ -37,7 +37,7 @@ var/list/image/ghost_darkness_images = list() //this is a list of images for thi
verbs += /mob/dead/observer/proc/dead_tele
// Our new boo spell.
- spell_list += new /obj/effect/proc_holder/spell/wizard/aoe_turf/boo(src)
+ AddSpell(new /obj/effect/proc_holder/spell/wizard/aoe_turf/boo(src))
can_reenter_corpse = flags & GHOST_CAN_REENTER
started_as_observer = flags & GHOST_IS_OBSERVER
diff --git a/code/modules/mob/living/carbon/alien/humanoid/life.dm b/code/modules/mob/living/carbon/alien/humanoid/life.dm
index 9ecf410a4d3..ce94cb4c8a2 100644
--- a/code/modules/mob/living/carbon/alien/humanoid/life.dm
+++ b/code/modules/mob/living/carbon/alien/humanoid/life.dm
@@ -58,6 +58,9 @@
//Status updates, death etc.
handle_regular_status_updates()
+
+ handle_actions()
+
update_canmove()
update_icons()
diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm
index 7e876c1a116..01722c780ba 100644
--- a/code/modules/mob/living/carbon/human/inventory.dm
+++ b/code/modules/mob/living/carbon/human/inventory.dm
@@ -197,8 +197,6 @@
update_inv_l_hand()
- update_action_buttons()
-
//This is an UNSAFE proc. Use mob_can_equip() before calling this one! Or rather use equip_to_slot_if_possible() or advanced_equip_to_slot_if_possible()
diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm
index ec2e253e100..f784c141eeb 100644
--- a/code/modules/mob/living/carbon/human/life.dm
+++ b/code/modules/mob/living/carbon/human/life.dm
@@ -138,6 +138,9 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc
//Status updates, death etc.
handle_regular_status_updates() //Optimized a bit
+
+ handle_actions()
+
update_canmove()
//Update our name based on whether our face is obscured/disfigured
@@ -1044,20 +1047,19 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc
if(hud_updateflag)
handle_hud_list()
-
if(!client) return 0
if(hud_updateflag)
handle_hud_list()
+ update_action_buttons()
+
for(var/image/hud in client.images)
if(copytext(hud.icon_state,1,4) == "hud") //ugly, but icon comparison is worse, I believe
client.images.Remove(hud)
client.screen.Remove(global_hud.blurry, global_hud.druggy, global_hud.vimpaired, global_hud.darkMask,/* global_hud.nvg*/)
- update_action_buttons()
-
if(damageoverlay.overlays)
damageoverlay.overlays = list()
@@ -1796,7 +1798,6 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc
holder.icon_state = "hudscientopia"
hud_list[NATIONS_HUD] = holder
- update_power_buttons()
hud_updateflag = 0
/mob/living/carbon/human/proc/process_nations()
diff --git a/code/modules/mob/living/carbon/metroid/life.dm b/code/modules/mob/living/carbon/metroid/life.dm
index afcb48726bd..a839b8a85b2 100644
--- a/code/modules/mob/living/carbon/metroid/life.dm
+++ b/code/modules/mob/living/carbon/metroid/life.dm
@@ -42,6 +42,8 @@
handle_regular_status_updates() // Status updates, death etc.
+ handle_actions()
+
handle_wetness()
/mob/living/carbon/slime/proc/AIprocess() // the master AI process
diff --git a/code/modules/mob/living/carbon/monkey/life.dm b/code/modules/mob/living/carbon/monkey/life.dm
index cc1808ff6c5..bdb27ade772 100644
--- a/code/modules/mob/living/carbon/monkey/life.dm
+++ b/code/modules/mob/living/carbon/monkey/life.dm
@@ -67,6 +67,9 @@
//Status updates, death etc.
handle_regular_status_updates()
+
+ handle_actions()
+
update_canmove()
if(client)
diff --git a/code/modules/mob/living/carbon/superheroes.dm b/code/modules/mob/living/carbon/superheroes.dm
index fb4f597bbae..a08c5a2833a 100644
--- a/code/modules/mob/living/carbon/superheroes.dm
+++ b/code/modules/mob/living/carbon/superheroes.dm
@@ -34,8 +34,7 @@
for(var/spell in default_spells)
var/obj/effect/proc_holder/spell/wizard/S = spell
if(!S) return
- H.spell_list += new S
- H.update_power_buttons()
+ H.AddSpell(new S)
/datum/superheroes/proc/assign_id(var/mob/living/carbon/human/H)
var/obj/item/weapon/card/id/syndicate/W = new(H)
@@ -147,7 +146,7 @@
charge_max = 450
clothes_req = 0
range = 1 //Adjacent to user
- icon_power_button = "spell_greytide"
+ action_icon_state = "spell_greytide"
var/recruiting = 0
/obj/effect/proc_holder/spell/wizard/targeted/recruit/cast(list/targets)
diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm
index aff6a6d415e..c5742f89945 100644
--- a/code/modules/mob/living/living_defense.dm
+++ b/code/modules/mob/living/living_defense.dm
@@ -242,6 +242,80 @@
if(volume >= 20) fire_stacks -= 0.5
if(volume >= 50) fire_stacks -= 1
+/mob/living/regular_hud_updates()
+ ..()
+ update_action_buttons()
+
+/mob/living/proc/handle_actions()
+ //Pretty bad, i'd use picked/dropped instead but the parent calls in these are nonexistent
+ for(var/datum/action/A in actions)
+ if(A.CheckRemoval(src))
+ A.Remove(src)
+ for(var/obj/item/I in src)
+ if(I.action_button_name)
+ if(!I.action)
+ if(I.action_button_is_hands_free)
+ I.action = new/datum/action/item_action/hands_free
+ else
+ I.action = new/datum/action/item_action
+ I.action.name = I.action_button_name
+ I.action.target = I
+ I.action.Grant(src)
+ return
+
+/mob/living/update_action_buttons()
+ if(!hud_used) return
+ if(!client) return
+
+ if(hud_used.hud_shown != 1) //Hud toggled to minimal
+ return
+
+ client.screen -= hud_used.hide_actions_toggle
+ for(var/datum/action/A in actions)
+ if(A.button)
+ client.screen -= A.button
+
+ if(hud_used.action_buttons_hidden)
+ if(!hud_used.hide_actions_toggle)
+ hud_used.hide_actions_toggle = new(hud_used)
+ hud_used.hide_actions_toggle.UpdateIcon()
+
+ if(!hud_used.hide_actions_toggle.moved)
+ hud_used.hide_actions_toggle.screen_loc = hud_used.ButtonNumberToScreenCoords(1)
+ //hud_used.SetButtonCoords(hud_used.hide_actions_toggle,1)
+
+ client.screen += hud_used.hide_actions_toggle
+ return
+
+ var/button_number = 0
+ for(var/datum/action/A in actions)
+ button_number++
+ if(A.button == null)
+ var/obj/screen/movable/action_button/N = new(hud_used)
+ N.owner = A
+ A.button = N
+
+ var/obj/screen/movable/action_button/B = A.button
+
+ B.UpdateIcon()
+
+ B.name = A.UpdateName()
+
+ client.screen += B
+
+ if(!B.moved)
+ B.screen_loc = hud_used.ButtonNumberToScreenCoords(button_number)
+ //hud_used.SetButtonCoords(B,button_number)
+
+ if(button_number > 0)
+ if(!hud_used.hide_actions_toggle)
+ hud_used.hide_actions_toggle = new(hud_used)
+ hud_used.hide_actions_toggle.InitialiseIcon(src)
+ if(!hud_used.hide_actions_toggle.moved)
+ hud_used.hide_actions_toggle.screen_loc = hud_used.ButtonNumberToScreenCoords(button_number+1)
+ //hud_used.SetButtonCoords(hud_used.hide_actions_toggle,button_number+1)
+ client.screen += hud_used.hide_actions_toggle
+
//This is called when the mob is thrown into a dense turf
/mob/living/proc/turf_collision(var/turf/T, var/speed)
src.take_organ_damage(speed*5)
diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm
index 1a683b9e183..6abc87a50a3 100644
--- a/code/modules/mob/living/living_defines.dm
+++ b/code/modules/mob/living/living_defines.dm
@@ -48,4 +48,6 @@
var/nightvision = 0
var/list/icon/pipes_shown = list()
- var/last_played_vent
\ No newline at end of file
+ var/last_played_vent
+
+ var/list/datum/action/actions = list()
\ No newline at end of file
diff --git a/code/modules/mob/living/silicon/pai/life.dm b/code/modules/mob/living/silicon/pai/life.dm
index 5ddbc0efe38..b53095f045d 100644
--- a/code/modules/mob/living/silicon/pai/life.dm
+++ b/code/modules/mob/living/silicon/pai/life.dm
@@ -18,6 +18,7 @@
silence_time = null
src << "Communication circuit reinitialized. Speech and messaging functionality restored."
handle_statuses()
+ handle_actions()
/mob/living/silicon/pai/updatehealth()
if(status_flags & GODMODE)
diff --git a/code/modules/mob/living/silicon/robot/life.dm b/code/modules/mob/living/silicon/robot/life.dm
index 7f713c8a2c3..2abf3f6a050 100644
--- a/code/modules/mob/living/silicon/robot/life.dm
+++ b/code/modules/mob/living/silicon/robot/life.dm
@@ -11,6 +11,8 @@
clamp_values()
handle_regular_status_updates()
+ handle_actions()
+
if(client)
handle_regular_hud_updates()
update_items()
diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm
index 0d637fc6c78..684896e7d77 100644
--- a/code/modules/mob/living/simple_animal/constructs.dm
+++ b/code/modules/mob/living/simple_animal/constructs.dm
@@ -31,7 +31,7 @@
name = text("[initial(name)] ([rand(1, 1000)])")
real_name = name
for(var/spell in construct_spells)
- spell_list += new spell(src)
+ AddSpell(new spell(src))
/mob/living/simple_animal/construct/Die()
..()
diff --git a/code/modules/mob/living/simple_animal/hostile/statue.dm b/code/modules/mob/living/simple_animal/hostile/statue.dm
index 30115ec7957..755434de05c 100644
--- a/code/modules/mob/living/simple_animal/hostile/statue.dm
+++ b/code/modules/mob/living/simple_animal/hostile/statue.dm
@@ -56,9 +56,9 @@
/mob/living/simple_animal/hostile/statue/New(loc, var/mob/living/creator)
..()
// Give spells
- spell_list += new /obj/effect/proc_holder/spell/wizard/aoe_turf/flicker_lights(src)
- spell_list += new /obj/effect/proc_holder/spell/wizard/aoe_turf/blindness(src)
- spell_list += new /obj/effect/proc_holder/spell/wizard/targeted/night_vision(src)
+ AddSpell(new /obj/effect/proc_holder/spell/wizard/aoe_turf/flicker_lights(src))
+ AddSpell(new /obj/effect/proc_holder/spell/wizard/aoe_turf/blindness(src))
+ AddSpell(new /obj/effect/proc_holder/spell/wizard/targeted/night_vision(src))
// Give nightvision
see_invisible = SEE_INVISIBLE_OBSERVER_NOLIGHTING
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index 76c8c4733d7..3e1fd60f404 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -108,6 +108,8 @@
handle_weakened()
handle_paralysed()
+ handle_actions()
+
//Movement
if(!client && !stop_automated_movement && wander && (ckey == null))
if(isturf(src.loc) && !resting && !buckled && canmove) //This is so it only moves if it's not inside a closet, gentics machine, etc.
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index ac726058103..11c94d16e16 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -1455,4 +1455,17 @@ mob/proc/yank_out_object()
else
src.visible_message("[src] pukes all over \himself!","You puke all over yourself!")
location.add_vomit_floor(src, 1)
- playsound(location, 'sound/effects/splat.ogg', 50, 1)
\ No newline at end of file
+ playsound(location, 'sound/effects/splat.ogg', 50, 1)
+
+/mob/proc/AddSpell(var/obj/effect/proc_holder/spell/spell)
+ spell_list += spell
+ if(!spell.action)
+ spell.action = new/datum/action/spell_action
+ spell.action.target = spell
+ spell.action.name = spell.name
+ spell.action.button_icon = spell.action_icon
+ spell.action.button_icon_state = spell.action_icon_state
+ spell.action.background_icon_state = spell.action_background_icon_state
+ if(isliving(src))
+ spell.action.Grant(src)
+ return
\ No newline at end of file
diff --git a/code/modules/mob/spirit/mask/mask.dm b/code/modules/mob/spirit/mask/mask.dm
index 36e8fff5d1a..a6ce20f0e66 100644
--- a/code/modules/mob/spirit/mask/mask.dm
+++ b/code/modules/mob/spirit/mask/mask.dm
@@ -4,9 +4,9 @@
/mob/spirit/mask/New()
..()
- spell_list += new /obj/effect/proc_holder/spell/wizard/aoe_turf/conjure/create_talisman(src)
- spell_list += new /obj/effect/proc_holder/spell/wizard/aoe_turf/blood_speech(src)
- spell_list += new /obj/effect/proc_holder/spell/wizard/aoe_turf/shatter_lights(src)
+ AddSpell(new /obj/effect/proc_holder/spell/wizard/aoe_turf/conjure/create_talisman(src))
+ AddSpell(new /obj/effect/proc_holder/spell/wizard/aoe_turf/blood_speech(src))
+ AddSpell(new /obj/effect/proc_holder/spell/wizard/aoe_turf/shatter_lights(src))
/mob/spirit/mask/verb/go_to_follower()
diff --git a/code/modules/projectiles/guns/projectile/automatic.dm b/code/modules/projectiles/guns/projectile/automatic.dm
index e3c5ce80533..f4c1142039c 100644
--- a/code/modules/projectiles/guns/projectile/automatic.dm
+++ b/code/modules/projectiles/guns/projectile/automatic.dm
@@ -155,7 +155,6 @@
mag_type = "/obj/item/ammo_box/magazine/m545"
fire_sound = 'sound/weapons/Gunshot_smg.ogg'
action_button_name = "Toggle Grenade Launcher"
- icon_action_button = "Action_c90gl"
can_suppress = 0
var/select = 1 //1 for boolets, 0 for explosions.
var/obj/item/weapon/gun/projectile/revolver/grenadelauncher/underbarrel
diff --git a/code/modules/projectiles/projectile/change.dm b/code/modules/projectiles/projectile/change.dm
index 23f44bf19da..0a828d3be11 100644
--- a/code/modules/projectiles/projectile/change.dm
+++ b/code/modules/projectiles/projectile/change.dm
@@ -74,7 +74,7 @@
return
for (var/obj/effect/proc_holder/spell/wizard/S in M.spell_list)
- new_mob.spell_list += new S.type
+ new_mob.AddSpell(new S.type)
new_mob.a_intent = "harm"
if(M.mind)
diff --git a/code/modules/projectiles/projectile/magic.dm b/code/modules/projectiles/projectile/magic.dm
index e6fc21e672f..cc2a94ad1f0 100644
--- a/code/modules/projectiles/projectile/magic.dm
+++ b/code/modules/projectiles/projectile/magic.dm
@@ -219,7 +219,7 @@ proc/wabbajack(mob/living/M)
return
for (var/obj/effect/proc_holder/spell/wizard/S in M.spell_list)
- new_mob.spell_list += new S.type
+ new_mob.AddSpell(new S.type)
new_mob.attack_log = M.attack_log
M.attack_log += text("\[[time_stamp()]\] [M.real_name] ([M.ckey]) became [new_mob.real_name].")
diff --git a/icons/mob/actions.dmi b/icons/mob/actions.dmi
new file mode 100644
index 00000000000..400db51debe
Binary files /dev/null and b/icons/mob/actions.dmi differ
diff --git a/paradise.dme b/paradise.dme
index 1bf34f25e1d..224f1e0df9f 100644
--- a/paradise.dme
+++ b/paradise.dme
@@ -49,12 +49,14 @@
#include "code\_onclick\telekinesis.dm"
#include "code\_onclick\ventcrawl.dm"
#include "code\_onclick\hud\_defines.dm"
+#include "code\_onclick\hud\action.dm"
#include "code\_onclick\hud\ai.dm"
#include "code\_onclick\hud\alien.dm"
#include "code\_onclick\hud\alien_larva.dm"
#include "code\_onclick\hud\hud.dm"
#include "code\_onclick\hud\human.dm"
#include "code\_onclick\hud\monkey.dm"
+#include "code\_onclick\hud\movable_screen_objects.dm"
#include "code\_onclick\hud\other_mobs.dm"
#include "code\_onclick\hud\robot.dm"
#include "code\_onclick\hud\screen_objects.dm"