diff --git a/code/_onclick/hud/_defines.dm b/code/_onclick/hud/_defines.dm index 1312331ff49..1775761d6a2 100644 --- a/code/_onclick/hud/_defines.dm +++ b/code/_onclick/hud/_defines.dm @@ -17,38 +17,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 "WEST :0, NORTH:0" -#define ui_action_slot2 "WEST+1 :0, NORTH:0" -#define ui_action_slot3 "WEST+2 :0, NORTH:0" -#define ui_action_slot4 "WEST+3 :0, NORTH:0" -#define ui_action_slot5 "WEST+4 :0, NORTH:0" -#define ui_action_slot6 "WEST+5 :0, NORTH:0" -#define ui_action_slot7 "WEST+6 :0, NORTH:0" -#define ui_action_slot8 "WEST+7 :0, NORTH:0" -#define ui_action_slot9 "WEST+8 :0, NORTH:0" -#define ui_action_slot10 "WEST+9 :0, NORTH:0" -#define ui_action_slot11 "WEST+10 :0, NORTH:0" -#define ui_action_slot12 "WEST+11 :0, NORTH:0" -#define ui_action_slot13 "WEST+12 :0, NORTH:0" -#define ui_action_slot14 "WEST+13 :0, NORTH:0" -#define ui_action_slot15 "WEST+14 :0, NORTH:0" -#define ui_action_slot16 "WEST :0, NORTH-1:0" -#define ui_action_slot17 "WEST+1 :0, NORTH-1:0" -#define ui_action_slot18 "WEST+2 :0, NORTH-1:0" -#define ui_action_slot19 "WEST+3 :0, NORTH-1:0" -#define ui_action_slot20 "WEST+4 :0, NORTH-1:0" -#define ui_action_slot21 "WEST+5 :0, NORTH-1:0" -#define ui_action_slot22 "WEST+6 :0, NORTH-1:0" -#define ui_action_slot23 "WEST+7 :0, NORTH-1:0" -#define ui_action_slot24 "WEST+8 :0, NORTH-1:0" -#define ui_action_slot25 "WEST+9 :0, NORTH-1:0" -#define ui_action_slot26 "WEST+10 :0, NORTH-1:0" -#define ui_action_slot27 "WEST+11 :0, NORTH-1:0" -#define ui_action_slot28 "WEST+12 :0, NORTH-1:0" -#define ui_action_slot29 "WEST+13 :0, NORTH-1:0" -#define ui_action_slot30 "WEST+14 :0, NORTH-1:0" - //Lower left, persistant menu #define ui_inventory "WEST:6,SOUTH:5" @@ -155,4 +123,3 @@ #define ui_head "WEST+1:8,SOUTH+3:11" - diff --git a/code/_onclick/hud/action.dm b/code/_onclick/hud/action.dm new file mode 100644 index 00000000000..f91f9e1e266 --- /dev/null +++ b/code/_onclick/hud/action.dm @@ -0,0 +1,238 @@ +#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/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.mob_spell_list) \ No newline at end of file diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm index c84ae5a071c..c896fb76999 100644 --- a/code/_onclick/hud/hud.dm +++ b/code/_onclick/hud/hud.dm @@ -110,8 +110,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/obj/screen/movable/action_button/hide_toggle/hide_actions_toggle + var/action_buttons_hidden = 0 datum/hud/New(mob/owner) mymob = owner @@ -243,8 +243,6 @@ datum/hud/New(mob/owner) mymob.client.screen -= other if(hotkeybuttons) mymob.client.screen -= hotkeybuttons - if(item_action_list) - mymob.client.screen -= item_action_list //These ones are not a part of 'adding', 'other' or 'hotkeybuttons' but we want them gone. mymob.client.screen -= mymob.zone_sel //zone_sel is a mob variable for some reason. @@ -269,8 +267,6 @@ datum/hud/New(mob/owner) mymob.client.screen -= other if(hotkeybuttons) mymob.client.screen -= hotkeybuttons - if(item_action_list) - mymob.client.screen -= item_action_list //These ones are not a part of 'adding', 'other' or 'hotkeybuttons' but we want them gone. mymob.client.screen -= mymob.zone_sel //zone_sel is a mob variable for some reason. diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm index 774c6f24900..64e8cdc77e9 100644 --- a/code/_onclick/hud/human.dm +++ b/code/_onclick/hud/human.dm @@ -323,100 +323,3 @@ else client.screen -= hud_used.hotkeybuttons hud_used.hotkey_ui_hidden = 1 - - -/mob/living/carbon/human/update_action_buttons() - var/num = 1 - if(!hud_used) return - if(!client) return - - if(hud_used.hud_shown != 1) //Hud toggled to minimal - return - - client.screen -= hud_used.item_action_list - - for(var/obj/item/I in src) - if(I.action_button_name) - if(hud_used.item_action_list.len < num) - var/obj/screen/item_action/N = new(hud_used) - hud_used.item_action_list += N - - var/obj/screen/item_action/A = hud_used.item_action_list[num] - - A.icon = ui_style2icon(client.prefs.UI_style) - A.icon_state = "template" - - A.overlays = list() - var/image/img = image(I.icon, A, I.icon_state) - img.pixel_x = 0 - img.pixel_y = 0 - A.overlays += img - - A.name = I.action_button_name - A.owner = I - - client.screen += hud_used.item_action_list[num] - - 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 - if(6) - A.screen_loc = ui_action_slot6 - if(7) - A.screen_loc = ui_action_slot7 - if(8) - A.screen_loc = ui_action_slot8 - if(9) - A.screen_loc = ui_action_slot9 - if(10) - A.screen_loc = ui_action_slot10 - if(11) - A.screen_loc = ui_action_slot11 - if(12) - A.screen_loc = ui_action_slot12 - if(13) - A.screen_loc = ui_action_slot13 - if(14) - A.screen_loc = ui_action_slot14 - if(15) - A.screen_loc = ui_action_slot15 - if(16) - A.screen_loc = ui_action_slot16 - if(17) - A.screen_loc = ui_action_slot17 - if(18) - A.screen_loc = ui_action_slot18 - if(19) - A.screen_loc = ui_action_slot19 - if(20) - A.screen_loc = ui_action_slot20 - if(21) - A.screen_loc = ui_action_slot21 - if(22) - A.screen_loc = ui_action_slot22 - if(23) - A.screen_loc = ui_action_slot23 - if(24) - A.screen_loc = ui_action_slot24 - if(25) - A.screen_loc = ui_action_slot25 - if(26) - A.screen_loc = ui_action_slot26 - if(27) - A.screen_loc = ui_action_slot27 - if(28) - A.screen_loc = ui_action_slot28 - if(29) - A.screen_loc = ui_action_slot29 - if(30) - A.screen_loc = ui_action_slot30 - break //30 slots available, so no more can be added. - num++ diff --git a/code/_onclick/hud/movable_screen_objects.dm b/code/_onclick/hud/movable_screen_objects.dm index 8e0455db14d..a0dc4827ba9 100644 --- a/code/_onclick/hud/movable_screen_objects.dm +++ b/code/_onclick/hud/movable_screen_objects.dm @@ -10,7 +10,7 @@ /obj/screen/movable var/snap2grid = FALSE - + var/moved = FALSE //Snap Screen Object //Tied to the grid, snaps to the nearest turf @@ -43,6 +43,7 @@ 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 diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index 69d9dfe534a..e15c104de11 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -42,32 +42,6 @@ return 1 -/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(!owner.action_button_is_hands_free && (usr.restrained() || usr.stunned || usr.lying)) - return 1 - - if(usr.stat) - return 1 - - if(!(owner in 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/drop name = "drop" icon = 'icons/mob/screen_midnight.dmi' diff --git a/code/datums/mind.dm b/code/datums/mind.dm index dbdcb3afadb..0583bb6e072 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -80,6 +80,8 @@ current = new_character //associate ourself with our new body new_character.mind = src //and associate our new body with ourself transfer_antag_huds(new_character) //inherit the antag HUDs from this mind (TODO: move this to a possible antag datum) + if(spell_list.len > 0) + transfer_mindbound_actions(new_character) if(active) new_character.key = key //now transfer the key to link the client to our new body @@ -1310,6 +1312,32 @@ ticker.mode.greet_gang(src) ticker.mode.equip_gang(current) + + +/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_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 + /mob/proc/sync_mind() mind_initialize() //updates the mind (or creates and initializes one if one doesn't exist) mind.active = 1 //indicates that the mind is currently synced with a client diff --git a/code/datums/spell.dm b/code/datums/spell.dm index 587d5f1c646..b6978142e01 100644 --- a/code/datums/spell.dm +++ b/code/datums/spell.dm @@ -53,6 +53,11 @@ 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/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/proc/cast_check(skipcharge = 0,mob/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(((!user.mind) || !(src in user.mind.spell_list)) && !(src in user.mob_spell_list)) @@ -347,4 +352,45 @@ 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.mob_spell_list)) + return 0 + + if(user.z == ZLEVEL_CENTCOM && !centcom_cancast) //Certain spells are not allowed on the centcom zlevel + return 0 + if(user.z == ZLEVEL_CENTCOM && 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 + + if(clothes_req) //clothes check + if(!istype(H.wear_suit, /obj/item/clothing/suit/wizrobe) && !istype(H.wear_suit, /obj/item/clothing/suit/space/hardsuit/wizard)) + return 0 + if(!istype(H.shoes, /obj/item/clothing/shoes/sandal)) + return 0 + if(!istype(H.head, /obj/item/clothing/head/wizard) && !istype(H.head, /obj/item/clothing/head/helmet/space/hardsuit/wizard)) + return 0 + else + if(clothes_req || human_req) + return 0 + if(nonabstract_req && (isbrain(user) || ispAI(user))) + return 0 return 1 \ No newline at end of file diff --git a/code/datums/spells/barnyard.dm b/code/datums/spells/barnyard.dm index 7b62eb90a81..5b81f684b44 100644 --- a/code/datums/spells/barnyard.dm +++ b/code/datums/spells/barnyard.dm @@ -14,6 +14,8 @@ selection_type = "range" var/list/compatible_mobs = list(/mob/living/carbon/human,/mob/living/carbon/monkey) + action_icon_state = "barn" + /obj/effect/proc_holder/spell/targeted/barnyardcurse/cast(list/targets, mob/user = usr) if(!targets.len) user << "No target found in range." diff --git a/code/datums/spells/emplosion.dm b/code/datums/spells/emplosion.dm index 33ad284421c..e27814a6fde 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/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 dc098de63f3..da2b438ebbb 100644 --- a/code/datums/spells/ethereal_jaunt.dm +++ b/code/datums/spells/ethereal_jaunt.dm @@ -13,6 +13,7 @@ centcom_cancast = 0 //Prevent people from getting to centcom nonabstract_req = 1 var/jaunt_duration = 50 //in deciseconds + action_icon_state = "jaunt" /obj/effect/proc_holder/spell/targeted/ethereal_jaunt/cast(list/targets) //magnets, so mostly hardcoded for(var/mob/living/target in targets) diff --git a/code/datums/spells/knock.dm b/code/datums/spells/knock.dm index b96c96455a8..85bcaa0c6da 100644 --- a/code/datums/spells/knock.dm +++ b/code/datums/spells/knock.dm @@ -10,6 +10,8 @@ range = 3 cooldown_min = 20 //20 deciseconds reduction per rank + action_icon_state = "knock" + /obj/effect/proc_holder/spell/aoe_turf/knock/cast(list/targets) for(var/turf/T in targets) for(var/obj/machinery/door/door in T.contents) diff --git a/code/datums/spells/lightning.dm b/code/datums/spells/lightning.dm index b3e813c7e0e..38249722221 100644 --- a/code/datums/spells/lightning.dm +++ b/code/datums/spells/lightning.dm @@ -14,6 +14,8 @@ var/ready = 0 var/image/halo = null + action_icon_state = "lightning" + /obj/effect/proc_holder/spell/targeted/lightning/Click() if(!ready) if(cast_check()) diff --git a/code/datums/spells/mime.dm b/code/datums/spells/mime.dm index 12c4a8e837b..122c89c8c74 100644 --- a/code/datums/spells/mime.dm +++ b/code/datums/spells/mime.dm @@ -12,6 +12,8 @@ range = 0 cast_sound = null + action_icon_state = "mime" + action_background_icon_state = "bg_mime" /obj/effect/proc_holder/spell/aoe_turf/conjure/mime_wall/Click() if(usr && usr.mind) @@ -35,6 +37,9 @@ range = -1 include_user = 1 + action_icon_state = "mime" + action_background_icon_state = "bg_mime" + /obj/effect/proc_holder/spell/targeted/mime/speak/Click() if(!usr) return diff --git a/code/datums/spells/mind_transfer.dm b/code/datums/spells/mind_transfer.dm index 0c8032c9b7e..710d98ba015 100644 --- a/code/datums/spells/mind_transfer.dm +++ b/code/datums/spells/mind_transfer.dm @@ -13,6 +13,8 @@ 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 + 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. Make sure spells that are removed from spell_list are actually removed and deleted when mind transfering. diff --git a/code/datums/spells/summonitem.dm b/code/datums/spells/summonitem.dm index 70becd17a9f..bdd35c2dd01 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/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 a0b201d9dd7..14ba4bad123 100644 --- a/code/datums/spells/wizard.dm +++ b/code/datums/spells/wizard.dm @@ -24,6 +24,8 @@ proj_trail_lifespan = 5 proj_trail_icon_state = "magicmd" + action_icon_state = "magicm" + /obj/effect/proc_holder/spell/targeted/inflict_handler/magic_missile amt_weakened = 3 amt_dam_fire = 10 @@ -46,6 +48,8 @@ duration = 300 cooldown_min = 300 //25 deciseconds reduction per rank + action_icon_state = "mutate" + /obj/effect/proc_holder/spell/targeted/inflict_handler/disintegrate name = "Disintegrate" desc = "This spell instantly kills somebody adjacent to you with the vilest of magick." @@ -63,6 +67,8 @@ sparks_spread = 1 sparks_amt = 4 + action_icon_state = "gib" + /obj/effect/proc_holder/spell/targeted/smoke name = "Smoke" desc = "This spell spawns a cloud of choking smoke at your location and does not require wizard garb." @@ -79,6 +85,8 @@ smoke_spread = 2 smoke_amt = 10 + action_icon_state = "smoke" + /obj/effect/proc_holder/spell/targeted/emplosion/disable_tech name = "Disable Tech" desc = "This spell disables all weapons, cameras and most other technology in range." @@ -115,6 +123,8 @@ centcom_cancast = 0 //prevent people from getting to centcom + action_icon_state = "blink" + /obj/effect/proc_holder/spell/targeted/area_teleport/teleport name = "Teleport" desc = "This spell teleports you to a type of area of your selection." @@ -146,6 +156,8 @@ summon_type = list("/obj/effect/forcefield") summon_lifespan = 300 + action_icon_state = "shield" + /obj/effect/proc_holder/spell/aoe_turf/conjure/carp name = "Summon Carp" @@ -174,6 +186,8 @@ summon_type = list(/obj/structure/constructshell) + action_icon_state = "artificer" + /obj/effect/proc_holder/spell/aoe_turf/conjure/creature name = "Summon Creature Swarm" @@ -203,6 +217,8 @@ starting_spells = list("/obj/effect/proc_holder/spell/targeted/inflict_handler/blind","/obj/effect/proc_holder/spell/targeted/genetic/blind") + action_icon_state = "blind" + /obj/effect/proc_holder/spell/targeted/inflict_handler/blind amt_eye_blind = 10 amt_eye_blurry = 20 @@ -226,6 +242,8 @@ summon_type = "/obj/structure/closet/statue" + action_icon_state = "statue" + /obj/effect/proc_holder/spell/dumbfire/fireball name = "Fireball" desc = "This spell fires a fireball at a target and does not require wizard garb." @@ -245,6 +263,8 @@ proj_lifespan = 200 proj_step_delay = 1 + action_icon_state = "fireball" + /obj/effect/proc_holder/spell/turf/fireball/cast(var/turf/T) explosion(T, -1, 0, 2, 3, 0, flame_range = 2) @@ -271,6 +291,8 @@ selection_type = "view" var/maxthrow = 5 + action_icon_state = "repulse" + /obj/effect/proc_holder/spell/aoe_turf/repulse/cast(list/targets) var/mob/user = usr var/list/thrownatoms = list() @@ -279,10 +301,10 @@ for(var/turf/T in targets) //Done this way so things don't get thrown all around hilariously. for(var/atom/movable/AM in T) thrownatoms += AM - + for(var/atom/movable/AM in thrownatoms) if(AM == user || AM.anchored) continue - + var/obj/effect/overlay/targeteffect = new /obj/effect/overlay{icon='icons/effects/effects.dmi'; icon_state="shieldsparkles"; mouse_opacity=0; density = 0}() AM.overlays += targeteffect throwtarget = get_edge_target_turf(user, get_dir(user, get_step_away(AM, user))) diff --git a/code/game/gamemodes/antag_spawner.dm b/code/game/gamemodes/antag_spawner.dm index 7be421ee470..549243bf86c 100644 --- a/code/game/gamemodes/antag_spawner.dm +++ b/code/game/gamemodes/antag_spawner.dm @@ -71,21 +71,21 @@ M << "You are the [usr.real_name]'s apprentice! You are bound by magic contract to follow their orders and help them in accomplishing their goals." switch(type) if("destruction") - M.mind.spell_list += new /obj/effect/proc_holder/spell/targeted/projectile/magic_missile(null) - M.mind.spell_list += new /obj/effect/proc_holder/spell/dumbfire/fireball(null) + M.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/projectile/magic_missile(null)) + M.mind.AddSpell(new /obj/effect/proc_holder/spell/dumbfire/fireball(null)) M << "Your service has not gone unrewarded, however. Studying under [usr.real_name], you have learned powerful, destructive spells. You are able to cast magic missile and fireball." if("bluespace") - M.mind.spell_list += new /obj/effect/proc_holder/spell/targeted/area_teleport/teleport(null) - M.mind.spell_list += new /obj/effect/proc_holder/spell/targeted/ethereal_jaunt(null) + M.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/area_teleport/teleport(null)) + M.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/ethereal_jaunt(null)) M << "Your service has not gone unrewarded, however. Studying under [usr.real_name], you have learned reality bending mobility spells. You are able to cast teleport and ethereal jaunt." if("healing") - M.mind.spell_list += new /obj/effect/proc_holder/spell/targeted/charge(null) - M.mind.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/conjure/forcewall(null) + M.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/charge(null)) + M.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/conjure/forcewall(null)) 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 [usr.real_name], you have learned livesaving survival spells. You are able to cast charge and forcewall." if("robeless") - M.mind.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/knock(null) - M.mind.spell_list += new /obj/effect/proc_holder/spell/targeted/mind_transfer(null) + M.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/knock(null)) + M.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/mind_transfer(null)) M << "Your service has not gone unrewarded, however. Studying under [usr.real_name], you have learned stealthy, robeless spells. You are able to cast knock and mindswap." equip_antag(M) diff --git a/code/game/gamemodes/wizard/spellbook.dm b/code/game/gamemodes/wizard/spellbook.dm index 7df187b1aa6..138a77305c1 100644 --- a/code/game/gamemodes/wizard/spellbook.dm +++ b/code/game/gamemodes/wizard/spellbook.dm @@ -100,7 +100,7 @@ dat += "Knock (10)
" dat += "This spell opens nearby doors and does not require wizard garb.
" - dat += "Curse of the Barnyward (15)
" + dat += "Curse of the Barnyward (15)
" dat += " This Spell dooms any unlucky soul to the life of a barnyard animal. Well not exactly but you still get to laugh at them when they MOO!. It does not require a wizard garb.
" dat += "Flesh to Stone (60)
" @@ -259,71 +259,71 @@ switch(href_list["spell_choice"]) 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.mind.spell_list += new /obj/effect/proc_holder/spell/targeted/projectile/magic_missile(null) + H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/projectile/magic_missile(null)) 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.mind.spell_list += new /obj/effect/proc_holder/spell/dumbfire/fireball(null) + H.mind.AddSpell(new /obj/effect/proc_holder/spell/dumbfire/fireball(null)) 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.mind.spell_list += new /obj/effect/proc_holder/spell/targeted/inflict_handler/disintegrate(null) + H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/inflict_handler/disintegrate(null)) 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.mind.spell_list += new /obj/effect/proc_holder/spell/targeted/emplosion/disable_tech(null) + H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/emplosion/disable_tech(null)) 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.mind.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/repulse(null) + H.mind.AddSpell(new /obj/effect/proc_holder/spell/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.mind.spell_list += new /obj/effect/proc_holder/spell/targeted/smoke(null) + H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/smoke(null)) 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.mind.spell_list += new /obj/effect/proc_holder/spell/targeted/trigger/blind(null) + H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/trigger/blind(null)) 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.mind.spell_list += new /obj/effect/proc_holder/spell/targeted/mind_transfer(null) + H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/mind_transfer(null)) 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.mind.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/conjure/forcewall(null) + H.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/conjure/forcewall(null)) 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.mind.spell_list += new /obj/effect/proc_holder/spell/targeted/turf_teleport/blink(null) + H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/turf_teleport/blink(null)) 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.mind.spell_list += new /obj/effect/proc_holder/spell/targeted/area_teleport/teleport(null) + H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/area_teleport/teleport(null)) 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.mind.spell_list += new /obj/effect/proc_holder/spell/targeted/genetic/mutate(null) + H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/genetic/mutate(null)) 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.mind.spell_list += new /obj/effect/proc_holder/spell/targeted/ethereal_jaunt(null) + H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/ethereal_jaunt(null)) 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.mind.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/knock(null) + H.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/knock(null)) temp = "You have learned knock." 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.mind.spell_list += new /obj/effect/proc_holder/spell/targeted/inflict_handler/flesh_to_stone(null) + H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/inflict_handler/flesh_to_stone(null)) temp = "You have learned flesh to stone." 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.mind.spell_list += new /obj/effect/proc_holder/spell/targeted/summonitem(null) + H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/summonitem(null)) temp = "You have learned instant summons." 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.mind.spell_list += new /obj/effect/proc_holder/spell/targeted/lightning(null) + H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/lightning(null)) temp = "You have learned lightning bolt." 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 @@ -352,7 +352,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.mind.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/conjure/construct(null) + H.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/conjure/construct(null)) temp = "You have purchased a belt full of soulstones and have learned the artificer spell." max_uses-- if("necrostone") @@ -384,7 +384,7 @@ max_uses-- if("barnyard") feedback_add_details("wizard_spell_learned","BC") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - H.mind.spell_list += new /obj/effect/proc_holder/spell/targeted/barnyardcurse(null) + H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/barnyardcurse(null)) temp = "You have learned the curse of the barnyard." if("wands") feedback_add_details("wizard_spell_learned","WA") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells @@ -439,7 +439,7 @@ if(used) recoil(user) else - user.mind.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) diff --git a/code/game/jobs/job/civilian.dm b/code/game/jobs/job/civilian.dm index cd2e564b41b..90700b72776 100644 --- a/code/game/jobs/job/civilian.dm +++ b/code/game/jobs/job/civilian.dm @@ -78,8 +78,8 @@ Mime H.equip_to_slot_or_del(new /obj/item/clothing/suit/suspenders(H), slot_wear_suit) if(H.mind) - H.mind.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/conjure/mime_wall(null) - H.mind.spell_list += new /obj/effect/proc_holder/spell/targeted/mime/speak(null) + H.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/conjure/mime_wall(null)) + H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/mime/speak(null)) H.mind.miming = 1 H.rename_self("mime") diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 20706d966fb..7260637b1ab 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -24,6 +24,7 @@ //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. @@ -307,9 +308,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) - + attack_self(usr) /obj/item/proc/IsShield() return 0 diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 956e2d99bc7..106becf41c8 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -441,9 +441,9 @@ var/list/admin_verbs_hideable = list( message_admins("[key_name_admin(usr)] gave [key_name(T)] the spell [S].") if(T.mind) - T.mind.spell_list += new S + T.mind.AddSpell(new S) else - T.mob_spell_list += new S + T.AddSpell(new S) message_admins("Spells given to mindless mobs will not be transferred in mindswap or cloning!") diff --git a/code/modules/events/holiday/xmas.dm b/code/modules/events/holiday/xmas.dm index eacc8eacaba..3f40addebdf 100644 --- a/code/modules/events/holiday/xmas.dm +++ b/code/modules/events/holiday/xmas.dm @@ -143,9 +143,9 @@ santa_objective.completed = 1 //lets cut our santas some slack. santa_objective.owner = santa.mind santa.mind.objectives += santa_objective - santa.mind.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/conjure/presents + santa.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/conjure/presents) var/obj/effect/proc_holder/spell/targeted/area_teleport/teleport/telespell = new(santa) telespell.clothes_req = 0 //santa robes aren't actually magical. - santa.mind.spell_list += telespell //does the station have chimneys? WHO KNOWS! + santa.mind.AddSpell(telespell) //does the station have chimneys? WHO KNOWS! santa << "You are Santa! Your objective is to bring joy to the people on this station. You can conjure more presents using a spell, and there are several presents in your bag." diff --git a/code/modules/events/wizard/imposter.dm b/code/modules/events/wizard/imposter.dm index e3b4c5d1fb6..5d3567a9d47 100644 --- a/code/modules/events/wizard/imposter.dm +++ b/code/modules/events/wizard/imposter.dm @@ -33,9 +33,9 @@ I.key = C.key //Operation: Fuck off and scare people - I.mind.spell_list += new /obj/effect/proc_holder/spell/targeted/area_teleport/teleport(null) - I.mind.spell_list += new /obj/effect/proc_holder/spell/targeted/turf_teleport/blink(null) - I.mind.spell_list += new /obj/effect/proc_holder/spell/targeted/ethereal_jaunt(null) + I.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/area_teleport/teleport(null)) + I.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/turf_teleport/blink(null)) + I.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/ethereal_jaunt(null)) ticker.mode.traitors += I.mind I.mind.special_role = "imposter" diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm index c1e89721f8a..2bec9a1583b 100644 --- a/code/modules/mob/living/carbon/human/inventory.dm +++ b/code/modules/mob/living/carbon/human/inventory.dm @@ -301,9 +301,6 @@ s_store = null update_inv_s_store(0) - 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() //set redraw_mob to 0 if you don't wish the hud to be updated - if you're doing it manually in your own proc. /mob/living/carbon/human/equip_to_slot(obj/item/I, slot, redraw_mob = 1) diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm index daebf276b12..76df2c205e8 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -375,8 +375,6 @@ /mob/living/carbon/handle_regular_hud_updates() if(!client) return 0 - update_action_buttons() - if(damageoverlay) if(damageoverlay.overlays) damageoverlay.overlays = list() diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm index e2f440bcfb5..3e996ed1ae0 100644 --- a/code/modules/mob/living/life.dm +++ b/code/modules/mob/living/life.dm @@ -47,6 +47,8 @@ handle_disabilities() // eye, ear, brain damages handle_status_effects() //all special effects, stunned, weakened, jitteryness, hallucination, sleeping, etc + handle_actions() + update_canmove() if(client) @@ -131,6 +133,22 @@ if(ear_damage < 100) adjustEarDamage(-0.05,-1) +/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 //this handles hud updates. Calls update_vision() and handle_hud_icons() /mob/living/proc/handle_regular_hud_updates() @@ -138,6 +156,7 @@ handle_vision() handle_hud_icons() + update_action_buttons() return 1 @@ -185,3 +204,56 @@ /mob/living/proc/handle_hud_icons_health() 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.UpdateIcon() + 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 diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index e90a20e97d0..394626546c8 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -43,3 +43,4 @@ var/list/image/staticOverlays = list() var/lying_pixel_offset = 0 //offset for pixel_y when the mob is lying down. var/has_limbs = 0 //does the mob have distinct limbs?(arms,legs, chest,head) + var/list/datum/action/actions = list() \ No newline at end of file diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 3a4af5d847c..a3d17f3c6fe 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -946,4 +946,17 @@ var/list/slot_equipment_priority = list( \ return /mob/proc/setEarDamage() + return + +/mob/proc/AddSpell(var/obj/effect/proc_holder/spell/spell) + mob_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/icons/mob/actions.dmi b/icons/mob/actions.dmi new file mode 100644 index 00000000000..568fbd295d6 Binary files /dev/null and b/icons/mob/actions.dmi differ diff --git a/tgstation.dme b/tgstation.dme index bd612a48f11..4d9c6ae81c3 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -76,6 +76,7 @@ #include "code\_onclick\overmind.dm" #include "code\_onclick\telekinesis.dm" #include "code\_onclick\hud\_defines.dm" +#include "code\_onclick\hud\action.dm" #include "code\_onclick\hud\ai.dm" #include "code\_onclick\hud\alert.dm" #include "code\_onclick\hud\alien.dm"