Merge branch 'master' of https://github.com/VOREStation/VOREStation into Fluff_Items_worshop

This commit is contained in:
JoanRisu
2017-03-02 23:28:45 -08:00
105 changed files with 4451 additions and 330 deletions

View File

@@ -672,6 +672,8 @@ proc/admin_notice(var/message, var/rights)
//This is basically how death alarms do it
var/obj/item/device/radio/headset/a = new /obj/item/device/radio/headset/ert(null)
a.icon = 'icons/obj/radio.dmi' //VOREStation Tweak
a.icon_state = "intercom" //VOREStation Tweak
var/channel = input("Channel for message:","Channel", null) as null|anything in (list("Common") + a.keyslot1.channels + a.keyslot2.channels)

View File

@@ -38,6 +38,7 @@ proc/createRandomZlevel()
admin_notice("\red \b Loading away mission...", R_DEBUG)
var/map = pick(potentialRandomZlevels)
world.log << "Away mission picked: [map]" //VOREStation Add for debugging
var/file = file(map)
if(isfile(file))
maploader.load_map(file)

View File

@@ -0,0 +1,12 @@
//Org flags
//Ships you might see
#define ORG_HAS_NAVY 0x1
#define ORG_HAS_TRADERS 0x2
#define ORG_HAS_TECH 0x4
#define ORG_HAS_MERCS 0x8
#define ORG_HAS_DIPLO 0x10
//What they get up to kinda
#define ORG_HAS_SHADY 0x20
#define ORG_HAS_ENTERTAIN 0x40
#define ORG_HAS_HUGENESS 0x80

View File

@@ -0,0 +1,128 @@
//Cactus, Speedbird, Dynasty, oh my
var/datum/lore/atc_controller/atc = new/datum/lore/atc_controller
/datum/lore/atc_controller
var/delay_max = 25 MINUTES //How long between ATC traffic, max
var/delay_min = 40 MINUTES //How long between ATC traffic, min
var/backoff_delay = 5 MINUTES //How long to back off if we can't talk and want to
var/next_message //When the next message should happen in world.time
var/force_chatter_type //Force a specific type of messages
var/squelched = 0 //If ATC is squelched currently
/datum/lore/atc_controller/New()
spawn(100) //Lots of lag at the start of a shift.
msg("New shift beginning, resuming traffic control.")
next_message = world.time + rand(delay_min,delay_max)
process()
/datum/lore/atc_controller/proc/process()
if(world.time >= next_message)
if(squelched)
next_message = world.time + backoff_delay
else
next_message = world.time + rand(delay_min,delay_max)
random_convo()
spawn(1 MINUTE) //We don't really need high-accuracy here.
process()
/datum/lore/atc_controller/proc/msg(var/message,var/sender)
ASSERT(message)
global_announcer.autosay("[message]", sender ? sender : "Virgo Air/Space Control")
/datum/lore/atc_controller/proc/reroute_traffic(var/yes = 1)
if(yes)
msg("Rerouting traffic away from NSS Adaphagia.")
squelched = 1
else
msg("Resuming normal traffic routing around NSS Adaphagia.")
squelched = 0
/datum/lore/atc_controller/proc/shift_ending(var/evac = 0)
msg("Automated Shuttle departing NSS Virgo Central Command for NSS Adaphagia on routine transfer route.","NT Automated Shuttle")
sleep(5 SECONDS)
msg("Automated Shuttle, cleared to complete routine transfer from NSS Adaphagia to NSS Virgo Central Command.")
/datum/lore/atc_controller/proc/random_convo()
var/one = pick(loremaster.orgs) //These will pick an index, not an instance
var/two = pick(loremaster.orgs)
var/datum/lore/org/source = loremaster.orgs[one] //Resolve to the instances
var/datum/lore/org/dest = loremaster.orgs[two]
//Let's get some mission parameters
var/owner = source.sname //Use the short name
var/prefix = pick(source.ship_prefixes) //Pick a random prefix
var/mission = source.ship_prefixes[prefix] //The value of the prefix is the mission type that prefix does
var/shipname = pick(source.ship_names) //Pick a random ship name to go with it
var/destname = pick(dest.holding_names) //Pick a random holding from the destination
var/combined_name = "[owner] [prefix] [shipname]"
var/alt_atc_names = list("Virgo TraCon","Virgo Control","Virgo ATC","Virgo Airspace")
var/wrong_atc_names = list("Sol Command","Polaris TraCon","Orion Control")
var/mission_noun = list("flight","mission","route")
var/request_verb = list("requesting","calling for","asking for")
//First response is 'yes', second is 'no'
var/requests = list("Virgo transit clearance" = list("permission for transit granted", "permission for transit denied, contact regional on 953.5"),
"planetary flight rules" = list("authorizing planetary flight rules", "denying planetary flight rules right now due to traffic"),
"special flight rules" = list("authorizing special flight rules", "denying special flight rules, not allowed for your traffic class"),
"current solar weather info" = list("sending you the relevant information via tightbeam", "cannot fulfill your request at the moment"),
"nearby traffic info" = list("sending you current traffic info", "no available info in your area"),
"remote telemetry data" = list("sending telemetry now", "no uplink from your ship, recheck your uplink and ask again"),
"refueling information" = list("sending refueling information now", "no fuel for your ship class in this sector"),
"a current system time sync" = list("sending time sync ping to you now", "your ship isn't compatible with our time sync, set time manually"),
"current system starcharts" = list("transmitting current starcharts", "your request is queued, overloaded right now"),
"permission to engage FTL" = list("permission to engage FTL granted, good day", "permission denied, wait for current traffic to pass"),
"permission to transit system" = list("permission to transit granted, good day", "permission denied, wait for current traffic to pass"),
"permission to depart system" = list("permission to depart granted, good day", "permission denied, wait for current traffic to pass"),
"permission to enter system" = list("good day, permission to enter granted", "permission denied, wait for current traffic to pass"),
)
//Random chance things for variety
var/chatter_type = "normal"
if(force_chatter_type)
chatter_type = force_chatter_type
else
chatter_type = pick(2;"emerg",5;"wrong_freq","normal") //Be nice to have wrong_lang...
var/yes = prob(90) //Chance for them to say yes vs no
var/request = pick(requests)
var/callname = pick(alt_atc_names)
var/response = requests[request][yes ? 1 : 2] //1 is yes, 2 is no
var/full_request
var/full_response
var/full_closure
switch(chatter_type)
if("wrong_freq")
callname = pick(wrong_atc_names)
full_request = "[callname], this is [combined_name] on a [mission] [pick(mission_noun)] to [destname], [pick(request_verb)] [request]."
full_response = "[combined_name], this is Virgo TraCon, wrong frequency. Switch to [rand(700,999)].[rand(1,9)]."
full_closure = "Virgo TraCon, understood, apologies."
if("wrong_lang")
//Can't implement this until autosay has language support
if("emerg")
var/problem = pick("hull breaches on multiple decks","unknown life forms on board","a drive about to go critical","asteroids impacting the hull","a total loss of engine power","people trying to board the ship")
full_request = "This is [combined_name] declaring an emergency! We have [problem]!"
full_response = "[combined_name], this is Virgo TraCon, copy. Switch to emergency responder channel [rand(700,999)].[rand(1,9)]."
full_closure = "Virgo TraCon, okay, switching now."
else
full_request = "[callname], this is [combined_name] on a [mission] [pick(mission_noun)] to [destname], [pick(request_verb)] [request]."
full_response = "[combined_name], this is Virgo TraCon, [response]." //Virgo TraCon always calls themselves TraCon
full_closure = "Virgo TraCon, [yes ? "thank you" : "understood"], good day." //They always copy what TraCon called themselves in the end when they realize they said it wrong
//Ship sends request to ATC
msg(full_request,"[prefix] [shipname]")
sleep(5 SECONDS)
//ATC sends response to ship
msg(full_response)
sleep(5 SECONDS)
//Ship sends response to ATC
msg(full_closure,"[prefix] [shipname]")
return

View File

@@ -0,0 +1,14 @@
//I AM THE LOREMASTER, ARE YOU THE GATEKEEPER?
var/datum/lore/loremaster/loremaster = new/datum/lore/loremaster
/datum/lore/loremaster
var/list/orgs = list()
/datum/lore/loremaster/New()
var/paths //Just reuse this a bunch of times.
paths = typesof(/datum/lore/org) - /datum/lore/org
for(var/path in paths)
var/datum/lore/org/instance = new path()
orgs[path] = instance

View File

@@ -0,0 +1,360 @@
//Datums for different companies that can be used by busy_space
/datum/lore/org
var/name = "" //Organization's name
var/sname = "" //Org's shortname (NanoTrasen for "NanoTrasen Incorporated")
var/desc = "" //Long description of org, but only current stuff, see 'history'
var/history = "" //Historical discription of org's origins
var/work = "" //Short description of their work, eg "an arms manufacturer"
var/headquarters = "" //Location of Org's HQ
var/motto = "" //A motto, if they have one
var/org_flags = 0 //Flags for the org
var/list/ship_prefixes = list()//Some might have more than one! Like NanoTrasen. Value is the mission they perform.
var/list/ship_names = list()//Names of spaceships
var/list/holding_names = list()//Names of static holdings (planets, bases)
//////////////////////////////////////////////////////////////////////////////////
/datum/lore/org/nanotrasen
name = "NanoTrasen Incorporated"
sname = "NanoTrasen"
desc = "A megacorporation specializing in genetic and phoron research. The founder, Xavier Trasen, set the company \
up to be a powerhouse of buying up smaller companies, and turning a profit on the backs of it's workers. \
It's not known to be the most controversy-free company, nor the best to work for, though millions are employed \
nonetheless by NanoTrasen."
history = "Originally founded on Mars in 23rd Century by a man named Xavier Trasen, NanoTrasen started \
out as a small company, whose research was mostly based around gene-therapy. After a controversy over \
cloning, and buying many smaller companies, Xavier Trasen aggressively pursued phoron research \
as soon as it was discovered, bringing NanoTrasen to the forefront of the field."
work = "mega-conglomerate"
headquarters = "Mars"
motto = ""
org_flags = ORG_HAS_NAVY|ORG_HAS_TECH|ORG_HAS_HUGENESS
//Generic ship names!
ship_prefixes = list("NSV" = "exploration", "NTV" = "hauling", "NDV" = "patrol", "NRV" = "emergency response")
ship_names = list("Profit",
"Discovery",
"Endeavour",
"Desire",
"Gains",
"Torch II",
"Columbia",
"Leyte Gulf",
"Exeter",
"Zhukov",
"Xavier",
"Liteon",
"Fanatic",
"Slow Boat",
"Listing",
"Even Faster",
"Likely Story",
"Looking Glass",
"Witchcraft")
holding_names = list("NSS Phi Gamma",
"NSB Adelphia",
"NSS Vertigo",
"NSB Checkmate",
"NSS Lampour",
"NSB Adelade",
"NSS Indiana",
"NSB Memory Alpha",
"NSS Memory Beta")
/datum/lore/org/federation
name = "United Federation of Planets"
sname = "Federation"
desc = "The United Federation is a federation of planets that have agreed to exist semi-autonomously \
under a single central hybrid government, sharing the ideals of liberty, equality, and rights \
for all. It is one of the larger known interstellar powers in known space and is seen as being \
the fastest building power. The core planet of Gaia is known for having a proud military culture \
that, ironically, tends to stomp out any idea of warmongering from their cadets due to their \
scarred history and the Federation's ideals."
history = "Before the United Federation, there was a simple alliance with no name between core planet \
members. The United Federation itself found its roots in the aftermath of the Bloody \
Valentine Civil War, a racially motivated war that occurred in 2550 during the last year of \
the Federation Alliance of Gaia between the Genetically Modified and so-called Naturalists. \
Neutral nations in Gaia's political sphere, encouraged by alien observers, formed the United \
Federation when the indiscriminate loss of life became intolerable. 2555 saw the official \
signing of the Federation Charter between the core planet members."
work = "governing body"
headquarters = ""
motto = ""
org_flags = ORG_HAS_NAVY|ORG_HAS_TRADERS|ORG_HAS_TECH|ORG_HAS_DIPLO
//Star Trek ship names!
ship_prefixes = list("SCV" = "military", "STV" = "trading", "SDV" = "diplomatic")
ship_names = list("Kestrel",
"Beacon",
"Signal",
"Flying Freedom",
"Los Canas",
"Ixiom",
"Falken",
"Marigold",
"White Valley",
"Eternal",
"Arkbird",
"Akira",
"Kongou",
"Maki",
"Kagero",
"Nishiki",
"Icarus",
"Yuudachi",
"Tiki",
"Lucina",
"Tenryu",
"Spirit of Koni",
"Lady of Onoilph")
holding_names = list("Ruins of Chani City on Quarri III",
"Ruins of Kreely City on Ocan II",
"Ruins of Mishi City on Lucida IV",
"Ruins of Posloo City on Pi Cephei Prime",
"Molten Plains of Anarakis VII",
"Living City of Shani",
"Floating City of Nuni Vanni",
"Crystalline City of Delve Tile",
"New Iapetus Colony",
"Onul Colony",
"Ahemait Colony",
"New Amasia Colony",
"New Vesta Colony",
"Amaus Research Facility on Azaleh III",
"Living City of Na'me L'Tauri",
"Living City of Fithpa",
"Resource Mines of Lyra III",
"Resource Mines of Chi Cerberi III",
"Ceani Military Outpost on Rily VII",
"Naro Industrial Complex on Scheddi III",
"Mari Industrial Complex on Furlou Prime",
"Runni Crystal Mines of Keid V")
/datum/lore/org/solgov
name = "Solar Confederate Government"
sname = "SolGov"
desc = "SolGov is the entity in which many human states are members. Though SolGov has a dedicated miltiary force in the UNSC, \
it also claims the use of the forces of the member states when it needs to affect a \
military goal. Many if not most human states are members of SolGov, including all entities in Sol."
history = "Originally a military/economic pact between Earth and Mars in the early days of human colonization, \
the SolGov body of member states has grown over the years to be quite large, and hold a sizable \
amount of power compared to similar bodies."
work = "government of Sol"
headquarters = "Luna"
motto = ""
org_flags = ORG_HAS_TRADERS|ORG_HAS_DIPLO
//Random ship names!
ship_prefixes = list("SOL" = "SolGov") //Don't ask questions!
ship_names = list("Torch",
"Phoenix",
"Majesty",
"Duke",
"King",
"Mandrake",
"Foxglove",
"Prompt",
"Regal",
"Lordship",
"Highness",
"Rapido",
"Paperwork",
"Arthur",
"Durandal",
"Roland")
holding_names = list("San Francisco on Earth",
"SolGov Fleet Academy on Earth",
"Gateway One above Luna",
"SolGov Command on Luna",
"Olympus City on Mars",
"Hermes Naval Shipyard above Mars",
"a settlement on Titan",
"a settlement on Europa",
"Aleph Grande on Ganymede",
"a new colony in Proxima II",
"a new settlement on Ceti IV-B",
"a colony ship around Ceti IV-B",
"a classified location in SolGov territory")
/datum/lore/org/unsc
name = "United Nations Space Command"
sname = "Navy" //Otherwise they call the ships UNSC UNSC Name
desc = "The dedicated military force of SolGov, formed from the remnants of the United Nations, is the might of SolGov. \
While it is greater in military strength than most alien polities, it is not by much."
history = ""
work = ""
headquarters = "Earth"
motto = ""
org_flags = ORG_HAS_NAVY|ORG_HAS_TECH
//Halo ship names!
ship_prefixes = list("UNSC" = "military")
ship_names = list("Colorado",
"Anjou",
"Shanxi",
"Hammerhead",
"Piranha",
"Barracuda",
"DeGaulle",
"Leonidas",
"Tokugawa",
"Halcyon",
"Bastion",
"Adjudicator",
"Devestator",
"Corsair",
"Herakles",
"Ain't No Sunshine",
"Dust of Snow",
"Finite Hearts")
holding_names = list("San Francisco on Earth",
"SolGov Fleet Academy on Earth",
"Gateway One above Luna",
"SolGov Command on Luna",
"Olympus City on Mars",
"Hermes Naval Shipyard above Mars",
"a settlement on Titan",
"a settlement on Europa",
"Aleph Grande on Ganymede",
"a new colony in Proxima II",
"a new settlement on Ceti IV-B",
"a colony ship around Ceti IV-B",
"a classified location in SolGov territory")
/datum/lore/org/kitsuhana
name = "Kitsuhana Heavy Industries"
sname = "Kitsuhana"
desc = "A large post-scarcity amalgamation of races, Kitsuhana is no longer a company but rather a loose association of 'members' \
who only share the KHI name and their ideals in common. Kitsuhana accepts interviews to join their ranks, and though they have no \
formal structure with regards to government or law, the concept of 'consent' drives most of the large decision making. Kitsuhanans \
pride themselves on their ability to avoid consequence. Their post-scarcity allows them to rebuild, regrow, and replenish almost any \
lost asset or resource nearly instantly. It leads to many of the Kitsuhana 'members' treating everything with frivolity, \
and lends them a care-free demeanor."
history = "Originally a heavy industrial equipment and space mining company. During a forced evacuation of their homeworld, \
they were they only organization with enough ship capacity to evacuate any of the population, starting with their employees. \
After the resulting slowship travel to nearby starsystems, most of the population decided to keep the moniker of the \
company name. Over the years, Kitsuhana developed into a post-scarcity anarchy where virtually nothing has consequences \
and Kitsuhana 'members' can live their lives as they see fit, often in isolation."
work = "utopian anarchy"
headquarters = "Kitsuhana Prime"
motto = "Do what you want. We know we will."
org_flags = ORG_HAS_TRADERS|ORG_HAS_TECH|ORG_HAS_MERCS|ORG_HAS_ENTERTAIN
//Culture ship names!
ship_prefixes = list("KHI" = "personal") //Everybody's out for themselves, yanno.
ship_names = list("Nervous Energy",
"Prosthetic Conscience",
"Revisionist",
"Trade Surplus",
"Flexible Demeanour",
"Just Read The Instructions",
"Limiting Factor",
"Cargo Cult",
"Gunboat Diplomat",
"A Ship With A View",
"Cantankerous",
"I Thought He Was With You",
"Never Talk To Strangers",
"Sacrificial Victim",
"Unwitting Accomplice",
"Bad For Business",
"Just Testing",
"Size Isn't Everything",
"Yawning Angel",
"Liveware Problem",
"Very Little Gravitas Indeed",
"Zero Gravitas",
"Gravitas Free Zone",
"Absolutely No You-Know-What")
holding_names = list("Kitsuhana Prime",
"Kitsuhana Beta",
"Kitsuhana Gamma",
"the Kitsuhana Forge",
"a Kitsuhanan's home",
"a Kitsuhana ringworld in Pleis Ceti V",
"a Kitsuhana ringworld in Lund VI",
"a Kitsuhana ringworld in Dais IX",
"a Kitsuhana ringworld in Leibert II-b")
/datum/lore/org/ares
name = "Ares Confederation"
sname = "ArCon"
desc = "A rebel faction on the fringes of human space that renounced the government of both SolGov and their corporate overlords. \
The Confederation has two fleets, a regular United Fleet Host, comprised of professional crewmen and officers and the Free Host of the Confederation, \
which are privateers, volunteers and former pirates. The Ares Confederation only holds a \
dozen planets, but are fiercely defending any incursion on their territory."
history = "Originally only a strike of miners on the dusty, arid planet of Ares in the year 2540, \
the Ares Confederation was quickly established under the leadership of \
retired UNSC Colonel Rodrick Gellaume, who is now Prime Minister."
work = "rebel fringe government"
headquarters = "Paraiso a <20>strea"
motto = "Liberty to the Stars!"
org_flags = ORG_HAS_NAVY|ORG_HAS_SHADY
ship_prefixes = list("UFHV" = "military", "FFHV" = "shady")
ship_names = list("Liberty",
"Charged Negotiation",
"People's Fist",
"Corporation Breaker",
"Laughing Maniac",
"Not Insured",
"Prehensile Ethics",
"Fist of Ares",
"Gellaume",
"Memory of Fallen",
"Star of Tiamat",
"Mostly Harmless",
"Hero of the Revolution",
"Dawnstar",
"Freedom",
"Fiery Justice",
"Bulwark of the Free",
"Pride of Liberty",
"Gauntlet",
"Petrov",
"Miko",
"Mahama",
"Jerome",
"Rodrick",
"Torch",
"Torch of Freedom",
"She Is One Of Ours Sir",
"Fuck The Captain",
"None Of Your Business")
holding_names = list("Drydocks of the Ares Confederation",
"a classified location",
"a Homestead on Paraiso a <20>strea",
"a contested sector of ArCon space",
"one of our free colonies",
"the Gateway 98-C at Arest",
"Sars Mara on Ares",
"Listening Post Maryland-Sigma",
"an emergency nav bouy",
"New Berlin on Nov-Ferrum",
"a settlement needing our help",
"Forward Base Sigma-Alpha in ArCon space")
/*
/datum/lore/org
name = ""
sname = ""
desc = ""
history = ""
work = ""
headquarters = ""
motto = ""
org_flags = 0
ship_prefixes = list()
ship_names = list()
holding_names = list()
*/

View File

@@ -47,6 +47,7 @@
character.flavor_texts["hands"] = pref.flavor_texts["hands"]
character.flavor_texts["legs"] = pref.flavor_texts["legs"]
character.flavor_texts["feet"] = pref.flavor_texts["feet"]
character.ooc_notes = pref.metadata //VOREStation Add
/datum/category_item/player_setup_item/general/flavor/content(var/mob/user)
. += "<b>Flavor:</b><br>"

View File

@@ -6,3 +6,19 @@
display_name = "wedding ring, silver"
path = /obj/item/clothing/gloves/weddingring/silver
/datum/gear/gloves/colored
display_name = "gloves, colorable"
path = /obj/item/clothing/gloves/color
/datum/gear/gloves/colored/New()
..()
gear_tweaks = list(gear_tweak_free_color_choice)
/datum/gear/gloves/latex/colorable
display_name = "gloves, latex, colorable"
path = /obj/item/clothing/gloves/latex
/datum/gear/gloves/latex/colorable/New()
..()
gear_tweaks = list(gear_tweak_free_color_choice)

View File

@@ -0,0 +1,7 @@
/datum/gear/suit/labcoat_colorable
display_name = "labcoat, colorable"
path = /obj/item/clothing/suit/storage/toggle/labcoat
/datum/gear/suit/labcoat_colorable/New()
..()
gear_tweaks = list(gear_tweak_free_color_choice)

View File

@@ -0,0 +1,35 @@
/datum/gear/uniform/voxcasual
display_name = "casual wear (Vox)"
path = /obj/item/clothing/under/vox/vox_casual
sort_category = "Xenowear"
whitelisted = "Vox"
/datum/gear/uniform/voxrobes
display_name = "comfy robes (Vox)"
path = /obj/item/clothing/under/vox/vox_robes
sort_category = "Xenowear"
whitelisted = "Vox"
/datum/gear/accessory/vox
display_name = "storage vest (Vox)"
path = /obj/item/clothing/accessory/storage/vox
sort_category = "Xenowear"
whitelisted = "Vox"
/datum/gear/gloves/vox
display_name = "insulated gauntlets (Vox)"
path = /obj/item/clothing/gloves/vox
sort_category = "Xenowear"
whitelisted = "Vox"
/datum/gear/shoes/vox
display_name = "magclaws (Vox)"
path = /obj/item/clothing/shoes/magboots/vox
sort_category = "Xenowear"
whitelisted = "Vox"
/datum/gear/mask/vox
display_name = "alien mask (Vox)"
path = /obj/item/clothing/mask/gas/swat/vox
sort_category = "Xenowear"
whitelisted = "Vox"

View File

@@ -0,0 +1,43 @@
// Define a place to save in character setup
/datum/preferences
var/resleeve_lock = 0 // Whether movs should have OOC reslieving protection. Default false.
var/resleeve_scan = 1 // Whether mob should start with a pre-spawn body scan. Default true.
// Definition of the stuff for Sizing
/datum/category_item/player_setup_item/vore/resleeve
name = "Resleeving"
sort_order = 4
/datum/category_item/player_setup_item/vore/resleeve/load_character(var/savefile/S)
S["resleeve_lock"] >> pref.resleeve_lock
S["resleeve_scan"] >> pref.resleeve_scan
/datum/category_item/player_setup_item/vore/resleeve/save_character(var/savefile/S)
S["resleeve_lock"] << pref.resleeve_lock
S["resleeve_scan"] << pref.resleeve_scan
/datum/category_item/player_setup_item/vore/resleeve/sanitize_character()
pref.resleeve_lock = sanitize_integer(pref.resleeve_lock, 0, 1, initial(pref.resleeve_lock))
pref.resleeve_scan = sanitize_integer(pref.resleeve_scan, 0, 1, initial(pref.resleeve_scan))
/datum/category_item/player_setup_item/vore/resleeve/copy_to_mob(var/mob/living/carbon/human/character)
if(character && !istype(character,/mob/living/carbon/human/dummy))
spawn(50)
new/datum/transhuman/body_record/(character, pref.resleeve_scan, pref.resleeve_lock) //Clearly related to size.
if(pref.resleeve_lock)
character.resleeve_lock = character.ckey
/datum/category_item/player_setup_item/vore/resleeve/content(var/mob/user)
. += "<br>"
. += "<b>Start With Body Scan:</b> <a [pref.resleeve_scan ? "class='linkOn'" : ""] href='?src=\ref[src];toggle_resleeve_scan=1'><b>[pref.resleeve_scan ? "Yes" : "No"]</b></a><br>"
. += "<b>Prevent Body Impersonation:</b> <a [pref.resleeve_lock ? "class='linkOn'" : ""] href='?src=\ref[src];toggle_resleeve_lock=1'><b>[pref.resleeve_lock ? "Yes" : "No"]</b></a><br>"
/datum/category_item/player_setup_item/vore/resleeve/OnTopic(var/href, var/list/href_list, var/mob/user)
if(href_list["toggle_resleeve_lock"])
pref.resleeve_lock = pref.resleeve_lock ? 0 : 1;
return TOPIC_REFRESH
else if(href_list["toggle_resleeve_scan"])
pref.resleeve_scan = pref.resleeve_scan ? 0 : 1;
return TOPIC_REFRESH
return ..();

View File

@@ -13,4 +13,9 @@
/obj/item/clothing/gloves/weddingring/silver
name = "silver wedding ring"
icon_state = "wedring_s"
item_state = "wedring_s"
item_state = "wedring_s"
/obj/item/clothing/gloves/color
desc = "A pair of gloves, they don't look special in any way."
item_state_slots = list(slot_r_hand_str = "white", slot_l_hand_str = "white")
icon_state = "latex"

View File

@@ -80,8 +80,8 @@
/obj/item/rig_module/device/plasmacutter,
/obj/item/rig_module/device/drill,
/obj/item/rig_module/device/orescanner,
/obj/item/rig_module/vision/meson
)
/obj/item/rig_module/vision/meson,
/obj/item/rig_module/maneuvering_jets) //VOREStation Edit - Added maneuvering jets
/obj/item/weapon/rig/eva
name = "EVA suit control module"

View File

@@ -3,6 +3,7 @@
desc = "This permit entitles the bearer to conduct their duties without a uniform. Normally issued to furred crewmembers or those with nothing to hide."
icon = 'icons/obj/card.dmi'
icon_state = "guest"
body_parts_covered = 0
sprite_sheets = list()

View File

@@ -21,12 +21,12 @@
// 'basic' language; spoken by default.
/datum/language/common
name = LANGUAGE_GALCOM
desc = "The common galactic tongue."
desc = "The common galactic tongue, engineered for cross-species communication."
speech_verb = "says"
whisper_verb = "whispers"
key = "0"
flags = RESTRICTED
syllables = list("blah","blah","blah","bleh","meh","neh","nah","wah")
syllables = list("vol", "zum", "coo","zoo","bi","do","ooz","ite","og","re","si","ite","ish","ar","at","on","ee","east","ma","da", "rim")
//TODO flag certain languages to use the mob-type specific say_quote and then get rid of these.
/datum/language/common/get_spoken_verb(var/msg_end)

View File

@@ -72,24 +72,25 @@
/datum/language/skrell
name = LANGUAGE_SKRELLIAN
desc = "A melodic and complex language spoken by the Skrell of Qerrbalak. Some of the notes are inaudible to humans."
desc = "A set of warbles and hums, the language itself a complex mesh of both melodic and rhythmic components, exceptionally capable of conveying intent and emotion of the speaker."
speech_verb = "warbles"
ask_verb = "warbles"
exclaim_verb = "warbles"
exclaim_verb = "sings"
whisper_verb = "hums"
colour = "skrell"
key = "k"
space_chance = 30
flags = WHITELISTED
syllables = list("qr","qrr","xuq","qil","quum","xuqm","vol","xrim","zaoo","qu-uu","qix","qoo","zix","*","!")
syllables = list("qr","qrr","xuq","qil","quum","xuqm","vol","xrim","zaoo","qu-uu","qix","qoo","zix","*","!", "'")
/datum/language/human
name = LANGUAGE_SOL_COMMON
desc = "A bastardized hybrid of informal English and elements of Mandarin Chinese; the common language of the Sol system."
desc = "A bastardized hybrid of many languages, including Chinese, English, French, and more; it is the common language of the Sol system."
speech_verb = "says"
whisper_verb = "whispers"
colour = "solcom"
key = "1"
flags = WHITELISTED
//syllables are at the bottom of the file
/datum/language/human/get_spoken_verb(var/msg_end)
@@ -118,7 +119,7 @@
colour = "changeling"
key = "6"
flags = NO_STUTTER
syllables = list("beep","beep","beep","beep","beep","boop","boop","boop","bop","bop","dee","dee","doo","doo","hiss","hss","buzz","buzz","bzz","ksssh","keey","wurr","wahh","tzzz")
syllables = list("beep","beep","beep","beep","beep","boop","boop","boop","bop","bop","dee","dee","doo","doo","hiss","hss","buzz","buzz","bzz","ksssh","keey","wurr","wahh","tzzz","shh","shk")
space_chance = 10
/datum/language/machine/can_speak_special(var/mob/speaker)
@@ -155,9 +156,13 @@
/*
This list really long, mainly because I can't make up my mind about which mandarin syllables should be removed,
and the english syllables had to be duplicated so that there is roughly a 50-50 weighting.
The other 3 languages were duplicated just so they could show occasionally.
Sources:
http://www.sttmedia.com/syllablefrequency-english
http://www.sttmedia.com/syllablefrequency-spanish
http://www.sttmedia.com/syllablefrequency-russian
http://www.sttmedia.com/syllablefrequency-french
http://www.chinahighlights.com/travelguide/learning-chinese/pinyin-syllables.htm
*/
/datum/language/human/syllables = list(
@@ -210,4 +215,31 @@
"al", "an", "ar", "as", "at", "ea", "ed", "en", "er", "es", "ha", "he", "hi", "in", "is", "it",
"le", "me", "nd", "ne", "ng", "nt", "on", "or", "ou", "re", "se", "st", "te", "th", "ti", "to",
"ve", "wa", "all", "and", "are", "but", "ent", "era", "ere", "eve", "for", "had", "hat", "hen", "her", "hin",
"his", "ing", "ion", "ith", "not", "ome", "oul", "our", "sho", "ted", "ter", "tha", "the", "thi")
"his", "ing", "ion", "ith", "not", "ome", "oul", "our", "sho", "ted", "ter", "tha", "the", "thi",
"ah", "be", "bo", "eh", "ep", "et", "ka", "ko", "ha", "he", "ho", "ob", "oh", "op", "oc", "ot", "pa", "pe", "ct", "ta", "te", "to",
"vse", "tak", "nak", "no", "epo", "pre", "kan", "dly", "ime", "sha", "kur", "yey", "khi", "yeg", "ne",
"ion", "ne", "nas", "v",
"ah", "be", "bo", "eh", "ep", "et", "ka", "ko", "ha", "he", "ho", "ob", "oh", "op", "oc", "ot", "pa", "pe", "ct", "ta", "te", "to",
"vse", "tak", "nak", "no", "epo", "pre", "kan", "dly", "ime", "sha", "kur", "yey", "khi", "yeg", "ne",
"ion", "ne", "nas", "v",
"ah", "be", "bo", "eh", "ep", "et", "ka", "ko", "ha", "he", "ho", "ob", "oh", "op", "oc", "ot", "pa", "pe", "ct", "ta", "te", "to",
"vse", "tak", "nak", "no", "epo", "pre", "kan", "dly", "ime", "sha", "kur", "yey", "khi", "yeg", "ne",
"ion", "ne", "nas", "v",
"ai", "an", "ar", "au", "ce", "ch", "co", "de", "em", "en", "er", "es", "et", "eu", "il", "in", "is", "la", "le",
"ma", "me", "ne", "ns", "nt", "on", "ou", "pa", "qu", "ra", "re", "se", "te", "ti", "tr", "ue", "ur", "us", "ve",
"tou", "e", "eve", "hen", "son", "non", "not", "le",
"ai", "an", "ar", "au", "ce", "ch", "co", "de", "em", "en", "er", "es", "et", "eu", "il", "in", "is", "la", "le",
"ma", "me", "ne", "ns", "nt", "on", "ou", "pa", "qu", "ra", "re", "se", "te", "ti", "tr", "ue", "ur", "us", "ve",
"tou", "e", "eve", "hen", "son", "non", "not", "le",
"ai", "an", "ar", "au", "ce", "ch", "co", "de", "em", "en", "er", "es", "et", "eu", "il", "in", "is", "la", "le",
"ma", "me", "ne", "ns", "nt", "on", "ou", "pa", "qu", "ra", "re", "se", "te", "ti", "tr", "ue", "ur", "us", "ve",
"tou", "e", "eve", "hen", "son", "non", "not", "le",
"ad", "al", "an", "ar", "as", "ci", "co", "de", "do", "el", "en", "er", "es", "ie", "in", "la", "lo", "me", "na",
"no", "nt", "or", "os", "pa", "qu", "ra", "re", "ro", "se", "st", "ta", "te", "to", "ue", "un",
"tod", "ser", "su", "no", "nue", "el",
"ad", "al", "an", "ar", "as", "ci", "co", "de", "do", "el", "en", "er", "es", "ie", "in", "la", "lo", "me", "na",
"no", "nt", "or", "os", "pa", "qu", "ra", "re", "ro", "se", "st", "ta", "te", "to", "ue", "un",
"tod", "ser", "su", "no", "nue", "el",
"ad", "al", "an", "ar", "as", "ci", "co", "de", "do", "el", "en", "er", "es", "ie", "in", "la", "lo", "me", "na",
"no", "nt", "or", "os", "pa", "qu", "ra", "re", "ro", "se", "st", "ta", "te", "to", "ue", "un",
"tod", "ser", "su", "no", "nue", "el")

View File

@@ -62,6 +62,3 @@
flags = 0
/datum/language/gutter
flags = WHITELISTED
/datum/language/machine
flags = NO_STUTTER | WHITELISTED

View File

@@ -438,7 +438,7 @@
if(print_flavor_text()) msg += "[print_flavor_text()]\n"
// VOREStation Start
if(config.allow_Metadata && client)
if(ooc_notes)
msg += "<span class = 'deptradio'>OOC Notes:</span> <a href='?src=\ref[src];ooc_notes=1'>\[View\]</a>\n"
// VOREStation End
msg += "*---------*</span><br>"

View File

@@ -1644,6 +1644,8 @@
holder1.icon_state = "hud_imp_tracking"
if(istype(I,/obj/item/weapon/implant/loyalty))
holder2.icon_state = "hud_imp_loyal"
if(istype(I,/obj/item/weapon/implant/backup))//VOREStation Edit - Commandeering this for backup implants
holder2.icon_state = "hud_imp_loyal" //VOREStation Edit
if(istype(I,/obj/item/weapon/implant/chem))
holder3.icon_state = "hud_imp_chem"

View File

@@ -187,12 +187,18 @@
return sanitizeName(name)
/datum/species/proc/equip_survival_gear(var/mob/living/carbon/human/H,var/extendedtank = 1)
var/boxtype = /obj/item/weapon/storage/box/survival //Default survival box
if(H.isSynthetic())
boxtype = /obj/item/weapon/storage/box //Empty box for synths
else if(extendedtank)
boxtype = /obj/item/weapon/storage/box/engineer //Special box for engineers
if(H.backbag == 1)
if (extendedtank) H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/engineer(H), slot_r_hand)
else H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H), slot_r_hand)
if (extendedtank) H.equip_to_slot_or_del(new boxtype(H), slot_r_hand)
else H.equip_to_slot_or_del(new boxtype(H), slot_r_hand)
else
if (extendedtank) H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/engineer(H.back), slot_in_backpack)
else H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H.back), slot_in_backpack)
if (extendedtank) H.equip_to_slot_or_del(new boxtype(H.back), slot_in_backpack)
else H.equip_to_slot_or_del(new boxtype(H.back), slot_in_backpack)
/datum/species/proc/create_organs(var/mob/living/carbon/human/H) //Handles creation of mob organs.

View File

@@ -485,15 +485,17 @@ default behaviour is:
set name = "Examine Meta-Info (OOC)"
set category = "OOC"
set src in view()
//VOREStation Edit Start - Making it so SSD people have prefs with fallback to original style.
if(config.allow_Metadata)
if(client)
if(ooc_notes)
usr << "[src]'s Metainfo:<br>[ooc_notes]"
else if(client)
usr << "[src]'s Metainfo:<br>[client.prefs.metadata]"
else
usr << "[src] does not have any stored infomation!"
else
usr << "OOC Metadata is not supported by this server!"
//VOREStation Edit End - Making it so SSD people have prefs with fallback to original style.
return
/mob/living/Move(a, b, flag)

View File

@@ -0,0 +1,2 @@
/mob/living
var/ooc_notes = null

View File

@@ -75,7 +75,7 @@ var/list/mob_hat_cache = list()
/mob/living/silicon/robot/drone/New()
..()
verbs += /mob/living/proc/ventcrawl //VOREStation Edit - Rule of fun bruh.
verbs += /mob/living/proc/hide
remove_language("Robot Talk")
add_language("Robot Talk", 0)

View File

@@ -0,0 +1,9 @@
/mob/living/silicon/robot/drone
can_enter_vent_with = list(
/obj/item/device/radio/borg,
/obj/machinery/camera,
/obj/item/device/camera/siliconcam/drone_camera,
/obj/item/weapon/robot_module/drone,
/obj/item/weapon/cell,
/obj/screen/movable/ability_master,
/obj/item/weapon/card/id/synthetic)

View File

@@ -70,7 +70,7 @@
var/obj/machinery/hologram/holopad/T = src.holo
if(T && T.masters[src])//If there is a hologram and its master is the user.
var/obj/effect/overlay/aiholo/hologram = T.masters[src] //VOREStation Add for people in the hologram to hear the messages
//Human-like, sorta, heard by those who understand humans.
var/rendered_a
//Speach distorted, heard by those who do not understand AIs.
@@ -85,7 +85,7 @@
rendered_a = "<span class='game say'><span class='name'>[name]</span> [verb], <span class='message'>\"[message]\"</span></span>"
rendered_b = "<span class='game say'><span class='name'>[voice_name]</span> [verb], <span class='message'>\"[message_stars]\"</span></span>"
src << "<i><span class='game say'>Holopad transmitted, <span class='name'>[real_name]</span> [verb], <span class='message'><span class='body'>\"[message]\"</span></span></span></i>"//The AI can "hear" its own message.
if(hologram.bellied) hologram.bellied.show_message(rendered_a, 2) //VOREStation Add so holobellied people can hear
for(var/mob/M in hearers(T.loc))//The location is the object, default distance.
if(M.say_understands(src))//If they understand AI speak. Humans and the like will be able to.
M.show_message(rendered_a, 2)
@@ -111,7 +111,8 @@
if(T && T.masters[src])
var/rendered = "<span class='game say'><span class='name'>[name]</span> <span class='message'>[message]</span></span>"
src << "<i><span class='game say'>Holopad action relayed, <span class='name'>[real_name]</span> <span class='message'>[message]</span></span></i>"
var/obj/effect/overlay/aiholo/hologram = T.masters[src] //VOREStation Add for people in the hologram to hear the messages
if(hologram.bellied) hologram.bellied.show_message(rendered, 2) //VOREStation Add so holobellied people can hear
for(var/mob/M in viewers(T.loc))
M.show_message(rendered, 2)
else //This shouldn't occur, but better safe then sorry.

View File

@@ -3,7 +3,7 @@
desc = "Hiss!"
icon_state = "xenohunter"
icon_living = "xenohunter"
icon_dead = "xenohunter_dead"
icon_dead = "xenohunter-dead"
icon_gib = "gibbed-a"
response_help = "pokes"
response_disarm = "shoves"
@@ -39,7 +39,7 @@
name = "alien drone"
icon_state = "xenodrone"
icon_living = "xenodrone"
icon_dead = "xenodrone_dead"
icon_dead = "xenodrone-dead"
health = 60
melee_damage_lower = 15
melee_damage_upper = 15
@@ -48,7 +48,7 @@
name = "alien sentinel"
icon_state = "xenosentinel"
icon_living = "xenosentinel"
icon_dead = "xenosentinel_dead"
icon_dead = "xenosentinel-dead"
health = 120
melee_damage_lower = 30 // Buffed from 15 since vore doesn't work for ranged mobs.
melee_damage_upper = 30
@@ -61,7 +61,7 @@
name = "alien queen"
icon_state = "xenoqueen"
icon_living = "xenoqueen"
icon_dead = "xenoqueen_dead"
icon_dead = "xenoqueen-dead"
maxHealth = 250
melee_damage_lower = 30 // Buffed from 15 since vore doesn't work for ranged mobs.
melee_damage_upper = 30

View File

@@ -1,10 +1,19 @@
//
// Paper Shredder Machine
//
/obj/machinery/papershredder
name = "paper shredder"
desc = "For those documents you don't want seen."
icon = 'icons/obj/bureaucracy.dmi'
icon_state = "papershredder0"
icon = 'icons/obj/papershredder.dmi'
icon_state = "shredder-off"
var/shred_anim = "shredder-shredding"
density = 1
anchored = 1
use_power = 1
idle_power_usage = 10
active_power_usage = 200
power_channel = EQUIP
circuit = /obj/item/weapon/circuitboard/papershredder
var/max_paper = 10
var/paperamount = 0
var/list/shred_amounts = list(
@@ -16,17 +25,40 @@
/obj/item/weapon/paper_bundle = 3,
)
/obj/machinery/papershredder/New()
..()
component_parts = list()
component_parts += new /obj/item/weapon/stock_parts/motor(src)
component_parts += new /obj/item/weapon/stock_parts/gear(src)
component_parts += new /obj/item/weapon/stock_parts/gear(src)
component_parts += new /obj/item/weapon/stock_parts/micro_laser(src)
RefreshParts()
update_icon()
/obj/machinery/papershredder/attackby(var/obj/item/W, var/mob/user)
if(istype(W, /obj/item/weapon/storage))
empty_bin(user, W)
return
else if(istype(W, /obj/item/weapon/wrench))
playsound(loc, 'sound/items/Ratchet.ogg', 50, 1)
anchored = !anchored
user << "<span class='notice'>You [anchored ? "wrench" : "unwrench"] \the [src].</span>"
return
else if(default_part_replacement(user, W))
return
else if(default_deconstruction_screwdriver(user, W))
return
else if(default_deconstruction_crowbar(user, W))
return
else
var/paper_result
for(var/shred_type in shred_amounts)
if(istype(W, shred_type))
paper_result = shred_amounts[shred_type]
if(paper_result)
if(inoperable())
return // Need powah!
if(paperamount == max_paper)
user << "<span class='warning'>\The [src] is full; please empty it before you continue.</span>"
return
@@ -34,6 +66,7 @@
user.drop_from_inventory(W)
qdel(W)
playsound(src.loc, 'sound/items/pshred.ogg', 75, 1)
flick(shred_anim, src)
if(paperamount > max_paper)
user <<"<span class='danger'>\The [src] was too full, and shredded paper goes everywhere!</span>"
for(var/i=(paperamount-max_paper);i>0;i--)
@@ -92,8 +125,40 @@
paperamount--
return PoolOrNew(/obj/item/weapon/shreddedp, get_turf(src))
/obj/machinery/papershredder/power_change()
..()
spawn(rand(0,15))
update_icon()
/obj/machinery/papershredder/update_icon()
icon_state = "papershredder[max(0,min(5,Floor(paperamount/2)))]"
overlays.Cut()
if(operable())
icon_state = "shredder-on"
else
icon_state = "shredder-off"
// Fullness overlay
overlays += "shredder-[max(0,min(5,Floor(paperamount/max_paper*5)))]"
if (panel_open)
overlays += "panel_open"
//
// Shredded Paper Item
//
/obj/item/weapon/shreddedp
name = "shredded paper"
icon = 'icons/obj/bureaucracy.dmi'
icon_state = "shredp"
throwforce = 0
w_class = ITEMSIZE_TINY
throw_range = 3
throw_speed = 1
/obj/item/weapon/shreddedp/New()
..()
pixel_x = rand(-5,5)
pixel_y = rand(-5,5)
if(prob(65)) color = pick("#BABABA","#7F7F7F")
/obj/item/weapon/shreddedp/attackby(var/obj/item/W as obj, var/mob/user)
if(istype(W, /obj/item/weapon/flame/lighter))
@@ -122,18 +187,3 @@
M.drop_from_inventory(src)
PoolOrNew(/obj/effect/decal/cleanable/ash,get_turf(src))
qdel(src)
/obj/item/weapon/shreddedp
name = "shredded paper"
icon = 'icons/obj/bureaucracy.dmi'
icon_state = "shredp"
throwforce = 0
w_class = ITEMSIZE_TINY
throw_range = 3
throw_speed = 1
/obj/item/weapon/shreddedp/New()
..()
pixel_x = rand(-5,5)
pixel_y = rand(-5,5)
if(prob(65)) color = pick("#BABABA","#7F7F7F")

View File

@@ -1,11 +1,20 @@
/obj/item/weapon/gun/energy/particle
name = "Antiparticle projector gun"
/obj/item/weapon/gun/energy/particle //base gun, similar stats to an egun
name = "Antiparticle projector pistol"
icon = 'icons/obj/gun_vr.dmi'
icon_state = "particle"
item_state = "particle"
desc = "An unconventional firearm, APP guns generate attogram-scale quantities of antimatter which are then launched using an electromagnetic field."
force = 5
fire_sound = 'sound/weapons/Laser.ogg'
icon_state = "ppistol"
item_state = "ppistol_item"
icon_override = 'icons/obj/gun_vr.dmi'
item_icons = null
desc = "A Kawashima Material Technology Model 7 anti-particle projector, housed in a rugged casing."
description_info = "An unconventional weapon, APP guns generate attogram-scale quantities of antimatter which \
are then launched using an electromagnetic field. They are only suitable for use in depressurised environments, \
else the antimatter pellet is liable to strike the air before it reaches the target. This can result in catastrophic \
failure, making them unsuitable as military weapons in practical situations as they are prone to backfiring and \
jamming, though they perform as adequately as any laser weapon in vacuum. Nonetheless, they have found a niche among \
miners and salvage crews, as their lack of usefulness as a firearm in habitable areas means most authorities do not \
classify them as dangerous weapons (at least, not dangerous to whoever they're pointed at) - instead, in most \
jurisdictions including NT space, APP guns are officially classed as mining equipment rather than firearms."
fire_sound = 'sound/weapons/blaster.ogg'
slot_flags = SLOT_BELT
w_class = ITEMSIZE_NORMAL
projectile_type = /obj/item/projectile/bullet/particle
@@ -13,8 +22,45 @@
fire_delay = 10
charge_cost = 240 //same cost as lasers
var/safetycatch = 0 //if 1, won't let you fire in pressurised environment, rather than malfunctioning
var/obj/item/pressurelock/attached_safety
/obj/item/weapon/gun/energy/particle/advanced //particle equivalent of AEG
name = "Advanced antiparticle rifle"
icon_state = "particle"
item_state = "particle_item"
desc = "An antiparticle projector gun with an enhanced power-generation unit."
slot_flags = SLOT_BELT
force = 8 //looks heavier than a pistol
w_class = ITEMSIZE_LARGE //bigger than a pistol, too.
fire_delay = 6 //This one's not a handgun, it should have the same fire delay as everything else
self_recharge = 1
modifystate = null
battery_lock = 1
recharge_time = 15 // every 15 ticks, recharge 2 shots. Rather slower than AEG.
charge_delay = 20 //Starts recharging faster after firing than an AEG, but much slower recharge rate. Balances out for a full charge.
/obj/item/weapon/gun/energy/particle/cannon //particle version of laser cannon
name = "Anti-particle cannon"
desc = "A giant beast of an antimatter gun, packed with an internal reactor to allow for extreme longevity on remote mining expeditions."
icon_state = "heavyparticle"
item_state = "heavyparticle_item"
fire_sound = 'sound/weapons/lasercannonfire.ogg'
slot_flags = SLOT_BACK
projectile_type = /obj/item/projectile/bullet/particle/heavy
battery_lock = 1
fire_delay = 20
w_class = ITEMSIZE_HUGE // So it can't fit in a backpack.
force = 10
one_handed_penalty = 6 // The thing's heavy and huge.
accuracy = 3
charge_cost = 480 // 5 shots
self_recharge = 1
charge_delay = 20 //won't start charging until it's ready to fire again
recharge_time = 20 //100 ticks after that to refill the whole thing.
//special behaviours for particle guns below
/obj/item/weapon/gun/energy/particle/special_check(var/mob/user)
if (..())
var/turf/T = get_turf(src)
@@ -32,56 +78,113 @@
return 0
else if (prob(min(pressure, 100))) //pressure% chance of failing
var/severity = rand(pressure)
if (severity <= 10) // just doesn't fire. 10% chance in 100 atmo.
user.visible_message("<span class='warning'>*click*</span>", "<span class='danger'>\The [src] jams.</span>")
playsound(src.loc, 'sound/weapons/empty.ogg', 100, 1)
else if (severity <= 60) //50% chance of fizzling and wasting a shot
user.visible_message("<span class='warning'>\The [user] fires \the [src], but the shot fizzles in the air!</span>", "<span class='danger'>You fire \the [src], but the shot fizzles in the air!</span>")
power_supply.charge -= charge_cost
playsound(src.loc, fire_sound, 100, 1)
var/datum/effect/effect/system/spark_spread/sparks = PoolOrNew(/datum/effect/effect/system/spark_spread)
sparks.set_up(2, 1, T)
sparks.start()
update_icon()
else if (severity <= 80) //20% chance of shorting out and emptying the cell
user.visible_message("<span class='warning'>\The [user] pulls the trigger, but \the [src] shorts out!</span>", "<span class='danger'>You pull the trigger, but \the [src] shorts out!</span>")
power_supply.charge = 0
var/datum/effect/effect/system/spark_spread/sparks = PoolOrNew(/datum/effect/effect/system/spark_spread)
sparks.set_up(2, 1, T)
sparks.start()
update_icon()
else if (severity <= 90) //10% chance of breaking the gun
user.visible_message("<span class='warning'>\The [user] pulls the trigger, but \the [src] erupts in a shower of sparks!</span>", "<span class='danger'>You pull the trigger, but \the [src] bursts into a shower of sparks!</span>")
var/datum/effect/effect/system/spark_spread/sparks = PoolOrNew(/datum/effect/effect/system/spark_spread)
sparks.set_up(2, 1, T)
sparks.start()
power_supply.charge = 0
power_supply.maxcharge = 0
power_supply.desc += " It seems to be burnt out!"
desc += " The casing is covered in scorch-marks."
fire_delay += fire_delay // even if you swap out the cell for a good one, the gun's cluckety-clucked.
charge_cost += charge_cost
update_icon()
else if (severity <= 150) // 10% chance of exploding
user << "<span class='danger'>The [src] explodes!</span>"
explosion(T, -1, -1, 1, 1)
qdel(src)
else //can only possibly happen if you're dumb enough to fire it in an OVER pressure environment, over 150kPa
user << "<span class='danger'>The [src] explodes catastrophically!</span>"
explosion(T, -1, 1, 2, 2)
qdel(src)
pressuremalfunction(severity, user, T)
return 0
return 1
return 0
/obj/item/weapon/gun/energy/particle/proc/pressuremalfunction(severity, var/mob/user, var/turf/T)
if (severity <= 10) // just doesn't fire. 10% chance in 100 atmo.
user.visible_message("<span class='warning'>*click*</span>", "<span class='danger'>\The [src] jams.</span>")
playsound(src.loc, 'sound/weapons/empty.ogg', 100, 1)
else if (severity <= 60) //50% chance of fizzling and wasting a shot
user.visible_message("<span class='warning'>\The [user] fires \the [src], but the shot fizzles in the air!</span>", "<span class='danger'>You fire \the [src], but the shot fizzles in the air!</span>")
power_supply.charge -= charge_cost
playsound(src.loc, fire_sound, 100, 1)
var/datum/effect/effect/system/spark_spread/sparks = PoolOrNew(/datum/effect/effect/system/spark_spread)
sparks.set_up(2, 1, T)
sparks.start()
update_icon()
else if (severity <= 80) //20% chance of shorting out and emptying the cell
user.visible_message("<span class='warning'>\The [user] pulls the trigger, but \the [src] shorts out!</span>", "<span class='danger'>You pull the trigger, but \the [src] shorts out!</span>")
power_supply.charge = 0
var/datum/effect/effect/system/spark_spread/sparks = PoolOrNew(/datum/effect/effect/system/spark_spread)
sparks.set_up(2, 1, T)
sparks.start()
update_icon()
else if (severity <= 90) //10% chance of breaking the gun
user.visible_message("<span class='warning'>\The [user] pulls the trigger, but \the [src] erupts in a shower of sparks!</span>", "<span class='danger'>You pull the trigger, but \the [src] bursts into a shower of sparks!</span>")
var/datum/effect/effect/system/spark_spread/sparks = PoolOrNew(/datum/effect/effect/system/spark_spread)
sparks.set_up(2, 1, T)
sparks.start()
power_supply.charge = 0
power_supply.maxcharge = 1 //just to avoid div/0 runtimes
power_supply.desc += " It seems to be burnt out!"
desc += " The casing is covered in scorch-marks."
fire_delay += fire_delay // even if you swap out the cell for a good one, the gun's cluckety-clucked.
charge_cost += charge_cost
update_icon()
else if (severity <= 150) // 10% chance of exploding
user.visible_message("<span class='danger'>\The [user] pulls the trigger, but \the [src] explodes!</span>", "<span class='danger'>The [src] explodes!</span>")
log_and_message_admins("blew themself up with a particle gun.", user)
explosion(T, -1, -1, 1, 1)
qdel(src)
else //can only possibly happen if you're dumb enough to fire it in an OVER pressure environment, over 150kPa
user.visible_message("<span class='danger'>\The [user] pulls the trigger, but \the [src] explodes!</span>", "<span class='danger'>The [src] explodes catastrophically!</span>")
log_and_message_admins("blew their dumb ass up with a particle gun.", user)
explosion(T, -1, 1, 2, 2)
qdel(src)
/obj/item/weapon/gun/energy/particle/cannon/pressuremalfunction(severity, user, T)
..(severity*2, user, T)
/obj/item/weapon/gun/energy/particle/attackby(var/obj/item/A as obj, mob/user as mob)
if(istype(A, /obj/item/pressurelock))
if(safetycatch)
user << "<span class='notice'>\The [src] already has a [attached_safety].</span>"
return
user << "<span class='notice'>You insert \the [A] into \the [src].</span>"
user.drop_item()
A.loc = src
attached_safety = A
safetycatch = 1
return
if(istype(A, /obj/item/weapon/screwdriver))
if(safetycatch && attached_safety)
user << "<span class='notice'>You begin removing \the [attached_safety] from \the [src].</span>"
if(do_after(user, 25))
user << "<span class='notice'>You remove \the [attached_safety] from \the [src].</span>"
user.put_in_hands(attached_safety)
safetycatch = 0
attached_safety = null
return
..()
// accessory
/obj/item/pressurelock
name = "Pressure interlock"
icon = 'icons/obj/gun_vr.dmi'
icon_state = "pressurelock"
desc = "A safety interlock that can be installed in an antiparticle projector. It prevents the weapon from discharging in pressurised environments."
w_class = ITEMSIZE_TINY
// projectiles below
/obj/item/projectile/bullet/particle
name = "particle"
name = "antimatter pellet"
icon = 'icons/obj/projectiles_vr.dmi'
icon_state = "particle"
damage = 40
damage_type = BURN
check_armour = "energy"
embed_chance = 0
/obj/item/projectile/bullet/particle/heavy
name = "antimatter slug"
icon_state = "particle-heavy"
damage = 80 // same as a laser cannon
armor_penetration = 25 //it explodes on the surface of things, so less armor pen than the laser cannon
light_range = 3
light_power = 1
light_color = "#CCFFFF"
/turf/simulated/mineral/bullet_act(var/obj/item/projectile/Proj)
if(istype(Proj, /obj/item/projectile/bullet/particle))
if(prob(Proj.damage))
GetDrilled()

View File

@@ -0,0 +1,279 @@
// Customizable Foods //////////////////////////////////////////
var/global/deepFriedEverything = 0
var/global/deepFriedNutriment = 0
var/global/foodNesting = 0
var/global/recursiveFood = 0
var/global/ingredientLimit = 20
/obj/item/weapon/reagent_containers/food/snacks/customizable
icon = 'icons/obj/food_custom.dmi'
trash = /obj/item/trash/plate
bitesize = 2
var/ingMax = 100
var/list/ingredients = list()
var/stackIngredients = 0
var/fullyCustom = 0
var/addTop = 0
var/image/topping
var/image/filling
/obj/item/weapon/reagent_containers/food/snacks/customizable/New(loc,ingredient)
. = ..()
topping = image(icon,,"[initial(icon_state)]_top")
filling = image(icon,,"[initial(icon_state)]_filling")
src.reagents.add_reagent("nutriment",3)
src.updateName()
return
/obj/item/weapon/reagent_containers/food/snacks/customizable/attackby(obj/item/I, mob/user)
if(istype(I,/obj/item/weapon/reagent_containers/food/snacks))
if((contents.len >= ingMax) || (contents.len >= ingredientLimit))
to_chat(user, "<span class='warning'>That's already looking pretty stuffed.</span>")
return
var/obj/item/weapon/reagent_containers/food/snacks/S = I
if(istype(S,/obj/item/weapon/reagent_containers/food/snacks/customizable))
var/obj/item/weapon/reagent_containers/food/snacks/customizable/SC = S
if(fullyCustom && SC.fullyCustom)
to_chat(user, "<span class='warning'>You slap yourself on the back of the head for thinking that stacking plates is an interesting dish.</span>")
return
if(!recursiveFood && istype(I, /obj/item/weapon/reagent_containers/food/snacks/customizable))
//to_chat(user, "<span class='warning'>[pick("As uniquely original as that idea is, you can't figure out how to perform it.","That would be a straining topological exercise.","This world just isn't ready for your cooking genius.","It's possible that you may have a problem.","It won't fit.","You don't think that would taste very good.","Quit goofin' around.")]</span>")
to_chat(user, "<span class='warning'>As uniquely original as that idea is, you can't figure out how to perform it.</span>")
return
/*if(!user.drop_item())
user << "<span class='warning'>\The [I] is stuck to your hands!</span>"
return*/
user.drop_item()
I.forceMove(src)
S.reagents.trans_to(src,S.reagents.total_volume)
ingredients += S
if(src.addTop)
overlays -= topping //thank you Comic
if(!fullyCustom && !stackIngredients && overlays.len)
overlays -= filling //we can't directly modify the overlay, so we have to remove it and then add it again
var/newcolor = S.filling_color != "#FFFFFF" ? S.filling_color : AverageColor(getFlatIcon(S, S.dir, 0), 1, 1)
filling.color = BlendRGB(filling.color, newcolor, 1/ingredients.len)
overlays += filling
else
overlays += generateFilling(S)
if(addTop)
drawTopping()
updateName()
to_chat(user, "<span class='notice'>You add the [I.name] to the [src.name].</span>")
else
. = ..()
return
/obj/item/weapon/reagent_containers/food/snacks/customizable/proc/generateFilling(var/obj/item/weapon/reagent_containers/food/snacks/S, params)
var/image/I
if(fullyCustom)
var/icon/C = getFlatIcon(S, S.dir, 0)
I = image(C)
I.pixel_y = 12 * empty_Y_space(C)
else
I = filling
if(istype(S) && S.filling_color != "#FFFFFF")
I.color = S.filling_color
else
I.color = AverageColor(getFlatIcon(S, S.dir, 0), 1, 1)
if(src.stackIngredients)
I.pixel_y = src.ingredients.len * 2
else
src.overlays.len = 0
if(src.fullyCustom || src.stackIngredients)
var/clicked_x = text2num(params2list(params)["icon-x"])
if (isnull(clicked_x))
I.pixel_x = 0
else if (clicked_x < 9)
I.pixel_x = -2 //this looks pretty shitty
else if (clicked_x < 14)
I.pixel_x = -1 //but hey
else if (clicked_x < 19)
I.pixel_x = 0 //it works
else if (clicked_x < 25)
I.pixel_x = 1
else
I.pixel_x = 2
return I
/obj/item/weapon/reagent_containers/food/snacks/customizable/proc/updateName()
var/i = 1
var/new_name
for(var/obj/item/S in ingredients)
if(i == 1)
new_name += "[S.name]"
else if(i == src.ingredients.len)
new_name += " and [S.name]"
else
new_name += ", [S.name]"
i++
new_name = "[new_name] [initial(name)]"
if(length(new_name) >= 150)
name = "something yummy"
else
name = new_name
return new_name
/obj/item/weapon/reagent_containers/food/snacks/customizable/Destroy()
for(. in ingredients) qdel(.)
return ..()
/obj/item/weapon/reagent_containers/food/snacks/customizable/proc/drawTopping()
var/image/I = topping
I.pixel_y = (ingredients.len+1)*2
overlays += I
// Sandwiches //////////////////////////////////////////////////
/obj/item/weapon/reagent_containers/food/snacks/customizable/sandwich
name = "sandwich"
desc = "A timeless classic."
icon_state = "c_sandwich"
stackIngredients = 1
addTop = 0
/obj/item/weapon/reagent_containers/food/snacks/customizable/sandwich/attackby(obj/item/I,mob/user)
if(istype(I,/obj/item/weapon/reagent_containers/food/snacks/breadslice) && !addTop)
I.reagents.trans_to(src,I.reagents.total_volume)
qdel(I)
addTop = 1
src.drawTopping()
else
..()
/obj/item/weapon/reagent_containers/food/snacks/customizable/burger
name = "burger"
desc = "The apex of space culinary achievement."
icon_state = "c_burger"
stackIngredients = 1
addTop = 1
// Misc Subtypes ///////////////////////////////////////////////
/obj/item/weapon/reagent_containers/food/snacks/customizable/fullycustom
name = "on a plate"
desc = "A unique dish."
icon_state = "fullycustom"
fullyCustom = 1 //how the fuck do you forget to add this?
ingMax = 1
/obj/item/weapon/reagent_containers/food/snacks/customizable/soup
name = "soup"
desc = "A bowl with liquid and... stuff in it."
icon_state = "soup"
trash = /obj/item/trash/bowl
/obj/item/weapon/reagent_containers/food/snacks/customizable/pizza
name = "pan pizza"
desc = "A personalized pan pizza meant for only one person."
icon_state = "personal_pizza"
/obj/item/weapon/reagent_containers/food/snacks/customizable/pasta
name = "spaghetti"
desc = "Noodles. With stuff. Delicious."
icon_state = "pasta_bot"
// Various Snacks //////////////////////////////////////////////
/obj/item/weapon/reagent_containers/food/snacks/breadslice/attackby(obj/item/I,mob/user,params)
if(istype(I,/obj/item/weapon/reagent_containers/food/snacks))
if(!recursiveFood && istype(I, /obj/item/weapon/reagent_containers/food/snacks/customizable))
to_chat(user, "<span class='warning'>Sorry, no recursive food.</span>")
return
var/obj/F = new/obj/item/weapon/reagent_containers/food/snacks/customizable/sandwich(get_turf(src),I) //boy ain't this a mouthful
F.attackby(I, user)
qdel(src)
else
return ..()
/obj/item/weapon/reagent_containers/food/snacks/bun/attackby(obj/item/I, mob/user)
// Bun + meatball = burger
if(istype(I,/obj/item/weapon/reagent_containers/food/snacks/meatball))
new /obj/item/weapon/reagent_containers/food/snacks/monkeyburger(src)
to_chat(user, "You make a burger.")
qdel(I)
qdel(src)
// Bun + cutlet = hamburger
else if(istype(I, /obj/item/weapon/reagent_containers/food/snacks/cutlet))
new /obj/item/weapon/reagent_containers/food/snacks/monkeyburger(src)
to_chat(user, "You make a burger.")
qdel(I)
qdel(src)
// Bun + sausage = hotdog
else if(istype(I, /obj/item/weapon/reagent_containers/food/snacks/sausage))
new /obj/item/weapon/reagent_containers/food/snacks/hotdog(src)
to_chat(user, "You make a hotdog.")
qdel(I)
qdel(src)
if(istype(I,/obj/item/weapon/reagent_containers/food/snacks))
if(!recursiveFood && istype(I, /obj/item/weapon/reagent_containers/food/snacks/customizable))
to_chat(user, "<span class='warning'>Sorry, no recursive food.</span>")
return
var/obj/F = new/obj/item/weapon/reagent_containers/food/snacks/customizable/burger(get_turf(src),I)
F.attackby(I, user)
qdel(src)
else
return ..()
/obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough/attackby(obj/item/I, mob/user)
if(istype(I, /obj/item/weapon/reagent_containers/food/snacks))
if(!recursiveFood && istype(I, /obj/item/weapon/reagent_containers/food/snacks/customizable))
to_chat(user, "<span class='warning'>Sorry, no recursive food.</span>")
return
var/obj/F = new/obj/item/weapon/reagent_containers/food/snacks/customizable/pizza(get_turf(src),I)
F.attackby(I, user)
qdel(src)
else
return ..()
/obj/item/weapon/reagent_containers/food/snacks/spagetti/attackby(obj/item/I, mob/user)
if(istype(I, /obj/item/weapon/reagent_containers/food/snacks))
if(!recursiveFood && istype(I, /obj/item/weapon/reagent_containers/food/snacks/customizable))
to_chat(user, "<span class='warning'>Sorry, no recursive food.</span>")
return
var/obj/F = new/obj/item/weapon/reagent_containers/food/snacks/customizable/pasta(get_turf(src),I)
F.attackby(I, user)
qdel(src)
else
return ..()
// Custom Meals ////////////////////////////////////////////////
/*
/obj/item/trash/plate/attackby(obj/item/I, mob/user)
if(istype(I,/obj/item/weapon/reagent_containers/food/snacks))
if(istype(I,/obj/item/weapon/reagent_containers/food/snacks/customizable/fullycustom)) //no platestacking even with recursive food, for now
to_chat(user, "<span class='warning'>That's already got a plate!</span>")
return
var/obj/F = new/obj/item/weapon/reagent_containers/food/snacks/customizable/fullycustom(get_turf(src),I)
F.attackby(I, user)
qdel(src)
else
return ..()
*/
/obj/item/trash/bowl
name = "bowl"
desc = "An empty bowl. Put some food in it to start making a soup."
icon = 'icons/obj/food_custom.dmi'
icon_state = "soup"
/obj/item/trash/bowl/attackby(obj/item/I, mob/user)
if(istype(I,/obj/item/weapon/reagent_containers/food/snacks))
if(!recursiveFood && istype(I, /obj/item/weapon/reagent_containers/food/snacks/customizable))
to_chat(user, "<span class='warning'>Sorry, no recursive food.</span>")
return
var/obj/F = new/obj/item/weapon/reagent_containers/food/snacks/customizable/soup(get_turf(src),I)
F.attackby(I, user)
qdel(src)
else
return ..()

View File

@@ -14,6 +14,13 @@
materials = list(DEFAULT_WALL_MATERIAL = 7000, "glass" = 7000, "gold" = 2000, "diamond" = 3000)
build_path = /obj/item/weapon/implantcase/vrlanguage
/datum/design/item/implant/backup
name = "backup implant"
id = "implant_backup"
req_tech = list(TECH_MATERIAL = 2, TECH_BIO = 2, TECH_DATA = 4, TECH_ENGINEERING = 2)
materials = list(DEFAULT_WALL_MATERIAL = 2000, "glass" = 2000)
build_path = /obj/item/weapon/implantcase/backup
/datum/design/item/weapon/sizegun
name = "shrink ray"
id = "shrinkray"
@@ -36,4 +43,41 @@
req_tech = list(TECH_MAGNET = 4, TECH_COMBAT = 3, TECH_BIO = 3)
materials = list(DEFAULT_WALL_MATERIAL = 1000, "glass" = 1000)
build_path = /obj/item/clothing/glasses/sunglasses/omnihud
sort_string = "GAAFB"
sort_string = "GAAFB"
// Resleeving Circuitboards
/datum/design/circuit/comm_server
name = "grower pod"
id = "transhuman_clonepod"
req_tech = list(TECH_DATA = 3, TECH_BIO = 3)
build_path = /obj/item/weapon/circuitboard/transhuman_clonepod
sort_string = "HAADA"
/datum/design/circuit/transhuman_synthprinter
name = "SynthFab 3000"
id = "transhuman_synthprinter"
req_tech = list(TECH_DATA = 3, TECH_ENGINEERING = 3)
build_path = /obj/item/weapon/circuitboard/transhuman_synthprinter
sort_string = "HAADB"
/datum/design/circuit/transhuman_resleever
name = "resleeving pod"
id = "transhuman_resleever"
req_tech = list(TECH_ENGINEERING = 4, TECH_BIO = 4)
build_path = /obj/item/weapon/circuitboard/transhuman_resleever
sort_string = "HAADC"
/datum/design/circuit/resleeving_control
name = "resleeving control console"
id = "resleeving_control"
req_tech = list(TECH_DATA = 5)
build_path = /obj/item/weapon/circuitboard/resleeving_control
sort_string = "HAADE"
/datum/design/circuit/partslathe
name = "parts lathe"
id = "partslathe"
req_tech = list(TECH_DATA = 2, TECH_ENGINEERING = 2)
build_path = /obj/item/weapon/circuitboard/partslathe
sort_string = "HABAD"

View File

@@ -0,0 +1,3 @@
#define MR_NORMAL 0
#define MR_UNSURE 1
#define MR_DEAD 2

View File

@@ -0,0 +1,41 @@
#ifndef T_BOARD
#error T_BOARD macro is not defined but we need it!
#endif
/obj/item/weapon/circuitboard/transhuman_clonepod
name = T_BOARD("grower pod")
board_type = new /datum/frame/frame_types/machine
build_path = /obj/machinery/clonepod/transhuman
origin_tech = list(TECH_DATA = 3, TECH_BIO = 3)
req_components = list(
/obj/item/stack/cable_coil = 2,
/obj/item/weapon/stock_parts/scanning_module = 2,
/obj/item/weapon/stock_parts/manipulator = 2,
/obj/item/weapon/stock_parts/console_screen = 1)
/obj/item/weapon/circuitboard/transhuman_synthprinter
name = T_BOARD("SynthFab 3000")
board_type = new /datum/frame/frame_types/machine
build_path = /obj/machinery/transhuman/synthprinter
origin_tech = list(TECH_DATA = 3, TECH_ENGINEERING = 3)
req_components = list(
/obj/item/stack/cable_coil = 2,
/obj/item/weapon/stock_parts/matter_bin = 1,
/obj/item/weapon/stock_parts/scanning_module = 1,
/obj/item/weapon/stock_parts/manipulator = 2)
/obj/item/weapon/circuitboard/transhuman_resleever
name = T_BOARD("resleeving pod")
board_type = new /datum/frame/frame_types/machine
build_path = /obj/machinery/transhuman/resleever
origin_tech = list(TECH_ENGINEERING = 4, TECH_BIO = 4)
req_components = list(
/obj/item/stack/cable_coil = 2,
/obj/item/weapon/stock_parts/scanning_module = 2,
/obj/item/weapon/stock_parts/manipulator = 2,
/obj/item/weapon/stock_parts/console_screen = 1)
/obj/item/weapon/circuitboard/resleeving_control
name = T_BOARD("resleeving control console")
build_path = /obj/machinery/computer/transhuman/resleeving
origin_tech = list(TECH_DATA = 5)

View File

@@ -0,0 +1,376 @@
/obj/machinery/computer/transhuman/resleeving
name = "resleeving control console"
icon = 'icons/obj/computer.dmi'
icon_keyboard = "med_key"
icon_screen = "dna"
light_color = "#315ab4"
circuit = /obj/item/weapon/circuitboard/resleeving_control
req_access = list(access_heads) //Only used for record deletion right now.
var/list/pods = list() //Linked grower pods.
var/list/spods = list()
var/list/sleevers = list() //Linked resleeving booths.
var/temp = ""
var/menu = 1 //Which menu screen to display
var/datum/transhuman/body_record/active_br = null
var/datum/transhuman/mind_record/active_mr = null
var/datum/transhuman/infocore/TC //Easy debugging access
var/organic_capable = 1
var/synthetic_capable = 1
var/obj/item/weapon/disk/transcore/disk
/obj/machinery/computer/transhuman/resleeving/initialize()
..()
updatemodules()
TC = transcore
/obj/machinery/computer/transhuman/resleeving/Destroy()
releasepods()
..()
/obj/machinery/computer/transhuman/resleeving/proc/updatemodules()
releasepods()
findpods()
/obj/machinery/computer/transhuman/resleeving/proc/releasepods()
for(var/obj/machinery/clonepod/transhuman/P in pods)
P.connected = null
P.name = initial(P.name)
pods.Cut()
for(var/obj/machinery/transhuman/synthprinter/P in spods)
P.connected = null
P.name = initial(P.name)
spods.Cut()
for(var/obj/machinery/transhuman/resleever/P in sleevers)
P.connected = null
P.name = initial(P.name)
sleevers.Cut()
/obj/machinery/computer/transhuman/resleeving/proc/findpods()
var/num = 1
var/area/A = get_area(src)
for(var/obj/machinery/clonepod/transhuman/P in A.get_contents())
if(!P.connected)
pods += P
P.connected = src
P.name = "[initial(P.name)] #[num++]"
for(var/obj/machinery/transhuman/synthprinter/P in A.get_contents())
if(!P.connected)
spods += P
P.connected = src
P.name = "[initial(P.name)] #[num++]"
for(var/obj/machinery/transhuman/resleever/P in A.get_contents())
if(!P.connected)
sleevers += P
P.connected = src
P.name = "[initial(P.name)] #[num++]"
/obj/machinery/computer/transhuman/resleeving/attackby(obj/item/W as obj, mob/user as mob)
if(istype(W, /obj/item/device/multitool))
var/obj/item/device/multitool/M = W
var/obj/machinery/clonepod/transhuman/P = M.connecting
if(P && !(P in pods))
pods += P
P.connected = src
P.name = "[initial(P.name)] #[pods.len]"
user << "<span class='notice'>You connect [P] to [src].</span>"
else if(istype(W, /obj/item/weapon/disk/transcore))
user.unEquip(W)
disk = W
disk.forceMove(src)
user << "<span class='notice'>You insert \the [W] into \the [src].</span>"
else
..()
return
/obj/machinery/computer/transhuman/resleeving/attack_ai(mob/user as mob)
return attack_hand(user)
/obj/machinery/computer/transhuman/resleeving/attack_hand(mob/user as mob)
user.set_machine(src)
add_fingerprint(user)
if(stat & (BROKEN|NOPOWER))
return
updatemodules()
ui_interact(user)
/obj/machinery/computer/transhuman/resleeving/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
user.set_machine(src)
var/data[0]
var/bodyrecords_list_ui[0]
for(var/N in TC.body_scans)
var/datum/transhuman/body_record/BR = TC.body_scans[N]
bodyrecords_list_ui[++bodyrecords_list_ui.len] = list("name" = N, "recref" = "\ref[BR]")
var/mindrecords_list_ui[0]
for(var/N in TC.backed_up)
var/datum/transhuman/mind_record/MR = TC.backed_up[N]
mindrecords_list_ui[++mindrecords_list_ui.len] = list("name" = N, "recref" = "\ref[MR]")
var/pods_list_ui[0]
for(var/obj/machinery/clonepod/transhuman/pod in pods)
pods_list_ui[++pods_list_ui.len] = list("pod" = pod, "biomass" = pod.biomass)
var/spods_list_ui[0]
for(var/obj/machinery/transhuman/synthprinter/spod in spods)
spods_list_ui[++spods_list_ui.len] = list("spod" = spod, "steel" = spod.stored_material[DEFAULT_WALL_MATERIAL], "glass" = spod.stored_material["glass"])
var/sleevers_list_ui[0]
for(var/obj/machinery/transhuman/resleever/resleever in sleevers)
sleevers_list_ui[++sleevers_list_ui.len] = list("sleever" = resleever, "occupant" = resleever.occupant ? resleever.occupant.real_name : "None")
if(pods)
data["pods"] = pods_list_ui
else
data["pods"] = null
if(spods)
data["spods"] = spods_list_ui
else
data["spods"] = null
if(sleevers)
data["sleevers"] = sleevers_list_ui
else
data["pods"] = null
if(bodyrecords_list_ui.len)
data["bodyrecords"] = bodyrecords_list_ui
else
data["bodyrecords"] = null
if(mindrecords_list_ui.len)
data["mindrecords"] = mindrecords_list_ui
else
data["mindrecords"] = null
if(active_br)
var/can_grow_active = 1
if(!synthetic_capable && active_br.synthetic) //Disqualified due to being synthetic in an organic only.
can_grow_active = 0
else if(!organic_capable && !active_br.synthetic) //Disqualified for the opposite.
can_grow_active = 0
else if(!synthetic_capable && !organic_capable) //What have you done??
can_grow_active = 0
else if(active_br.toocomplex)
can_grow_active = 0
data["activeBodyRecord"] = list("real_name" = active_br.mydna.name, \
"speciesname" = active_br.speciesname ? active_br.speciesname : active_br.mydna.dna.species, \
"gender" = active_br.bodygender, \
"synthetic" = active_br.synthetic ? "Yes" : "No", \
"locked" = active_br.locked ? "Low" : "High", \
"cando" = can_grow_active)
else
data["activeRecord"] = null
if(active_mr)
var/can_sleeve_current = 1
if(!sleevers.len)
can_sleeve_current = 0
data["activeMindRecord"] = list("charname" = active_mr.mindname, \
"obviously_dead" = active_mr.dead_state == MR_DEAD ? "Past-due" : "Current", \
"cando" = can_sleeve_current)
else
data["activeMindRecord"] = null
data["menu"] = menu
data["podsLen"] = pods.len
data["spodsLen"] = spods.len
data["sleeversLen"] = sleevers.len
data["temp"] = temp
data["coredumped"] = transcore.core_dumped
data["emergency"] = disk ? 1 : 0
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "sleever.tmpl", src.name, 400, 450)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(5)
/obj/machinery/computer/transhuman/resleeving/Topic(href, href_list)
if(..())
return 1
else if (href_list["view_brec"])
active_br = locate(href_list["view_brec"])
if(active_br && istype(active_br.mydna))
menu = 4
else
active_br = null
temp = "ERROR: Record missing."
else if (href_list["view_mrec"])
active_mr = locate(href_list["view_mrec"])
if(active_mr && istype(active_mr))
menu = 5
else
active_mr = null
temp = "ERROR: Record missing."
else if (href_list["refresh"])
updateUsrDialog()
else if (href_list["coredump"])
if(disk)
transcore.core_dump(disk)
disk.forceMove(get_turf(src))
disk = null
else if (href_list["ejectdisk"])
disk.forceMove(get_turf(src))
disk = null
else if (href_list["create"])
if(istype(active_br))
//Tried to grow a synth but no synth pods.
if(active_br.synthetic && !spods.len)
temp = "Error: No SynthFabs detected."
//Tried to grow an organic but no growpods.
else if(!active_br.synthetic && !pods.len)
temp = "Error: No growpods detected."
//We have the machines. We can rebuild them. Probably.
else
//We're cloning a synth.
if(active_br.synthetic)
var/obj/machinery/transhuman/synthprinter/spod = spods[1]
if (spods.len > 1)
spod = input(usr,"Select a SynthFab to use", "Printer selection") as anything in spods
//Already doing someone.
if(spod.busy)
temp = "Error: SynthFab is currently busy."
//Not enough steel or glass
else if(spod.stored_material[DEFAULT_WALL_MATERIAL] < spod.body_cost)
temp = "Error: Not enough [DEFAULT_WALL_MATERIAL] in SynthFab."
else if(spod.stored_material["glass"] < spod.body_cost)
temp = "Error: Not enough glass in SynthFab."
//Gross pod (broke mid-cloning or something).
else if(spod.broken)
temp = "Error: SynthFab malfunction."
//Do the cloning!
else if(spod.print(active_br))
temp = "Initiating printing cycle..."
menu = 1
else
temp = "Initiating printing cycle...<br>Error: Post-initialisation failed. Printing cycle aborted."
//We're cloning an organic.
else
var/obj/machinery/clonepod/transhuman/pod = pods[1]
if (pods.len > 1)
pod = input(usr,"Select a growing pod to use", "Pod selection") as anything in pods
//Already doing someone.
if(pod.occupant)
temp = "Error: Growpod is currently occupied."
//Not enough materials.
else if(pod.biomass < CLONE_BIOMASS)
temp = "Error: Not enough biomass."
//Gross pod (broke mid-cloning or something).
else if(pod.mess)
temp = "Error: Growpod malfunction."
//Disabled in config.
else if(!config.revival_cloning)
temp = "Error: Unable to initiate growing cycle."
//Do the cloning!
else if(pod.growclone(active_br))
temp = "Initiating growing cycle..."
menu = 1
else
temp = "Initiating growing cycle...<br>Error: Post-initialisation failed. Growing cycle aborted."
//The body record is broken somehow.
else
temp = "Error: Data corruption."
else if (href_list["sleeve"])
if(istype(active_mr))
if(!sleevers.len)
temp = "Error: No sleevers detected."
else
var/obj/machinery/transhuman/resleever/sleever = sleevers[1]
if (sleevers.len > 1)
sleever = input(usr,"Select a resleeving pod to use", "Resleever selection") as anything in sleevers
//No body to sleeve into.
if(!sleever.occupant)
temp = "Error: Resleeving pod is not occupied."
//OOC body lock thing.
if(sleever.occupant.resleeve_lock && active_mr.ckey != sleever.occupant.resleeve_lock)
temp = "Error: Mind incompatible with body."
//Body to sleeve into, but mind is in another living body.
else if(active_mr.mind_ref.current && active_mr.mind_ref.current.stat < DEAD) //Mind is in a body already that's alive
var/answer = alert(active_mr.mind_ref.current,"Someone is attempting to restore a backup of your mind into another body. Do you want to move to that body? You MAY suffer memory loss! (Same rules as CMD apply)","Resleeving","Yes","No")
//They declined to be moved.
if(answer == "No")
temp = "Initiating resleeving...<br>Error: Post-initialisation failed. Resleeving cycle aborted."
menu = 1
//They approved being moved.
else
sleever.putmind(active_mr)
temp = "Initiating current backup & resleeving..."
menu = 1
//They were dead, or otherwise available.
else
sleever.putmind(active_mr)
temp = "Initiating resleeving..."
menu = 1
//IDK but it broke somehow.
else
temp = "Error: Data corruption."
else if (href_list["menu"])
menu = href_list["menu"]
temp = ""
nanomanager.update_uis(src)
add_fingerprint(usr)
// In here because only relevant to computer
/obj/item/weapon/cmo_disk_holder
name = "cmo emergency packet"
desc = "A small paper packet with printing on one side. \"Tear open in case of Code Delta or Emergency Evacuation ONLY. Use in any other case is UNLAWFUL.\""
icon = 'icons/vore/custom_items_vr.dmi'
icon_state = "cmoemergency"
item_state = "card-id"
/obj/item/weapon/cmo_disk_holder/attack_self(var/mob/attacker)
playsound(src, 'sound/items/poster_ripped.ogg', 50)
attacker << "<span class='warning'>You tear open \the [name].</span>"
attacker.unEquip(src)
var/obj/item/weapon/disk/transcore/newdisk = new(get_turf(src))
attacker.put_in_any_hand_if_possible(newdisk)
qdel(src)
/obj/item/weapon/disk/transcore
name = "TransCore Dump Disk"
desc = "It has a small label. \n\
\"1.INSERT DISK INTO RESLEEVING CONSOLE\n\
2. BEGIN CORE DUMP PROCEDURE\n\
3. ENSURE DISK SAFETY WHEN EJECTED\""
icon = 'icons/obj/cloning.dmi'
icon_state = "harddisk"
item_state = "card-id"
w_class = ITEMSIZE_SMALL
var/datum/transhuman/mind_record/list/stored = list()

View File

@@ -0,0 +1,74 @@
/obj/item/weapon/book/manual/resleeving
name = "Resleeving, the New Cloning?"
icon_state = "stasis"
author = "Dnar Koshi"
title = "Resleeving, the New Cloning?"
dat = {"<html>
<head>
<style>
h1 {font-size: 18px; margin: 15px 0px 5px;}
h2 {font-size: 15px; margin: 15px 0px 5px;}
li {margin: 2px 0px 2px 15px;}
ul {margin: 5px; padding: 0px;}
ol {margin: 5px; padding: 0px 15px;}
body {font-size: 13px; font-family: Verdana;}
</style>
</head>
<body>
<h1><a name="Contents">Contents</a></h1>
<ol>
<li><a href="#Foreword">Foreword: A Licensed Technology</a></li>
<li><a href="#Implant">The Mindstate Backup Implant</a></li>
<li><a href="#Usage">How to Perform Resleeving</a></li>
<li><a href="#Considerations">Special Considerations</a></li>
</ol>
<br>
<h1><a name="Foreword">Foreword: A Licensed Technology</a></h1>
This message must remain attached to all documentation regarding Nanotrasen Resleeving Technology.<br>
All Nanotrasen Resleeving Technology (NRT) is licensed to Nanotrasen by Kitsuhana Heavy Industries. It should only be used in the ways set forth in this guide.
Special consideration to the moral and ethical use of this technology should be undertaken before applying it in the field. Make sure you understand the technology fully before using the machinery.<br>
<a href="#Contents">Contents</a>
<h1><a name="Implant">The Mindstate Backup Implant</a></h1>
Anyone wishing to enjoy the benefits of resleeving must have been implanted with a Mindstate Backup implant. These implants use advanced (licensed) technology to
perform backups of the whole mindstate at periodic intervals. The backups are not constant, however, and being resleeved after death may result in memory loss for
the time since the last backup until the demise of the body. Generally this can encompass anywhere from 5 to 50 minutes, though it has been known to be longer or shorter, depending
on the timing of the backups, when the person expired, and when the resleeving was started.<br>
<a href="#Contents">Contents</a>
<h1><a name="Usage">How to Perform Resleeving</a></h1>
The Nanotrasen Resleeving Technology consists of four machines:
<ul>
<li>The Growpod - For growing organic bodies.</li>
<li>The SynthFab - For recreating synthetic bodies.</li>
<li>The resleeving pod - For combining minds and bodies.</li>
<li>The resleeving console - For controlling the other machines.</li>
</ul>
Performing resleeving is relatively simple. Nanotrasen maintains body-scan backups of all guests taken when you began your employement, applied for a visa, or at another time.
These scans are stored in a database maintained by Nanotrasen, and are sent to stations where it may become necessary to put them to use. You can view all the current body scans at the
resleeving console. You can also view all current mindstate backups at the console.<br>
The process of resleeving is simply:
<ol>
<li>Select a body to create from the body records. This should be the person's original body, or a suitable donor body if none is available.</li>
<li>Create the body using either the SynthFab or the growpod. Upon completion, correct any issues with the body (typically slight genetic or other damage will have occured).</li>
<li>Place the body into the resleeving pod, and select an appropriate mind to sleeve into the body on the console.</li>
<li>Sleeve the mind into the body, using the console.</li>
</ol>
Being resleeved can be a disorienting and painful process. It is very likely that the person will need to acclimate to their new body, and should be given a place to rest for several minutes while
they get used to their motor functions. Resleeving tends to remap these, so it may take a while for the person to become fully acclimated driving their new body.<br>
<a href="#Contents">Contents</a>
<h1><a name="Considerations">Special Considerations</a></h1>
There are some special considerations to be taken into account while using resleeving technology:<br>
<ul>
<li>Resleeving someone while they were already in a living body is extremely disorienting, and can cause memory corruption or loss in some cases. <b>It may be considered medical malpractice. It should only be used as a last resort.</b></li>
<li>Resleeving a mind into a body with a mind already present is <b>extremely unethical</b> and is <b>considered murder</b> in Nanotrasen space. You should not do it under any circumstances.</li>
<li>Needlessly printing copies of bodies wastes resources, and though biomass, metal, and glass may be readily available, these bodies are the property of their original mind. <b>Only print 'spares' with consent.</b></li>
</ul>
Please keep these in mind while using the Nanotrasen Resleeving Technology.<br>
<a href="#Contents">Contents</a>
</body>
</html>
"}

View File

@@ -0,0 +1,79 @@
////////////////////////////////
//// Resleeving implant
//// for both organic and synthetic crew
////////////////////////////////
//The backup implant itself
/obj/item/weapon/implant/backup
name = "backup implant"
desc = "A mindstate backup implant that occasionally stores a copy of one's mind on a central server for backup purposes."
var/last_attempt
var/attempt_delay = 5 MINUTES
/obj/item/weapon/implant/backup/get_data()
var/dat = {"
<b>Implant Specifications:</b><BR>
<b>Name:</b> [company_name] Employee Backup Implant<BR>
<b>Life:</b> ~8 hours.<BR>
<b>Important Notes:</b> Implant is life-limited due to KHI licensing restrictions. Dissolves into harmless biomaterial after around ~8 hours, the typical work shift.<BR>
<HR>
<b>Implant Details:</b><BR>
<b>Function:</b> Contains a small swarm of nanobots that perform neuron scanning to create mind-backups.<BR>
<b>Special Features:</b> Will allow restoring of backups during the 8-hour period it is active.<BR>
<b>Integrity:</b> Generally very survivable. Susceptible to being destroyed by acid."}
return dat
/obj/item/weapon/implant/backup/implanted(var/mob/living/carbon/human/H)
..()
if(istype(H))
var/obj/item/weapon/implant/backup/other_imp = locate(/obj/item/weapon/implant/backup,H)
if(other_imp && other_imp.imp_in == H)
qdel(other_imp) //implant fight
if(H.mind) //One out here just in case they are dead
transcore.m_backup(H.mind)
last_attempt = world.time
backup()
return 1
/obj/item/weapon/implant/backup/proc/backup()
last_attempt = world.time
var/mob/living/carbon/human/H = loc
//Okay we're in a human with a mind at least
if(istype(H) && H == imp_in && H.mind && H.stat < DEAD)
transcore.m_backup(H.mind)
spawn(attempt_delay)
backup()
//The glass case for the implant
/obj/item/weapon/implantcase/backup
name = "glass case - 'backup'"
desc = "A case containing a backup implant."
icon_state = "implantcase-b"
/obj/item/weapon/implantcase/backup/New()
src.imp = new /obj/item/weapon/implant/backup(src)
..()
return
//The box of backup implants
/obj/item/weapon/storage/box/backup_kit
name = "backup implant kit"
desc = "Box of stuff used to implant backup implants."
icon_state = "implant"
item_state_slots = list(slot_r_hand_str = "syringe_kit", slot_l_hand_str = "syringe_kit")
/obj/item/weapon/storage/box/backup_kit/New()
..()
for(var/i = 1 to 7)
new /obj/item/weapon/implantcase/backup(src)
new /obj/item/weapon/implanter(src)
//Purely for fluff
/obj/item/weapon/implant/backup/full
name = "khi backup implant"
desc = "A normal KHI wireless cortical stack with neutrino and QE transmission for constant-stream consciousness upload."

View File

@@ -0,0 +1,227 @@
////////////////////////////////
//// Mind/body data storage system
//// for the resleeving tech
////////////////////////////////
/mob/living/carbon/human/var/resleeve_lock
/mob/living/carbon/human/var/original_player
var/datum/transhuman/infocore/transcore = new/datum/transhuman/infocore
//Mind-backup database
/datum/transhuman/infocore
var/overdue_time = 15 MINUTES
var/process_time = 1 MINUTE
var/core_dumped = 0
var/datum/transhuman/mind_record/list/backed_up = list()
var/datum/transhuman/mind_record/list/has_left = list()
var/datum/transhuman/body_record/list/body_scans = list()
/datum/transhuman/infocore/New()
process()
/datum/transhuman/infocore/proc/process()
if(core_dumped) return
for(var/N in backed_up)
var/datum/transhuman/mind_record/curr_MR = backed_up[N]
if(!curr_MR)
log_debug("Tried to process [N] in transcore w/o a record!")
continue
var/since_backup = world.time - curr_MR.last_update
if(since_backup < overdue_time)
curr_MR.dead_state = MR_NORMAL
else
if(curr_MR.dead_state != MR_DEAD) //First time switching to dead
notify(N)
curr_MR.dead_state = MR_DEAD
spawn(process_time)
process()
/datum/transhuman/infocore/proc/m_backup(var/datum/mind/mind)
ASSERT(mind)
if(!mind.name || core_dumped)
return 0
var/datum/transhuman/mind_record/MR
if(mind.name in backed_up)
MR = backed_up[mind.name]
MR.last_update = world.time
else
MR = new(mind, mind.current, 1)
return 1
/datum/transhuman/infocore/proc/notify(var/name)
ASSERT(name)
var/obj/item/device/radio/headset/a = new /obj/item/device/radio/headset/heads/captain(null)
a.autosay("[name] is past-due for a mind backup. This will be the only notification.", "TransCore Oversight", "Medical")
qdel(a)
/datum/transhuman/infocore/proc/add_backup(var/datum/transhuman/mind_record/MR)
ASSERT(MR)
backed_up[MR.mindname] = MR
log_debug("Added [MR.mindname] to transcore DB.")
/datum/transhuman/infocore/proc/stop_backup(var/datum/transhuman/mind_record/MR)
ASSERT(MR)
has_left[MR.mindname] = MR
backed_up.Remove("[MR.mindname]")
MR.cryo_at = world.time
log_debug("Put [MR.mindname] in transcore suspended DB.")
/datum/transhuman/infocore/proc/add_body(var/datum/transhuman/body_record/BR)
ASSERT(BR)
body_scans[BR.mydna.name] = BR
log_debug("Added [BR.mydna.name] to transcore body DB.")
/datum/transhuman/infocore/proc/core_dump(var/obj/item/weapon/disk/transcore/disk)
ASSERT(disk)
var/obj/item/device/radio/headset/a = new /obj/item/device/radio/headset/heads/captain(null)
a.autosay("An emergency core dump has been initiated!", "TransCore Oversight", "Command")
a.autosay("An emergency core dump has been initiated!", "TransCore Oversight", "Medical")
qdel(a)
disk.stored += backed_up
backed_up.Cut()
core_dumped = 1
return disk.stored.len
/////// Mind-backup record ///////
/datum/transhuman/mind_record
//User visible
var/mindname = "!!ERROR!!"
//0: Normal, 1: Might be dead, 2: Definitely dead, show on console
var/dead_state = 0
var/last_update = 0
//Backend
var/ckey = ""
var/id_gender
var/datum/mind/mind_ref
var/cryo_at
var/languages
var/mind_oocnotes
/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)
if(!istype(M))
return //Only works with humanoids.
//The mind!
mind_ref = mind
mindname = mind.name
ckey = ckey(mind.key)
cryo_at = 0
//Mental stuff the game doesn't keep mentally
id_gender = M.identifying_gender
languages = M.languages.Copy()
mind_oocnotes = M.ooc_notes
last_update = world.time
if(add_to_db)
transcore.add_backup(src)
/////// Body Record ///////
/datum/transhuman/body_record
var/datum/dna2/record/mydna
//These may or may not be set, mostly irrelevant since it's just a body record.
var/ckey
var/locked
var/client/client_ref
var/datum/mind/mind_ref
var/synthetic
var/speciesname
var/bodygender
var/body_oocnotes
var/list/limb_data = list(BP_HEAD, BP_L_HAND, BP_R_HAND, BP_L_ARM, BP_R_ARM, BP_L_FOOT, BP_R_FOOT, BP_L_LEG, BP_R_LEG, BP_GROIN, BP_TORSO)
var/list/organ_data = list(O_HEART, O_EYES, O_LUNGS, O_BRAIN)
var/toocomplex
var/sizemult
/datum/transhuman/body_record/New(var/mob/living/carbon/human/M,var/add_to_db = 1,var/ckeylock = 0)
ASSERT(M)
//Person OOCly doesn't want people impersonating them
locked = ckeylock
//Prevent people from printing restricted and whitelisted species
var/datum/species/S = all_species["[M.dna.species]"]
if(S)
toocomplex = (S.spawn_flags & SPECIES_IS_WHITELISTED) || (S.spawn_flags & SPECIES_IS_RESTRICTED)
//General stuff about them
synthetic = M.isSynthetic()
speciesname = M.custom_species ? M.custom_species : null
bodygender = M.gender
body_oocnotes = M.ooc_notes
sizemult = M.size_multiplier
//Probably should
M.dna.check_integrity()
//The DNA2 stuff
mydna = new ()
mydna.dna = M.dna.Clone()
mydna.ckey = M.ckey
mydna.id = copytext(md5(M.real_name), 2, 6)
mydna.name = M.dna.real_name
mydna.types = DNA2_BUF_UI|DNA2_BUF_UE|DNA2_BUF_SE
mydna.flavor = M.flavor_texts.Copy()
//My stuff
client_ref = M.client
ckey = M.ckey
mind_ref = M.mind
//External organ status. 0:gone, 1:normal, "string":manufacturer
for(var/limb in limb_data)
var/obj/item/organ/external/O = M.organs_by_name[limb]
//Missing limb.
if(!O)
limb_data[limb] = 0
//Has model set, is pros.
else if(O.model)
limb_data[limb] = O.model
//Nothing special, present and normal.
else
limb_data[limb] = 1
//Internal organ status
for(var/org in organ_data)
var/obj/item/organ/I = M.internal_organs_by_name[org]
//Who knows? Missing lungs maybe on synths, etc.
if(!I)
continue
//This needs special handling because brains never think they are 'robotic', even posibrains
if(org == O_BRAIN)
switch(I.type)
if(/obj/item/organ/internal/mmi_holder) //Assisted
organ_data[org] = 1
if(/obj/item/organ/internal/mmi_holder/posibrain) //Mechanical
organ_data[org] = 2
if(/obj/item/organ/internal/mmi_holder/robot) //Digital
organ_data[org] = 3
else //Anything else just give a brain to
organ_data[org] = 0
continue
//Just set the data to this. 0:normal, 1:assisted, 2:mechanical, 3:digital
organ_data[org] = I.robotic
if(add_to_db)
transcore.add_body(src)

View File

@@ -0,0 +1,529 @@
////////////////////////////////
//// Machines required for body printing
//// and decanting into bodies
////////////////////////////////
/////// Grower Pod ///////
/obj/machinery/clonepod/transhuman
name = "grower pod"
circuit = /obj/item/weapon/circuitboard/transhuman_clonepod
/obj/machinery/clonepod/transhuman/growclone(var/datum/transhuman/body_record/current_project)
//Manage machine-specific stuff.
if(mess || attempting)
return 0
attempting = 1 //One at a time!!
locked = 1
eject_wait = 1
spawn(30)
eject_wait = 0
//Get the DNA and generate a new mob
var/datum/dna2/record/R = current_project.mydna
var/mob/living/carbon/human/H = new /mob/living/carbon/human(src, R.dna.species)
if(current_project.locked)
H.resleeve_lock = current_project.ckey
//Fix the external organs
for(var/part in current_project.limb_data)
var/status = current_project.limb_data[part]
if(status == null) continue //Species doesn't have limb? Child of amputated limb?
var/obj/item/organ/external/O = H.organs_by_name[part]
if(!O) continue //Not an organ. Perhaps another amputation removed it already.
if(status == 1) //Normal limbs
continue
else if(status == 0) //Missing limbs
O.remove_rejuv()
else if(status) //Anything else is a manufacturer
O.remove_rejuv() //Don't robotize them, leave them removed so robotics can attach a part.
//Look, this machine can do this because [reasons] okay?!
for(var/part in current_project.organ_data)
var/status = current_project.organ_data[part]
if(status == null) continue //Species doesn't have organ? Child of missing part?
var/obj/item/organ/I = H.internal_organs_by_name[name]
if(!I) continue//Not an organ. Perhaps external conversion changed it already?
if(status == 0) //Normal organ
continue
else if(status == 1) //Assisted organ
I.mechassist()
else if(status == 2) //Mechanical organ
I.robotize()
else if(status == 3) //Digital organ
I.digitize()
occupant = H
//Set the name or generate one
if(!R.dna.real_name)
R.dna.real_name = "clone ([rand(0,999)])"
H.real_name = R.dna.real_name
//Apply DNA
H.dna = R.dna.Clone()
H.original_player = current_project.ckey
//Apply damage
H.adjustCloneLoss(150)
H.Paralyse(4)
H.updatehealth()
//Grower specific mutations
if(heal_level < 60)
randmutb(H)
H.dna.UpdateSE()
H.dna.UpdateUI()
//Update appearance, remake icons
H.UpdateAppearance()
H.sync_organ_dna()
H.regenerate_icons()
//Basically all the VORE stuff
H.ooc_notes = current_project.body_oocnotes
H.flavor_texts = current_project.mydna.flavor.Copy()
H.size_multiplier = current_project.sizemult
if(current_project.speciesname)
H.custom_species = current_project.speciesname
//Suiciding var
H.suiciding = 0
//Making double-sure this is not set
H.mind = null
//Machine specific stuff at the end
update_icon()
attempting = 0
return 1
/obj/machinery/clonepod/transhuman/process()
if(stat & NOPOWER)
if(occupant)
locked = 0
go_out()
return
if((occupant) && (occupant.loc == src))
if(occupant.stat == DEAD)
locked = 0
go_out()
connected_message("Clone Rejected: Deceased.")
return
else if(occupant.health < heal_level && occupant.getCloneLoss() > 0)
//Slowly get that clone healed and finished.
occupant.adjustCloneLoss(-2 * heal_rate)
//Premature clones may have brain damage.
occupant.adjustBrainLoss(-(ceil(0.5*heal_rate)))
//So clones don't die of oxyloss in a running pod.
if(occupant.reagents.get_reagent_amount("inaprovaline") < 30)
occupant.reagents.add_reagent("inaprovaline", 60)
//Also heal some oxyloss ourselves because inaprovaline is so bad at preventing it!!
occupant.adjustOxyLoss(-4)
use_power(7500) //This might need tweaking.
return
else if((occupant.health >= heal_level) && (!eject_wait))
playsound(src.loc, 'sound/machines/ding.ogg', 50, 1)
audible_message("\The [src] signals that the growing process is complete.")
connected_message("Growing Process Complete.")
locked = 0
go_out()
return
else if((!occupant) || (occupant.loc != src))
occupant = null
if(locked)
locked = 0
return
return
//Synthetic version
/obj/machinery/transhuman/synthprinter
name = "SynthFab 3000"
desc = "A rapid fabricator for synthetic bodies."
icon = 'icons/obj/machines/synthpod.dmi'
icon_state = "pod_0"
circuit = /obj/item/weapon/circuitboard/transhuman_synthprinter
density = 1
anchored = 1
var/list/stored_material = list(DEFAULT_WALL_MATERIAL = 30000, "glass" = 30000)
var/connected //What console it's done up with
var/busy = 0 //Busy cloning
var/body_cost = 15000 //Cost of a cloned body (metal and glass ea.)
var/datum/transhuman/body_record/current_project
var/broken = 0
/obj/machinery/transhuman/synthprinter/New()
..()
component_parts = list()
component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
component_parts += new /obj/item/weapon/stock_parts/scanning_module(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/stack/cable_coil(src, 2)
RefreshParts()
update_icon()
/obj/machinery/transhuman/synthprinter/process()
if(stat & NOPOWER)
if(busy)
busy = 0
current_project = null
update_icon()
return
if(busy > 0 && busy <= 95)
busy += 5
if(busy >= 100)
make_body()
return
/obj/machinery/transhuman/synthprinter/proc/print(var/datum/transhuman/body_record/BR)
if(!istype(BR) || busy)
return 0
if(stored_material[DEFAULT_WALL_MATERIAL] < body_cost || stored_material["glass"] < body_cost)
return 0
current_project = BR
busy = 5
update_icon()
return 1
/obj/machinery/transhuman/synthprinter/proc/make_body()
//Manage machine-specific stuff
if(!current_project)
busy = 0
update_icon()
return
//Get the DNA and generate a new mob
var/datum/dna2/record/R = current_project.mydna
var/mob/living/carbon/human/H = new /mob/living/carbon/human(src, R.dna.species)
if(current_project.locked)
H.resleeve_lock = current_project.ckey
//Fix the external organs
for(var/part in current_project.limb_data)
var/status = current_project.limb_data[part]
if(status == null) continue //Species doesn't have limb? Child of amputated limb?
var/obj/item/organ/external/O = H.organs_by_name[part]
if(!O) continue //Not an organ. Perhaps another amputation removed it already.
if(status == 1) //Normal limbs
continue
else if(status == 0) //Missing limbs
O.remove_rejuv()
else if(status) //Anything else is a manufacturer
O.robotize(status)
//Then the internal organs
for(var/part in current_project.organ_data)
var/status = current_project.organ_data[part]
if(status == null) continue //Species doesn't have organ? Child of missing part?
var/obj/item/organ/I = H.internal_organs_by_name[part]
if(!I) continue//Not an organ. Perhaps external conversion changed it already?
if(status == 0) //Normal organ
continue
else if(status == 1) //Assisted organ
I.mechassist()
else if(status == 2) //Mechanical organ
I.robotize()
else if(status == 3) //Digital organ
I.digitize()
//Set the name or generate one
if(!R.dna.real_name)
R.dna.real_name = "synth ([rand(0,999)])"
H.real_name = R.dna.real_name
//Apply DNA
H.dna = R.dna.Clone()
H.original_player = current_project.ckey
//Apply damage
H.adjustBruteLoss(20)
H.adjustFireLoss(20)
H.updatehealth()
//Update appearance, remake icons
H.UpdateAppearance()
H.sync_organ_dna()
H.regenerate_icons()
//Basically all the VORE stuff
H.ooc_notes = current_project.body_oocnotes
H.flavor_texts = current_project.mydna.flavor.Copy()
H.size_multiplier = current_project.sizemult
if(current_project.speciesname)
H.custom_species = current_project.speciesname
//Suiciding var
H.suiciding = 0
//Making double-sure this is not set
H.mind = null
//Plonk them here.
H.regenerate_icons()
H.loc = get_turf(src)
//Machine specific stuff at the end
stored_material[DEFAULT_WALL_MATERIAL] -= body_cost
stored_material["glass"] -= body_cost
busy = 0
update_icon()
return 1
/obj/machinery/transhuman/synthprinter/attack_hand(mob/user as mob)
if((busy == 0) || (stat & NOPOWER))
return
user << "Current print cycle is [busy]% complete."
return
/obj/machinery/transhuman/synthprinter/attackby(obj/item/W as obj, mob/user as mob)
src.add_fingerprint(user)
if(busy)
user << "<span class='notice'>\The [src] is busy. Please wait for completion of previous operation.</span>"
return
if(default_deconstruction_screwdriver(user, W))
return
if(default_deconstruction_crowbar(user, W))
return
if(default_part_replacement(user, W))
return
if(panel_open)
user << "<span class='notice'>You can't load \the [src] while it's opened.</span>"
return
if(!istype(W, /obj/item/stack/material))
user << "<span class='notice'>You cannot insert this item into \the [src]!</span>"
return
var/obj/item/stack/material/S = W
if(!(S.material.name in stored_material))
user << "<span class='warning'>\the [src] doesn't accept [S.material]!</span>"
return
var/amnt = S.perunit
var/max_res_amount = 30000
if(stored_material[S.material.name] + amnt <= max_res_amount)
if(S && S.amount >= 1)
var/count = 0
while(stored_material[S.material.name] + amnt <= max_res_amount && S.amount >= 1)
stored_material[S.material.name] += amnt
S.use(1)
count++
user << "You insert [count] [S.name] into \the [src]."
else
user << "\the [src] cannot hold more [S.name]."
updateUsrDialog()
return
/obj/machinery/transhuman/synthprinter/update_icon()
..()
icon_state = "pod_0"
if(busy && !(stat & NOPOWER))
icon_state = "pod_1"
else if(broken)
icon_state = "pod_g"
/////// Resleever Pod ///////
/obj/machinery/transhuman/resleever
name = "resleeving pod"
desc = "Used to combine mind and body into one unit."
icon = 'icons/obj/machines/implantchair.dmi'
icon_state = "implantchair"
circuit = /obj/item/weapon/circuitboard/transhuman_resleever
density = 1
opacity = 0
anchored = 1
var/blur_amount
var/confuse_amount
var/mob/living/carbon/human/occupant = null
var/connected = null
/obj/machinery/transhuman/resleever/New()
..()
component_parts = list()
component_parts += new /obj/item/weapon/stock_parts/scanning_module(src)
component_parts += new /obj/item/weapon/stock_parts/scanning_module(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/weapon/stock_parts/console_screen(src)
component_parts += new /obj/item/stack/cable_coil(src, 2)
RefreshParts()
update_icon()
/obj/machinery/transhuman/resleever/RefreshParts()
var/scan_rating = 0
for(var/obj/item/weapon/stock_parts/scanning_module/SM in component_parts)
scan_rating += SM.rating
confuse_amount = (48 - scan_rating * 8)
var/manip_rating = 0
for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts)
manip_rating += M.rating
blur_amount = (48 - manip_rating * 8)
/obj/machinery/transhuman/resleever/attack_hand(mob/user as mob)
user.set_machine(src)
var/health_text = ""
var/mind_text = ""
if(src.occupant)
if(src.occupant.stat >= DEAD)
health_text = "<FONT color=red>DEAD</FONT>"
else if(src.occupant.health < 0)
health_text = "<FONT color=red>[round(src.occupant.health,0.1)]</FONT>"
else
health_text = "[round(src.occupant.health,0.1)]"
if(src.occupant.mind)
mind_text = "Mind present: [occupant.mind.name]"
else
mind_text = "Mind absent."
var/dat ="<B>Resleever Status</B><BR>"
dat +="<B>Current occupant:</B> [src.occupant ? "<BR>Name: [src.occupant]<BR>Health: [health_text]<BR>" : "<FONT color=red>None</FONT>"]<BR>"
dat +="<B>Mind status:</B> [mind_text]<BR>"
user.set_machine(src)
user << browse(dat, "window=resleever")
onclose(user, "resleever")
/obj/machinery/transhuman/resleever/attackby(obj/item/W as obj, mob/user as mob)
src.add_fingerprint(user)
if(default_deconstruction_screwdriver(user, W))
return
if(default_deconstruction_crowbar(user, W))
return
if(default_part_replacement(user, W))
return
if(istype(W, /obj/item/weapon/grab))
var/obj/item/weapon/grab/G = W
if(!ismob(G.affecting))
return
for(var/mob/living/carbon/slime/M in range(1, G.affecting))
if(M.Victim == G.affecting)
usr << "[G.affecting:name] will not fit into the [src.name] because they have a slime latched onto their head."
return
var/mob/M = G.affecting
if(put_mob(M))
qdel(G)
src.updateUsrDialog()
return ..()
/obj/machinery/transhuman/resleever/proc/putmind(var/datum/transhuman/mind_record/MR)
if(!occupant || !istype(occupant) || occupant.stat >= DEAD)
return 0
//In case they already had a mind!
occupant << "<span class='warning'>You feel your mind being overwritten...</span>"
if(occupant.mind)
log_and_message_admins("was resleeve-wiped from their body.",occupant.mind)
occupant.ghostize()
//Attach as much stuff as possible to the mob.
for(var/datum/language/L in MR.languages)
occupant.add_language(L.name)
MR.mind_ref.active = 1 //Well, it's about to be.
MR.mind_ref.transfer_to(occupant) //Does mind+ckey+client.
occupant.identifying_gender = MR.id_gender
occupant.ooc_notes = MR.mind_oocnotes
occupant.apply_vore_prefs() //Cheap hack for now to give them SOME bellies.
//Give them a backup implant
var/obj/item/weapon/implant/backup/new_imp = new()
if(new_imp.implanted(occupant))
new_imp.loc = occupant
new_imp.imp_in = occupant
new_imp.implanted = 1
//Put it in the head! Makes sense.
var/obj/item/organ/external/affected = occupant.get_organ(BP_HEAD)
affected.implants += new_imp
new_imp.part = affected
//Inform them and make them a little dizzy.
if(confuse_amount + blur_amount <= 16)
occupant << "<span class='notice'>You feel a small pain in your head as you're given a new backup implant. Your new body feels comfortable already, however.</span>"
else
occupant << "<span class='warning'>You feel a small pain in your head as you're given a new backup implant. Oh, and a new body. It's disorienting, to say the least.</span>"
occupant.confused = max(occupant.confused, confuse_amount)
occupant.eye_blurry = max(occupant.eye_blurry, blur_amount)
if(occupant.original_player != occupant.ckey)
log_and_message_admins("is now a cross-sleeved character. Body originally belonged to [occupant.original_player]. Mind is now [occupant.mind.name].",occupant)
return 1
/obj/machinery/transhuman/resleever/proc/go_out(var/mob/M)
if(!( src.occupant ))
return
if (src.occupant.client)
src.occupant.client.eye = src.occupant.client.mob
src.occupant.client.perspective = MOB_PERSPECTIVE
src.occupant.loc = src.loc
src.occupant = null
icon_state = "implantchair"
return
/obj/machinery/transhuman/resleever/proc/put_mob(mob/living/carbon/human/M as mob)
if(!ishuman(M))
usr << "<span class='warning'>\The [src] cannot hold this!</span>"
return
if(src.occupant)
usr << "<span class='warning'>\The [src] is already occupied!</span>"
return
if(M.client)
M.client.perspective = EYE_PERSPECTIVE
M.client.eye = src
M.stop_pulling()
M.loc = src
src.occupant = M
src.add_fingerprint(usr)
icon_state = "implantchair_on"
return 1
/obj/machinery/transhuman/resleever/verb/get_out()
set name = "EJECT Occupant"
set category = "Object"
set src in oview(1)
if(usr.stat != 0)
return
src.go_out(usr)
add_fingerprint(usr)
return
/obj/machinery/transhuman/resleever/verb/move_inside()
set name = "Move INSIDE"
set category = "Object"
set src in oview(1)
if(usr.stat != 0 || stat & (NOPOWER|BROKEN))
return
put_mob(usr)
return

View File

@@ -0,0 +1,46 @@
// Bluespace crystals, used in telescience and when crushed it will blink you to a random turf.
/obj/item/weapon/ore/bluespace_crystal
name = "bluespace crystal"
desc = "A glowing bluespace crystal, not much is known about how they work. It looks very delicate."
icon = 'icons/obj/telescience.dmi'
icon_state = "bluespace_crystal"
w_class = ITEMSIZE_TINY
origin_tech = list(TECH_BLUESPACE = 6, TECH_MATERIAL = 3)
var/blink_range = 8 // The teleport range when crushed/thrown at someone.
/obj/item/weapon/ore/bluespace_crystal/New()
..()
pixel_x = rand(-5, 5)
pixel_y = rand(-5, 5)
/obj/item/weapon/ore/bluespace_crystal/attack_self(mob/user)
user.visible_message("<span class='warning'>[user] crushes [src]!</span>", "<span class='danger'>You crush [src]!</span>")
var/datum/effect/effect/system/spark_spread/s = PoolOrNew(/datum/effect/effect/system/spark_spread)
s.set_up(5, 1, get_turf(src))
s.start()
blink_mob(user)
user.unEquip(src)
qdel(src)
/obj/item/weapon/ore/bluespace_crystal/proc/blink_mob(mob/living/L)
do_teleport(L, get_turf(L), blink_range, asoundin = 'sound/effects/phasein.ogg')
/obj/item/weapon/ore/bluespace_crystal/throw_impact(atom/hit_atom)
if(!..()) // not caught in mid-air
visible_message("<span class='notice'>[src] fizzles and disappears upon impact!</span>")
var/turf/T = get_turf(hit_atom)
var/datum/effect/effect/system/spark_spread/s = PoolOrNew(/datum/effect/effect/system/spark_spread)
s.set_up(5, 1, T)
s.start()
if(isliving(hit_atom))
blink_mob(hit_atom)
qdel(src)
// Artifical bluespace crystal, doesn't give you much research.
/obj/item/weapon/ore/bluespace_crystal/artificial
name = "artificial bluespace crystal"
desc = "An artificially made bluespace crystal, it looks delicate."
origin_tech = list(TECH_BLUESPACE = 3, TECH_PHORON = 4)
blink_range = 4 // Not as good as the organic stuff!

View File

@@ -0,0 +1,53 @@
#ifndef T_BOARD
#error T_BOARD macro is not defined but we need it!
#endif
// The circuit boards
/obj/item/weapon/circuitboard/telesci_console
name = T_BOARD("Telepad Control Console")
build_path = /obj/machinery/computer/telescience
origin_tech = list(TECH_DATA = 3, TECH_BLUESPACE = 3, TECH_PHORON = 4)
/obj/item/weapon/circuitboard/telesci_pad
name = T_BOARD("Telepad")
board_type = new /datum/frame/frame_types/machine
build_path = /obj/machinery/telepad
origin_tech = list(TECH_DATA = 4, TECH_ENGINEERING = 4, TECH_PHORON = 4, TECH_BLUESPACE = 5)
req_components = list(
/obj/item/weapon/ore/bluespace_crystal = 1,
/obj/item/weapon/stock_parts/capacitor = 2,
/obj/item/stack/cable_coil = 5,
/obj/item/weapon/stock_parts/console_screen = 1)
// The Designs
/datum/design/circuit/telesci_console
name = "Telepad Control Console"
id = "telesci_console"
req_tech = list(TECH_DATA = 3, TECH_BLUESPACE = 3, TECH_PHORON = 4)
build_path = /obj/item/weapon/circuitboard/telesci_console
sort_string = "HAAEA"
/datum/design/circuit/telesci_pad
name = "Telepad"
id = "telesci_pad"
req_tech = list(TECH_DATA = 4, TECH_ENGINEERING = 4, TECH_PHORON = 4, TECH_BLUESPACE = 5)
build_path = /obj/item/weapon/circuitboard/telesci_pad
sort_string = "HAAEB"
/datum/design/item/telesci_gps
name = "GPS device"
id = "telesci_gps"
req_tech = list(TECH_MATERIAL = 2, TECH_BLUESPACE = 2)
materials = list(DEFAULT_WALL_MATERIAL = 500, "glass" = 1000)
build_path = /obj/item/device/gps/advanced
sort_string = "HAAEB"
/datum/design/item/bluespace_crystal
name = "Artificial Bluespace Crystal"
id = "bluespace_crystal"
req_tech = list(TECH_BLUESPACE = 3, TECH_PHORON = 4)
materials = list("diamond" = 1500, "phoron" = 1500)
build_path = /obj/item/weapon/ore/bluespace_crystal/artificial
sort_string = "HAAEC"

View File

@@ -0,0 +1,78 @@
var/global/list/GPS_list = list()
// These are distinguished from the ordinary "Relay Position Devices" that just print your location
// In that they are also all networked with each other to show each other's locations.
/obj/item/device/gps/advanced
name = "global positioning system"
desc = "Helping lost spacemen find their way through the planets since 1995."
icon = 'icons/obj/telescience.dmi'
icon_state = "gps-c"
w_class = ITEMSIZE_SMALL
slot_flags = SLOT_BELT
origin_tech = list(TECH_DATA = 2, TECH_ENGINEERING = 2)
var/gpstag = "COM0"
var/emped = 0
/obj/item/device/gps/advanced/New()
..()
GPS_list.Add(src)
name = "global positioning system ([gpstag])"
overlays += "working"
/obj/item/device/gps/advanced/Del()
GPS_list.Remove(src)
..()
/obj/item/device/gps/advanced/emp_act(severity)
emped = 1
overlays -= "working"
overlays += "emp"
spawn(300)
emped = 0
overlays -= "emp"
overlays += "working"
/obj/item/device/gps/advanced/attack_self(mob/user as mob)
var/obj/item/device/gps/advanced/t = ""
if(emped)
t += "ERROR"
else
t += "<BR><A href='?src=\ref[src];tag=1'>Set Tag</A> "
t += "<BR>Tag: [gpstag]"
for(var/obj/item/device/gps/advanced/G in GPS_list)
var/turf/pos = get_turf(G)
var/area/gps_area = get_area(G)
var/tracked_gpstag = G.gpstag
if(G.emped == 1)
t += "<BR>[tracked_gpstag]: ERROR"
else
t += "<BR>[tracked_gpstag]: [format_text(gps_area.name)] ([pos.x], [pos.y], [pos.z])"
var/datum/browser/popup = new(user, "GPS", name, 600, 450)
popup.set_content(t)
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
popup.open()
/obj/item/device/gps/advanced/Topic(href, href_list)
..()
if(href_list["tag"] )
var/a = input("Please enter desired tag.", name, gpstag) as text
a = uppertext(copytext(sanitize(a), 1, 5))
if(src.loc == usr)
gpstag = a
name = "global positioning system ([gpstag])"
attack_self(usr)
/obj/item/device/gps/advanced/science
icon_state = "gps-s"
gpstag = "SCI0"
/obj/item/device/gps/advanced/engineering
icon_state = "gps-e"
gpstag = "ENG0"
/obj/item/device/gps/advanced/security
icon_state = "gps-sec"
gpstag = "SEC0"

View File

@@ -0,0 +1,47 @@
///SCI TELEPAD///
/obj/machinery/telepad
name = "telepad"
desc = "A bluespace telepad used for teleporting objects to and from a location."
icon = 'icons/obj/telescience.dmi'
icon_state = "pad-idle"
anchored = 1
use_power = 1
circuit = /obj/item/weapon/circuitboard/telesci_pad
idle_power_usage = 200
active_power_usage = 5000
var/efficiency
/obj/machinery/telepad/New()
..()
component_parts = list()
component_parts += new /obj/item/weapon/ore/bluespace_crystal(src)
component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
component_parts += new /obj/item/weapon/stock_parts/console_screen(src)
component_parts += new /obj/item/stack/cable_coil(src, 5)
RefreshParts()
update_icon()
/obj/machinery/telepad/RefreshParts()
var/E
for(var/obj/item/weapon/stock_parts/capacitor/C in component_parts)
E += C.rating
efficiency = E
/obj/machinery/telepad/attackby(obj/item/W as obj, mob/user as mob)
src.add_fingerprint(user)
if(default_deconstruction_screwdriver(user, W))
return
if(default_deconstruction_crowbar(user, W))
return
if(default_part_replacement(user, W))
return
if(panel_open)
if(istype(W, /obj/item/device/multitool))
var/obj/item/device/multitool/M = W
M.connectable = src
user << "<span class='caution'>You save the data in the [M.name]'s buffer.</span>"
return 1
return ..()

View File

@@ -0,0 +1,384 @@
/obj/machinery/computer/telescience
name = "\improper Telepad Control Console"
desc = "Used to teleport objects to and from the telescience telepad."
icon_screen = "teleport"
icon_keyboard = "teleport_key"
circuit = /obj/item/weapon/circuitboard/telesci_console
var/sending = 1
var/obj/machinery/telepad/telepad = null
var/temp_msg = "Telescience control console initialized.<BR>Welcome."
// VARIABLES //
var/teles_left // How many teleports left until it becomes uncalibrated
var/datum/projectile_data/last_tele_data = null
var/z_co = 1
var/distance_off
var/rotation_off
var/turf/last_target
var/rotation = 0
var/distance = 5
// Based on the distance used
var/teleport_cooldown = 0
var/teleporting = 0
var/starting_crystals = 2
var/max_crystals = 4
// Used to adjust OP-ness: (4 crystals * 6 efficiency * 12.5 coefficient) = 300 range.
var/powerCoefficient = 12.5
var/list/crystals = list()
var/obj/item/device/gps/inserted_gps
/obj/machinery/computer/telescience/New()
..()
recalibrate()
/obj/machinery/computer/telescience/Destroy()
eject()
if(inserted_gps)
inserted_gps.forceMove(loc)
inserted_gps = null
return ..()
/obj/machinery/computer/telescience/examine(mob/user)
..()
user << "There are [crystals.len ? crystals.len : "no"] bluespace crystal\s in the crystal slots."
/obj/machinery/computer/telescience/initialize()
..()
for(var/i = 1; i <= starting_crystals; i++)
crystals += new /obj/item/weapon/ore/bluespace_crystal/artificial(src) // starting crystals
/obj/machinery/computer/telescience/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/weapon/ore/bluespace_crystal))
if(crystals.len >= max_crystals)
user << "<span class='warning'>There are not enough crystal slots.</span>"
return
if(!user.unEquip(W))
return
crystals += W
W.forceMove(src)
user.visible_message("[user] inserts [W] into \the [src]'s crystal slot.", "<span class='notice'>You insert [W] into \the [src]'s crystal slot.</span>")
updateDialog()
else if(istype(W, /obj/item/device/gps))
if(!inserted_gps)
inserted_gps = W
user.unEquip(W)
W.forceMove(src)
user.visible_message("[user] inserts [W] into \the [src]'s GPS device slot.", "<span class='notice'>You insert [W] into \the [src]'s GPS device slot.</span>")
else if(istype(W, /obj/item/device/multitool))
var/obj/item/device/multitool/M = W
if(M.connectable && istype(M.connectable, /obj/machinery/telepad))
telepad = M.connectable
M.connectable = null
user << "<span class='caution'>You upload the data from the [W.name]'s buffer.</span>"
else
return ..()
/obj/machinery/computer/telescience/proc/get_max_allowed_distance()
return Floor(crystals.len * telepad.efficiency * powerCoefficient)
/obj/machinery/computer/telescience/attack_ai(mob/user)
src.attack_hand(user)
/obj/machinery/computer/telescience/attack_hand(mob/user)
if(..())
return
ui_interact(user)
/obj/machinery/computer/telescience/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
user.set_machine(src)
var/data[0]
if(!telepad)
in_use = 0 //Yeah so if you deconstruct teleporter while its in the process of shooting it wont disable the console
data["noTelepad"] = 1
else
data["insertedGps"] = inserted_gps
data["rotation"] = rotation
data["currentZ"] = z_co
data["cooldown"] = max(0, min(100, round(teleport_cooldown - world.time) / 10))
data["crystalCount"] = crystals.len
data["maxCrystals"] = max_crystals
data["maxPossibleDistance"] = Floor(max_crystals * powerCoefficient * 6); // max efficiency is 6
data["maxAllowedDistance"] = get_max_allowed_distance()
data["distance"] = distance
data["tempMsg"] = temp_msg
if(telepad.panel_open)
data["tempMsg"] = "Telepad undergoing physical maintenance operations."
data["sectorOptions"] = list()
for(var/z in config.player_levels)
data["sectorOptions"] += z
if(last_tele_data)
data["lastTeleData"] = list()
data["lastTeleData"]["src_x"] = last_tele_data.src_x
data["lastTeleData"]["src_y"] = last_tele_data.src_y
data["lastTeleData"]["distance"] = last_tele_data.distance
data["lastTeleData"]["time"] = last_tele_data.time
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "telescience_console.tmpl", src.name, 400, 450)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(5)
/obj/machinery/computer/telescience/proc/sparks()
if(telepad)
var/datum/effect/effect/system/spark_spread/s = PoolOrNew(/datum/effect/effect/system/spark_spread)
s.set_up(5, 1, get_turf(telepad))
s.start()
else
return
/obj/machinery/computer/telescience/proc/telefail()
switch(rand(99))
if(0 to 85)
sparks()
visible_message("<span class='warning'>The telepad weakly fizzles.</span>")
return
if(86 to 90)
// Irradiate everyone in telescience!
for(var/obj/machinery/telepad/E in machines)
var/L = get_turf(E)
sparks(target = L)
for(var/mob/living/carbon/human/M in viewers(L, null))
M.apply_effect((rand(10, 20)), IRRADIATE, 0)
to_chat(M, "<span class='warning'>You feel strange.</span>")
return
if(91 to 98)
// They did the mash! (They did the monster mash!) The monster mash! (It was a graveyard smash!)
sparks()
if(telepad)
var/L = get_turf(telepad)
var/blocked = list(/mob/living/simple_animal/hostile/vore)
var/list/hostiles = typesof(/mob/living/simple_animal/hostile/vore) - blocked
playsound(L, 'sound/effects/phasein.ogg', 100, 1, extrarange = 3, falloff = 5)
for(var/i in 1 to rand(1,4))
var/chosen = pick(hostiles)
var/mob/living/simple_animal/hostile/H = new chosen
H.forceMove(L)
return
if(99)
sparks()
visible_message("<span class='warning'>The telepad changes colors rapidly, and opens a portal, and you see what your mind seems to think is the very threads that hold the pattern of the universe together, and a eerie sense of paranoia creeps into you.</span>")
spacevine_infestation()
return
/obj/machinery/computer/telescience/proc/doteleport(mob/user)
if(teleport_cooldown > world.time)
return
if(teleporting)
return
if(telepad)
var/trueDistance = Clamp(distance + distance_off, 1, get_max_allowed_distance())
var/trueRotation = rotation + rotation_off
var/datum/projectile_data/proj_data = simple_projectile_trajectory(telepad.x, telepad.y, trueRotation, trueDistance)
last_tele_data = proj_data
var/trueX = proj_data.dest_x
var/trueY = proj_data.dest_y
if(trueX < 1 || trueX > world.maxx || trueY < 1 || trueY > world.maxy)
telefail()
temp_msg = "ERROR! Target coordinate is outside known time and space!"
return
var/spawn_time = round(proj_data.time) * 10
var/turf/target = locate(trueX, trueY, z_co)
last_target = target
var/area/A = get_area(target)
flick("pad-beam", telepad)
if(spawn_time > 15) // 1.5 seconds
playsound(telepad.loc, 'sound/weapons/flash.ogg', 50, 1)
// Wait depending on the time the projectile took to get there
teleporting = 1
temp_msg = "Powering up bluespace crystals.<BR>Please wait."
spawn(spawn_time) // in deciseconds
if(!telepad)
return
if(telepad.inoperable())
return
teleporting = 0
teleport_cooldown = world.time + (spawn_time * 2)
teles_left -= 1
// use a lot of power
use_power(trueDistance * 10000)
var/datum/effect/effect/system/spark_spread/S = PoolOrNew(/datum/effect/effect/system/spark_spread)
S.set_up(5, 1, get_turf(telepad))
S.start()
if(!A || (A.flags & BLUE_SHIELDED))
telefail()
temp_msg = "ERROR!<BR>Target is shielded from bluespace intersection!"
return
temp_msg = "Teleport successful.<BR>"
if(teles_left < 10)
temp_msg += "Calibration required soon.<BR>"
temp_msg += "Data printed below."
var/sparks = get_turf(target)
var/datum/effect/effect/system/spark_spread/Y = PoolOrNew(/datum/effect/effect/system/spark_spread)
Y.set_up(5, 1, sparks)
Y.start()
var/turf/source = target
var/turf/dest = get_turf(telepad)
var/log_msg = ""
log_msg += ": [key_name(user)] has teleported "
if(sending)
source = dest
dest = target
flick("pad-beam", telepad)
playsound(telepad.loc, 'sound/weapons/emitter2.ogg', 25, 1, extrarange = 3, falloff = 5)
for(var/atom/movable/ROI in source)
// if is anchored, don't let through
if(ROI.anchored)
if(isliving(ROI))
var/mob/living/L = ROI
if(L.buckled)
// TP people on office chairs
if(L.buckled.anchored)
continue
log_msg += "[key_name(L)] (on a chair), "
else
continue
else if(!isobserver(ROI))
continue
if(ismob(ROI))
var/mob/T = ROI
log_msg += "[key_name(T)], "
else
log_msg += "[ROI.name]"
if (istype(ROI, /obj/structure/closet))
var/obj/structure/closet/C = ROI
log_msg += " ("
for(var/atom/movable/Q as mob|obj in C)
if(ismob(Q))
log_msg += "[key_name(Q)], "
else
log_msg += "[Q.name], "
if (dd_hassuffix(log_msg, "("))
log_msg += "empty)"
else
log_msg += ")"
log_msg += ", "
do_teleport(ROI, dest)
if (!dd_hassuffix(log_msg, ", "))
log_msg += "nothing"
log_msg += " [sending ? "to" : "from"] [trueX], [trueY], [z_co] ([A ? A.name : "null area"])"
investigate_log(log_msg, "telesci")
updateDialog()
/obj/machinery/computer/telescience/proc/teleport(mob/user)
distance = Clamp(distance, 0, get_max_allowed_distance())
if(rotation == null || distance == null || z_co == null)
temp_msg = "ERROR!<BR>Set a distance, rotation and sector."
return
if(distance <= 0)
telefail()
temp_msg = "ERROR!<BR>No distance selected!"
return
if(!(z_co in config.player_levels))
telefail()
temp_msg = "ERROR! Sector is outside known time and space!"
return
if(teles_left > 0)
doteleport(user)
else
telefail()
temp_msg = "ERROR!<BR>Calibration required."
return
return
/obj/machinery/computer/telescience/proc/eject()
for(var/obj/item/I in crystals)
I.forceMove(src.loc)
crystals -= I
distance = 0
/obj/machinery/computer/telescience/Topic(href, href_list)
if(..())
return
if(!telepad || telepad.panel_open)
updateDialog()
return
if(href_list["setrotation"])
var/new_rot = input("Please input desired bearing in degrees.", name, rotation) as num
if(..()) // Check after we input a value, as they could've moved after they entered something
return
rotation = Clamp(new_rot, -900, 900)
rotation = round(rotation, 0.01)
if(href_list["setdistance"])
var/new_pow = input("Please input desired distance in meters.", name, rotation) as num
if(..()) // Check after we input a value, as they could've moved after they entered something
return
distance = Clamp(new_pow, 1, get_max_allowed_distance())
distance = Floor(distance)
if(href_list["setz"])
var/new_z = text2num(href_list["setz"])
if(new_z in config.player_levels)
z_co = new_z
if(href_list["ejectGPS"])
if(inserted_gps)
inserted_gps.forceMove(loc)
inserted_gps = null
if(href_list["setMemory"])
if(last_target && inserted_gps)
// TODO - What was this even supposed to do??
//inserted_gps.locked_location = last_target
temp_msg = "Location saved."
else
temp_msg = "ERROR!<BR>No data was stored."
if(href_list["send"])
sending = 1
teleport(usr)
if(href_list["receive"])
sending = 0
teleport(usr)
if(href_list["recal"])
recalibrate()
sparks()
temp_msg = "NOTICE:<BR>Calibration successful."
if(href_list["eject"])
eject()
temp_msg = "NOTICE:<BR>Bluespace crystals ejected."
updateDialog()
/obj/machinery/computer/telescience/proc/recalibrate()
teles_left = rand(40, 50)
distance_off = rand(-4, 4)
rotation_off = rand(-10, 10)
// Procedure that calculates the actual trajectory taken!
/proc/simple_projectile_trajectory(var/src_x, var/src_y, var/rotation, var/distance)
var/time = distance / 10 // 100ms per distance seems fine?
var/dest_x = src_x + distance*sin(rotation);
var/dest_y = src_y + distance*cos(rotation);
return new /datum/projectile_data(src_x, src_y, time, distance, 0, 0, dest_x, dest_y)

View File

@@ -45,8 +45,8 @@ var/list/ventcrawl_machinery = list(
if(carried_item == ability_master)
return 1
for(var/type in can_enter_vent_with)
if(istype(carried_item, can_enter_vent_with))
return get_inventory_slot(carried_item) == 0
if(istype(carried_item, type)) //VOREStation Edit - It was a typo before maybe?
return 1 //VOREStation Edit also
return 0
/mob/living/carbon/is_allowed_vent_crawl_item(var/obj/item/carried_item)

View File

@@ -158,6 +158,11 @@
icon_state = "bunny"
do_colouration = 1
/datum/sprite_accessory/ears/antlers
name = "antlers"
desc = ""
icon_state = "antlers"
// Special snowflake ears go below here.
/datum/sprite_accessory/ears/molenar_kitsune

View File

@@ -0,0 +1,93 @@
//Dat AI vore yo
#define HOLO_ORIGINAL_COLOR null //This seems to work for some reason? And look better?
#define HOLO_HARDLIGHT_COLOR "#d97de0"
#define HOLO_ORIGINAL_ALPHA 128
#define HOLO_HARDLIGHT_ALPHA 210
/obj/effect/overlay/aiholo
var/mob/living/bellied //Only belly one person at a time. No huge vore-organs setup for AIs.
pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE
alpha = HOLO_ORIGINAL_ALPHA //Half alpha here rather than in the icon so we can toggle it easily.
color = HOLO_ORIGINAL_COLOR //This is the blue from icons.dm that it was before.
desc = "A hologram representing an AI persona."
/obj/effect/overlay/aiholo/proc/get_prey(var/mob/living/prey)
if(bellied) return
playsound('sound/effects/stealthoff.ogg',50,0)
bellied = prey
prey.forceMove(src)
visible_message("[src] entirely engulfs [prey] in hardlight holograms!")
usr << "<span class='notice'>You completely engulf [prey] in hardlight holograms!</span>" //Can't be part of the above, because the above is from the hologram.
desc = "[initial(desc)] It seems to have hardlight mode enabled and someone inside."
pass_flags = 0
color = HOLO_HARDLIGHT_COLOR
alpha = HOLO_HARDLIGHT_ALPHA
/obj/effect/overlay/aiholo/proc/drop_prey()
if(!bellied) return
playsound('sound/effects/stealthoff.ogg',50,0)
bellied.forceMove(get_turf(src))
bellied.Weaken(2)
bellied.visible_message("[bellied] flops out of \the [src].","You flop out of \the [src].","You hear a thud.")
bellied = null
desc = "[initial(desc)]"
pass_flags = initial(pass_flags)
color = initial(color)
alpha = initial(alpha)
/obj/effect/overlay/aiholo/Destroy()
drop_prey()
..()
/mob/living/silicon/ai/verb/holo_nom()
set name = "Hardlight Nom"
set category = "Vore"
set desc = "Wrap up a person in hardlight holograms."
// Wrong state
if (!eyeobj || !holo)
usr << "<span class='warning'>You can only use this when holo-projecting!</span>"
return
//Holopads have this 'masters' list where the keys are AI names and the values are the hologram effects
var/obj/effect/overlay/aiholo/hologram = holo.masters[src]
//Something wrong on holopad
if(!hologram)
return
//Already full
if (hologram.bellied)
var/choice = alert("You can only contain one person. [hologram.bellied] is in you.","Already Full","Drop Mob","Cancel")
if(choice == "Drop Mob")
hologram.drop_prey()
return
var/mob/living/prey = input(src,"Select a mob to eat","Holonoms") as mob in oview(0,eyeobj)|null
if(!prey)
return //Probably cancelled
if(!istype(prey))
usr << "<span class='warning'>Invalid mob choice!</span>"
return
hologram.visible_message("[hologram] starts engulfing [prey] in hardlight holograms!")
src << "<span class='notice'>You begin engulfing [prey] in hardlight holograms.</span>" //Can't be part of the above, because the above is from the hologram.
if(do_after(user=eyeobj,delay=50,target=prey,needhand=0) && holo && hologram && !hologram.bellied) //Didn't move and still projecting and effect exists and no other bellied people
hologram.get_prey(prey)
/* Can't, lets them examine things in camera blackout areas
//I basically have to do this, you know?
/mob/living/silicon/ai/examinate(atom/A as mob|obj|turf in view(eyeobj))
set name = "Examine"
set category = "IC"
A.examine(src)
*/
/mob/living/AIShiftClick(var/mob/user) //Shift-click as AI overridden on mobs to examine.
if(user.client)
src.examine(user)
return

View File

@@ -27,17 +27,20 @@
set category = "Vore"
set src in oview(1)
var/mob/living/carbon/human/user = usr
if(!istype(user) || user.stat) return
var/datum/belly/B = vore_organs[vore_selected]
if(faction != usr.faction)
usr << "<span class='warning'>This predator isn't friendly, and doesn't give a shit about your opinions of it digesting you.</span>"
if(faction != user.faction)
user << "<span class='warning'>This predator isn't friendly, and doesn't give a shit about your opinions of it digesting you.</span>"
return
if(B.digest_mode == "Hold")
var/confirm = alert(usr, "Enabling digestion on [name] will cause it to digest all stomach contents. Using this to break OOC prefs is against the rules. Digestion will disable itself after 20 minutes.", "Enabling [name]'s Digestion", "Enable", "Cancel")
var/confirm = alert(user, "Enabling digestion on [name] will cause it to digest all stomach contents. Using this to break OOC prefs is against the rules. Digestion will disable itself after 20 minutes.", "Enabling [name]'s Digestion", "Enable", "Cancel")
if(confirm == "Enable")
B.digest_mode = "Digest"
spawn(12000) //12000=20 minutes
if(src) B.digest_mode = "Hold"
else
var/confirm = alert(usr, "This mob is currently set to digest all stomach contents. Do you want to disable this?", "Disabling [name]'s Digestion", "Disable", "Cancel")
var/confirm = alert(user, "This mob is currently set to digest all stomach contents. Do you want to disable this?", "Disabling [name]'s Digestion", "Disable", "Cancel")
if(confirm == "Disable")
B.digest_mode = "Hold"

View File

@@ -114,7 +114,7 @@
dat += "<span style='[spanstyle]'> ([B.internal_contents.len])</span></a></li>"
if(user.vore_organs.len < 10)
if(user.vore_organs.len < 20)
dat += "<li style='float: left'><a href='?src=\ref[src];newbelly=1'>New+</a></li>"
dat += "</ol>"
dat += "<HR>"
@@ -360,7 +360,7 @@
hearer << sound('sound/vore/squish2.ogg',volume=80)
if(href_list["newbelly"])
if(user.vore_organs.len >= 10)
if(user.vore_organs.len >= 20)
return 1
var/new_name = html_encode(input(usr,"New belly's name:","New Belly") as text|null)

View File

@@ -154,8 +154,8 @@
name = "Aronai's Kit"
desc = "A kit containing Aronai's equipment."
has_items = list(
/obj/item/weapon/storage/backpack/fluff/aronai,
/obj/item/weapon/rig/light/hacker/fluff/aronai,
///obj/item/weapon/storage/backpack/fluff/aronai,
///obj/item/weapon/rig/light/hacker/fluff/aronai,
/obj/item/clothing/under/rank/khi/fluff/aronai,
/obj/item/fluff/permit/aronai_kadigan,
/obj/item/weapon/gun/projectile/khi/pistol,

View File

@@ -643,7 +643,6 @@
new /obj/item/weapon/wirecutters(src)
new /obj/item/device/multitool(src)
new /obj/item/stack/cable_coil(src, 30, "red")
new /obj/item/stack/cable_coil(src, 30, "green")
// molenar:Giliana Gamish
/obj/item/clothing/suit/storage/toggle/labcoat/fluff/molenar
@@ -807,6 +806,12 @@
rolled_sleeves = 0
starting_accessories = list(/obj/item/clothing/accessory/black)
//Kisukegema:Kisuke `the nerd` Gema
/obj/item/clothing/glasses/sunglasses/omnihud/kamina
name = "Kamina glasses"
icon_state = "kamina"
desc = "ROW ROW, FIGHT THE POWER."
//Kitsuhana Uniforms
/obj/item/clothing/under/rank/khi
name = "Delete Me"

View File

@@ -39,7 +39,7 @@
icon = 'icons/obj/gun_vr.dmi'
icon_state = "battlerifle"
icon_override = 'icons/obj/gun_vr.dmi'
item_state = "battlerifle"
item_state = "battlerifle_i"
item_icons = null
w_class = ITEMSIZE_LARGE
recoil = 2 // The battlerifle was known for its nasty recoil.
@@ -64,7 +64,7 @@
icon_state = "haloshotgun"
icon_override = 'icons/obj/gun_vr.dmi'
item_state = "haloshotgun"
item_state = "haloshotgun_i"
item_icons = null
ammo_type = /obj/item/ammo_casing/shotgun

View File

@@ -327,33 +327,37 @@ obj/item/weapon/material/hatchet/tacknife/combatknife/fluff/katarina/handle_shie
//arokha:Aronai Kadigan - Vials to go with mk2 hypo
/obj/item/weapon/reagent_containers/glass/beaker/vial/vr
stabilize
name = "vial (1tr1in2tri2dxp)"
name = "vial (stabilize)"
desc = "10 Tricordrazine, 10 Dexalin Plus, 5 Tramadol, 5 Inaprovaline"
New()
..()
reagents.add_reagent("tramadol", 5)
reagents.add_reagent("inaprovaline", 5)
reagents.add_reagent("tricordrazine", 10)
reagents.add_reagent("dexalinp", 10)
reagents.add_reagent("tramadol", 5)
reagents.add_reagent("inaprovaline", 5)
bashed
name = "vial (5bi1tri)"
name = "vial (brute)"
desc = "25 Bicaridine, 5 Tricordrazine"
New()
..()
reagents.add_reagent("bicaridine", 25)
reagents.add_reagent("tricordrazine", 5)
toasted
name = "vial (3der2kel1tri)"
name = "vial (burn)"
desc = "10 Kelotane, 15 Dermaline, 5 Tricordrazine"
New()
..()
reagents.add_reagent("kelotane", 10)
reagents.add_reagent("dermaline", 15)
reagents.add_reagent("tricordrazine", 5)
poisoned
name = "vial (4dy1hy1tri)"
name = "vial (toxins)"
desc = "25 Dylovene, 2 Hyronalin, 3 Tricordrazine"
New()
..()
reagents.add_reagent("anti_toxin", 20)
reagents.add_reagent("hyronalin", 5)
reagents.add_reagent("tricordrazine", 5)
reagents.add_reagent("anti_toxin", 25)
reagents.add_reagent("hyronalin", 2)
reagents.add_reagent("tricordrazine", 3)
//Swat43:Fortune Bloise
/obj/item/weapon/storage/backpack/satchel/fluff/swat43bag
@@ -566,4 +570,17 @@ obj/item/weapon/material/hatchet/tacknife/combatknife/fluff/katarina/handle_shie
desc = "A custom-made MKII hypospray belonging to Chakat Tempest. There's small print engraved on the handle: A medicine-cat has no time for doubt. Act now, act swiftly."
icon = 'icons/vore/custom_items_vr.dmi'
item_state = "temphypo"
icon_state = "temphypo"
icon_state = "temphypo"
//WickedTempest: Chakat Tempest
/obj/item/weapon/storage/backpack/saddlebag/tempest
name = "Tempest's Saddlebags"
desc = "A custom-made set of saddlebags, tailored to Chakat Tempest's exact dimensions, and taste in color! One one side, there's small print stitched in: ...to carry the weight of any responsibility, burden or task."
icon = 'icons/vore/custom_items_vr.dmi'
icon_override = 'icons/vore/custom_items_vr.dmi'
item_state = "tempestsaddlebag"
icon_state = "tempestbag"
max_storage_space = INVENTORY_DUFFLEBAG_SPACE //Since they play a macro character, no reason to put custom slowdown code on here.
slowdown = 0
taurtype = /datum/sprite_accessory/tail/taur/feline/tempest
no_message = "These saddlebags seem to be fitted for someone else, and keep slipping off!"

View File

@@ -119,3 +119,14 @@
The individual named above is licensed by the Nanotrasen Department of Civil Protection to openly carry a MEUSOC 45. CONDITIONS.
This license expires on 31/May/2561 and must be renewed by CentCom prior to this date."}
// dhaeleena:Dhaeleena M'iar
/obj/item/fluff/permit/dhaeleena_miar
name = "Dhaeleena M'iar's Sidearm Permit"
desc = {"
<b>NAME:</b> Dhaeleena M'iar | <b>RACE:</b> Tajara | <b>HOMEWORLD:</b> Slyria
<b>DOB:</b> 15/Nov/2535 | <b>HEIGHT:</b> 210,3cm | <b>SEX:</b> Female
The individual named above is licensed by the Nanotrasen Department of Civil Protection
to carry one Mateba Model 6 Unica handgun with stun/rubber/flash ammo.
This license expires on 01/Mar/2562 and must be renewed by CentCom prior to this date."}