TGUI NIFs

This commit is contained in:
ShadowLarkens
2020-09-07 23:45:13 -07:00
parent f16b10c033
commit 26c295bfb4
14 changed files with 937 additions and 546 deletions

View File

@@ -101,6 +101,9 @@ You can also set the stat of a NIF to NIF_TEMPFAIL without any issues to disable
//Draw me yo.
update_icon()
if(!our_statclick)
our_statclick = new(null, "Open", src)
//Destructor cleans up references
/obj/item/device/nif/Destroy()
human = null
@@ -356,6 +359,8 @@ You can also set the stat of a NIF to NIF_TEMPFAIL without any issues to disable
/obj/item/device/nif/proc/notify(var/message,var/alert = 0)
if(!human || stat == NIF_TEMPFAIL) return
last_notification = message // TGUI Hook
to_chat(human,"<b>\[[bicon(src.big_icon)]NIF\]</b> displays, \"<span class='[alert ? "danger" : "notice"]'>[message]</span>\"")
if(prob(1)) human.visible_message("<span class='notice'>\The [human] [pick(look_messages)].</span>")
if(alert)

View File

@@ -22,6 +22,7 @@
nif_status = "Unknown - Error"
nif_status += " (Condition: [nif_percent]%)"
stat("NIF Status", nif_status)
stat("UI", nif.our_statclick) // TGUI Hook
if(nif.stat == NIF_WORKING)
stat("- Modules -", "LMB: Toggle, Shift+LMB: Info/Uninstall")

View File

@@ -0,0 +1,114 @@
/************************************************************************\
* This module controls everything to do with the NIF's tgui interface. *
\************************************************************************/
/**
* Etc variables on the NIF to keep this self contained
*/
/obj/item/device/nif
var/static/list/valid_ui_themes = list(
"abductor",
"cardtable",
"hackerman",
"malfunction",
"ntos",
"paper",
"retro",
"syndicate"
)
var/tmp/obj/effect/statclick/nif_open/our_statclick
var/tmp/last_notification
/**
* Special stat button for the interface
*/
/obj/effect/statclick/nif_open
/obj/effect/statclick/nif_open/Click(location, control, params)
var/obj/item/device/nif/N = target
if(istype(N))
N.tgui_interact(usr)
/**
* The NIF State ensures that only our authorized implanted user can touch us.
*/
/obj/item/device/nif/tgui_state(mob/user)
return GLOB.tgui_nif_main_state
/**
* Standard TGUI stub to open the NIF.js template.
*/
/obj/item/device/nif/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "NIF", name)
ui.open()
/**
* tgui_data gives the UI any relevant data it needs.
* In our case, that's basically everything from our statpanel.
*/
/obj/item/device/nif/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
data["theme"] = save_data["ui_theme"]
data["last_notification"] = last_notification
// Random biometric information
data["nutrition"] = human.nutrition
data["isSynthetic"] = human.isSynthetic()
data["nif_percent"] = round((durability/initial(durability))*100)
data["nif_stat"] = stat
data["modules"] = list()
if(stat == NIF_WORKING)
for(var/nifsoft in nifsofts)
if(!nifsoft)
continue
var/datum/nifsoft/NS = nifsoft
data["modules"].Add(list(list(
"name" = NS.name,
"desc" = NS.desc,
"p_drain" = NS.p_drain,
"a_drain" = NS.a_drain,
"illegal" = NS.illegal,
"wear" = NS.wear,
"cost" = NS.cost,
"activates" = NS.activates,
"active" = NS.active,
"stat_text" = NS.stat_text(),
"ref" = REF(NS),
)))
return data
/**
* tgui_act handles all user input in the UI.
*/
/obj/item/device/nif/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
switch(action)
if("setTheme")
if((params["theme"] in valid_ui_themes) || params["theme"] == null)
save_data["ui_theme"] = params["theme"]
return TRUE
if("toggle_module")
var/datum/nifsoft/NS = locate(params["module"]) in nifsofts
if(!istype(NS))
return
if(NS.activates)
if(NS.active)
NS.deactivate()
else
NS.activate()
return TRUE
if("uninstall")
var/datum/nifsoft/NS = locate(params["module"]) in nifsofts
if(!istype(NS))
return
NS.uninstall()
return TRUE
if("dismissNotification")
last_notification = null
return TRUE

View File

@@ -106,12 +106,12 @@
vision_flags = (NIF_V_MESONS)
incompatible_with = list(NIF_MATERIAL,NIF_THERMALS,NIF_NIGHTVIS)
life()
if((. = ..()))
var/mob/living/carbon/human/H = nif.human
H.sight |= SEE_TURFS
if(H.client)
H.client.screen |= global_hud.meson
/datum/nifsoft/mesons/life()
if((. = ..()))
var/mob/living/carbon/human/H = nif.human
H.sight |= SEE_TURFS
if(H.client)
H.client.screen |= global_hud.meson
/datum/nifsoft/material
name = "Material Scanner"
@@ -125,12 +125,12 @@
vision_flags = (NIF_V_MATERIAL)
incompatible_with = list(NIF_MESONS,NIF_THERMALS,NIF_NIGHTVIS)
life()
if((. = ..()))
var/mob/living/carbon/human/H = nif.human
H.sight |= SEE_OBJS
if(H.client)
H.client.screen |= global_hud.material
/datum/nifsoft/material/life()
if((. = ..()))
var/mob/living/carbon/human/H = nif.human
H.sight |= SEE_OBJS
if(H.client)
H.client.screen |= global_hud.material
/datum/nifsoft/thermals
name = "Thermal Scanner"
@@ -145,12 +145,12 @@
vision_flags = (NIF_V_THERMALS)
incompatible_with = list(NIF_MESONS,NIF_MATERIAL,NIF_NIGHTVIS)
life()
if((. = ..()))
var/mob/living/carbon/human/H = nif.human
H.sight |= SEE_MOBS
if(H.client)
H.client.screen |= global_hud.thermal
/datum/nifsoft/thermals/life()
if((. = ..()))
var/mob/living/carbon/human/H = nif.human
H.sight |= SEE_MOBS
if(H.client)
H.client.screen |= global_hud.thermal
/datum/nifsoft/nightvis
name = "Low-Light Amp"
@@ -164,9 +164,9 @@
vision_flags = (NIF_V_NIGHTVIS)
incompatible_with = list(NIF_MESONS,NIF_MATERIAL,NIF_THERMALS)
life()
if((. = ..()))
var/mob/living/carbon/human/H = nif.human
H.see_in_dark += 7
if(H.client)
H.client.screen |= global_hud.nvg
/datum/nifsoft/nightvis/life()
if((. = ..()))
var/mob/living/carbon/human/H = nif.human
H.see_in_dark += 7
if(H.client)
H.client.screen |= global_hud.nvg

View File

@@ -13,63 +13,63 @@
health_flags = (NIF_H_ORGREPAIR)
//These self-activate on their own, these aren't user-settable to on/off.
activate()
if((. = ..()))
mode = 1
/datum/nifsoft/medichines_org/activate()
if((. = ..()))
mode = 1
deactivate()
if((. = ..()))
a_drain = initial(a_drain)
mode = initial(mode)
nif.human.Stasis(0)
/datum/nifsoft/medichines_org/deactivate()
if((. = ..()))
a_drain = initial(a_drain)
mode = initial(mode)
nif.human.Stasis(0)
life()
if((. = ..()))
var/mob/living/carbon/human/H = nif.human
var/HP_percent = H.health/H.getMaxHealth()
/datum/nifsoft/medichines_org/life()
if((. = ..()))
var/mob/living/carbon/human/H = nif.human
var/HP_percent = H.health/H.getMaxHealth()
//Mode changing state machine
if(HP_percent >= 0.9)
if(mode)
nif.notify("User Status: NORMAL. Medichines deactivating.")
deactivate()
return TRUE
else if(!mode && HP_percent < 0.8)
nif.notify("User Status: INJURED. Commencing medichine routines.",TRUE)
activate()
else if(mode == 1 && HP_percent < 0.2)
nif.notify("User Status: DANGER. Seek medical attention!",TRUE)
mode = 2
else if(mode == 2 && HP_percent < -0.4)
nif.notify("User Status: CRITICAL. Notifying medical, and starting emergency stasis!",TRUE)
mode = 3
if(!isbelly(H.loc)) //Not notified in case of vore, for gameplay purposes.
var/turf/T = get_turf(H)
var/obj/item/device/radio/headset/a = new /obj/item/device/radio/headset/heads/captain(null)
a.autosay("[H.real_name] has been put in emergency stasis, located at ([T.x],[T.y],[T.z])!", "[H.real_name]'s NIF", "Medical")
qdel(a)
//Handle the actions in each mode
//Injured but not critical
//Mode changing state machine
if(HP_percent >= 0.9)
if(mode)
H.adjustToxLoss(-0.1 * mode)
H.adjustBruteLoss(-0.1 * mode)
H.adjustFireLoss(-0.1 * mode)
if(mode >= 2)
nif.use_charge(a_drain) //A second drain if we're in level 2+
//Patient critical - emergency stasis
if(mode >= 3)
if(HP_percent <= 0)
H.Stasis(3)
if(HP_percent > 0.2)
H.Stasis(0)
nif.notify("Ending emergency stasis.",TRUE)
mode = 2
nif.notify("User Status: NORMAL. Medichines deactivating.")
deactivate()
return TRUE
else if(!mode && HP_percent < 0.8)
nif.notify("User Status: INJURED. Commencing medichine routines.",TRUE)
activate()
else if(mode == 1 && HP_percent < 0.2)
nif.notify("User Status: DANGER. Seek medical attention!",TRUE)
mode = 2
else if(mode == 2 && HP_percent < -0.4)
nif.notify("User Status: CRITICAL. Notifying medical, and starting emergency stasis!",TRUE)
mode = 3
if(!isbelly(H.loc)) //Not notified in case of vore, for gameplay purposes.
var/turf/T = get_turf(H)
var/obj/item/device/radio/headset/a = new /obj/item/device/radio/headset/heads/captain(null)
a.autosay("[H.real_name] has been put in emergency stasis, located at ([T.x],[T.y],[T.z])!", "[H.real_name]'s NIF", "Medical")
qdel(a)
//Handle the actions in each mode
//Injured but not critical
if(mode)
H.adjustToxLoss(-0.1 * mode)
H.adjustBruteLoss(-0.1 * mode)
H.adjustFireLoss(-0.1 * mode)
if(mode >= 2)
nif.use_charge(a_drain) //A second drain if we're in level 2+
//Patient critical - emergency stasis
if(mode >= 3)
if(HP_percent <= 0)
H.Stasis(3)
if(HP_percent > 0.2)
H.Stasis(0)
nif.notify("Ending emergency stasis.",TRUE)
mode = 2
return TRUE
/datum/nifsoft/medichines_syn
name = "Medichines"
@@ -86,44 +86,44 @@
health_flags = (NIF_H_SYNTHREPAIR)
//These self-activate on their own, these aren't user-settable to on/off.
activate()
if((. = ..()))
mode = 1
/datum/nifsoft/medichines_syn/activate()
if((. = ..()))
mode = 1
deactivate()
if((. = ..()))
mode = 0
life()
if((. = ..()))
//We're good!
if(!nif.human.bad_external_organs.len)
if(mode || active)
nif.notify("User Status: NORMAL. Medichines deactivating.")
deactivate()
return TRUE
if(!mode && !active)
nif.notify("User Status: DAMAGED. Medichines performing minor repairs.",TRUE)
activate()
for(var/eo in nif.human.bad_external_organs)
var/obj/item/organ/external/EO = eo
for(var/w in EO.wounds)
var/datum/wound/W = w
if(W.damage <= 5)
W.heal_damage(0.1)
EO.update_damages()
if(EO.update_icon())
nif.human.UpdateDamageIcon(1)
nif.use_charge(0.1)
return TRUE //Return entirely, we only heal one at a time.
else if(mode == 1)
mode = 2
nif.notify("Medichines unable to repair all damage. Perform manual repairs.",TRUE)
/datum/nifsoft/medichines_syn/deactivate()
if((. = ..()))
mode = 0
/datum/nifsoft/medichines_syn/life()
if((. = ..()))
//We're good!
if(!nif.human.bad_external_organs.len)
if(mode || active)
nif.notify("User Status: NORMAL. Medichines deactivating.")
deactivate()
return TRUE
if(!mode && !active)
nif.notify("User Status: DAMAGED. Medichines performing minor repairs.",TRUE)
activate()
for(var/eo in nif.human.bad_external_organs)
var/obj/item/organ/external/EO = eo
for(var/w in EO.wounds)
var/datum/wound/W = w
if(W.damage <= 5)
W.heal_damage(0.1)
EO.update_damages()
if(EO.update_icon())
nif.human.UpdateDamageIcon(1)
nif.use_charge(0.1)
return TRUE //Return entirely, we only heal one at a time.
else if(mode == 1)
mode = 2
nif.notify("Medichines unable to repair all damage. Perform manual repairs.",TRUE)
return TRUE
/datum/nifsoft/spare_breath
name = "Respirocytes"
desc = "Nanites simulating red blood cells will filter and recycle oxygen for a short time, preventing suffocation in hostile environments. NOTE: Only capable of supplying OXYGEN."
@@ -137,47 +137,47 @@
var/filled = 100 //Tracks the internal tank 'refilling', which still uses power
health_flags = (NIF_H_SPAREBREATH)
activate()
if(!(filled > 50))
nif.notify("Respirocytes not saturated!",TRUE)
return FALSE
if((. = ..()))
nif.notify("Now taking air from reserves.")
/datum/nifsoft/spare_breath/activate()
if(!(filled > 50))
nif.notify("Respirocytes not saturated!",TRUE)
return FALSE
if((. = ..()))
nif.notify("Now taking air from reserves.")
deactivate()
if((. = ..()))
nif.notify("Now taking air from environment and refilling reserves.")
/datum/nifsoft/spare_breath/deactivate()
if((. = ..()))
nif.notify("Now taking air from environment and refilling reserves.")
life()
if((. = ..()))
if(active) //Supplying air, not recharging it
switch(filled) //Text warnings
if(75)
nif.notify("Respirocytes at 75% saturation.",TRUE)
if(50)
nif.notify("Respirocytes at 50% saturation!",TRUE)
if(25)
nif.notify("Respirocytes at 25% saturation, seek a habitable environment!",TRUE)
if(5)
nif.notify("Respirocytes at 5% saturation! Failure imminent!",TRUE)
/datum/nifsoft/spare_breath/life()
if((. = ..()))
if(active) //Supplying air, not recharging it
switch(filled) //Text warnings
if(75)
nif.notify("Respirocytes at 75% saturation.",TRUE)
if(50)
nif.notify("Respirocytes at 50% saturation!",TRUE)
if(25)
nif.notify("Respirocytes at 25% saturation, seek a habitable environment!",TRUE)
if(5)
nif.notify("Respirocytes at 5% saturation! Failure imminent!",TRUE)
if(filled == 0) //Ran out
deactivate()
else //Drain a little
filled--
if(filled == 0) //Ran out
deactivate()
else //Drain a little
filled--
else //Recharging air, not supplying it
if(filled == 100)
return TRUE
else if(nif.use_charge(0.1) && ++filled == 100)
nif.notify("Respirocytes now fully saturated.")
else //Recharging air, not supplying it
if(filled == 100)
return TRUE
else if(nif.use_charge(0.1) && ++filled == 100)
nif.notify("Respirocytes now fully saturated.")
proc/resp_breath()
if(!active) return null
var/datum/gas_mixture/breath = new(BREATH_VOLUME)
breath.adjust_gas("oxygen", BREATH_MOLES)
breath.temperature = T20C
return breath
/datum/nifsoft/spare_breath/proc/resp_breath()
if(!active) return null
var/datum/gas_mixture/breath = new(BREATH_VOLUME)
breath.adjust_gas("oxygen", BREATH_MOLES)
breath.temperature = T20C
return breath
/datum/nifsoft/mindbackup
name = "Mind Backup"
@@ -185,19 +185,19 @@
list_pos = NIF_BACKUP
cost = 125
activate()
if((. = ..()))
var/mob/living/carbon/human/H = nif.human
SStranscore.m_backup(H.mind,H.nif,one_time = TRUE)
persist_nif_data(H)
nif.notify("Mind backed up!")
nif.use_charge(0.1)
deactivate()
return TRUE
/datum/nifsoft/mindbackup/activate()
if((. = ..()))
var/mob/living/carbon/human/H = nif.human
SStranscore.m_backup(H.mind,H.nif,one_time = TRUE)
persist_nif_data(H)
nif.notify("Mind backed up!")
nif.use_charge(0.1)
deactivate()
return TRUE
deactivate()
if((. = ..()))
return TRUE
/datum/nifsoft/mindbackup/deactivate()
if((. = ..()))
return TRUE
stat_text()
return "Store Backup"
/datum/nifsoft/mindbackup/stat_text()
return "Store Backup"

View File

@@ -7,25 +7,25 @@
p_drain = 0.025
var/datum/tgui_module/crew_monitor/nif/arscreen
New()
..()
arscreen = new(nif)
/datum/nifsoft/crewmonitor/New()
..()
arscreen = new(nif)
Destroy()
QDEL_NULL(arscreen)
return ..()
/datum/nifsoft/crewmonitor/Destroy()
QDEL_NULL(arscreen)
return ..()
activate()
if((. = ..()))
arscreen.tgui_interact(nif.human)
return TRUE
/datum/nifsoft/crewmonitor/activate()
if((. = ..()))
arscreen.tgui_interact(nif.human)
return TRUE
deactivate()
if((. = ..()))
return TRUE
/datum/nifsoft/crewmonitor/deactivate()
if((. = ..()))
return TRUE
stat_text()
return "Show Monitor"
/datum/nifsoft/crewmonitor/stat_text()
return "Show Monitor"
/datum/nifsoft/alarmmonitor
name = "Alarm Monitor"
@@ -36,22 +36,22 @@
p_drain = 0.025
var/datum/tgui_module/alarm_monitor/engineering/nif/tgarscreen
New()
..()
tgarscreen = new(nif)
/datum/nifsoft/alarmmonitor/New()
..()
tgarscreen = new(nif)
Destroy()
QDEL_NULL(tgarscreen)
return ..()
/datum/nifsoft/alarmmonitor/Destroy()
QDEL_NULL(tgarscreen)
return ..()
activate()
if((. = ..()))
tgarscreen.tgui_interact(nif.human)
return TRUE
/datum/nifsoft/alarmmonitor/activate()
if((. = ..()))
tgarscreen.tgui_interact(nif.human)
return TRUE
deactivate()
if((. = ..()))
return TRUE
/datum/nifsoft/alarmmonitor/deactivate()
if((. = ..()))
return TRUE
stat_text()
return "Show Monitor"
/datum/nifsoft/alarmmonitor/stat_text()
return "Show Monitor"

View File

@@ -34,10 +34,10 @@
tick_flags = NIF_ACTIVETICK
combat_flags = (NIF_C_PAINKILLERS)
life()
if((. = ..()))
var/mob/living/carbon/human/H = nif.human
H.bloodstr.add_reagent("numbenzyme",0.5)
/datum/nifsoft/painkillers/life()
if((. = ..()))
var/mob/living/carbon/human/H = nif.human
H.bloodstr.add_reagent("numbenzyme",0.5)
/datum/nifsoft/hardclaws
name = "Bloodletters"
@@ -74,25 +74,25 @@ var/global/datum/unarmed_attack/hardclaws/unarmed_hardclaws = new()
var/used = FALSE
combat_flags = (NIF_C_HIDELASER)
activate()
if((. = ..()))
if(used)
nif.notify("You do not have a hidden weapon to deploy anymore!",TRUE)
deactivate()
return FALSE
if(!nif.use_charge(50))
nif.notify("Insufficient energy to deploy weapon!",TRUE)
deactivate()
return FALSE
/datum/nifsoft/hidelaser/activate()
if((. = ..()))
if(used)
nif.notify("You do not have a hidden weapon to deploy anymore!",TRUE)
deactivate()
return FALSE
if(!nif.use_charge(50))
nif.notify("Insufficient energy to deploy weapon!",TRUE)
deactivate()
return FALSE
var/mob/living/carbon/human/H = nif.human
H.adjustHalLoss(30)
var/obj/item/weapon/gun/energy/gun/martin/dazzle/dgun = new(get_turf(H))
H.put_in_hands(dgun)
nif.notify("Weapon deployed!",TRUE)
used = TRUE
spawn(0)
uninstall()
var/mob/living/carbon/human/H = nif.human
H.adjustHalLoss(30)
var/obj/item/weapon/gun/energy/gun/martin/dazzle/dgun = new(get_turf(H))
H.put_in_hands(dgun)
nif.notify("Weapon deployed!",TRUE)
used = TRUE
spawn(0)
uninstall()
//The gun to go with this implant
/obj/item/weapon/gun/energy/gun/martin/dazzle

View File

@@ -21,243 +21,243 @@
var/list/brainmobs = list()
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()
..()
load_settings()
/datum/nifsoft/soulcatcher/New()
..()
load_settings()
Destroy()
QDEL_LIST_NULL(brainmobs)
return ..()
/datum/nifsoft/soulcatcher/Destroy()
QDEL_LIST_NULL(brainmobs)
return ..()
activate()
if((. = ..()))
show_settings(nif.human)
spawn(0)
deactivate()
/datum/nifsoft/soulcatcher/activate()
if((. = ..()))
show_settings(nif.human)
spawn(0)
deactivate()
deactivate()
if((. = ..()))
return TRUE
stat_text()
return "Change Settings ([brainmobs.len] minds)"
install()
if((. = ..()))
nif.set_flag(NIF_O_SCOTHERS,NIF_FLAGS_OTHER) //Required on install, because other_flags aren't sufficient for our complicated settings.
nif.human.verbs |= /mob/living/carbon/human/proc/nsay
nif.human.verbs |= /mob/living/carbon/human/proc/nme
uninstall()
QDEL_LIST_NULL(brainmobs)
if((. = ..()) && nif && nif.human) //Sometimes NIFs are deleted outside of a human
nif.human.verbs -= /mob/living/carbon/human/proc/nsay
nif.human.verbs -= /mob/living/carbon/human/proc/nme
proc/save_settings()
if(!nif)
return
nif.save_data["[list_pos]"] = inside_flavor
/datum/nifsoft/soulcatcher/deactivate()
if((. = ..()))
return TRUE
proc/load_settings()
if(!nif)
return
var/load = nif.save_data["[list_pos]"]
if(load)
inside_flavor = load
return TRUE
/datum/nifsoft/soulcatcher/stat_text()
return "Change Settings ([brainmobs.len] minds)"
proc/notify_into(var/message)
var/sound = nif.good_sound
/datum/nifsoft/soulcatcher/install()
if((. = ..()))
nif.set_flag(NIF_O_SCOTHERS,NIF_FLAGS_OTHER) //Required on install, because other_flags aren't sufficient for our complicated settings.
nif.human.verbs |= /mob/living/carbon/human/proc/nsay
nif.human.verbs |= /mob/living/carbon/human/proc/nme
to_chat(nif.human,"<b>\[[bicon(nif.big_icon)]NIF\]</b> <b>Soulcatcher</b> displays, \"<span class='notice nif'>[message]</span>\"")
nif.human << sound
/datum/nifsoft/soulcatcher/uninstall()
QDEL_LIST_NULL(brainmobs)
if((. = ..()) && nif && nif.human) //Sometimes NIFs are deleted outside of a human
nif.human.verbs -= /mob/living/carbon/human/proc/nsay
nif.human.verbs -= /mob/living/carbon/human/proc/nme
/datum/nifsoft/soulcatcher/proc/save_settings()
if(!nif)
return
nif.save_data["[list_pos]"] = inside_flavor
return TRUE
/datum/nifsoft/soulcatcher/proc/load_settings()
if(!nif)
return
var/load = nif.save_data["[list_pos]"]
if(load)
inside_flavor = load
return TRUE
/datum/nifsoft/soulcatcher/proc/notify_into(var/message)
var/sound = nif.good_sound
to_chat(nif.human,"<b>\[[bicon(nif.big_icon)]NIF\]</b> <b>Soulcatcher</b> displays, \"<span class='notice nif'>[message]</span>\"")
nif.human << sound
for(var/brainmob in brainmobs)
var/mob/living/carbon/brain/caught_soul/CS = brainmob
to_chat(CS,"<b>\[[bicon(nif.big_icon)]NIF\]</b> <b>Soulcatcher</b> displays, \"<span class='notice nif'>[message]</span>\"")
brainmob << sound
/datum/nifsoft/soulcatcher/proc/say_into(var/message, var/mob/living/sender, var/mob/eyeobj)
var/sender_name = eyeobj ? eyeobj.name : sender.name
//AR Projecting
if(eyeobj)
sender.eyeobj.visible_message("<b>[sender_name]</b> says, \"[message]\"")
//Not AR Projecting
else
to_chat(nif.human,"<span class='game say nif'><b>\[[bicon(nif.big_icon)]NIF\]</b> <b>[sender_name]</b> speaks, \"[message]\"</span>")
for(var/brainmob in brainmobs)
var/mob/living/carbon/brain/caught_soul/CS = brainmob
to_chat(CS,"<b>\[[bicon(nif.big_icon)]NIF\]</b> <b>Soulcatcher</b> displays, \"<span class='notice nif'>[message]</span>\"")
brainmob << sound
to_chat(CS,"<span class='game say nif'><b>\[[bicon(nif.big_icon)]NIF\]</b> <b>[sender_name]</b> speaks, \"[message]\"</span>")
proc/say_into(var/message, var/mob/living/sender, var/mob/eyeobj)
var/sender_name = eyeobj ? eyeobj.name : sender.name
log_nsay(message,nif.human.real_name,sender)
//AR Projecting
if(eyeobj)
sender.eyeobj.visible_message("<b>[sender_name]</b> says, \"[message]\"")
/datum/nifsoft/soulcatcher/proc/emote_into(var/message, var/mob/living/sender, var/mob/eyeobj)
var/sender_name = eyeobj ? eyeobj.name : sender.name
//Not AR Projecting
else
to_chat(nif.human,"<span class='game say nif'><b>\[[bicon(nif.big_icon)]NIF\]</b> <b>[sender_name]</b> speaks, \"[message]\"</span>")
for(var/brainmob in brainmobs)
var/mob/living/carbon/brain/caught_soul/CS = brainmob
to_chat(CS,"<span class='game say nif'><b>\[[bicon(nif.big_icon)]NIF\]</b> <b>[sender_name]</b> speaks, \"[message]\"</span>")
//AR Projecting
if(eyeobj)
sender.eyeobj.visible_message("[sender_name] [message]")
log_nsay(message,nif.human.real_name,sender)
//Not AR Projecting
else
to_chat(nif.human,"<span class='emote nif'><b>\[[bicon(nif.big_icon)]NIF\]</b> <b>[sender_name]</b> [message]</span>")
for(var/brainmob in brainmobs)
var/mob/living/carbon/brain/caught_soul/CS = brainmob
to_chat(CS,"<span class='emote nif'><b>\[[bicon(nif.big_icon)]NIF\]</b> <b>[sender_name]</b> [message]</span>")
proc/emote_into(var/message, var/mob/living/sender, var/mob/eyeobj)
var/sender_name = eyeobj ? eyeobj.name : sender.name
log_nme(message,nif.human.real_name,sender)
//AR Projecting
if(eyeobj)
sender.eyeobj.visible_message("[sender_name] [message]")
/datum/nifsoft/soulcatcher/proc/show_settings(var/mob/living/carbon/human/H)
set waitfor = FALSE
var/settings_list = list(
"Catching You \[[setting_flags & NIF_SC_CATCHING_ME ? "Enabled" : "Disabled"]\]" = NIF_SC_CATCHING_ME,
"Catching Prey \[[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,
"Mind Backups \[[setting_flags & NIF_SC_BACKUPS ? "Enabled" : "Disabled"]\]" = NIF_SC_BACKUPS,
"AR Projecting \[[setting_flags & NIF_SC_PROJECTING ? "Enabled" : "Disabled"]\]" = NIF_SC_PROJECTING,
"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)
//Not AR Projecting
else
to_chat(nif.human,"<span class='emote nif'><b>\[[bicon(nif.big_icon)]NIF\]</b> <b>[sender_name]</b> [message]</span>")
for(var/brainmob in brainmobs)
var/mob/living/carbon/brain/caught_soul/CS = brainmob
to_chat(CS,"<span class='emote nif'><b>\[[bicon(nif.big_icon)]NIF\]</b> <b>[sender_name]</b> [message]</span>")
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, MAX_MESSAGE_LEN*2)
inside_flavor = new_flavor
nif.notify("Updating VR environment...")
for(var/brain in brainmobs)
var/mob/living/carbon/brain/caught_soul/CS = brain
to_chat(CS,"<span class='notice'>Your surroundings change to...</span>\n[inside_flavor]")
save_settings()
return TRUE
log_nme(message,nif.human.real_name,sender)
if("Erase Contents")
var/mob/living/carbon/brain/caught_soul/brainpick = input(nif.human,"Select a mind to delete:","Erase Mind") as null|anything in brainmobs
proc/show_settings(var/mob/living/carbon/human/H)
set waitfor = FALSE
var/settings_list = list(
"Catching You \[[setting_flags & NIF_SC_CATCHING_ME ? "Enabled" : "Disabled"]\]" = NIF_SC_CATCHING_ME,
"Catching Prey \[[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,
"Mind Backups \[[setting_flags & NIF_SC_BACKUPS ? "Enabled" : "Disabled"]\]" = NIF_SC_BACKUPS,
"AR Projecting \[[setting_flags & NIF_SC_PROJECTING ? "Enabled" : "Disabled"]\]" = NIF_SC_PROJECTING,
"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)
var/warning = alert(nif.human,"Are you SURE you want to erase \"[brainpick]\"?","Erase Mind","CANCEL","DELETE","CANCEL")
if(warning == "DELETE")
brainmobs -= brainpick
qdel(brainpick)
return TRUE
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, MAX_MESSAGE_LEN*2)
inside_flavor = new_flavor
nif.notify("Updating VR environment...")
for(var/brain in brainmobs)
var/mob/living/carbon/brain/caught_soul/CS = brain
to_chat(CS,"<span class='notice'>Your surroundings change to...</span>\n[inside_flavor]")
save_settings()
return TRUE
//Must just be a flag without special handling then.
else
var/flag = settings_list[choice]
return toggle_setting(flag)
if("Erase Contents")
var/mob/living/carbon/brain/caught_soul/brainpick = input(nif.human,"Select a mind to delete:","Erase Mind") as null|anything in brainmobs
/datum/nifsoft/soulcatcher/proc/toggle_setting(var/flag)
setting_flags ^= flag
var/warning = alert(nif.human,"Are you SURE you want to erase \"[brainpick]\"?","Erase Mind","CANCEL","DELETE","CANCEL")
if(warning == "DELETE")
brainmobs -= brainpick
qdel(brainpick)
return TRUE
var/notify_message
//Special treatment
switch(flag)
if(NIF_SC_BACKUPS)
if(setting_flags & NIF_SC_BACKUPS)
notify_message = "Mind backup system enabled."
else
notify_message = "Mind backup system disabled."
//Must just be a flag without special handling then.
else
var/flag = settings_list[choice]
return toggle_setting(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)
for(var/brain in brainmobs)
var/mob/living/carbon/brain/caught_soul/brainmob = brain
brainmob.ext_deaf = FALSE
notify_message = "External audio input enabled."
else
for(var/brain in brainmobs)
var/mob/living/carbon/brain/caught_soul/brainmob = brain
brainmob.ext_deaf = TRUE
notify_message = "External audio input disabled."
if(NIF_SC_ALLOW_EYES)
if(setting_flags & NIF_SC_ALLOW_EYES)
for(var/brain in brainmobs)
var/mob/living/carbon/brain/caught_soul/brainmob = brain
brainmob.ext_blind = FALSE
notify_message = "External video input enabled."
else
for(var/brain in brainmobs)
var/mob/living/carbon/brain/caught_soul/brainmob = brain
brainmob.ext_blind = TRUE
notify_message = "External video input disabled."
proc/toggle_setting(var/flag)
setting_flags ^= flag
if(notify_message)
notify_into(notify_message)
var/notify_message
//Special treatment
switch(flag)
if(NIF_SC_BACKUPS)
if(setting_flags & NIF_SC_BACKUPS)
notify_message = "Mind backup system enabled."
else
notify_message = "Mind backup system disabled."
return TRUE
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)
for(var/brain in brainmobs)
var/mob/living/carbon/brain/caught_soul/brainmob = brain
brainmob.ext_deaf = FALSE
notify_message = "External audio input enabled."
else
for(var/brain in brainmobs)
var/mob/living/carbon/brain/caught_soul/brainmob = brain
brainmob.ext_deaf = TRUE
notify_message = "External audio input disabled."
if(NIF_SC_ALLOW_EYES)
if(setting_flags & NIF_SC_ALLOW_EYES)
for(var/brain in brainmobs)
var/mob/living/carbon/brain/caught_soul/brainmob = brain
brainmob.ext_blind = FALSE
notify_message = "External video input enabled."
else
for(var/brain in brainmobs)
var/mob/living/carbon/brain/caught_soul/brainmob = brain
brainmob.ext_blind = TRUE
notify_message = "External video input disabled."
//Complex version for catching in-round characters
/datum/nifsoft/soulcatcher/proc/catch_mob(var/mob/M)
if(!M.mind) return
if(notify_message)
notify_into(notify_message)
//Create a new brain mob
var/mob/living/carbon/brain/caught_soul/brainmob = new(nif)
brainmob.nif = nif
brainmob.soulcatcher = src
brainmob.container = src
brainmob.stat = 0
brainmob.silent = FALSE
dead_mob_list -= brainmob
brainmob.add_language(LANGUAGE_GALCOM)
brainmobs |= brainmob
return TRUE
//Put the mind and player into the mob
M.mind.transfer_to(brainmob)
brainmob.name = brainmob.mind.name
brainmob.real_name = brainmob.mind.name
//Complex version for catching in-round characters
proc/catch_mob(var/mob/M)
if(!M.mind) return
//If we caught our owner, special settings.
if(M == nif.human)
brainmob.ext_deaf = FALSE
brainmob.ext_blind = FALSE
brainmob.parent_mob = TRUE
//Create a new brain mob
var/mob/living/carbon/brain/caught_soul/brainmob = new(nif)
brainmob.nif = nif
brainmob.soulcatcher = src
brainmob.container = src
brainmob.stat = 0
brainmob.silent = FALSE
dead_mob_list -= brainmob
brainmob.add_language(LANGUAGE_GALCOM)
brainmobs |= brainmob
//If they have these values, apply them
if(ishuman(M))
var/mob/living/carbon/human/H = M
brainmob.dna = H.dna
brainmob.ooc_notes = H.ooc_notes
brainmob.timeofhostdeath = H.timeofdeath
SStranscore.m_backup(brainmob.mind,0) //It does ONE, so medical will hear about it.
//Put the mind and player into the mob
M.mind.transfer_to(brainmob)
brainmob.name = brainmob.mind.name
brainmob.real_name = brainmob.mind.name
//Else maybe they're a joining ghost
else if(isobserver(M))
brainmob.transient = TRUE
qdel(M) //Bye ghost
//If we caught our owner, special settings.
if(M == nif.human)
brainmob.ext_deaf = FALSE
brainmob.ext_blind = FALSE
brainmob.parent_mob = TRUE
//Give them a flavortext message
var/message = "<span class='notice'>Your vision fades in a haze of static, before returning.</span>\n\
Around you, you see...\n\
[inside_flavor]"
//If they have these values, apply them
if(ishuman(M))
var/mob/living/carbon/human/H = M
brainmob.dna = H.dna
brainmob.ooc_notes = H.ooc_notes
brainmob.timeofhostdeath = H.timeofdeath
SStranscore.m_backup(brainmob.mind,0) //It does ONE, so medical will hear about it.
to_chat(brainmob,message)
//Else maybe they're a joining ghost
else if(isobserver(M))
brainmob.transient = TRUE
qdel(M) //Bye ghost
//Reminder on how this works to host
if(brainmobs.len == 1) //Only spam this on the first one
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 using the NSay and NMe verbs (or the *nsay and *nme emotes).</span>")
//Give them a flavortext message
var/message = "<span class='notice'>Your vision fades in a haze of static, before returning.</span>\n\
Around you, you see...\n\
[inside_flavor]"
to_chat(brainmob,message)
//Reminder on how this works to host
if(brainmobs.len == 1) //Only spam this on the first one
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 using the NSay and NMe verbs (or the *nsay and *nme emotes).</span>")
//Announce to host and other minds
notify_into("New mind loaded: [brainmob.name]")
return TRUE
//Announce to host and other minds
notify_into("New mind loaded: [brainmob.name]")
return TRUE
////////////////
//The caught mob

View File

@@ -9,24 +9,24 @@
p_drain = 0.01
other_flags = (NIF_O_COMMLINK)
install()
if((. = ..()))
nif.comm = new(nif,src)
/datum/nifsoft/commlink/install()
if((. = ..()))
nif.comm = new(nif,src)
uninstall()
var/obj/item/device/nif/lnif = nif //Awkward. Parent clears it in an attempt to clean up.
if((. = ..()) && lnif)
QDEL_NULL(lnif.comm)
/datum/nifsoft/commlink/uninstall()
var/obj/item/device/nif/lnif = nif //Awkward. Parent clears it in an attempt to clean up.
if((. = ..()) && lnif)
QDEL_NULL(lnif.comm)
activate()
if((. = ..()))
nif.comm.initialize_exonet(nif.human)
nif.comm.ui_interact(nif.human,key_state = commlink_state)
spawn(0)
deactivate()
/datum/nifsoft/commlink/activate()
if((. = ..()))
nif.comm.initialize_exonet(nif.human)
nif.comm.ui_interact(nif.human,key_state = commlink_state)
spawn(0)
deactivate()
stat_text()
return "Show Commlink"
/datum/nifsoft/commlink/stat_text()
return "Show Commlink"
/datum/nifsoft/commlink/Topic(href, href_list)
if(href_list["open"])
@@ -39,18 +39,18 @@
var/obj/item/device/nif/nif
var/datum/nifsoft/commlink/nifsoft
New(var/newloc,var/soft)
..()
nif = newloc
nifsoft = soft
QDEL_NULL(camera) //Not supported on internal one.
/obj/item/device/communicator/commlink/New(var/newloc,var/soft)
..()
nif = newloc
nifsoft = soft
QDEL_NULL(camera) //Not supported on internal one.
Destroy()
if(nif)
nif.comm = null
nif = null
nifsoft = null
return ..()
/obj/item/device/communicator/commlink/Destroy()
if(nif)
nif.comm = null
nif = null
nifsoft = null
return ..()
/obj/item/device/communicator/commlink/register_device(var/new_name)
owner = new_name

View File

@@ -9,36 +9,36 @@
var/obj/machinery/power/apc/apc
other_flags = (NIF_O_APCCHARGE)
activate()
if((. = ..()))
var/mob/living/carbon/human/H = nif.human
apc = locate(/obj/machinery/power/apc) in get_step(H,H.dir)
if(!apc)
apc = locate(/obj/machinery/power/apc) in get_step(H,0)
if(!apc)
nif.notify("You must be facing an APC to connect to.",TRUE)
spawn(0)
deactivate()
return FALSE
H.visible_message("<span class='warning'>Thin snakelike tendrils grow from [H] and connect to \the [apc].</span>","<span class='notice'>Thin snakelike tendrils grow from you and connect to \the [apc].</span>")
deactivate()
if((. = ..()))
apc = null
life()
if((. = ..()))
var/mob/living/carbon/human/H = nif.human
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
else
nif.notify("APC charging has ended.")
H.visible_message("<span class='warning'>[H]'s snakelike tendrils whip back into their body from \the [apc].</span>","<span class='notice'>The APC connector tendrils return to your body.</span>")
/datum/nifsoft/apc_recharge/activate()
if((. = ..()))
var/mob/living/carbon/human/H = nif.human
apc = locate(/obj/machinery/power/apc) in get_step(H,H.dir)
if(!apc)
apc = locate(/obj/machinery/power/apc) in get_step(H,0)
if(!apc)
nif.notify("You must be facing an APC to connect to.",TRUE)
spawn(0)
deactivate()
return FALSE
return FALSE
H.visible_message("<span class='warning'>Thin snakelike tendrils grow from [H] and connect to \the [apc].</span>","<span class='notice'>Thin snakelike tendrils grow from you and connect to \the [apc].</span>")
/datum/nifsoft/apc_recharge/deactivate()
if((. = ..()))
apc = null
/datum/nifsoft/apc_recharge/life()
if((. = ..()))
var/mob/living/carbon/human/H = nif.human
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
else
nif.notify("APC charging has ended.")
H.visible_message("<span class='warning'>[H]'s snakelike tendrils whip back into their body from \the [apc].</span>","<span class='notice'>The APC connector tendrils return to your body.</span>")
deactivate()
return FALSE
/datum/nifsoft/pressure
name = "Pressure Seals"
@@ -62,31 +62,31 @@
applies_to = NIF_SYNTHETIC
other_flags = (NIF_O_HEATSINKS)
activate()
if((. = ..()))
if(used >= 1500)
nif.notify("Heat sinks not safe to operate again yet! Max 75% on activation.",TRUE)
spawn(0)
deactivate()
return FALSE
stat_text()
return "[active ? "Active" : "Disabled"] (Stored Heat: [FLOOR((used/20), 1)]%)"
life()
if((. = ..()))
//Not being used, all clean.
if(!active && !used)
return TRUE
//Being used, and running out.
else if(active && ++used == 2000)
nif.notify("Heat sinks overloaded! Shutting down!",TRUE)
/datum/nifsoft/heatsinks/activate()
if((. = ..()))
if(used >= 1500)
nif.notify("Heat sinks not safe to operate again yet! Max 75% on activation.",TRUE)
spawn(0)
deactivate()
return FALSE
//Being cleaned, and finishing empty.
else if(!active && --used == 0)
nif.notify("Heat sinks re-chilled.")
/datum/nifsoft/heatsinks/stat_text()
return "[active ? "Active" : "Disabled"] (Stored Heat: [FLOOR((used/20), 1)]%)"
/datum/nifsoft/heatsinks/life()
if((. = ..()))
//Not being used, all clean.
if(!active && !used)
return TRUE
//Being used, and running out.
else if(active && ++used == 2000)
nif.notify("Heat sinks overloaded! Shutting down!",TRUE)
deactivate()
//Being cleaned, and finishing empty.
else if(!active && --used == 0)
nif.notify("Heat sinks re-chilled.")
/datum/nifsoft/compliance
name = "Compliance Module"
@@ -99,24 +99,24 @@
access = 999 //Prevents anyone from buying it without an emag.
var/laws = "Be nice to people!"
New(var/newloc,var/newlaws)
laws = newlaws //Sanitize before this (the disk does)
..(newloc)
/datum/nifsoft/compliance/New(var/newloc,var/newlaws)
laws = newlaws //Sanitize before this (the disk does)
..(newloc)
activate()
if((. = ..()))
to_chat(nif.human,"<span class='danger'>You are compelled to follow these rules: </span>\n<span class='notify'>[laws]</span>")
/datum/nifsoft/compliance/activate()
if((. = ..()))
to_chat(nif.human,"<span class='danger'>You are compelled to follow these rules: </span>\n<span class='notify'>[laws]</span>")
install()
if((. = ..()))
to_chat(nif.human,"<span class='danger'>You feel suddenly compelled to follow these rules: </span>\n<span class='notify'>[laws]</span>")
/datum/nifsoft/compliance/install()
if((. = ..()))
to_chat(nif.human,"<span class='danger'>You feel suddenly compelled to follow these rules: </span>\n<span class='notify'>[laws]</span>")
uninstall()
nif.notify("ERROR! Unable to comply!",TRUE)
return FALSE //NOPE.
/datum/nifsoft/compliance/uninstall()
nif.notify("ERROR! Unable to comply!",TRUE)
return FALSE //NOPE.
stat_text()
return "Show Laws"
/datum/nifsoft/compliance/stat_text()
return "Show Laws"
/datum/nifsoft/sizechange
name = "Mass Alteration"
@@ -125,28 +125,28 @@
cost = 375
wear = 6
activate()
if((. = ..()))
var/new_size = input("Put the desired size (25-200%)", "Set Size", 200) as num
/datum/nifsoft/sizechange/activate()
if((. = ..()))
var/new_size = input("Put the desired size (25-200%)", "Set Size", 200) as num
if (!ISINRANGE(new_size,25,200))
to_chat(nif.human,"<span class='notice'>The safety features of the NIF Program prevent you from choosing this size.</span>")
return
else
nif.human.resize(new_size/100)
to_chat(nif.human,"<span class='notice'>You set the size to [new_size]%</span>")
if (!ISINRANGE(new_size,25,200))
to_chat(nif.human,"<span class='notice'>The safety features of the NIF Program prevent you from choosing this size.</span>")
return
else
nif.human.resize(new_size/100)
to_chat(nif.human,"<span class='notice'>You set the size to [new_size]%</span>")
nif.human.visible_message("<span class='warning'>Swirling grey mist envelops [nif.human] as they change size!</span>","<span class='notice'>Swirling streams of nanites wrap around you as you change size!</span>")
nif.human.visible_message("<span class='warning'>Swirling grey mist envelops [nif.human] as they change size!</span>","<span class='notice'>Swirling streams of nanites wrap around you as you change size!</span>")
spawn(0)
deactivate()
spawn(0)
deactivate()
deactivate()
if((. = ..()))
return TRUE
/datum/nifsoft/sizechange/deactivate()
if((. = ..()))
return TRUE
stat_text()
return "Change Size"
/datum/nifsoft/sizechange/stat_text()
return "Change Size"
/datum/nifsoft/worldbend
name = "World Bender"
@@ -155,22 +155,22 @@
cost = 100
a_drain = 0.01
activate()
if((. = ..()))
var/list/justme = list(nif.human)
for(var/human in human_mob_list)
if(human == nif.human)
continue
var/mob/living/carbon/human/H = human
H.display_alt_appearance("animals", justme)
alt_farmanimals += nif.human
/datum/nifsoft/worldbend/activate()
if((. = ..()))
var/list/justme = list(nif.human)
for(var/human in human_mob_list)
if(human == nif.human)
continue
var/mob/living/carbon/human/H = human
H.display_alt_appearance("animals", justme)
alt_farmanimals += nif.human
deactivate()
if((. = ..()))
var/list/justme = list(nif.human)
for(var/human in human_mob_list)
if(human == nif.human)
continue
var/mob/living/carbon/human/H = human
H.hide_alt_appearance("animals", justme)
alt_farmanimals -= nif.human
/datum/nifsoft/worldbend/deactivate()
if((. = ..()))
var/list/justme = list(nif.human)
for(var/human in human_mob_list)
if(human == nif.human)
continue
var/mob/living/carbon/human/H = human
H.hide_alt_appearance("animals", justme)
alt_farmanimals -= nif.human

View File

@@ -16,6 +16,21 @@ GLOBAL_DATUM_INIT(tgui_nif_state, /datum/tgui_state/nif_state, new)
return STATUS_CLOSE
// This is slightly distinct from the module state, as it wants to update if not working
GLOBAL_DATUM_INIT(tgui_nif_main_state, /datum/tgui_state/nif_main_state, new)
/datum/tgui_state/nif_main_state/can_use_topic(var/src_object, var/mob/user)
if(ishuman(user))
var/mob/living/carbon/human/H = user
if(!H.nif || src_object != H.nif)
return STATUS_CLOSE
if(H.nif.stat == NIF_WORKING)
return user.shared_tgui_interaction()
else
return min(user.shared_tgui_interaction(), STATUS_UPDATE)
return STATUS_CLOSE
GLOBAL_DATUM_INIT(tgui_commlink_state, /datum/tgui_state/commlink_state, new)
/datum/tgui_state/commlink_state/can_use_topic(var/src_object, var/mob/user)
if(ishuman(user))

View File

@@ -0,0 +1,255 @@
import { round } from 'common/math';
import { Fragment } from 'inferno';
import { useBackend, useLocalState } from "../backend";
import { Box, Button, Flex, Icon, LabeledList, ProgressBar, Modal, Section, Dropdown, AnimatedNumber, NoticeBox, Table } from "../components";
import { Window } from "../layouts";
const NIF_WORKING = 0;
const NIF_POWFAIL = 1;
const NIF_TEMPFAIL = 2;
const NIF_INSTALLING = 3;
const NIF_PREINSTALL = 4;
const validThemes = [
"abductor",
"cardtable",
"hackerman",
"malfunction",
"ntos",
"paper",
"retro",
"syndicate",
];
export const NIF = (props, context) => {
const { act, config, data } = useBackend(context);
const {
theme,
last_notification,
} = data;
const [settingsOpen, setSettingsOpen] = useLocalState(context, "settingsOpen", false);
const [viewingModule, setViewing] = useLocalState(context, "viewingModule", null);
return (
<Window theme={theme} width={500} height={400} resizable>
<Window.Content scrollable>
{!!last_notification && (
<NoticeBox info>
<Table verticalAlign="middle">
<Table.Row verticalAlign="middle">
<Table.Cell verticalAlign="middle">{last_notification}</Table.Cell>
<Table.Cell verticalAlign="middle" collapsing>
<Button
color="red"
icon="times"
tooltip="Dismiss"
tooltipPosition="left"
onClick={() => act("dismissNotification")} />
</Table.Cell>
</Table.Row>
</Table>
</NoticeBox>
)}
{!!viewingModule && (
<Modal m={1} p={0} color="label">
<Section m={0} title={viewingModule.name} buttons={
<Fragment>
<Button.Confirm
icon="ban"
color="bad"
content="Uninstall"
confirmIcon="ban"
confirmContent={"Uninstall " + viewingModule.name + "?"}
onClick={() => {
act("uninstall", { module: viewingModule.ref });
setViewing(null);
}} />
<Button
icon="window-close"
onClick={() => setViewing(null)} />
</Fragment>
}>
<Box>{viewingModule.desc}</Box>
<Box>
It consumes <Box color="good" inline>{viewingModule.p_drain}</Box> energy units while installed,
and <Box color="average" inline>{viewingModule.a_drain}</Box> additionally while active.
</Box>
<Box color={viewingModule.illegal ? "bad" : "good"}>
It is {viewingModule.illegal ? "NOT " : ""}
a legal software package.
</Box>
<Box>
The MSRP of the package is <Box color="good" inline>{viewingModule.cost}.</Box>
</Box>
<Box>
The difficulty to construct the associated implant is&nbsp;
<Box color="good" inline>Rating {viewingModule.wear}</Box>.
</Box>
</Section>
</Modal>
)}
<Section title={"Welcome to your NIF, " + config.user.name} buttons={
<Button
icon="cogs"
tooltip="Settings"
tooltipPosition="bottom-left"
selected={settingsOpen}
onClick={() => setSettingsOpen(!settingsOpen)} />
}>
{settingsOpen && <NIFSettings /> || <NIFMain setViewing={setViewing} />}
</Section>
</Window.Content>
</Window>
);
};
const getNifCondition = (nif_stat, nif_percent) => {
switch (nif_stat) {
case NIF_WORKING:
if (nif_percent < 25) {
return "Service Needed Soon";
} else {
return "Operating Normally";
}
break;
case NIF_POWFAIL:
return "Insufficient Energy!";
break;
case NIF_TEMPFAIL:
return "System Failure!";
break;
case NIF_INSTALLING:
return "Adapting To User";
break;
}
return "Unknown";
};
const getNutritionText = (nutrition, isSynthetic) => {
if (isSynthetic) {
if (nutrition >= 450) {
return "Overcharged";
} else if (nutrition >= 250) {
return "Good Charge";
}
return "Low Charge";
}
if (nutrition >= 250) {
return "NIF Power Requirement met.";
} else if (nutrition >= 150) {
return "Fluctuations in available power.";
}
return "Power failure imminent.";
};
const NIFMain = (props, context) => {
const { act, config, data } = useBackend(context);
const {
nif_percent,
nif_stat,
last_notification,
nutrition,
isSynthetic,
modules,
} = data;
const {
setViewing,
} = props;
return (
<Box>
<LabeledList>
<LabeledList.Item label="NIF Condition">
<ProgressBar
value={nif_percent}
minValue={0}
maxValue={100}
ranges={{
good: [50, Infinity],
average: [25, 50],
bad: [-Infinity, 0],
}}>
{getNifCondition(nif_stat, nif_percent)} (<AnimatedNumber value={nif_percent} />%)
</ProgressBar>
</LabeledList.Item>
<LabeledList.Item label={"NIF Power"}>
<ProgressBar
value={nutrition}
minValue={0}
maxValue={700}
ranges={{
good: [250, Infinity],
average: [150, 250],
bad: [0, 150],
}}>
{getNutritionText(nutrition, isSynthetic)}
</ProgressBar>
</LabeledList.Item>
</LabeledList>
<Section level={2} title="NIFSoft Modules" mt={1}>
<LabeledList>
{modules.map(module => (
<LabeledList.Item
label={module.name}
key={module.ref}
buttons={
<Fragment>
<Button.Confirm
icon="trash"
color="bad"
confirmContent="UNINSTALL?"
confirmIcon="trash"
tooltip="Uninstall Module"
tooltipPosition="left"
onClick={() => act("uninstall", { module: module.ref })} />
<Button
icon="search"
onClick={() => setViewing(module)}
tooltip="View Information"
tooltipPosition="left" />
</Fragment>
}>
{module.activates && (
<Button
fluid
selected={module.active}
content={module.stat_text}
onClick={() => act("toggle_module", { module: module.ref })} />
) || (
<Box>
{module.stat_text}
</Box>
)}
</LabeledList.Item>
))}
</LabeledList>
</Section>
</Box>
);
};
const NIFSettings = (props, context) => {
const { act, data } = useBackend(context);
const {
theme,
} = data;
return (
<LabeledList>
<LabeledList.Item label="NIF Theme" verticalAlign="top">
<Dropdown
width="100%"
placeholder="Default"
selected={theme}
options={validThemes}
onSelected={val => act("setTheme", { theme: val })} />
</LabeledList.Item>
</LabeledList>
);
};

File diff suppressed because one or more lines are too long

View File

@@ -2963,6 +2963,7 @@
#include "code\modules\nifsoft\nif.dm"
#include "code\modules\nifsoft\nif_softshop.dm"
#include "code\modules\nifsoft\nif_statpanel.dm"
#include "code\modules\nifsoft\nif_tgui.dm"
#include "code\modules\nifsoft\nifsoft.dm"
#include "code\modules\nifsoft\software\01_vision.dm"
#include "code\modules\nifsoft\software\05_health.dm"