diff --git a/code/__DEFINES/role_preferences.dm b/code/__DEFINES/role_preferences.dm index 0f74b31c249..17f3ef4b505 100644 --- a/code/__DEFINES/role_preferences.dm +++ b/code/__DEFINES/role_preferences.dm @@ -97,6 +97,7 @@ #define ROLE_MAINTENANCE_DRONE "Maintenance Drone" #define ROLE_BATTLECRUISER_CREW "Battlecruiser Crew" #define ROLE_BATTLECRUISER_CAPTAIN "Battlecruiser Captain" +#define ROLE_VENUSHUMANTRAP "Venus Human Trap" /// This defines the antagonists you can operate with in the settings. diff --git a/code/_globalvars/lists/poll_ignore.dm b/code/_globalvars/lists/poll_ignore.dm index fb237b37903..db5a23e7685 100644 --- a/code/_globalvars/lists/poll_ignore.dm +++ b/code/_globalvars/lists/poll_ignore.dm @@ -20,6 +20,7 @@ #define POLL_IGNORE_CONTRACTOR_SUPPORT "contractor_support" #define POLL_IGNORE_ACADEMY_WIZARD "academy_wizard" #define POLL_IGNORE_PAI "pai" +#define POLL_IGNORE_VENUSHUMANTRAP "venus_human_trap" GLOBAL_LIST_INIT(poll_ignore_desc, list( @@ -43,6 +44,7 @@ GLOBAL_LIST_INIT(poll_ignore_desc, list( POLL_IGNORE_CONTRACTOR_SUPPORT = "Contractor Support Unit", POLL_IGNORE_ACADEMY_WIZARD = "Academy Wizard Defender", POLL_IGNORE_PAI = JOB_PERSONAL_AI, + POLL_IGNORE_VENUSHUMANTRAP = "Venus Human Traps", )) GLOBAL_LIST_INIT(poll_ignore, init_poll_ignore()) diff --git a/code/modules/jobs/job_types/spawner/venus_human_trap.dm b/code/modules/jobs/job_types/spawner/venus_human_trap.dm new file mode 100644 index 00000000000..6fd354a4989 --- /dev/null +++ b/code/modules/jobs/job_types/spawner/venus_human_trap.dm @@ -0,0 +1,3 @@ +/datum/job/venus_human_trap + title = ROLE_VENUSHUMANTRAP + policy_index = ROLE_VENUSHUMANTRAP diff --git a/code/modules/jobs/jobs.dm b/code/modules/jobs/jobs.dm index 7658050da8e..5eea0d7fc46 100644 --- a/code/modules/jobs/jobs.dm +++ b/code/modules/jobs/jobs.dm @@ -21,6 +21,7 @@ GLOBAL_LIST_INIT(exp_specialmap, list( ROLE_SPACE_BAR_PATRON, ROLE_LAVALAND_SYNDICATE, ROLE_MAINTENANCE_DRONE, + ROLE_VENUSHUMANTRAP, ROLE_GHOST_ROLE, ), // Ghost roles EXP_TYPE_GHOST = list() // dead people, observers diff --git a/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm b/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm index 13815f1a4e3..dec507046e1 100644 --- a/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm +++ b/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm @@ -9,6 +9,7 @@ * Once it grows a venus human trap, the bud itself will destroy itself. * */ +/// Flower bud structure that ghost role spawns, actual spawn logic handled by /obj/effect/mob_spawn/ghost_role/venus_human_trap /obj/structure/alien/resin/flower_bud //inheriting basic attack/damage stuff from alien structures name = "flower bud" desc = "A large pulsating plant..." @@ -32,8 +33,13 @@ var/list/vines = list() + /// The spawner that actually handles spawning the ghost role in + var/obj/effect/mob_spawn/ghost_role/venus_human_trap/spawner + /obj/structure/alien/resin/flower_bud/Initialize(mapload) . = ..() + spawner = new(get_turf(loc)) + spawner.flower_bud = src countdown = new(src) var/list/anchors = list() anchors += locate(x-2,y+2,z) @@ -55,21 +61,18 @@ /obj/structure/alien/resin/flower_bud/Destroy() QDEL_LIST(vines) + QDEL_NULL(countdown) + if(spawner) // anti harddel checks + if(!QDELETED(spawner)) + qdel(spawner) + spawner = null return ..() -/** - * Spawns a venus human trap, then qdels itself. - * - * Displays a message, spawns a human venus trap, then qdels itself. - */ +/// Tells the spawner that the venus human trap is ready /obj/structure/alien/resin/flower_bud/proc/bear_fruit() visible_message(span_danger("The plant has borne fruit!")) - var/mob/living/simple_animal/hostile/venus_human_trap/spawned_human_trap = new(get_turf(src)) - if(trait_flags & SPACEVINE_HEAT_RESISTANT) - spawned_human_trap.unsuitable_heat_damage = 0 - if(trait_flags & SPACEVINE_COLD_RESISTANT) - spawned_human_trap.unsuitable_cold_damage = 0 - qdel(src) + if(spawner) + spawner.bear_fruit() /obj/structure/alien/resin/flower_bud/proc/progress_growth() growth_icon++ @@ -78,6 +81,9 @@ return addtimer(CALLBACK(src, .proc/progress_growth), growth_time/4) +/obj/structure/alien/resin/flower_bud/attack_ghost(mob/user) + spawner.attack_ghost(user) + /obj/effect/ebeam/vine name = "thick vine" mouse_opacity = MOUSE_OPACITY_ICON @@ -192,41 +198,11 @@ L.Knockdown(1 SECONDS) ranged_cooldown = world.time + ranged_cooldown_time -/mob/living/simple_animal/hostile/venus_human_trap/Login() - . = ..() - to_chat(src, span_boldwarning("You are a venus human trap! Protect the kudzu at all costs, and feast on those who oppose you!")) - -/mob/living/simple_animal/hostile/venus_human_trap/attack_ghost(mob/user) - . = ..() - if(. || !(GLOB.ghost_role_flags & GHOSTROLE_SPAWNER)) - return - humanize_plant(user) - /mob/living/simple_animal/hostile/venus_human_trap/Destroy() for(var/datum/beam/vine as anything in vines) qdel(vine) // reference is automatically deleted by remove_vine return ..() -/** - * Sets a ghost to control the plant if the plant is eligible - * - * Asks the interacting ghost if they would like to control the plant. - * If they answer yes, and another ghost hasn't taken control, sets the ghost to control the plant. - * Arguments: - * * mob/user - The ghost to possibly control the plant - */ -/mob/living/simple_animal/hostile/venus_human_trap/proc/humanize_plant(mob/user) - if(key || !playable_plant || stat) - return - var/plant_ask = tgui_alert(usr,"Become a venus human trap?", "Are you reverse vegan?", list("Yes", "No")) - if(plant_ask == "No" || QDELETED(src)) - return - if(key) - to_chat(user, span_warning("Someone else already took this plant!")) - return - key = user.key - log_game("[key_name(src)] took control of [name].") - /** * Manages how the vines should affect the things they're attached to. * diff --git a/code/modules/mob_spawn/ghost_roles/venus_human_trap.dm b/code/modules/mob_spawn/ghost_roles/venus_human_trap.dm new file mode 100644 index 00000000000..6d1e0b9e438 --- /dev/null +++ b/code/modules/mob_spawn/ghost_roles/venus_human_trap.dm @@ -0,0 +1,54 @@ +/// Handles logic for ghost spawning code, visible object in game is handled by /obj/structure/alien/resin/flower_bud +/obj/effect/mob_spawn/ghost_role/venus_human_trap + name = "flower bud" + desc = "A large pulsating plant..." + icon = 'icons/effects/spacevines.dmi' + icon_state = "bud0" + mob_type = /mob/living/simple_animal/hostile/venus_human_trap + prompt_name = "venus human trap" + you_are_text = "You are a venus human trap." + flavour_text = "You are a venus human trap! Protect the kudzu at all costs, and feast on those who oppose you!" + faction = list("hostile","vines","plants") + spawner_job_path = /datum/job/venus_human_trap + /// Physical structure housing the spawner + var/obj/structure/alien/resin/flower_bud/flower_bud + /// Used to determine when to notify ghosts + var/ready = FALSE + +/obj/effect/mob_spawn/ghost_role/venus_human_trap/Destroy() + if(flower_bud) // anti harddel checks + if(!QDELETED(flower_bud)) + qdel(flower_bud) + flower_bud = null + return ..() + +/obj/effect/mob_spawn/ghost_role/venus_human_trap/equip(mob/living/simple_animal/hostile/venus_human_trap/spawned_human_trap) + if(spawned_human_trap && flower_bud) + if(flower_bud.trait_flags & SPACEVINE_HEAT_RESISTANT) + spawned_human_trap.unsuitable_heat_damage = 0 + if(flower_bud.trait_flags & SPACEVINE_COLD_RESISTANT) + spawned_human_trap.unsuitable_cold_damage = 0 + +/// Called when the attached flower bud has borne fruit (ie. is ready) +/obj/effect/mob_spawn/ghost_role/venus_human_trap/proc/bear_fruit() + ready = TRUE + notify_ghosts("[src] has borne fruit!", null, enter_link = "(Click to play)", source = src, action = NOTIFY_ATTACK, ignore_key = POLL_IGNORE_VENUSHUMANTRAP) + +/obj/effect/mob_spawn/ghost_role/venus_human_trap/Topic(href, href_list) + . = ..() + if(.) + return + if(href_list["activate"]) + var/mob/dead/observer/ghost = usr + if(istype(ghost)) + ghost.ManualFollow(src) + attack_ghost(ghost) + +/obj/effect/mob_spawn/ghost_role/venus_human_trap/allow_spawn(mob/user, silent = FALSE) + . = ..() + if(!.) + return FALSE + if(!ready) + if(!silent) + to_chat(user, span_warning("\The [src] has not borne fruit yet!")) + return FALSE diff --git a/tgstation.dme b/tgstation.dme index b5231fa191d..8b51550deb1 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -3184,6 +3184,7 @@ #include "code\modules\jobs\job_types\spawner\spider.dm" #include "code\modules\jobs\job_types\spawner\syndicate_cybersun.dm" #include "code\modules\jobs\job_types\spawner\syndicate_cybersun_captain.dm" +#include "code\modules\jobs\job_types\spawner\venus_human_trap.dm" #include "code\modules\jobs\job_types\spawner\zombie.dm" #include "code\modules\keybindings\bindings_atom.dm" #include "code\modules\keybindings\bindings_client.dm" @@ -3693,6 +3694,7 @@ #include "code\modules\mob_spawn\ghost_roles\space_roles.dm" #include "code\modules\mob_spawn\ghost_roles\spider_roles.dm" #include "code\modules\mob_spawn\ghost_roles\unused_roles.dm" +#include "code\modules\mob_spawn\ghost_roles\venus_human_trap.dm" #include "code\modules\mod\mod_actions.dm" #include "code\modules\mod\mod_activation.dm" #include "code\modules\mod\mod_ai.dm"