The PR that fixed Assimilation (#42156)

lots of commits
This commit is contained in:
Kierany9
2019-01-24 12:14:08 -05:00
committed by moo
parent 839cb25343
commit 8113154a22
8 changed files with 163 additions and 38 deletions
+4
View File
@@ -99,6 +99,10 @@
#define STATUS_EFFECT_INLOVE /datum/status_effect/in_love //Displays you as being in love with someone else, and makes hearts appear around them.
#define STATUS_EFFECT_HIVE_TRACKER /datum/status_effect/hive_track
#define STATUS_EFFECT_HIVE_RADAR /datum/status_effect/agent_pinpointer/hivemind
/////////////
// SLIME //
/////////////
+12 -1
View File
@@ -36,6 +36,17 @@
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/M)
if(!M)
return FALSE
@@ -91,4 +102,4 @@
/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."
the hivemind with ease, although they appear unable to affect mindshielded personnel."
+74
View File
@@ -0,0 +1,74 @@
#define HIVEMIND_RADAR_MIN_DISTANCE 7 //Very generous, as the targets are only tracked for a few minutes.
#define HIVEMIND_RADAR_MAX_DISTANCE 50
#define HIVEMIND_RADAR_PING_TIME 20 //2s 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?.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, "<span class='assimilator'>The psychic energies eminating from afar have died down... for now</span>")
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 = 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."
@@ -42,13 +42,17 @@
return FALSE
if(is_hivemember(target))
var/warning = ""
for(var/datum/antagonist/hivemind/hive in GLOB.antagonists)
if(hive.hivemembers.Find(target))
var/hive_name = hive.get_real_name()
if(hive_name)
warning += "[hive_name]. "
to_chat(target, "<span class='warning'>You hear supernatural wailing echo throughout your mind. If you listen closely you can hear... [warning]Are those... names?</span>")
var/mob/living/carbon/C = hive.owner.current.get_real_hivehost()
if(C)
C.apply_status_effect(STATUS_EFFECT_HIVE_TRACKER, target)
target.apply_status_effect(STATUS_EFFECT_HIVE_TRACKER, C)
if(C.mind) //If you were using mind control, too bad
C.apply_status_effect(STATUS_EFFECT_HIVE_RADAR)
to_chat(C, "<span class='userdanger'>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.</span>")
to_chat(target, "<span class='assimilator'>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!</span>")
target.apply_status_effect(STATUS_EFFECT_HIVE_RADAR)
remove_hivemember(target)
var/datum/antagonist/rev/rev = target.mind.has_antag_datum(/datum/antagonist/rev)
+31 -16
View File
@@ -7,6 +7,7 @@
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/static/datum/objective/hivemind/assimilate_common/common_assimilation_obj //Make it static since we want a common target for all the antags
var/list/upgrade_tiers = list(
@@ -34,6 +35,10 @@
if(hive_size != old_size)
check_powers()
/datum/antagonist/hivemind/proc/get_threat_multiplier()
calc_size()
return min(hive_size/50 + threat_level/20, 1)
/datum/antagonist/hivemind/proc/check_powers()
for(var/power in upgrade_tiers)
var/level = upgrade_tiers[power]
@@ -43,27 +48,13 @@
if(hive_size > 0)
to_chat(owner, "<span class='assimilator'>We have unlocked [the_spell.name].</span><span class='bold'> [the_spell.desc]</span>")
/datum/antagonist/hivemind/proc/get_real_name() //Gets the real name of the host, even if they're temporarily in another one
var/obj/effect/proc_holder/spell/target_hive/hive_control/the_spell = locate(/obj/effect/proc_holder/spell/target_hive/hive_control) in owner.spell_list
var/datum/mind/M = owner
if(M)
var/mob/living/L = owner.current
if(L)
if(the_spell && the_spell.active)
if(the_spell.original_body)
return the_spell.original_body.real_name
return L.real_name
return ""
/datum/antagonist/hivemind/proc/add_to_hive(var/mob/living/carbon/human/H)
var/warning = "<span class='userdanger'>We detect a surge of psionic energy from [H.real_name] before they disappear from the hive. An enemy host, or simply a stolen vessel?</span>"
var/user_warning = "<span class='userdanger'>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!</span>"
for(var/datum/antagonist/hivemind/enemy_hive in GLOB.antagonists)
if(H.mind == enemy_hive.owner)
if(is_real_hivehost(H))
var/eject_time = rand(1400,1600) //2.5 minutes +- 10 seconds
addtimer(CALLBACK(GLOBAL_PROC, /proc/to_chat, H, 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(GLOBAL_PROC, /proc/to_chat, owner, warning), eject_time) //As well as the host who just added them as soon as they're ejected
addtimer(CALLBACK(GLOBAL_PROC, /proc/remove_hivemember, H), eject_time)
addtimer(CALLBACK(src, .proc/handle_ejection, H), eject_time)
hivemembers |= H
calc_size()
@@ -71,6 +62,30 @@
hivemembers -= H
calc_size()
/datum/antagonist/hivemind/proc/handle_ejection(mob/living/carbon/human/H)
var/user_warning = "The enemy host has been ejected from our mind"
if(!H || !owner)
return
var/mob/living/carbon/human/H2 = owner.current
if(!H2)
return
var/mob/living/real_H = H.get_real_hivehost()
var/mob/living/real_H2 = H2.get_real_hivehost()
if(is_real_hivehost(H))
real_H2.apply_status_effect(STATUS_EFFECT_HIVE_TRACKER, real_H)
real_H.apply_status_effect(STATUS_EFFECT_HIVE_RADAR)
to_chat(real_H, "<span class='userdanger'>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.</span>")
if(is_real_hivehost(H2))
real_H.apply_status_effect(STATUS_EFFECT_HIVE_TRACKER, real_H2)
real_H2.apply_status_effect(STATUS_EFFECT_HIVE_RADAR)
user_warning += " and we've managed to pinpoint their location"
to_chat(H2, "<span class='userdanger'>[user_warning]!</span>")
/datum/antagonist/hivemind/proc/destroy_hive()
hivemembers = list()
calc_size()
@@ -46,6 +46,8 @@
var/minimum_range = PINPOINTER_MINIMUM_RANGE
var/range_fuzz_factor = PINPOINTER_EXTRA_RANDOM_RANGE
var/mob/scan_target = null
var/range_mid = 8
var/range_far = 16
/obj/screen/alert/status_effect/agent_pinpointer
name = "Internal Affairs Integrated Pinpointer"
@@ -66,13 +68,13 @@
linked_alert.icon_state = "pinondirect"
else
linked_alert.setDir(get_dir(here, there))
switch(get_dist(here, there))
if(1 to 8)
linked_alert.icon_state = "pinonclose"
if(9 to 16)
linked_alert.icon_state = "pinonmedium"
if(16 to INFINITY)
linked_alert.icon_state = "pinonfar"
var/dist = (get_dist(here, there))
if(dist >= 1 && dist <= range_mid)
linked_alert.icon_state = "pinonclose"
else if(dist > range_mid && dist <= range_far)
linked_alert.icon_state = "pinonmedium"
else if(dist > range_far)
linked_alert.icon_state = "pinonfar"
/datum/status_effect/agent_pinpointer/proc/scan_for_target()
scan_target = null
+23 -9
View File
@@ -248,7 +248,7 @@
/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 ten seconds, although a larger hive may be able to sustain it for up to two minutes. 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."
desc = "We assume direct control of one of our vessels, leaving our current body for up to ten seconds, although a larger hive may be able to sustain it for up to two minutes. 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."
charge_max = 600
action_icon_state = "force"
active = FALSE
@@ -285,6 +285,14 @@
QDEL_NULL(backseat)
if(original_body?.mind)
var/datum/antagonist/hivemind/hive = original_body.mind.has_antag_datum(/datum/antagonist/hivemind)
if(hive)
if((world.time-time_initialized) <= 300)
hive.threat_level += 0.5
else
hive.threat_level += 1
/obj/effect/proc_holder/spell/target_hive/hive_control/on_lose(mob/user)
release_control()
@@ -456,6 +464,9 @@
deadchat_broadcast("<span class='deadsay'><span class='name'>[target]</span> has suffered a mysterious heart attack!</span>", target)
else
to_chat(user, "<span class='warning'>We are unable to induce a heart attack!</span>")
var/datum/antagonist/hivemind/hive = user.mind.has_antag_datum(/datum/antagonist/hivemind)
if(hive)
hive.threat_level += 2
/obj/effect/proc_holder/spell/target_hive/hive_warp
name = "Distortion Field"
@@ -516,7 +527,6 @@
var/mob/living/carbon/human/target = targets[1]
var/in_hive = hive.hivemembers.Find(target)
var/list/enemies = list()
var/enemy_names = ""
to_chat(user, "<span class='notice'>We begin probing [target.name]'s mind!</span>")
if(do_after(user,100,0,target))
@@ -528,22 +538,26 @@
return
for(var/datum/antagonist/hivemind/enemy in GLOB.antagonists)
var/datum/mind/M = enemy.owner
if(!M || M.current == user)
if(M?.current == user)
continue
if(enemy.hivemembers.Find(target))
var/hive_name = enemy.get_real_name()
if(hive_name)
enemies += hive_name
var/mob/living/real_enemy = (M.current.get_real_hivehost())
enemies += real_enemy
enemy.remove_from_hive(target)
to_chat(M.current, "<span class='userdanger'>We detect a surge of psionic energy from [target.real_name] before they disappear from the hive. An enemy host, or simply a stolen vessel?</span>")
real_enemy.apply_status_effect(STATUS_EFFECT_HIVE_TRACKER, user)
if(is_real_hivehost(M.current)) //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)
to_chat(real_enemy, "<span class='userdanger'>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.</span>")
if(enemy.owner == target && is_real_hivehost(target))
user.Stun(70)
user.Jitter(14)
to_chat(user, "<span class='userdanger'>A sudden surge of psionic energy rushes into your mind, only a Hive host could have such power!!</span>")
return
if(enemies.len)
enemy_names = enemies.Join(". ")
to_chat(user, "<span class='userdanger'>In a moment of clarity, we see all. Another hive. Faces. Our nemesis. [enemy_names]. They are watching us. They know we are coming.</span>")
to_chat(user, "<span class='userdanger'>In a moment of clarity, we see all. Another hive. Faces. Our nemesis. They have heard our call. They know we are coming.</span>")
user.apply_status_effect(STATUS_EFFECT_HIVE_RADAR)
else
to_chat(user, "<span class='notice'>We peer into the inner depths of their mind and see nothing, no enemies lurk inside this mind.</span>")
else
+1
View File
@@ -548,6 +548,7 @@
#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"