NIF Fixes and Soulcatcher NIFSoft, Money Tweak

This commit is contained in:
Arokha Sieyes
2017-06-08 23:03:02 -04:00
parent 5b9d37ffec
commit 5236e2675f
12 changed files with 361 additions and 26 deletions

View File

@@ -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

View File

@@ -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 = ""

View File

@@ -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]"

View File

@@ -13,6 +13,42 @@
if ("awoo")
message = "awoos loudly. AwoooOOOOoooo!"
m_type = 2
if ("nsay")
if(!nif)
to_chat(src,"<span class='warning'>You can't use *nsay without a NIF.</span>")
return 1
var/datum/nifsoft/soulcatcher/SC = nif.imp_check(NIF_SOULCATCHER)
if(!SC)
to_chat(src,"<span class='warning'>You need the Soulcatcher software to use *nme.</span>")
return 1
if(!SC.brainmob.mind)
to_chat(src,"<span class='warning'>You need a loaded mind to use *nme.</span>")
return 1
var/nifmessage = sanitize(input("Type a message to say.") as text|null)
if(nifmessage)
nifmessage = "<b>\[\icon[nif.big_icon]NIF\]</b> <b>[src]</b> speaks, \"[nifmessage]\""
to_chat(SC.brainmob,nifmessage)
to_chat(src,nifmessage)
return 1
if ("nme")
if(!nif)
to_chat(src,"<span class='warning'>You can't use *nme without a NIF.</span>")
return 1
var/datum/nifsoft/soulcatcher/SC = nif.imp_check(NIF_SOULCATCHER)
if(!SC)
to_chat(src,"<span class='warning'>You need the Soulcatcher software to use *nme.</span>")
return 1
if(!SC.brainmob.mind)
to_chat(src,"<span class='warning'>You need a loaded mind to use *nme.</span>")
return 1
var/nifmessage = sanitize(input("Type an action to perform.") as text|null)
if(nifmessage)
nifmessage = "<b>\[\icon[nif.big_icon]NIF\]</b> <b>[src]</b> [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)

View File

@@ -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,"<span class='danger'>[message]</span>")
human.adjustHalLoss(35)
human.custom_pain(message,35)
if(2)
human.Weaken(5)
to_chat(human,"<span class='danger'>A wave of weakness rolls over you.</span>")

View File

@@ -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)

View File

@@ -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"

View File

@@ -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

View File

@@ -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,"<span class='notice'>Your surroundings change to...</span>\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,"<b>\[\icon[nif.big_icon]NIF\]</b> <span class='notice'>Your access to your host's auditory sense has been unrestricted.</span>")
else
brainmob.ext_deaf = TRUE
to_chat(brainmob,"<b>\[\icon[nif.big_icon]NIF\]</b> <span class='warning'>Your access to your host's auditory sense has been restricted.</span>")
if(NIF_SC_ALLOW_EYES)
if(setting_flags & NIF_SC_ALLOW_EYES)
brainmob.ext_blind = FALSE
to_chat(brainmob,"<b>\[\icon[nif.big_icon]NIF\]</b> <span class='notice'>Your access to your host's visual sense has been unrestricted.</span>")
else
brainmob.ext_blind = TRUE
to_chat(brainmob,"<b>\[\icon[nif.big_icon]NIF\]</b> <span class='warning'>Your access to your host's visual sense has been restricted.</span>")
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 = "<span class='notice'>Your vision fades in a haze of static, before returning.</span>\nAround you, you see...\n[inside_flavor]"
to_chat(brainmob,message)
nif.notify("Mind loaded into VR space: [brainmob.name]")
to_chat(nif.human,"<span class='notice'>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'.</span>")
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,"<b>\[\icon[nif.big_icon]NIF\]</b> <b>[name]</b> speaks, \"[message]\"")
to_chat(src,"<b>\[\icon[nif.big_icon]NIF\]</b> <b>[name]</b> 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 << "<span class='warning'>You cannot send IC messages (muted).</span>"
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,"<b>\[\icon[nif.big_icon]NIF\]</b> <b>[name]</b> [message]")
to_chat(src,"<b>\[\icon[nif.big_icon]NIF\]</b> <b>[name]</b> [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

View File

@@ -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

View File

@@ -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"]

View File

@@ -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"