From 3bc220eae1c0e2b7dfdce735d83627f2c6b8cf72 Mon Sep 17 00:00:00 2001 From: jjpark-kb <55967837+jjpark-kb@users.noreply.github.com> Date: Wed, 19 Jan 2022 21:15:06 -0500 Subject: [PATCH] borer midround, balance, and objective (#10806) * borer midround, balance, and objective * adds borer bannable * okay fine * I hate this * added the cage * why * admin foolery * add borer egg to uplink, 20 at 20 minutes * add to uplink --- code/__DEFINES/role_preferences.dm | 4 + code/modules/admin/sql_ban_system.dm | 1 + .../cortical_borer/code/cortical_borer.dm | 22 +++- .../code/cortical_borer_abilities.dm | 27 +++-- .../code/cortical_borer_antag.dm | 54 ++++++++- .../cortical_borer/code/cortical_borer_egg.dm | 10 ++ .../code/cortical_borer_items.dm | 110 ++++++++++++++++++ .../modules/cortical_borer/icons/items.dmi | Bin 0 -> 1007 bytes tgstation.dme | 1 + 9 files changed, 212 insertions(+), 17 deletions(-) create mode 100644 modular_skyrat/modules/cortical_borer/code/cortical_borer_items.dm create mode 100644 modular_skyrat/modules/cortical_borer/icons/items.dmi diff --git a/code/__DEFINES/role_preferences.dm b/code/__DEFINES/role_preferences.dm index 035529d57f6..b3470f86c96 100644 --- a/code/__DEFINES/role_preferences.dm +++ b/code/__DEFINES/role_preferences.dm @@ -37,6 +37,8 @@ #define ROLE_SPACE_DRAGON "Space Dragon" #define ROLE_SPIDER "Spider" #define ROLE_WIZARD_MIDROUND "Wizard (Midround)" +//SKYRAT EDIT: Cortical Borers +#define ROLE_BORER "Borer" // Latejoin roles #define ROLE_HERETIC_SMUGGLER "Heretic Smuggler" @@ -135,6 +137,8 @@ GLOBAL_LIST_INIT(special_roles, list( ROLE_SPACE_DRAGON = 0, ROLE_SPIDER = 0, ROLE_WIZARD_MIDROUND = 14, + //SKYRAT EDIT: Cortical Borers + ROLE_BORER = 0, // Latejoin ROLE_HERETIC_SMUGGLER = 0, diff --git a/code/modules/admin/sql_ban_system.dm b/code/modules/admin/sql_ban_system.dm index 1520cb5b0d6..d4f3fc94ec6 100644 --- a/code/modules/admin/sql_ban_system.dm +++ b/code/modules/admin/sql_ban_system.dm @@ -358,6 +358,7 @@ ROLE_SYNDICATE, ROLE_TRAITOR, ROLE_WIZARD, + ROLE_BORER,//SKYRAT EDIT: Cortical Borers ), "Skyrat Ban Options" = list( BAN_PACIFICATION, diff --git a/modular_skyrat/modules/cortical_borer/code/cortical_borer.dm b/modular_skyrat/modules/cortical_borer/code/cortical_borer.dm index 7f0e8199873..2b18150cb00 100644 --- a/modular_skyrat/modules/cortical_borer/code/cortical_borer.dm +++ b/modular_skyrat/modules/cortical_borer/code/cortical_borer.dm @@ -1,9 +1,12 @@ GLOBAL_VAR_INIT(objective_egg_borer_number, 5) GLOBAL_VAR_INIT(objective_egg_egg_number, 10) -GLOBAL_VAR_INIT(objective_willing_hosts, 20) +GLOBAL_VAR_INIT(objective_willing_hosts, 10) +GLOBAL_VAR_INIT(objective_blood_chem, 5) +GLOBAL_VAR_INIT(objective_blood_borer, 5) -GLOBAL_VAR_INIT(successful_borer, 0) +GLOBAL_VAR_INIT(successful_egg_number, 0) GLOBAL_LIST_EMPTY(willing_hosts) +GLOBAL_VAR_INIT(successful_blood_chem, 0) //we need a way of buffing leg speed... here /datum/movespeed_modifier/borer_speed @@ -240,10 +243,16 @@ GLOBAL_LIST_EMPTY(willing_hosts) var/body_focus = null ///how many children the borer has produced var/children_produced = 0 + ///how many blood chems have been learned through the blood + var/blood_chems_learned = 0 ///we dont want to spam the chat var/deathgasp_once = FALSE //the limit to the chemical and stat evolution var/limited_borer = 10 + ///borers can only enter biologicals if true + var/organic_restricted = TRUE + ///borers are unable to enter changelings if true + var/changeling_restricted = TRUE /mob/living/simple_animal/cortical_borer/Initialize(mapload) . = ..() @@ -299,8 +308,9 @@ GLOBAL_LIST_EMPTY(willing_hosts) . += "Sugar detected! Unable to generate resources!" . += "" . += "OBJECTIVES:" - . += "1) [GLOB.objective_egg_borer_number] borers producing [GLOB.objective_egg_egg_number] eggs: [GLOB.successful_borer]/[GLOB.objective_egg_borer_number]" + . += "1) [GLOB.objective_egg_borer_number] borers producing [GLOB.objective_egg_egg_number] eggs: [GLOB.successful_egg_number]/[GLOB.objective_egg_borer_number]" . += "2) [GLOB.objective_willing_hosts] willing hosts: [length(GLOB.willing_hosts)]/[GLOB.objective_willing_hosts]" + . += "3) [GLOB.objective_blood_borer] borers learning [GLOB.objective_blood_chem] from the blood: [GLOB.successful_blood_chem]/[GLOB.objective_blood_borer]" /mob/living/simple_animal/cortical_borer/Life(delta_time, times_fired) . = ..() @@ -336,12 +346,14 @@ GLOBAL_LIST_EMPTY(willing_hosts) timed_maturity = world.time + 1 SECONDS maturity_age++ - //no objectives means 20:40; one objective means 15:30; two objectives mean 10:20 + //20:40, 15:30, 10:20, 5:10 var/maturity_threshold = 20 - if(GLOB.successful_borer >= GLOB.objective_egg_borer_number) + if(GLOB.successful_egg_number >= GLOB.objective_egg_borer_number) maturity_threshold -= 5 if(length(GLOB.willing_hosts) >= GLOB.objective_willing_hosts) maturity_threshold -= 5 + if(GLOB.successful_blood_chem >= GLOB.objective_blood_borer) + maturity_threshold -= 5 if(maturity_age == maturity_threshold) if(chemical_evolution < limited_borer) //you can only have a default of 10 at a time diff --git a/modular_skyrat/modules/cortical_borer/code/cortical_borer_abilities.dm b/modular_skyrat/modules/cortical_borer/code/cortical_borer_abilities.dm index 91a73de6a9f..7293ef6127f 100644 --- a/modular_skyrat/modules/cortical_borer/code/cortical_borer_abilities.dm +++ b/modular_skyrat/modules/cortical_borer/code/cortical_borer_abilities.dm @@ -135,6 +135,9 @@ cortical_owner.chemical_evolution += 5 return cortical_owner.known_chemicals += reagent_choice.type + cortical_owner.blood_chems_learned++ + if(cortical_owner.blood_chems_learned == 5) + GLOB.successful_blood_chem += 1 to_chat(owner, span_notice("You have learned [initial(reagent_choice.name)]")) StartCooldown() @@ -624,6 +627,9 @@ //having a host means we need to leave them then if(cortical_owner.human_host) + if(cortical_owner.host_sugar()) + to_chat(owner, span_warning("Sugar inhibits your abilities to function!")) + return to_chat(cortical_owner, span_notice("You forcefully detach from the host.")) to_chat(cortical_owner.human_host, span_notice("Something carefully tickles your inner ear...")) var/obj/item/organ/borer_body/borer_organ = locate() in cortical_owner.human_host.internal_organs @@ -648,15 +654,15 @@ if(listed_human.has_borer()) continue // hosts need to be organic - if(!(listed_human.dna.species.inherent_biotypes & MOB_ORGANIC)) + if(!(listed_human.dna.species.inherent_biotypes & MOB_ORGANIC) && cortical_owner.organic_restricted) continue // hosts need to be organic - if(!(listed_human.mob_biotypes & MOB_ORGANIC)) + if(!(listed_human.mob_biotypes & MOB_ORGANIC) && cortical_owner.organic_restricted) continue //hosts cannot be changelings if(listed_human.mind) var/datum/antagonist/changeling/changeling = listed_human.mind.has_antag_datum(/datum/antagonist/changeling) - if(changeling) + if(changeling && cortical_owner.changeling_restricted) continue usable_hosts += listed_human @@ -773,8 +779,8 @@ var/obj/effect/mob_spawn/ghost_role/borer_egg/spawned_egg = new /obj/effect/mob_spawn/ghost_role/borer_egg(borer_turf) spawned_egg.generation = (cortical_owner.generation + 1) cortical_owner.children_produced++ - if(cortical_owner.children_produced >= GLOB.objective_egg_egg_number) - GLOB.successful_borer += 1 + if(cortical_owner.children_produced == GLOB.objective_egg_egg_number) + GLOB.successful_egg_number += 1 if(prob(25)) cortical_owner.human_host.gain_trauma_type(BRAIN_TRAUMA_MILD, TRAUMA_RESILIENCE_BASIC) to_chat(cortical_owner.human_host, span_warning("Your brain begins to hurt...")) @@ -918,12 +924,13 @@ to_chat(owner, span_warning("Sugar inhibits your abilities to function!")) return if(cortical_owner.chemical_storage < 300) - to_chat(cortical_owner, span_warning("You require at least 200 chemical units before you can revive your host!")) + to_chat(cortical_owner, span_warning("You require at least 300 chemical units before you can ask your host!")) return cortical_owner.chemical_storage -= 300 - if(locate(cortical_owner.human_host) in GLOB.willing_hosts) - to_chat(cortical_owner, span_warning("This host is already willing, try another host!")) - return + for(var/ckey_check in GLOB.willing_hosts) + if(ckey_check == cortical_owner.human_host.ckey) + to_chat(cortical_owner, span_warning("This host is already willing, try another host!")) + return to_chat(cortical_owner, span_notice("The host is being asked...")) var/host_choice = tgui_input_list(cortical_owner.human_host,"Do you accept to be a willing host?", "Willing Host Request", list("Yes", "No")) if(host_choice != "Yes") @@ -932,5 +939,5 @@ return to_chat(cortical_owner, span_notice("The host was willing!")) to_chat(cortical_owner.human_host, span_notice("You have accepted being a willing host!")) - GLOB.willing_hosts += cortical_owner.human_host + GLOB.willing_hosts += cortical_owner.human_host.ckey StartCooldown() diff --git a/modular_skyrat/modules/cortical_borer/code/cortical_borer_antag.dm b/modular_skyrat/modules/cortical_borer/code/cortical_borer_antag.dm index 943d8d59d03..58006466cfb 100644 --- a/modular_skyrat/modules/cortical_borer/code/cortical_borer_antag.dm +++ b/modular_skyrat/modules/cortical_borer/code/cortical_borer_antag.dm @@ -24,7 +24,7 @@ /datum/antagonist/cortical_borer name = "Cortical Borer" - job_rank = ROLE_ALIEN + job_rank = ROLE_BORER show_in_antagpanel = TRUE roundend_category = "cortical borers" antagpanel_category = "Cortical borers" @@ -32,6 +32,9 @@ show_to_ghosts = TRUE var/datum/team/cortical_borers/borers +/datum/antagonist/cortical_borer/get_preview_icon() + return finish_preview_icon(icon('modular_skyrat/modules/cortical_borer/icons/animal.dmi', "brainslug")) + /datum/antagonist/cortical_borer/get_team() return borers @@ -67,7 +70,7 @@ parts += span_greentext("Borers were able to survive the shift!") else parts += span_redtext("Borers were unable to survive the shift!") - if(GLOB.successful_borer >= GLOB.objective_egg_borer_number) + if(GLOB.successful_egg_number >= GLOB.objective_egg_borer_number) parts += span_greentext("Borers were able to produce enough eggs!") else parts += span_redtext("Borers were unable to produce enough eggs!") @@ -75,6 +78,10 @@ parts += span_greentext("Borers were able to gather enough willing hosts!") else parts += span_redtext("Borers were unable to gather enough willing hosts!") + if(GLOB.successful_blood_chem >= GLOB.objective_blood_borer) + parts += span_greentext("Borers were able to learn enough chemicals through the blood!") + else + parts += span_redtext("Borers were unable to learn enough chemicals through the blood!") return "
[parts.Join("
")]
" /datum/round_event_control/cortical_borer @@ -124,3 +131,46 @@ to_chat(spawned_cb, span_warning("You are a cortical borer! You can fear someone to make them stop moving, but make sure to inhabit them! You only grow/heal/talk when inside a host!")) for(var/mob/dead_mob in GLOB.dead_mob_list) to_chat(dead_mob, span_notice("The cortical borers have been selected, you are able to orbit them! Remember, they can reproduce!")) + +/datum/dynamic_ruleset/midround/from_ghosts/cortical_borer + name = "Cortical Borer Infestation" + antag_datum = /datum/antagonist/cortical_borer + antag_flag = ROLE_BORER + enemy_roles = list( + JOB_CAPTAIN, + JOB_DETECTIVE, + JOB_HEAD_OF_SECURITY, + JOB_SECURITY_OFFICER, + ) + required_enemies = list(2,2,1,1,1,1,1,0,0,0) + required_candidates = 1 + weight = 3 + cost = 15 + requirements = list(101,101,101,70,50,40,20,15,10,10) + repeatable = TRUE + var/list/vents = list() + +/datum/dynamic_ruleset/midround/from_ghosts/cortical_borer/execute() + for(var/obj/machinery/atmospherics/components/unary/vent_pump/temp_vent in GLOB.machines) + if(QDELETED(temp_vent)) + continue + if(is_station_level(temp_vent.loc.z) && !temp_vent.welded) + var/datum/pipeline/temp_vent_parent = temp_vent.parents[1] + if(!temp_vent_parent) + continue // No parent vent + // Stops Borers getting stuck in small networks. + // See: Security, Virology + if(temp_vent_parent.other_atmos_machines.len > 20) + vents += temp_vent + if(!vents.len) + return FALSE + . = ..() + +/datum/dynamic_ruleset/midround/from_ghosts/cortical_borer/generate_ruleset_body(mob/applicant) + var/obj/vent = pick_n_take(vents) + var/mob/living/simple_animal/cortical_borer/new_borer = new(vent.loc) + new_borer.key = applicant.key + new_borer.move_into_vent(vent) + message_admins("[ADMIN_LOOKUPFLW(new_borer)] has been made into a borer by the midround ruleset.") + log_game("DYNAMIC: [key_name(new_borer)] was spawned as a borer by the midround ruleset.") + return new_borer diff --git a/modular_skyrat/modules/cortical_borer/code/cortical_borer_egg.dm b/modular_skyrat/modules/cortical_borer/code/cortical_borer_egg.dm index 841b1ecbfd7..d9b899581f5 100644 --- a/modular_skyrat/modules/cortical_borer/code/cortical_borer_egg.dm +++ b/modular_skyrat/modules/cortical_borer/code/cortical_borer_egg.dm @@ -72,3 +72,13 @@ new /obj/effect/decal/cleanable/food/egg_smudge(hit_turf) QDEL_NULL(host_spawner) qdel(src) + +/datum/uplink_item/dangerous/cortical_borer + name = "Cortical Borer Egg" + desc = "The egg of a cortical borer. The cortical borer is a parasite that can produce chemicals upon command, as well as \ + learn new chemicals through the blood if old enough. Be careful as there is no way to get the borer to pledge allegiance \ + to yourself. The egg is extremely fragile, do not crush it in your hand nor throw it. \ + The egg is required to sit out in the open in order to hatch. (Cannot be hidden in closets, etc.)" + progression_minimum = 20 MINUTES + item = /obj/item/borer_egg + cost = 20 diff --git a/modular_skyrat/modules/cortical_borer/code/cortical_borer_items.dm b/modular_skyrat/modules/cortical_borer/code/cortical_borer_items.dm new file mode 100644 index 00000000000..34ea1cbf511 --- /dev/null +++ b/modular_skyrat/modules/cortical_borer/code/cortical_borer_items.dm @@ -0,0 +1,110 @@ +/obj/item/cortical_cage + name = "cortical borer cage" + desc = "A harmless cage that is intended to capture cortical borers." + icon = 'modular_skyrat/modules/cortical_borer/icons/items.dmi' + icon_state = "cage" + + ///If true, the trap is "open" and can trigger. + var/opened = FALSE + ///The radio that is inserted into the trap. + var/obj/item/radio/internal_radio + ///The borer that is inside the trap + var/mob/living/simple_animal/cortical_borer/trapped_borer + +/obj/item/cortical_cage/Initialize(mapload) + . = ..() + update_appearance() + var/static/list/loc_connections = list( + COMSIG_ATOM_ENTERED = .proc/spring_trap, + ) + AddElement(/datum/element/connect_loc, loc_connections) + +/obj/item/cortical_cage/update_overlays() + . = ..() + if(trapped_borer) + . += "borer" + if(internal_radio) + . += "radio" + if(opened) + . += "doors_open" + else + . += "doors_closed" + +/obj/item/cortical_cage/attack_self(mob/user, modifiers) + opened = !opened + if(opened) + user.visible_message("[user] opens [src].", "You open [src].", "You hear a metallic thunk.") + else + user.visible_message("[user] closes [src].", "You close [src].", "You hear a metallic thunk.") + playsound(src, 'sound/machines/boltsup.ogg', 30, TRUE) + update_appearance() + +/obj/item/cortical_cage/attackby(obj/item/attacking_item, mob/user, params) + if(istype(attacking_item, /obj/item/radio)) + internal_radio = attacking_item + internal_radio.forceMove(src) + visible_message("[internal_radio] attaches to [src] with a click.", "You attach [internal_radio] to the [src].", "You hear a clicking sound.") + update_appearance() + return + return ..() + +/obj/item/cortical_cage/crowbar_act(mob/living/user, obj/item/tool) + . = ..() + if(internal_radio) + internal_radio.forceMove(get_turf(src)) + user.visible_message("[internal_radio] pops off [src].", "You pop off [internal_radio] from [src].", "You hear a clicking sound then a loud metallic thunk.") + internal_radio = null + update_appearance() + return + +/obj/item/cortical_cage/proc/spring_trap(datum/source, atom/movable/AM) + SIGNAL_HANDLER + //it will only trigger on a cortical borer, and it has to be opened + if(!iscorticalborer(AM) || !opened) + return + trapped_borer = AM + trapped_borer.visible_message("[trapped_borer] gets sucked into [src]!", "You get sucked into [src]!", "You hear a vacuuming sound.") + trapped_borer.forceMove(src) + opened = FALSE + if(internal_radio) + var/area/src_area = get_area(src) + internal_radio.talk_into(src, "A cortical borer has been trapped in [src_area].", RADIO_CHANNEL_COMMON) + playsound(src, 'sound/machines/boltsup.ogg', 30, TRUE) + update_appearance() + +/obj/item/cortical_cage/relaymove(mob/living/user, direction) + if(!iscorticalborer(user)) + user.forceMove(get_turf(src)) + update_appearance() + return + if(opened) + loc.visible_message(span_notice("[user] climbs out of [src]!"), \ + span_warning("[user] jumps out of [src]!")) + opened = FALSE + trapped_borer.forceMove(get_turf(src)) + trapped_borer = null + update_appearance() + return + else if(user.client) + container_resist_act(user) + +/obj/item/cortical_cage/container_resist_act(mob/living/user) + user.changeNext_move(CLICK_CD_BREAKOUT) + user.last_special = world.time + CLICK_CD_BREAKOUT + to_chat(user, span_notice("You begin squeezing through the bars in an attempt to escape! (This will take time.)")) + to_chat(loc, span_warning("You see [user] begin trying to squeeze through the bars!")) + if(!do_after(user, rand(30 SECONDS, 40 SECONDS), target = user) || opened || !(user in contents)) + return + loc.visible_message(span_warning("[user] squeezes through [src]'s handles!"), null, null, null, user) + to_chat(user, span_boldannounce("Bingo, you squeeze through!")) + opened = FALSE + trapped_borer.forceMove(get_turf(src)) + trapped_borer = null + update_appearance() + +/datum/crafting_recipe/cortical_cage + name = "Cortical Borer Cage" + result = /obj/item/cortical_cage + reqs = list(/obj/item/forging/complete/plate = 2, + /obj/item/stack/rods = 4) + category = CAT_MISC diff --git a/modular_skyrat/modules/cortical_borer/icons/items.dmi b/modular_skyrat/modules/cortical_borer/icons/items.dmi new file mode 100644 index 0000000000000000000000000000000000000000..156981031ab7e78d6c47cd0fb5f741eae9b0c455 GIT binary patch literal 1007 zcmVV=-0C=2*%&`i>KoA7b`t~b^q!lsI_8Li$6v;2hnOl>Cn3cUl@$W6th$!i1 z;LYSX)~BXJ)i(5CjX`Eu9JV_$&*0Mti+xFEkBDKWXku*kfK#%Rg&>Mxfd*o&Bx>-%KGm(N8MGZ+J@d1SxlmsU#+G9 z00R$6L_t(|ob8;=YZE~j#@|gt)5zjStCXS$9yAB-#fgGNN}*c6dMJt>1kd>c3SK4W zQZJrDPhR{3s;59O?M1=OA>d^LQlSX(VybQ;h-E#L-K5E8lXYkJ$*%A3l8|KQ-I-^e zcV=FeDCKgQ7#s=o4gBx00AN@EFiG?cj5@lmn|`j(WHO4|_v`={{0{ywZLk1+kTLkf zwB?wBR8=(%!*I2ZSG=^Ts;ackcj6_!5JGl%$Nu*S5LD-_wg(MD=WldfH?15x=>0Ii z9X5V0m-E|IM+${PPkhG|BzyJ;)n@15MwLSX1UdVIh+)lqS?wW+^dcN92L!S3I$;=w zBFhD_azLe02`#9sSg~k2kHwu08FF>h{GD7XqsjkhM{<^8hXX4%Goc@D3qhaitkvC4yqbDY}<%)2`YZ1 zQ&1e}DMtsXzRW^gTsR~^Sk=&=V?+sCfH3#IVa6JD>}qJ3Gm}$Mn*GL=(f7h$h1si= zK6#xT;Fn@4uO*u;@#A~T{%qyR3n>Ri761(Ig21o