Files
vgstation13/code/game/machinery/mind_machine.dm
adacovsk b8c95c9f0c Refactor tinfoil hat snowflake code (#32664)
* replace

* fixed

* Update powers.dm

* M_PSY_RESIST refactors

* argh

* Update powers.dm

* Update teleport.dm

* Update teleport.dm

* turn into proc

remove digital camo
turn everything into can_mind_interact

* seems to work

* Update misc_special.dm

* Update misc_special.dm

* Update mob.dm

* Update mob.dm

* Update mob.dm

* Update teleport.dm

* Update teleport.dm

* Update teleport.dm

* Update teleport.dm

* PSY to interference

* Update goon_powers.dm

* changing the name again

* telepathy blocked again
2022-06-03 20:49:12 -05:00

854 lines
29 KiB
Plaintext

/obj/machinery/mind_machine
name = "\improper Mind Machine"
icon = 'icons/obj/mind_machine.dmi'
density = 1
anchored = 1
use_power = 1
idle_power_usage = 50
active_power_usage = 2000
light_power_on = 1
machine_flags = SCREWTOGGLE | CROWDESTROY | EMAGGABLE | FIXED2WORK | WRENCHMOVE
#define MINDMACHINE_CURRENTLY_ACTIVE "Currently active: please wait"
#define MINDMACHINE_PODS_UNLOCKED "Pods already unlocked"
#define MINDMACHINE_PODS_LOCKED "Pods are locked"
#define MINDMACHINE_REQ_SCAN "Require scan"
#define MINDMACHINE_DELAY_CAUTION "Proceed with caution: supervisor advised"
#define MINDMACHINE_MISSING_OCC "Missing occupant"
#define MINDMACHINE_CONDUIT_CHARGE "Conduit requires charge"
#define MINDMACHINE_SHIELD_ERROR "Critical error, aborting"
#define MINDMACHINE_LIVING_REQUIRED "Living mind required"
#define MINDMACHINE_SHARD_REACTION "Warning: Unknown internal reaction"
#define MINDMACHINE_SCANNER_INSUFF "Scanners insufficient"
#define MINDMACHINE_UNKNOWN_INT "Unknown interruption"
#define MINDMACHINE_SUM_TOO_LOW "Sum intelligence too low"
#define MINDMACHINE_DELIVERY_ERROR "Error in mind delivery"
#define MINDMACHINE_MIND_DAMAGED "Mind sustained damage"
#define MINDMACHINE_SAFETY_CONSUMED "Safety consumed"
#define MINDMACHINE_TRANSPORT_ANOM "Mind transport anomaly"
#define MINDMACHINE_NOERROR "No errors"
#define MINDMACHINE_LOWER "Lower"
#define MINDMACHINE_HIGHER "Higher"
#define MINDMACHINE_SILICON "Artificial"
#define MINDMACHINE_SHIELDED "Shielded"
/obj/machinery/mind_machine/mind_machine_hub
name = "\improper Mind Machine Hub"
icon_state = "mind_hub"
desc = "The main hub of a complete mind machine setup. Placed between two mind pods and used to control and manage the transfer. Houses an experimental bluespace conduit which uses bluespace crystals for charge."
var/bluespaceConduit = 0 //Swap ammo
var/soulShardSafety = FALSE //Day ruin insurance
var/obj/machinery/mind_machine/mind_machine_pod/connectOne //All "variableNameOne" refer to information about the connectOne pod
var/obj/machinery/mind_machine/mind_machine_pod/connectTwo //Likewise for variableNameTwo for connectTwo
var/podsConnected = FALSE
var/mob/living/occupantOne = null
var/mob/living/occupantTwo = null
var/occupantStatOne = null
var/occupantStatTwo = null
var/mindTypeOne = null //Player mind, simple mob, silicon, etc
var/mindTypeTwo = null
var/lockedPods = FALSE
var/currentlySwapping = FALSE
var/swapProgress = 0
var/list/theFly = list() //If more than one creature enters a pod, ie: human with borer carrying a carp in his bag
var/occupantScan = FALSE
var/manipRating = 4 //Determines speed of swap/malfunction chance on delay swap
var/scanRatingOne = 6 //Determines if you can swap silicons
var/scanRatingTwo = 6
var/errorMessage = MINDMACHINE_NOERROR
var/beenSwapped = FALSE
var/malfSwap = FALSE //Triggers malfunction if true
var/list/illegalSwap = list() //Might break the game/remove the player from the round. If you get mechahitler in there you deserve your round, though
//////Parts and connection/////////
/obj/machinery/mind_machine/mind_machine_hub/New()
..()
illegalSwap = boss_mobs + blacklisted_mobs - list(/mob/living/simple_animal/hostile/mechahitler,
/mob/living/simple_animal/hostile/alien/queen/large,
/mob/living/simple_animal/hostile/retaliate/cockatrice,
/mob/living/simple_animal/hostile/asteroid/goliath/david/dave,
/mob/living/simple_animal/hostile/bear/spare,
/mob/living/simple_animal/hostile/asteroid/rockernaut/boss,
/mob/living/simple_animal/hostile/mining_drone
)
component_parts = newlist(
/obj/item/weapon/circuitboard/mind_machine_hub,
/obj/item/weapon/stock_parts/console_screen,
/obj/item/weapon/stock_parts/manipulator/nano,
/obj/item/weapon/stock_parts/manipulator/nano,
/obj/item/weapon/stock_parts/subspace/analyzer,
/obj/item/weapon/stock_parts/subspace/filter,
/obj/item/weapon/stock_parts/subspace/amplifier
)
RefreshParts()
/obj/machinery/mind_machine/mind_machine_hub/RefreshParts()
var/manipCount = 0
for(var/obj/item/weapon/stock_parts/SP in component_parts)
if(istype(SP, /obj/item/weapon/stock_parts/manipulator))
manipCount += SP.rating
manipRating = manipCount
/obj/machinery/mind_machine/mind_machine_hub/proc/findConnections() //Finds and links the hub with the pods on either side
connectOne = findConnectOne()
if(connectOne)
connectOne.connectedHub = src
connectOne.podNumber = 1
connectTwo = findConnectTwo()
if(connectTwo)
connectTwo.connectedHub = src
connectTwo.podNumber = 2
if ((connectOne) && (connectTwo))
podsConnected = TRUE
connectOne.RefreshParts()
connectTwo.RefreshParts()
/obj/machinery/mind_machine/mind_machine_hub/proc/findConnectOne()
for(var/obj/machinery/mind_machine/mind_machine_pod/CO in orange(1,src))
if(CO != connectTwo && CO.anchored)
return CO
/obj/machinery/mind_machine/mind_machine_hub/proc/findConnectTwo()
for(var/obj/machinery/mind_machine/mind_machine_pod/CT in orange(1,src))
if(CT != connectOne && CT.anchored)
return CT
/obj/machinery/mind_machine/mind_machine_hub/Destroy()
if(connectOne)
connectOne.connectedHub = null
connectOne.podNumber = 0
connectOne = null
if(connectTwo)
connectTwo.connectedHub = null
connectTwo.podNumber = 0
connectTwo = null
. = ..()
/obj/machinery/mind_machine/mind_machine_hub/attackby(var/obj/item/A, var/mob/user)
..()
if(istype(A, /obj/item/bluespace_crystal))
var/obj/item/bluespace_crystal/B = A
if(user.drop_item(B, src))
bluespaceConduit += B.blueChargeValue
B.playtoolsound(src, 50)
to_chat(user, "<span class='notice'>[istype(B, /obj/item/bluespace_crystal/flawless) ? "The bluespace conduit flashes violently before calming to a glow!" : "\The [B.name] is assimilated into the conduit!"]</span>")
qdel(B)
nanomanager.update_uis(src)
return
if(istype(A, /obj/item/soulstone))
if(soulShardSafety != FALSE)
to_chat(user, "<span class='notice'>That slot is already full!</span>")
return
if(A.contents.len)
to_chat(user, "<span class='notice'>The stone must be empty to function properly.</span>") //prevents deleting players in stones
return
if(user.drop_item(A, src))
playsound(src,'sound/effects/bonebreak4.ogg', 25, 1)
to_chat(user, "<span class='notice'>The stone is pulled into the machine. You can hear crunching and a quiet sizzle from inside.</span>")
qdel(A)
soulShardSafety = TRUE
nanomanager.update_uis(src)
/obj/machinery/mind_machine/mind_machine_hub/attack_hand(mob/user)
if(!podsConnected || !connectOne || !connectTwo)
resetConnections(user)
if(!currentlySwapping)
if(!connectOne.Adjacent(src) || !connectTwo.Adjacent(src))
resetConnections(user)
if(!podsConnected)
to_chat(user, "<span class='notice'>Pod connection error.</span>")
return //No UI without pods
ui_interact(user)
/obj/machinery/mind_machine/mind_machine_hub/proc/resetConnections(mob/user)
to_chat(user, "<span class='notice'>Establishing pod connections.</span>")
podsConnected = FALSE
connectOne = FALSE
connectTwo = FALSE
findConnections()
//////UI stuff/////////////
/obj/machinery/mind_machine/mind_machine_hub/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = NANOUI_FOCUS)
if(errorMessage != MINDMACHINE_NOERROR)
spawn(5 SECONDS)
errorMessage = MINDMACHINE_NOERROR
var/list/data = list(
"occupantScan" = occupantScan,
"lockedPods" = lockedPods,
"bluespaceConduit" = bluespaceConduit,
"soulShardSafety" = soulShardSafety,
"manipRating" = manipRating,
"swapProgress" = swapProgress,
"errorMessage" = errorMessage
)
var/occData[0]
if(occupantScan)
occData["nameOne"] = occupantOne.name
occData["nameTwo"] = occupantTwo.name
occData["statOne"] = occupantStatOne
occData["statTwo"] = occupantStatTwo
occData["mindTypeOne"] = mindTypeOne
occData["mindTypeTwo"] = mindTypeTwo
data["occData"] = occData;
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
if(!ui)
ui = new(user, src, ui_key, "mind_machine.tmpl", "Mind Machine", 350,500)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
/obj/machinery/mind_machine/mind_machine_hub/Topic(href, href_list)
if(..())
return
if(!connectOne.Adjacent(src) || !connectTwo.Adjacent(src) || !connectOne.anchored || !connectTwo.anchored)
return
if(podsConnected)
if(href_list["scan_start"])
if(!currentlySwapping)
playsound(src, 'sound/machines/twobeep.ogg', 35, 1)
scanOccupants()
return TRUE
else
errorMessage = MINDMACHINE_CURRENTLY_ACTIVE
return TRUE
if(href_list["unlock_pods"])
if(((!connectOne.contents.len) || (!connectTwo.contents.len)) && (currentlySwapping))
unlockPods() //Safeguard against the pod getting trapped in infinite scan
return TRUE
if(!lockedPods)
errorMessage = MINDMACHINE_PODS_UNLOCKED
return TRUE
if(currentlySwapping)
errorMessage = MINDMACHINE_CURRENTLY_ACTIVE
return TRUE
else
unlockPods()
return TRUE
if(href_list["eject_pods"])
if((!currentlySwapping) && (!lockedPods))
playsound(src, 'sound/machines/twobeep.ogg', 35, 1)
ejectPods()
return TRUE
if(lockedPods == TRUE)
errorMessage = MINDMACHINE_PODS_LOCKED
return TRUE
if(href_list["mind_swap"])
if((occupantScan) && (!currentlySwapping))
log_admin("[key_name(usr)] mind swap at [formatJumpTo(get_turf(usr))]")
playsound(src, 'sound/machines/twobeep.ogg', 35, 1)
swapOccupants()
return TRUE
if(!occupantScan)
errorMessage = MINDMACHINE_REQ_SCAN
return TRUE
if(currentlySwapping)
errorMessage = MINDMACHINE_CURRENTLY_ACTIVE
return TRUE
if(href_list["delay_swap"])
if(!currentlySwapping)
log_admin("[key_name(usr)] delayed mind swap at [formatJumpTo(get_turf(usr))]")
currentlySwapping = TRUE
playsound(src, 'sound/machines/twobeep.ogg', 35, 1)
delayedSwap()
return TRUE
//////Scan and Swap, other UI procs//////////////
/obj/machinery/mind_machine/mind_machine_hub/proc/unlockPods()
occupantScan = FALSE
mindTypeOne = "None"
mindTypeTwo = "None"
connectOne.icon_state = "mind_pod_open"
connectTwo.icon_state = "mind_pod_open"
playsound(connectTwo, 'sound/machines/door_unbolt.ogg', 35, 1)
playsound(connectOne, 'sound/machines/door_unbolt.ogg', 35, 1)
if(!beenSwapped)
flick("mind_pod_opening", connectOne)
flick("mind_pod_opening", connectTwo)
else
flick("mind_pod_thefly", connectOne)
flick("mind_pod_thefly", connectTwo)
beenSwapped = FALSE
lockedPods = FALSE
/obj/machinery/mind_machine/mind_machine_hub/proc/ejectPods()
connectOne.go_out()
connectTwo.go_out()
/obj/machinery/mind_machine/mind_machine_hub/proc/delayedSwap()
if(!occupantScan)
errorMessage = MINDMACHINE_DELAY_CAUTION
nanomanager.update_uis(src)
sleep(5 SECONDS)
if(gcDestroyed)
return
currentlySwapping = FALSE
if(occupantOne && occupantTwo)
scanOccupants()
if(prob(8-manipRating)) //A tiny bit risky with no upgrades, 0 risk with full xenoarch manipulators.
malfSwap = TRUE
swapOccupants()
unlockPods()
else
errorMessage = MINDMACHINE_MISSING_OCC
/obj/machinery/mind_machine/mind_machine_hub/proc/scanOccupants()
if((!locate(occupantOne,connectOne.contents)) || (!locate(occupantTwo, connectTwo.contents)))
errorMessage = MINDMACHINE_MISSING_OCC
return
currentlySwapping = TRUE
lockedPods = TRUE
if(!occupantScan && !beenSwapped)
playsound(connectOne, 'sound/machines/poddoor.ogg', 55, 1)
playsound(connectTwo, 'sound/machines/poddoor.ogg', 55, 1)
flick("mind_pod_closing",connectOne)
connectOne.icon_state = "mind_pod_closed"
flick("mind_pod_closing",connectTwo)
connectTwo.icon_state = "mind_pod_closed"
sleep(2 SECONDS)
if(gcDestroyed)
return
if(!locate(occupantOne,connectOne.contents) || !locate(occupantTwo, connectTwo.contents) || !connectOne || !connectTwo)
errorMessage = MINDMACHINE_MISSING_OCC
currentlySwapping = FALSE
occupantOne = null
occupantTwo = null
return
occupantScan = TRUE
playsound(connectOne, 'sound/effects/sparks4.ogg', 80, 1)
playsound(connectTwo, 'sound/effects/sparks4.ogg', 80, 1)
scanPod(occupantOne)
scanPod(occupantTwo)
currentlySwapping = FALSE
/obj/machinery/mind_machine/mind_machine_hub/proc/scanPod(var/mob/living/S)
var/MT
var/OS
switch(S.stat)
if(CONSCIOUS)
OS = "Alive"
if(UNCONSCIOUS)
OS = "Unconscious"
if(DEAD)
OS = "Dead"
if(!S.mind)
MT = MINDMACHINE_LOWER//Simple mob
if(S.mind)
if(isrobot(S))
MT = MINDMACHINE_SILICON //Silicon player, obviously
else
MT = MINDMACHINE_HIGHER //Player controlled
if(isvampire(S) || isanycultist(S) || ischangeling(S) || ismalf(S))
MT = MINDMACHINE_SHIELDED //Mostly to fix spell bugs but also tinfoil
if(is_type_in_list(S, illegalSwap) || is_type_in_list(S, illegalSwap))
MT = MINDMACHINE_SHIELDED
if((ishigherbeing(S)) || (ismonkey(S)))
if(!can_mind_interact(S.mind))
MT = MINDMACHINE_SHIELDED
if(S == occupantOne)
mindTypeOne = MT
occupantStatOne = OS
if(S == occupantTwo)
mindTypeTwo = MT
occupantStatTwo = OS
/obj/machinery/mind_machine/mind_machine_hub/proc/swapOccupants(var/mob/living/M)
if(!occupantScan || !lockedPods)
return
if(!locate(occupantOne,connectOne.contents) || (!locate(occupantTwo, connectTwo.contents)))
errorMessage = MINDMACHINE_MISSING_OCC //sanity and wizards exist
occupantOne = null
occupantTwo = null
unlockPods()
return
if(bluespaceConduit <= 0)
errorMessage = MINDMACHINE_CONDUIT_CHARGE
return
if(mindTypeOne == MINDMACHINE_SHIELDED || mindTypeTwo == MINDMACHINE_SHIELDED)
errorMessage = MINDMACHINE_SHIELD_ERROR
spark(src)
spark(connectOne)
spark(connectTwo)
unlockPods()
return
if(occupantStatOne == "Dead" || occupantStatTwo == "Dead") //Being able to swap if they die between scan and swap is intentional
if(!soulShardSafety) //Secrets
errorMessage = MINDMACHINE_LIVING_REQUIRED
return
soulShardSafety = FALSE
errorMessage = MINDMACHINE_SHARD_REACTION
if(isobserver(occupantOne.mind) || isobserver(occupantTwo.mind)) //Probably safest
return
currentlySwapping = TRUE
icon_state = "mind_hub_active"
connectOne.icon_state = "mind_pod_active"
connectTwo.icon_state = "mind_pod_active"
flyTally(occupantOne)
flyTally(occupantTwo)
for(var/prog in 1 to 40/manipRating) //Counts up 5 to 10 seconds, checks if we lost power each time and ruins your day if so. Otherwise just for UI progress bar
if(stat & (FORCEDISABLE|NOPOWER))
malfSwap = TRUE
if(!connectOne.Adjacent(src) || !connectTwo.Adjacent(src))
malfSwap = TRUE
sleep(1 SECONDS)
if(gcDestroyed)
return
if(!locate(occupantOne,connectOne.contents) || !locate(occupantTwo, connectTwo.contents) || !connectOne || !connectTwo)
errorMessage = MINDMACHINE_MISSING_OCC
swapProgress = 0
currentlySwapping = FALSE
occupantOne = null
occupantTwo = null
return
swapProgress += 1
nanomanager.update_uis(src)
log_admin("Mind machine swap: [occupantOne] and [occupantTwo] at [formatJumpTo(get_turf(src))]")
if(malfSwap) ///////////Swaps begin///////
malfunction()
return
if(mindTypeOne == MINDMACHINE_LOWER && mindTypeTwo == MINDMACHINE_LOWER)
lowerSwap()
return
if(theFly.len > 0)
theFlySwap()
return
if(mindTypeOne == MINDMACHINE_HIGHER && mindTypeTwo == MINDMACHINE_HIGHER)
higherSwap()
return
if(mindTypeOne ==MINDMACHINE_HIGHER && mindTypeTwo == MINDMACHINE_LOWER || mindTypeOne == MINDMACHINE_LOWER && mindTypeTwo == MINDMACHINE_HIGHER)
animorphsSwap()
return
if(mindTypeOne == MINDMACHINE_SILICON && scanRatingOne <7 || mindTypeTwo == MINDMACHINE_SILICON && scanRatingTwo <7)
errorMessage = MINDMACHINE_SCANNER_INSUFF
swapProgress = 0
currentlySwapping = FALSE
iconReset()
return
if(mindTypeOne == MINDMACHINE_SILICON && mindTypeTwo == MINDMACHINE_SILICON)
higherSwap() //Silicon swaps, checks if their pod is upgraded enough then performs normal swap
return
if(mindTypeOne == MINDMACHINE_SILICON && mindTypeTwo != MINDMACHINE_SILICON)
if(mindTypeTwo == MINDMACHINE_LOWER)
animorphsSwap()
return
if(mindTypeTwo == MINDMACHINE_HIGHER && theFly.len == 0)
higherSwap()
return
if(mindTypeTwo == MINDMACHINE_SILICON && mindTypeOne != MINDMACHINE_SILICON)
if(mindTypeOne == MINDMACHINE_LOWER)
animorphsSwap()
return
if(mindTypeOne == MINDMACHINE_HIGHER && !theFly.len)
higherSwap()
return
else
errorMessage = MINDMACHINE_UNKNOWN_INT
currentlySwapping = FALSE
swapProgress = 0
unlockPods()
/obj/machinery/mind_machine/mind_machine_hub/proc/flyTally(var/mob/living/M)
for(var/obj/item/weapon/holder/i in get_contents_in_object(M)) //Carp in pack? Outta luck, Jack
theFly += i
var/list/borers = M.get_brain_worms()
for(var/mob/living/simple_animal/borer/B in borers) //borers in the body are counted
theFly += B
/obj/machinery/mind_machine/mind_machine_hub/emp_act(severity)
..()
if(currentlySwapping)
malfSwap = TRUE
/obj/machinery/mind_machine/mind_machine_hub/emag_act()
if(currentlySwapping)
spark(src)
malfSwap = TRUE
//Procs for the mind swap//////////
/obj/machinery/mind_machine/mind_machine_hub/proc/lowerSwap(var/mob/living/LO, var/mob/living/LT)
LO = occupantOne
LT = occupantTwo
if(isanimal(LO) && isanimal(LT))
var/mob/living/simple_animal/SO = LO
var/mob/living/simple_animal/ST = LT
var/occOneFaction = SO.faction
var/occTwoFaction = ST.faction
SO.faction = occTwoFaction //Make friendly spiders and angry corgis
ST.faction = occOneFaction
var/occOneSpeakChance = SO.speak_chance
var/occTwoSpeakChance = ST.speak_chance
SO.speak_chance = occTwoSpeakChance
ST.speak_chance = occOneSpeakChance
var/occOneName = SO.name
var/occTwoName = ST.name
SO.name = occTwoName
ST.name = occOneName
var/list/occOneSpeak = list()
var/list/occTwoSpeak = list()
for(var/V in SO.speak)
occOneSpeak += V
SO.speak -= V
for(var/V in ST.speak)
occTwoSpeak += V
ST.speak -= V
for(var/V in occTwoSpeak)
SO.speak += V
for(var/V in occOneSpeak)
ST.speak += V
var/occOnePet = ST.is_pet
var/occTwoPet = SO.is_pet
SO.is_pet = occTwoPet
ST.is_pet = occOnePet
bluespaceConduit -= 1
else
errorMessage = MINDMACHINE_SUM_TOO_LOW //There's just nothing to swap for monkeymen
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 1)
mainReset()
/obj/machinery/mind_machine/mind_machine_hub/proc/higherSwap()
var/mob/living/HO = occupantOne
var/mob/living/HT = occupantTwo
if(HO.mind.special_verbs.len) //Swapping players, stolen from mind transfer
for(var/V in HO.mind.special_verbs)
HO.verbs -= V
if(HT.mind.special_verbs.len)
for(var/V in HT.mind.special_verbs)
HT.verbs -= V //Simple animals can't have special verbs so we just remove them without re-adding. Admins fear the machine.
var/list/HO_spells = HO.spell_list.Copy()
var/list/HT_spells = HT.spell_list.Copy()
for(var/spell/S in HO.spell_list)
HO.remove_spell(S)
for(var/spell/S in HT.spell_list)
HT.remove_spell(S)
var/mob/living/dummy = new(src)
HO.mind.transfer_to(dummy)
HT.mind.transfer_to(HO)
dummy.mind.transfer_to(HT)
qdel(dummy)
for(var/spell/S in HO_spells)
HT.add_spell(S)
for(var/spell/S in HT_spells)
HO.add_spell(S)
HO.confused += 8
HO.dizziness += 8
HT.confused += 8
HT.dizziness += 8
bluespaceConduit -= 1
mainReset()
/obj/machinery/mind_machine/mind_machine_hub/proc/animorphsSwap()
var/mob/animorph = null //Our player
var/mob/simpleMob = null
var/mob/living/MO = occupantOne
var/mob/living/MT = occupantTwo
if(MO.mind)
animorph = MO
simpleMob = MT
if(MT.mind)
animorph = MT
simpleMob = MO
if(animorph.mind.special_verbs.len)
for(var/V in animorph.mind.special_verbs)
animorph.verbs -= V
var/list/animorph_spells = animorph.spell_list.Copy()
for(var/spell/S in animorph.spell_list)
animorph.remove_spell(S)
animorph.mind.transfer_to(simpleMob)
for(var/spell/S in animorph_spells)
animorph.add_spell(S)
bluespaceConduit -= 1
mainReset()
/obj/machinery/mind_machine/mind_machine_hub/proc/malfunction()
malfSwap = FALSE
if(!soulShardSafety) //If there's no safety and it's emagged or an EMP goes off mid-scan, throws minds into a mindless mob within 50 tiles
malfSwap(occupantOne, mindTypeOne)
malfSwap(occupantTwo, mindTypeTwo)
beenSwapped = TRUE
else
soulShardSafety = FALSE
errorMessage = MINDMACHINE_SAFETY_CONSUMED
bluespaceConduit -= 1
scanSwapReset()
iconReset()
swapProgress = 0
/obj/machinery/mind_machine/mind_machine_hub/proc/malfSwap(var/mob/living/M, var/MT)
if(MT == MINDMACHINE_HIGHER || MT == MINDMACHINE_SILICON)
var/list/woopsMobs = list()
var/mob/woopsTarget = null
for(var/mob/living/R in mob_list)
if((!R.mind) && (R.stat != 2) && (get_dist(src, R) < 50) && (connectOne.z == R.z) && (!is_type_in_list(R, illegalSwap)))
woopsMobs += R
if(woopsMobs.len)
woopsTarget = pick(woopsMobs)
var/list/M_spells = list()
M_spells = M.spell_list.Copy()
if(M.mind.special_verbs.len) //All the safeties in higher swap.
for(var/V in M.mind.special_verbs)
M.verbs -= V
for(var/spell/S in M.spell_list)
M.remove_spell(S)
M.mind.transfer_to(woopsTarget)
log_admin("Mind machine malfunction: [M] sent into [woopsTarget] at [formatJumpTo(get_turf(woopsTarget))]")
for(var/spell/S in M_spells)
woopsTarget.add_spell(S)
woopsMobs.len = 0 //Just to be safe
to_chat(M, "<span class='bdanger'>Your mind is thrown out of the machine and forced into a nearby vessel!</span>")
playsound(M, "sound/effects/phasein.ogg", 50, 1)
errorMessage = MINDMACHINE_DELIVERY_ERROR
else
to_chat(M, "<span class='bdanger'>Your mind is severely damaged by the feedback!</span>")
playsound(M, "sound/misc/balloon_pop.ogg", 50, 1)
if(ishuman(M))
M.adjustBrainLoss(75)
errorMessage = MINDMACHINE_MIND_DAMAGED
if(MT == MINDMACHINE_LOWER)
var/list/randFaction = list("hostile", "neutral", "carp", "necro", "wizard", "syndicate", "cult")
M.faction = pick(randFaction)
/obj/machinery/mind_machine/mind_machine_hub/proc/theFlySwap()
var/list/mindFly = list()
var/list/simpFly = list()
var/mob/living/MO = occupantOne
var/mob/living/MT = occupantTwo
for(var/obj/item/weapon/holder/D in theFly)
for(var/mob/M in D.contents)
theFly += M //Gets the mob stored in the holder, adds it to the list
qdel(D)
theFly += MO
theFly += MT
for(var/mob/living/q in theFly)
if(q.mind)
mindFly += q
else
simpFly += q
var/mob/living/dummy = new(src)
simpFly += dummy
var/mob/nuYou = null
for(var/mob/living/flies in mindFly)
nuYou = pick(simpFly)
if(flies.mind.special_verbs.len)
for(var/V in flies.mind.special_verbs)
flies.verbs -= V
for(var/spell/S in flies.spell_list)
flies.remove_spell(S)
flies.mind.transfer_to(nuYou)
simpFly += flies
simpFly -= nuYou
if(dummy.mind)
nuYou = pick(simpFly)
dummy.mind.transfer_to(nuYou)
qdel(dummy)
bluespaceConduit -= 1
mainReset()
theFly.len = 0
simpFly.len = 0
mindFly.len = 0
errorMessage = MINDMACHINE_TRANSPORT_ANOM
/obj/machinery/mind_machine/mind_machine_hub/proc/mainReset()
scanSwapReset()
iconReset()
postSwapReset()
/obj/machinery/mind_machine/mind_machine_hub/proc/iconReset()
connectOne.icon_state = "mind_pod_closed"
connectTwo.icon_state = "mind_pod_closed"
icon_state = "mind_hub"
/obj/machinery/mind_machine/mind_machine_hub/proc/scanSwapReset()
currentlySwapping = FALSE
occupantScan = FALSE
/obj/machinery/mind_machine/mind_machine_hub/proc/postSwapReset()
swapProgress = 0
beenSwapped = TRUE
//Swaps over///////////////
//Pod stuff//////////
/obj/machinery/mind_machine/mind_machine_pod
name = "Mind Machine Pod"
icon_state = "mind_pod_open"
desc = "A large pod used for mind transfers. Contains two locking systems: One for ensuring occupants do not disturb the transfer process, and another that prevents lower minded creatures from leaving on their own."
var/mob/living/occupant = null
var/podNumber = 0
var/obj/machinery/mind_machine/mind_machine_hub/connectedHub
/obj/machinery/mind_machine/mind_machine_pod/New()
..()
component_parts = newlist(
/obj/item/weapon/circuitboard/mind_machine_pod,
/obj/item/weapon/stock_parts/scanning_module/adv/phasic,
/obj/item/weapon/stock_parts/scanning_module/adv/phasic,
/obj/item/weapon/stock_parts/subspace/treatment,
/obj/item/weapon/stock_parts/subspace/ansible,
/obj/item/weapon/stock_parts/subspace/amplifier,
/obj/item/weapon/stock_parts/subspace/crystal,
/obj/item/weapon/stock_parts/subspace/transmitter
)
RefreshParts()
/obj/machinery/mind_machine/mind_machine_pod/RefreshParts()
var/scanCount = 0
for(var/obj/item/weapon/stock_parts/SC in component_parts)
if(istype(SC, /obj/item/weapon/stock_parts/scanning_module))
scanCount += SC.rating
switch(podNumber)
if(1)
connectedHub.scanRatingOne = scanCount
if(2)
connectedHub.scanRatingTwo = scanCount
/obj/machinery/mind_machine/mind_machine_pod/Destroy()
go_out()
if(connectedHub)
connectedHub.podsConnected = FALSE
switch(podNumber)
if(1)
connectedHub.connectOne = null
if(2)
connectedHub.connectTwo = null
..()
/obj/machinery/mind_machine/mind_machine_pod/crowbarDestroy(mob/user, obj/item/tool/crowbar/I)
if(occupant)
to_chat(user, "<span class='warning'>[occupant] is inside the [src]!</span>")
return FALSE
return ..()
/obj/machinery/mind_machine/mind_machine_pod/MouseDropTo(atom/movable/O, mob/user)
if(connectedHub.lockedPods)
to_chat(user, "<span class='notice'>The pod is locked tight!</span>")
return
if(!ismob(O))
return
if(!isturf(O.loc) || !isturf(user.loc) || !user.Adjacent(O)) //I stole all this from DNA scanners
return
if(user.incapacitated() || user.lying)
return
if(!Adjacent(user) || !user.Adjacent(src) || user.contents.Find(src))
return
if(O.anchored)
return
if(!ishigherbeing(user) && !isrobot(user))
return
if(occupant)
to_chat(user, "<span class='notice'>The pod is already occupied!</span>")
return
if(panel_open)
to_chat(user, "<span class='notice'>Close the maintenance panel first.</span>")
return
var/mob/L = O
if(!istype(L))
return
if(iscluwnebanned(L))
to_chat(user, "<span class='notice'>You consider loading the pod, but something tells you that would be a bad idea.</span>")
return
for(var/mob/living/carbon/slime/M in range(1,L))
if(M.Victim == L)
to_chat(usr, "<span class='notice'>[L] will not fit into the pod because they have a slime latched onto their head.</span>")
return
if(L == user)
visible_message("<span class='notice'>[user] climbs into \the [src].</span>")
else
visible_message("<span class='notice'>[user] puts [L.name] into \the [src].</span>")
if(user.pulling == L)
user.stop_pulling()
put_in(L)
/obj/machinery/mind_machine/mind_machine_pod/MouseDropFrom(over_object, src_location, var/turf/over_location, src_control, over_control, params)
if(connectedHub.lockedPods)
to_chat(usr, "<span class='notice'>The pod is locked tight!</span>")
return
if(!ishigherbeing(usr) && !isrobot(usr) || usr.incapacitated() || usr.lying)
return
if(!occupant)
to_chat(usr, "<span class='warning'>\The [src] is unoccupied!</span>")
return
over_location = get_turf(over_location)
if(!istype(over_location) || over_location.density)
return
if(!Adjacent(over_location) || !Adjacent(usr) || !usr.Adjacent(over_location))
return
for(var/atom/movable/A in over_location.contents)
if(A.density)
if((A == src) || istype(A, /mob))
continue
return
if(occupant == usr)
visible_message("<span class='notice'>[usr] climbs out of the \the [src]</span>")
else
visible_message("<span class='notice'>[usr] pulls [occupant.name] out of \the [src].</span>")
go_out(over_location, ejector = usr)
/obj/machinery/mind_machine/mind_machine_pod/proc/put_in(var/mob/M)
M.forceMove(src)
M.reset_view()
src.occupant = M
switch(podNumber)
if(1)
connectedHub.occupantOne = occupant
if(2)
connectedHub.occupantTwo = occupant
/obj/machinery/mind_machine/mind_machine_pod/proc/go_out(var/exit = src.loc, var/mob/ejector)
if(!occupant)
for(var/atom/movable/M in contents)
M.forceMove(get_turf(src))
return 0
if(!occupant.gcDestroyed)
occupant.forceMove(exit)
occupant.reset_view()
occupant = null
switch(podNumber)
if(1)
connectedHub.occupantOne = null
if(2)
connectedHub.occupantTwo = null
/obj/machinery/mind_machine/mind_machine_pod/relaymove(mob/user)
if(user.stat)
return
if(connectedHub.currentlySwapping)
to_chat(user, "<span class='warning'>Your head feels fuzzy and your body is limp. You can't properly focus on getting out.</span>")
if(do_after(user, src, 90 SECONDS)) //More of a safety than a feature
connectedHub.currentlySwapping = FALSE
connectedHub.beenSwapped = FALSE
connectedHub.malfSwap = FALSE
connectedHub.swapProgress = 0
connectedHub.theFly.len = 0
connectedHub.unlockPods()
return
if(connectedHub.lockedPods)
to_chat(user, "<span class='info'>You begin pushing and prying at the door.</span>")
if(do_after(user, src, 10 SECONDS))
connectedHub.unlockPods()
return
src.go_out(ejector = user)
/obj/machinery/mind_machine/mind_machine_pod/Exited(var/atom/movable/O)
if (O == occupant)
occupant = null
switch(podNumber)
if(1)
connectedHub.occupantOne = null
if(2)
connectedHub.occupantTwo = null