From 568d289a6787399fb6eb1e7c71ce901733e898ee Mon Sep 17 00:00:00 2001 From: AnturK Date: Mon, 11 May 2015 08:36:45 -0700 Subject: [PATCH] Generic Action\Action Button System This commit ports the GAABS from -tg-station13. The GAABS allows for generic, movable, hud elements for spells, powers, and items. --- code/_onclick/hud/_defines.dm | 23 -- code/_onclick/hud/action.dm | 247 ++++++++++++++++++ code/_onclick/hud/hud.dm | 6 +- code/_onclick/hud/human.dm | 60 +---- code/_onclick/hud/movable_screen_objects.dm | 85 ++++++ code/_onclick/hud/other_mobs.dm | 63 +---- code/_onclick/hud/screen_objects.dm | 44 +--- code/datums/mind.dm | 33 +++ code/datums/spell.dm | 56 +++- code/datums/spells/area_teleport.dm | 1 - code/datums/spells/emplosion.dm | 2 + code/datums/spells/ethereal_jaunt.dm | 2 +- code/datums/spells/fake_gib.dm | 2 +- code/datums/spells/horsemask.dm | 2 +- code/datums/spells/knock.dm | 2 +- code/datums/spells/lightning.dm | 2 +- code/datums/spells/magnet.dm | 2 +- code/datums/spells/mind_transfer.dm | 2 +- code/datums/spells/summonitem.dm | 2 + code/datums/spells/wizard.dm | 25 +- code/game/dna/genes/gene.dm | 4 +- code/game/dna/genes/goon_disabilities.dm | 2 +- code/game/dna/genes/goon_powers.dm | 12 +- code/game/dna/genes/vg_powers.dm | 8 +- code/game/gamemodes/shadowling/shadowling.dm | 2 +- .../shadowling/shadowling_abilities.dm | 8 +- .../special_shadowling_abilities.dm | 20 +- code/game/gamemodes/wizard/artefact.dm | 18 +- code/game/gamemodes/wizard/spellbook.dm | 46 ++-- code/game/gamemodes/wizard/wizard.dm | 1 - code/game/jobs/jobprocs.dm | 3 +- code/game/objects/items.dm | 14 +- code/game/objects/items/devices/flashlight.dm | 3 +- .../objects/items/weapons/chrono_eraser.dm | 1 - code/game/objects/items/weapons/defib.dm | 1 - .../objects/items/weapons/tanks/jetpack.dm | 2 +- .../objects/items/weapons/tanks/watertank.dm | 1 - code/modules/admin/admin_verbs.dm | 10 +- code/modules/clothing/glasses/glasses.dm | 4 +- code/modules/clothing/head/hardhat.dm | 2 +- code/modules/clothing/head/misc.dm | 1 - code/modules/clothing/head/misc_special.dm | 2 +- code/modules/clothing/masks/boxing.dm | 7 +- code/modules/clothing/masks/breath.dm | 2 - code/modules/clothing/masks/gasmask.dm | 2 - code/modules/clothing/masks/miscellaneous.dm | 2 - code/modules/clothing/shoes/magboots.dm | 1 - .../modules/clothing/spacesuits/chronosuit.dm | 1 - code/modules/clothing/spacesuits/rig.dm | 4 +- code/modules/clothing/suits/armor.dm | 2 +- code/modules/clothing/suits/miscellaneous.dm | 1 - .../clothing/under/accessories/holster.dm | 2 +- .../clothing/under/accessories/storage.dm | 2 +- code/modules/mob/dead/observer/observer.dm | 2 +- .../mob/living/carbon/alien/humanoid/life.dm | 3 + .../mob/living/carbon/human/inventory.dm | 2 - code/modules/mob/living/carbon/human/life.dm | 9 +- .../modules/mob/living/carbon/metroid/life.dm | 2 + code/modules/mob/living/carbon/monkey/life.dm | 3 + code/modules/mob/living/carbon/superheroes.dm | 5 +- code/modules/mob/living/living_defense.dm | 74 ++++++ code/modules/mob/living/living_defines.dm | 4 +- code/modules/mob/living/silicon/pai/life.dm | 1 + code/modules/mob/living/silicon/robot/life.dm | 2 + .../mob/living/simple_animal/constructs.dm | 2 +- .../living/simple_animal/hostile/statue.dm | 6 +- .../mob/living/simple_animal/simple_animal.dm | 2 + code/modules/mob/mob.dm | 15 +- code/modules/mob/spirit/mask/mask.dm | 6 +- .../projectiles/guns/projectile/automatic.dm | 1 - code/modules/projectiles/projectile/change.dm | 2 +- code/modules/projectiles/projectile/magic.dm | 2 +- icons/mob/actions.dmi | Bin 0 -> 30912 bytes paradise.dme | 2 + 74 files changed, 662 insertions(+), 335 deletions(-) create mode 100644 code/_onclick/hud/action.dm create mode 100644 code/_onclick/hud/movable_screen_objects.dm create mode 100644 icons/mob/actions.dmi 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 0000000000000000000000000000000000000000..400db51debe52607c862d9316828fb1ad5a15ca2 GIT binary patch literal 30912 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 G4*q|yo$~7d literal 0 HcmV?d00001 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"