diff --git a/code/__DEFINES/antagonists.dm b/code/__DEFINES/antagonists.dm index 751c4870d41..7a7617a1db4 100644 --- a/code/__DEFINES/antagonists.dm +++ b/code/__DEFINES/antagonists.dm @@ -51,13 +51,6 @@ #define HIJACK_HIJACKER 1 //Needs to be present for shuttle to be hijacked #define HIJACK_PREVENT 2 //Prevents hijacking same way as non-antags -//Assimilation -#define TRACKER_DEFAULT_TIME 900 -#define TRACKER_MINDSHIELD_TIME 1200 -#define TRACKER_AWAKENED_TIME 3000 -#define TRACKER_BONUS_LARGE 300 -#define TRACKER_BONUS_SMALL 100 - //Syndicate Contracts #define CONTRACT_STATUS_INACTIVE 1 #define CONTRACT_STATUS_ACTIVE 2 diff --git a/code/__DEFINES/atom_hud.dm b/code/__DEFINES/atom_hud.dm index 7fea7f92edd..7e0b1fdf6e2 100644 --- a/code/__DEFINES/atom_hud.dm +++ b/code/__DEFINES/atom_hud.dm @@ -58,9 +58,8 @@ #define ANTAG_HUD_SOULLESS 21 #define ANTAG_HUD_CLOCKWORK 22 #define ANTAG_HUD_BROTHER 23 -#define ANTAG_HUD_HIVE 24 -#define ANTAG_HUD_OBSESSED 25 -#define ANTAG_HUD_FUGITIVE 26 +#define ANTAG_HUD_OBSESSED 24 +#define ANTAG_HUD_FUGITIVE 25 // Notification action types #define NOTIFY_JUMP "jump" diff --git a/code/__DEFINES/role_preferences.dm b/code/__DEFINES/role_preferences.dm index f39407f3215..caac65c6d98 100644 --- a/code/__DEFINES/role_preferences.dm +++ b/code/__DEFINES/role_preferences.dm @@ -27,7 +27,7 @@ #define ROLE_BROTHER "Blood Brother" #define ROLE_BRAINWASHED "Brainwashed Victim" #define ROLE_OVERTHROW "Syndicate Mutineer" //Role removed, left here for safety. -#define ROLE_HIVE "Hivemind Host" +#define ROLE_HIVE "Hivemind Host" //Role removed, left here for safety. #define ROLE_OBSESSED "Obsessed" #define ROLE_SENTIENCE "Sentience Potion Spawn" #define ROLE_MIND_TRANSFER "Mind Transfer Potion" @@ -59,7 +59,6 @@ GLOBAL_LIST_INIT(special_roles, list( ROLE_ABDUCTOR, ROLE_DEVIL = /datum/game_mode/devil, ROLE_SERVANT_OF_RATVAR = /datum/game_mode/clockwork_cult, - ROLE_HIVE = /datum/game_mode/hivemind, ROLE_INTERNAL_AFFAIRS = /datum/game_mode/traitor/internal_affairs, ROLE_SENTIENCE )) diff --git a/code/__DEFINES/status_effects.dm b/code/__DEFINES/status_effects.dm index a99422e60db..3d08f16e8c6 100644 --- a/code/__DEFINES/status_effects.dm +++ b/code/__DEFINES/status_effects.dm @@ -111,10 +111,6 @@ #define STATUS_EFFECT_BUGGED /datum/status_effect/bugged //Lets other mobs listen in on what it hears -#define STATUS_EFFECT_HIVE_TRACKER /datum/status_effect/hive_track - -#define STATUS_EFFECT_HIVE_RADAR /datum/status_effect/agent_pinpointer/hivemind - #define STATUS_EFFECT_BOUNTY /datum/status_effect/bounty //rewards the person who added this to the target with refreshed spells and a fair heal ///////////// diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index d0b4e8529bf..855e0ee7d01 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -227,5 +227,4 @@ #define LOCKED_HELMET_TRAIT "locked-helmet" #define NINJA_SUIT_TRAIT "ninja-suit" #define ANTI_DROP_IMPLANT_TRAIT "anti-drop-implant" -#define HIVEMIND_ONE_MIND_TRAIT "one_mind" #define VR_ZONE_TRAIT "vr_zone_trait" diff --git a/code/_onclick/hud/fullscreen.dm b/code/_onclick/hud/fullscreen.dm index 9155fcd033c..81dbcf28761 100644 --- a/code/_onclick/hud/fullscreen.dm +++ b/code/_onclick/hud/fullscreen.dm @@ -115,16 +115,6 @@ layer = CURSE_LAYER plane = FULLSCREEN_PLANE -/obj/screen/fullscreen/hive_mc - icon_state = "hive_mc" - layer = CURSE_LAYER - plane = FULLSCREEN_PLANE - -/obj/screen/fullscreen/hive_eyes - icon_state = "hive_eyes" - layer = CURSE_LAYER - plane = FULLSCREEN_PLANE - /obj/screen/fullscreen/impaired icon_state = "impairedoverlay" diff --git a/code/datums/hud.dm b/code/datums/hud.dm index 7b69da07778..f0c417c50f5 100644 --- a/code/datums/hud.dm +++ b/code/datums/hud.dm @@ -27,10 +27,8 @@ GLOBAL_LIST_INIT(huds, list( ANTAG_HUD_SOULLESS = new/datum/atom_hud/antag/hidden(), ANTAG_HUD_CLOCKWORK = new/datum/atom_hud/antag(), ANTAG_HUD_BROTHER = new/datum/atom_hud/antag/hidden(), - ANTAG_HUD_HIVE = new/datum/atom_hud/antag/hidden(), ANTAG_HUD_OBSESSED = new/datum/atom_hud/antag/hidden(), - ANTAG_HUD_FUGITIVE = new/datum/atom_hud/antag(), - ANTAG_HUD_HIVEAWAKE = new/datum/atom_hud/antag() + ANTAG_HUD_FUGITIVE = new/datum/atom_hud/antag() )) /datum/atom_hud diff --git a/code/game/gamemodes/hivemind/hivemind.dm b/code/game/gamemodes/hivemind/hivemind.dm deleted file mode 100644 index 3df6ea0d5aa..00000000000 --- a/code/game/gamemodes/hivemind/hivemind.dm +++ /dev/null @@ -1,107 +0,0 @@ -/datum/game_mode/hivemind - name = "Assimilation" - config_tag = "hivemind" - report_type = "hivemind" - antag_flag = ROLE_HIVE - false_report_weight = 5 - protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain") - restricted_jobs = list("Cyborg","AI") - required_players = 24 - required_enemies = 2 - recommended_enemies = 3 - reroll_friendly = 1 - enemy_minimum_age = 0 - - announce_span = "danger" - announce_text = "The hosts of several psionic hiveminds have infiltrated the station and are looking to assimilate the crew!\n\ - Hosts: Expand your hivemind and complete your objectives at all costs!\n\ - Crew: Prevent the hosts from getting into your mind!" - - var/list/hosts = list() - -/proc/is_hivehost(mob/living/M) - if(!M || !M.mind) - return - return M.mind.has_antag_datum(/datum/antagonist/hivemind) - -/mob/living/proc/is_real_hivehost() //This proc ignores mind controlled vessels - for(var/datum/antagonist/hivemind/hive in GLOB.antagonists) - if(!hive.owner?.spell_list) - continue - var/obj/effect/proc_holder/spell/target_hive/hive_control/the_spell = locate(/obj/effect/proc_holder/spell/target_hive/hive_control) in hive.owner.spell_list - if((!the_spell || !the_spell.active ) && mind == hive.owner) - return TRUE - if(the_spell?.active && the_spell.original_body == src) - return TRUE - return FALSE - -/mob/living/proc/get_real_hivehost() //Returns src unless it's under mind control, then it returns the original body - var/mob/living/M = src - if(!M) - return - if(!is_hivehost(M) || is_real_hivehost(M)) - return M - var/obj/effect/proc_holder/spell/target_hive/hive_control/the_spell = locate(/obj/effect/proc_holder/spell/target_hive/hive_control) in M.mind.spell_list - if(the_spell?.active) - return the_spell.original_body - return M - -/proc/is_hivemember(mob/living/L) - if(!L) - return FALSE - var/datum/mind/M = L.mind - if(!M) - return FALSE - for(var/datum/antagonist/hivemind/H in GLOB.antagonists) - if(H.hivemembers.Find(M)) - return TRUE - return FALSE - -/proc/remove_hivemember(mob/living/L) //Removes somebody from all hives as opposed to the antag proc remove_from_hive() - var/datum/mind/M = L?.mind - if(!M) - return - for(var/datum/antagonist/hivemind/H in GLOB.antagonists) - if(H.hivemembers.Find(M)) - H.hivemembers -= M - H.calc_size() - var/datum/antagonist/hivevessel/V = L.is_wokevessel() - if(V && M) - M.remove_antag_datum(/datum/antagonist/hivevessel) - -/datum/game_mode/hivemind/pre_setup() - - if(CONFIG_GET(flag/protect_roles_from_antagonist)) - restricted_jobs += protected_jobs - - if(CONFIG_GET(flag/protect_assistant_from_antagonist)) - restricted_jobs += "Assistant" - - var/num_hosts = max( 1 , rand(0,1) + min(8, round(num_players() / 8) ) ) //1 host for every 8 players up to 64, with a 50% chance of an extra - - for(var/j = 0, j < num_hosts, j++) - if (!antag_candidates.len) - break - var/datum/mind/host = antag_pick(antag_candidates) - hosts += host - host.special_role = ROLE_HIVE - host.restricted_roles = restricted_jobs - log_game("[key_name(host)] has been selected as a hivemind host") - antag_candidates.Remove(host) - - if(hosts.len < required_enemies) - setup_error = "Not enough host candidates" - return FALSE - else - return TRUE - - -/datum/game_mode/hivemind/post_setup() - for(var/datum/mind/i in hosts) - i.add_antag_datum(/datum/antagonist/hivemind) - return ..() - -/datum/game_mode/hivemind/generate_report() - return "Reports of psychic activity have been showing up in this sector, and we believe this may have to do with a containment breach on \[REDACTED\] last month \ - when a sapient hive intelligence displaying paranormal powers escaped into the unknown. They present a very large risk as they can assimilate people into \ - the hivemind with ease, although they appear unable to affect mindshielded personnel." diff --git a/code/game/gamemodes/hivemind/objectives.dm b/code/game/gamemodes/hivemind/objectives.dm deleted file mode 100644 index 526fc03e83b..00000000000 --- a/code/game/gamemodes/hivemind/objectives.dm +++ /dev/null @@ -1,53 +0,0 @@ -/datum/objective/hivemind - -/datum/objective/hivemind/hivesize - explanation_text = "This is a bug. Error:HIVE2" - target_amount = 10 - -/datum/objective/hivemind/hivesize/New() - target_amount = ( max(8, round(GLOB.joined_player_list.len/3)) + rand(0,3) ) - update_explanation_text() - -/datum/objective/hivemind/hivesize/update_explanation_text() - explanation_text = "End the round with at least [target_amount] beings assimilated into the hive." - -/datum/objective/hivemind/hivesize/check_completion() - var/datum/antagonist/hivemind/host = owner.has_antag_datum(/datum/antagonist/hivemind) - if(!host) - return FALSE - return host.hive_size >= target_amount - -/datum/objective/hivemind/hiveescape - explanation_text = "This is a bug. Error:HIVE2" - target_amount = 10 - -/datum/objective/hivemind/hiveescape/New() - target_amount = ( max(5, round(GLOB.joined_player_list.len/6)) + rand(0,2) ) - update_explanation_text() - -/datum/objective/hivemind/hiveescape/update_explanation_text() - explanation_text = "Have at least [target_amount] members of the hive escape on the shuttle alive and free." - -/datum/objective/hivemind/hiveescape/check_completion() - var/count = 0 - var/datum/antagonist/hivemind/host = owner.has_antag_datum(/datum/antagonist/hivemind) - if(!host) - return FALSE - for(var/datum/mind/M in host.hivemembers) - if(considered_escaped(M)) - count++ - return count >= target_amount - -/datum/objective/hivemind/biggest - explanation_text = "End the round with more vessels than any other hivemind host." - -/datum/objective/hivemind/biggest/check_completion() - var/datum/antagonist/hivemind/host = owner.has_antag_datum(/datum/antagonist/hivemind) - if(!host) - return FALSE - for(var/datum/antagonist/hivemind/H in GLOB.antagonists) - if(H == host) - continue - if(H.hive_size >= host.hive_size) - return FALSE - return TRUE diff --git a/code/game/gamemodes/hivemind/radar.dm b/code/game/gamemodes/hivemind/radar.dm deleted file mode 100644 index bb5827cdc2c..00000000000 --- a/code/game/gamemodes/hivemind/radar.dm +++ /dev/null @@ -1,74 +0,0 @@ -#define HIVEMIND_RADAR_MIN_DISTANCE 0 //Very generous, as the targets are only tracked for a few minutes. -#define HIVEMIND_RADAR_MAX_DISTANCE 50 -#define HIVEMIND_RADAR_PING_TIME 40 //4s update time. - -//Modified IA/changeling pinpointer, points to the nearest person who is afflicted with the hive tracker status effect -/datum/status_effect/agent_pinpointer/hivemind - id = "hive_pinpointer" - alert_type = /obj/screen/alert/status_effect/agent_pinpointer/hivemind - minimum_range = HIVEMIND_RADAR_MIN_DISTANCE - tick_interval = HIVEMIND_RADAR_PING_TIME - range_fuzz_factor = 0 - -/datum/status_effect/agent_pinpointer/hivemind/point_to_target() //If we found what we're looking for, show the distance and direction - if(scan_target) - if(owner.mind) - var/datum/antagonist/hivemind/hive = owner.mind.has_antag_datum(/datum/antagonist/hivemind) - if(hive) - range_far = range_mid * (2-hive.get_threat_multiplier()) - if(scan_target.mind) - var/datum/antagonist/hivemind/enemy_hive = scan_target.mind.has_antag_datum(/datum/antagonist/hivemind) - if(enemy_hive) - range_far = max(range_mid * (1+enemy_hive.get_threat_multiplier()), range_far) - - ..() - -/datum/status_effect/agent_pinpointer/hivemind/scan_for_target() - var/turf/my_loc = get_turf(owner) - - var/list/mob/living/carbon/targets = list() - var/trackable_targets_exist = FALSE - - for(var/mob/living/carbon/C in GLOB.alive_mob_list) - if(C == owner) - continue - var/datum/status_effect/hive_track/mark = C.has_status_effect(STATUS_EFFECT_HIVE_TRACKER) - if(mark && mark.tracked_by == owner) - trackable_targets_exist = TRUE - var/their_loc = get_turf(C) - var/distance = get_dist_euclidian(my_loc, their_loc) - if (distance < HIVEMIND_RADAR_MAX_DISTANCE) - var/multiplier = 0.5 - if(C.mind) - var/datum/antagonist/hivemind/hive = C.mind.has_antag_datum(/datum/antagonist/hivemind) - if(hive) - multiplier = hive.get_threat_multiplier() - targets[C] = ((HIVEMIND_RADAR_MAX_DISTANCE ** 2) - (distance ** 2)) * multiplier - - if(targets.len) - scan_target = pickweight(targets) //Point at a 'random' target, biasing heavily towards closer ones. - else - scan_target = null - if(!trackable_targets_exist) - to_chat(owner, "The psychic energies eminating from afar have died down... for now") - owner.remove_status_effect(STATUS_EFFECT_HIVE_RADAR) - -//"Trackable" status effect -/datum/status_effect/hive_track - id = "hive_track" - duration = 1200 - status_type = STATUS_EFFECT_MULTIPLE - alert_type = null - var/mob/living/tracked_by - -/datum/status_effect/hive_track/on_creation(mob/living/new_owner, mob/living/hunter, set_duration) - . = ..() - if(.) - tracked_by = hunter - if(isnum(set_duration)) - duration = world.time + set_duration - -//Screen alert -/obj/screen/alert/status_effect/agent_pinpointer/hivemind - name = "Psychic link" - desc = "Somebody is there, and they're definitely not friendly." diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm index 9a4b60eb65e..85ae13751b2 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -220,7 +220,6 @@ if(H) H.faction |= factions - remove_hivemember(H) for(var/V in quirks) var/datum/quirk/Q = new V(H) diff --git a/code/game/objects/items/implants/implant_mindshield.dm b/code/game/objects/items/implants/implant_mindshield.dm index 5a3edeb994f..90b4f798977 100644 --- a/code/game/objects/items/implants/implant_mindshield.dm +++ b/code/game/objects/items/implants/implant_mindshield.dm @@ -26,40 +26,13 @@ if(target.mind.has_antag_datum(/datum/antagonist/brainwashed)) target.mind.remove_antag_datum(/datum/antagonist/brainwashed) - var/datum/antagonist/hivemind/host = target.mind.has_antag_datum(/datum/antagonist/hivemind) //Releases the target from mind control beforehand - if(host) - var/datum/mind/M = host.owner - if(M) - var/obj/effect/proc_holder/spell/target_hive/hive_control/the_spell = locate(/obj/effect/proc_holder/spell/target_hive/hive_control) in M.spell_list - if(the_spell && the_spell.active) - the_spell.release_control() - - if(target.mind.has_antag_datum(/datum/antagonist/rev/head) || target.mind.has_antag_datum(/datum/antagonist/hivemind) || target.mind.unconvertable) + if(target.mind.has_antag_datum(/datum/antagonist/rev/head)|| target.mind.unconvertable) if(!silent) target.visible_message("[target] seems to resist the implant!", "You feel something interfering with your mental conditioning, but you resist it!") removed(target, 1) qdel(src) return TRUE //the implant is still used - var/datum/antagonist/hivevessel/woke = target.is_wokevessel() - if(is_hivemember(target)) - for(var/datum/antagonist/hivemind/hive in GLOB.antagonists) - if(hive.hivemembers.Find(target.mind)) - var/mob/living/carbon/C = hive.owner.current.get_real_hivehost() - if(C) - C.apply_status_effect(STATUS_EFFECT_HIVE_TRACKER, target, woke?TRACKER_AWAKENED_TIME:TRACKER_MINDSHIELD_TIME) - target.apply_status_effect(STATUS_EFFECT_HIVE_TRACKER, C, TRACKER_DEFAULT_TIME) - if(C.mind) //If you were using mind control, too bad - C.apply_status_effect(STATUS_EFFECT_HIVE_RADAR) - to_chat(C, "We detect a surge of psionic energy from a far away vessel before they disappear from the hive. Whatever happened, there's a good chance they're after us now.") - to_chat(target, "You hear supernatural wailing echo throughout your mind as you are finally set free. Deep down, you can feel the lingering presence of those who enslaved you... as can they!") - target.apply_status_effect(STATUS_EFFECT_HIVE_RADAR) - remove_hivemember(target) - - if(woke) - woke.one_mind?.remove_member(target.mind) - target.mind.remove_antag_datum(/datum/antagonist/hivevessel) - var/datum/antagonist/rev/rev = target.mind.has_antag_datum(/datum/antagonist/rev) if(rev) rev.remove_revolutionary(FALSE, user) diff --git a/code/modules/antagonists/hivemind/hivemind.dm b/code/modules/antagonists/hivemind/hivemind.dm deleted file mode 100644 index 163fb29a196..00000000000 --- a/code/modules/antagonists/hivemind/hivemind.dm +++ /dev/null @@ -1,298 +0,0 @@ -/datum/antagonist/hivemind - name = "Hivemind Host" - roundend_category = "hiveminds" - antagpanel_category = "Hivemind Host" - job_rank = ROLE_HIVE - antag_moodlet = /datum/mood_event/focused - var/special_role = ROLE_HIVE - var/list/hivemembers = list() - var/hive_size = 0 - var/threat_level = 0 // Part of what determines how strong the radar is, on a scale of 0 to 10 - var/track_bonus = 0 // Bonus time to your tracking abilities - var/size_mod = 0 // Bonus size for using reclaim - var/list/individual_track_bonus = list() // Bonus time to tracking individual targets - var/unlocked_one_mind = FALSE - var/datum/team/hivemind/active_one_mind - var/mutable_appearance/glow - - var/list/upgrade_tiers = list( - //Tier 1 - Roundstart powers - /obj/effect/proc_holder/spell/target_hive/hive_add = 0, - /obj/effect/proc_holder/spell/target_hive/hive_remove = 0, - /obj/effect/proc_holder/spell/target_hive/hive_see = 0, - /obj/effect/proc_holder/spell/targeted/hive_shock = 0, - /obj/effect/proc_holder/spell/self/telekinetic_hand = 0, - //Tier 2 - Tracking related powers - /obj/effect/proc_holder/spell/self/hive_scan = 5, - /obj/effect/proc_holder/spell/targeted/hive_reclaim = 5, - /obj/effect/proc_holder/spell/targeted/hive_hack = 5, - //Tier 3 - Combat related powers - /obj/effect/proc_holder/spell/self/hive_drain = 10, - /obj/effect/proc_holder/spell/targeted/induce_panic = 10, - /obj/effect/proc_holder/spell/targeted/forcewall/hive = 10, - //Tier 4 - Chaos-spreading powers - /obj/effect/proc_holder/spell/self/hive_wake = 15, - /obj/effect/proc_holder/spell/self/hive_loyal = 15, - /obj/effect/proc_holder/spell/target_hive/hive_control = 15, - //Tier 5 - Deadly powers - /obj/effect/proc_holder/spell/targeted/pin = 20, - /obj/effect/proc_holder/spell/target_hive/nightmare = 20 - ) - - -/datum/antagonist/hivemind/proc/calc_size() - listclearnulls(hivemembers) - var/temp = 0 - for(var/datum/mind/M in hivemembers) - if(M.current && M.current.stat != DEAD) - temp++ - if(hive_size != temp) - hive_size = temp - check_powers() - -/datum/antagonist/hivemind/proc/get_threat_multiplier() - calc_size() - return min((hive_size+size_mod*2)/50 + threat_level/20, 1) - -/datum/antagonist/hivemind/proc/get_carbon_members() - var/list/carbon_members = list() - for(var/datum/mind/M in hivemembers) - if(!M.current || !iscarbon(M.current)) - continue - carbon_members += M.current - return carbon_members - -/datum/antagonist/hivemind/proc/check_powers() - for(var/power in upgrade_tiers) - var/level = upgrade_tiers[power] - if(hive_size+size_mod >= level && !(locate(power) in owner.spell_list)) - var/obj/effect/proc_holder/spell/the_spell = new power(null) - owner.AddSpell(the_spell) - if(hive_size > 0) - to_chat(owner, "We have unlocked [the_spell.name]. [the_spell.desc]") - - if(!unlocked_one_mind && hive_size >= 15) - var/lead = TRUE - for(var/datum/antagonist/hivemind/enemy in GLOB.antagonists) - if(enemy == src) - continue - if(!enemy.active_one_mind && enemy.hive_size <= hive_size + size_mod - 20) - continue - lead = FALSE - break - if(lead) - unlocked_one_mind = TRUE - owner.AddSpell(new/obj/effect/proc_holder/spell/self/one_mind) - to_chat(owner, "Our true power, the One Mind, is finally within reach.") - -/datum/antagonist/hivemind/proc/add_track_bonus(datum/antagonist/hivemind/enemy, bonus) - if(!individual_track_bonus[enemy]) - individual_track_bonus[enemy] = bonus - else - individual_track_bonus[enemy] += bonus - -/datum/antagonist/hivemind/proc/get_track_bonus(datum/antagonist/hivemind/enemy) - if(!individual_track_bonus[enemy]) - . = 0 - else - . = individual_track_bonus[enemy] - . += (TRACKER_DEFAULT_TIME + track_bonus) - -/datum/antagonist/hivemind/proc/add_to_hive(mob/living/carbon/C) - if(!C) - return - var/datum/mind/M = C.mind - if(M) - hivemembers |= M - calc_size() - - var/user_warning = "We have detected an enemy hivemind using our physical form as a vessel and have begun ejecting their mind! They will be alerted of our disappearance once we succeed!" - if(C.is_real_hivehost()) - var/eject_time = rand(1400,1600) //2.5 minutes +- 10 seconds - addtimer(CALLBACK(GLOBAL_PROC, /proc/to_chat, C, user_warning), rand(500,1300)) // If the host has assimilated an enemy hive host, alert the enemy before booting them from the hive after a short while - addtimer(CALLBACK(src, .proc/handle_ejection, C), eject_time) - else if(active_one_mind) - C.hive_awaken(final_form=active_one_mind) - -/datum/antagonist/hivemind/proc/is_carbon_member(mob/living/carbon/C) - if(!hivemembers || !C || !iscarbon(C)) - return FALSE - var/datum/mind/M = C.mind - if(!M || !hivemembers.Find(M)) - return FALSE - return TRUE - -/datum/antagonist/hivemind/proc/remove_from_hive(mob/living/carbon/C) - var/datum/mind/M = C.mind - if(M) - hivemembers -= M - calc_size() - if(active_one_mind) - var/datum/antagonist/hivevessel/V = C.is_wokevessel() - if(V) - M.remove_antag_datum(/datum/antagonist/hivevessel) - -/datum/antagonist/hivemind/proc/handle_ejection(mob/living/carbon/C) - var/user_warning = "The enemy host has been ejected from our mind" - if(!C || !owner) - return - var/mob/living/carbon/C2 = owner.current - if(!C2) - return - - var/mob/living/real_C = C.get_real_hivehost() - var/mob/living/real_C2 = C2.get_real_hivehost() - var/datum/antagonist/hivemind/hive_C - var/datum/antagonist/hivemind/hive_C2 - if(real_C.mind) - hive_C = real_C.mind.has_antag_datum(/datum/antagonist/hivemind) - if(real_C2.mind) - hive_C2 = real_C2.mind.has_antag_datum(/datum/antagonist/hivemind) - if(!hive_C || !hive_C2) - return - if(C == real_C) //Mind control check - real_C2.apply_status_effect(STATUS_EFFECT_HIVE_TRACKER, real_C, hive_C.get_track_bonus(hive_C2)) - real_C.apply_status_effect(STATUS_EFFECT_HIVE_RADAR) - to_chat(real_C2, "We detect a surge of psionic energy from a far away vessel before they disappear from the hive. Whatever happened, there's a good chance they're after us now.") - if(C2 == real_C2) - real_C.apply_status_effect(STATUS_EFFECT_HIVE_TRACKER, real_C2, hive_C2.get_track_bonus(hive_C)) - real_C2.apply_status_effect(STATUS_EFFECT_HIVE_RADAR) - user_warning += " and we've managed to pinpoint their location" - to_chat(real_C, "[user_warning]!") - -/datum/antagonist/hivemind/proc/destroy_hive() - go_back_to_sleep() - hivemembers = list() - calc_size() - for(var/power in upgrade_tiers) - if(!upgrade_tiers[power]) - continue - owner.RemoveSpell(power) - -/datum/antagonist/hivemind/antag_panel_data() - return "Vessels Assimilated: [hive_size] (+[size_mod])" - -/datum/antagonist/hivemind/proc/awaken() - if(!owner?.current) - return - var/mob/living/carbon/C = owner.current.get_real_hivehost() - if(!C) - return - owner.AddSpell(new/obj/effect/proc_holder/spell/self/hive_comms) - ADD_TRAIT(C, TRAIT_STUNIMMUNE, HIVEMIND_ONE_MIND_TRAIT) - ADD_TRAIT(C, TRAIT_SLEEPIMMUNE, HIVEMIND_ONE_MIND_TRAIT) - ADD_TRAIT(C, TRAIT_VIRUSIMMUNE, HIVEMIND_ONE_MIND_TRAIT) - ADD_TRAIT(C, TRAIT_NOLIMBDISABLE, HIVEMIND_ONE_MIND_TRAIT) - ADD_TRAIT(C, TRAIT_NOHUNGER, HIVEMIND_ONE_MIND_TRAIT) - ADD_TRAIT(C, TRAIT_NODISMEMBER, HIVEMIND_ONE_MIND_TRAIT) - log_game("[key_name(owner)] has awakened vessels.") - -/datum/antagonist/hivemind/proc/go_back_to_sleep() - if(!active_one_mind) - return - for(var/datum/mind/M in hivemembers) - M.remove_antag_datum(/datum/antagonist/hivevessel) - active_one_mind.remove_member(M) - if(!(owner?.current)) - return - var/mob/living/carbon/C = owner.current.get_real_hivehost() - if(!C) - return - owner.RemoveSpell(new/obj/effect/proc_holder/spell/self/hive_comms) - REMOVE_TRAIT(C, TRAIT_STUNIMMUNE, HIVEMIND_ONE_MIND_TRAIT) - REMOVE_TRAIT(C, TRAIT_SLEEPIMMUNE, HIVEMIND_ONE_MIND_TRAIT) - REMOVE_TRAIT(C, TRAIT_VIRUSIMMUNE, HIVEMIND_ONE_MIND_TRAIT) - REMOVE_TRAIT(C, TRAIT_NOLIMBDISABLE, HIVEMIND_ONE_MIND_TRAIT) - REMOVE_TRAIT(C, TRAIT_NOHUNGER, HIVEMIND_ONE_MIND_TRAIT) - REMOVE_TRAIT(C, TRAIT_NODISMEMBER, HIVEMIND_ONE_MIND_TRAIT) - active_one_mind.Destroy() - -/datum/antagonist/hivemind/on_gain() - owner.special_role = special_role - check_powers() - forge_objectives() - ..() - -/datum/antagonist/hivemind/apply_innate_effects() - if(owner.assigned_role == "Clown") - var/mob/living/carbon/human/traitor_mob = owner.current - if(traitor_mob && istype(traitor_mob)) - if(!silent) - to_chat(traitor_mob, "The great psionic powers of the Hive lets you overcome your clownish nature, allowing you to wield weapons with impunity.") - traitor_mob.dna.remove_mutation(CLOWNMUT) - var/datum/atom_hud/antag/hud = GLOB.huds[ANTAG_HUD_HIVE] - hud.join_hud(owner.current) - set_antag_hud(owner.current, "hivemind") - -/datum/antagonist/hivemind/remove_innate_effects() - if(owner.assigned_role == "Clown") - var/mob/living/carbon/human/traitor_mob = owner.current - if(traitor_mob && istype(traitor_mob)) - traitor_mob.dna.add_mutation(CLOWNMUT) - var/datum/atom_hud/antag/hud = GLOB.huds[ANTAG_HUD_HIVE] - hud.leave_hud(owner.current) - set_antag_hud(owner.current, null) - -/datum/antagonist/hivemind/on_removal() - //Remove all hive powers here - for(var/power in upgrade_tiers) - owner.RemoveSpell(power) - - if(!silent && owner.current) - to_chat(owner.current," Your psionic powers fade, you are no longer the hivemind's host! ") - owner.special_role = null - ..() - -/datum/antagonist/hivemind/proc/forge_objectives() - if(prob(50)) - var/datum/objective/hivemind/hivesize/size_objective = new - size_objective.owner = owner - objectives += size_objective - else if(prob(70)) - var/datum/objective/hivemind/hiveescape/hive_escape_objective = new - hive_escape_objective.owner = owner - objectives += hive_escape_objective - else - var/datum/objective/hivemind/biggest/biggest_objective = new - biggest_objective.owner = owner - objectives += biggest_objective - - var/datum/objective/escape/escape_objective = new - escape_objective.owner = owner - objectives += escape_objective - - return - -/datum/antagonist/hivemind/greet() - to_chat(owner.current, "You are the host of a powerful Hivemind.") - to_chat(owner.current, "Your psionic powers will grow by assimilating the crew into your hive. Use the Assimilate Vessel spell on a stationary \ - target, and after ten seconds he will be one of the hive. This is completely silent and safe to use, and failing will reset the cooldown. As \ - you assimilate the crew, you will gain more powers to use. Most are silent and won't help you in a fight, but grant you great power over your \ - vessels. Hover your mouse over a power's action icon for an extended description on what it does. There are other hiveminds onboard the station, \ - collaboration is possible, but a strong enough hivemind can reap many rewards from a well planned betrayal.") - owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/assimilation.ogg', 100, FALSE, pressure_affected = FALSE) - - owner.announce_objectives() - -/datum/antagonist/hivemind/roundend_report() - var/list/result = list() - - result += printplayer(owner) - result += "Hive Size: [hive_size]" - var/greentext = TRUE - if(objectives) - result += printobjectives(objectives) - for(var/datum/objective/objective in objectives) - if(!objective.check_completion()) - greentext = FALSE - break - - if(objectives.len == 0 || greentext) - result += "The [name] was successful!" - else - result += "The [name] has failed!" - - return result.Join("
") - -/datum/antagonist/hivemind/is_gamemode_hero() - return SSticker.mode.name == "Assimilation" diff --git a/code/modules/antagonists/hivemind/vessel.dm b/code/modules/antagonists/hivemind/vessel.dm deleted file mode 100644 index 6b13cbcd589..00000000000 --- a/code/modules/antagonists/hivemind/vessel.dm +++ /dev/null @@ -1,93 +0,0 @@ -/datum/team/hivemind - name = "One Mind" - -/datum/antagonist/hivevessel - name = "Awoken Vessel" - job_rank = ROLE_BRAINWASHED - roundend_category = "awoken vessels" - show_in_antagpanel = TRUE - antagpanel_category = "Other" - show_name_in_check_antagonists = TRUE - var/datum/team/hivemind/one_mind - var/mutable_appearance/glow - -/mob/living/proc/is_wokevessel() - return mind?.has_antag_datum(/datum/antagonist/hivevessel) - -/mob/living/proc/hive_awaken(objective, datum/team/hivemind/final_form) - if(!mind) - return - var/datum/mind/M = mind - var/datum/antagonist/hivevessel/vessel = M.has_antag_datum(/datum/antagonist/hivevessel) - if(!vessel) - vessel = new() - if(final_form) - vessel.objectives = list() //Reset objectives on re-awoken vessels - if(ishuman(M.current)) - vessel.glow = mutable_appearance('icons/effects/hivemind.dmi', "awoken", -BODY_BEHIND_LAYER) - M.current.add_overlay(vessel.glow) - M.AddSpell(new/obj/effect/proc_holder/spell/self/hive_comms) - vessel.one_mind = final_form - vessel.one_mind.add_member(M) - vessel.objectives |= vessel.one_mind.objectives - else - var/datum/objective/brainwashing/obj = new(objective) - vessel.objectives += obj - var/message = " has been awoken with the following objectives: [objective]." - deadchat_broadcast(message, "[M]", follow_target = M, turf_target = get_turf(M), message_type=DEADCHAT_REGULAR) - log_game("[key_name(M)] has been awoken with the following objectives: [objective]") - if(!M.has_antag_datum(/datum/antagonist/hivevessel)) - M.add_antag_datum(vessel) - -/datum/antagonist/hivevessel/apply_innate_effects() - if(owner.assigned_role == "Clown") - var/mob/living/carbon/human/traitor_mob = owner.current - if(traitor_mob && istype(traitor_mob)) - if(!silent) - to_chat(traitor_mob, "Our newfound powers allow us to overcome our clownish nature, allowing us to wield weapons with impunity.") - traitor_mob.dna.remove_mutation(CLOWNMUT) - var/datum/atom_hud/antag/hud = GLOB.huds[ANTAG_HUD_HIVE] - hud.join_hud(owner.current) - set_antag_hud(owner.current, "hivevessel") - -/datum/antagonist/hivevessel/remove_innate_effects() - if(owner.assigned_role == "Clown") - var/mob/living/carbon/human/traitor_mob = owner.current - if(traitor_mob && istype(traitor_mob)) - traitor_mob.dna.add_mutation(CLOWNMUT) - var/datum/atom_hud/antag/hud = GLOB.huds[ANTAG_HUD_HIVE] - hud.leave_hud(owner.current) - set_antag_hud(owner.current, null) - -/datum/antagonist/hivevessel/greet() - to_chat(owner, "Your mind is suddenly opened, as you see the pinnacle of evolution...") - to_chat(owner, "Follow your objectives, at any cost!") - var/i = 1 - for(var/X in objectives) - var/datum/objective/O = X - to_chat(owner, "[i]. [O.explanation_text]") - i++ - -/datum/antagonist/hivevessel/on_removal() - if(owner?.current && glow) - owner.current.cut_overlay(glow) - if(one_mind && owner) - one_mind.remove_member(owner) - ..() - -/datum/antagonist/hivevessel/farewell() - to_chat(owner, "Your mind closes up once more...") - to_chat(owner, "You feel the weight of your objectives disappear! You no longer have to obey them.") - -/datum/antagonist/hivevessel/roundend_report() - if(!owner) - CRASH("antagonist datum without owner") - - if(one_mind) - return printplayer(owner) - - var/list/report = list() - report += printplayer(owner) - if(objectives.len) - report += printobjectives(objectives) - return report.Join("
") diff --git a/code/modules/goonchat/browserassets/css/browserOutput.css b/code/modules/goonchat/browserassets/css/browserOutput.css index 0c45d98ab24..ae0c5728d50 100644 --- a/code/modules/goonchat/browserassets/css/browserOutput.css +++ b/code/modules/goonchat/browserassets/css/browserOutput.css @@ -380,7 +380,6 @@ em {font-style: normal; font-weight: bold;} .noticealien {color: #059223;} .alertalien {color: #059223; font-weight: bold;} .changeling {color: #059223; font-style: italic;} -.assimilator {color: #059223; font-size: 16px ; font-weight: bold;} .alertsyndie {color: #FF0000; font-size: 24px ; font-weight: bold;} .spider {color: #8800ff;} diff --git a/code/modules/goonchat/browserassets/css/browserOutput_white.css b/code/modules/goonchat/browserassets/css/browserOutput_white.css index 06b891869e3..63279c9de9a 100644 --- a/code/modules/goonchat/browserassets/css/browserOutput_white.css +++ b/code/modules/goonchat/browserassets/css/browserOutput_white.css @@ -378,8 +378,6 @@ h1.alert, h2.alert {color: #000000;} .noticealien {color: #00c000;} .alertalien {color: #00c000; font-weight: bold;} .changeling {color: #800080; font-style: italic;} -.assimilator {color: #800080; font-size: 16px ; font-weight: bold;} -.bigassimilator {color: #800080; font-size: 32px ; font-weight: bold;} .alertsyndie {color: #FF0000; font-size: 24px ; font-weight: bold;} .spider {color: #4d004d; font-weight: bold; font-size: 24px;} diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm index c32f67f30f3..6b254bb626e 100644 --- a/code/modules/mob/living/carbon/human/death.dm +++ b/code/modules/mob/living/carbon/human/death.dm @@ -41,11 +41,6 @@ log_game("[key_name(src)] has died (BRUTE: [src.getBruteLoss()], BURN: [src.getFireLoss()], TOX: [src.getToxLoss()], OXY: [src.getOxyLoss()], CLONE: [src.getCloneLoss()]) ([AREACOORD(src)])") if(is_devil(src)) INVOKE_ASYNC(is_devil(src), /datum/antagonist/devil.proc/beginResurrectionCheck, src) - if(is_hivemember(src)) - remove_hivemember(src) - if(is_hivehost(src)) - var/datum/antagonist/hivemind/hive = mind.has_antag_datum(/datum/antagonist/hivemind) - hive.destroy_hive() /mob/living/carbon/human/proc/makeSkeleton() ADD_TRAIT(src, TRAIT_DISFIGURED, TRAIT_GENERIC) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 203a2e228f7..854a2a5f351 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -73,10 +73,6 @@ if(changeling) stat("Chemical Storage", "[changeling.chem_charges]/[changeling.chem_storage]") stat("Absorbed DNA", changeling.absorbedcount) - var/datum/antagonist/hivemind/hivemind = mind.has_antag_datum(/datum/antagonist/hivemind) - if(hivemind) - stat("Hivemind Vessels", "[hivemind.hive_size] (+[hivemind.size_mod])") - stat("Psychic Link Duration", "[(hivemind.track_bonus + TRACKER_DEFAULT_TIME)/10] seconds") //NINJACODE if(istype(wear_suit, /obj/item/clothing/suit/space/space_ninja)) //Only display if actually a ninja. diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index fc4b5485bea..774f8286830 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -1467,9 +1467,6 @@ GLOBAL_LIST_EMPTY(roundstart_races) var/datum/antagonist/rev/rev = H.mind.has_antag_datum(/datum/antagonist/rev) if(rev) rev.remove_revolutionary(FALSE, user) - var/datum/antagonist/hivevessel/woke = H.is_wokevessel() - if(woke && woke.one_mind) - H.mind.remove_antag_datum(/datum/antagonist/hivevessel) if(bloody) //Apply blood if(H.wear_mask) diff --git a/code/modules/research/nanites/nanite_programs/buffing.dm b/code/modules/research/nanites/nanite_programs/buffing.dm index b2caf0e0fde..1746eb668d9 100644 --- a/code/modules/research/nanites/nanite_programs/buffing.dm +++ b/code/modules/research/nanites/nanite_programs/buffing.dm @@ -118,7 +118,7 @@ /datum/nanite_program/mindshield/enable_passive_effect() . = ..() - if(!host_mob.mind.has_antag_datum(/datum/antagonist/rev, TRUE) && !is_hivemember(host_mob) && !host_mob.is_wokevessel()) //won't work if on a rev, to avoid having implanted revs. same applies for hivemind members. + if(!host_mob.mind.has_antag_datum(/datum/antagonist/rev, TRUE)) //won't work if on a rev, to avoid having implanted revs. ADD_TRAIT(host_mob, TRAIT_MINDSHIELD, "nanites") host_mob.sec_hud_set_implants() diff --git a/code/modules/spells/spell_types/hivemind.dm b/code/modules/spells/spell_types/hivemind.dm deleted file mode 100644 index fd7fc29ec52..00000000000 --- a/code/modules/spells/spell_types/hivemind.dm +++ /dev/null @@ -1,1001 +0,0 @@ -/obj/effect/proc_holder/spell/target_hive - panel = "Hivemind Abilities" - invocation_type = "none" - selection_type = "range" - action_icon = 'icons/mob/actions/actions_hive.dmi' - action_background_icon_state = "bg_hive" - action_icon_state = "spell_default" - clothes_req = 0 - human_req = 1 - antimagic_allowed = TRUE - range = 0 //SNOWFLAKE, 0 is unlimited for target_external=0 spells - var/target_external = 0 //Whether or not we select targets inside or outside of the hive - - -/obj/effect/proc_holder/spell/target_hive/choose_targets(mob/user = usr) - var/datum/antagonist/hivemind/hive = user.mind.has_antag_datum(/datum/antagonist/hivemind) - if(!hive || !hive.hivemembers) - to_chat(user, "This is a bug. Error:HIVE1") - return - var/list/possible_targets = list() - var/list/targets = list() - - if(target_external) - for(var/mob/living/carbon/H in view_or_range(range, user, selection_type)) - if(user == H) - continue - if(!can_target(H)) - continue - if(!hive.is_carbon_member(H)) - possible_targets += H - else - possible_targets = hive.get_carbon_members() - if(range) - possible_targets &= view_or_range(range, user, selection_type) - - var/mob/living/carbon/human/H = input("Choose the target for the spell.", "Targeting") as null|mob in possible_targets - if(!H) - revert_cast() - return - targets += H - perform(targets,user=user) - -/obj/effect/proc_holder/spell/target_hive/hive_add - name = "Assimilate Vessel" - desc = "We silently add an unsuspecting target to the hive." - selection_type = "view" - action_icon_state = "add" - - charge_max = 50 - range = 7 - target_external = 1 - var/bruteforce = FALSE - -/obj/effect/proc_holder/spell/target_hive/hive_add/cast(list/targets, mob/living/user = usr) - var/mob/living/carbon/target = targets[1] - var/datum/antagonist/hivemind/hive = user.mind.has_antag_datum(/datum/antagonist/hivemind) - - if(!target.mind || !target.client || target.stat == DEAD) - to_chat(user, "We detect no neural activity in this body.") - var/shielded = HAS_TRAIT(target, TRAIT_MINDSHIELD) - var/foiled = target.anti_magic_check(FALSE, FALSE, TRUE, 0) - if(shielded && !bruteforce) - to_chat(user, "Powerful technology protects [target.name]'s mind.") - revert_cast() - return - if((shielded || foiled) && bruteforce) - to_chat(user, "We [bruteforce ? "bruteforce" : "force"] our way past the mental barriers of [target.name] and begin linking our minds!") - else - to_chat(user, "We begin linking our mind with [target.name]!") - var/multiplier = (!foiled || bruteforce) ? 5 : 10 - if(!do_after(user,multiplier*(1.5**get_dist(user, target)),0,user) || !(target in view(range))) - to_chat(user, "We fail to connect to [target.name].") - revert_cast() - return - if((HAS_TRAIT(target, TRAIT_MINDSHIELD) && !bruteforce)) - to_chat(user, "We fail to connect to [target.name].") - revert_cast() - return - to_chat(user, "[target.name] was added to the Hive!") - hive.add_to_hive(target) - hive.threat_level = max(0, hive.threat_level-0.1) - if(bruteforce) - if(target.anti_magic_check(FALSE, FALSE, TRUE, 6)) - target.adjustBrainLoss(10) - to_chat(user, "We are briefly exhausted by the effort required by our enhanced assimilation abilities.") - user.Immobilize(50) - SEND_SIGNAL(target, COMSIG_NANITE_SET_VOLUME, 0) - for(var/obj/item/implant/mindshield/M in target.implants) - qdel(M) - else - target.anti_magic_check(FALSE, FALSE, TRUE) - -/obj/effect/proc_holder/spell/target_hive/hive_remove - name = "Release Vessel" - desc = "We silently remove a nearby target from the hive. We must be close to their body to do so." - selection_type = "view" - action_icon_state = "remove" - - charge_max = 50 - range = 7 - -/obj/effect/proc_holder/spell/target_hive/hive_remove/cast(list/targets, mob/living/user = usr) - var/mob/living/carbon/target = targets[1] - - var/datum/antagonist/hivemind/hive = user.mind.has_antag_datum(/datum/antagonist/hivemind) - if(!hive) - to_chat(user, "This is a bug. Error:HIVE1") - return - var/datum/mind/M = target.mind - if(!M) - revert_cast() - return - hive.remove_from_hive(target) - hive.calc_size() - hive.threat_level += 0.1 - to_chat(user, "We remove [target.name] from the hive") - if(hive.active_one_mind) - var/datum/antagonist/hivevessel/woke = target.is_wokevessel() - if(woke) - hive.active_one_mind.remove_member(M) - M.remove_antag_datum(/datum/antagonist/hivevessel) - -/obj/effect/proc_holder/spell/target_hive/hive_see - name = "Hive Vision" - desc = "We use the eyes of one of our vessels. Use again to look through our own eyes once more." - action_icon_state = "see" - var/mob/living/carbon/vessel - var/mob/living/host //Didn't really have any other way to auto-reset the perspective if the other mob got qdeled - var/limited = FALSE - - charge_max = 20 - -/obj/effect/proc_holder/spell/target_hive/hive_see/on_lose(mob/living/user) - user.reset_perspective() - user.clear_fullscreen("hive_eyes") - -/obj/effect/proc_holder/spell/target_hive/hive_see/cast(list/targets, mob/living/user = usr) - if(!active) - vessel = targets[1] - if(vessel) - if(vessel.anti_magic_check(FALSE, FALSE, TRUE, 0)) - if(get_dist(src, vessel) > 42) - to_chat(user, "We were unable to link our view with [vessel.name]. A barrier of tinfoil prevents us to do so at this distance.") - revert_cast() - return - limited = TRUE - to_chat(user, "A barrier of tinfoil drastically dampens our link with [vessel.name]. We'll be able to sustain the link as long as they remain within 42 tiles from us.") - vessel.apply_status_effect(STATUS_EFFECT_BUGGED, user) - user.reset_perspective(vessel) - active = TRUE - host = user - user.clear_fullscreen("hive_mc") - user.overlay_fullscreen("hive_eyes", /obj/screen/fullscreen/hive_eyes) - revert_cast() - else - vessel.remove_status_effect(STATUS_EFFECT_BUGGED) - user.reset_perspective() - user.clear_fullscreen("hive_eyes") - var/obj/effect/proc_holder/spell/target_hive/hive_control/the_spell = locate(/obj/effect/proc_holder/spell/target_hive/hive_control) in user.mind.spell_list - if(the_spell && the_spell.active) - user.overlay_fullscreen("hive_mc", /obj/screen/fullscreen/hive_mc) - active = FALSE - limited = FALSE - revert_cast() - -/obj/effect/proc_holder/spell/target_hive/hive_see/process() - if(active && (!vessel || !is_hivemember(vessel) || QDELETED(vessel) || (limited && get_dist(vessel, host) > 42))) - to_chat(host, "Our vessel is one of us no more!") - host.reset_perspective() - host.clear_fullscreen("hive_eyes") - active = FALSE - limited = FALSE - if(!QDELETED(vessel)) - vessel.remove_status_effect(STATUS_EFFECT_BUGGED) - ..() - -/obj/effect/proc_holder/spell/target_hive/hive_see/choose_targets(mob/user = usr) - if(!active) - ..() - else - perform(,user) - -/obj/effect/proc_holder/spell/targeted/hive_shock - name = "Sensory Shock" - desc = "After a short charging time, we overload the mind of one of our vessels with psionic energy, temporarilly disrupting their sight, hearing, and speech." - charge_max = 600 - panel = "Hivemind Abilities" - invocation_type = "none" - clothes_req = 0 - human_req = 1 - action_icon = 'icons/mob/actions/actions_hive.dmi' - action_background_icon_state = "bg_hive" - action_icon_state = "shock" - antimagic_allowed = TRUE - range = 7 - selection_type = "range" - -/obj/effect/proc_holder/spell/targeted/hive_shock/cast(list/targets, mob/user = usr) - var/datum/antagonist/hivemind/hive = user.mind.has_antag_datum(/datum/antagonist/hivemind) - if(!hive || !hive.hivemembers) - to_chat(user, "This is a bug. Error:HIVE1") - return - var/mob/living/carbon/target = targets[1] - to_chat(user, "We increase the psionic bandwidth between ourself and the target!") - var/power = 1 - if(target.anti_magic_check(FALSE, FALSE, TRUE)) - power *= 0.5 - if(!hive.is_carbon_member(target)) - power *= 0.5 - target.blind_eyes(4*power) - target.blur_eyes(30*power) - target.minimumDeafTicks(15*power) //equivalent to 30s deafness max - target.Jitter(10*power) - target.silent += 10*power - target.stuttering += 30*power - target.Knockdown(1*power) - target.stop_pulling() - to_chat(target, "You feel your mind start to burn!") - -/obj/effect/proc_holder/spell/self/hive_scan - name = "Psychoreception" - desc = "We release a pulse to receive information on any enemies we have previously located via Network Invasion, as well as those currently tracking us." - panel = "Hivemind Abilities" - charge_max = 1800 - invocation_type = "none" - clothes_req = 0 - human_req = 1 - action_icon = 'icons/mob/actions/actions_hive.dmi' - action_background_icon_state = "bg_hive" - action_icon_state = "scan" - antimagic_allowed = TRUE - -/obj/effect/proc_holder/spell/self/hive_scan/cast(mob/living/user = usr) - var/datum/antagonist/hivemind/hive = user.mind.has_antag_datum(/datum/antagonist/hivemind) - if(!hive) - to_chat(user, "This is a bug. Error:HIVE1") - return - var/message - var/distance - - for(var/datum/status_effect/hive_track/track in user.status_effects) - var/mob/living/L = track.tracked_by - if(!L) - continue - if(!do_after(user,5,0,user)) - to_chat(user, "Our concentration has been broken!") - break - distance = get_dist(user, L) - message = "[(L.is_real_hivehost()) ? "Someone": "A hivemind host"] tracking us" - if(user.z != L.z || L.stat == DEAD) - message += " could not be found." - else - var/multiplier = L.anti_magic_check(FALSE, FALSE, TRUE) ? rand(0.6, 1.4) : 1 - switch(distance*multiplier) - if(0 to 2) - message += " is right next to us!" - if(2 to 14) - message += " is nearby." - if(14 to 28) - message += " isn't too far away." - if(28 to INFINITY) - message += " is quite far away." - to_chat(user, "[message]") - for(var/datum/antagonist/hivemind/enemy in hive.individual_track_bonus) - if(!do_after(user,5,0,user)) - to_chat(user, "Our concentration has been broken!") - break - var/mob/living/carbon/C = enemy.owner?.current - if(!C) - continue - var/multiplier = C.anti_magic_check(FALSE, FALSE, TRUE) ? rand(0.6, 1.4) : 1 - var/mob/living/real_enemy = C.get_real_hivehost() - distance = get_dist(user, real_enemy) - message = "A host that we can track for [(hive.individual_track_bonus[enemy])/10] extra seconds" - if(user.z != real_enemy.z || real_enemy.stat == DEAD) - message += " could not be found." - else - multiplier = real_enemy.anti_magic_check(FALSE, FALSE, TRUE) ? rand(0.6, 1.4) : 1 - switch(distance*multiplier) - if(0 to 2) - message += " is right next to us!" - if(2 to 14) - if(enemy.get_threat_multiplier() >= 0.85 && distance <= 7) - message += " is in this very room!" - else - message += " is nearby." - if(14 to 28) - message += " isn't too far away." - if(28 to INFINITY) - message += " is quite far away." - to_chat(user, "[message]") - -/obj/effect/proc_holder/spell/self/hive_drain - name = "Repair Protocol" - desc = "Our many vessels sacrifice a small portion of their mind's vitality to cure us of our physical and mental ailments." - panel = "Hivemind Abilities" - charge_max = 600 - clothes_req = 0 - invocation_type = "none" - action_icon = 'icons/mob/actions/actions_hive.dmi' - action_background_icon_state = "bg_hive" - action_icon_state = "drain" - human_req = 1 - antimagic_allowed = TRUE - -/obj/effect/proc_holder/spell/self/hive_drain/cast(mob/living/carbon/human/user) - var/datum/antagonist/hivemind/hive = user.mind.has_antag_datum(/datum/antagonist/hivemind) - if(!hive || !hive.hivemembers) - return - var/iterations = 0 - var/list/carbon_members = hive.get_carbon_members() - if(!carbon_members.len) - return - if(!user.getBruteLoss() && !user.getFireLoss() && !user.getCloneLoss() && !user.getBrainLoss() && !user.getStaminaLoss()) - to_chat(user, "We cannot heal ourselves any more with this power!") - revert_cast() - to_chat(user, "We begin siphoning power from our many vessels!") - while(iterations < 7) - var/mob/living/carbon/target = pick(carbon_members) - if(!do_after(user,10,0,user)) - to_chat(user, "Our concentration has been broken!") - break - if(!target) - to_chat(user, "We have run out of vessels to drain.") - break - var/regen = target.anti_magic_check(FALSE, FALSE, TRUE) ? 5 : 10 - target.adjustBrainLoss(regen/2) - if(user.getBruteLoss() > user.getFireLoss()) - user.heal_ordered_damage(regen, list(CLONE, BRUTE, BURN, STAMINA)) - else - user.heal_ordered_damage(regen, list(CLONE, BURN, BRUTE, STAMINA)) - if(!user.getBruteLoss() && !user.getFireLoss() && !user.getCloneLoss() && !user.getStaminaLoss()) //If we don't have any of these, stop looping - to_chat(user, "We finish our healing") - break - iterations++ - user.setBrainLoss(0) - - -/mob/living/passenger - name = "mind control victim" - real_name = "unknown conscience" - -/mob/living/passenger/UnarmedAttack(atom/A) - return - -/mob/living/passenger/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null) - to_chat(src, "You find yourself unable to speak, you aren't in control of your body!") - return FALSE - -/mob/living/passenger/emote(act, m_type = null, message = null, intentional = FALSE) - to_chat(src, "You find yourself unable to emote, you aren't in control of your body!") - return - -/mob/living/passenger/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode) - return - -/obj/effect/proc_holder/spell/target_hive/hive_control - name = "Mind Control" - desc = "We assume direct control of one of our vessels, leaving our current body for up to a minute. It can be cancelled at any time by casting it again. Powers can be used via our vessel, although if it dies, the entire hivemind will come down with it. Our ability to sense psionic energy is completely nullified while using this power, and it will end immediately should we attempt to move too far from our starting point." - charge_max = 1200 - action_icon_state = "force" - active = FALSE - var/mob/living/carbon/human/original_body //The original hivemind host - var/mob/living/carbon/human/vessel - var/mob/living/passenger/backseat //Storage for the mind controlled vessel - var/turf/starting_spot - var/power = 600 - var/time_initialized = 0 - var/out_of_range = FALSE - var/restricted_range = FALSE - -/obj/effect/proc_holder/spell/target_hive/hive_control/proc/release_control() //If the spell is active, force everybody into their original bodies if they exist, ghost them otherwise, delete the backseat - if(!active) - return - active = FALSE - charge_counter = max((0.5-(world.time-time_initialized)/power)*charge_max, 0) //Partially refund the power based on how long it was used, up to a max of half the charge time - if(!QDELETED(vessel)) - vessel.clear_fullscreen("hive_mc") - if(vessel.mind) - if(QDELETED(original_body)) - vessel.ghostize(0) - else - vessel.mind.transfer_to(original_body, 1) - original_body.Sleeping(vessel.AmountSleeping()) // Mirrors any sleep or unconsciousness from the vessel - original_body.Unconscious(vessel.AmountUnconscious()) - - if(!QDELETED(backseat) && backseat.mind) - if(QDELETED(vessel)) - backseat.ghostize(0) - else - backseat.mind.transfer_to(vessel,1) - vessel.visible_message("[vessel] suddenly wakes up, as though [vessel.p_they()] [vessel.p_were()] under foreign control!") - vessel.Jitter(3) - message_admins("[ADMIN_LOOKUPFLW(vessel)] is no longer being controlled by [ADMIN_LOOKUPFLW(original_body)] (Hivemind Host).") - log_game("[key_name(vessel)] was released from Mind Control by [key_name(original_body)].") - - QDEL_NULL(backseat) - - if(original_body?.mind) - var/datum/antagonist/hivemind/hive = original_body.mind.has_antag_datum(/datum/antagonist/hivemind) - if(hive) - hive.threat_level += 1 - - restricted_range = FALSE - - -/obj/effect/proc_holder/spell/target_hive/hive_control/on_lose(mob/user) - release_control() - -/obj/effect/proc_holder/spell/target_hive/hive_control/cast(list/targets, mob/living/user = usr) - if(!active) - vessel = targets[1] - var/datum/antagonist/hivemind/hive = user.mind.has_antag_datum(/datum/antagonist/hivemind) - if(!hive) - to_chat(user, "This is a bug. Error:HIVE1") - return - original_body = user - vessel = targets[1] - to_chat(user, "We begin merging our mind with [vessel.name].") - var/timely = 50 - if(vessel.anti_magic_check(FALSE, FALSE, TRUE)) - timely = 100 - restricted_range = TRUE - if(!do_after(user, timely, FALSE, user)) - to_chat(user, "We fail to assume control of the target!") - revert_cast() - return - if(user.z != vessel.z || (restricted_range && get_dist(vessel, user) > 35)) - to_chat(user, "Our vessel is too far away to control!") - revert_cast() - return - for(var/datum/antagonist/hivemind/H in GLOB.antagonists) - if(H.owner == user.mind) - continue - if(H.owner == vessel.mind) - to_chat(user, "We have detected a foreign presence within this mind, it would be unwise to merge so intimately with it.") - revert_cast() - return - backseat = new /mob/living/passenger() - if(vessel && vessel.mind && backseat) - var/obj/effect/proc_holder/spell/target_hive/hive_see/the_spell = locate(/obj/effect/proc_holder/spell/target_hive/hive_see) in user.mind.spell_list - if(the_spell && the_spell.active) //Uncast Hive Sight just to make things easier when casting during mind control - the_spell.perform(,user) - message_admins("[ADMIN_LOOKUPFLW(vessel)] has been temporarily taken over by [ADMIN_LOOKUPFLW(user)] (Hivemind Host).") - log_game("[key_name(vessel)] was Mind Controlled by [key_name(user)].") - - deadchat_broadcast(" has just been mind controlled!", "[vessel]", vessel) - - original_body = user - backseat.loc = vessel - backseat.name = vessel.real_name - backseat.real_name = vessel.real_name - vessel.mind.transfer_to(backseat, 1) - user.mind.transfer_to(vessel, 1) - backseat.blind_eyes(power) - vessel.overlay_fullscreen("hive_mc", /obj/screen/fullscreen/hive_mc) - active = TRUE - out_of_range = FALSE - starting_spot = get_turf(vessel) - time_initialized = world.time - revert_cast() - to_chat(vessel, "We can sustain our control for a maximum of [round(power/10)] seconds.") - if(do_after(user,power,0,user,0)) - to_chat(vessel, "We cannot sustain the mind control any longer and release control!") - else - to_chat(vessel, "Our body has been disturbed, interrupting the mind control!") - release_control() - else - to_chat(usr, "We detect no neural activity in our vessel!") - revert_cast() - else - release_control() - -/obj/effect/proc_holder/spell/target_hive/hive_control/revert_cast() - . = ..() - restricted_range = FALSE - -/obj/effect/proc_holder/spell/target_hive/hive_control/process() - if(active) - if(QDELETED(vessel)) //If we've been gibbed or otherwise deleted, ghost both of them and kill the original - original_body.adjustBrainLoss(200) - release_control() - else if(!is_hivemember(backseat)) //If the vessel is no longer a hive member, return to original bodies - to_chat(vessel, "Our vessel is one of us no more!") - release_control() - else if(!QDELETED(original_body) && (!backseat.ckey || vessel.stat == DEAD)) //If the original body exists and the vessel is dead/ghosted, return both to body but not before killing the original - original_body.adjustBrainLoss(200) - to_chat(vessel.mind, "Our vessel is one of us no more!") - release_control() - else if(!QDELETED(original_body) && original_body.z != vessel.z) //Return to original bodies - release_control() - to_chat(original_body, "Our vessel is too far away to control!") - else if(QDELETED(original_body) || original_body.stat == DEAD) //Return vessel to its body, either return or ghost the original - to_chat(vessel, "Our body has been destroyed, the hive cannot survive without its host!") - release_control() - else - var/multiplier = restricted_range ? 0.5 : 1 - if(!out_of_range && get_dist(starting_spot, vessel) > 14*multiplier) - out_of_range = TRUE - flash_color(vessel, flash_color="#800080", flash_time=10) - to_chat(vessel, "Our vessel has been moved too far away from the initial point of control, we will be disconnected if we go much further!") - addtimer(CALLBACK(src, .proc/range_check, multiplier), 30) - else if(get_dist(starting_spot, vessel) > 21*multiplier) - release_control() - - ..() - -/obj/effect/proc_holder/spell/target_hive/hive_control/proc/range_check(multiplier = 1) - if(!active) - return - if(get_dist(starting_spot, vessel) > 14 * multiplier) - release_control() - out_of_range = FALSE - -/obj/effect/proc_holder/spell/target_hive/hive_control/choose_targets(mob/user = usr) - if(!active) - ..() - else - perform(,user) - -/obj/effect/proc_holder/spell/targeted/induce_panic - name = "Induce Panic" - desc = "We unleash a burst of psionic energy, inducing a debilitating fear in those around us and reducing their combat readiness. We can also briefly affect silicon-based life with this burst." - panel = "Hivemind Abilities" - charge_max = 600 - range = 7 - invocation_type = "none" - clothes_req = 0 - max_targets = 0 - antimagic_allowed = TRUE - action_icon = 'icons/mob/actions/actions_hive.dmi' - action_background_icon_state = "bg_hive" - action_icon_state = "panic" - -/obj/effect/proc_holder/spell/targeted/induce_panic/cast(list/targets, mob/living/user = usr) - var/datum/antagonist/hivemind/hive = user.mind.has_antag_datum(/datum/antagonist/hivemind) - if(!hive) - to_chat(user, "This is a bug. Error:HIVE1") - return - for(var/mob/living/carbon/human/target in targets) - if(target.stat == DEAD) - continue - target.Jitter(14) - target.apply_damage(35 + rand(0,15), STAMINA, target.get_bodypart(BODY_ZONE_HEAD)) - if(target.is_real_hivehost() || target.anti_magic_check(FALSE, FALSE, TRUE)) - continue - if(prob(20)) - var/text = pick(":h Help!!",":h Run!",":h They're here!",":h Get out!",":h Hide!",":h Kill them!",":h Cult!",":h Changeling!",":h Traitor!",":h Nuke ops!",":h Revolutionaries!",":h Wizard!",":h Zombies!",":h Ghosts!",":h AI rogue!",":h Borgs emagged!",":h Maint!!",":h Dying!!",":h AI lock down the borgs law 1!",":h I'm losing control of the situation!!") - target.say(text, forced = "panic") - var/effect = rand(1,4) - switch(effect) - if(1) - to_chat(target, "You panic and drop everything to the ground!") - target.drop_all_held_items() - if(2) - to_chat(target, "You panic and flail around!") - target.click_random_mob() - addtimer(CALLBACK(target, "click_random_mob"), 5) - addtimer(CALLBACK(target, "click_random_mob"), 10) - addtimer(CALLBACK(target, "click_random_mob"), 15) - addtimer(CALLBACK(target, "click_random_mob"), 20) - addtimer(CALLBACK(target, "Stun", 30), 25) - target.confused += 10 - if(3) - to_chat(target, "You freeze up in fear!") - target.Stun(70) - if(4) - to_chat(target, "You feel nauseous as dread washes over you!") - target.Dizzy(15) - target.apply_damage(30, STAMINA, target.get_bodypart(BODY_ZONE_HEAD)) - target.hallucination += 45 - - for(var/mob/living/silicon/target in targets) - target.Unconscious(50) - -/obj/effect/proc_holder/spell/targeted/pin - name = "Psychic Pin" - desc = "We send out a controlled pulse of psionic energy, pinning everyone in sight, and knocking out silicon-based lifeforms. This is weaker against enemy hiveminds." - panel = "Hivemind Abilities" - charge_max = 600 - range = 7 - invocation_type = "none" - clothes_req = 0 - max_targets = 0 - antimagic_allowed = TRUE - action_icon = 'icons/mob/actions/actions_hive.dmi' - action_background_icon_state = "bg_hive" - action_icon_state = "pin" - -/obj/effect/proc_holder/spell/targeted/pin/cast(list/targets, mob/living/user = usr) - if(!targets) - to_chat(user, "Nobody is in sight, it'd be a waste to do that now.") - revert_cast() - return - var/list/victims = list() - for(var/mob/living/target in targets) - if(target.stat == DEAD) - continue - if(target.is_real_hivehost() || (!iscarbon(target) && !issilicon(target))) - continue - victims += target - var/statustime = max(80,240/(1+round(victims.len/3))) - for(var/mob/living/carbon/victim in victims) - if(victim.is_real_hivehost()) - victim.Knockdown(statustime/4) - else - victim.Knockdown(statustime) - to_chat(victim, "A sudden force throws you to the ground!") - for(var/mob/living/silicon/victim in victims) - victim.Unconscious(statustime) - var/datum/antagonist/hivemind/hive = user.mind.has_antag_datum(/datum/antagonist/hivemind) - if(victims.len && hive) - hive.threat_level += 1 - -/obj/effect/proc_holder/spell/target_hive/nightmare - name = "Living nightmares" - desc = "The target's fears break out and attack them, obscuring their vision and clawing at them." - range = 7 - charge_max = 1800 - action_icon_state = "nightmare" - -/obj/effect/proc_holder/spell/target_hive/nightmare/cast(list/targets, mob/living/user = usr) - var/mob/living/carbon/target = targets[1] - if(!do_after(user,30,0,user)) - to_chat(user, "Our concentration has been broken!") - revert_cast() - return - to_chat(target, "You see dark smoke swirling around you!") - if(target.anti_magic_check(FALSE, FALSE, TRUE)) - to_chat(user, "We begin bruteforcing the tinfoil barriers of [target.name] and pulling out their nightmares.") - if(!do_after(user, 30, FALSE, user) || !(target in view(range))) - to_chat(user, "Our concentration has been broken!") - return - target.apply_status_effect(STATUS_EFFECT_HIVEMIND_CURSE, CURSE_SPAWNING | CURSE_BLINDING) - to_chat(user, "We have brought forth the targets nightmares!") - deadchat_broadcast(" is suffering corporial nightmares!", "[target]", target) - - var/datum/antagonist/hivemind/hive = user.mind.has_antag_datum(/datum/antagonist/hivemind) - if(hive) - hive.threat_level += 3 - -/obj/item/extendohand/hivemind - name = "Telekinetic hand" - desc = "Extends the reach of your unarmed combat. Drop to remove." - icon = 'icons/mob/actions/actions_hive.dmi' - icon_state = "hivehand" - item_state = "hivehand" - lefthand_file = 'icons/mob/inhands/misc/touchspell_lefthand.dmi' - righthand_file = 'icons/mob/inhands/misc/touchspell_righthand.dmi' - - reach = 3 - min_reach = -1 - item_flags = ABSTRACT | DROPDEL - -/obj/effect/proc_holder/spell/self/telekinetic_hand - name = "Telekinetic hand" - desc = "Makes a telekinetic hand to extend the reach of our unarmed combat. Drop to remove." - clothes_req = 0 - invocation_type = "none" - antimagic_allowed = TRUE - charge_max = 200 - panel = "Hivemind Abilities" - action_background_icon_state = "bg_hive" - action_icon = 'icons/mob/actions/actions_hive.dmi' - action_icon_state = "hivehand" - var/spell_item = /obj/item/extendohand/hivemind - -/obj/effect/proc_holder/spell/self/telekinetic_hand/cast(mob/user = usr) - if(user.get_active_held_item()==null) - var/obj/item/W = new spell_item - user.put_in_hands(W) - to_chat(user, "You make a telekinetic hand!") - else - to_chat(user,"You cannot make a telekinetic hand while holding something!") - revert_cast() - -/obj/effect/proc_holder/spell/targeted/hive_hack - name = "Network Invasion" - desc = "We probe the mind of an adjacent target and extract valuable information on any enemy hives they may belong to. Takes longer if the target is not in our hive or wearing tinfoil protection." - panel = "Hivemind Abilities" - charge_max = 600 - range = 1 - invocation_type = "none" - clothes_req = 0 - max_targets = 1 - action_icon = 'icons/mob/actions/actions_hive.dmi' - action_background_icon_state = "bg_hive" - action_icon_state = "hack" - antimagic_allowed = TRUE - -/obj/effect/proc_holder/spell/targeted/hive_hack/cast(list/targets, mob/living/user = usr) - var/datum/antagonist/hivemind/hive = user.mind.has_antag_datum(/datum/antagonist/hivemind) - if(!hive) - to_chat(user, "This is a bug. Error:HIVE1") - return - var/mob/living/carbon/target = targets[1] - var/in_hive = hive.is_carbon_member(target) - var/list/enemies = list() - - to_chat(user, "We begin probing [target.name]'s mind!") - if(do_after(user,100,0,target)) - var/foiled = target.anti_magic_check(FALSE, FALSE, TRUE) - if(!in_hive || foiled) - var/timely = !in_hive ? 200 : 100 - to_chat(user, "Their mind slowly opens up to us.") - if(!do_after(user,timely,FALSE,target)) - to_chat(user, "Our concentration has been broken!") - revert_cast() - return - for(var/datum/antagonist/hivemind/enemy in GLOB.antagonists) - var/datum/mind/M = enemy.owner - if(!M?.current) - continue - if(M.current == user) - continue - if(enemy.is_carbon_member(target)) - hive.add_track_bonus(enemy, TRACKER_BONUS_LARGE) - var/mob/living/real_enemy = (M.current.get_real_hivehost()) - enemies += real_enemy - enemy.remove_from_hive(target) - real_enemy.apply_status_effect(STATUS_EFFECT_HIVE_TRACKER, user, hive.get_track_bonus(enemy)) - if(M.current.is_real_hivehost()) //If they were using mind control, too bad - real_enemy.apply_status_effect(STATUS_EFFECT_HIVE_RADAR) - target.apply_status_effect(STATUS_EFFECT_HIVE_TRACKER, real_enemy, enemy.get_track_bonus(hive)) - to_chat(real_enemy, "We detect a surge of psionic energy from a far away vessel before they disappear from the hive. Whatever happened, there's a good chance they're after us now.") - - if(enemy.owner == M && target.is_real_hivehost()) - var/atom/throwtarget - throwtarget = get_edge_target_turf(src, get_dir(src, get_step_away(user, src))) - SEND_SOUND(user, sound(pick('sound/hallucinations/turn_around1.ogg','sound/hallucinations/turn_around2.ogg'),0,1,50)) - flash_color(user, flash_color="#800080", flash_time=10) - user.Paralyze(10) - user.throw_at(throwtarget, 5, 1,src) - to_chat(user, "A sudden surge of psionic energy rushes into your mind, only a Hive host could have such power!!") - return - if(enemies.len) - hive.track_bonus += TRACKER_BONUS_SMALL - to_chat(user, "In a moment of clarity, we see all. Another hive. Faces. Our nemesis. They have heard our call. They know we are coming.") - to_chat(user, "This vision has provided us insight on our very nature, improving our sensory abilities, particularly against the hives this vessel belonged to.") - user.apply_status_effect(STATUS_EFFECT_HIVE_RADAR) - else - to_chat(user, "We peer into the inner depths of their mind and see nothing, no enemies lurk inside this mind.") - else - to_chat(user, "Our concentration has been broken!") - revert_cast() - -/obj/effect/proc_holder/spell/targeted/hive_reclaim - name = "Reclaim" - desc = "Allows us to instantly syphon the psionic energy from an adjacent critically injured host, killing them immediately. If it succeeds, we will be able to advance our own powers a great deal." - panel = "Hivemind Abilities" - charge_max = 600 - range = 1 - max_targets = 0 - invocation_type = "none" - clothes_req = 0 - human_req = 1 - action_icon = 'icons/mob/actions/actions_hive.dmi' - action_background_icon_state = "bg_hive" - action_icon_state = "reclaim" - antimagic_allowed = TRUE - -/obj/effect/proc_holder/spell/targeted/hive_reclaim/cast(list/targets, mob/living/user = usr) - var/datum/antagonist/hivemind/hive = user.mind.has_antag_datum(/datum/antagonist/hivemind) - if(!hive) - to_chat(user, "This is a bug. Error:HIVE1") - return - var/found_target = FALSE - var/gibbed = FALSE - - for(var/mob/living/carbon/C in targets) - if(!is_hivehost(C)) - continue - if(C.InCritical() || (C.stat == DEAD && C.timeofdeath + 150 >= world.time) ) - C.gib() - hive.track_bonus += TRACKER_BONUS_LARGE - hive.size_mod += 5 - hive.threat_level += 1 - gibbed = TRUE - found_target = TRUE - else if(C.IsUnconscious()) - C.adjustOxyLoss(100) - found_target = TRUE - - if(!found_target) - revert_cast() - return - - flash_color(user, flash_color="#800080", flash_time=10) - if(gibbed) - to_chat(user,"We have reclaimed what gifts weaker minds were squandering and gain ever more insight on our psionic abilities.") - to_chat(user,"Thanks to this new knowledge, our sensory powers last a great deal longer.") - hive.check_powers() - -/obj/effect/proc_holder/spell/self/hive_wake - name = "Chaos Induction" - desc = "A one-use power, we awaken four random vessels within our hive and force them to do our bidding." - panel = "Hivemind Abilities" - charge_type = "charges" - charge_max = 1 - invocation_type = "none" - clothes_req = 0 - human_req = 1 - action_icon = 'icons/mob/actions/actions_hive.dmi' - action_background_icon_state = "bg_hive" - action_icon_state = "chaos" - antimagic_allowed = TRUE - -/obj/effect/proc_holder/spell/self/hive_wake/cast(mob/living/user = usr) - var/datum/antagonist/hivemind/hive = user.mind.has_antag_datum(/datum/antagonist/hivemind) - if(!hive) - to_chat(user, "This is a bug. Error:HIVE1") - return - if(!hive.hivemembers) - return - var/list/valid_targets = list() - for(var/datum/mind/M in hive.hivemembers) - var/mob/living/carbon/C = M.current - if(!C || is_hivehost(C) || C.is_wokevessel() || C.stat == DEAD || C.InCritical() || C.anti_magic_check(FALSE, FALSE, TRUE, 4)) - continue - valid_targets += C - - if(!valid_targets || valid_targets.len < 4) - to_chat(user, "We lack the vessels to use this power.") - revert_cast() - return - - var/objective = stripped_input(user, "What objective do you want to give to your vessels?", "Objective") - - if(!objective || !hive) - revert_cast() - return - - hive.threat_level += 6 - for(var/i = 0, i < 4, i++) - var/mob/living/carbon/C = pick_n_take(valid_targets) - C.hive_awaken(objective) - -/obj/effect/proc_holder/spell/self/hive_loyal - name = "Bruteforce" - desc = "Our ability to assimilate is boosted at the cost of, allowing us to crush the technology shielding the minds of savyy personnel and assimilate them. This power comes at a small price, and we will be immobilized for a few seconds after assimilation." - panel = "Hivemind Abilities" - charge_max = 600 - invocation_type = "none" - clothes_req = 0 - human_req = 1 - action_icon = 'icons/mob/actions/actions_hive.dmi' - action_background_icon_state = "bg_hive" - action_icon_state = "loyal" - antimagic_allowed = TRUE - -/obj/effect/proc_holder/spell/self/hive_loyal/cast(mob/living/user = usr) - var/datum/antagonist/hivemind/hive = user.mind.has_antag_datum(/datum/antagonist/hivemind) - if(!hive) - to_chat(user, "This is a bug. Error:HIVE1") - return - var/obj/effect/proc_holder/spell/target_hive/hive_add/the_spell = locate(/obj/effect/proc_holder/spell/target_hive/hive_add) in user.mind.spell_list - if(!the_spell) - to_chat(user, "This is a bug. Error:HIVE5") - return - the_spell.bruteforce = !active - to_chat(user, "We [active?"let our minds rest and cancel our crushing power.":"prepare to crush mindshielding technology!"]") - active = !active - if(active) - revert_cast() - -/obj/effect/proc_holder/spell/targeted/forcewall/hive - name = "Telekinetic Field" - desc = "Our psionic powers form a barrier around us in the phsyical world that only we can pass through." - panel = "Hivemind Abilities" - charge_max = 600 - clothes_req = 0 - human_req = 1 - invocation_type = "none" - action_icon = 'icons/mob/actions/actions_hive.dmi' - action_background_icon_state = "bg_hive" - action_icon_state = "forcewall" - range = -1 - include_user = 1 - antimagic_allowed = TRUE - wall_type = /obj/effect/forcefield/wizard/hive - var/wall_type_b = /obj/effect/forcefield/wizard/hive/invis - -/obj/effect/proc_holder/spell/targeted/forcewall/hive/cast(list/targets,mob/user = usr) - new wall_type(get_turf(user),user) - for(var/dir in GLOB.alldirs) - new wall_type_b(get_step(user, dir),user) - var/datum/antagonist/hivemind/hive = user.mind.has_antag_datum(/datum/antagonist/hivemind) - if(hive) - hive.threat_level += 0.5 - -/obj/effect/forcefield/wizard/hive - name = "Telekinetic Field" - desc = "You think, therefore it is." - timeleft = 300 - pixel_x = -32 //Centres the 96x96 sprite - pixel_y = -32 - icon = 'icons/effects/96x96.dmi' - icon_state = "hive_shield" - layer = ABOVE_ALL_MOB_LAYER - mouse_opacity = MOUSE_OPACITY_TRANSPARENT - -/obj/effect/forcefield/wizard/hive/CanPass(atom/movable/mover, turf/target) - if(mover == wizard) - return TRUE - return FALSE - -/obj/effect/forcefield/wizard/hive/invis - icon = null - icon_state = null - pixel_x = 0 - pixel_y = 0 - invisibility = INVISIBILITY_MAXIMUM - -/obj/effect/proc_holder/spell/self/one_mind - name = "One Mind" - desc = "Our true power... finally within reach." - panel = "Hivemind Abilities" - charge_type = "charges" - charge_max = 1 - invocation_type = "none" - clothes_req = 0 - human_req = 1 - action_icon = 'icons/mob/actions/actions_hive.dmi' - action_background_icon_state = "bg_hive" - action_icon_state = "assim" - antimagic_allowed = TRUE - -/obj/effect/proc_holder/spell/self/one_mind/cast(mob/living/user = usr) - var/datum/antagonist/hivemind/hive = user.mind.has_antag_datum(/datum/antagonist/hivemind) - if(!hive) - to_chat(user, "This is a bug. Error:HIVE1") - return - var/mob/living/boss = user.get_real_hivehost() - var/datum/objective/protect/new_objective = new /datum/objective/protect - new_objective.target = user.mind - new_objective.explanation_text = "Ensure the One Mind survives under the leadership of [boss.real_name]." - var/datum/team/hivemind/one_mind_team = new /datum/team/hivemind(user.mind) - hive.active_one_mind = one_mind_team - one_mind_team.objectives += new_objective - for(var/datum/antagonist/hivevessel/vessel in GLOB.antagonists) - var/mob/living/carbon/C = vessel.owner?.current - if(C && hive.is_carbon_member(C)) - vessel.one_mind = one_mind_team - for(var/datum/antagonist/hivemind/enemy in GLOB.antagonists) - if(enemy.owner) - enemy.owner.RemoveSpell(new/obj/effect/proc_holder/spell/self/one_mind) - sound_to_playing_players('sound/effects/one_mind.ogg') - hive.glow = mutable_appearance('icons/effects/hivemind.dmi', "awoken", -BODY_BEHIND_LAYER) - addtimer(CALLBACK(user, /atom/proc/add_overlay, hive.glow), 150) - addtimer(CALLBACK(hive, /datum/antagonist/hivemind/proc/awaken), 150) - addtimer(CALLBACK(GLOBAL_PROC, /proc/send_to_playing_players, "THE ONE MIND RISES"), 150) - addtimer(CALLBACK(GLOBAL_PROC, /proc/sound_to_playing_players, 'sound/effects/magic.ogg'), 150) - for(var/datum/mind/M in hive.hivemembers) - var/mob/living/carbon/C = M.current - if(!C) - continue - if(is_hivehost(C)) - continue - if(C.stat == DEAD) - continue - C.Jitter(15) - C.Unconscious(150) - C.anti_magic_check(FALSE, FALSE, TRUE, 6) - to_chat(C, "Something's wrong...") - addtimer(CALLBACK(GLOBAL_PROC, /proc/to_chat, C, "...your memories are becoming fuzzy."), 45) - addtimer(CALLBACK(GLOBAL_PROC, /proc/to_chat, C, "You try to remember who you are..."), 90) - addtimer(CALLBACK(GLOBAL_PROC, /proc/to_chat, C, "There is no you..."), 110) - addtimer(CALLBACK(GLOBAL_PROC, /proc/to_chat, C, "...there is only us."), 130) - addtimer(CALLBACK(C, /mob/living/proc/hive_awaken, new_objective, one_mind_team), 150) - -/obj/effect/proc_holder/spell/self/hive_comms - name = "Hive Communication" - desc = "Now that we are free we may finally share our thoughts with our many bretheren." - panel = "Hivemind Abilities" - charge_max = 100 - invocation_type = "none" - clothes_req = 0 - human_req = 1 - action_icon = 'icons/mob/actions/actions_hive.dmi' - action_background_icon_state = "bg_hive" - action_icon_state = "comms" - antimagic_allowed = TRUE - -/obj/effect/proc_holder/spell/self/hive_comms/cast(mob/living/user = usr) - var/message = stripped_input(user, "What do you want to say?", "Hive Communication") - if(!message) - return - var/title = "One Mind" - var/span = "changeling" - if(user.mind && user.mind.has_antag_datum(/datum/antagonist/hivemind)) - span = "assimilator" - var/my_message = "[title] [findtextEx(user.name, user.real_name) ? user.name : "[user.real_name] (as [user.name])"]: [message]" - for(var/i in GLOB.player_list) - var/mob/M = i - if(is_hivehost(M) || is_hivemember(M)) - to_chat(M, my_message) - else if(M in GLOB.dead_mob_list) - var/link = FOLLOW_LINK(M, user) - to_chat(M, "[link] [my_message]") - - user.log_talk(message, LOG_SAY, tag="hive") diff --git a/config/game_options.txt b/config/game_options.txt index 0465e3ef209..409f3599da6 100644 --- a/config/game_options.txt +++ b/config/game_options.txt @@ -126,7 +126,6 @@ CONTINUOUS CLOCKWORK_CULT CONTINUOUS CHANGELING CONTINUOUS WIZARD #CONTINUOUS MONKEY -CONTINUOUS HIVEMIND ##Note: do not toggle continuous off for these modes, as they have no antagonists and would thus end immediately! diff --git a/icons/effects/96x96.dmi b/icons/effects/96x96.dmi index 3ec7701d095..ca60ea7ced2 100644 Binary files a/icons/effects/96x96.dmi and b/icons/effects/96x96.dmi differ diff --git a/icons/effects/hivemind.dmi b/icons/effects/hivemind.dmi deleted file mode 100644 index c78dc0f6453..00000000000 Binary files a/icons/effects/hivemind.dmi and /dev/null differ diff --git a/icons/mob/actions/actions_hive.dmi b/icons/mob/actions/actions_hive.dmi deleted file mode 100644 index 105b1ff4316..00000000000 Binary files a/icons/mob/actions/actions_hive.dmi and /dev/null differ diff --git a/sound/ambience/antag/assimilation.ogg b/sound/ambience/antag/assimilation.ogg deleted file mode 100644 index 81290237e6a..00000000000 Binary files a/sound/ambience/antag/assimilation.ogg and /dev/null differ diff --git a/sound/ambience/license.txt b/sound/ambience/license.txt index 60305c0a9f3..5fb0ece74d1 100644 --- a/sound/ambience/license.txt +++ b/sound/ambience/license.txt @@ -4,5 +4,3 @@ ambidet2.ogg is Night on the Docks, Piano by Kevin Macleod. It has been licensed It has been cropped for use ingame, and also fades in. aurora_caelus.ogg is Music for Manatees, by Kevin Macleod. It has been licensed under CC-BY 3.0 license. It has been cropped for use ingame, and also fades out. -antag/assimilation.ogg is Alien Spaceship UFO Sound effect, by Daniel Simon (http://soundbible.com/2213-Alien-Spaceship-UFO.html). It has been licensed under CC-BY 3.0 license. - It has been cropped for use ingame, and also fades out \ No newline at end of file diff --git a/sound/effects/license.txt b/sound/effects/license.txt index ac3058e5d6c..c928a9872f3 100644 --- a/sound/effects/license.txt +++ b/sound/effects/license.txt @@ -1,5 +1,2 @@ -one_mind.ogg is Mars Attacks Sounds, by Mike Koenig (http://soundbible.com/1047-Mars-Attacks.html). It has been licensed under CC-BY 3.0 license. - It is unaltered ingame - hit_punch.ogg and hit_kick.ogg are made by Taira Komori (https://taira-komori.jpn.org/freesounden.html) diff --git a/sound/effects/one_mind.ogg b/sound/effects/one_mind.ogg deleted file mode 100644 index 2c8bd214c57..00000000000 Binary files a/sound/effects/one_mind.ogg and /dev/null differ diff --git a/tgstation.dme b/tgstation.dme index 4a7f7743860..f96fd31305f 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -591,9 +591,6 @@ #include "code\game\gamemodes\devil\objectives.dm" #include "code\game\gamemodes\devil\devil agent\devil_agent.dm" #include "code\game\gamemodes\extended\extended.dm" -#include "code\game\gamemodes\hivemind\hivemind.dm" -#include "code\game\gamemodes\hivemind\objectives.dm" -#include "code\game\gamemodes\hivemind\radar.dm" #include "code\game\gamemodes\meteor\meteor.dm" #include "code\game\gamemodes\meteor\meteors.dm" #include "code\game\gamemodes\monkey\monkey.dm" @@ -1376,8 +1373,6 @@ #include "code\modules\antagonists\fugitive\hunter.dm" #include "code\modules\antagonists\greentext\greentext.dm" #include "code\modules\antagonists\highlander\highlander.dm" -#include "code\modules\antagonists\hivemind\hivemind.dm" -#include "code\modules\antagonists\hivemind\vessel.dm" #include "code\modules\antagonists\magic_servant\servant.dm" #include "code\modules\antagonists\monkey\monkey.dm" #include "code\modules\antagonists\morph\morph.dm" @@ -2724,7 +2719,6 @@ #include "code\modules\spells\spell_types\forcewall.dm" #include "code\modules\spells\spell_types\genetic.dm" #include "code\modules\spells\spell_types\godhand.dm" -#include "code\modules\spells\spell_types\hivemind.dm" #include "code\modules\spells\spell_types\infinite_guns.dm" #include "code\modules\spells\spell_types\inflict_handler.dm" #include "code\modules\spells\spell_types\knock.dm"