diff --git a/code/__defines/nifsoft.dm b/code/__defines/nifsoft.dm index e4d4f12293..06d1b0c7aa 100644 --- a/code/__defines/nifsoft.dm +++ b/code/__defines/nifsoft.dm @@ -16,27 +16,29 @@ #define NIF_UVFILTER 12 #define NIF_FLASHPROT 13 //Health-related -#define NIF_ORGANIC_HEAL 14 -#define NIF_SYNTH_HEAL 15 -#define NIF_AUTOSTASIS 16 //These two are just part of -#define NIF_MED_ALARM 17 //medichines right now -#define NIF_TOXHEAL 18 -#define NIF_SPAREBREATH 19 +#define NIF_CREWMONITOR 14 +#define NIF_ORGANIC_HEAL 15 +#define NIF_SYNTH_HEAL 16 +#define NIF_AUTOSTASIS 17 //These two are just part of +#define NIF_MED_ALARM 18 //medichines right now +#define NIF_TOXHEAL 19 //And this, for organics +#define NIF_SPAREBREATH 20 //Combat Related -#define NIF_BRUTEARMOR 20 -#define NIF_BURNARMOR 21 -#define NIF_PAINKILLERS 22 -#define NIF_HARDCLAWS 23 -#define NIF_HIDDENLASER 24 +#define NIF_BRUTEARMOR 21 +#define NIF_BURNARMOR 22 +#define NIF_PAINKILLERS 23 +#define NIF_HARDCLAWS 24 +#define NIF_HIDDENLASER 25 //Other -#define NIF_COMMLINK 25 -#define NIF_SUITSENSORS 26 +#define NIF_COMMLINK 26 #define NIF_APCCHARGE 27 #define NIF_PRESSURE 28 #define NIF_HEATSINK 29 +#define NIF_COMPLIANCE 30 +#define NIF_SIZECHANGE 31 // Must be equal to the highest number above -#define TOTAL_NIF_SOFTWARE 29 +#define TOTAL_NIF_SOFTWARE 31 ////////////////////// // NIF flag list hints @@ -78,10 +80,9 @@ //Other #define NIF_O_COMMLINK 0x1 -#define NIF_O_SENSORS 0x2 -#define NIF_O_APCCHARGE 0x4 -#define NIF_O_PRESSURESEAL 0x8 -#define NIF_O_HEATSINKS 0x10 +#define NIF_O_APCCHARGE 0x2 +#define NIF_O_PRESSURESEAL 0x4 +#define NIF_O_HEATSINKS 0x8 /////////////////// // applies_to flags diff --git a/code/game/objects/structures/trash_pile.dm b/code/game/objects/structures/trash_pile.dm index 5490251280..0959f93004 100644 --- a/code/game/objects/structures/trash_pile.dm +++ b/code/game/objects/structures/trash_pile.dm @@ -225,7 +225,8 @@ prob(4);/obj/item/device/radio_jammer, prob(2);/obj/item/weapon/storage/box/syndie_kit/spy, prob(2);/obj/item/weapon/grenade/anti_photon, - prob(1);/obj/item/weapon/cell/hyper/empty) + prob(1);/obj/item/weapon/cell/hyper/empty, + prob(1);/obj/item/weapon/disk/nifsoft/compliance) var/obj/item/I = new path() return I diff --git a/code/modules/client/preference_setup/vore/08_nif.dm b/code/modules/client/preference_setup/vore/08_nif.dm new file mode 100644 index 0000000000..52586d3bcf --- /dev/null +++ b/code/modules/client/preference_setup/vore/08_nif.dm @@ -0,0 +1,45 @@ +//Pretty small file, mostly just for storage. +/datum/preferences + var/obj/item/device/nif/nif_path + var/nif_durability + +// Definition of the stuff for NIFs +/datum/category_item/player_setup_item/vore/nif + name = "NIF Data" + sort_order = 8 + +/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 + +/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 + +/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. + pref.nif_path = text2path(pref.nif_path) //Try to convert it to a hard path. + if(!pref.nif_path) //If we couldn't, kill it. + 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? + 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]") + +/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) + + //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 + 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]" + save_character(S) + +/datum/category_item/player_setup_item/vore/nif/content(var/mob/user) + . += "NIF: [ispath(pref.nif_path) ? "Present" : "None"]" diff --git a/code/modules/mob/living/carbon/human/human_attackhand.dm b/code/modules/mob/living/carbon/human/human_attackhand.dm index 3af1a52bf6..b321d288fb 100644 --- a/code/modules/mob/living/carbon/human/human_attackhand.dm +++ b/code/modules/mob/living/carbon/human/human_attackhand.dm @@ -1,5 +1,6 @@ /mob/living/carbon/human/proc/get_unarmed_attack(var/mob/living/carbon/human/target, var/hit_zone) // VOREStation Edit - Begin + if(nif && nif.flag_check(NIF_C_HARDCLAWS,NIF_FLAGS_COMBAT)){return unarmed_hardclaws} if(src.default_attack && src.default_attack.is_usable(src, target, hit_zone)) if(pulling_punches) var/datum/unarmed_attack/soft_type = src.default_attack.get_sparring_variant() diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm index 30ee7c64d6..d1f468500b 100644 --- a/code/modules/mob/living/carbon/human/human_damage.dm +++ b/code/modules/mob/living/carbon/human/human_damage.dm @@ -104,6 +104,7 @@ amount *= M.incoming_damage_percent if(!isnull(M.incoming_brute_damage_percent)) amount *= M.incoming_brute_damage_percent + if(nif && nif.flag_check(NIF_C_BRUTEARMOR,NIF_FLAGS_COMBAT)){amount *= 0.7} //VOREStation Edit - NIF mod for damage resistance for this type of damage take_overall_damage(amount, 0) else for(var/datum/modifier/M in modifiers) @@ -120,6 +121,7 @@ amount *= M.incoming_damage_percent if(!isnull(M.incoming_fire_damage_percent)) amount *= M.incoming_fire_damage_percent + if(nif && nif.flag_check(NIF_C_BURNARMOR,NIF_FLAGS_COMBAT)){amount *= 0.7} //VOREStation Edit - NIF mod for damage resistance for this type of damage take_overall_damage(0, amount) else for(var/datum/modifier/M in modifiers) @@ -139,6 +141,7 @@ amount *= M.incoming_damage_percent if(!isnull(M.incoming_brute_damage_percent)) amount *= M.incoming_brute_damage_percent + if(nif && nif.flag_check(NIF_C_BRUTEARMOR,NIF_FLAGS_COMBAT)){amount *= 0.7} //VOREStation Edit - NIF mod for damage resistance for this type of damage O.take_damage(amount, 0, sharp=is_sharp(damage_source), edge=has_edge(damage_source), used_weapon=damage_source) else for(var/datum/modifier/M in modifiers) @@ -160,6 +163,7 @@ amount *= M.incoming_damage_percent if(!isnull(M.incoming_fire_damage_percent)) amount *= M.incoming_fire_damage_percent + if(nif && nif.flag_check(NIF_C_BURNARMOR,NIF_FLAGS_COMBAT)){amount *= 0.7} //VOREStation Edit - NIF mod for damage resistance for this type of damage O.take_damage(0, amount, sharp=is_sharp(damage_source), edge=has_edge(damage_source), used_weapon=damage_source) else for(var/datum/modifier/M in modifiers) diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 75d598fb69..fd21301044 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -666,7 +666,8 @@ pressure_alert = -1 else if( !(COLD_RESISTANCE in mutations)) - take_overall_damage(brute=LOW_PRESSURE_DAMAGE, used_weapon = "Low Pressure") + if(!isSynthetic() || !nif || !nif.flag_check(NIF_O_PRESSURESEAL,NIF_FLAGS_OTHER)) //VOREStation Edit - NIF pressure seals + take_overall_damage(brute=LOW_PRESSURE_DAMAGE, used_weapon = "Low Pressure") if(getOxyLoss() < 55) // 11 OxyLoss per 4 ticks when wearing internals; unconsciousness in 16 ticks, roughly half a minute adjustOxyLoss(4) // 16 OxyLoss per 4 ticks when no internals present; unconsciousness in 13 ticks, roughly twenty seconds pressure_alert = -2 @@ -703,7 +704,8 @@ // FBPs will overheat, prosthetic limbs are fine. if(robobody_count) - bodytemperature += round(robobody_count*1.75) + if(!nif || !nif.flag_check(NIF_O_HEATSINKS,NIF_FLAGS_OTHER)) //VOREStation Edit - NIF heatsinks + bodytemperature += round(robobody_count*1.75) var/body_temperature_difference = species.body_temperature - bodytemperature diff --git a/code/modules/nano/interaction/inventory_vr.dm b/code/modules/nano/interaction/inventory_vr.dm index 373e9f382b..21ee1ca590 100644 --- a/code/modules/nano/interaction/inventory_vr.dm +++ b/code/modules/nano/interaction/inventory_vr.dm @@ -1,7 +1,7 @@ /* This state checks that the src_object is on the user's glasses slot. */ -/var/global/datum/topic_state/inventory_state/glasses_state = new() +/var/global/datum/topic_state/glasses_state/glasses_state = new() /datum/topic_state/glasses_state/can_use_topic(var/src_object, var/mob/user) if(ishuman(user)) @@ -10,3 +10,23 @@ return user.shared_nano_interaction() return STATUS_CLOSE + +/var/global/datum/topic_state/nif_state/nif_state = new() + +/datum/topic_state/nif_state/can_use_topic(var/src_object, var/mob/user) + if(ishuman(user)) + var/mob/living/carbon/human/H = user + if(H.nif && H.nif.stat == NIF_WORKING && src_object == H.nif) + return user.shared_nano_interaction() + + return STATUS_CLOSE + +/var/global/datum/topic_state/commlink_state/commlink_state = new() + +/datum/topic_state/commlink_state/can_use_topic(var/src_object, var/mob/user) + if(ishuman(user)) + var/mob/living/carbon/human/H = user + if(H.nif && H.nif.stat == NIF_WORKING && H.nif.comm == src_object) + return user.shared_nano_interaction() + + return STATUS_CLOSE diff --git a/code/modules/nifsoft/nif.dm b/code/modules/nifsoft/nif.dm index b4ef9eafd7..dc958718cc 100644 --- a/code/modules/nifsoft/nif.dm +++ b/code/modules/nifsoft/nif.dm @@ -3,8 +3,8 @@ //Nanotech Implant Foundation /obj/item/device/nif - name = "nanotech implant foundation" - desc = "A somewhat degraded copy of a Kitsuhana working surface, in a box. Can print new \ + name = "nanite implant framework" + desc = "A somewhat diminished knockoff of a Kitsuhana nano working surface, in a box. Can print new \ implants inside living hosts on the fly based on software uploads. Must be surgically \ implanted in the head to work. May eventually wear out and break." @@ -14,7 +14,7 @@ w_class = ITEMSIZE_TINY var/durability = 100 // Durability remaining - var/burn_factor = 100 // Divisor for power charge from nutrition (efficiency basically) + var/bioadap = FALSE // If it'll work in fancy species var/tmp/power_usage = 0 // Nifsoft adds to this var/tmp/mob/living/carbon/human/human // Our owner! @@ -31,31 +31,51 @@ var/tmp/install_done // Time when install will finish var/tmp/open = FALSE // If it's open for maintenance (1-3) - var/obj/item/clothing/glasses/hud/nif_hud/nif_hud + var/obj/item/clothing/glasses/hud/nif_hud/nif_hud // The AR ones require this + var/obj/item/device/communicator/commlink/comm // The commlink requires this var/global/icon/big_icon - var/global/click_sound = 'sound/effects/pop.ogg' + var/global/click_sound = 'sound/items/nif_click.ogg' + var/global/bad_sound = 'sound/items/nif_tone_bad.ogg' + var/global/good_sound = 'sound/items/nif_tone_good.ogg' + var/global/list/look_messages = list( + "flicks their eyes around", + "looks at something unseen", + "reads some invisible text", + "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) - new /datum/nifsoft/ar_civ(src) + + //Required for AR stuff. nif_hud = new(src) + //First one to spawn in the game, make a big icon if(!big_icon) big_icon = new(icon,icon_state = "nif_full") - //Probably loading from a save + //If given a human on spawn (probably from persistence) if(ishuman(newloc)) var/mob/living/carbon/human/H = newloc - implant(H) - owner = H.mind.name - name = initial(name) + " ([owner])" - stat = NIF_WORKING + if(!quick_implant(H)) + WARNING("NIF spawned in [H] failed to implant") + spawn(0) + qdel(src) + else + //Free commlink for return customers + new /datum/nifsoft/commlink(src) + //Free civilian AR included + new /datum/nifsoft/ar_civ(src) + + //If given wear (like when spawned) then done if(wear) durability = wear + wear(0) //Just make it update. + //Draw me yo. update_icon() //Destructor cleans up references @@ -66,12 +86,20 @@ for(var/S in nifsofts) if(S) qdel(S) + if(nif_hud) + qdel(nif_hud) + if(comm) + qdel(comm) + nifsofts.Cut() ..() //Being implanted in some mob /obj/item/device/nif/proc/implant(var/mob/living/carbon/human/H) - if(istype(H) && !H.nif && H.species && !(H.species.flags & NO_SCAN) && (loc == H.get_organ(BP_HEAD))) //NO_SCAN is the default 'too complicated' flag. + if(istype(H) && !H.nif && H.species && (loc == H.get_organ(BP_HEAD))) + if(!bioadap && (H.species.flags & NO_SCAN)) //NO_SCAN is the default 'too complicated' flag + return FALSE + human = H human.nif = src stat = NIF_INSTALLING @@ -87,8 +115,10 @@ return FALSE src.forceMove(head) head.implants += src - owner = H.real_name - return implant(H) + spawn(0) //Let the character finish spawning yo. + owner = H.mind.name + implant(H) + return TRUE return FALSE @@ -121,20 +151,20 @@ //Wear update/check proc /obj/item/device/nif/proc/wear(var/wear = 0) - if(wear) - durability -= wear * rand(0.85,1.15) // Also +/- 15% + wear *= (rand(85,115) / 100) //Apparently rand() only takes integers. + durability -= wear if(durability <= 0) - stat = NIF_TEMPFAIL - update_icon() notify("Danger! General system insta#^!($",TRUE) to_chat(human,"Your NIF vision overlays disappear and your head suddenly seems very quiet...") + stat = NIF_TEMPFAIL + update_icon() //Attackby proc, for maintenance /obj/item/device/nif/attackby(obj/item/weapon/W, mob/user as mob) if(open == 0 && istype(W,/obj/item/weapon/screwdriver)) if(do_after(user, 4 SECONDS, src) && open == 0) - user.visible_message("[user] unscrews and pries open \the [src].","You unscrew and pry open \the [src].") + user.visible_message("[user] unscrews and pries open \the [src].","You unscrew and pry open \the [src].") playsound(user, 'sound/items/Screwdriver.ogg', 50, 1) open = 1 update_icon() @@ -144,25 +174,25 @@ to_chat(user,"You need at least three coils of wire to add them to \the [src].") return if(do_after(user, 6 SECONDS, src) && open == 1 && C.use(3)) - user.visible_message("[user] replaces some wiring in \the [src].","You replace any burned out wiring in \the [src].") + user.visible_message("[user] replaces some wiring in \the [src].","You replace any burned out wiring in \the [src].") playsound(user, 'sound/items/Deconstruct.ogg', 50, 1) open = 2 update_icon() else if(open == 2 && istype(W,/obj/item/device/multitool)) if(do_after(user, 8 SECONDS, src) && open == 2) - user.visible_message("[user] resets several circuits in \the [src].","You find and repair any faulty circuits in \the [src].") + user.visible_message("[user] resets several circuits in \the [src].","You find and repair any faulty circuits in \the [src].") open = 3 update_icon() else if(open == 3 && istype(W,/obj/item/weapon/screwdriver)) if(do_after(user, 3 SECONDS, src) && open == 3) - user.visible_message("[user] closes up \the [src].","You re-seal \the [src] for use once more.") + user.visible_message("[user] closes up \the [src].","You re-seal \the [src] for use once more.") playsound(user, 'sound/items/Screwdriver.ogg', 50, 1) open = FALSE durability = initial(durability) stat = NIF_PREINSTALL update_icon() -//Wear update/check proc +//Icon updating /obj/item/device/nif/update_icon() if(open) icon_state = "nif_open[open]" @@ -181,19 +211,24 @@ //The (dramatic) install process /obj/item/device/nif/proc/handle_install() - if(human.stat) //No stuff while KO. Sleeping it off is viable, and doesn't start until you wake up from surgery + if(human.stat || !human.mind) //No stuff while KO or not sleeved return FALSE //Firsties if(!install_done) - if(human.real_name == owner) + if(human.mind.name == owner) install_done = world.time + 1 MINUTE notify("Welcome back, [owner]! Performing quick-calibration...") - else + else if(!owner) install_done = world.time + 30 MINUTES notify("Adapting to new user...") sleep(5 SECONDS) notify("Adjoining optic [human.isSynthetic() ? "interface" : "nerve"], please be patient.",TRUE) + else + notify("You are not an authorized user for this device. Please contact [owner].",TRUE) + unimplant() + stat = NIF_TEMPFAIL + return FALSE var/percent_done = (world.time - (install_done - (30 MINUTES))) / (30 MINUTES) @@ -229,7 +264,7 @@ //Finishing up if(1.0 to INFINITY) stat = NIF_WORKING - owner = human.real_name + owner = human.mind.name name = initial(name) + " ([owner])" notify("Calibration complete! User data stored!") @@ -272,12 +307,19 @@ //Prints 'AR' messages to the user /obj/item/device/nif/proc/notify(var/message,var/alert = 0) - if(!human) return + if(!human || stat == NIF_TEMPFAIL) return to_chat(human,"\[\icon[src.big_icon]NIF\] displays, \"[message]\"") + if(prob(1)) human.visible_message("\The [human] [pick(look_messages)].") + if(alert) + human << bad_sound + else + human << good_sound //Called to spend nutrition, returns 1 if it was able to /obj/item/device/nif/proc/use_charge(var/use_charge) + if(stat != NIF_WORKING) return FALSE + //You don't want us to take any? Well okay. if(!use_charge) return TRUE @@ -292,6 +334,8 @@ //Install a piece of software /obj/item/device/nif/proc/install(var/datum/nifsoft/new_soft) + if(stat == NIF_TEMPFAIL) return FALSE + if(nifsofts[new_soft.list_pos]) return FALSE @@ -305,6 +349,7 @@ notify("The software \"[new_soft]\" is not supported in organic life.",TRUE) return FALSE + wear(new_soft.wear) nifsofts[new_soft.list_pos] = new_soft power_usage += new_soft.p_drain @@ -320,7 +365,6 @@ if(new_soft.other_flags) other_flags |= new_soft.other_flags - wear(new_soft.wear) return TRUE //Uninstall a piece of software @@ -353,7 +397,10 @@ //Activate a nifsoft /obj/item/device/nif/proc/activate(var/datum/nifsoft/soft) + if(stat != NIF_WORKING) return FALSE + if(human) + if(prob(5)) human.visible_message("\The [human] [pick(look_messages)].") var/applies_to = soft.applies_to var/synth = human.isSynthetic() if(synth && !(applies_to & NIF_SYNTHETIC)) @@ -366,6 +413,7 @@ return FALSE if(!use_charge(soft.a_drain)) + notify("Not enough power to activate \"[soft]\" NIFsoft!",TRUE) return FALSE if(soft.tick_flags == NIF_ACTIVETICK) @@ -378,6 +426,9 @@ //Deactivate a nifsoft /obj/item/device/nif/proc/deactivate(var/datum/nifsoft/soft) + if(human) + if(prob(5)) human.visible_message("\The [human] [pick(look_messages)].") + if(soft.tick_flags == NIF_ACTIVETICK) nifsofts_life -= soft @@ -427,7 +478,7 @@ //Check for an installed implant /obj/item/device/nif/proc/imp_check(var/soft) - if(!stat == NIF_WORKING) return FALSE + if(stat != NIF_WORKING) return FALSE ASSERT(soft) if(ispath(soft)) @@ -439,7 +490,8 @@ //Check for a set flag /obj/item/device/nif/proc/flag_check(var/flag,var/hint) - if(!stat == NIF_WORKING) return FALSE + if(stat != NIF_WORKING) return FALSE + ASSERT(flag && hint) var/result = FALSE @@ -457,6 +509,7 @@ return result +/////////////////////////////////////////////////////////////////////////////////////// //NIF HUD object becasue HUD handling is trash and should be rewritten /obj/item/clothing/glasses/hud/nif_hud/var/obj/item/device/nif/nif @@ -464,6 +517,12 @@ ..(newloc) nif = newloc +/obj/item/clothing/glasses/hud/nif_hud/Destroy() + if(nif) + nif.nif_hud = null + nif = null + ..() + /obj/item/clothing/glasses/hud/nif_hud/process_hud(M,var/thing) //Faster checking with local var, and this is called often so I want fast. var/visflags = nif.vision_flags @@ -479,3 +538,22 @@ process_omni_hud(nif.human, "sci") else if(NIF_V_AR_CIVILIAN & visflags) process_omni_hud(nif.human, "civ") + +// Alternate NIFs +/obj/item/device/nif/bad + name = "second-hand NIF" + desc = "A copy of a copy of a copy of a copy of... this can't be any good, right? Surely?" + durability = 10 + +/obj/item/device/nif/authentic + name = "\improper Kitsuhana NIF" + desc = "An actual Kitsuhana working surface, in a box. From a society slightly less afraid \ + of self-replicating nanotechnology. Basically just a high-endurance NIF." + durability = 1000 + +/obj/item/device/nif/bioadap + name = "bioadaptive NIF" + desc = "A NIF that goes out of it's way to accomidate strange body types. \ + Will function in species where it normally wouldn't." + durability = 25 + bioadap = TRUE diff --git a/code/modules/nifsoft/nif_softshop.dm b/code/modules/nifsoft/nif_softshop.dm index 3680b47786..4d0da46843 100644 --- a/code/modules/nifsoft/nif_softshop.dm +++ b/code/modules/nifsoft/nif_softshop.dm @@ -20,7 +20,7 @@ starting_illegal_nifsoft = list() for(var/P in subtypesof(/datum/nifsoft) - /datum/nifsoft/package) var/datum/nifsoft/NS = P - if(initial(NS.initial)) + if(initial(NS.vended)) switch(initial(NS.illegal)) if(TRUE) starting_illegal_nifsoft += NS @@ -40,7 +40,13 @@ for(var/entry in current_list[1]) var/datum/nifsoft/NS = entry - var/name = initial(NS.name) + var/applies_to = initial(NS.applies_to) + var/context = "" + if(!(applies_to & NIF_SYNTHETIC)) + context = " (Org Only)" + else if(!(applies_to & NIF_ORGANIC)) + context = " (Syn Only)" + var/name = "[initial(NS.name)][context]" var/datum/stored_item/vending_product/product = new/datum/stored_item/vending_product(src, entry, name) product.price = initial(NS.cost) @@ -61,6 +67,104 @@ return ..() +/* +/obj/proc/allowed(mob/M) + //check if it doesn't require any access at all + if(src.check_access(null)) + return 1 + + var/id = M.GetIdCard() + if(id) + return check_access(id) + return 0 + +///obj/item/proc/GetAccess() +// return list() + +/atom/movable/proc/GetAccess() + var/obj/item/weapon/card/id/id = GetIdCard() + return id ? id.GetAccess() : list() + +/obj/proc/GetID() + return null + +/obj/proc/check_access(obj/item/I) + return check_access_list(I ? I.GetAccess() : list()) + +/obj/proc/check_access_list(var/list/L) + if(!req_access) req_access = list() + if(!req_one_access) req_one_access = list() + if(!L) return 0 + if(!istype(L, /list)) return 0 + return has_access(req_access, req_one_access, L) +*/ + +//Had to override this too +/obj/machinery/vending/nifsoft_shop/Topic(href, href_list) + if(stat & (BROKEN|NOPOWER)) + return + if(usr.stat || usr.restrained()) + return + + if(href_list["remove_coin"] && !istype(usr,/mob/living/silicon)) + if(!coin) + usr << "There is no coin in this machine." + return + + coin.forceMove(src.loc) + if(!usr.get_active_hand()) + usr.put_in_hands(coin) + usr << "You remove \the [coin] from \the [src]" + coin = null + categories &= ~CAT_COIN + + if((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf)))) + if((href_list["vend"]) && (vend_ready) && (!currently_vending)) + if((!allowed(usr)) && !emagged && scan_id) //For SECURE VENDING MACHINES YEAH + usr << "Access denied." //Unless emagged of course + flick(icon_deny,src) + return + + var/key = text2num(href_list["vend"]) + var/datum/stored_item/vending_product/R = product_records[key] + + // This should not happen unless the request from NanoUI was bad + if(!(R.category & categories)) + return + + //Specific soft access checking + var/datum/nifsoft/path = R.item_path + if(initial(path.access)) + var/list/soft_access = list(initial(path.access)) + var/list/usr_access = usr.GetAccess() + if(!has_access(soft_access, list(), usr_access) && !emagged) + usr << "You aren't authorized to buy [initial(path.name)]." + flick(icon_deny,src) + return + + if(R.price <= 0) + vend(R, usr) + else if(istype(usr,/mob/living/silicon)) //If the item is not free, provide feedback if a synth is trying to buy something. + usr << "Artificial unit recognized. Artificial units cannot complete this transaction. Purchase canceled." + return + else + currently_vending = R + if(!vendor_account || vendor_account.suspended) + status_message = "This machine is currently unable to process payments due to problems with the associated account." + status_error = 1 + else + status_message = "[initial(path.desc)]

Please swipe a card or insert cash to pay for the item." + status_error = 0 + + else if(href_list["cancelpurchase"]) + currently_vending = null + + else if((href_list["togglevoice"]) && (panel_open)) + shut_up = !shut_up + + add_fingerprint(usr) + nanomanager.update_uis(src) + // Also special treatment! /obj/machinery/vending/nifsoft_shop/vend(datum/stored_item/vending_product/R, mob/user) var/mob/living/carbon/human/H = user diff --git a/code/modules/nifsoft/nif_statpanel.dm b/code/modules/nifsoft/nif_statpanel.dm index 990bf43565..4ddba7a3c9 100644 --- a/code/modules/nifsoft/nif_statpanel.dm +++ b/code/modules/nifsoft/nif_statpanel.dm @@ -4,7 +4,7 @@ SetupNifStat() /mob/living/carbon/human/proc/SetupNifStat() - var/nif_status + var/nif_status = "" switch(nif.stat) if(NIF_WORKING) nif_status = "Operating Normally" @@ -16,6 +16,7 @@ nif_status = "Adapting To User" else nif_status = "Unknown - Error" + nif_status += " ([round((nif.durability/initial(nif.durability))*100)]%)" stat("NIF Status", nif_status) if(!nif.stat) @@ -39,17 +40,13 @@ nifsoft = new_soft nifsoft_name = new_soft.name name = new_soft.name - toggleable = new_soft.activates /obj/effect/nif_stat/Destroy() nifsoft = null ..() /obj/effect/nif_stat/proc/atom_button_text() - if(!toggleable) - name = "Always On" - else - name = "[nifsoft.active ? "Active" : "Disabled"]" + name = nifsoft.stat_text() return src /obj/effect/nif_stat/Click(var/location, var/control, var/params) diff --git a/code/modules/nifsoft/nifsoft.dm b/code/modules/nifsoft/nifsoft.dm index 453e00d79b..f86e0150e3 100644 --- a/code/modules/nifsoft/nifsoft.dm +++ b/code/modules/nifsoft/nifsoft.dm @@ -9,9 +9,9 @@ var/cost = 1000 // Cost in cash of buying this software from a terminal //TODO - While coding - var/initial = TRUE // This is available in NIFSoft Shops at the start of the game + var/vended = TRUE // This is available in NIFSoft Shops at the start of the game var/wear = 1 // The wear (+/- 10% when applied) that this causes to the NIF - var/list/req_one_access // What access they need to buy it + var/access // What access they need to buy it, can only set one for ~reasons~ var/illegal = FALSE // If this is a black-market nifsoft (emag option) var/active = FALSE // Whether the active mode of this implant is on @@ -63,6 +63,7 @@ deactivate() if(nif) . = nif.uninstall(src) + nif = null qdel(src) //Called every life() tick on a mob on active implants @@ -88,6 +89,17 @@ uninstall() return +//Called when installed from a disk +/datum/nifsoft/proc/disk_install(var/mob/living/carbon/human/target,var/mob/living/carbon/human/user) + return TRUE + +//Stat-line clickable text +/datum/nifsoft/proc/stat_text() + if(activates) + return "[active ? "Active" : "Disabled"]" + + return "Always On" + ////////////////////// //A package of NIF software /datum/nifsoft/package @@ -108,3 +120,62 @@ software.Cut() software = null ..() + +///////////////// +// A NIFSoft Disk +/obj/item/weapon/disk/nifsoft + name = "NIFSoft Disk" + desc = "It has a small label: \n\ + \"Portable NIFSoft Disk. \n\ + Insert directly into brain.\"" + icon = 'icons/obj/cloning.dmi' + icon_state = "datadisk2" + item_state = "card-id" + w_class = ITEMSIZE_SMALL + var/datum/nifsoft/stored = null + var/laws = "" + +/obj/item/weapon/disk/nifsoft/afterattack(var/A, mob/user, flag, params) + if(!in_range(user, A)) + return + + if(!ishuman(user) || !ishuman(A)) + return + + var/mob/living/carbon/human/Ht = A + var/mob/living/carbon/human/Hu = user + + if(!Ht.nif || Ht.nif.stat != NIF_WORKING) + to_chat(user,"Either they don't have a NIF, or the disk can't connect.") + return + + Ht.visible_message("[Hu] begins uploading new NIFSoft into [Ht]!","[Hu] is uploading new NIFSoft into you!") + if(do_after(Ht,10 SECONDS,Hu)) + var/extra = extra_params() + new stored(Ht.nif,extra) + qdel(src) + +//So disks can pass fancier stuff. +/obj/item/weapon/disk/nifsoft/proc/extra_params() + return null + +/obj/item/weapon/disk/nifsoft/compliance + name = "NIFSoft Disk (Compliance)" + desc = "Wow, adding laws to people? That seems illegal. It probably is. Okay, it really is." + stored = /datum/nifsoft/compliance + +/obj/item/weapon/disk/nifsoft/compliance/afterattack(var/A, mob/user, flag, params) + if(!laws) + to_chat(user,"You haven't set any laws yet. Use the disk in-hand first.") + return + ..(A,user,flag,params) + +/obj/item/weapon/disk/nifsoft/compliance/attack_self(mob/user) + var/newlaws = input(user,"Please Input Laws","Compliance Laws",laws) as message + newlaws = sanitize(newlaws,2048) + if(newlaws) + to_chat(user,"You set the laws to:
[newlaws]") + laws = newlaws + +/obj/item/weapon/disk/nifsoft/compliance/extra_params() + return laws diff --git a/code/modules/nifsoft/software/01_vision.dm b/code/modules/nifsoft/software/01_vision.dm index 15f253d9b2..d222cd67dd 100644 --- a/code/modules/nifsoft/software/01_vision.dm +++ b/code/modules/nifsoft/software/01_vision.dm @@ -5,16 +5,15 @@ desc = "Provides a general identification and health status overlay on your vision with no frills." list_pos = NIF_CIVILIAN_AR cost = 500 - initial = TRUE a_drain = 0.05 activate() - if(..()) + if((. = ..())) nif.deactivate_these(NIF_MEDICAL_AR,NIF_SECURITY_AR,NIF_ENGINE_AR,NIF_SCIENCE_AR,NIF_OMNI_AR) nif.set_flag(NIF_V_AR_CIVILIAN,NIF_FLAGS_VISION) deactivate() - if(..()) + if((. = ..())) nif.clear_flag(NIF_V_AR_CIVILIAN,NIF_FLAGS_VISION) /datum/nifsoft/ar_med @@ -22,17 +21,16 @@ desc = "Like the civilian model, but provides medical records access and virus database lookup." list_pos = NIF_MEDICAL_AR cost = 750 - initial = TRUE - req_one_access = list(access_medical) + access = access_medical a_drain = 0.05 activate() - if(..()) + if((. = ..())) nif.deactivate_these(NIF_CIVILIAN_AR,NIF_SECURITY_AR,NIF_ENGINE_AR,NIF_SCIENCE_AR,NIF_OMNI_AR) nif.set_flag(NIF_V_AR_MEDICAL,NIF_FLAGS_VISION) deactivate() - if(..()) + if((. = ..())) nif.clear_flag(NIF_V_AR_MEDICAL,NIF_FLAGS_VISION) /datum/nifsoft/ar_sec @@ -40,17 +38,16 @@ desc = "Like the civilian model, but provides access to arrest status and security records." list_pos = NIF_SECURITY_AR cost = 750 - initial = TRUE - req_one_access = list(access_security) + access = access_security a_drain = 0.05 activate() - if(..()) + if((. = ..())) nif.deactivate_these(NIF_CIVILIAN_AR,NIF_MEDICAL_AR,NIF_ENGINE_AR,NIF_SCIENCE_AR,NIF_OMNI_AR) nif.set_flag(NIF_V_AR_SECURITY,NIF_FLAGS_VISION) deactivate() - if(..()) + if((. = ..())) nif.clear_flag(NIF_V_AR_SECURITY,NIF_FLAGS_VISION) /datum/nifsoft/ar_eng @@ -58,17 +55,16 @@ desc = "Like the civilian model, but provides station alert notices." list_pos = NIF_ENGINE_AR cost = 750 - initial = TRUE - req_one_access = list(access_engine) + access = access_engine a_drain = 0.05 activate() - if(..()) + if((. = ..())) nif.deactivate_these(NIF_CIVILIAN_AR,NIF_MEDICAL_AR,NIF_SECURITY_AR,NIF_SCIENCE_AR,NIF_OMNI_AR) nif.set_flag(NIF_V_AR_ENGINE,NIF_FLAGS_VISION) deactivate() - if(..()) + if((. = ..())) nif.clear_flag(NIF_V_AR_ENGINE,NIF_FLAGS_VISION) /datum/nifsoft/ar_science @@ -76,17 +72,16 @@ desc = "Like the civilian model, but provides ... well, nothing. For now." list_pos = NIF_SCIENCE_AR cost = 750 - initial = TRUE - req_one_access = list(access_research) + access = access_research a_drain = 0.05 activate() - if(..()) + if((. = ..())) nif.deactivate_these(NIF_CIVILIAN_AR,NIF_MEDICAL_AR,NIF_SECURITY_AR,NIF_ENGINE_AR,NIF_OMNI_AR) nif.set_flag(NIF_V_AR_SCIENCE,NIF_FLAGS_VISION) deactivate() - if(..()) + if((. = ..())) nif.clear_flag(NIF_V_AR_SCIENCE,NIF_FLAGS_VISION) /datum/nifsoft/ar_omni @@ -94,17 +89,16 @@ desc = "Like the civilian model, but provides most of the features of the medical and security overlays as well." list_pos = NIF_OMNI_AR cost = 750 - initial = TRUE - req_one_access = list(access_captain) + access = access_captain a_drain = 0.05 activate() - if(..()) + if((. = ..())) nif.deactivate_these(NIF_CIVILIAN_AR,NIF_MEDICAL_AR,NIF_SECURITY_AR,NIF_ENGINE_AR,NIF_SCIENCE_AR) nif.set_flag(NIF_V_AR_OMNI,NIF_FLAGS_VISION) deactivate() - if(..()) + if((. = ..())) nif.clear_flag(NIF_V_AR_OMNI,NIF_FLAGS_VISION) ////////////// @@ -117,11 +111,11 @@ a_drain = 0.025 activate() - if(..()) + if((. = ..())) nif.set_flag(NIF_V_CORRECTIVE,NIF_FLAGS_VISION) deactivate() - if(..()) + if((. = ..())) nif.clear_flag(NIF_V_CORRECTIVE,NIF_FLAGS_VISION) /datum/nifsoft/uvblocker @@ -132,11 +126,11 @@ a_drain = 0.2 activate() - if(..()) + if((. = ..())) nif.set_flag(NIF_V_UVFILTER,NIF_FLAGS_VISION) deactivate() - if(..()) + if((. = ..())) nif.clear_flag(NIF_V_UVFILTER,NIF_FLAGS_VISION) /datum/nifsoft/flashprot @@ -144,15 +138,15 @@ desc = "Enables a high-speed shielding response to intense light, such as flashes, to block them." list_pos = NIF_FLASHPROT cost = 600 - req_one_access = list(access_security) + access = access_security a_drain = 0.05 activate() - if(..()) + if((. = ..())) nif.set_flag(NIF_V_FLASHPROT,NIF_FLAGS_VISION) deactivate() - if(..()) + if((. = ..())) nif.clear_flag(NIF_V_FLASHPROT,NIF_FLAGS_VISION) //////////////// @@ -163,19 +157,20 @@ list_pos = NIF_MESONS cost = 1000 a_drain = 0.1 + access = access_engine tick_flags = NIF_ACTIVETICK activate() - if(..()) + if((. = ..())) nif.deactivate_these(NIF_MATERIAL,NIF_THERMALS,NIF_NIGHTVIS) nif.set_flag(NIF_V_MESONS,NIF_FLAGS_VISION) deactivate() - if(..()) + if((. = ..())) nif.clear_flag(NIF_V_MESONS,NIF_FLAGS_VISION) life() - if(..()) + if((. = ..())) var/mob/living/carbon/human/H = nif.human H.client.screen |= global_hud.meson H.sight |= SEE_TURFS @@ -186,19 +181,20 @@ list_pos = NIF_MATERIAL cost = 1000 a_drain = 0.1 + access = access_research tick_flags = NIF_ACTIVETICK activate() - if(..()) + if((. = ..())) nif.deactivate_these(NIF_MESONS,NIF_THERMALS,NIF_NIGHTVIS) nif.set_flag(NIF_V_MATERIAL,NIF_FLAGS_VISION) deactivate() - if(..()) + if((. = ..())) nif.clear_flag(NIF_V_MATERIAL,NIF_FLAGS_VISION) life() - if(..()) + if((. = ..())) nif.human.sight |= SEE_OBJS /datum/nifsoft/thermals @@ -206,21 +202,21 @@ desc = "Similar to the worn Thermal Goggles, these allow you to see heat-emitting creatures through walls." list_pos = NIF_THERMALS cost = 1000 - req_one_access = list(access_security) a_drain = 0.1 + access = access_captain tick_flags = NIF_ACTIVETICK activate() - if(..()) + if((. = ..())) nif.deactivate_these(NIF_MESONS,NIF_MATERIAL,NIF_NIGHTVIS) nif.set_flag(NIF_V_THERMALS,NIF_FLAGS_VISION) deactivate() - if(..()) + if((. = ..())) nif.clear_flag(NIF_V_THERMALS,NIF_FLAGS_VISION) life() - if(..()) + if((. = ..())) var/mob/living/carbon/human/H = nif.human H.sight |= SEE_MOBS H.client.screen |= global_hud.thermal @@ -231,21 +227,21 @@ desc = "Similar to the worn Night Vision Goggles, these allow you to see in complete darkness." list_pos = NIF_NIGHTVIS cost = 1000 - req_one_access = list(access_security) a_drain = 0.1 + access = access_security tick_flags = NIF_ACTIVETICK activate() - if(..()) + if((. = ..())) nif.deactivate_these(NIF_MESONS,NIF_MATERIAL,NIF_THERMALS) nif.set_flag(NIF_V_NIGHTVIS,NIF_FLAGS_VISION) deactivate() - if(..()) + if((. = ..())) nif.clear_flag(NIF_V_NIGHTVIS,NIF_FLAGS_VISION) life() - if(..()) + if((. = ..())) var/mob/living/carbon/human/H = nif.human H.see_in_dark += 7 H.client.screen |= global_hud.nvg diff --git a/code/modules/nifsoft/software/05_health.dm b/code/modules/nifsoft/software/05_health.dm index 4bc83c407f..1d606d2653 100644 --- a/code/modules/nifsoft/software/05_health.dm +++ b/code/modules/nifsoft/software/05_health.dm @@ -1,14 +1,41 @@ -/* -#define NIF_SPAREBREATH 17 -*/ +// #define NIF_CREWMONITOR 14 +/datum/nifsoft/crewmonitor + name = "Crew Monitor" + desc = "A link to the local crew monitor sensors. Useful for finding people in trouble." + list_pos = NIF_CREWMONITOR + access = access_medical + cost = 1250 + p_drain = 0.025 + var/datum/nano_module/crew_monitor/arscreen + + New() + ..() + arscreen = new(nif) + + Destroy() + qdel(arscreen) + ..() + + activate() + if((. = ..())) + arscreen.ui_interact(nif.human,"main",null,1,nif_state) + return TRUE + + deactivate() + if((. = ..())) + return TRUE + + stat_text() + return "Show Monitor" /datum/nifsoft/medichines_org - name = "Medichines (Org)" + name = "Medichines" desc = "An internal swarm of nanites to make sure you stay in good shape and to promote healing, or to preserve you if you are critically injured." list_pos = NIF_ORGANIC_HEAL cost = 2500 p_drain = 0.05 a_drain = 0.1 //This is messed with manually below. + wear = 2 activates = FALSE //It is automatic in emergencies, not manually controllable. tick_flags = NIF_ALWAYSTICK applies_to = NIF_ORGANIC @@ -16,19 +43,19 @@ //These self-activate on their own, these aren't user-settable to on/off. activate() - if(..()) + if((. = ..())) nif.set_flag(NIF_H_ORGREPAIR,NIF_FLAGS_HEALTH) mode = 1 deactivate() - if(..()) + if((. = ..())) nif.clear_flag(NIF_H_ORGREPAIR,NIF_FLAGS_HEALTH) a_drain = initial(a_drain) mode = initial(mode) - nif.human.in_stasis = 0 + nif.human.Stasis(0) life() - if(..()) + if((. = ..())) var/mob/living/carbon/human/H = nif.human var/HP_percent = H.health/H.getMaxHealth() @@ -67,21 +94,22 @@ //Patient critical - emergency stasis if(mode >= 3) if(HP_percent <= 0) - H.in_stasis = 3 + H.Stasis(3) if(HP_percent > 0.2) - H.in_stasis = 0 + H.Stasis(0) nif.notify("Ending emergency stasis.",TRUE) mode = 2 return TRUE /datum/nifsoft/medichines_syn - name = "Medichines (Syn)" + name = "Medichines" desc = "A swarm of mechanical repair nanites, able to repair relatively minor damage to synthetic bodies. Large repairs must still be performed manually." list_pos = NIF_SYNTH_HEAL cost = 2500 p_drain = 0.05 a_drain = 0.00 //This is manually drained below. + wear = 2 activates = FALSE //It is automatic in emergencies, not manually controllable. tick_flags = NIF_ALWAYSTICK applies_to = NIF_SYNTHETIC @@ -89,17 +117,17 @@ //These self-activate on their own, these aren't user-settable to on/off. activate() - if(..()) + if((. = ..())) nif.set_flag(NIF_H_SYNTHREPAIR,NIF_FLAGS_HEALTH) mode = 1 deactivate() - if(..()) + if((. = ..())) nif.clear_flag(NIF_H_SYNTHREPAIR,NIF_FLAGS_HEALTH) mode = 0 life() - if(..()) + if((. = ..())) //We're good! if(!nif.human.bad_external_organs.len) if(mode || active) @@ -135,6 +163,7 @@ cost = 650 p_drain = 0.05 a_drain = 0.1 + wear = 2 tick_flags = NIF_ALWAYSTICK applies_to = NIF_ORGANIC var/filled = 100 //Tracks the internal tank 'refilling', which still uses power @@ -143,17 +172,17 @@ if(!(filled > 50)) nif.notify("Respirocytes not saturated!",TRUE) return FALSE - if(..()) + if((. = ..())) nif.set_flag(NIF_H_SPAREBREATH,NIF_FLAGS_HEALTH) nif.notify("Now taking air from reserves.") deactivate() - if(..()) + if((. = ..())) nif.clear_flag(NIF_H_SPAREBREATH,NIF_FLAGS_HEALTH) nif.notify("Now taking air from environment and refilling reserves.") life() - if(..()) + if((. = ..())) if(active) //Supplying air, not recharging it switch(filled) //Text warnings if(75) diff --git a/code/modules/nifsoft/software/10_combat.dm b/code/modules/nifsoft/software/10_combat.dm index 64f3ae9a25..38fe1b86e2 100644 --- a/code/modules/nifsoft/software/10_combat.dm +++ b/code/modules/nifsoft/software/10_combat.dm @@ -1,7 +1,140 @@ /* -#define NIF_BRUTEARMOR 18 -#define NIF_BURNARMOR 19 -#define NIF_PAINKILLERS 20 -#define NIF_HARDCLAWS 21 #define NIF_HIDDENLASER 22 -*/ \ No newline at end of file +*/ + +/datum/nifsoft/brute_armor + name = "Bullhide Mod" + desc = "A difficult-to-produce thickening of the dermis and skeletal structure, allowing a user to absorb more external trauma from physical sources." + list_pos = NIF_BRUTEARMOR + cost = 3200 + p_drain = 0.05 + illegal = TRUE + wear = 3 + access = 999 //Prevents anyone from buying it without an emag. + activates = FALSE //It's armor. + + install() + if((. = ..())) + nif.set_flag(NIF_C_BRUTEARMOR,NIF_FLAGS_COMBAT) + + uninstall() + . = ..() + nif.clear_flag(NIF_C_BRUTEARMOR,NIF_FLAGS_COMBAT) + +/datum/nifsoft/burn_armor + name = "Dragon's Skin" + desc = "A thin layer of material under the skin provides heat disappation for burns, reducing the trauma from lasers and fire. Not effective against ongoing environmental heat." + list_pos = NIF_BURNARMOR + cost = 3200 + p_drain = 0.05 + illegal = TRUE + wear = 3 + access = 999 //Prevents anyone from buying it without an emag. + activates = FALSE //It's armor. + + install() + if((. = ..())) + nif.set_flag(NIF_C_BURNARMOR,NIF_FLAGS_COMBAT) + + uninstall() + . = ..() + nif.clear_flag(NIF_C_BURNARMOR,NIF_FLAGS_COMBAT) + +/datum/nifsoft/painkillers + name = "Nova Shock" + desc = "A constant stream of high-grade painkillers numb the user's body to all pain. Generally results in extreme addiction or overdose." + list_pos = NIF_PAINKILLERS + cost = 2600 + a_drain = 1 //Gotta produce them drugs, yo. + illegal = TRUE + wear = 2 + access = 999 //Prevents anyone from buying it without an emag. + tick_flags = NIF_ACTIVETICK + + activate() + if((. = ..())) + nif.set_flag(NIF_C_PAINKILLERS,NIF_FLAGS_COMBAT) + + deactivate() + if((. = ..())) + nif.clear_flag(NIF_C_PAINKILLERS,NIF_FLAGS_COMBAT) + + life() + if((. = ..())) + var/mob/living/carbon/human/H = nif.human + H.bloodstr.add_reagent("numbenzyme",0.5) + +/datum/nifsoft/hardclaws + name = "Bloodletters" + desc = "Generates monofilament wires from one's fingertips, allowing one to slash through almost any armor with relative ease. The monofilaments need to be replaced constantly, though, which does use power." + list_pos = NIF_HARDCLAWS + cost = 2200 + a_drain = 0.5 + illegal = TRUE + wear = 4 + access = 999 //Prevents anyone from buying it without an emag. + + activate() + if((. = ..())) + nif.set_flag(NIF_C_HARDCLAWS,NIF_FLAGS_COMBAT) + + deactivate() + if((. = ..())) + nif.clear_flag(NIF_C_HARDCLAWS,NIF_FLAGS_COMBAT) + +// The unarmed attack to go with the hardclaws +var/global/datum/unarmed_attack/hardclaws/unarmed_hardclaws = new() +/datum/unarmed_attack/hardclaws + attack_verb = list("claws") + attack_noun = list("talons") + damage = 15 + attack_sound = "punch" + miss_sound = 'sound/weapons/punchmiss.ogg' + sharp = 1 + edge = 1 + sparring_variant_type = /datum/unarmed_attack/hardclaws + +/datum/nifsoft/hidelaser + name = "Dazzle" + desc = "Fabricates a 2-shot holdout laser inside your body, which can be deployed (somewhat painfully) on demand. Only enough materials to generate one." + list_pos = NIF_HIDDENLASER + cost = 2200 + //a_drain = 50 //Done manually below. + illegal = TRUE + wear = 6 + access = 999 //Prevents anyone from buying it without an emag. + var/used = FALSE + + activate() + if((. = ..())) + nif.set_flag(NIF_C_HIDELASER,NIF_FLAGS_COMBAT) + 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() + + deactivate() + if((. = ..())) + nif.clear_flag(NIF_C_HIDELASER,NIF_FLAGS_COMBAT) + +//The gun to go with this implant +/obj/item/weapon/gun/energy/gun/martin/dazzle + name = "Microlaser" + desc = "A tiny nanofabricated laser." + + icon = 'icons/obj/gun_vr.dmi' + icon_state = "PDW" + item_state = "gun" diff --git a/code/modules/nifsoft/software/14_commlink.dm b/code/modules/nifsoft/software/14_commlink.dm new file mode 100644 index 0000000000..4380c53952 --- /dev/null +++ b/code/modules/nifsoft/software/14_commlink.dm @@ -0,0 +1,132 @@ +/////////// +// Commlink - Has a bunch of extra stuff due to communicator defines. +/datum/nifsoft/commlink + name = "Commlink" + desc = "An internal communicator for keeping in touch with people." + list_pos = NIF_COMMLINK + cost = 500 + wear = 0 + p_drain = 0.01 + + install() + if((. = ..())) + nif.comm = new(nif,src) + + activate() + if((. = ..())) + nif.set_flag(NIF_O_COMMLINK,NIF_FLAGS_OTHER) + nif.comm.initialize_exonet(nif.human) + nif.comm.ui_interact(nif.human,key_state = commlink_state) + spawn(0) + deactivate() + + deactivate() + if((. = ..())) + nif.clear_flag(NIF_O_COMMLINK,NIF_FLAGS_OTHER) + + stat_text() + return "Show Commlink" + +/datum/nifsoft/commlink/Topic(href, href_list) + if(href_list["open"]) + activate() + +/obj/item/device/communicator/commlink + name = "commlink" + desc = "An internal communicator, basically." + occupation = "\[Commlink\]" + var/obj/item/device/nif/nif + var/datum/nifsoft/commlink/nifsoft + + New(var/newloc,var/soft) + ..() + nif = newloc + nifsoft = soft + register_device(nif.human) + qdel(camera) //Not supported on internal one. + + Destroy() + if(nif) + nif.comm = null + nif = null + ..() + +//So that only the owner's chat is relayed to others. +/obj/item/device/communicator/commlink/hear_talk(mob/living/M, text, verb, datum/language/speaking) + if(M != nif.human) return + for(var/obj/item/device/communicator/comm in communicating) + + var/turf/T = get_turf(comm) + if(!T) return + + var/icon_object = src + + var/list/mobs_to_relay + if(istype(comm,/obj/item/device/communicator/commlink)) + var/obj/item/device/communicator/commlink/CL = comm + mobs_to_relay = list(CL.nif.human) + icon_object = CL.nif.big_icon + else + var/list/in_range = get_mobs_and_objs_in_view_fast(T,world.view,0) + mobs_to_relay = in_range["mobs"] + + for(var/mob/mob in mobs_to_relay) + //Can whoever is hearing us understand? + if(!mob.say_understands(M, speaking)) + if(speaking) + text = speaking.scramble(text) + else + text = stars(text) + var/name_used = M.GetVoice() + var/rendered = null + if(speaking) //Language being used + rendered = "\icon[icon_object] [name_used] [speaking.format_message(text, verb)]" + else + rendered = "\icon[icon_object] [name_used] [verb], \"[text]\"" + mob.show_message(rendered, 2) + +//Not supported by the internal one +/obj/item/device/communicator/commlink/show_message(msg, type, alt, alt_type) + return + +//The silent treatment +/obj/item/device/communicator/commlink/request(var/atom/candidate) + if(candidate in voice_requests) + return + var/who = null + if(isobserver(candidate)) + who = candidate.name + else if(istype(candidate, /obj/item/device/communicator)) + var/obj/item/device/communicator/comm = candidate + who = comm.owner + comm.voice_invites |= src + + if(!who) + return + + voice_requests |= candidate + + if(ringer && nif.human) + nif.notify("New commlink call from [who]. (Open)") + +//Similar reason +/obj/item/device/communicator/commlink/request_im(var/atom/candidate, var/origin_address, var/text) + var/who = null + if(isobserver(candidate)) + var/mob/observer/dead/ghost = candidate + who = ghost + im_list += list(list("address" = origin_address, "to_address" = exonet.address, "im" = text)) + else if(istype(candidate, /obj/item/device/communicator)) + var/obj/item/device/communicator/comm = candidate + who = comm.owner + comm.im_contacts |= src + im_list += list(list("address" = origin_address, "to_address" = exonet.address, "im" = text)) + else return + + im_contacts |= candidate + + if(!who) + return + + if(ringer && nif.human) + nif.notify("Commlink message from [who]: \"[text]\" (Open)") diff --git a/code/modules/nifsoft/software/15_misc.dm b/code/modules/nifsoft/software/15_misc.dm index a20e26c3a6..cc8d6b8b10 100644 --- a/code/modules/nifsoft/software/15_misc.dm +++ b/code/modules/nifsoft/software/15_misc.dm @@ -1,9 +1,182 @@ -/* -#define NIF_COMMLINK 23 -#define NIF_SUITSENSORS 24 -#define NIF_APCCHARGE 25 -#define NIF_PRESSURE 26 -#define NIF_HEATSINK 27 -#define NIF_UVFILTER 28 -#define NIF_FLASHPROT 29 -*/ \ No newline at end of file +/datum/nifsoft/apc_recharge + name = "APC Connector" + desc = "A small attachment that allows synthmorphs to recharge themselves from APCs." + list_pos = NIF_APCCHARGE + cost = 1250 + wear = 2 + applies_to = NIF_SYNTHETIC + tick_flags = NIF_ACTIVETICK + var/obj/machinery/power/apc/apc + + activate() + if((. = ..())) + var/mob/living/carbon/human/H = nif.human + nif.set_flag(NIF_O_APCCHARGE,NIF_FLAGS_OTHER) + 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("Thin snakelike tendrils grow from [H] and connect to \the [apc].","Thin snakelike tendrils grow from you and connect to \the [apc].") + + deactivate() + if((. = ..())) + nif.clear_flag(NIF_O_APCCHARGE,NIF_FLAGS_OTHER) + apc = null + + life() + if((. = ..())) + var/mob/living/carbon/human/H = nif.human + if(apc && (get_dist(H,apc) <= 1) && H.nutrition < 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("[H]'s snakelike tendrils whip back into their body from \the [apc].","The APC connector tendrils return to your body.") + deactivate() + return FALSE + +/datum/nifsoft/pressure + name = "Pressure Seals" + desc = "Creates pressure seals around important synthetic components to protect them from vacuum. Almost impossible on organics." + list_pos = NIF_PRESSURE + cost = 1750 + a_drain = 0.5 + wear = 3 + applies_to = NIF_SYNTHETIC + + activate() + if((. = ..())) + nif.set_flag(NIF_O_PRESSURESEAL,NIF_FLAGS_OTHER) + + deactivate() + if((. = ..())) + nif.clear_flag(NIF_O_PRESSURESEAL,NIF_FLAGS_OTHER) + +/datum/nifsoft/heatsinks + name = "Heat Sinks" + desc = "Advanced heat sinks for internal heat storage of heat on a synth until able to vent it in atmosphere." + list_pos = NIF_HEATSINK + cost = 1450 + a_drain = 0.25 + wear = 3 + var/used = 0 + tick_flags = NIF_ALWAYSTICK + applies_to = NIF_SYNTHETIC + + activate() + if((. = ..())) + if(used >= 50) + nif.notify("Heat sinks not safe to operate again yet!",TRUE) + spawn(0) + deactivate() + return FALSE + nif.set_flag(NIF_O_HEATSINKS,NIF_FLAGS_OTHER) + + deactivate() + if((. = ..())) + nif.clear_flag(NIF_O_HEATSINKS,NIF_FLAGS_OTHER) + + life() + if((. = ..())) + //Not being used, all clean. + if(!active && !used) + return TRUE + + //Being used, and running out. + else if(active && ++used == 100) + 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" + desc = "A system that allows one to apply 'laws' to sapient life. Extremely illegal, of course." + list_pos = NIF_COMPLIANCE + cost = 8200 + wear = 4 + illegal = TRUE + vended = FALSE + 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) + + activate() + if((. = ..())) + to_chat(nif.human,"You are compelled to follow these rules: \n[laws]") + + install() + if((. = ..())) + to_chat(nif.human,"You feel suddenly compelled to follow these rules: \n[laws]") + + uninstall() + nif.notify("ERROR! Unable to comply!",TRUE) + return FALSE //NOPE. + + stat_text() + return "Show Laws" + +/datum/nifsoft/sizechange + name = "Mass Alteration" + desc = "A system that allows one to change their size, through drastic mass rearrangement. Causes significant wear when installed." + list_pos = NIF_SIZECHANGE + cost = 750 + wear = 6 + + activate() + if((. = ..())) + var/choice = alert(nif.human,"Change which way?","Mass Alteration","Size Up","Cancel", "Size Down") + if(choice == "Cancel") + spawn(0) deactivate() + return FALSE + + if(!nif.use_charge(100)) + nif.notify("Insufficient energy to resize!",TRUE) + spawn(0) deactivate() + return FALSE + + if(choice == "Size Up") + switch(nif.human.size_multiplier) + if(RESIZE_BIG to RESIZE_HUGE) + nif.human.resize(RESIZE_HUGE) + if(RESIZE_NORMAL to RESIZE_BIG) + nif.human.resize(RESIZE_BIG) + if(RESIZE_SMALL to RESIZE_NORMAL) + nif.human.resize(RESIZE_NORMAL) + if((0 - INFINITY) to RESIZE_TINY) + nif.human.resize(RESIZE_SMALL) + + else if(choice == "Size Down") + switch(nif.human.size_multiplier) + if(RESIZE_HUGE to INFINITY) + nif.human.resize(RESIZE_BIG) + if(RESIZE_BIG to RESIZE_HUGE) + nif.human.resize(RESIZE_NORMAL) + if(RESIZE_NORMAL to RESIZE_BIG) + nif.human.resize(RESIZE_SMALL) + if((0 - INFINITY) to RESIZE_NORMAL) + nif.human.resize(RESIZE_TINY) + + nif.human.visible_message("Swirling grey mist envelops [nif.human] as they change size!","Swirling streams of nanites wrap around you as you change size!") + nif.human.update_icons() + + spawn(0) + deactivate() + + deactivate() + if((. = ..())) + return TRUE + + stat_text() + return "Change Size" \ No newline at end of file diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm index 63a1d2ff50..478ebc4d38 100644 --- a/code/modules/organs/organ_external.dm +++ b/code/modules/organs/organ_external.dm @@ -98,6 +98,8 @@ while(null in owner.organs) owner.organs -= null + implants.Cut() //VOREStation Add - Remove these too! + return ..() /obj/item/organ/external/emp_act(severity) diff --git a/code/modules/research/designs_vr.dm b/code/modules/research/designs_vr.dm index 07285cf921..64ed9b5d30 100644 --- a/code/modules/research/designs_vr.dm +++ b/code/modules/research/designs_vr.dm @@ -77,6 +77,14 @@ build_path = /obj/item/device/universal_translator/ear sort_string = "HABBB" +/datum/design/item/nif + name = "nanite implant framework" + id = "nif" + req_tech = list(TECH_MAGNET = 5, TECH_BLUESPACE = 5, TECH_MATERIAL = 5, TECH_ENGINEERING = 5, TECH_DATA = 5) + materials = list(DEFAULT_WALL_MATERIAL = 5000, "glass" = 8000, "uranium" = 6000, "diamond" = 6000) + build_path = /obj/item/device/nif + sort_string = "HABBC" + // Resleeving Circuitboards /datum/design/circuit/transhuman_clonepod diff --git a/code/modules/resleeving/implant.dm b/code/modules/resleeving/implant.dm index d5e2dfac6a..e6dd47b705 100644 --- a/code/modules/resleeving/implant.dm +++ b/code/modules/resleeving/implant.dm @@ -49,7 +49,8 @@ BITSET(H.hud_updateflag, BACKUP_HUD) //Okay we've got a mind at least if(H == imp_in && H.mind && H.stat < DEAD) - transcore.m_backup(H.mind) + transcore.m_backup(H.mind,H.nif) + persist_nif_data(H) spawn(attempt_delay) backup() diff --git a/code/modules/resleeving/infocore.dm b/code/modules/resleeving/infocore.dm index e03e3291a9..dc0b06d8bd 100644 --- a/code/modules/resleeving/infocore.dm +++ b/code/modules/resleeving/infocore.dm @@ -40,7 +40,7 @@ var/datum/transhuman/infocore/transcore = new/datum/transhuman/infocore spawn(process_time) process() -/datum/transhuman/infocore/proc/m_backup(var/datum/mind/mind) +/datum/transhuman/infocore/proc/m_backup(var/datum/mind/mind,var/obj/item/device/nif/nif) ASSERT(mind) if(!mind.name || core_dumped) return 0 @@ -50,6 +50,20 @@ var/datum/transhuman/infocore/transcore = new/datum/transhuman/infocore if(mind.name in backed_up) MR = backed_up[mind.name] MR.last_update = world.time + if(nif) + MR.nif_path = nif.type + MR.nif_durability = nif.durability + var/list/nifsofts = list() + for(var/N in nif.nifsofts) + if(N) + var/datum/nifsoft/nifsoft = N + nifsofts += nifsoft.type + MR.nif_software = nifsofts + else + MR.nif_path = null + MR.nif_durability = null + MR.nif_software = null + else MR = new(mind, mind.current, 1) @@ -114,6 +128,10 @@ var/datum/transhuman/infocore/transcore = new/datum/transhuman/infocore var/languages var/mind_oocnotes + var/nif_path + var/nif_durability + var/list/nif_software + /datum/transhuman/mind_record/New(var/datum/mind/mind,var/mob/living/carbon/human/M,var/obj/item/weapon/implant/backup/imp,var/add_to_db = 1) ASSERT(mind && M && imp) diff --git a/code/modules/resleeving/machines.dm b/code/modules/resleeving/machines.dm index abab41e929..4216f6fb0a 100644 --- a/code/modules/resleeving/machines.dm +++ b/code/modules/resleeving/machines.dm @@ -504,6 +504,12 @@ occupant.ooc_notes = MR.mind_oocnotes occupant.apply_vore_prefs() //Cheap hack for now to give them SOME bellies. + //Re-supply a NIF if one was backed up with them. + if(MR.nif_path) + var/obj/item/device/nif/nif = new MR.nif_path(occupant,MR.nif_durability) + for(var/path in MR.nif_software) + new path(nif) + // If it was a custom sleeve (not owned by anyone), update namification sequences if(!occupant.original_player) occupant.real_name = occupant.mind.name diff --git a/code/modules/vore/persist/persist_vr.dm b/code/modules/vore/persist/persist_vr.dm index 977473812a..bddd9bc7b9 100644 --- a/code/modules/vore/persist/persist_vr.dm +++ b/code/modules/vore/persist/persist_vr.dm @@ -78,6 +78,10 @@ WARNING("persist_interround_data failed to prep [occupant] for persisting") return + //This one doesn't rely on persistence prefs + if(ishuman(occupant) && occupant.stat != DEAD) + persist_nif_data(occupant, prefs) + if(!prefs.persistence_settings) return // Persistence disabled by preference settings @@ -94,6 +98,7 @@ if(prefs.persistence_settings & PERSIST_WEIGHT) resolve_excess_nutrition(H) prefs.weight_vr = H.weight + prefs.save_character() // Saves mob's current coloration state to prefs @@ -212,7 +217,30 @@ * towards future shenanigans such as upgradable NIFs or different types or things of that nature, * without invoking the need for a bunch of different save file variables. */ -/proc/persist_nif_data(var/mob/living/carbon/human/H) +/proc/persist_nif_data(var/mob/living/carbon/human/H,var/datum/preferences/prefs) if(!istype(H)) CRASH("persist_nif_data given a nonhuman: [H]") + if(!prefs) + prefs = prep_for_persist(H) + + if(!prefs) + WARNING("persist_nif_data failed to prep [H] for persisting") + return + + var/obj/item/device/nif/nif = H.nif + + if(nif) + prefs.nif_path = nif.type + prefs.nif_durability = nif.durability + else + prefs.nif_path = null + prefs.nif_durability = 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"] + + var/savefile/S = new /savefile(prefs.path) + if(!S) WARNING ("Couldn't load NIF save savefile? [prefs.real_name]") + S.cd = "/character[prefs.default_slot]" + nif_prefs.save_character(S) diff --git a/icons/obj/vending_vr.dmi b/icons/obj/vending_vr.dmi index b6c7cbb8e6..e7f1f48d32 100644 Binary files a/icons/obj/vending_vr.dmi and b/icons/obj/vending_vr.dmi differ diff --git a/maps/tether/tether-01-surface.dmm b/maps/tether/tether-01-surface.dmm index a9046f15e7..564f67fe31 100644 --- a/maps/tether/tether-01-surface.dmm +++ b/maps/tether/tether-01-surface.dmm @@ -1152,7 +1152,7 @@ "awh" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0},/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor/tiled,/area/tether/surfacebase/atrium_one) "awi" = (/obj/effect/floor_decal/borderfloor{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/structure/disposalpipe/junction{dir = 1; icon_state = "pipe-j2"},/obj/effect/floor_decal/industrial/danger{dir = 4},/obj/effect/floor_decal/steeldecal/steel_decals7{dir = 9},/obj/effect/floor_decal/steeldecal/steel_decals7{dir = 10},/turf/simulated/floor/tiled,/area/tether/surfacebase/atrium_one) "awj" = (/obj/machinery/status_display{pixel_y = 30},/obj/machinery/vending/fitness,/obj/effect/floor_decal/corner/lightgrey{dir = 9},/obj/effect/floor_decal/corner/lightgrey{dir = 6},/turf/simulated/floor/tiled/monotile,/area/crew_quarters/locker/laundry_arrival) -"awk" = (/obj/machinery/vending/cola,/obj/effect/floor_decal/corner/lightgrey{dir = 9},/obj/effect/floor_decal/corner/lightgrey{dir = 6},/turf/simulated/floor/tiled/monotile,/area/crew_quarters/locker/laundry_arrival) +"awk" = (/obj/structure/disposalpipe/segment{dir = 4},/obj/effect/floor_decal/borderfloor{dir = 1},/obj/effect/floor_decal/corner/lightgrey/border{dir = 1},/obj/effect/floor_decal/steeldecal/steel_decals7{dir = 4},/obj/effect/floor_decal/steeldecal/steel_decals7,/obj/machinery/vending/nifsoft_shop,/turf/simulated/floor/tiled,/area/tether/surfacebase/atrium_three) "awl" = (/obj/machinery/vending/snack,/obj/effect/floor_decal/corner/lightgrey{dir = 9},/obj/effect/floor_decal/corner/lightgrey{dir = 6},/turf/simulated/floor/tiled/monotile,/area/crew_quarters/locker/laundry_arrival) "awm" = (/obj/machinery/camera/network/civilian,/obj/machinery/vending/coffee,/obj/effect/floor_decal/corner/lightgrey{dir = 9},/obj/effect/floor_decal/corner/lightgrey{dir = 6},/turf/simulated/floor/tiled/monotile,/area/crew_quarters/locker/laundry_arrival) "awn" = (/obj/effect/floor_decal/borderfloor{dir = 9},/obj/effect/floor_decal/corner/lightgrey/border{dir = 9},/turf/simulated/floor/tiled,/area/crew_quarters/locker/laundry_arrival) @@ -4237,7 +4237,7 @@ "bDy" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/structure/disposalpipe/segment,/obj/effect/floor_decal/steeldecal/steel_decals4{dir = 4},/obj/effect/floor_decal/steeldecal/steel_decals4{dir = 9},/turf/simulated/floor/tiled,/area/tether/surfacebase/atrium_three) "bDz" = (/obj/structure/cable{icon_state = "1-2"},/obj/effect/floor_decal/borderfloor{dir = 1},/obj/effect/floor_decal/corner/lightgrey/border{dir = 1},/obj/effect/floor_decal/borderfloor/corner2{dir = 4},/obj/effect/floor_decal/corner/lightgrey/bordercorner2{dir = 4},/obj/effect/floor_decal/steeldecal/steel_decals7{dir = 4},/obj/effect/floor_decal/steeldecal/steel_decals7,/turf/simulated/floor/tiled,/area/tether/surfacebase/atrium_three) "bDA" = (/obj/structure/disposalpipe/segment{dir = 4; icon_state = "pipe-c"},/obj/machinery/firealarm{dir = 2; layer = 3.3; pixel_x = 0; pixel_y = 26},/obj/effect/floor_decal/borderfloor{dir = 1},/obj/effect/floor_decal/corner/lightgrey/border{dir = 1},/obj/effect/floor_decal/steeldecal/steel_decals7{dir = 4},/obj/effect/floor_decal/steeldecal/steel_decals7,/turf/simulated/floor/tiled,/area/tether/surfacebase/atrium_three) -"bDB" = (/obj/structure/disposalpipe/segment{dir = 4},/obj/effect/floor_decal/borderfloor{dir = 1},/obj/effect/floor_decal/corner/lightgrey/border{dir = 1},/obj/effect/floor_decal/steeldecal/steel_decals7{dir = 4},/obj/effect/floor_decal/steeldecal/steel_decals7,/turf/simulated/floor/tiled,/area/tether/surfacebase/atrium_three) +"bDB" = (/obj/effect/floor_decal/corner/lightgrey{dir = 9},/obj/effect/floor_decal/corner/lightgrey{dir = 6},/obj/machinery/vending/nifsoft_shop,/turf/simulated/floor/tiled/monotile,/area/crew_quarters/locker/laundry_arrival) "bDC" = (/obj/machinery/disposal,/obj/structure/disposalpipe/trunk{dir = 8},/obj/effect/floor_decal/borderfloor{dir = 5},/obj/effect/floor_decal/corner/lightgrey/border{dir = 5},/turf/simulated/floor/tiled,/area/tether/surfacebase/atrium_three) "bDD" = (/obj/structure/cable/green{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/tiled/dark,/area/tcomsat{name = "\improper Telecomms Lobby"}) "bDE" = (/obj/machinery/atmospherics/unary/vent_pump/on{dir = 1},/obj/machinery/porta_turret{dir = 6},/turf/simulated/floor/tiled/dark,/area/tcomsat{name = "\improper Telecomms Lobby"}) @@ -5455,7 +5455,7 @@ aaaaadaadaadaadaadaadaadaadaadaagaagamGasrassastasuasuasuasuasuasuasvaswasxasyas aaaaadaadaadaadaadaadaadaadaadaagamGamGamGamGatcaoZaoZatdateatfatgathaoZatiatjatkatlatmatnatoatparpatqatratratratratsasLattatuatvatwatxatxatxatyasLatzatAasOatBatCatCatCatCatCatCagIagIagIaagaagaagaagaagaagaagagIatDatEatFatGatGatGatGatGatHatGatGatGatGatGatGatIatJanRatKaoTaoTatLatMatNatOaoTaoWaslanRaagapCapCapCapCatPataaqWaqnaqoarCarBarCarCarCarCarBarCaqrapCaaa aaaaadaadaadaadaadaadaadaadaagaagamGatQatRatSatTaoZaquaotatQamGatUatVatWamGatXatYarparparparparparpatZauaauaauaauaauaasLaubaucaudaueaufaufaufaugasLbeQauibeSaukatCaulaulaulaulatCaumaunagIagIagIagIauoagIagIagIagIaupakuauqaurausautautauuauvauwauxautautautauyajPajQanRauzauzauAauBauCauDauEauFauGauHanRaagapCauIauIapCauJataaqWaqnaqoarCarBarCarCarCarCarBarCaqrapCaaa aaaaadaadaadaadaadaadaadaadaagaagamGauKaoZaoZatTaoZauLaotauMamGatUauNauOamGauPauQbfxarXarXarXarXauSauTauaauUauVauWauXauYauZavaavbavcavdavdavdaveasLaZkavgasOavhatCaulaulaulaulaulaviavjavkavlavmavnavnavoavpavqavravsavtavuagIagIavvavvavvavvavvavvavwavvavvavxajPajQanRanRanRanRavyavzanRanRanRanRanRavAagIapCavBavBapCavCavDaqWaqnaqoarCarBarCarCarCarCarBarCaqYapCaaa -aaaaadaadaadaadaadaadaadaadaadaagamGavEavFavGavHbhtavJaotatQamGavKavLavMamGavNavOauaauaauaauaauaauaauaauaavPavQavRavSavTavUavVavWavXavYavYavZawaasLawbavgasOavhatCaulaulaulaulaulaviaviaviawcaviaviawdaviaweatGawfawgawhawiamgagXavvawjawkawlawmawnawoawpavvawqawrawsawtawuawvawwawxawyawzawAawBawCawDawEawuawFawGawGawHawIawJaqWaqnaqoarCarBarCarCarCarCarBarCaqrapCaaa +aaaaadaadaadaadaadaadaadaadaadaagamGavEavFavGavHbhtavJaotatQamGavKavLavMamGavNavOauaauaauaauaauaauaauaauaavPavQavRavSavTavUavVavWavXavYavYavZawaasLawbavgasOavhatCaulaulaulaulaulaviaviaviawcaviaviawdaviaweatGawfawgawhawiamgagXavvawjbDBawlawmawnawoawpavvawqawrawsawtawuawvawwawxawyawzawAawBawCawDawEawuawFawGawGawHawIawJaqWaqnaqoarCarBarCarCarCarCarBarCaqrapCaaa aaaaadaadaadaadaadaadaadaadaadaagawKawKawKawKawKawKawKawKawKawKawKawKawKawKawLavOauaawMawNawOawPawQawRawSawTawUawVawWauYawXawYawZaxaaxbaxcaxdaxeblMaxgblPasOavhatCaxiaulaulaulatCaxjaxkaxlaxmaxnaxoaxpaxqaxraxsaxtaxuaxvaxwagIagIavvaxxaxyaxzaxzaxAbZmaxCaxDaxEasRawgaxFatGatGaxGatGaxHaxIatGatGawgatGatGaxJaxKaxLaxMaxNaxKaxOaqWaqnaqoarCarBarCarCarCarCarBarCaqratbaaa aaaaadaadaadaadaadaadaadaadaadaagarpaxPaxQaxRaxRaxSaxRaxTaxUaxRaxRaxUaxRbphaxWavOauaaxXaxYaxZayaaybayaayaayaayaaycaydauYayeayfaygayhayiayjaykaylasLakYaymasObpiatCatCatCatCatCatCayoaypagIagIagIagIagIagIayqagIagIagIagIagIagIaagavvayraysaytayuayvaywayxayyayzayAayBayCayDayEayFayDayGayHayHayIayJayKayHayHayLayMayNayOayPayQaqWaqnaqoarCarBarCarCarCarCarBarCaqrapCaaa aaaaadaadaadaadaadaadaadaadaadaagarpayRaySayTayTayTayTayTayTayTayTayTayTayTayUayVauaayWawUayXayYayZayZayZazaazbazcazdasLasLasLauYauYazeasLasLasLasLaagazfasOasOasPasPasPasPasPasPagIagIagIaagaagaagaagazgazhazgaagaagaagaagaagaagavvaziazjazkazkavvazlazmavvagIagIaznagIagIagIagIagIazoagIagIagIagIagIauoagIapCazpazpapCavCazqaqWaqnaqoarCarBarCarCarCarCarBarCaqYapCaaa @@ -5687,7 +5687,7 @@ boYboZboZboZboZboZboZboZboZboZboZboZboZbpabpabpabpabpabpabpabpabpabpabpabpabpabp boYboZboZboZboZboZboZboZboZboZboZboZboZbpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabqfbzhbCibAWbBFbBGbBGbBHbBHbBHbBHbBHbBIbBJbAFbAGbCjbznbCkbClbClbCmbCnbAHbCobznbpabpabpabpabzrbBnbCpbzrbCqbCqbzrbCrbBqbzwbAhbAibAibAibAibAibAibAibAibAibAibAibAibAibAibAibAjbvEbCsbCtbCubCubCubCvbCubCwbCxbCwbCwbCwbCwbCybCybCybCybpabpaboZboZboZboZboZboZboZboZboZboZboZboZboY boYboZboZboZboZboZboZboZboZboZboZboZboZbpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabzhbCzbAWbBFbBGbBGbCAbzObCBbBHbBHbBIbBJbAFbAGbCCbznbCDbCEbCFbCGbCHbAHbCIbznbpabpabpabpabzrbCJbCKbzrbCqbCqbzrbCLbBqbzwbAhbAibAibAibAibAibAibAibAibAibAibAibAibAibAibAibAjbvEbBUbCMbCNaMZaNybCQbCRbCSbCTbCUbCVbCWbCSbCXbCYbCZbDabpabpabpabpaboZboZboZboZboZboZboZboZboZboZboY boYboZboZboZboZboZboZboZboZboZboZboZboZbpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabzGbAVbAWbBFbBGbBGbDbbDcbDdbBHbBHbBIbBJbAFbAGbCjbznbznbznbznbDebDfbzobznbznbwObwOaHnaHnbzrbzrbzrbzrbzrbzrbzrbDgbDhbzwbIIbAibAibAibAibAibAibAibAibAibAibAibAibAibAibAibAjbvEbDibDjbDkbDlbDmbDnbDobCSbDpbCTbCTbDqbCSbDrbDsbDtbDabpabpabpabpaboZboZboZboZboZboZboZboZboZboZboY -boYboZboZboZboZboZboZboZboZboZboZboZbpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabzGbDubDvbBFbBGbBGbBGbBGbBGbBHbBHbBIbBJbAFbAGbAGbzibDwbwVbDxbDybDzbxbbxobDAbDBbDCaHnbmbbdqbaMaHobwsaPTaPFbwsbDIbBqaQRaQQbAhbAibAibAibAibAibAibAibAibAibAibAibAibAibAibAjbvEbBUbDJbwsbwsbDKbDLbDMbCSbDNbCTbCTbDObCSbDsbDsbDPbDabpabpabpabpaboZboZboZboZboZboZboZboZboZboZboY +boYboZboZboZboZboZboZboZboZboZboZboZbpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabzGbDubDvbBFbBGbBGbBGbBGbBGbBHbBHbBIbBJbAFbAGbAGbzibDwbwVbDxbDybDzbxbbxobDAawkbDCaHnbmbbdqbaMaHobwsaPTaPFbwsbDIbBqaQRaQQbAhbAibAibAibAibAibAibAibAibAibAibAibAibAibAibAjbvEbBUbDJbwsbwsbDKbDLbDMbCSbDNbCTbCTbDObCSbDsbDsbDPbDabpabpabpabpaboZboZboZboZboZboZboZboZboZboZboY boYboZboZboZboZboZboZboZboZboZboZboZbpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabzGbAVbDQbBFbBGbBGbBGbBGbBGbBHbBHbBIbDRbDSbDTbDUbDVbDWbyobyobDXbDYbyxbyxbDZbygbEaaHnbmmbmlbmlbmjbwsbEebEfbEgbEhbEiaRsaRrbAhbAibAibAibAibAibAibAibAibAibAibAibAibAibAibAjbEkbElbEmbEnbEobEpbEqaRGbCSbEsbEtbEubEvbCSbEwbExbDsbDabpabpabpabpaboZboZboZboZboZboZboZboZboZboZboY boYboZboZboZboZboZboZboZboZboZboZboZbpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabzhbEybDQbEzbEAbEAbEAbEAbEAbEBbEBbECbEDbEEbEFbEGbEHbEIbEJbEJbEJbEKbELbEMbENbEObEPbmtbmwbmvbmvbmubwsaRZbDHbwsbEVbzvaSdaSabAhbAibAibAibAibAibAibAibAibAibAibAibAibAibAibAjbEXbBUbEYbEZbwsaSCbCQaSBbCSbFcbFdbFebFfbCSbFgbFhbFibDabpabpabpabpaboZboZboZboZboZboZboZboZboZboZboY boYboZboZboZboZboZboZboZboZboZboZboZbpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabzhbFjbFkbFlbFlbFlbFlbFlbFlbFlbFlbFlbFmbFnbFobFpbzhbwsbzZbzZbzZbwsbwsbvEbyVbFqbFraHnbmbbmybmxaHobwsbwsbwsbwsbFubzvaTeaTabAhbAibAibAibAibAibAibAibAibAibAibAibAibAibAibAjbEXbBUbFvbDkbDkbDkaTybDkbCSbCSbFxbFybCSbCSbFzbFAbFzbFBbpabpabpabpaboZboZboZboZboZboZboZboZboZboZboY diff --git a/maps/tether/tether-03-station.dmm b/maps/tether/tether-03-station.dmm index 221a24b85b..3c0a2abc28 100644 --- a/maps/tether/tether-03-station.dmm +++ b/maps/tether/tether-03-station.dmm @@ -2680,7 +2680,7 @@ "aZB" = (/obj/machinery/door/firedoor/glass,/obj/structure/disposalpipe/segment,/obj/machinery/door/blast/regular{density = 0; dir = 4; icon_state = "pdoor0"; id = "englockdown"; name = "Engineering Lockdown"; opacity = 0},/obj/machinery/door/airlock/glass_engineering{name = "Engineering Mezzenine"; req_one_access = list()},/turf/simulated/floor/tiled/steel_grid,/area/engineering/foyer_mezzenine) "aZC" = (/obj/machinery/door/airlock/maintenance/engi,/obj/structure/cable{icon_state = "1-2"},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/door/firedoor/glass,/turf/simulated/floor/plating,/area/hallway/station/port) "aZD" = (/obj/machinery/vending/snack,/obj/effect/floor_decal/corner/lightgrey{dir = 9},/obj/effect/floor_decal/corner/lightgrey{dir = 6},/obj/effect/floor_decal/steeldecal/steel_decals9,/obj/effect/floor_decal/steeldecal/steel_decals9{dir = 4},/obj/effect/floor_decal/steeldecal/steel_decals9{dir = 1},/obj/effect/floor_decal/steeldecal/steel_decals9{dir = 8},/turf/simulated/floor/tiled,/area/hallway/station/port) -"aZE" = (/obj/machinery/vending/cola,/obj/effect/floor_decal/corner/lightgrey{dir = 9},/obj/effect/floor_decal/corner/lightgrey{dir = 6},/obj/effect/floor_decal/steeldecal/steel_decals9,/obj/effect/floor_decal/steeldecal/steel_decals9{dir = 4},/obj/effect/floor_decal/steeldecal/steel_decals9{dir = 1},/obj/effect/floor_decal/steeldecal/steel_decals9{dir = 8},/turf/simulated/floor/tiled,/area/hallway/station/starboard) +"aZE" = (/obj/effect/floor_decal/corner/lightgrey{dir = 9},/obj/effect/floor_decal/corner/lightgrey{dir = 6},/obj/effect/floor_decal/steeldecal/steel_decals9,/obj/effect/floor_decal/steeldecal/steel_decals9{dir = 4},/obj/effect/floor_decal/steeldecal/steel_decals9{dir = 1},/obj/effect/floor_decal/steeldecal/steel_decals9{dir = 8},/obj/machinery/vending/nifsoft_shop,/turf/simulated/floor/tiled,/area/hallway/station/starboard) "aZF" = (/obj/machinery/vending/coffee,/obj/effect/floor_decal/corner/lightgrey{dir = 9},/obj/effect/floor_decal/corner/lightgrey{dir = 6},/obj/effect/floor_decal/steeldecal/steel_decals9,/obj/effect/floor_decal/steeldecal/steel_decals9{dir = 4},/obj/effect/floor_decal/steeldecal/steel_decals9{dir = 1},/obj/effect/floor_decal/steeldecal/steel_decals9{dir = 8},/turf/simulated/floor/tiled,/area/hallway/station/starboard) "aZG" = (/turf/simulated/wall/r_wall,/area/hallway/station/starboard) "aZH" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0},/obj/effect/floor_decal/borderfloor{dir = 8},/obj/effect/floor_decal/corner/lightgrey/border{dir = 8},/obj/effect/floor_decal/steeldecal/steel_decals7{dir = 5},/obj/effect/floor_decal/steeldecal/steel_decals7{dir = 6},/turf/simulated/floor/tiled,/area/hallway/station/starboard) diff --git a/maps/tether/tether-06-colony.dmm b/maps/tether/tether-06-colony.dmm index 9c04bd82cf..45192898b2 100644 --- a/maps/tether/tether-06-colony.dmm +++ b/maps/tether/tether-06-colony.dmm @@ -1363,6 +1363,8 @@ "Ak" = (/obj/structure/table/reinforced,/obj/item/device/camera,/obj/item/weapon/storage/box/ids,/obj/effect/floor_decal/borderfloorblack{dir = 8},/obj/effect/floor_decal/corner/blue/border{dir = 8},/obj/effect/floor_decal/borderfloorblack/corner2{dir = 10},/obj/effect/floor_decal/corner/blue/bordercorner2{dir = 10},/turf/unsimulated/floor{icon_state = "vault"; dir = 5},/area/centcom/security{name = "\improper CentCom Residential Security"}) "Al" = (/obj/structure/table/reinforced,/obj/machinery/computer/skills,/obj/effect/floor_decal/borderfloorblack{dir = 4},/obj/effect/floor_decal/corner/blue/border{dir = 4},/obj/effect/floor_decal/borderfloorblack/corner2{dir = 5},/obj/effect/floor_decal/corner/blue/bordercorner2{dir = 5},/turf/unsimulated/floor{icon_state = "vault"; dir = 5},/area/centcom/security{name = "\improper CentCom Residential Security"}) "Am" = (/obj/effect/floor_decal/borderfloorblack,/obj/effect/floor_decal/corner/blue/border,/obj/effect/floor_decal/borderfloorblack/corner2{dir = 9},/obj/effect/floor_decal/borderfloorblack/corner2,/obj/effect/floor_decal/corner/blue/bordercorner2{dir = 9},/obj/effect/floor_decal/corner/blue/bordercorner2,/turf/unsimulated/floor{icon_state = "vault"; dir = 5},/area/centcom/security{name = "\improper CentCom Residential Security"}) +"An" = (/obj/effect/floor_decal/borderfloor,/obj/effect/floor_decal/corner/blue/border,/obj/machinery/vending/nifsoft_shop,/turf/unsimulated/floor/steel,/area/centcom/security) +"Ao" = (/obj/machinery/vending/nifsoft_shop,/turf/unsimulated/floor/steel{icon = 'icons/turf/floors_vr.dmi'; icon_state = "wood"},/area/centcom/restaurant) (1,1,1) = {" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa @@ -1441,7 +1443,7 @@ aaababababababababababababababababababababababababababjMkikhkhkikjkkjMababababab aaababababababababababababababababababababababababababjMlLkhkhkikjkkjMababababababacgGgGgGgGgGgGgGnHnInJnKnLhrhrnMnNnOkHnPnQnRlUlUnSnTlUnSnTlUlUnUnVnWkHltlololololonXnYnZlololololooakHahahahejobocodoeofogmdmdejkJhlhlhlhlnEohnFohnFnFoinGkKeS aaabababababababababababababababojokokokokokokokokokokolomononomomomomababababababacacacacacacacgGgGgGgGhthtoohrgGgGgGkHkHkHkHopoqkHkHorkHkHosoqkHkHkHotototototototototototototototototahahahouejejejejejovjKjKejkJhlkFkDkEhlowowowowowowhlkKeS aaabababababababababababababababomoxoyozoyoyoyoyozoyoAoBoCoCoCoDoEabababababababababacacacacacacgGoFoGoHoGoIhrhroJoGoKkHoLoMoNlUlUoOoPlUoQoRlUlUoSoToLotoUoVoWoXotoYoZpaoZoYotpbpbpbpbotahahahpclGkekelHkekdhlhlkclFhlkKejkJhlhlhlhlhlhlhlhlkKeS -aaabababababababababababababababomoxoyfyeWeWeWeWfyoyoAoBoCoCoCpfoEabababababababababacacacacacacgGpglPhrlPphhrhrhrhrpikHpjlUlUlUlUpklTnwlXpllUlUlUlUpmotoUpnoWoXotpopopopopootppppppppotahahahpckFkChlkBkDkDkChlkBkChlpqejprkDkDkDkEkFkDpsptpueS +aaabababababababababababababababomoxoyfyeWeWeWeWfyoyoAoBoCoCoCpfoEabababababababababacacacacacacgGpglPhrlPphhrhrhrhrpikHpjlUlUlUlUpklTnwlXpllUlUlUlUpmotoUpnoWoXotpopopopopootppppppppotahahahpckFkChlkBkDkDkChlkBkChlpqejprAnkDkDkEkFkDpsptpueS aaabababababababababababababababomoxfyfTfRhchcipfTfyoAoBoCoCoCpzoEabababababababababacacacacacacgGpAmkpBpCmkhrhrhrhrpDkHpjlUlUlUlUpEpFpFpFpGlUlUlUlUpHotoUpnoWpnpIpopopopopopJpopopopKotahahahouejejpcejejejejpLejejpcejejpMpNpNpNlFlGpNpNpNpOeS aaabababababababababababababababompPeWpdkMhchckMpeeWoAoBoCoCoCpzoEabababababababababacacacacacacgGmKhrhrhrhrhrhrhrhrpTkHpjlUlUlUlUlUlUlUlUlUlUlUlUlUpmotoUpnpnpnpIpopopopopopJpopopopKotbHahahjJpUpVhlpWpXjJsfhlpvpwhlqbejqcqdqdqdhlhlqdqdqdqeeS aaabababababababababababababababomoxeWpxpxhchcpxpxeWoAoBoCoCoCpzoEabababababababababababacacacacgGmKhrhrhrhrhrhrhrhrqgkHpjlUlUlUlUlUlUlUlUlUlUlUlUlUpmotoUpnpnqhotpoqipoqipootqjqjqjqjotahahahjJqknGhlhlqlqmqnhlhlqoqpqqejqrqsqsqsqsqsqsqsqsqteS @@ -1452,7 +1454,7 @@ aaabababababababababababababababomoxqfpxpxhchcpxpxqfoAoBoCoCahrKahahahahahahahah aaabababababababababababababababomoxqfipiphchcipipqfoAoBoCoCrTrKahahahahahahahahahahahahahahahahahrpahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahjDahahahjDahahahahahrLahrMrMrMrMahrNrzrzrzrzrOrUrQrRrRrSrI aaabababababababababababababababomoxeWqvkMhchckMqweWoAoBoCoCadriahahahahahahahahahrMrMrMrMrMrMahahqUahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahahjDahahahjDahahahahahrXrYrYrYrYrYrYrZrzrzrzrzrCrDsasbsbscrI aaabababababababababababababababomoxfyqVpxhchcpxrgfyoAoBoCoCqWqXqXqXqXqXqXqXqXqXqXqXqXqXrhrVrJrJrVrhqXqXqXqXshjDqXqXshjDqXqXqXqXsisjsksjsisislslsisislslsijDjDjDotototsmototototslslslsijDjDjDejejejejejejousnsnsnsnsnsnouejejejejejejejejejejeS -aaabababababababababababababababquoxpyhchchchchchcpQoAoBoCoCoCoDoEabababababababababababrhsdrWsesdrhsrsrsraiahahssstahahaisrsrsrsisisisisisusvswsxswsyszsisAahahotsBsCsDsDsEsFotsGsHsIslahahahejsJsKsKsKsLejhlpYhlhlpYhlejsMsNsOsPsQejsRsSsTsUeS +aaabababababababababababababababquoxpyhchchchchchcpQoAoBoCoCoCoDoEabababababababababababrhsdrWsesdrhsrsrsraiahahssstahahaisrsrsrsisisisisisusvAosxswsyszsisAahahotsBsCsDsDsEsFotsGsHsIslahahahejsJsKsKsKsLejhlpYhlhlpYhlejsMsNsOsPsQejsRsSsTsUeS aaabababababababababababababababomoxsopxhcipiphcspsooAoBoCoCoCpzoEabababababababababababrhsVsqsXsWrhahtbtctctctctctctctctctctdahsiszsytetfswswswswswswswsiahahahottgsDsDthototottitjtkslahahahejtltmtmtmtnejejovtotoovejejtpfcfcfcfctqfcfcfctreS aaabababababababababababababababompPsosYhcipiphcsZsooAoBoCoCoCpzoEabababababababababababrhtstatattrhahtwtxtxtxtytxtxtytxtxtxtzahsiswswtAtAswswswtAtAswswsiahahahottgsDsDsDtBsFottCtDtEslahahahejtFfcfcfcfctGtHtIfcfctJtKtLfcfcfcfctMejtNfcfctreS aaabababababababababababababababomoxfyfTtupxtvhcfTfyoAoBoCoCoCpzoEabababababababababababrhtPtOuHtQrhtTtwtxtUtVtVtVtVtVtVtUtxtztWslswtXtYtZuaswtXubucuaswslahahahotudsDsDthotototuetDtEsiahahahejufugfcuhuiujukulfcfculumunuoupfcuqurejusututuueS diff --git a/maps/tether/tether-07-misc.dmm b/maps/tether/tether-07-misc.dmm index 9f4b9f4d35..c1189bb371 100644 --- a/maps/tether/tether-07-misc.dmm +++ b/maps/tether/tether-07-misc.dmm @@ -930,7 +930,7 @@ "rT" = (/obj/structure/table/rack,/obj/item/device/radio,/obj/item/device/radio,/obj/item/device/radio,/obj/item/device/radio,/obj/item/device/radio,/obj/effect/floor_decal/borderfloorblack,/turf/unsimulated/floor{dir = 2; icon_state = "dark"},/area/antag/antag_base) "rU" = (/obj/structure/table/rack,/obj/item/weapon/pinpointer/nukeop,/obj/item/weapon/pinpointer/nukeop,/obj/item/weapon/pinpointer/nukeop,/obj/item/weapon/pinpointer/nukeop,/obj/item/weapon/pinpointer/nukeop,/obj/item/weapon/pinpointer/nukeop,/obj/effect/floor_decal/borderfloorblack,/turf/unsimulated/floor{dir = 2; icon_state = "dark"},/area/antag/antag_base) "rV" = (/obj/structure/table/rack,/obj/item/device/flashlight/flare,/obj/item/device/flashlight/flare,/obj/item/device/flashlight/flare,/obj/item/device/flashlight/flare,/obj/item/device/flashlight/flare,/obj/item/device/flashlight/flare,/obj/item/device/flashlight/flare,/obj/effect/floor_decal/borderfloorblack{dir = 6},/turf/unsimulated/floor{dir = 2; icon_state = "dark"},/area/antag/antag_base) -"rW" = (/obj/effect/floor_decal/borderfloorblack{dir = 8},/turf/unsimulated/floor{dir = 2; icon_state = "dark"},/area/antag/antag_base) +"rW" = (/obj/effect/floor_decal/borderfloorblack{dir = 8},/obj/machinery/vending/nifsoft_shop{categories = 111; emagged = 1; name = "Hacked NIFSoft Shop"; prices = list()},/turf/unsimulated/floor{dir = 2; icon_state = "dark"},/area/antag/antag_base) "rX" = (/obj/machinery/telecomms/allinone{intercept = 1},/turf/unsimulated/floor{dir = 2; icon_state = "dark"},/area/antag/antag_base) "rY" = (/obj/machinery/door/airlock/external{frequency = 1380; icon_state = "door_locked"; id_tag = "antag_ground_shuttle_hatch"; locked = 1; name = "Shuttle Hatch"; req_access = list(13)},/turf/simulated/shuttle/floor/black,/area/shuttle/antag_ground/base) "rZ" = (/obj/machinery/door/airlock/external{frequency = 1380; icon_state = "door_locked"; id_tag = "antag_space_shuttle_hatch"; locked = 1; name = "Shuttle Hatch"; req_access = list(13)},/turf/simulated/shuttle/floor/black,/area/shuttle/antag_space/base) diff --git a/sound/items/nif_click.ogg b/sound/items/nif_click.ogg new file mode 100644 index 0000000000..4bb8db9f30 Binary files /dev/null and b/sound/items/nif_click.ogg differ diff --git a/sound/items/nif_tone_bad.ogg b/sound/items/nif_tone_bad.ogg new file mode 100644 index 0000000000..d2c237acf3 Binary files /dev/null and b/sound/items/nif_tone_bad.ogg differ diff --git a/sound/items/nif_tone_good.ogg b/sound/items/nif_tone_good.ogg new file mode 100644 index 0000000000..e6365ba8db Binary files /dev/null and b/sound/items/nif_tone_good.ogg differ diff --git a/vorestation.dme b/vorestation.dme index 86ab4afd95..41f8895e95 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -1304,6 +1304,7 @@ #include "code\modules\client\preference_setup\vore\05_persistence.dm" #include "code\modules\client\preference_setup\vore\06_vantag.dm" #include "code\modules\client\preference_setup\vore\07_traits.dm" +#include "code\modules\client\preference_setup\vore\08_nif.dm" #include "code\modules\clothing\chameleon.dm" #include "code\modules\clothing\clothing.dm" #include "code\modules\clothing\clothing_accessories.dm" @@ -1971,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\14_commlink.dm" #include "code\modules\nifsoft\software\15_misc.dm" #include "code\modules\organs\blood.dm" #include "code\modules\organs\misc.dm"