mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-11 18:53:06 +00:00
Merge branch 'master' of https://github.com/VOREStation/VOREStation into Fluff_Items_worshop
This commit is contained in:
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
12
code/modules/busy_space/_defines.dm
Normal file
12
code/modules/busy_space/_defines.dm
Normal 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
|
||||
128
code/modules/busy_space/air_traffic.dm
Normal file
128
code/modules/busy_space/air_traffic.dm
Normal 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
|
||||
14
code/modules/busy_space/loremaster.dm
Normal file
14
code/modules/busy_space/loremaster.dm
Normal 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
|
||||
360
code/modules/busy_space/orgs.dm
Normal file
360
code/modules/busy_space/orgs.dm
Normal 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()
|
||||
*/
|
||||
@@ -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>"
|
||||
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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"
|
||||
43
code/modules/client/preference_setup/vore/04_resleeving.dm
Normal file
43
code/modules/client/preference_setup/vore/04_resleeving.dm
Normal 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 ..();
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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")
|
||||
@@ -62,6 +62,3 @@
|
||||
flags = 0
|
||||
/datum/language/gutter
|
||||
flags = WHITELISTED
|
||||
/datum/language/machine
|
||||
flags = NO_STUTTER | WHITELISTED
|
||||
|
||||
|
||||
@@ -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>"
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
2
code/modules/mob/living/living_defines_vr.dm
Normal file
2
code/modules/mob/living/living_defines_vr.dm
Normal file
@@ -0,0 +1,2 @@
|
||||
/mob/living
|
||||
var/ooc_notes = null
|
||||
@@ -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)
|
||||
|
||||
9
code/modules/mob/living/silicon/robot/drone/drone_vr.dm
Normal file
9
code/modules/mob/living/silicon/robot/drone/drone_vr.dm
Normal 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)
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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 ..()
|
||||
@@ -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"
|
||||
|
||||
3
code/modules/resleeving/_defines.dm
Normal file
3
code/modules/resleeving/_defines.dm
Normal file
@@ -0,0 +1,3 @@
|
||||
#define MR_NORMAL 0
|
||||
#define MR_UNSURE 1
|
||||
#define MR_DEAD 2
|
||||
41
code/modules/resleeving/circuitboards.dm
Normal file
41
code/modules/resleeving/circuitboards.dm
Normal 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)
|
||||
376
code/modules/resleeving/computers.dm
Normal file
376
code/modules/resleeving/computers.dm
Normal 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()
|
||||
74
code/modules/resleeving/documents.dm
Normal file
74
code/modules/resleeving/documents.dm
Normal 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>
|
||||
"}
|
||||
79
code/modules/resleeving/implant.dm
Normal file
79
code/modules/resleeving/implant.dm
Normal 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."
|
||||
227
code/modules/resleeving/infocore.dm
Normal file
227
code/modules/resleeving/infocore.dm
Normal 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)
|
||||
529
code/modules/resleeving/machines.dm
Normal file
529
code/modules/resleeving/machines.dm
Normal 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
|
||||
46
code/modules/telesci/bscyrstal.dm
Normal file
46
code/modules/telesci/bscyrstal.dm
Normal 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!
|
||||
53
code/modules/telesci/construction.dm
Normal file
53
code/modules/telesci/construction.dm
Normal 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"
|
||||
78
code/modules/telesci/gps_advanced.dm
Normal file
78
code/modules/telesci/gps_advanced.dm
Normal 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"
|
||||
47
code/modules/telesci/telepad.dm
Normal file
47
code/modules/telesci/telepad.dm
Normal 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 ..()
|
||||
384
code/modules/telesci/telesci_computer.dm
Normal file
384
code/modules/telesci/telesci_computer.dm
Normal 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)
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
93
code/modules/vore/eating/silicon_vr.dm
Normal file
93
code/modules/vore/eating/silicon_vr.dm
Normal 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
|
||||
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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!"
|
||||
|
||||
@@ -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."}
|
||||
Reference in New Issue
Block a user