diff --git a/code/__defines/nifsoft.dm b/code/__defines/nifsoft.dm
index 06d1b0c7aa..daf63425ea 100644
--- a/code/__defines/nifsoft.dm
+++ b/code/__defines/nifsoft.dm
@@ -36,9 +36,10 @@
#define NIF_HEATSINK 29
#define NIF_COMPLIANCE 30
#define NIF_SIZECHANGE 31
+#define NIF_SOULCATCHER 32
// Must be equal to the highest number above
-#define TOTAL_NIF_SOFTWARE 31
+#define TOTAL_NIF_SOFTWARE 32
//////////////////////
// NIF flag list hints
@@ -83,6 +84,8 @@
#define NIF_O_APCCHARGE 0x2
#define NIF_O_PRESSURESEAL 0x4
#define NIF_O_HEATSINKS 0x8
+#define NIF_O_SCMYSELF 0x10 //Soulcatcher stuff
+#define NIF_O_SCOTHERS 0x20
///////////////////
// applies_to flags
diff --git a/code/game/jobs/job/job.dm b/code/game/jobs/job/job.dm
index 6add65ce55..dd265203d6 100644
--- a/code/game/jobs/job/job.dm
+++ b/code/game/jobs/job/job.dm
@@ -54,7 +54,7 @@
if(COMPANY_OPPOSED) loyalty = 0.70
//give them an account in the station database
- var/money_amount = (rand(5,50) + rand(5, 50)) * loyalty * economic_modifier * ECO_MODIFIER
+ var/money_amount = (rand(15,40) + rand(15,40)) * loyalty * economic_modifier * ECO_MODIFIER //VOREStation Edit - Smoothed peaks.
var/datum/money_account/M = create_account(H.real_name, money_amount, null)
if(H.mind)
var/remembered_info = ""
diff --git a/code/modules/client/preference_setup/vore/08_nif.dm b/code/modules/client/preference_setup/vore/08_nif.dm
index 52586d3bcf..62ebbdbeac 100644
--- a/code/modules/client/preference_setup/vore/08_nif.dm
+++ b/code/modules/client/preference_setup/vore/08_nif.dm
@@ -2,6 +2,7 @@
/datum/preferences
var/obj/item/device/nif/nif_path
var/nif_durability
+ var/list/nif_savedata
// Definition of the stuff for NIFs
/datum/category_item/player_setup_item/vore/nif
@@ -11,10 +12,12 @@
/datum/category_item/player_setup_item/vore/nif/load_character(var/savefile/S)
S["nif_path"] >> pref.nif_path
S["nif_durability"] >> pref.nif_durability
+ S["nif_savedata"] >> pref.nif_savedata
/datum/category_item/player_setup_item/vore/nif/save_character(var/savefile/S)
S["nif_path"] << pref.nif_path
S["nif_durability"] << pref.nif_durability
+ S["nif_savedata"] << pref.nif_savedata
/datum/category_item/player_setup_item/vore/nif/sanitize_character()
if(pref.nif_path && !ispath(pref.nif_path)) //We have at least a text string that should be a path.
@@ -23,19 +26,23 @@
pref.nif_path = null //Kill!
WARNING("Loaded a NIF but it was an invalid path, [pref.real_name]")
- if(ispath(pref.nif_path) && !pref.nif_durability) //How'd you lose this?
+ if(ispath(pref.nif_path) && isnull(pref.nif_durability)) //How'd you lose this?
pref.nif_durability = initial(pref.nif_path.durability) //Well, have a new one, my bad.
WARNING("Loaded a NIF but with no durability, [pref.real_name]")
+ if(!islist(pref.nif_savedata))
+ pref.nif_savedata = list()
+
/datum/category_item/player_setup_item/vore/nif/copy_to_mob(var/mob/living/carbon/human/character)
//If you had a NIF...
if((character.type == /mob/living/carbon/human) && ispath(pref.nif_path) && pref.nif_durability)
- new pref.nif_path(character,pref.nif_durability)
+ new pref.nif_path(character,pref.nif_durability,pref.nif_savedata)
//And now here's the trick. We wipe these so that if they die, they lose the NIF.
//Backup implants will start saving this again periodically, and so will cryo'ing out.
pref.nif_path = null
pref.nif_durability = null
+ pref.nif_savedata = null
var/savefile/S = new /savefile(pref.path)
if(!S) WARNING ("Couldn't load NIF save savefile? [pref.real_name]")
S.cd = "/character[pref.default_slot]"
diff --git a/code/modules/mob/living/carbon/human/emote_vr.dm b/code/modules/mob/living/carbon/human/emote_vr.dm
index 274ddd2904..4b3091b440 100644
--- a/code/modules/mob/living/carbon/human/emote_vr.dm
+++ b/code/modules/mob/living/carbon/human/emote_vr.dm
@@ -13,6 +13,42 @@
if ("awoo")
message = "awoos loudly. AwoooOOOOoooo!"
m_type = 2
+ if ("nsay")
+ if(!nif)
+ to_chat(src,"You can't use *nsay without a NIF.")
+ return 1
+ var/datum/nifsoft/soulcatcher/SC = nif.imp_check(NIF_SOULCATCHER)
+ if(!SC)
+ to_chat(src,"You need the Soulcatcher software to use *nme.")
+ return 1
+ if(!SC.brainmob.mind)
+ to_chat(src,"You need a loaded mind to use *nme.")
+ return 1
+ var/nifmessage = sanitize(input("Type a message to say.") as text|null)
+ if(nifmessage)
+ nifmessage = "\[\icon[nif.big_icon]NIF\] [src] speaks, \"[nifmessage]\""
+ to_chat(SC.brainmob,nifmessage)
+ to_chat(src,nifmessage)
+ return 1
+
+ if ("nme")
+ if(!nif)
+ to_chat(src,"You can't use *nme without a NIF.")
+ return 1
+ var/datum/nifsoft/soulcatcher/SC = nif.imp_check(NIF_SOULCATCHER)
+ if(!SC)
+ to_chat(src,"You need the Soulcatcher software to use *nme.")
+ return 1
+ if(!SC.brainmob.mind)
+ to_chat(src,"You need a loaded mind to use *nme.")
+ return 1
+ var/nifmessage = sanitize(input("Type an action to perform.") as text|null)
+ if(nifmessage)
+ nifmessage = "\[\icon[nif.big_icon]NIF\] [src] [nifmessage]"
+ to_chat(SC.brainmob,nifmessage)
+ to_chat(src,nifmessage)
+ return 1
+
if ("flip")
var/danger = 1 //Base 1% chance to break something.
var/list/involved_parts = list(BP_L_LEG, BP_R_LEG, BP_L_FOOT, BP_R_FOOT)
diff --git a/code/modules/nifsoft/nif.dm b/code/modules/nifsoft/nif.dm
index e8f4976f48..8dc8d9c52e 100644
--- a/code/modules/nifsoft/nif.dm
+++ b/code/modules/nifsoft/nif.dm
@@ -1,3 +1,14 @@
+/* //////////////////////////////
+The NIF has a proc API shared with NIFSofts, and you should not really ever
+directly interact with this API. Procs like install(), uninstall(), etc should
+not be directly called. If you want to install a new NIFSoft, pass the NIF in
+the constructor for a new instance of the NIFSoft. If you want to force a NIFSoft
+to be uninstalled, use imp_check to get a reference to it, and call
+uninstall() only on the return value of that.
+
+You can also set the stat of a NIF to NIF_TEMPFAIL without any issues to disable it.
+*/ //////////////////////////////
+
//Holder on humans to prevent having to 'find' it every time
/mob/living/carbon/human/var/obj/item/device/nif/nif
@@ -45,17 +56,22 @@
"seems to be daydreaming",
"focuses elsewhere for a moment")
-//Constructor comes with a free AR HUD
-/obj/item/device/nif/New(var/newloc,var/wear)
- ..(newloc)
+ var/list/save_data
- //Required for AR stuff.
- nif_hud = new(src)
+//Constructor comes with a free AR HUD
+/obj/item/device/nif/New(var/newloc,var/wear,var/list/load_data)
+ ..(newloc)
//First one to spawn in the game, make a big icon
if(!big_icon)
big_icon = new(icon,icon_state = "nif_full")
+ //Required for AR stuff.
+ nif_hud = new(src)
+
+ //Put loaded data here if we loaded any
+ save_data = islist(load_data) ? load_data.Copy() : list()
+
//If given a human on spawn (probably from persistence)
if(ishuman(newloc))
var/mob/living/carbon/human/H = newloc
@@ -233,7 +249,8 @@
var/percent_done = (world.time - (install_done - (30 MINUTES))) / (30 MINUTES)
- human.client.screen.Add(global_hud.whitense) //This is the camera static
+ if(human.client)
+ human.client.screen.Add(global_hud.whitense) //This is the camera static
switch(percent_done) //This is 0.0 to 1.0 kinda percent.
//Connecting to optical nerves
@@ -242,19 +259,20 @@
//Mapping brain
if(0.2 to 0.9)
- if(prob(99)) return TRUE
+ if(prob(98)) return TRUE
var/incident = rand(1,3)
switch(incident)
if(1)
var/message = pick(list(
- "Your head throbs around your new implant.",
- "The skin around your recent surgery itches.",
- "A wave of nausea overtakes you as the world seems to spin.",
- "The floor suddenly seems to come up at you.",
- "There's a throbbing lump of ice behind your eyes.",
- "A wave of pain shoots down your neck."
+ "Your head throbs around your new implant!",
+ "The skin around your recent surgery itches!",
+ "A wave of nausea overtakes you as the world seems to spin!",
+ "The floor suddenly seems to come up at you!",
+ "There's a throbbing lump of ice behind your eyes!",
+ "A wave of pain shoots down your neck!"
))
- to_chat(human,"[message]")
+ human.adjustHalLoss(35)
+ human.custom_pain(message,35)
if(2)
human.Weaken(5)
to_chat(human,"A wave of weakness rolls over you.")
diff --git a/code/modules/nifsoft/nif_statpanel.dm b/code/modules/nifsoft/nif_statpanel.dm
index 23b5aca0b1..579dc44ec9 100644
--- a/code/modules/nifsoft/nif_statpanel.dm
+++ b/code/modules/nifsoft/nif_statpanel.dm
@@ -5,18 +5,22 @@
/mob/living/carbon/human/proc/SetupNifStat()
var/nif_status = ""
+ var/nif_percent = round((nif.durability/initial(nif.durability))*100)
switch(nif.stat)
if(NIF_WORKING)
- nif_status = "Operating Normally"
+ if(nif_percent < 20)
+ nif_status = "Service Needed Soon"
+ else
+ nif_status = "Operating Normally"
if(NIF_POWFAIL)
nif_status = "Insufficient Energy!"
if(NIF_TEMPFAIL)
- nif_status = "Needs Maintenance!"
+ nif_status = "System Failure!"
if(NIF_INSTALLING)
nif_status = "Adapting To User"
else
nif_status = "Unknown - Error"
- nif_status += " ([round((nif.durability/initial(nif.durability))*100)]%)"
+ nif_status += " (Condition: [nif_percent]%)"
stat("NIF Status", nif_status)
if(nif.stat == NIF_WORKING)
diff --git a/code/modules/nifsoft/nifsoft.dm b/code/modules/nifsoft/nifsoft.dm
index 0703adfab4..fdccca0bce 100644
--- a/code/modules/nifsoft/nifsoft.dm
+++ b/code/modules/nifsoft/nifsoft.dm
@@ -1,3 +1,6 @@
+//Please see the comment above the main NIF definition before
+//trying to call any of these procs directly.
+
//A single piece of NIF software
/datum/nifsoft
var/name = "Prototype"
diff --git a/code/modules/nifsoft/software/01_vision.dm b/code/modules/nifsoft/software/01_vision.dm
index d222cd67dd..c58377f957 100644
--- a/code/modules/nifsoft/software/01_vision.dm
+++ b/code/modules/nifsoft/software/01_vision.dm
@@ -172,8 +172,9 @@
life()
if((. = ..()))
var/mob/living/carbon/human/H = nif.human
- H.client.screen |= global_hud.meson
H.sight |= SEE_TURFS
+ if(H.client)
+ H.client.screen |= global_hud.meson
/datum/nifsoft/material
name = "Material Scanner"
@@ -219,8 +220,9 @@
if((. = ..()))
var/mob/living/carbon/human/H = nif.human
H.sight |= SEE_MOBS
- H.client.screen |= global_hud.thermal
H.see_invisible = SEE_INVISIBLE_NOLIGHTING
+ if(H.client)
+ H.client.screen |= global_hud.thermal
/datum/nifsoft/nightvis
name = "Low-Light Amp"
@@ -244,6 +246,7 @@
if((. = ..()))
var/mob/living/carbon/human/H = nif.human
H.see_in_dark += 7
- H.client.screen |= global_hud.nvg
H.see_invisible = SEE_INVISIBLE_NOLIGHTING
+ if(H.client)
+ H.client.screen |= global_hud.nvg
diff --git a/code/modules/nifsoft/software/13_soulcatcher.dm b/code/modules/nifsoft/software/13_soulcatcher.dm
new file mode 100644
index 0000000000..f1eac1bef3
--- /dev/null
+++ b/code/modules/nifsoft/software/13_soulcatcher.dm
@@ -0,0 +1,258 @@
+//These two also have NIF FLAG representations. These are the local setting representations.
+#define NIF_SC_CATCHING_ME 0x1
+#define NIF_SC_CATCHING_OTHERS 0x2
+//These are purely local setings flags, without global representation.
+#define NIF_SC_ALLOW_EARS 0x4
+#define NIF_SC_ALLOW_EYES 0x8
+
+///////////
+// Soulcatcher - Like a posibrain, sorta!
+/datum/nifsoft/soulcatcher
+ name = "Soulcatcher"
+ desc = "A mind storage and processing system capable of capturing and supporting a single human-intelligence mind on body death, into a small VR space."
+ list_pos = NIF_SOULCATCHER
+ cost = 1265
+ wear = 1
+ p_drain = 0.01
+
+ var/setting_flags = (NIF_SC_CATCHING_ME|NIF_SC_CATCHING_OTHERS|NIF_SC_ALLOW_EARS|NIF_SC_ALLOW_EYES)
+ var/mob/living/carbon/brain/caught_soul/brainmob
+ var/inside_flavor = "A small completely white room with a couch, and a window to what seems to be the outside world. A small sign in the corner says 'Configure Me'."
+
+ New()
+ ..()
+ brainmob = new(nif)
+ brainmob.nif = nif
+ brainmob.container = src
+ brainmob.stat = 0
+ brainmob.silent = FALSE
+ dead_mob_list -= src.brainmob
+ load_settings()
+
+ Destroy()
+ if(brainmob)
+ brainmob.container = null
+ qdel(brainmob)
+ ..()
+
+ install()
+ if((. = ..()))
+ nif.set_flag(NIF_O_SCMYSELF,NIF_FLAGS_OTHER)
+ nif.set_flag(NIF_O_SCOTHERS,NIF_FLAGS_OTHER)
+
+ uninstall()
+ if((. = ..()))
+ nif.clear_flag(NIF_O_SCMYSELF,NIF_FLAGS_OTHER)
+ nif.clear_flag(NIF_O_SCOTHERS,NIF_FLAGS_OTHER)
+
+ activate()
+ if((. = ..()))
+ show_settings(nif.human)
+ spawn(0)
+ deactivate()
+
+ deactivate()
+ if((. = ..()))
+ return TRUE
+
+ stat_text()
+ return "Change Settings[brainmob.mind ? " (Mind Stored)" : ""]"
+
+ proc/save_settings()
+ nif.save_data["[list_pos]"] = inside_flavor
+ return TRUE
+
+ proc/load_settings()
+ var/load = nif.save_data["[list_pos]"]
+ if(load)
+ inside_flavor = load
+ return TRUE
+
+ proc/show_settings(var/mob/living/carbon/human/H)
+ var/settings_list = list(
+ "Catching You \[[setting_flags & NIF_SC_CATCHING_ME ? "Enabled" : "Disabled"]\]" = NIF_SC_CATCHING_ME,
+ "Catching Others \[[setting_flags & NIF_SC_CATCHING_OTHERS ? "Enabled" : "Disabled"]\]" = NIF_SC_CATCHING_OTHERS,
+ "Ext. Hearing \[[setting_flags & NIF_SC_ALLOW_EARS ? "Enabled" : "Disabled"]\]" = NIF_SC_ALLOW_EARS,
+ "Ext. Vision \[[setting_flags & NIF_SC_ALLOW_EYES ? "Enabled" : "Disabled"]\]" = NIF_SC_ALLOW_EYES,
+ "Design Inside",
+ "Erase Contents")
+ var/choice = input(nif.human,"Select a setting to modify:","Soulcatcher NIFSoft") as null|anything in settings_list
+ if(choice in settings_list)
+ switch(choice)
+ if("Design Inside")
+ var/new_flavor = input(nif.human, "Type what the prey sees after being 'caught'. This will be \
+ printed after an intro ending with: \"Around you, you see...\" to the prey. If you already \
+ have prey, this will be printed to them after \"Your surroundings change to...\". Limit 2048 char.", \
+ "VR Environment", html_decode(inside_flavor)) as message
+ new_flavor = sanitize(new_flavor)
+ inside_flavor = new_flavor
+ nif.notify("Updating VR environment...")
+ to_chat(brainmob,"Your surroundings change to...\n[inside_flavor]")
+ save_settings()
+ return TRUE
+
+ if("Erase Contents")
+ if(brainmob && brainmob.mind)
+ var/warning = alert(nif.human,"Are you SURE you want to erase [brainmob.mind.name]?","Erase Mind","CANCEL","DELETE","CANCEL")
+ if(warning == "DELETE")
+ brainmob.ghostize()
+ qdel(brainmob)
+ brainmob = new(nif)
+ nif.notify("Mind deleted!",TRUE)
+ return TRUE
+ else
+ nif.notify("No mind to delete!",TRUE)
+ return TRUE
+
+ //Must just be a flag without special handling then.
+ else
+ var/flag = settings_list[choice]
+ return toggle_setting(flag)
+
+ proc/toggle_setting(var/flag)
+ setting_flags ^= flag
+
+ //Special treatment
+ switch(flag)
+ if(NIF_SC_CATCHING_ME)
+ if(setting_flags & NIF_SC_CATCHING_ME)
+ nif.set_flag(NIF_O_SCMYSELF,NIF_FLAGS_OTHER)
+ else
+ nif.clear_flag(NIF_O_SCMYSELF,NIF_FLAGS_OTHER)
+ if(NIF_SC_CATCHING_OTHERS)
+ if(setting_flags & NIF_SC_CATCHING_OTHERS)
+ nif.set_flag(NIF_O_SCOTHERS,NIF_FLAGS_OTHER)
+ else
+ nif.clear_flag(NIF_O_SCOTHERS,NIF_FLAGS_OTHER)
+ if(NIF_SC_ALLOW_EARS)
+ if(setting_flags & NIF_SC_ALLOW_EARS)
+ brainmob.ext_deaf = FALSE
+ to_chat(brainmob,"\[\icon[nif.big_icon]NIF\] Your access to your host's auditory sense has been unrestricted.")
+ else
+ brainmob.ext_deaf = TRUE
+ to_chat(brainmob,"\[\icon[nif.big_icon]NIF\] Your access to your host's auditory sense has been restricted.")
+ if(NIF_SC_ALLOW_EYES)
+ if(setting_flags & NIF_SC_ALLOW_EYES)
+ brainmob.ext_blind = FALSE
+ to_chat(brainmob,"\[\icon[nif.big_icon]NIF\] Your access to your host's visual sense has been unrestricted.")
+ else
+ brainmob.ext_blind = TRUE
+ to_chat(brainmob,"\[\icon[nif.big_icon]NIF\] Your access to your host's visual sense has been restricted.")
+
+ return TRUE
+
+ proc/catch_mob(var/mob/living/carbon/human/H)
+ if(istype(H))
+ if(H == nif.human) //Reset our permissions to be permissive to the owner.
+ brainmob.ext_deaf = FALSE
+ brainmob.ext_blind = FALSE
+ brainmob.parent_mob = TRUE
+
+ brainmob.dna = H.dna
+ brainmob.timeofhostdeath = H.timeofdeath
+ brainmob.stat = 0
+ if(H.mind)
+ H.mind.transfer_to(brainmob)
+ brainmob.name = brainmob.mind.name
+ var/message = "Your vision fades in a haze of static, before returning.\nAround you, you see...\n[inside_flavor]"
+ to_chat(brainmob,message)
+ nif.notify("Mind loaded into VR space: [brainmob.name]")
+ to_chat(nif.human,"Your occupant's messages/actions can only be seen by you, and you can \
+ send messages that only they can hear/see by 'say'ing either '*nsay' or '*nme'.")
+ return TRUE
+
+ return FALSE
+
+////////////////
+//The caught mob
+/mob/living/carbon/brain/caught_soul
+ name = "recorded mind"
+ desc = "A mind recorded and being played on digital hardware."
+ use_me = 1
+ var/ext_deaf = FALSE //Forbidden from 'ear' access on host
+ var/ext_blind = FALSE //Forbidden from 'eye' access on host
+ var/parent_mob = FALSE //If we've captured our owner
+ var/obj/item/device/nif/nif
+
+/mob/living/carbon/brain/caught_soul/Destroy()
+ nif = null
+ ..()
+
+/mob/living/carbon/brain/caught_soul/Life()
+ if(!client) return
+
+ . = ..()
+
+ if(parent_mob) return
+ //If they're blinded
+ if(ext_blind)
+ eye_blind = 5
+ client.screen.Remove(global_hud.whitense)
+ overlay_fullscreen("blind", /obj/screen/fullscreen/blind)
+ else
+ eye_blind = 0
+ clear_fullscreens()
+ client.screen.Add(global_hud.whitense)
+
+ //If they're deaf
+ if(ext_deaf)
+ ear_deaf = 5
+ else
+ ear_deaf = 0
+
+/mob/living/carbon/brain/caught_soul/hear_say()
+ if(ext_deaf || !client)
+ return FALSE
+ ..()
+
+/mob/living/carbon/brain/caught_soul/show_message()
+ if(ext_blind || !client)
+ return FALSE
+ ..()
+
+/mob/living/carbon/brain/caught_soul/say(var/message)
+ if(parent_mob) return ..()
+ if(silent) return FALSE
+ to_chat(nif.human,"\[\icon[nif.big_icon]NIF\] [name] speaks, \"[message]\"")
+ to_chat(src,"\[\icon[nif.big_icon]NIF\] [name] speaks, \"[message]\"")
+
+/mob/living/carbon/brain/caught_soul/emote(var/act,var/m_type=1,var/message = null)
+ if(parent_mob) return ..()
+ if(silent) return FALSE
+ if (act == "me")
+ if(silent)
+ return
+ if (src.client)
+ if (client.prefs.muted & MUTE_IC)
+ src << "You cannot send IC messages (muted)."
+ return
+ if (stat)
+ return
+ if(!(message))
+ return
+ return custom_emote(m_type, message)
+ else
+ return FALSE
+
+/mob/living/carbon/brain/caught_soul/custom_emote(var/m_type, var/message)
+ if(silent) return FALSE
+ to_chat(nif.human,"\[\icon[nif.big_icon]NIF\] [name] [message]")
+ to_chat(src,"\[\icon[nif.big_icon]NIF\] [name] [message]")
+
+///////////////////
+//The catching hook
+/hook/death/proc/nif_soulcatcher(var/mob/living/carbon/human/H)
+ if(!istype(H)) return TRUE //Hooks must return TRUE
+
+ if(H.nif && H.nif.flag_check(NIF_O_SCMYSELF,NIF_FLAGS_OTHER)) //They are caught in their own NIF
+ var/datum/nifsoft/soulcatcher/SC = H.nif.imp_check(NIF_SOULCATCHER)
+ if(!SC.brainmob.mind) //As long as they don't have one
+ SC.catch_mob(H,TRUE)
+ else if(ishuman(H.loc)) //Died in someone
+ var/mob/living/carbon/human/HP = H.loc
+ if(HP.nif && HP.nif.flag_check(NIF_O_SCOTHERS,NIF_FLAGS_OTHER))
+ var/datum/nifsoft/soulcatcher/SC = HP.nif.imp_check(NIF_SOULCATCHER)
+ if(!SC.brainmob.mind) //As long as they don't have one
+ SC.catch_mob(H,FALSE)
+
+ return TRUE
\ No newline at end of file
diff --git a/code/modules/nifsoft/software/15_misc.dm b/code/modules/nifsoft/software/15_misc.dm
index cc8d6b8b10..91ea175338 100644
--- a/code/modules/nifsoft/software/15_misc.dm
+++ b/code/modules/nifsoft/software/15_misc.dm
@@ -31,7 +31,7 @@
life()
if((. = ..()))
var/mob/living/carbon/human/H = nif.human
- if(apc && (get_dist(H,apc) <= 1) && H.nutrition < 450)
+ if(apc && (get_dist(H,apc) <= 1) && H.nutrition < 440) // 440 vs 450, life() happens before we get here so it'll never be EXACTLY 450
H.nutrition = min(H.nutrition+10, 450)
apc.drain_power(7000/450*10) //This is from the large rechargers. No idea what the math is.
return TRUE
diff --git a/code/modules/vore/persist/persist_vr.dm b/code/modules/vore/persist/persist_vr.dm
index bddd9bc7b9..eb124f58f6 100644
--- a/code/modules/vore/persist/persist_vr.dm
+++ b/code/modules/vore/persist/persist_vr.dm
@@ -15,7 +15,7 @@
// Handle people leaving due to round ending.
/hook/roundend/proc/persist_locations()
- for(var/mob/Player in player_list)
+ for(var/mob/Player in human_mob_list)
if(!Player.mind || isnewplayer(Player))
continue // No mind we can do nothing, new players we care not for
else if(Player.stat == DEAD)
@@ -233,9 +233,11 @@
if(nif)
prefs.nif_path = nif.type
prefs.nif_durability = nif.durability
+ prefs.nif_savedata = nif.save_data.Copy()
else
prefs.nif_path = null
prefs.nif_durability = null
+ prefs.nif_savedata = null
var/datum/category_group/player_setup_category/vore_cat = prefs.player_setup.categories_by_name["VORE"]
var/datum/category_item/player_setup_item/vore/nif/nif_prefs = vore_cat.items_by_name["NIF Data"]
diff --git a/vorestation.dme b/vorestation.dme
index 41f8895e95..8325921369 100644
--- a/vorestation.dme
+++ b/vorestation.dme
@@ -1972,6 +1972,7 @@
#include "code\modules\nifsoft\software\01_vision.dm"
#include "code\modules\nifsoft\software\05_health.dm"
#include "code\modules\nifsoft\software\10_combat.dm"
+#include "code\modules\nifsoft\software\13_soulcatcher.dm"
#include "code\modules\nifsoft\software\14_commlink.dm"
#include "code\modules\nifsoft\software\15_misc.dm"
#include "code\modules\organs\blood.dm"