[MIRROR] Basic Mob Spiders I: Ability refactor [MDB IGNORE] (#19200)

* Basic Mob Spiders I: Ability refactor

* Update tgstation.dme

* Update tgstation.dme

* Update tgstation.dme

* Update tgstation.dme

* Update tgstation.dme

* Update tgstation.dme

---------

Co-authored-by: Jacquerel <hnevard@gmail.com>
Co-authored-by: KathrinBailey <53862927+KathrinBailey@users.noreply.github.com>
Co-authored-by: KathrinBailey <kat892@outlook.com>
This commit is contained in:
SkyratBot
2023-02-22 19:49:39 +01:00
committed by GitHub
parent 5f1fe0a0a9
commit bb9b68a88d
11 changed files with 380 additions and 389 deletions
@@ -0,0 +1,70 @@
/**
* Sets a directive to be given to all future spiders created by the user.
* This will be overwritten if used again.
*/
/datum/action/set_spider_directive
name = "Set Directive"
desc = "Set a directive for your future children to follow."
button_icon = 'icons/mob/actions/actions_animal.dmi'
button_icon_state = "directive"
background_icon_state = "bg_alien"
overlay_icon_state = "bg_alien_border"
check_flags = AB_CHECK_CONSCIOUS
/// Current directive to apply
var/current_directive = ""
/datum/action/set_spider_directive/Trigger(trigger_flags)
. = ..()
if(!.)
return
var/new_directive = tgui_input_text(owner, "Enter the new directive", "Create directive", "[current_directive]")
if(isnull(new_directive) || QDELETED(src) || QDELETED(owner) || !IsAvailable(feedback = TRUE))
return FALSE
current_directive = new_directive
message_admins("[ADMIN_LOOKUPFLW(owner)] set its directive to: '[current_directive]'.")
owner.log_message("set its directive to: '[current_directive]'.", LOG_GAME)
return TRUE
/**
* Sends a message to all currently living spiders.
*/
/datum/action/command_spiders
name = "Command"
desc = "Send a command to all living spiders."
button_icon = 'icons/mob/actions/actions_animal.dmi'
button_icon_state = "command"
background_icon_state = "bg_alien"
overlay_icon_state = "bg_alien_border"
check_flags = AB_CHECK_CONSCIOUS
/datum/action/command_spiders/Trigger(trigger_flags)
. = ..()
if(!.)
return
var/input = tgui_input_text(owner, "Input a command for your legions to follow.", "Command")
if(!input || QDELETED(src) || QDELETED(owner) || !IsAvailable(feedback = TRUE))
return FALSE
spider_command(owner, input)
return TRUE
/**
* Sends a message to all spiders from the target.
*
* Allows the user to send a message to all spiders that exist. Ghosts will also see the message.
* Arguments:
* * user - The spider sending the message
* * message - The message to be sent
*/
/datum/action/command_spiders/proc/spider_command(mob/living/user, message)
if(!message)
return
var/my_message = span_spider("<b>Command from [user]:</b> [message]")
for(var/mob/living/simple_animal/hostile/giant_spider/spider as anything in GLOB.spidermobs)
to_chat(spider, my_message)
for(var/ghost in GLOB.dead_mob_list)
var/link = FOLLOW_LINK(ghost, user)
to_chat(ghost, "[link] [my_message]")
user.log_talk(message, LOG_SAY, tag = "spider command")
@@ -0,0 +1,82 @@
/datum/action/lay_eggs
name = "Lay Eggs"
desc = "Lay a cluster of eggs, which will soon grow into a normal spider."
button_icon = 'icons/mob/actions/actions_animal.dmi'
button_icon_state = "lay_eggs"
background_icon_state = "bg_alien"
overlay_icon_state = "bg_alien_border"
check_flags = AB_CHECK_CONSCIOUS
///How long it takes for a broodmother to lay eggs.
var/egg_lay_time = 12 SECONDS
///The type of egg we create
var/egg_type = /obj/effect/mob_spawn/ghost_role/spider
/datum/action/lay_eggs/Grant(mob/grant_to)
. = ..()
if (!owner)
return
RegisterSignals(owner, list(COMSIG_MOVABLE_MOVED, COMSIG_DO_AFTER_BEGAN, COMSIG_DO_AFTER_ENDED), PROC_REF(update_status_on_signal))
/datum/action/lay_eggs/Remove(mob/removed_from)
. = ..()
UnregisterSignal(removed_from, list(COMSIG_MOVABLE_MOVED, COMSIG_DO_AFTER_BEGAN, COMSIG_DO_AFTER_ENDED))
/datum/action/lay_eggs/IsAvailable(feedback = FALSE)
. = ..()
if(!.)
return FALSE
if(DOING_INTERACTION(owner, DOAFTER_SOURCE_SPIDER))
if (feedback)
owner.balloon_alert(owner, "busy!")
return FALSE
var/obj/structure/spider/eggcluster/eggs = locate() in get_turf(owner)
if(eggs)
if (feedback)
owner.balloon_alert(owner, "already eggs here!")
return FALSE
return TRUE
/datum/action/lay_eggs/Trigger(trigger_flags)
. = ..()
if (!.)
return
owner.balloon_alert_to_viewers("laying eggs...")
if(do_after(owner, egg_lay_time, target = get_turf(owner), interaction_key = DOAFTER_SOURCE_SPIDER))
var/obj/structure/spider/eggcluster/eggs = locate() in get_turf(owner)
if(eggs)
owner.balloon_alert(owner, "already eggs here!")
else
lay_egg()
else
owner.balloon_alert(owner, "interrupted!")
build_all_button_icons(UPDATE_BUTTON_STATUS)
/datum/action/lay_eggs/proc/lay_egg()
var/obj/effect/mob_spawn/ghost_role/spider/new_eggs = new egg_type(get_turf(owner))
new_eggs.faction = owner.faction
var/datum/action/set_spider_directive/spider_directive = locate() in owner.actions
if (spider_directive)
new_eggs.directive = spider_directive.current_directive
/datum/action/lay_eggs/enriched
name = "Lay Enriched Eggs"
desc = "Lay a cluster of eggs, which will soon grow into a greater spider. Requires you drain a human per cluster of these eggs."
button_icon_state = "lay_enriched_eggs"
egg_type = /obj/effect/mob_spawn/ghost_role/spider/enriched
/// How many charges we have to make eggs
var/charges = 0
/datum/action/lay_eggs/enriched/IsAvailable(feedback = FALSE)
. = ..()
if (!.)
return FALSE
if (charges <= 0)
if (feedback)
owner.balloon_alert(owner, "must feed first!")
return FALSE
return TRUE
/datum/action/lay_eggs/enriched/lay_egg()
charges--
return ..()
@@ -0,0 +1,85 @@
/// Make a sticky web under yourself for area fortification
/datum/action/cooldown/lay_web
name = "Spin Web"
desc = "Spin a web to slow down potential prey."
button_icon = 'icons/mob/actions/actions_animal.dmi'
button_icon_state = "lay_web"
background_icon_state = "bg_alien"
overlay_icon_state = "bg_alien_border"
check_flags = AB_CHECK_CONSCIOUS
cooldown_time = 0 SECONDS
/// How long it takes to lay a web
var/webbing_time = 4 SECONDS
/datum/action/cooldown/lay_web/Grant(mob/grant_to)
. = ..()
if (!owner)
return
RegisterSignals(owner, list(COMSIG_MOVABLE_MOVED, COMSIG_DO_AFTER_BEGAN, COMSIG_DO_AFTER_ENDED), PROC_REF(update_status_on_signal))
/datum/action/cooldown/lay_web/Remove(mob/removed_from)
. = ..()
UnregisterSignal(removed_from, list(COMSIG_MOVABLE_MOVED, COMSIG_DO_AFTER_BEGAN, COMSIG_DO_AFTER_ENDED))
/datum/action/cooldown/lay_web/IsAvailable(feedback = FALSE)
. = ..()
if(!.)
return FALSE
if(DOING_INTERACTION(owner, DOAFTER_SOURCE_SPIDER))
if (feedback)
owner.balloon_alert(owner, "busy!")
return FALSE
if(!isturf(owner.loc))
if (feedback)
owner.balloon_alert(owner, "invalid location!")
return FALSE
if(obstructed_by_other_web())
if (feedback)
owner.balloon_alert(owner, "already webbed!")
return FALSE
return TRUE
/// Returns true if there's a web we can't put stuff on in our turf
/datum/action/cooldown/lay_web/proc/obstructed_by_other_web()
return !!(locate(/obj/structure/spider/stickyweb) in get_turf(owner))
/datum/action/cooldown/lay_web/Activate()
. = ..()
var/turf/spider_turf = get_turf(owner)
var/obj/structure/spider/stickyweb/web = locate() in spider_turf
if(web)
owner.balloon_alert_to_viewers("sealing web...")
else
owner.balloon_alert_to_viewers("spinning web...")
if(do_after(owner, webbing_time, target = spider_turf, interaction_key = DOAFTER_SOURCE_SPIDER) && owner.loc == spider_turf)
plant_web(spider_turf, web)
else
owner.balloon_alert(owner, "interrupted!")
build_all_button_icons()
/// Creates a web in the current turf
/datum/action/cooldown/lay_web/proc/plant_web(turf/target_turf, obj/structure/spider/stickyweb/existing_web)
new /obj/structure/spider/stickyweb(target_turf)
/// Variant for genetics, created webs only allow the creator passage
/datum/action/cooldown/lay_web/genetic
desc = "Spin a web. Only you will be able to traverse your web easily."
cooldown_time = 4 SECONDS //the same time to lay a web
/datum/action/cooldown/lay_web/genetic/plant_web(turf/target_turf, obj/structure/spider/stickyweb/existing_web)
new /obj/structure/spider/stickyweb/genetic(target_turf, owner)
/// Variant which allows webs to be stacked into walls
/datum/action/cooldown/lay_web/sealer
desc = "Spin a web to slow down potential prey. Webs can be stacked to make solid structures."
/datum/action/cooldown/lay_web/sealer/plant_web(turf/target_turf, obj/structure/spider/stickyweb/existing_web)
if (existing_web)
qdel(existing_web)
new /obj/structure/spider/stickyweb/sealed(target_turf)
return
new /obj/structure/spider/stickyweb(target_turf)
/datum/action/cooldown/lay_web/sealer/obstructed_by_other_web()
return !!(locate(/obj/structure/spider/stickyweb/sealed) in get_turf(owner))
@@ -0,0 +1,110 @@
/datum/action/cooldown/wrap
name = "Wrap"
desc = "Wrap something or someone in a cocoon. \
If it's a human or similar species, you'll also consume them. \
Consuming a wrapped victim can empower your egg-laying abilities. \
Activate this ability and then click on an adjacent target to begin wrapping them."
background_icon_state = "bg_alien"
overlay_icon_state = "bg_alien_border"
button_icon = 'icons/mob/actions/actions_animal.dmi'
button_icon_state = "wrap_0"
check_flags = AB_CHECK_CONSCIOUS
click_to_activate = TRUE
ranged_mousepointer = 'icons/effects/mouse_pointers/wrap_target.dmi'
/// The time it takes to wrap something.
var/wrap_time = 5 SECONDS
/datum/action/cooldown/wrap/Grant(mob/grant_to)
. = ..()
if (!owner)
return
RegisterSignals(owner, list(COMSIG_DO_AFTER_BEGAN, COMSIG_DO_AFTER_ENDED), PROC_REF(update_status_on_signal))
/datum/action/cooldown/wrap/Remove(mob/removed_from)
. = ..()
UnregisterSignal(removed_from, list(COMSIG_DO_AFTER_BEGAN, COMSIG_DO_AFTER_ENDED))
/datum/action/cooldown/wrap/IsAvailable(feedback = FALSE)
. = ..()
if(!. || owner.incapacitated())
return FALSE
if(DOING_INTERACTION(owner, DOAFTER_SOURCE_SPIDER))
if (feedback)
owner.balloon_alert(owner, "busy!")
return FALSE
return TRUE
/datum/action/cooldown/wrap/set_click_ability(mob/on_who)
. = ..()
if(!.)
return
on_who.balloon_alert(on_who, "prepared to wrap")
button_icon_state = "wrap_1"
build_all_button_icons()
/datum/action/cooldown/wrap/unset_click_ability(mob/on_who, refund_cooldown = TRUE)
. = ..()
if(!.)
return
if (refund_cooldown)
on_who.balloon_alert(on_who, "wrap cancelled")
button_icon_state = "wrap_0"
build_all_button_icons()
/datum/action/cooldown/wrap/Activate(atom/to_wrap)
if(!owner.Adjacent(to_wrap))
owner.balloon_alert(owner, "must be closer!")
return FALSE
if(!ismovable(to_wrap) || to_wrap == owner)
return FALSE
if(isspider(to_wrap))
owner.balloon_alert(owner, "can't wrap spiders!")
return FALSE
var/atom/movable/target_movable = to_wrap
if(target_movable.anchored)
return FALSE
StartCooldown(wrap_time)
INVOKE_ASYNC(src, PROC_REF(cocoon), to_wrap)
return TRUE
/datum/action/cooldown/wrap/proc/cocoon(atom/movable/to_wrap)
owner.visible_message(
span_notice("[owner] begins to secrete a sticky substance around [to_wrap]."),
span_notice("You begin wrapping [to_wrap] into a cocoon."),
)
if(do_after(owner, wrap_time, target = to_wrap, interaction_key = DOAFTER_SOURCE_SPIDER))
wrap_target(to_wrap)
else
owner.balloon_alert(owner, "interrupted!")
/datum/action/cooldown/wrap/proc/wrap_target(atom/movable/to_wrap)
var/obj/structure/spider/cocoon/casing = new(to_wrap.loc)
if(isliving(to_wrap))
var/mob/living/living_wrapped = to_wrap
// You get a point every time you consume a living player, even if they've been consumed before.
// You only get a point for any individual corpse once, so you can't keep breaking it out and eating it again.
if(ishuman(living_wrapped) && (living_wrapped.stat != DEAD || !HAS_TRAIT(living_wrapped, TRAIT_SPIDER_CONSUMED)))
var/datum/action/lay_eggs/enriched/egg_power = locate() in owner.actions
if(egg_power)
egg_power.charges++
egg_power.build_all_button_icons()
owner.visible_message(
span_danger("[owner] sticks a proboscis into [living_wrapped] and sucks a viscous substance out."),
span_notice("You suck the nutriment out of [living_wrapped], feeding you enough to lay a cluster of enriched eggs."),
)
ADD_TRAIT(living_wrapped, TRAIT_SPIDER_CONSUMED, TRAIT_GENERIC)
living_wrapped.investigate_log("has been killed by being wrapped in a cocoon.", INVESTIGATE_DEATHS)
living_wrapped.death() //you just ate them, they're dead.
log_combat(owner, living_wrapped, "spider cocooned")
else
to_chat(owner, span_warning("[living_wrapped] is not edible!"))
to_wrap.forceMove(casing)
if(to_wrap.density || ismob(to_wrap))
casing.icon_state = pick("cocoon_large1", "cocoon_large2", "cocoon_large3")