From 9b5a2f7490e6871c03e9d2b396d9f6e0215d18f0 Mon Sep 17 00:00:00 2001 From: XDTM Date: Thu, 28 Sep 2017 23:01:41 +0200 Subject: [PATCH] Adds action buttons for spiders, refactors action code, nurse spiders can set a hereditary directive for their children to follow --- code/datums/action.dm | 30 +- code/game/objects/effects/spiders.dm | 4 + .../browserassets/css/browserOutput.css | 2 + .../carbon/alien/humanoid/alien_powers.dm | 39 ++- code/modules/mob/living/carbon/carbon.dm | 17 - .../mob/living/carbon/carbon_defines.dm | 1 - code/modules/mob/living/carbon/life.dm | 5 +- code/modules/mob/living/living.dm | 16 + code/modules/mob/living/living_defines.dm | 2 + .../simple_animal/hostile/giant_spider.dm | 294 +++++++++++++----- code/modules/spells/spell.dm | 30 +- icons/effects/wrap_target.dmi | Bin 0 -> 599 bytes icons/mob/actions/actions_animal.dmi | Bin 0 -> 3715 bytes 13 files changed, 302 insertions(+), 138 deletions(-) create mode 100644 icons/effects/wrap_target.dmi create mode 100644 icons/mob/actions/actions_animal.dmi diff --git a/code/datums/action.dm b/code/datums/action.dm index ca71a7cbec..a65294fa40 100644 --- a/code/datums/action.dm +++ b/code/datums/action.dm @@ -485,7 +485,7 @@ /datum/action/spell_action/New(Target) ..() - var/obj/effect/proc_holder/spell/S = target + var/obj/effect/proc_holder/S = target S.action = src name = S.name desc = S.desc @@ -495,36 +495,40 @@ button.name = name /datum/action/spell_action/Destroy() - var/obj/effect/proc_holder/spell/S = target + var/obj/effect/proc_holder/S = target S.action = null return ..() /datum/action/spell_action/Trigger() if(!..()) - return 0 + return FALSE if(target) - var/obj/effect/proc_holder/spell = target - spell.Click() - return 1 + var/obj/effect/proc_holder/S = target + S.Click() + return TRUE /datum/action/spell_action/IsAvailable() if(!target) - return 0 - var/obj/effect/proc_holder/spell/spell = target - if(owner) - return spell.can_cast(owner) - return 0 + return FALSE + return TRUE +/datum/action/spell_action/spell/IsAvailable() + if(!target) + return FALSE + var/obj/effect/proc_holder/spell/S = target + if(owner) + return S.can_cast(owner) + return FALSE /datum/action/spell_action/alien /datum/action/spell_action/alien/IsAvailable() if(!target) - return 0 + return FALSE var/obj/effect/proc_holder/alien/ab = target if(owner) return ab.cost_check(ab.check_turf,owner,1) - return 0 + return FALSE diff --git a/code/game/objects/effects/spiders.dm b/code/game/objects/effects/spiders.dm index 7a0faed690..6722ffd89b 100644 --- a/code/game/objects/effects/spiders.dm +++ b/code/game/objects/effects/spiders.dm @@ -52,6 +52,7 @@ icon_state = "eggs" var/amount_grown = 0 var/player_spiders = 0 + var/directive = "" //Message from the mother var/poison_type = "toxin" var/poison_per_bite = 5 var/list/faction = list("spiders") @@ -71,6 +72,7 @@ S.poison_type = poison_type S.poison_per_bite = poison_per_bite S.faction = faction.Copy() + S.directive = directive if(player_spiders) S.player_spiders = 1 qdel(src) @@ -87,6 +89,7 @@ var/obj/machinery/atmospherics/components/unary/vent_pump/entry_vent var/travelling_in_vent = 0 var/player_spiders = 0 + var/directive = "" //Message from the mother var/poison_type = "toxin" var/poison_per_bite = 5 var/list/faction = list("spiders") @@ -192,6 +195,7 @@ S.poison_per_bite = poison_per_bite S.poison_type = poison_type S.faction = faction.Copy() + S.directive = directive if(player_spiders) S.playable_spider = TRUE notify_ghosts("Spider [S.name] can be controlled", null, enter_link="(Click to play)", source=S, action=NOTIFY_ATTACK) diff --git a/code/modules/goonchat/browserassets/css/browserOutput.css b/code/modules/goonchat/browserassets/css/browserOutput.css index fa2c5d056c..f6810d0b05 100644 --- a/code/modules/goonchat/browserassets/css/browserOutput.css +++ b/code/modules/goonchat/browserassets/css/browserOutput.css @@ -353,6 +353,8 @@ h1.alert, h2.alert {color: #000000;} .borer {color: #543354; font-style: italic;} .changeling {color: #800080; font-style: italic;} +.spider {color: #4d004d;} + .interface {color: #330033;} .sans {font-family: "Comic Sans MS", cursive, sans-serif;} diff --git a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm index e6a5f58d69..1390028282 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm @@ -10,15 +10,15 @@ Doesn't work on other aliens/AI.*/ name = "Alien Power" panel = "Alien" var/plasma_cost = 0 - var/check_turf = 0 - var/has_action = 1 - var/datum/action/spell_action/alien/action = null - var/action_icon = 'icons/mob/actions/actions_xeno.dmi' - var/action_icon_state = "spell_default" - var/action_background_icon_state = "bg_alien" + var/check_turf = FALSE + has_action = TRUE + datum/action/spell_action/alien/action + action_icon = 'icons/mob/actions/actions_xeno.dmi' + action_icon_state = "spell_default" + action_background_icon_state = "bg_alien" -/obj/effect/proc_holder/alien/New() - ..() +/obj/effect/proc_holder/alien/Initialize() + . = ..() action = new(src) /obj/effect/proc_holder/alien/Click() @@ -30,15 +30,20 @@ Doesn't work on other aliens/AI.*/ user.adjustPlasma(-plasma_cost) return 1 -/obj/effect/proc_holder/alien/proc/on_gain(mob/living/carbon/user) +/obj/effect/proc_holder/alien/on_gain(mob/living/carbon/user) return -/obj/effect/proc_holder/alien/proc/on_lose(mob/living/carbon/user) +/obj/effect/proc_holder/alien/on_lose(mob/living/carbon/user) return -/obj/effect/proc_holder/alien/proc/fire(mob/living/carbon/user) +/obj/effect/proc_holder/alien/fire(mob/living/carbon/user) return 1 +/obj/effect/proc_holder/alien/get_panel_text() + . = ..() + if(plasma_cost > 0) + return "[plasma_cost]" + /obj/effect/proc_holder/alien/proc/cost_check(check_turf=0,mob/living/carbon/user,silent = 0) if(user.stat) if(!silent) @@ -168,7 +173,6 @@ Doesn't work on other aliens/AI.*/ if(user.getPlasma() > A.plasma_cost && A.corrode(O)) user.adjustPlasma(-A.plasma_cost) - /obj/effect/proc_holder/alien/neurotoxin name = "Spit Neurotoxin" desc = "Spits neurotoxin at someone, paralyzing them for a short time." @@ -179,7 +183,7 @@ Doesn't work on other aliens/AI.*/ var/message if(active) message = "You empty your neurotoxin gland." - remove_ranged_ability(user,message) + remove_ranged_ability(message) else message = "You prepare your neurotoxin gland. Left-click to fire at a target!" add_ranged_ability(user, message, TRUE) @@ -193,7 +197,7 @@ Doesn't work on other aliens/AI.*/ return var/p_cost = 50 if(!iscarbon(ranged_ability_user) || ranged_ability_user.lying || ranged_ability_user.stat) - remove_ranged_ability(ranged_ability_user) + remove_ranged_ability() return var/mob/living/carbon/user = ranged_ability_user @@ -219,8 +223,7 @@ Doesn't work on other aliens/AI.*/ return TRUE /obj/effect/proc_holder/alien/neurotoxin/on_lose(mob/living/carbon/user) - if(user.ranged_ability == src) - user.ranged_ability = null + remove_ranged_ability() /obj/effect/proc_holder/alien/neurotoxin/add_ranged_ability(mob/living/user, msg) ..() @@ -328,7 +331,3 @@ Doesn't work on other aliens/AI.*/ return 1 return 0 - - -/proc/cmp_abilities_cost(obj/effect/proc_holder/alien/a, obj/effect/proc_holder/alien/b) - return b.plasma_cost - a.plasma_cost diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index aa72ebfa9f..80c6d836a0 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -425,23 +425,6 @@ var/turf/target = get_turf(loc) I.throw_at(target,I.throw_range,I.throw_speed,src) -/mob/living/carbon/proc/AddAbility(obj/effect/proc_holder/alien/A) - abilities.Add(A) - A.on_gain(src) - if(A.has_action) - A.action.Grant(src) - sortInsert(abilities, /proc/cmp_abilities_cost, 0) - -/mob/living/carbon/proc/RemoveAbility(obj/effect/proc_holder/alien/A) - abilities.Remove(A) - A.on_lose(src) - if(A.action) - A.action.Remove(src) - -/mob/living/carbon/proc/add_abilities_to_panel() - for(var/obj/effect/proc_holder/alien/A in abilities) - statpanel("[A.panel]",A.plasma_cost > 0?"([A.plasma_cost])":"",A) - /mob/living/carbon/Stat() ..() if(statpanel("Status")) diff --git a/code/modules/mob/living/carbon/carbon_defines.dm b/code/modules/mob/living/carbon/carbon_defines.dm index 8e9f66de31..45c10c6ae9 100644 --- a/code/modules/mob/living/carbon/carbon_defines.dm +++ b/code/modules/mob/living/carbon/carbon_defines.dm @@ -35,7 +35,6 @@ has_limbs = 1 var/obj/item/reagent_containers/food/snacks/meat/slab/type_of_meat = /obj/item/reagent_containers/food/snacks/meat/slab - var/list/obj/effect/proc_holder/alien/abilities = list() var/gib_type = /obj/effect/decal/cleanable/blood/gibs var/rotate_on_lying = 1 diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm index b2e88e278a..47458b01d2 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -412,8 +412,9 @@ liver_failure() else liver.failing = FALSE - - if(((!(NOLIVER in dna.species.species_traits)) && (!liver))) + else + if((dna && dna.species && (NOLIVER in dna.species.species_traits))) + return liver_failure() /mob/living/carbon/proc/undergoing_liver_failure() diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 649e19ba29..1cf99e8d9e 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -982,3 +982,19 @@ client.move_delay = world.time + movement_delay() lying_prev = lying return canmove + +/mob/living/proc/AddAbility(obj/effect/proc_holder/A) + abilities.Add(A) + A.on_gain(src) + if(A.has_action) + A.action.Grant(src) + +/mob/living/proc/RemoveAbility(obj/effect/proc_holder/A) + abilities.Remove(A) + A.on_lose(src) + if(A.action) + A.action.Remove(src) + +/mob/living/proc/add_abilities_to_panel() + for(var/obj/effect/proc_holder/A in abilities) + statpanel("[A.panel]",A.get_panel_text(),A) \ No newline at end of file diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index f32ca97b09..36b8c62cca 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -77,3 +77,5 @@ var/datum/language/selected_default_language var/last_words //used for database logging + + var/list/obj/effect/proc_holder/abilities = list() diff --git a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm index 6ae5fe0622..f6a7c7c54a 100644 --- a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm +++ b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm @@ -48,7 +48,21 @@ see_in_dark = 4 lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE var/playable_spider = FALSE +<<<<<<< HEAD devourable = TRUE +======= + var/datum/action/innate/spider/lay_web/lay_web + var/directive = "" //Message passed down to children, to relay the creator's orders + +/mob/living/simple_animal/hostile/poison/giant_spider/Initialize() + . = ..() + lay_web = new + lay_web.Grant(src) + +/mob/living/simple_animal/hostile/poison/giant_spider/Destroy() + QDEL_NULL(lay_web) + return ..() +>>>>>>> 152c890... Adds action buttons for spiders, refactors action code, nurse spiders can set a hereditary directive for their children to follow (#30572) /mob/living/simple_animal/hostile/poison/giant_spider/Topic(href, href_list) if(href_list["activate"]) @@ -56,6 +70,12 @@ if(istype(ghost) && playable_spider) humanize_spider(ghost) +/mob/living/simple_animal/hostile/poison/giant_spider/Login() + ..() + if(directive) + to_chat(src, "Your mother left you a directive! Follow it at all costs.") + to_chat(src, "[directive]") + /mob/living/simple_animal/hostile/poison/giant_spider/attack_ghost(mob/user) if(!humanize_spider(user)) return ..() @@ -87,8 +107,26 @@ poison_per_bite = 3 var/atom/movable/cocoon_target var/fed = 0 + var/obj/effect/proc_holder/wrap/wrap + var/datum/action/innate/spider/lay_eggs/lay_eggs + var/datum/action/innate/spider/set_directive/set_directive var/static/list/consumed_mobs = list() //the tags of mobs that have been consumed by nurse spiders to lay eggs +/mob/living/simple_animal/hostile/poison/giant_spider/nurse/Initialize() + . = ..() + wrap = new + AddAbility(wrap) + lay_eggs = new + lay_eggs.Grant(src) + set_directive = new + set_directive.Grant(src) + +/mob/living/simple_animal/hostile/poison/giant_spider/nurse/Destroy() + RemoveAbility(wrap) + QDEL_NULL(lay_eggs) + QDEL_NULL(set_directive) + return ..() + //hunters have the most poison and move the fastest, so they can find prey /mob/living/simple_animal/hostile/poison/giant_spider/hunter desc = "Furry and black, it makes you shudder to look at it. This one has sparkling purple eyes." @@ -162,6 +200,9 @@ letmetalkpls = new letmetalkpls.Grant(src) +/mob/living/simple_animal/hostile/poison/giant_spider/nurse/midwife/Destroy() + QDEL_NULL(letmetalkpls) + return ..() /mob/living/simple_animal/hostile/poison/giant_spider/ice //spiders dont usually like tempatures of 140 kelvin who knew name = "giant ice spider" @@ -225,11 +266,11 @@ //second, spin a sticky spiderweb on this tile var/obj/structure/spider/stickyweb/W = locate() in get_turf(src) if(!W) - Web() + lay_web.Activate() else //third, lay an egg cluster there if(fed) - LayEggs() + lay_eggs.Activate() else //fourthly, cocoon any nearby items so those pesky pinkskins can't use them for(var/obj/O in can_see) @@ -247,62 +288,28 @@ else if(busy == MOVING_TO_TARGET && cocoon_target) if(get_dist(src, cocoon_target) <= 1) - Wrap() + cocoon() else busy = SPIDER_IDLE stop_automated_movement = FALSE -/mob/living/simple_animal/hostile/poison/giant_spider/verb/Web() - set name = "Lay Web" - set category = "Spider" - set desc = "Spread a sticky web to slow down prey." - - var/T = src.loc - - if(stat == DEAD) - return - if(busy != SPINNING_WEB) - busy = SPINNING_WEB - src.visible_message("\the [src] begins to secrete a sticky substance.") - stop_automated_movement = 1 - if(do_after(src, 40, target = T)) - if(busy == SPINNING_WEB && src.loc == T) - new /obj/structure/spider/stickyweb(T) - busy = SPIDER_IDLE - stop_automated_movement = FALSE - - -/mob/living/simple_animal/hostile/poison/giant_spider/nurse/verb/Wrap() - set name = "Wrap" - set category = "Spider" - set desc = "Wrap up prey to feast upon and objects for safe keeping." - - if(stat == DEAD) - return - if(!cocoon_target) - var/list/choices = list() - for(var/mob/living/L in view(1,src)) - if(L == src || L.anchored) - continue - if(istype(L, /mob/living/simple_animal/hostile/poison/giant_spider)) - continue - if(Adjacent(L)) - choices += L - for(var/obj/O in src.loc) - if(O.anchored) - continue - if(Adjacent(O)) - choices += O - var/temp_input = input(src,"What do you wish to cocoon?") in null|choices - if(temp_input && !cocoon_target) - cocoon_target = temp_input - - if(stat != DEAD && cocoon_target && Adjacent(cocoon_target) && !cocoon_target.anchored) +/mob/living/simple_animal/hostile/poison/giant_spider/nurse/proc/cocoon() + if(stat != DEAD && cocoon_target && !cocoon_target.anchored) + if(cocoon_target == src) + to_chat(src, "You can't wrap yourself!") + return + if(istype(cocoon_target, /mob/living/simple_animal/hostile/poison/giant_spider)) + to_chat(src, "You can't wrap other spiders!") + return + if(!Adjacent(cocoon_target)) + to_chat(src, "You can't reach [cocoon_target]!") + return if(busy == SPINNING_COCOON) + to_chat(src, "You're already spinning a cocoon!") return //we're already doing this, don't cancel out or anything busy = SPINNING_COCOON - visible_message("\the [src] begins to secrete a sticky substance around \the [cocoon_target].") + visible_message("[src] begins to secrete a sticky substance around [cocoon_target].","You begin wrapping [cocoon_target] into a cocoon.") stop_automated_movement = TRUE walk(src,0) if(do_after(src, 50, target = cocoon_target)) @@ -313,7 +320,8 @@ if(L.blood_volume && (L.stat != DEAD || !consumed_mobs[L.tag])) //if they're not dead, you can consume them anyway consumed_mobs[L.tag] = TRUE fed++ - visible_message("\the [src] sticks a proboscis into \the [L] and sucks a viscous substance out.") + lay_eggs.UpdateButtonIcon(TRUE) + visible_message("[src] sticks a proboscis into [L] and sucks a viscous substance out.","You suck the nutriment out of [L], feeding you enough to lay a cluster of eggs.") L.death() //you just ate them, they're dead. else to_chat(src, "[L] cannot sate your hunger!") @@ -325,35 +333,155 @@ busy = SPIDER_IDLE stop_automated_movement = FALSE -/mob/living/simple_animal/hostile/poison/giant_spider/nurse/verb/LayEggs() - set name = "Lay Eggs" - set category = "Spider" - set desc = "Lay a clutch of eggs, but you must wrap a creature for feeding first." +/datum/action/innate/spider + icon_icon = 'icons/mob/actions/actions_animal.dmi' + background_icon_state = "bg_alien" - var/obj/structure/spider/eggcluster/E = locate() in get_turf(src) - if(stat == DEAD) +/datum/action/innate/spider/lay_web + name = "Spin Web" + desc = "Spin a web to slow down potential prey." + check_flags = AB_CHECK_CONSCIOUS + button_icon_state = "lay_web" + +/datum/action/innate/spider/lay_web/Activate() + if(!istype(owner, /mob/living/simple_animal/hostile/poison/giant_spider/nurse)) return + var/mob/living/simple_animal/hostile/poison/giant_spider/nurse/S = owner + + if(!isturf(S.loc)) + return + var/turf/T = get_turf(S) + + var/obj/structure/spider/stickyweb/W = locate() in T + if(W) + to_chat(S, "There's already a web here!") + return + + if(S.busy != SPINNING_WEB) + S.busy = SPINNING_WEB + S.visible_message("[S] begins to secrete a sticky substance.","You begin to lay a web.") + S.stop_automated_movement = TRUE + if(do_after(S, 40, target = T)) + if(S.busy == SPINNING_WEB && S.loc == T) + new /obj/structure/spider/stickyweb(T) + S.busy = SPIDER_IDLE + S.stop_automated_movement = FALSE + else + to_chat(S, "You're already spinning a web!") + +/obj/effect/proc_holder/wrap + name = "Wrap" + panel = "Spider" + active = FALSE + datum/action/spell_action/action = null + desc = "Wrap something or someone in a cocoon. If it's a living being, you'll also consume them, allowing you to lay eggs." + ranged_mousepointer = 'icons/effects/wrap_target.dmi' + action_icon = 'icons/mob/actions/actions_animal.dmi' + action_icon_state = "wrap_0" + action_background_icon_state = "bg_alien" + +/obj/effect/proc_holder/wrap/Initialize() + . = ..() + action = new(src) + +/obj/effect/proc_holder/wrap/update_icon() + action.button_icon_state = "wrap_[active]" + action.UpdateButtonIcon() + +/obj/effect/proc_holder/wrap/Click() + if(!istype(usr, /mob/living/simple_animal/hostile/poison/giant_spider/nurse)) + return TRUE + var/mob/living/simple_animal/hostile/poison/giant_spider/nurse/user = usr + activate(user) + return TRUE + +/obj/effect/proc_holder/wrap/proc/activate(mob/living/user) + var/message + if(active) + message = "You no longer prepare to wrap something in a cocoon." + remove_ranged_ability(message) + else + message = "You prepare to wrap something in a cocoon. Left-click your target to start wrapping!" + add_ranged_ability(user, message, TRUE) + return 1 + +/obj/effect/proc_holder/wrap/InterceptClickOn(mob/living/caller, params, atom/target) + if(..()) + return + if(ranged_ability_user.incapacitated() || !istype(ranged_ability_user, /mob/living/simple_animal/hostile/poison/giant_spider/nurse)) + remove_ranged_ability() + return + + var/mob/living/simple_animal/hostile/poison/giant_spider/nurse/user = ranged_ability_user + + if(user.Adjacent(target) && (ismob(target) || isobj(target))) + var/atom/movable/target_atom = target + if(target_atom.anchored) + return + user.cocoon_target = target_atom + INVOKE_ASYNC(user, /mob/living/simple_animal/hostile/poison/giant_spider/nurse/.proc/cocoon) + remove_ranged_ability() + return TRUE + +/obj/effect/proc_holder/wrap/on_lose(mob/living/carbon/user) + remove_ranged_ability() + +/datum/action/innate/spider/lay_eggs + name = "Lay Eggs" + desc = "Lay a cluster of eggs, which will soon grow into more spiders. You must wrap a living being to do this." + check_flags = AB_CHECK_CONSCIOUS + button_icon_state = "lay_eggs" + +/datum/action/innate/spider/lay_eggs/IsAvailable() + if(..()) + if(!istype(owner, /mob/living/simple_animal/hostile/poison/giant_spider/nurse)) + return 0 + var/mob/living/simple_animal/hostile/poison/giant_spider/nurse/S = owner + if(S.fed) + return 1 + return 0 + +/datum/action/innate/spider/lay_eggs/Activate() + if(!istype(owner, /mob/living/simple_animal/hostile/poison/giant_spider/nurse)) + return + var/mob/living/simple_animal/hostile/poison/giant_spider/nurse/S = owner + + var/obj/structure/spider/eggcluster/E = locate() in get_turf(S) if(E) - to_chat(src, "There is already a cluster of eggs here!") - else if(!fed) - to_chat(src, "You are too hungry to do this!") - else if(busy != LAYING_EGGS) - busy = LAYING_EGGS - src.visible_message("\the [src] begins to lay a cluster of eggs.") - stop_automated_movement = 1 - if(do_after(src, 50, target = src.loc)) - if(busy == LAYING_EGGS) - E = locate() in get_turf(src) - if(!E) - var/obj/structure/spider/eggcluster/C = new /obj/structure/spider/eggcluster(src.loc) - if(ckey) - C.player_spiders = 1 - C.poison_type = poison_type - C.poison_per_bite = poison_per_bite - C.faction = faction.Copy() - fed-- - busy = SPIDER_IDLE - stop_automated_movement = FALSE + to_chat(S, "There is already a cluster of eggs here!") + else if(!S.fed) + to_chat(S, "You are too hungry to do this!") + else if(S.busy != LAYING_EGGS) + S.busy = LAYING_EGGS + S.visible_message("[S] begins to lay a cluster of eggs.","You begin to lay a cluster of eggs.") + S.stop_automated_movement = TRUE + if(do_after(S, 50, target = get_turf(S))) + if(S.busy == LAYING_EGGS) + E = locate() in get_turf(S) + if(!E || !isturf(S.loc)) + var/obj/structure/spider/eggcluster/C = new /obj/structure/spider/eggcluster(get_turf(S)) + if(S.ckey) + C.player_spiders = TRUE + C.directive = S.directive + C.poison_type = S.poison_type + C.poison_per_bite = S.poison_per_bite + C.faction = S.faction.Copy() + S.fed-- + UpdateButtonIcon(TRUE) + S.busy = SPIDER_IDLE + S.stop_automated_movement = FALSE + +/datum/action/innate/spider/set_directive + name = "Set Directive" + desc = "Set a directive for your children to follow." + check_flags = AB_CHECK_CONSCIOUS + button_icon_state = "directive" + +/datum/action/innate/spider/set_directive/Activate() + if(!istype(owner, /mob/living/simple_animal/hostile/poison/giant_spider/nurse)) + return + var/mob/living/simple_animal/hostile/poison/giant_spider/nurse/S = owner + S.directive = stripped_input(S, "Enter the new directive", "Create directive", "[S.directive]", MAX_MESSAGE_LEN) /mob/living/simple_animal/hostile/poison/giant_spider/Login() . = ..() @@ -365,7 +493,8 @@ /datum/action/innate/spider/comm name = "Command" - button_icon_state = "cult_comms" + desc = "Send a command to all living spiders." + button_icon_state = "command" /datum/action/innate/spider/comm/IsAvailable() if(!istype(owner, /mob/living/simple_animal/hostile/poison/giant_spider/nurse/midwife)) @@ -373,19 +502,22 @@ return TRUE /datum/action/innate/spider/comm/Trigger() - var/input = stripped_input(usr, "Input a message for your legions to follow.", "Command", "") + var/input = stripped_input(owner, "Input a command for your legions to follow.", "Command", "") if(QDELETED(src) || !input || !IsAvailable()) return FALSE - spider_command(usr, input) + spider_command(owner, input) return TRUE /datum/action/innate/spider/comm/proc/spider_command(mob/living/user, message) if(!message) return var/my_message - my_message = "COMMAND FROM SPIDER QUEEN: [message]" + my_message = "Command from [user]: [message]" for(var/mob/living/simple_animal/hostile/poison/giant_spider/M in GLOB.spidermobs) to_chat(M, my_message) + for(var/M in GLOB.dead_mob_list) + var/link = FOLLOW_LINK(M, user) + to_chat(M, "[link] [my_message]") log_talk(user, "SPIDERCOMMAND: [key_name(user)] : [message]",LOGSAY) /mob/living/simple_animal/hostile/poison/giant_spider/handle_temperature_damage() diff --git a/code/modules/spells/spell.dm b/code/modules/spells/spell.dm index 3cb56becf8..d3008625cf 100644 --- a/code/modules/spells/spell.dm +++ b/code/modules/spells/spell.dm @@ -8,6 +8,28 @@ var/ranged_mousepointer var/mob/living/ranged_ability_user var/ranged_clickcd_override = -1 + var/has_action = TRUE + var/datum/action/spell_action/action = null + var/action_icon = 'icons/mob/actions/actions_spells.dmi' + var/action_icon_state = "spell_default" + var/action_background_icon_state = "bg_spell" + +/obj/effect/proc_holder/Initialize() + . = ..() + if(has_action) + action = new(src) + +/obj/effect/proc_holder/proc/on_gain(mob/living/user) + return + +/obj/effect/proc_holder/proc/on_lose(mob/living/user) + return + +/obj/effect/proc_holder/proc/fire(mob/living/user) + return TRUE + +/obj/effect/proc_holder/proc/get_panel_text() + return "" GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for the badmin verb for now @@ -118,10 +140,10 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th var/critfailchance = 0 var/centcom_cancast = 1 //Whether or not the spell should be allowed on z2 - var/action_icon = 'icons/mob/actions/actions_spells.dmi' - var/action_icon_state = "spell_default" - var/action_background_icon_state = "bg_spell" - var/datum/action/spell_action/action + action_icon = 'icons/mob/actions/actions_spells.dmi' + action_icon_state = "spell_default" + action_background_icon_state = "bg_spell" + datum/action/spell_action/spell/action /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 diff --git a/icons/effects/wrap_target.dmi b/icons/effects/wrap_target.dmi new file mode 100644 index 0000000000000000000000000000000000000000..2e9a338c9ec23cc661af9298a9cd025367471991 GIT binary patch literal 599 zcmV-d0;v6oP)qPPdPJ>v%MQdqIDP^eXMp2j@0Q#v@dgmK0KEEXfzpqO9#r@j;F9vA)zZjtI|6+o+|4Zom lznGxz{}K=Me~Bmi|2MAsB*>D-4DSE{002ovPDHLkV1fu=DlY&4 literal 0 HcmV?d00001 diff --git a/icons/mob/actions/actions_animal.dmi b/icons/mob/actions/actions_animal.dmi new file mode 100644 index 0000000000000000000000000000000000000000..1dcf7590cd0fabdb06af0c2c6c488bce9fc6f0cb GIT binary patch literal 3715 zcmZ`+cT^MG*By$F8VJ2ZfPi#Flp2&yK#(Ra^qx?IAksuY6d?ox3g`oAf=Cgh1QZ2A zZ%VgNLzN=EO7)xf`~O?(oVl}R&6#`dzI*RAH_`020fe5H9smG{AyU@@99_WFr2PlH zE?v9J1P)mdcWgs+J%iovVz42YzyJUU%fa_G(YM3cHRtT|=F`{3FrOOPb+AY$t$>Ah z^v9A?X`de?Xg0Vt1kaYw4IlVWt4cImK8?25BAt(5Gn)*VsHZA(RCm7@2fMZD!t(#! z8G4z^;oX%$ONknAqTo_H{e73z5OCq{pY}BjU8BTVuoL@c@xD|a#-7vRtGtblvJv6Y zypWKiJ`96ov@q@)I&eMZvuaRn)o4q&o3Hd9MOX$pZI^r>}x)DJQD9y zdkp+`F3?01w9y9EM60BZ)Q2&`w(8%Z!kndI`>7)}YI<&rT~bC9FeI;m+#W0DHwM}4 zwTQCjGY-HkF!XLPFE`zA-r~O;v<@62&7-!OBFUe&mQT-{w@zmiJKd^h%p~drdBYI7 zMWLzPqkOndSkkd%Uh9mKRSo?lP;Hx>PU?E#&+VpBke?rOjg8qwXEa%xK;9}578Oi=-Q0Y`m;Ou9 z83M-QRA=o=9XfSq#-(8rBjMi78m>sE72V>D?_NNo(J`Z|@iP4cPo7p6GY)EsY~{dQ zOOdOxWWTx?AFYa;oH+Ah5CORS&`f*8P!U(%swZ-_ZR@B!pn*^R^ETyFfHJ#Y?Bs^N zogI&ludlhI<13GsFS{Iil&KQ2EV$0}8iB)qCDN@zCD>6y^pC$sB66MPIrIfv_oAvg z-7wlB)M>{hMB3ByXkuk0(~Uf4rECZoh(R58J&B|^tO{f9GWb!AS4XCN!D3{@G|e#T zv!H6}rZ-1kB@H3#{zr%RwlYt3MaSIF8efs@c|UFjq*iy{+sB~BbM z?eAzfDKnFkSX4v}77U}G*WXHy4?{57Wx5hkU|{UU6@KhiiNsi``1W@6jaL^+R9@C4 zoXtpNkH{Q0s(Z+yP^dAJY$XanB#kyEJ|l>qCU;r5|0>)t4n|9x&<;WmT-DcBS}fs+ zdz17V#hSb+d{5+wOgnUJWTepA#-@GgZb3x_qjmZ9QnC-RZ4OIXx=R5R4ok>zGJx2( z&motI79#e$B~AYrbEN;&c+3*iae_zW7Z>YI6MebBU1{AzR9H)g<HH>=Z&_rEQ z5Wk1r8;1Ns36=0&xQ~yI7m=&y%^8nun`IiXk{}Wac|W;fqAzG>VL{n22{BBc4N)sS z4dzck!YS=CS@8P*MQS&Odu4M|{|a|buk@1fg%x#C**C)V*mag3=Q7pg&!nCca`>{q zx8=Q7x9Xu6YoVXOs#0QajWL&|Ir}h~Y}!3o4^Q(yZd^jgu?xcud)J@f$6}BYB1F-7 zfug)p4zc2j8W~GzX-Uae5(!Ac;V^kJ{nrj~-3$Aj%z}s)`@2F>+Z10rOW0UzWXX&x z(kQ;$7P1{h2rY!RJbU#~t;hR4ezg$fbRCAxL5_=EPYWSv5EP`KYu+*6iJJ>iTXjP| zrv~P*+!+}eDj_QbBd6wq0tyHO^0vJEmW965qV^4lmfu{mi7LLC4egGoj;Kcz2&h{r z>D3=Cw!jVRru~%MLqgd3yM+Z)+vl)mxc%d(?c*p=Seh`XnY6StxJ+g(D6IeL+S=ON zyT7u}5brF0Ufng;dxE~QtChwn6W=b2_!awjez85N}%GBbI9kR>kis?(t@J< zBn(-JW2-Vr9|?iteTFm>C#Gem$kr79>@ufCtO}GVL70|u`U{qyCaYiXegR@|VXV}W zo0~fZZV0NPP(qts53rfPRyqtMI{Nzi|3^rR2raqAQE1T-oyA_b`BA}m=sV9^S30E3 z_oDc(nOA5*s^;9j%+Evv@+PhoMy&-3M?zlS03nzFqkUUZQN-Z>@Zrsq)6>%HM(MhW z92QdI#OzW6!*Sy&@J^L*v@tOgJ5Q zJ3T!OvR^KXp+@F)ON&rap(d1?or6P|7jMy7q@yXfSTgmrSPi1ZY2TEp=!bvmK-H@Y zI`09B_22Al6A&yaDyqZ;#q3qDx1T@fWJbnzwAng3;?vVvfyA%R`j-lWqC7m}n-Sy2 zvW|_{zWx5C8||dFlSlO15HUi+B+(M=g|4^w_J{=rgSBhFf17}&xD+m!hNK2J;dTid zfVS42;sd5(<96I8D1Nx1O7xiuFCX9N1i{lX zy6+XX5tca^K}mq=efsIs)QTSH>e9E2jQn)6`Dx2-sV}3h33LHY+$9h%kRj>t*yV5( z{yCgZDI4!48V8$Q?0tp~2*|Zggn?dQ0*rIi<`x`5v{Gq9bMKr|Skq0^A0CEs01*)p zBhkNBrEX^Ln&^A$jPF0wU^5zcN{RHL+ShrR$=`%`o(Q~Z04o{0D?ECIVWfYxH_(6L zr4K~7fDSoB^M$6fw&&NlnRTWlCyqxdXqSPL=7y1o9?1ue?G}OF-j~04DJHcQ zQ`A@eufqMDnj_Hat-evFN!|_0cYZY=pk~1>eC48X6jNOUp+`Gm*>< z_$dJ(rVvjKYf%fDwt^GLqr##Yoq^N!92IA5Lb(8dIGw5uyZE^Lj3)5Yu4QU+xIkQ8 zlKh9gTY)P4`rWZi0BL8Tn*wNU%fH{BDQnv_LDjFZ+|->S(EjSu0YzvE&tnn%d|uR= zVSKwQ|B4C$-tzt})V|)Y)o0M>^Pdr%O6WSb_Csc|!D>k3iw3))=9KOnU5xamzyWHL zd)Mh?@d*jyTwz+X-Powc$jrRZlO}3ghh~|H+A}GOihCJfSeejhtc#I9-xOPqc2hpw z9LF&|G#L3%R#sNNXt~5zM60)#32-ixTf_-jSqZhczrU{k-Osr{UgKF;RaeJ;e0*$M z>jjBBeI1L}v!~*+IS6lYJPHhavv_lFU$LjZzrD*jpku&MU2DHK#Pc;yd&vi)^g@n-W2qM|Kes$r(0_~^G)N_ zf0UG!|Fc}rHxs0t+|c)VH<1-Z9snprEFf zG^$auBWei&W>@l3;(EGc$3_RyEEju|rlmh*iLOzUD)(=4Q?eETq+g9UznoAV zZJs)3O$}r`0!SP(G{BUD@9u=3(%Hf+769Vb6artCDiPdxjbdOB6KO`P&sGJ6A-itA z^JM9FRV1(4f}LS~fF!VVe>P-rb&QRLa=-)45`DTdD%BEkNzUnvx9_LQcg{e~$@0lN zCAHB0O8JgI)Z1MbmclL{1E%GZ+o@m)$9jfkb_&= zi}Me6^5hF&yx`UuO*!XLU2Bb?!gh*Ygl{-EH8?kS4^drhWR~#c71tX%#R-s=c9Cr9CUaGXnzoSSme?_Qk!;DH!e#)dK4yhpeT zqt)^SYdJ8FVbj<4H(r~TgLB6Y4=W@mC%gIY{FC!%Ti({K)@A(Q@$3if{eye$0WEay z?&6FPJ#=1Kio0zywWlBB?l!HsIN)Obi#+x}Pof_gDzhueQ`G&T<0zif`h4|rtQ-YO ztW4^?pB;;>1@gnr*`Lay8@SG-TJMDIugX~pH!8Jx_zXr<>ML?T!Qmd3;tWRGyjK{t z{Hp?NvSg|?Uzr8<^U4n}KhUog3jcHUiRUE}wGra}>S0D$bc$lD>HFI7!_}1|o+s*a zZv?7dHlLiZy0z2SZ~Y8*-gwlajFF98w}0kJJ`{-Dv^TpLL%w_xfyj-dfU(mznNFaN z&QaH2a*Em2cQ1TY1|L;zh;9TQ{UJa2GPy-@lRfHkSpnHw21;=MFVBQvtTnFhEj?7h QQzc-icU!ko+a>P*0J=i=h5!Hn literal 0 HcmV?d00001