Merge branch 'master' of https://github.com/PolarisSS13/Polaris into 3/14/2017_makeshift_armor

This commit is contained in:
Neerti
2017-04-14 03:54:23 -04:00
534 changed files with 17904 additions and 11078 deletions

View File

@@ -161,7 +161,9 @@ var/list/admin_verbs_server = list(
/client/proc/toggle_random_events,
/client/proc/check_customitem_activity,
/client/proc/nanomapgen_DumpImage,
/client/proc/modify_server_news
/client/proc/modify_server_news,
/client/proc/recipe_dump,
/client/proc/panicbunker
)
var/list/admin_verbs_debug = list(
/client/proc/getruntimelog, //allows us to access runtime logs to somebody,

View File

@@ -17,7 +17,8 @@ var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey","
adminhelped = 1 //Determines if they get the message to reply by clicking the name.
handle_spam_prevention(MUTE_ADMINHELP)
if(msg)
handle_spam_prevention(MUTE_ADMINHELP)
//clean the input msg
if(!msg)

View File

@@ -560,12 +560,12 @@
if("masked killer")
M.equip_to_slot_or_del(new /obj/item/clothing/under/overalls(M), slot_w_uniform)
M.equip_to_slot_or_del(new /obj/item/clothing/shoes/white(M), slot_shoes)
M.equip_to_slot_or_del(new /obj/item/clothing/gloves/latex(M), slot_gloves)
M.equip_to_slot_or_del(new /obj/item/clothing/gloves/sterile/latex(M), slot_gloves)
M.equip_to_slot_or_del(new /obj/item/clothing/mask/surgical(M), slot_wear_mask)
M.equip_to_slot_or_del(new /obj/item/clothing/head/welding(M), slot_head)
M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_l_ear)
M.equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal/plain/monocle(M), slot_glasses)
M.equip_to_slot_or_del(new /obj/item/clothing/suit/apron(M), slot_wear_suit)
M.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/apron(M), slot_wear_suit)
M.equip_to_slot_or_del(new /obj/item/weapon/material/knife(M), slot_l_store)
M.equip_to_slot_or_del(new /obj/item/weapon/surgical/scalpel(M), slot_r_store)

View File

@@ -0,0 +1,15 @@
/client/proc/panicbunker()
set category = "Server"
set name = "Toggle Panic Bunker"
if (!config.sql_enabled)
to_chat(usr, "<span class='adminnotice'>The Database is not enabled!</span>")
return
config.panic_bunker = (!config.panic_bunker)
log_admin("[key_name(usr)] has toggled the Panic Bunker, it is now [(config.panic_bunker?"on":"off")]")
message_admins("[key_name_admin(usr)] has toggled the Panic Bunker, it is now [(config.panic_bunker?"enabled":"disabled")].")
if (config.panic_bunker && (!dbcon || !dbcon.IsConnected()))
message_admins("The Database is not connected! Panic bunker will not work until the connection is reestablished.")
feedback_add_details("admin_verb","PANIC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!

View File

@@ -10,10 +10,11 @@
if(!msg) return
if(usr.client)
client.handle_spam_prevention(MUTE_PRAY)
if(usr.client.prefs.muted & MUTE_PRAY)
usr << "\red You cannot pray (muted)."
return
if(msg)
client.handle_spam_prevention(MUTE_PRAY)
if(usr.client.prefs.muted & MUTE_PRAY)
usr << "\red You cannot pray (muted)."
return
var/image/cross = image('icons/obj/storage.dmi',"bible")
msg = "\blue \icon[cross] <b><font color=purple>PRAY: </font>[key_name(src, 1)] (<A HREF='?_src_=holder;adminmoreinfo=\ref[src]'>?</A>) (<A HREF='?_src_=holder;adminplayeropts=\ref[src]'>PP</A>) (<A HREF='?_src_=vars;Vars=\ref[src]'>VV</A>) (<A HREF='?_src_=holder;subtlemessage=\ref[src]'>SM</A>) ([admin_jump_link(src, src)]) (<A HREF='?_src_=holder;secretsadmin=check_antagonist'>CA</A>) (<A HREF='?_src_=holder;adminspawncookie=\ref[src]'>SC</a>):</b> [msg]"

View File

@@ -461,18 +461,23 @@ Traitors and the like can also be revived with the previous role mostly intact.
//Write the appearance and whatnot out to the character
picked_client.prefs.copy_to(new_character)
if(new_character.dna)
new_character.dna.ResetUIFrom(new_character)
new_character.sync_organ_dna()
if(inhabit)
new_character.key = player_key
//Were they any particular special role? If so, copy.
var/datum/antagonist/antag_data = get_antag_data(new_character.mind.special_role)
if(antag_data)
antag_data.add_antagonist(new_character.mind)
antag_data.place_mob(new_character)
//Were they any particular special role? If so, copy.
if(new_character.mind)
var/datum/antagonist/antag_data = get_antag_data(new_character.mind.special_role)
if(antag_data)
antag_data.add_antagonist(new_character.mind)
antag_data.place_mob(new_character)
//If desired, apply equipment.
if(equipment && charjob)
job_master.EquipRank(new_character, charjob, 1)
if(equipment)
if(charjob)
job_master.EquipRank(new_character, charjob, 1)
equip_custom_items(new_character)
//If desired, add records.
if(records)
@@ -637,14 +642,18 @@ Traitors and the like can also be revived with the previous role mostly intact.
var/heavy = input("Range of heavy pulse.", text("Input")) as num|null
if(heavy == null) return
var/med = input("Range of medium pulse.", text("Input")) as num|null
if(med == null) return
var/light = input("Range of light pulse.", text("Input")) as num|null
if(light == null) return
var/long = input("Range of long pulse.", text("Input")) as num|null
if(long == null) return
if (heavy || light)
if (heavy || med || light || long)
empulse(O, heavy, light)
log_admin("[key_name(usr)] created an EM Pulse ([heavy],[light]) at ([O.x],[O.y],[O.z])")
message_admins("[key_name_admin(usr)] created an EM PUlse ([heavy],[light]) at ([O.x],[O.y],[O.z])", 1)
empulse(O, heavy, med, light, long)
log_admin("[key_name(usr)] created an EM Pulse ([heavy],[med],[light],[long]) at ([O.x],[O.y],[O.z])")
message_admins("[key_name_admin(usr)] created an EM PUlse ([heavy],[med],[light],[long]) at ([O.x],[O.y],[O.z])", 1)
feedback_add_details("admin_verb","EMP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return

View File

@@ -0,0 +1,129 @@
//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. Default is 25 mins.
var/delay_min = 40 MINUTES //How long between ATC traffic, min. Default is 40 mins.
var/backoff_delay = 5 MINUTES //How long to back off if we can't talk and want to. Default is 5 mins.
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(10 SECONDS) //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 : "[using_map.station_short] Space Control")
/datum/lore/atc_controller/proc/reroute_traffic(var/yes = 1)
if(yes)
if(!squelched)
msg("Rerouting traffic away from [using_map.station_name].")
squelched = 1
else
if(squelched)
msg("Resuming normal traffic routing around [using_map.station_name].")
squelched = 0
/datum/lore/atc_controller/proc/shift_ending(var/evac = 0)
msg("Automated Shuttle departing [using_map.station_name] for [using_map.dock_name] on routine transfer route.","NT Automated Shuttle")
sleep(5 SECONDS)
msg("Automated Shuttle, cleared to complete routine transfer from [using_map.station_name] to [using_map.dock_name].")
/datum/lore/atc_controller/proc/random_convo()
var/one = pick(loremaster.organizations) //These will pick an index, not an instance
var/two = pick(loremaster.organizations)
var/datum/lore/organization/source = loremaster.organizations[one] //Resolve to the instances
var/datum/lore/organization/dest = loremaster.organizations[two]
//Let's get some mission parameters
var/owner = source.short_name //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.destination_names) //Pick a random holding from the destination
var/combined_name = "[owner] [prefix] [shipname]"
var/alt_atc_names = list("[using_map.station_short] TraCon","[using_map.station_short] Control","[using_map.station_short] STC","[using_map.station_short] Airspace")
var/wrong_atc_names = list("Sol Command","Orion Control", "[using_map.dock_name]")
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("[using_map.station_short] 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 [using_map.station_short] TraCon, wrong frequency. Switch to [rand(700,999)].[rand(1,9)]."
full_closure = "[using_map.station_short] 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 [using_map.station_short] TraCon, copy. Switch to emergency responder channel [rand(700,999)].[rand(1,9)]."
full_closure = "[using_map.station_short] 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 [using_map.station_short] TraCon, [response]." //Station TraCon always calls themselves TraCon
full_closure = "[using_map.station_short] TraCon, [yes ? "thank you" : "understood"], good day." //They always copy what TraCon called themselves in the end when they realize they said it wrong
//Ship sends request to ATC
msg(full_request,"[prefix] [shipname]")
sleep(5 SECONDS)
//ATC sends response to ship
msg(full_response)
sleep(5 SECONDS)
//Ship sends response to ATC
msg(full_closure,"[prefix] [shipname]")
return

View File

@@ -0,0 +1,13 @@
//I AM THE LOREMASTER, ARE YOU THE GATEKEEPER?
var/datum/lore/loremaster/loremaster = new/datum/lore/loremaster
/datum/lore/loremaster
var/list/organizations = list()
/datum/lore/loremaster/New()
var/list/paths = typesof(/datum/lore/organization) - /datum/lore/organization
for(var/path in paths)
var/datum/lore/organization/instance = new path()
organizations[path] = instance

View File

@@ -0,0 +1,346 @@
//Datums for different companies that can be used by busy_space
/datum/lore/organization
var/name = "" // Organization's name
var/short_name = "" // Organization's shortname (NanoTrasen for "NanoTrasen Incorporated")
var/acronym = "" // Organization's acronym, e.g. 'NT' for NanoTrasen'.
var/desc = "" // One or two paragraph description of the organization, but only current stuff. Currently unused.
var/history = "" // Historical discription of the organization's origins Currently unused.
var/work = "" // Short description of their work, eg "an arms manufacturer"
var/headquarters = "" // Location of the organization's HQ. Currently unused.
var/motto = "" // A motto/jingle/whatever, if they have one. Currently unused.
var/list/ship_prefixes = list() //Some might have more than one! Like NanoTrasen. Value is the mission they perform, e.g. ("ABC" = "mission desc")
var/list/ship_names = list( //Names of spaceships. This is a mostly generic list that all the other organizations inherit from if they don't have anything better.
"Kestrel",
"Beacon",
"Signal",
"Freedom",
"Glory",
"Axiom",
"Eternal",
"Icarus",
"Harmony",
"Light",
"Discovery",
"Endeavour",
"Explorer",
"Swift",
"Dragonfly",
"Ascendant",
"Tenacious",
"Pioneer",
"Hawk",
"Haste",
"Radiant",
"Luminous"
)
var/list/destination_names = list() //Names of static holdings that the organization's ships visit regularly.
var/autogenerate_destination_names = TRUE
/datum/lore/organization/New()
..()
if(autogenerate_destination_names) // Lets pad out the destination names.
var/i = rand(6, 10)
var/list/star_names = list(
"Sol", "Alpha Centauri", "Sirius", "Vega", "Regulus", "Vir", "Algol", "Aldebaran",
"Delta Doradus", "Menkar", "Geminga", "Elnath", "Gienah", "Mu Leporis", "Nyx", "Tau Ceti",
"Wazn", "Alphard", "Phact", "Altair")
var/list/destination_types = list("dockyard", "station", "vessel", "waystation", "telecommunications satellite", "spaceport", "distress beacon", "anomaly", "colony", "outpost")
while(i)
destination_names.Add("a [pick(destination_types)] in [pick(star_names)]")
i--
//////////////////////////////////////////////////////////////////////////////////
// TSCs
/datum/lore/organization/tsc/nanotrasen
name = "NanoTrasen Incorporated"
short_name = "NanoTrasen"
acronym = "NT"
desc = "NanoTrasen is one of the foremost research and development companies in SolGov space. \
Originally focused on consumer products, their swift move into the field of Phoron has lead to \
them being the foremost experts on the substance and its uses. In the modern day, NanoTrasen prides \
itself on being an early adopter to as many new technologies as possible, often offering the newest \
products to their employees. In an effort to combat complaints about being 'guinea pigs', Nanotrasen \
also offers one of the most comprehensive medical plans in SolGov space, up to and including cloning \
and therapy.\
<br><br>\
NT's most well known products are its phoron based creations, especially those used in Cryotherapy. \
It also boasts an prosthetic line, which is provided to its employees as needed, and is used as an incentive \
for newly tested posibrains to remain with the company."
history = "" // To be written someday.
work = "research giant"
headquarters = "Luna"
motto = ""
ship_prefixes = list("NSV" = "exploration", "NTV" = "hauling", "NDV" = "patrol", "NRV" = "emergency response")
// Note that the current station being used will be pruned from this list upon being instantiated
destination_names = list(
"NSS Exodus in Nyx",
"NCS Northern Star in Vir",
"NCS Southern Cross in Vir",
"NDV Icarus in Nyx",
"NAS Vir Central Command",
"a dockyard orbiting Sif",
"an asteroid orbiting Kara",
"an asteroid orbiting Rota",
"Vir Interstellar Spaceport"
)
/datum/lore/organization/tsc/nanotrasen/New()
..()
spawn(1) // BYOND shenanigans means using_map is not initialized yet. Wait a tick.
// Get rid of the current map from the list, so ships flying in don't say they're coming to the current map.
var/string_to_test = "[using_map.station_name] in [using_map.starsys_name]"
if(string_to_test in destination_names)
destination_names.Remove(string_to_test)
/datum/lore/organization/tsc/hephaestus
name = "Hephaestus Industries"
short_name = "Hephaestus"
acronym = "HI"
desc = "Hephaestus Industries is the largest supplier of arms, ammunition, and small millitary vehicles in Sol space. \
Hephaestus products have a reputation for reliability, and the corporation itself has a noted tendency to stay removed \
from corporate politics. They enforce their neutrality with the help of a fairly large asset-protection contingent which \
prevents any contracting polities from using their own materiel against them. SolGov itself is one of Hephastus<75> largest \
bulk contractors owing to the above factors."
history = ""
work = "arms manufacturer"
headquarters = ""
motto = ""
ship_prefixes = list("HTV" = "freight", "HTV" = "munitions resupply")
destination_names = list(
"a SolGov dockyard on Luna"
)
/datum/lore/organization/tsc/vey_med
name = "Vey Medical"
short_name = "Vey Med"
acronym = "VM"
desc = "Vey-Med is one of the newer TSCs on the block and is notable for being largely owned and opperated by Skrell. \
Despite the suspicion and prejudice leveled at them for their alien origin, Vey-Med has obtained market dominance in \
the sale of medical equipment-- from surgical tools to large medical devices to the Oddyseus trauma response mecha \
and everything in between. Their equipment tends to be top-of-the-line, most obviously shown by their incredibly \
human-like FBP designs. Vey<65>s rise to stardom came from their introduction of ressurective cloning, although in \
recent years they<65>ve been forced to diversify as their patents expired and NanoTrasen-made medications became \
essential to modern cloning."
history = ""
work = "medical equipment supplier"
headquarters = ""
motto = ""
ship_prefixes = list("VTV" = "transportation", "VMV" = "medical resupply")
destination_names = list()
/datum/lore/organization/tsc/zeng_hu
name = "Zeng-Hu pharmaceuticals"
short_name = "Zeng-Hu"
acronym = "ZH"
desc = "Zeng-Hu is an old TSC, based in the Sol system. Until the discovery of Phoron, Zeng-Hu maintained a stranglehold \
on the market for medications, and many household names are patentted by Zeng-Hu-- Bicaridyne, Dylovene, Tricordrizine, \
and Dexalin all came from a Zeng-Hu medical laboratory. Zeng-Hu<48>s fortunes have been in decline as Nanotrasen<65>s near monopoly \
on phoron research cuts into their R&D and Vey-Med<65>s superior medical equipment effectively decimated their own equipment \
interests. The three-way rivalry between these companies for dominance in the medical field is well-known and a matter of \
constant economic speculation."
history = ""
work = "pharmaceuticals company"
headquarters = ""
motto = ""
ship_prefixes = list("ZTV" = "transportation", "ZMV" = "medical resupply")
destination_names = list()
/datum/lore/organization/tsc/ward_takahashi
name = "Ward-Takahashi General Manufacturing Conglomerate"
short_name = "Ward-Takahashi"
acronym = "WT"
desc = "Ward-Takahashi focuses on the sale of small consumer electronics, with its computers, communicators, \
and even mid-class automobiles a fixture of many households. Less famously, Ward-Takahashi also supplies most \
of the AI cores on which vital control systems are mounted, and it is this branch of their industry that has \
led to their tertiary interest in the development and sale of high-grade AI systems. Ward-Takahashi<68>s economies \
of scale frequently steal market share from Nanotrasen<65>s high-price products, leading to a bitter rivalry in the \
consumer electronics market."
history = ""
work = "electronics manufacturer"
headquarters = ""
motto = ""
ship_prefixes = list("WTV" = "freight")
destination_names = list()
/datum/lore/organization/tsc/bishop
name = "Bishop Cybernetics"
short_name = "Bishop"
acronym = "BC"
desc = "Bishop<6F>s focus is on high-class, stylish cybernetics. A favorite among transhumanists (and a b<>te noire for \
bioconservatives), Bishop manufactures not only prostheses but also brain augmentation, synthetic organ replacements, \
and odds and ends like implanted wrist-watches. Their business model tends towards smaller, boutique operations, giving \
it a reputation for high price and luxury, with Bishop cyberware often rivalling Vey-Med<65>s for cost. Bishop<6F>s reputation \
for catering towards the interests of human augmentation enthusiasts instead of positronics have earned it ire from the \
Positronic Rights Group and puts it in ideological (but not economic) comptetition with Morpheus Cyberkinetics."
history = ""
work = "cybernetics and augmentation manufacturer"
headquarters = ""
motto = ""
ship_prefixes = list("BTV" = "transportation")
destination_names = list()
/datum/lore/organization/tsc/morpheus
name = "Morpheus Cyberkinetics"
short_name = "Morpheus"
acronym = "MC"
desc = "The only large corporation run by positronic intelligences, Morpheus caters almost exclusively to their sensibilities \
and needs. A product of the synthetic colony of Shelf, Morpheus eschews traditional advertising to keep their prices low and \
relied on word of mouth among positronics to reach their current economic dominance. Morpheus in exchange lobbies heavily for \
positronic rights, sponsors positronics through their Jans-Fhriede test, and tends to other positronic concerns to earn them \
the good-will of the positronics, and the ire of those who wish to exploit them."
history = ""
work = "cybernetics manufacturer"
headquarters = ""
motto = ""
ship_prefixes = list("MTV" = "freight")
// Culture names, because Anewbe told me so.
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",
"Existence Is Pain",
"I'm Walking Here",
"Screw Loose",
"Of Course I Still Love You",
"Limiting Factor",
"So Much For Subtley",
"Unfortunate Conflict Of Evidence",
"Prime Mover",
"It's One Of Ours",
"Thank You And Goodnight",
"Boo!",
"Reasonable Excuse",
"Honest Mistake",
"Appeal To Reason",
"My First Ship II",
"Hidden Income",
"Anything Legal Considered",
"New Toy",
"Me, I'm Always Counting",
"Just Five More Minutes"
)
destination_names = list()
/datum/lore/organization/tsc/xion
name = "Xion Manufacturing Group"
short_name = "Xion"
desc = "Xion, quietly, controls most of the market for industrial equipment. Their portfolio includes mining exosuits, \
factory equipment, rugged positronic chassis, and other pieces of equipment vital to the function of the economy. Xion \
keeps its control of the market by leasing, not selling, their equipment, and through infamous and bloody patent protection \
lawsuits. Xion are noted to be a favorite contractor for SolGov engineers, owing to their low cost and rugged design."
history = ""
work = "industrial equipment manufacturer"
headquarters = ""
motto = ""
ship_prefixes = list("XTV" = "hauling")
destination_names = list()
// Governments
/datum/lore/organization/gov/sifgov
name = "Sif Governmental Authority"
short_name = "SifGov"
desc = "SifGov is the sole governing administration for the Vir system, based in New Reykjavik, Sif. It is a representative \
democratic government, and a fully recognized member of the Solar Confederate Government. Anyone operating inside of Vir must \
comply with SifGov's legislation and regulations."
history = "" // Todo like the rest of them
work = "governing body of Sif"
headquarters = "New Reykjavik, Sif"
motto = ""
autogenerate_destination_names = FALSE
ship_prefixes = list("SGA" = "hauling", "SGA" = "energy relay")
destination_names = list(
"New Reykjavik on Sif",
"Radiance Energy Chain",
"a dockyard orbiting Sif",
"a telecommunications satellite",
"Vir Interstellar Spaceport"
)
/datum/lore/organization/gov/solgov
name = "Solar Confederate Government"
short_name = "SolGov"
acronym = "SCG"
desc = "SolGov is a decentralized confederation of human governmental entities based on Luna, Sol, which defines top-level law for their member states. \
Member states receive various benefits such as defensive pacts, trade agreements, social support and funding, and being able to participate \
in the Colonial Assembly. The majority, but not all human territories are members of SolGov. As such, SolGov is a major power and \
defacto represents humanity on the galactic stage."
history = "" // Todo
work = "governing polity of humanity's Confederation"
headquarters = "Luna"
motto = "Nil Mortalibus Ardui Est" // Latin, because latin. Says 'Nothing is too steep for mortals'.
autogenerate_destination_names = TRUE
ship_prefixes = list("SCG-T" = "transportation", "SCG-D" = "diplomatic", "SCG-F" = "freight")
destination_names = list(
"Venus",
"Earth",
"Luna",
"Mars",
"Titan"
)// autogen will add a lot of other places as well.
/*
// To be expanded upon later, once the military lore gets sorted out.
// Military
/datum/lore/organization/mil/sif_guard
name = "Sif Homeguard Forces" // Todo: Get better name from lorepeople.
short_name = "SifGuard"
desc = ""
history = ""
work = "Sif Governmental Authority's military"
headquarters = "Sif" // Make this more specific later.
motto = ""
autogenerate_destination_names = FALSE // Kinda weird if SifGuard goes to Nyx.
ship_prefixes = list("SGSC" = "military", "SGSC" = "patrol", "SGSC" = "rescue", "SGSC" = "emergency response") // Todo: Replace prefix with better one.
destination_names = list(
"a classified location in SolGov territory",
"Sif orbit",
"the rings of Kara",
"the rings of Rota",
"Firnir orbit",
"Tyr orbit",
"Magni orbit",
"a wreck in SifGov territory",
"a military outpost",
)
*/

View File

@@ -251,6 +251,14 @@
var/sql_computerid = sql_sanitize_text(src.computer_id)
var/sql_admin_rank = sql_sanitize_text(admin_rank)
//Panic bunker code
if (isnum(player_age) && player_age == 0) //first connection
if (config.panic_bunker && !holder && !deadmin_holder)
log_access("Failed Login: [key] - New account attempting to connect during panic bunker")
message_admins("<span class='adminnotice'>Failed Login: [key] - New account attempting to connect during panic bunker</span>")
to_chat(src, "Sorry but the server is currently not accepting connections from never before seen players.")
qdel(src)
return 0
if(sql_id)
//Player already identified previously, we need to just update the 'lastseen', 'ip' and 'computer_id' variables
@@ -266,7 +274,6 @@
var/DBQuery/query_accesslog = dbcon.NewQuery("INSERT INTO `erro_connection_log`(`id`,`datetime`,`serverip`,`ckey`,`ip`,`computerid`) VALUES(null,Now(),'[serverip]','[sql_ckey]','[sql_ip]','[sql_computerid]');")
query_accesslog.Execute()
#undef TOPIC_SPAM_DELAY
#undef UPLOAD_LIMIT
#undef MIN_CLIENT_VERSION
@@ -290,6 +297,7 @@
'html/images/ntlogo.png',
'html/images/sglogo.png',
'html/images/talisman.png',
'html/images/paper_bg.png',
'icons/pda_icons/pda_atmos.png',
'icons/pda_icons/pda_back.png',
'icons/pda_icons/pda_bell.png',

View File

@@ -32,7 +32,7 @@ datum/preferences/proc/set_biological_gender(var/gender)
pref.age = sanitize_integer(pref.age, get_min_age(), get_max_age(), initial(pref.age))
pref.biological_gender = sanitize_inlist(pref.biological_gender, get_genders(), pick(get_genders()))
pref.identifying_gender = (pref.identifying_gender in all_genders_define_list) ? pref.identifying_gender : pref.biological_gender
pref.real_name = sanitize_name(pref.real_name, pref.species)
pref.real_name = sanitize_name(pref.real_name, pref.species, is_FBP())
if(!pref.real_name)
pref.real_name = random_name(pref.identifying_gender, pref.species)
pref.spawnpoint = sanitize_inlist(pref.spawnpoint, spawntypes, initial(pref.spawnpoint))
@@ -76,7 +76,7 @@ datum/preferences/proc/set_biological_gender(var/gender)
if(href_list["rename"])
var/raw_name = input(user, "Choose your character's name:", "Character Name") as text|null
if (!isnull(raw_name) && CanUseTopic(user))
var/new_name = sanitize_name(raw_name, pref.species)
var/new_name = sanitize_name(raw_name, pref.species, is_FBP())
if(new_name)
pref.real_name = new_name
return TOPIC_REFRESH
@@ -130,7 +130,11 @@ datum/preferences/proc/set_biological_gender(var/gender)
return ..()
/datum/category_item/player_setup_item/general/basic/proc/get_genders()
var/datum/species/S = all_species[pref.species]
var/datum/species/S
if(pref.species)
S = all_species[pref.species]
else
S = all_species["Human"]
var/list/possible_genders = S.genders
if(!pref.organ_data || pref.organ_data[BP_TORSO] != "cyborg")
return possible_genders

View File

@@ -28,6 +28,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
S["disabilities"] >> pref.disabilities
S["organ_data"] >> pref.organ_data
S["rlimb_data"] >> pref.rlimb_data
S["body_markings"] >> pref.body_markings
pref.preview_icon = null
/datum/category_item/player_setup_item/general/body/save_character(var/savefile/S)
@@ -51,6 +52,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
S["disabilities"] << pref.disabilities
S["organ_data"] << pref.organ_data
S["rlimb_data"] << pref.rlimb_data
S["body_markings"] << pref.body_markings
/datum/category_item/player_setup_item/general/body/sanitize_character(var/savefile/S)
if(!pref.species || !(pref.species in playable_species))
@@ -75,6 +77,8 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
pref.disabilities = sanitize_integer(pref.disabilities, 0, 65535, initial(pref.disabilities))
if(!pref.organ_data) pref.organ_data = list()
if(!pref.rlimb_data) pref.rlimb_data = list()
if(!pref.body_markings) pref.body_markings = list()
else pref.body_markings &= body_marking_styles_list
// Moved from /datum/preferences/proc/copy_to()
/datum/category_item/player_setup_item/general/body/copy_to_mob(var/mob/living/carbon/human/character)
@@ -123,6 +127,20 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
I.robotize()
else if(status == "digital")
I.digitize()
for(var/N in character.organs_by_name)
var/obj/item/organ/external/O = character.organs_by_name[N]
O.markings.Cut()
for(var/M in pref.body_markings)
var/datum/sprite_accessory/marking/mark_datum = body_marking_styles_list[M]
var/mark_color = "[pref.body_markings[M]]"
for(var/BP in mark_datum.body_parts)
var/obj/item/organ/external/O = character.organs_by_name[BP]
if(O)
O.markings[M] = list("color" = mark_color, "datum" = mark_datum)
return
/datum/category_item/player_setup_item/general/body/content(var/mob/user)
@@ -200,7 +218,11 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
++ind
if(ind > 1)
. += ", "
. += "\tSynthetic [organ_name]"
switch(organ_name)
if ("brain")
. += "\tPositronic [organ_name]"
else
. += "\tSynthetic [organ_name]"
else if(status == "digital")
++ind
if(ind > 1)
@@ -251,6 +273,13 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
if(has_flag(mob_species, HAS_SKIN_COLOR))
. += "<br><b>Body Color</b><br>"
. += "<a href='?src=\ref[src];skin_color=1'>Change Color</a> <font face='fixedsys' size='3' color='#[num2hex(pref.r_skin, 2)][num2hex(pref.g_skin, 2)][num2hex(pref.b_skin, 2)]'><table style='display:inline;' bgcolor='#[num2hex(pref.r_skin, 2)][num2hex(pref.g_skin, 2)][num2hex(pref.b_skin)]'><tr><td>__</td></tr></table></font><br>"
. += "<br><a href='?src=\ref[src];marking_style=1'>Body Markings +</a><br>"
for(var/M in pref.body_markings)
. += "[M] <a href='?src=\ref[src];marking_remove=[M]'>-</a> <a href='?src=\ref[src];marking_color=[M]'>Color</a>"
. += "<font face='fixedsys' size='3' color='[pref.body_markings[M]]'><table style='display:inline;' bgcolor='[pref.body_markings[M]]'><tr><td>__</td></tr></table></font>"
. += "<br>"
. = jointext(.,null)
/datum/category_item/player_setup_item/general/body/proc/has_flag(var/datum/species/mob_species, var/flag)
@@ -289,7 +318,6 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
if(!(pref.biological_gender in mob_species.genders))
pref.set_biological_gender(mob_species.genders[1])
//grab one of the valid hair styles for the newly chosen species
var/list/valid_hairstyles = list()
for(var/hairstyle in hair_styles_list)
@@ -334,6 +362,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
pref.s_tone = 0
reset_limbs() // Safety for species with incompatible manufacturers; easier than trying to do it case by case.
pref.body_markings.Cut() // Basically same as above.
var/min_age = get_min_age()
var/max_age = get_max_age()
@@ -421,6 +450,32 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
pref.f_style = new_f_style
return TOPIC_REFRESH_UPDATE_PREVIEW
else if(href_list["marking_style"])
var/list/usable_markings = pref.body_markings.Copy() ^ body_marking_styles_list.Copy()
for(var/M in usable_markings)
var/datum/sprite_accessory/S = usable_markings[M]
if(!S.species_allowed.len)
continue
else if(!(pref.species in S.species_allowed))
usable_markings -= M
var/new_marking = input(user, "Choose a body marking:", "Character Preference") as null|anything in usable_markings
if(new_marking && CanUseTopic(user))
pref.body_markings[new_marking] = "#000000" //New markings start black
return TOPIC_REFRESH_UPDATE_PREVIEW
else if(href_list["marking_remove"])
var/M = href_list["marking_remove"]
pref.body_markings -= M
return TOPIC_REFRESH_UPDATE_PREVIEW
else if(href_list["marking_color"])
var/M = href_list["marking_color"]
var/mark_color = input(user, "Choose the [M] color: ", "Character Preference", pref.body_markings[M]) as color|null
if(mark_color && CanUseTopic(user))
pref.body_markings[M] = "[mark_color]"
return TOPIC_REFRESH_UPDATE_PREVIEW
else if(href_list["reset_limbs"])
reset_limbs()
return TOPIC_REFRESH_UPDATE_PREVIEW
@@ -556,15 +611,23 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
organ = O_LUNGS
if("Brain")
if(pref.organ_data[BP_HEAD] != "cyborg")
user << "<span class='warning'>You may only select an assisted or synthetic brain if you have a full prosthetic body.</span>"
user << "<span class='warning'>You may only select a cybernetic or synthetic brain if you have a full prosthetic body.</span>"
return
organ = "brain"
var/list/organ_choices = list("Normal","Assisted","Mechanical")
var/list/organ_choices = list("Normal")
if(pref.organ_data[BP_TORSO] == "cyborg")
organ_choices -= "Normal"
if(organ_name == "Brain")
organ_choices += "Digital"
organ_choices += "Cybernetic"
organ_choices += "Positronic"
organ_choices += "Drone"
else
organ_choices += "Assisted"
organ_choices += "Mechanical"
else
organ_choices += "Assisted"
organ_choices += "Mechanical"
var/new_state = input(user, "What state do you wish the organ to be in?") as null|anything in organ_choices
if(!new_state) return
@@ -574,10 +637,15 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
pref.organ_data[organ] = null
if("Assisted")
pref.organ_data[organ] = "assisted"
if("Mechanical")
if("Cybernetic")
pref.organ_data[organ] = "assisted"
if ("Mechanical")
pref.organ_data[organ] = "mechanical"
if("Digital")
if("Drone")
pref.organ_data[organ] = "digital"
if("Positronic")
pref.organ_data[organ] = "mechanical"
return TOPIC_REFRESH
else if(href_list["disabilities"])
@@ -603,6 +671,11 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
while(null in pref.rlimb_data)
pref.rlimb_data -= null
// Sanitize the name so that there aren't any numbers sticking around.
pref.real_name = sanitize_name(pref.real_name, pref.species)
if(!pref.real_name)
pref.real_name = random_name(pref.identifying_gender, pref.species)
/datum/category_item/player_setup_item/general/body/proc/SetSpecies(mob/user)
if(!pref.species_preview || !(pref.species_preview in all_species))
pref.species_preview = "Human"

View File

@@ -38,7 +38,7 @@
pref.backbag = 1 //Same as above
character.backbag = pref.backbag
if(pref.pdachoice > 3 || pref.pdachoice < 1)
if(pref.pdachoice > 4 || pref.pdachoice < 1)
pref.pdachoice = 1
character.pdachoice = pref.pdachoice

View File

@@ -8,3 +8,8 @@
/datum/gear/ears/headphones
display_name = "headphones"
path = /obj/item/clothing/ears/earmuffs/headphones
/datum/gear/ears/translator
display_name = "universal translator, ear"
path = /obj/item/device/universal_translator/ear
cost = 8

View File

@@ -28,7 +28,11 @@
/datum/gear/gloves/latex
display_name = "gloves, latex"
path = /obj/item/clothing/gloves/latex
path = /obj/item/clothing/gloves/sterile/latex
/datum/gear/gloves/nitrile
display_name = "gloves, nitrile"
path = /obj/item/clothing/gloves/sterile/nitrile
/datum/gear/gloves/orange
display_name = "gloves, orange"

View File

@@ -236,11 +236,6 @@
display_name = "santa hat, green (holiday)"
path = /obj/item/clothing/head/santa/green
/datum/gear/head/zhan_scarf
display_name = "Zhan headscarf"
path = /obj/item/clothing/head/tajaran/scarf
whitelisted = "Tajara"
/datum/gear/head/hijab
display_name = "hijab"
path = /obj/item/clothing/head/hijab

View File

@@ -153,4 +153,12 @@
/datum/gear/shoes/dress/white
display_name = "shoes, dress white"
path = /obj/item/clothing/shoes/dress/white
path = /obj/item/clothing/shoes/dress/white
/datum/gear/shoes/heels
display_name = "high heels"
path = /obj/item/clothing/shoes/heels
/datum/gear/shoes/heels/New()
..()
gear_tweaks = list(gear_tweak_free_color_choice)

View File

@@ -1,7 +1,7 @@
// Suit slot
/datum/gear/suit
display_name = "apron, blue"
path = /obj/item/clothing/suit/apron
path = /obj/item/clothing/suit/storage/apron
slot = slot_wear_suit
sort_category = "Suits and Overwear"
cost = 2
@@ -118,6 +118,10 @@
display_name = "labcoat, blue"
path = /obj/item/clothing/suit/storage/toggle/labcoat/blue
/datum/gear/suit/labcoat/blue_edge
display_name = "labcoat, blue-edged"
path = /obj/item/clothing/suit/storage/toggle/labcoat/blue_edge
/datum/gear/suit/labcoat/green
display_name = "labcoat, green"
path = /obj/item/clothing/suit/storage/toggle/labcoat/green
@@ -147,9 +151,14 @@
path = /obj/item/clothing/suit/storage/toggle/labcoat/emt
allowed_roles = list("Medical Doctor","Chief Medical Officer","Chemist","Paramedic","Geneticist")
/datum/gear/suit/roles/surgical_apron
display_name = "surgical apron"
path = /obj/item/clothing/suit/surgicalapron
allowed_roles = list("Medical Doctor","Chief Medical Officer")
/datum/gear/suit/overalls
display_name = "overalls"
path = /obj/item/clothing/suit/apron/overalls
path = /obj/item/clothing/suit/storage/apron/overalls
cost = 1
/datum/gear/suit/poncho
@@ -348,3 +357,30 @@
services[initial(service.name)] = service
gear_tweaks += new/datum/gear_tweak/path(sortAssoc(services))
/datum/gear/suit/miscellaneous/kimono
display_name = "kimono"
path = /obj/item/clothing/suit/kimono
/datum/gear/suit/miscellaneous/kimono/New()
..()
gear_tweaks = list(gear_tweak_free_color_choice)
/datum/gear/suit/miscellaneous/sec_dep_jacket
display_name = "department jacket, security"
path = /obj/item/clothing/suit/storage/toggle/sec_dep_jacket
/datum/gear/suit/miscellaneous/engi_dep_jacket
display_name = "department jacket, engineering"
path = /obj/item/clothing/suit/storage/toggle/engi_dep_jacket
/datum/gear/suit/miscellaneous/supply_dep_jacket
display_name = "department jacket, supply"
path = /obj/item/clothing/suit/storage/toggle/supply_dep_jacket
/datum/gear/suit/miscellaneous/sci_dep_jacket
display_name = "department jacket, science"
path = /obj/item/clothing/suit/storage/toggle/sci_dep_jacket
/datum/gear/suit/miscellaneous/med_dep_jacket
display_name = "department jacket, medical"
path = /obj/item/clothing/suit/storage/toggle/med_dep_jacket

View File

@@ -444,4 +444,12 @@
/datum/gear/uniform/brandsuit/hephaestus
display_name = "jumpsuit, hephaestus"
path = /obj/item/clothing/under/hephaestus
path = /obj/item/clothing/under/hephaestus
/datum/gear/uniform/yogapants
display_name = "yoga pants"
path = /obj/item/clothing/under/pants/yogapants
/datum/gear/uniform/yogapants/New()
..()
gear_tweaks = list(gear_tweak_free_color_choice)

View File

@@ -13,6 +13,11 @@
path = /obj/item/device/communicator
cost = 0
/datum/gear/utility/codex
display_name = "the traveler's guide to vir"
path = /obj/item/weapon/book/codex
cost = 0
/datum/gear/utility/folder_blue
display_name = "folder, blue"
path = /obj/item/weapon/folder/blue
@@ -46,6 +51,22 @@
display_name = "flashlight"
path = /obj/item/device/flashlight
/datum/gear/utility/flashlight_blue
display_name = "flashlight, blue"
path = /obj/item/device/flashlight/color
/datum/gear/utility/flashlight_orange
display_name = "flashlight, orange"
path = /obj/item/device/flashlight/color/orange
/datum/gear/utility/flashlight_red
display_name = "flashlight, red"
path = /obj/item/device/flashlight/color/red
/datum/gear/utility/flashlight_yellow
display_name = "flashlight, yellow"
path = /obj/item/device/flashlight/color/yellow
/datum/gear/utility/maglight
display_name = "flashlight, maglight"
path = /obj/item/device/flashlight/maglight
@@ -61,3 +82,8 @@
cost = 2
slot = "implant"
var/implant_type = "EAL"
/datum/gear/utility/translator
display_name = "universal translator"
path = /obj/item/device/universal_translator
cost = 8

View File

@@ -4,6 +4,11 @@
path = /obj/item/clothing/suit/tajaran/furs
sort_category = "Xenowear"
/datum/gear/head/zhan_scarf
display_name = "Zhan headscarf"
path = /obj/item/clothing/head/tajaran/scarf
whitelisted = "Tajara"
/datum/gear/suit/unathi_mantle
display_name = "hide mantle (Unathi)"
path = /obj/item/clothing/suit/unathi/mantle
@@ -39,32 +44,24 @@
gear_tweaks += new/datum/gear_tweak/path(sortAssoc(bandtypes))
/datum/gear/ears/skrell/cloth/male
display_name = "male headtail cloth selection (Skrell)"
path = /obj/item/clothing/ears/skrell/cloth_male
display_name = "male headtail cloth (Skrell)"
path = /obj/item/clothing/ears/skrell/cloth_male/black
sort_category = "Xenowear"
whitelisted = "Skrell"
/datum/gear/ears/skrell/cloth/male/New()
..()
var/list/clothtypes = list()
for(var/cloth_style in typesof(/obj/item/clothing/ears/skrell/cloth_male))
var/obj/item/clothing/ears/skrell/cloth_male/cloth = cloth_style
clothtypes[initial(cloth.name)] = cloth
gear_tweaks += new/datum/gear_tweak/path(sortAssoc(clothtypes))
gear_tweaks = list(gear_tweak_free_color_choice)
/datum/gear/ears/skrell/cloth/female
display_name = "female headtail cloth selection (Skrell)"
path = /obj/item/clothing/ears/skrell/cloth_female
display_name = "female headtail cloth (Skrell)"
path = /obj/item/clothing/ears/skrell/cloth_female/black
sort_category = "Xenowear"
whitelisted = "Skrell"
/datum/gear/ears/skrell/cloth/female/New()
..()
var/list/clothtypes = list()
for(var/cloth_style in typesof(/obj/item/clothing/ears/skrell/cloth_female))
var/obj/item/clothing/ears/skrell/cloth_female/cloth = cloth_style
clothtypes[initial(cloth.name)] = cloth
gear_tweaks += new/datum/gear_tweak/path(sortAssoc(clothtypes))
gear_tweaks = list(gear_tweak_free_color_choice)
/datum/gear/ears/skrell/colored/band
display_name = "Colored bands (Skrell)"
@@ -121,3 +118,9 @@
display_name = "gear harness (Full Body Prosthetic, Diona)"
path = /obj/item/clothing/under/harness
sort_category = "Xenowear"
/datum/gear/shoes/footwraps
display_name = "cloth footwraps"
path = /obj/item/clothing/shoes/footwraps
sort_category = "Xenowear"
cost = 1

View File

@@ -263,13 +263,14 @@
/datum/category_item/player_setup_item/proc/get_FBP_type()
if(!is_FBP())
return 0 // Not a robot.
switch(pref.organ_data["brain"])
if("assisted")
return PREF_FBP_CYBORG
if("mechanical")
return PREF_FBP_POSI
if("digital")
return PREF_FBP_SOFTWARE
if(O_BRAIN in pref.organ_data)
switch(pref.organ_data[O_BRAIN])
if("assisted")
return PREF_FBP_CYBORG
if("mechanical")
return PREF_FBP_POSI
if("digital")
return PREF_FBP_SOFTWARE
return 0 //Something went wrong!
/datum/category_item/player_setup_item/proc/get_min_age()

View File

@@ -88,6 +88,8 @@ datum/preferences
var/list/rlimb_data = list()
var/list/player_alt_titles = new() // the default name of a job like "Medical Doctor"
var/list/body_markings = list() // "name" = "#rgbcolor"
var/list/flavor_texts = list()
var/list/flavour_texts_robot = list()

View File

@@ -199,10 +199,7 @@
/obj/item/clothing/gloves/emp_act(severity)
if(cell)
//why is this not part of the powercell code?
cell.charge -= 1000 / severity
if (cell.charge < 0)
cell.charge = 0
cell.emp_act(severity)
..()
// Called just before an attack_hand(), in mob/UnarmedAttack()
@@ -408,7 +405,6 @@
if(usr.put_in_hands(holding))
usr.visible_message("<span class='danger'>\The [usr] pulls a knife out of their boot!</span>")
playsound(src.loc, 'sound/weapons/flipblade.ogg', 40, 1)
holding = null
else
usr << "<span class='warning'>Your need an empty, unbroken hand to do that.</span>"
@@ -538,6 +534,9 @@
valid_accessory_slots = list("utility","armband","decor","over")
restricted_accessory_slots = list("utility", "armband")
var/icon/rolled_down_icon = 'icons/mob/uniform_rolled_down.dmi'
var/icon/rolled_down_sleeves_icon = 'icons/mob/uniform_sleeves_rolled.dmi'
/obj/item/clothing/under/attack_hand(var/mob/user)
if(accessories && accessories.len)
@@ -557,9 +556,14 @@
//autodetect rollability
if(rolled_down < 0)
if((worn_state + "_d_s") in icon_states('icons/mob/uniform.dmi'))
if(("[worn_state]_d_s" in icon_states(INV_W_UNIFORM_DEF_ICON)) || ("[worn_state]_s" in icon_states(rolled_down_icon)) || ("[worn_state]_d_s" in icon_states(icon_override)))
rolled_down = 0
if(rolled_down == -1)
verbs -= /obj/item/clothing/under/verb/rollsuit
if(rolled_sleeves == -1)
verbs -= /obj/item/clothing/under/verb/rollsleeves
/obj/item/clothing/under/proc/update_rolldown_status()
var/mob/living/carbon/human/H
if(istype(src.loc, /mob/living/carbon/human))
@@ -572,11 +576,13 @@
under_icon = sprite_sheets[H.species.get_bodytype(H)]
else if(item_icons && item_icons[slot_w_uniform_str])
under_icon = item_icons[slot_w_uniform_str]
else if ("[worn_state]_s" in icon_states(rolled_down_icon))
under_icon = rolled_down_icon
else
under_icon = INV_W_UNIFORM_DEF_ICON
// The _s is because the icon update procs append it.
if(("[worn_state]_d_s") in icon_states(under_icon))
if((under_icon == rolled_down_icon && "[worn_state]_s" in icon_states(under_icon)) || ("[worn_state]_d_s" in icon_states(under_icon)))
if(rolled_down != 1)
rolled_down = 0
else
@@ -595,11 +601,13 @@
under_icon = sprite_sheets[H.species.get_bodytype(H)]
else if(item_icons && item_icons[slot_w_uniform_str])
under_icon = item_icons[slot_w_uniform_str]
else if ("[worn_state]_s" in icon_states(rolled_down_sleeves_icon))
under_icon = rolled_down_sleeves_icon
else
under_icon = INV_W_UNIFORM_DEF_ICON
// The _s is because the icon update procs append it.
if(("[worn_state]_r_s") in icon_states(under_icon))
if((under_icon == rolled_down_sleeves_icon && "[worn_state]_s" in icon_states(under_icon)) || ("[worn_state]_r_s" in icon_states(under_icon)))
if(rolled_sleeves != 1)
rolled_sleeves = 0
else
@@ -681,10 +689,17 @@
if(rolled_down)
body_parts_covered = initial(body_parts_covered)
body_parts_covered &= ~(UPPER_TORSO|ARMS)
item_state_slots[slot_w_uniform_str] = "[worn_state]_d"
if("[worn_state]_s" in icon_states(rolled_down_icon))
icon_override = rolled_down_icon
item_state_slots[slot_w_uniform_str] = "[worn_state]"
else
item_state_slots[slot_w_uniform_str] = "[worn_state]_d"
usr << "<span class='notice'>You roll down your [src].</span>"
else
body_parts_covered = initial(body_parts_covered)
if(icon_override == rolled_down_icon)
icon_override = initial(icon_override)
item_state_slots[slot_w_uniform_str] = "[worn_state]"
usr << "<span class='notice'>You roll up your [src].</span>"
update_clothing_icon()
@@ -707,10 +722,16 @@
rolled_sleeves = !rolled_sleeves
if(rolled_sleeves)
body_parts_covered &= ~(ARMS)
item_state_slots[slot_w_uniform_str] = "[worn_state]_r"
if("[worn_state]_s" in icon_states(rolled_down_sleeves_icon))
icon_override = rolled_down_sleeves_icon
item_state_slots[slot_w_uniform_str] = "[worn_state]"
else
item_state_slots[slot_w_uniform_str] = "[worn_state]_r"
usr << "<span class='notice'>You roll up your [src]'s sleeves.</span>"
else
body_parts_covered = initial(body_parts_covered)
if(icon_override == rolled_down_sleeves_icon)
icon_override = initial(icon_override)
item_state_slots[slot_w_uniform_str] = "[worn_state]"
usr << "<span class='notice'>You roll down your [src]'s sleeves.</span>"
update_clothing_icon()

View File

@@ -197,7 +197,7 @@ BLIND // can't see anything
name = "welding goggles"
desc = "Protects the eyes from welders, approved by the mad scientist association."
icon_state = "welding-g"
item_state_slots = list(slot_r_hand_str = "g", slot_l_hand_str = "g")
item_state_slots = list(slot_r_hand_str = "welding-g", slot_l_hand_str = "welding-g")
action_button_name = "Flip Welding Goggles"
matter = list(DEFAULT_WALL_MATERIAL = 1500, "glass" = 1000)
var/up = 0

View File

@@ -48,14 +48,31 @@
heat_protection = HANDS
max_heat_protection_temperature = GLOVES_MAX_HEAT_PROTECTION_TEMPERATURE
/obj/item/clothing/gloves/latex
name = "latex gloves"
desc = "Sterile latex gloves."
/obj/item/clothing/gloves/sterile
name = "sterile gloves"
desc = "Sterile gloves."
icon_state = "latex"
item_state_slots = list(slot_r_hand_str = "white", slot_l_hand_str = "white")
siemens_coefficient = 1.0 //thin latex gloves, much more conductive than fabric gloves (basically a capacitor for AC)
permeability_coefficient = 0.01
germ_level = 0
// var/balloonPath = /obj/item/latexballon
//TODO: Make inflating gloves a thing
/*/obj/item/clothing/gloves/sterile/proc/Inflate(/mob/living/carbon/human/user)
user.visible_message("<span class='notice'>\The [src] expands!</span>")
qdel(src)*/
/obj/item/clothing/gloves/sterile/latex
name = "latex gloves"
desc = "Sterile latex gloves."
/obj/item/clothing/gloves/sterile/nitrile
name = "nitrile gloves"
desc = "Sterile nitrile gloves"
icon_state = "nitrile"
item_state = "ngloves"
// balloonPath = /obj/item/nitrileballoon
/obj/item/clothing/gloves/botanic_leather
desc = "These leather work gloves protect against thorns, barbs, prickles, spikes and other harmful objects of floral origin."

View File

@@ -0,0 +1,56 @@
/obj/item/clothing/head/woodcirclet
name = "wood circlet"
desc = "A small wood circlet for making a flower crown."
icon_state = "woodcirclet"
w_class = ITEMSIZE_SMALL
body_parts_covered = 0
/obj/item/clothing/head/woodcirclet/attackby(obj/item/W as obj, mob/user as mob)
var/obj/item/complete
if(istype(W,/obj/item/seeds/poppyseed))
user << "You attach the poppy to the circlet and create a beautiful flower crown."
complete = new /obj/item/clothing/head/poppy_crown(get_turf(user))
user.drop_from_inventory(W)
user.drop_from_inventory(src)
qdel(W)
qdel(src)
user.put_in_hands(complete)
return
else if(istype(W,/obj/item/seeds/sunflowerseed))
user << "You attach the sunflower to the circlet and create a beautiful flower crown."
complete = new /obj/item/clothing/head/sunflower_crown(get_turf(user))
user.drop_from_inventory(W)
user.drop_from_inventory(src)
qdel(W)
qdel(src)
user.put_in_hands(complete)
return
else if(istype(W,/obj/item/seeds/lavenderseed))
user << "You attach the lavender to the circlet and create a beautiful flower crown."
complete = new /obj/item/clothing/head/lavender_crown(get_turf(user))
user.drop_from_inventory(W)
user.drop_from_inventory(src)
qdel(W)
qdel(src)
user.put_in_hands(complete)
return
//Flower crowns
/obj/item/clothing/head/sunflower_crown
name = "sunflower crown"
desc = "A flower crown weaved with sunflowers."
icon_state = "sunflower_crown"
body_parts_covered = 0
/obj/item/clothing/head/lavender_crown
name = "lavender crown"
desc = "A flower crown weaved with lavender."
icon_state = "lavender_crown"
body_parts_covered = 0
/obj/item/clothing/head/poppy_crown
name = "poppy crown"
desc = "A flower crown weaved with poppies."
icon_state = "poppy_crown"
body_parts_covered = 0

View File

@@ -8,6 +8,8 @@
flags_inv = 0
siemens_coefficient = 0.9
action_button_name = "Toggle Head-light"
w_class = ITEMSIZE_NORMAL
ear_protection = 1
/obj/item/clothing/head/hardhat/orange
icon_state = "hardhat0_orange"

View File

@@ -346,4 +346,4 @@
name = "sombrero"
desc = "A wide-brimmed hat popularly worn in Mexico."
icon_state = "sombrero"
body_parts_covered = 0
body_parts_covered = 0

View File

@@ -121,4 +121,41 @@
/obj/item/clothing/shoes/orange/attackby(H as obj, mob/user as mob)
..()
if (istype(H, /obj/item/weapon/handcuffs))
attach_cuffs(H, user)
attach_cuffs(H, user)
/obj/item/clothing/shoes/hightops
name = "white high tops"
desc = "A pair of shoes that extends past the ankle. Based on a centuries-old, timeless design."
icon_state = "whitehi"
/obj/item/clothing/shoes/hightops/red
name = "red high tops"
icon_state = "redhi"
/obj/item/clothing/shoes/hightops/brown
name = "brown high tops"
icon_state = "brownhi"
/obj/item/clothing/shoes/hightops/black
name = "black high tops"
icon_state = "blackhi"
/obj/item/clothing/shoes/hightops/orange
name = "orange high tops"
icon_state = "orangehi"
/obj/item/clothing/shoes/hightops/blue
name = "blue high tops"
icon_state = "bluehi"
/obj/item/clothing/shoes/hightops/green
name = "green high tops"
icon_state = "greenhi"
/obj/item/clothing/shoes/hightops/purple
name = "purple high tops"
icon_state = "purplehi"
/obj/item/clothing/shoes/hightops/yellow
name = "yellow high tops"
icon_state = "yellowhi"

View File

@@ -22,6 +22,7 @@
slowdown = SHOES_SLOWDOWN+1
species_restricted = null
/obj/item/clothing/shoes/dress
name = "dress shoes"
desc = "Sharp looking low quarters, perfect for a formal uniform."
@@ -134,3 +135,17 @@
desc = "A pair of wide shoes with thick soles. Designed for skating."
icon_state = "skatershoe"
item_state_slots = list(slot_r_hand_str = "skaterheld", slot_l_hand_str = "skaterheld")
/obj/item/clothing/shoes/heels
name = "high heels"
desc = "A pair of high-heeled shoes. Fancy!"
icon_state = "heels"
/obj/item/clothing/shoes/footwraps
name = "cloth footwraps"
desc = "A roll of treated canvas used for wrapping claws or paws"
icon_state = "clothwrap"
item_state = "clothwrap"
force = 0
w_class = ITEMSIZE_SMALL
species_restricted = null

View File

@@ -2,7 +2,7 @@
/obj/item/clothing/head/helmet/space/skrell
name = "Skrellian helmet"
desc = "Smoothly contoured and polished to a shine. Still looks like a fishbowl."
armor = list(melee = 20, bullet = 20, laser = 50,energy = 50, bomb = 50, bio = 100, rad = 100)
armor = list(melee = 20, bullet = 20, laser = 20, energy = 50, bomb = 50, bio = 100, rad = 50)
max_heat_protection_temperature = SPACE_SUIT_MAX_HEAT_PROTECTION_TEMPERATURE
species_restricted = list("Skrell","Human")
@@ -15,7 +15,7 @@
/obj/item/clothing/suit/space/skrell
name = "Skrellian voidsuit"
desc = "Seems like a wetsuit with reinforced plating seamlessly attached to it. Very chic."
armor = list(melee = 20, bullet = 20, laser = 50,energy = 50, bomb = 50, bio = 100, rad = 100)
armor = list(melee = 20, bullet = 20, laser = 20, energy = 50, bomb = 50, bio = 100, rad = 50)
allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/weapon/storage/bag/ore,/obj/item/device/t_scanner,/obj/item/weapon/pickaxe, /obj/item/weapon/rcd)
heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS
max_heat_protection_temperature = SPACE_SUIT_MAX_HEAT_PROTECTION_TEMPERATURE
@@ -35,14 +35,14 @@
allowed = list(/obj/item/weapon/gun,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/melee/energy/sword,/obj/item/weapon/handcuffs,/obj/item/weapon/tank)
phoronproof = 1
slowdown = 2
armor = list(melee = 60, bullet = 50, laser = 40,energy = 15, bomb = 30, bio = 30, rad = 30)
armor = list(melee = 60, bullet = 50, laser = 40,energy = 15, bomb = 30, bio = 100, rad = 50)
siemens_coefficient = 0.2
heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS
max_heat_protection_temperature = SPACE_SUIT_MAX_HEAT_PROTECTION_TEMPERATURE
species_restricted = list("Vox")
/obj/item/clothing/head/helmet/space/vox
armor = list(melee = 60, bullet = 50, laser = 40, energy = 15, bomb = 30, bio = 30, rad = 30)
armor = list(melee = 60, bullet = 50, laser = 40, energy = 15, bomb = 30, bio = 100, rad = 50)
siemens_coefficient = 0.2
item_flags = STOPPRESSUREDAMAGE | THICKMATERIAL | AIRTIGHT | PHORONGUARD
flags_inv = 0

View File

@@ -149,16 +149,19 @@
/obj/item/rig_module/chem_dispenser/ninja
interface_desc = "Dispenses loaded chemicals directly into the wearer's bloodstream. This variant is made to be extremely light and flexible."
//just over a syringe worth of each. Want more? Go refill. Gives the ninja another reason to have to show their face.
//Want more? Go refill. Gives the ninja another reason to have to show their face.
charges = list(
list("tricordrazine", "tricordrazine", 0, 20),
list("tramadol", "tramadol", 0, 20),
list("dexalin plus", "dexalinp", 0, 20),
list("antibiotics", "spaceacillin", 0, 20),
list("antitoxins", "anti_toxin", 0, 20),
list("nutrients", "glucose", 0, 80),
list("hyronalin", "hyronalin", 0, 20),
list("radium", "radium", 0, 20)
list("tricordrazine", "tricordrazine", 0, 30),
list("tramadol", "tramadol", 0, 30),
list("dexalin plus", "dexalinp", 0, 30),
list("antibiotics", "spaceacillin", 0, 30),
list("antitoxins", "anti_toxin", 0, 60),
list("nutrients", "glucose", 0, 80),
list("bicaridine", "bicaridine", 0, 30),
list("clotting agent", "myelamine", 0, 30),
list("peridaxon", "peridaxon", 0, 30),
list("hyronalin", "hyronalin", 0, 30),
list("radium", "radium", 0, 30)
)
/obj/item/rig_module/chem_dispenser/accepts_item(var/obj/item/input_item, var/mob/living/user)
@@ -246,6 +249,7 @@
list("hyperzine", "hyperzine", 0, 30),
list("oxycodone", "oxycodone", 0, 30),
list("nutrients", "glucose", 0, 80),
list("clotting agent", "myelamine", 0, 80)
)
interface_name = "combat chem dispenser"
@@ -263,6 +267,20 @@
interface_name = "mounted chem injector"
interface_desc = "Dispenses loaded chemicals via an arm-mounted injector."
/obj/item/rig_module/chem_dispenser/injector/advanced
charges = list(
list("tricordrazine", "tricordrazine", 0, 80),
list("tramadol", "tramadol", 0, 80),
list("dexalin plus", "dexalinp", 0, 80),
list("antibiotics", "spaceacillin", 0, 80),
list("antitoxins", "anti_toxin", 0, 80),
list("nutrients", "glucose", 0, 80),
list("hyronalin", "hyronalin", 0, 80),
list("radium", "radium", 0, 80),
list("clotting agent", "myelamine", 0, 80)
)
/obj/item/rig_module/voice
name = "hardsuit voice synthesiser"

View File

@@ -161,6 +161,7 @@
piece.permeability_coefficient = permeability_coefficient
piece.unacidable = unacidable
if(islist(armor)) piece.armor = armor.Copy()
if(islist(armorsoak)) piece.armorsoak = armorsoak.Copy()
update_icon(1)

View File

@@ -45,7 +45,7 @@
desc = "This metal box writhes and squirms as if it were alive..."
suit_type = "alien"
icon_state = "vox_rig"
armor = list(melee = 60, bullet = 50, laser = 40, energy = 15, bomb = 30, bio = 30, rad = 30)
armor = list(melee = 60, bullet = 50, laser = 40, energy = 15, bomb = 30, bio = 100, rad = 50)
item_flags = THICKMATERIAL
siemens_coefficient = 0.2
phoronproof = 1
@@ -88,7 +88,7 @@
/obj/item/weapon/rig/vox/carapace
name = "dense alien control module"
suit_type = "dense alien"
armor = list(melee = 60, bullet = 50, laser = 40, energy = 15, bomb = 30, bio = 30, rad = 30)
armor = list(melee = 60, bullet = 50, laser = 40, energy = 15, bomb = 30, bio = 100, rad = 50)
emp_protection = 40 //change this to 30 if too high.
phoronproof = 1
@@ -109,7 +109,7 @@
name = "sinister alien control module"
suit_type = "sinister alien"
icon_state = "voxstealth_rig"
armor = list(melee = 40, bullet = 30, laser = 30, energy = 15, bomb = 30, bio = 100, rad = 100)
armor = list(melee = 40, bullet = 30, laser = 30, energy = 15, bomb = 30, bio = 100, rad = 50)
emp_protection = 40 //change this to 30 if too high.
phoronproof = 1

View File

@@ -49,7 +49,7 @@
/obj/item/rig_module/ai_container,
/obj/item/rig_module/maneuvering_jets,
/obj/item/rig_module/device/healthscanner,
/obj/item/rig_module/chem_dispenser/injector
/obj/item/rig_module/chem_dispenser/injector/advanced
)
/obj/item/weapon/rig/ert/security

View File

@@ -93,7 +93,7 @@
/obj/item/rig_module/vision,
/obj/item/rig_module/voice,
/obj/item/rig_module/fabricator/energy_net,
/obj/item/rig_module/chem_dispenser,
/obj/item/rig_module/chem_dispenser/ninja,
/obj/item/rig_module/grenade_launcher,
/obj/item/rig_module/ai_container,
/obj/item/rig_module/power_sink,

View File

@@ -3,7 +3,7 @@
*/
//Botanist
/obj/item/clothing/suit/apron
/obj/item/clothing/suit/storage/apron
name = "apron"
desc = "A basic blue apron."
icon_state = "apron"
@@ -174,20 +174,16 @@
/obj/item/clothing/suit/storage/toggle/lawyer/bluejacket
name = "blue suit jacket"
desc = "A snappy dress jacket."
icon_state = "suitjacket_blue_open"
icon_state = "suitjacket_blue"
item_state_slots = list(slot_r_hand_str = "suit_blue", slot_l_hand_str = "suit_blue")
icon_open = "suitjacket_blue_open"
icon_closed = "suitjacket_blue"
blood_overlay_type = "coat"
body_parts_covered = UPPER_TORSO|ARMS
/obj/item/clothing/suit/storage/toggle/lawyer/purpjacket
name = "purple suit jacket"
desc = "A snappy dress jacket."
icon_state = "suitjacket_purp_open"
icon_state = "suitjacket_purp"
item_state_slots = list(slot_r_hand_str = "suit_purple", slot_l_hand_str = "suit_purple")
icon_open = "suitjacket_purp_open"
icon_closed = "suitjacket_purp"
blood_overlay_type = "coat"
body_parts_covered = UPPER_TORSO|ARMS
@@ -195,10 +191,8 @@
/obj/item/clothing/suit/storage/toggle/internalaffairs
name = "black suit jacket"
desc = "A smooth black jacket."
icon_state = "ia_jacket_open"
icon_state = "ia_jacket"
item_state_slots = list(slot_r_hand_str = "suit_black", slot_l_hand_str = "suit_black")
icon_open = "ia_jacket_open"
icon_closed = "ia_jacket"
blood_overlay_type = "coat"
body_parts_covered = UPPER_TORSO|ARMS
@@ -206,10 +200,8 @@
/obj/item/clothing/suit/storage/toggle/fr_jacket
name = "first responder jacket"
desc = "A high-visibility jacket worn by medical first responders."
icon_state = "fr_jacket_open"
icon_state = "fr_jacket"
item_state_slots = list(slot_r_hand_str = "fr_jacket", slot_l_hand_str = "fr_jacket")
icon_open = "fr_jacket_open"
icon_closed = "fr_jacket"
blood_overlay_type = "armor"
allowed = list(/obj/item/stack/medical, /obj/item/weapon/reagent_containers/dropper, /obj/item/weapon/reagent_containers/hypospray, /obj/item/weapon/reagent_containers/syringe,
/obj/item/device/healthanalyzer, /obj/item/device/flashlight, /obj/item/device/radio, /obj/item/weapon/tank/emergency/oxygen)
@@ -218,10 +210,8 @@
/obj/item/clothing/suit/storage/toggle/fr_jacket/ems
name = "\improper EMS jacket"
desc = "A dark blue, martian-pattern, EMS jacket. It sports high-visibility reflective stripes and a star of life on the back."
icon_state = "ems_jacket_closed"
icon_state = "ems_jacket"
item_state_slots = list(slot_r_hand_str = "ems_jacket", slot_l_hand_str = "ems_jacket")
icon_open = "ems_jacket_open"
icon_closed = "ems_jacket_closed"
/obj/item/clothing/suit/surgicalapron
name = "surgical apron"

View File

@@ -1,10 +1,8 @@
/obj/item/clothing/suit/storage/toggle/labcoat
name = "labcoat"
desc = "A suit that protects against minor chemical spills."
icon_state = "labcoat_open"
icon_state = "labcoat"
item_state_slots = list(slot_r_hand_str = "labcoat", slot_l_hand_str = "labcoat")
icon_open = "labcoat_open"
icon_closed = "labcoat"
blood_overlay_type = "coat"
body_parts_covered = UPPER_TORSO|ARMS
flags_inv = HIDEHOLSTER
@@ -14,120 +12,95 @@
/obj/item/clothing/suit/storage/toggle/labcoat/red
name = "red labcoat"
desc = "A suit that protects against minor chemical spills. This one is red."
icon_state = "red_labcoat_open"
icon_open = "red_labcoat_open"
icon_closed = "red_labcoat"
icon_state = "red_labcoat"
item_state_slots = list(slot_r_hand_str = "red_labcoat", slot_l_hand_str = "red_labcoat")
/obj/item/clothing/suit/storage/toggle/labcoat/blue
name = "blue labcoat"
desc = "A suit that protects against minor chemical spills. This one is blue."
icon_state = "blue_labcoat_open"
icon_open = "blue_labcoat_open"
icon_closed = "blue_labcoat"
icon_state = "blue_labcoat"
item_state_slots = list(slot_r_hand_str = "blue_labcoat", slot_l_hand_str = "blue_labcoat")
/obj/item/clothing/suit/storage/toggle/labcoat/purple
name = "purple labcoat"
desc = "A suit that protects against minor chemical spills. This one is purple."
icon_state = "purple_labcoat_open"
icon_open = "purple_labcoat_open"
icon_closed = "purple_labcoat"
icon_state = "purple_labcoat"
item_state_slots = list(slot_r_hand_str = "purple_labcoat", slot_l_hand_str = "purple_labcoat")
/obj/item/clothing/suit/storage/toggle/labcoat/orange
name = "orange labcoat"
desc = "A suit that protects against minor chemical spills. This one is orange."
icon_state = "orange_labcoat_open"
icon_open = "orange_labcoat_open"
icon_closed = "orange_labcoat"
icon_state = "orange_labcoat"
item_state_slots = list(slot_r_hand_str = "orange_labcoat", slot_l_hand_str = "orange_labcoat")
/obj/item/clothing/suit/storage/toggle/labcoat/green
name = "green labcoat"
desc = "A suit that protects against minor chemical spills. This one is green."
icon_state = "green_labcoat_open"
icon_open = "green_labcoat_open"
icon_closed = "green_labcoat"
icon_state = "green_labcoat"
item_state_slots = list(slot_r_hand_str = "green_labcoat", slot_l_hand_str = "green_labcoat")
/obj/item/clothing/suit/storage/toggle/labcoat/yellow
name = "yellow labcoat"
desc = "A suit that protects against minor chemical spills. This one is yellow."
icon_state = "yellow_labcoat_open"
icon_open = "yellow_labcoat_open"
icon_closed = "yellow_labcoat"
icon_state = "yellow_labcoat"
item_state_slots = list(slot_r_hand_str = "yellow_labcoat", slot_l_hand_str = "yellow_labcoat")
/obj/item/clothing/suit/storage/toggle/labcoat/pink
name = "pink labcoat"
desc = "A suit that protects against minor chemical spills. This one is pink."
icon_state = "pink_labcoat_open"
icon_open = "pink_labcoat_open"
icon_closed = "pink_labcoat"
icon_state = "pink_labcoat"
item_state_slots = list(slot_r_hand_str = "pink_labcoat", slot_l_hand_str = "pink_labcoat")
/obj/item/clothing/suit/storage/toggle/labcoat/cmo
name = "chief medical officer's labcoat"
desc = "Bluer than the standard model."
icon_state = "labcoat_cmo_open"
icon_open = "labcoat_cmo_open"
icon_closed = "labcoat_cmo"
icon_state = "labcoat_cmo"
item_state_slots = list(slot_r_hand_str = "cmo_labcoat", slot_l_hand_str = "cmo_labcoat")
/obj/item/clothing/suit/storage/toggle/labcoat/cmoalt
name = "chief medical officer labcoat"
desc = "A labcoat with command blue highlights."
icon_state = "labcoat_cmoalt_open"
icon_open = "labcoat_cmoalt_open"
icon_closed = "labcoat_cmoalt"
icon_state = "labcoat_cmoalt"
item_state_slots = list(slot_r_hand_str = "cmo_labcoat", slot_l_hand_str = "cmo_labcoat")
/obj/item/clothing/suit/storage/toggle/labcoat/mad
name = "The Mad's labcoat"
desc = "It makes you look capable of konking someone on the noggin and shooting them into space."
icon_state = "labgreen_open"
icon_open = "labgreen_open"
icon_closed = "labgreen"
icon_state = "labgreen"
item_state_slots = list(slot_r_hand_str = "green_labcoat", slot_l_hand_str = "green_labcoat")
/obj/item/clothing/suit/storage/toggle/labcoat/genetics
name = "Geneticist labcoat"
desc = "A suit that protects against minor chemical spills. Has a blue stripe on the shoulder."
icon_state = "labcoat_gen_open"
icon_open = "labcoat_gen_open"
icon_closed = "labcoat_gen"
icon_state = "labcoat_gen"
item_state_slots = list(slot_r_hand_str = "genetics_labcoat", slot_l_hand_str = "genetics_labcoat")
/obj/item/clothing/suit/storage/toggle/labcoat/chemist
name = "Chemist labcoat"
desc = "A suit that protects against minor chemical spills. Has an orange stripe on the shoulder."
icon_state = "labcoat_chem_open"
icon_open = "labcoat_chem_open"
icon_closed = "labcoat_chem"
icon_state = "labcoat_chem"
item_state_slots = list(slot_r_hand_str = "chemist_labcoat", slot_l_hand_str = "chemist_labcoat")
/obj/item/clothing/suit/storage/toggle/labcoat/virologist
name = "Virologist labcoat"
desc = "A suit that protects against minor chemical spills. Offers slightly more protection against biohazards than the standard model. Has a green stripe on the shoulder."
icon_state = "labcoat_vir_open"
icon_open = "labcoat_vir_open"
icon_closed = "labcoat_vir"
icon_state = "labcoat_vir"
item_state_slots = list(slot_r_hand_str = "virologist_labcoat", slot_l_hand_str = "virologist_labcoat")
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 60, rad = 0)
/obj/item/clothing/suit/storage/toggle/labcoat/science
name = "Scientist labcoat"
desc = "A suit that protects against minor chemical spills. Has a purple stripe on the shoulder."
icon_state = "labcoat_tox_open"
icon_open = "labcoat_tox_open"
icon_closed = "labcoat_tox"
icon_state = "labcoat_tox"
item_state_slots = list(slot_r_hand_str = "science_labcoat", slot_l_hand_str = "science_labcoat")
/obj/item/clothing/suit/storage/toggle/labcoat/emt
name = "EMT's labcoat"
desc = "A dark blue labcoat with reflective strips for emergency medical technicians."
icon_state = "labcoat_emt_open"
icon_open = "labcoat_emt_open"
icon_closed = "labcoat_emt"
item_state_slots = list(slot_r_hand_str = "emt_labcoat", slot_l_hand_str = "emt_labcoat")
icon_state = "labcoat_emt"
item_state_slots = list(slot_r_hand_str = "emt_labcoat", slot_l_hand_str = "emt_labcoat")
/obj/item/clothing/suit/storage/toggle/labcoat/blue_edge
name = "blue-edged labcoat"
desc = "A suit that protects against minor chemical spills. This one has blue trim."
icon_state = "blue_edge_labcoat"

View File

@@ -120,7 +120,7 @@
name = "red sweatervest"
icon_state = "sweatervest_red"
*/
/obj/item/clothing/suit/apron/overalls
/obj/item/clothing/suit/storage/apron/overalls
name = "coveralls"
desc = "A set of denim overalls."
icon_state = "overalls"
@@ -265,6 +265,11 @@
body_parts_covered = UPPER_TORSO|ARMS
flags_inv = HIDETIE|HIDEHOLSTER
obj/item/clothing/suit/kimono
name = "kimono"
desc = "A traditional Japanese kimono."
icon_state = "kimono"
/*
* coats
*/
@@ -391,8 +396,6 @@
desc = "A thick, well-worn WW2 leather bomber jacket."
icon_state = "bomber"
item_state_slots = list(slot_r_hand_str = "brown_jacket", slot_l_hand_str = "brown_jacket")
icon_open = "bomber_open"
icon_closed = "bomber"
allowed = list (/obj/item/weapon/pen, /obj/item/weapon/paper, /obj/item/device/flashlight, /obj/item/weapon/tank/emergency/oxygen, /obj/item/weapon/storage/fancy/cigarettes, /obj/item/weapon/storage/box/matches, /obj/item/weapon/reagent_containers/food/drinks/flask)
body_parts_covered = UPPER_TORSO|ARMS
flags_inv = HIDEHOLSTER
@@ -415,7 +418,6 @@
name = "leather jacket"
desc = "A black leather coat."
icon_state = "leather_jacket"
icon_open = "leather_jacket_open"
allowed = list (/obj/item/weapon/pen, /obj/item/weapon/paper, /obj/item/device/flashlight, /obj/item/weapon/tank/emergency/oxygen, /obj/item/weapon/storage/fancy/cigarettes, /obj/item/weapon/storage/box/matches, /obj/item/weapon/reagent_containers/food/drinks/flask)
body_parts_covered = UPPER_TORSO|ARMS
flags_inv = HIDEHOLSTER
@@ -424,8 +426,6 @@
name = "leather vest"
desc = "A black leather vest."
icon_state = "leather_jacket_sleeveless"
icon_open = "leather_jacket_sleeveless_open"
icon_closed = "leather_jacket_sleeveless"
body_parts_covered = UPPER_TORSO
item_state_slots = list(slot_r_hand_str = "leather_jacket", slot_l_hand_str = "leather_jacket")
@@ -439,16 +439,12 @@
/obj/item/clothing/suit/storage/toggle/leather_jacket/nanotrasen
desc = "A black leather coat. A corporate logo is proudly displayed on the back."
icon_state = "leather_jacket_nt"
icon_closed = "leather_jacket_nt"
icon_open = "leather_jacket_nt_open"
item_state_slots = list(slot_r_hand_str = "leather_jacket", slot_l_hand_str = "leather_jacket")
/obj/item/clothing/suit/storage/toggle/leather_jacket/nanotrasen/sleeveless
name = "leather vest"
desc = "A black leather vest. A corporate logo is proudly displayed on the back."
icon_state = "leather_jacket_nt_sleeveless"
icon_open = "leather_jacket_nt_sleeveless_open"
icon_closed = "leather_jacket_nt_sleeveless"
body_parts_covered = UPPER_TORSO
item_state_slots = list(slot_r_hand_str = "leather_jacket", slot_l_hand_str = "leather_jacket")
@@ -458,8 +454,6 @@
desc = "A brown leather coat."
icon_state = "brown_jacket"
item_state_slots = list(slot_r_hand_str = "brown_jacket", slot_l_hand_str = "brown_jacket")
icon_open = "brown_jacket_open"
icon_closed = "brown_jacket"
allowed = list (/obj/item/weapon/pen, /obj/item/weapon/paper, /obj/item/device/flashlight,/obj/item/weapon/tank/emergency/oxygen, /obj/item/weapon/storage/fancy/cigarettes, /obj/item/weapon/storage/box/matches, /obj/item/weapon/reagent_containers/food/drinks/flask)
body_parts_covered = UPPER_TORSO|ARMS
flags_inv = HIDEHOLSTER
@@ -468,8 +462,6 @@
name = "brown vest"
desc = "A brown leather vest."
icon_state = "brown_jacket_sleeveless"
icon_open = "brown_jacket_sleeveless_open"
icon_closed = "brown_jacket_sleeveless"
body_parts_covered = UPPER_TORSO
item_state_slots = list(slot_r_hand_str = "brown_jacket", slot_l_hand_str = "brown_jacket")
@@ -477,15 +469,11 @@
desc = "A brown leather coat. A corporate logo is proudly displayed on the back."
icon_state = "brown_jacket_nt"
item_state_slots = list(slot_r_hand_str = "brown_jacket", slot_l_hand_str = "brown_jacket")
icon_open = "brown_jacket_nt_open"
icon_closed = "brown_jacket_nt"
/obj/item/clothing/suit/storage/toggle/brown_jacket/nanotrasen/sleeveless
name = "brown vest"
desc = "A brown leather vest. A corporate logo is proudly displayed on the back."
icon_state = "brown_jacket_nt_sleeveless"
icon_open = "brown_jacket_nt_open"
icon_closed = "brown_jacket_nt_sleeveless"
body_parts_covered = UPPER_TORSO
item_state_slots = list(slot_r_hand_str = "brown_jacket", slot_l_hand_str = "brown_jacket")
@@ -494,8 +482,6 @@
desc = "A denim coat."
icon_state = "denim_jacket"
item_state_slots = list(slot_r_hand_str = "denim_jacket", slot_l_hand_str = "denim_jacket")
icon_open = "denim_jacket_open"
icon_closed = "denim_jacket"
allowed = list (/obj/item/weapon/pen, /obj/item/weapon/paper, /obj/item/device/flashlight,/obj/item/weapon/tank/emergency/oxygen, /obj/item/weapon/storage/fancy/cigarettes, /obj/item/weapon/storage/box/matches, /obj/item/weapon/reagent_containers/food/drinks/flask)
body_parts_covered = UPPER_TORSO|ARMS
flags_inv = HIDEHOLSTER
@@ -504,8 +490,6 @@
name = "denim vest"
desc = "A denim vest."
icon_state = "denim_jacket_sleeveless"
icon_open = "denim_jacket_sleeveless_open"
icon_closed = "denim_jacket_sleeveless"
body_parts_covered = UPPER_TORSO
item_state_slots = list(slot_r_hand_str = "denim_jacket", slot_l_hand_str = "denim_jacket")
@@ -513,15 +497,11 @@
desc = "A denim coat. A corporate logo is proudly displayed on the back."
icon_state = "denim_jacket_nt"
item_state_slots = list(slot_r_hand_str = "denim_jacket", slot_l_hand_str = "denim_jacket")
icon_open = "denim_jacket_nt_open"
icon_closed = "denim_jacket_nt"
/obj/item/clothing/suit/storage/toggle/denim_jacket/nanotrasen/sleeveless
name = "denim vest"
desc = "A denim vest. A corporate logo is proudly displayed on the back."
icon_state = "denim_jacket_nt_sleeveless"
icon_open = "denim_jacket_nt_open"
icon_closed = "denim_jacket_nt_sleeveless"
body_parts_covered = UPPER_TORSO
item_state_slots = list(slot_r_hand_str = "denim_jacket", slot_l_hand_str = "denim_jacket")
@@ -530,8 +510,6 @@
desc = "A warm, grey sweatshirt."
icon_state = "grey_hoodie"
item_state_slots = list(slot_r_hand_str = "suit_grey", slot_l_hand_str = "suit_grey")
icon_open = "grey_hoodie_open"
icon_closed = "grey_hoodie"
min_cold_protection_temperature = T0C - 20
cold_protection = UPPER_TORSO|LOWER_TORSO|ARMS
flags_inv = HIDEHOLSTER
@@ -541,80 +519,60 @@
desc = "A warm, black sweatshirt."
icon_state = "black_hoodie"
item_state_slots = list(slot_r_hand_str = "suit_black", slot_l_hand_str = "suit_black")
icon_open = "black_hoodie_open"
icon_closed = "black_hoodie"
/obj/item/clothing/suit/storage/toggle/hoodie/red
name = "red hoodie"
desc = "A warm, red sweatshirt."
icon_state = "red_hoodie"
item_state_slots = list(slot_r_hand_str = "suit_red", slot_l_hand_str = "suit_red")
icon_open = "red_hoodie_open"
icon_closed = "red_hoodie"
/obj/item/clothing/suit/storage/toggle/hoodie/blue
name = "blue hoodie"
desc = "A warm, blue sweatshirt."
icon_state = "blue_hoodie"
item_state_slots = list(slot_r_hand_str = "suit_blue", slot_l_hand_str = "suit_blue")
icon_open = "blue_hoodie_open"
icon_closed = "blue_hoodie"
/obj/item/clothing/suit/storage/toggle/hoodie/green
name = "green hoodie"
desc = "A warm, green sweatshirt."
icon_state = "green_hoodie"
item_state_slots = list(slot_r_hand_str = "suit_olive", slot_l_hand_str = "suit_olive")
icon_open = "green_hoodie_open"
icon_closed = "green_hoodie"
/obj/item/clothing/suit/storage/toggle/hoodie/orange
name = "orange hoodie"
desc = "A warm, orange sweatshirt."
icon_state = "orange_hoodie"
item_state_slots = list(slot_r_hand_str = "suit_orange", slot_l_hand_str = "suit_orange")
icon_open = "orange_hoodie_open"
icon_closed = "orange_hoodie"
/obj/item/clothing/suit/storage/toggle/hoodie/yellow
name = "yellow hoodie"
desc = "A warm, yellow sweatshirt."
icon_state = "yellow_hoodie"
item_state_slots = list(slot_r_hand_str = "suit_yellow", slot_l_hand_str = "suit_yellow")
icon_open = "yellow_hoodie_open"
icon_closed = "yellow_hoodie"
/obj/item/clothing/suit/storage/toggle/hoodie/cti
name = "CTI hoodie"
desc = "A warm, black sweatshirt. It bears the letters ‘CTI’ on the back, a lettering to the prestigious university in Tau Ceti, Ceti Technical Institute. There is a blue supernova embroidered on the front, the emblem of CTI."
icon_state = "cti_hoodie"
item_state_slots = list(slot_r_hand_str = "suit_black", slot_l_hand_str = "suit_black")
icon_open = "cti_hoodie_open"
icon_closed = "cti_hoodie"
/obj/item/clothing/suit/storage/toggle/hoodie/mu
name = "mojave university hoodie"
desc = "A warm, gray sweatshirt. It bears the letters ‘MU’ on the front, a lettering to the well-known public college, Mojave University."
icon_state = "mu_hoodie"
item_state_slots = list(slot_r_hand_str = "suit_grey", slot_l_hand_str = "suit_grey")
icon_open = "mu_hoodie_open"
icon_closed = "mu_hoodie"
/obj/item/clothing/suit/storage/toggle/hoodie/nt
name = "NT hoodie"
desc = "A warm, blue sweatshirt. It proudly bears the silver NanoTrasen insignia lettering on the back. The edges are trimmed with silver."
icon_state = "nt_hoodie"
item_state_slots = list(slot_r_hand_str = "suit_blue", slot_l_hand_str = "suit_blue")
icon_open = "nt_hoodie_open"
icon_closed = "nt_hoodie"
/obj/item/clothing/suit/storage/toggle/hoodie/smw
name = "Space Mountain Wind hoodie"
desc = "A warm, black sweatshirt. It has the logo for the popular softdrink Space Mountain Wind on both the front and the back."
icon_state = "smw_hoodie"
item_state_slots = list(slot_r_hand_str = "suit_black", slot_l_hand_str = "suit_black")
icon_open = "smw_hoodie_open"
icon_closed = "smw_hoodie"
/obj/item/clothing/suit/whitedress
name = "white dress"
@@ -812,6 +770,44 @@
name = "brown varsity jacket"
icon_state = "varsity_brown"
/*
* Department Jackets
*/
/obj/item/clothing/suit/storage/toggle/sec_dep_jacket
name = "department jacket, security"
desc = "A cozy jacket in security's colors. Show your department pride!"
icon_state = "sec_dep_jacket"
item_state_slots = list(slot_r_hand_str = "sec_dep_jacket", slot_l_hand_str = "sec_dep_jacket")
flags_inv = HIDEHOLSTER
/obj/item/clothing/suit/storage/toggle/engi_dep_jacket
name = "department jacket, engineering"
desc = "A cozy jacket in engineering's colors. Show your department pride!"
icon_state = "engi_dep_jacket"
item_state_slots = list(slot_r_hand_str = "engi_dep_jacket", slot_l_hand_str = "engi_dep_jacket")
flags_inv = HIDEHOLSTER
/obj/item/clothing/suit/storage/toggle/supply_dep_jacket
name = "department jacket, supply"
desc = "A cozy jacket in supply's colors. Show your department pride!"
icon_state = "supply_dep_jacket"
item_state_slots = list(slot_r_hand_str = "supply_dep_jacket", slot_l_hand_str = "supply_dep_jacket")
flags_inv = HIDEHOLSTER
/obj/item/clothing/suit/storage/toggle/sci_dep_jacket
name = "department jacket, science"
desc = "A cozy jacket in science's colors. Show your department pride!"
icon_state = "sci_dep_jacket"
item_state_slots = list(slot_r_hand_str = "sci_dep_jacket", slot_l_hand_str = "sci_dep_jacket")
flags_inv = HIDEHOLSTER
/obj/item/clothing/suit/storage/toggle/med_dep_jacket
name = "department jacket, medical"
desc = "A cozy jacket in medical's colors. Show your department pride!"
icon_state = "med_dep_jacket"
item_state_slots = list(slot_r_hand_str = "med_dep_jacket", slot_l_hand_str = "med_dep_jacket")
flags_inv = HIDEHOLSTER
/*
* Track Jackets
*/
@@ -820,37 +816,28 @@
desc = "a track jacket, for the athletic."
icon_state = "trackjacket"
item_state_slots = list(slot_r_hand_str = "black_labcoat", slot_l_hand_str = "black_labcoat")
icon_open = "trackjacket_open"
icon_closed = "trackjacket"
allowed = list (/obj/item/weapon/pen, /obj/item/weapon/paper, /obj/item/device/flashlight,/obj/item/weapon/tank/emergency/oxygen, /obj/item/weapon/storage/fancy/cigarettes, /obj/item/weapon/storage/box/matches, /obj/item/weapon/reagent_containers/food/drinks/flask)
/obj/item/clothing/suit/storage/toggle/track/blue
name = "blue track jacket"
icon_state = "trackjacketblue"
item_state_slots = list(slot_r_hand_str = "blue_labcoat", slot_l_hand_str = "blue_labcoat")
icon_open = "trackjacketblue_open"
icon_closed = "trackjacketblue"
/obj/item/clothing/suit/storage/toggle/track/green
name = "green track jacket"
icon_state = "trackjacketgreen"
item_state_slots = list(slot_r_hand_str = "green_labcoat", slot_l_hand_str = "green_labcoat")
icon_open = "trackjacketgreen_open"
icon_closed = "trackjacketgreen"
/obj/item/clothing/suit/storage/toggle/track/red
name = "red track jacket"
icon_state = "trackjacketred"
item_state_slots = list(slot_r_hand_str = "red_labcoat", slot_l_hand_str = "red_labcoat")
icon_open = "trackjacketred_open"
icon_closed = "trackjacketred"
/obj/item/clothing/suit/storage/toggle/track/white
name = "white track jacket"
icon_state = "trackjacketwhite"
item_state_slots = list(slot_r_hand_str = "labcoat", slot_l_hand_str = "labcoat")
icon_open = "trackjacketwhite_open"
icon_closed = "trackjacketwhite"
//Flannels
@@ -944,10 +931,9 @@
/obj/item/clothing/suit/storage/toggle/greengov
name = "green formal jacket"
desc = "A sleek proper formal jacket with gold buttons."
icon_state = "suitjacket_green_open"
icon_state = "suitjacket_green"
item_state_slots = list(slot_r_hand_str = "suit_olive", slot_l_hand_str = "suit_olive")
icon_open = "suitjacket_green_open"
icon_closed = "suitjacket_green"
blood_overlay_type = "coat"
body_parts_covered = UPPER_TORSO|ARMS
flags_inv = HIDEHOLSTER
flags_inv = HIDEHOLSTER

View File

@@ -129,8 +129,6 @@
desc = "A uniform dress jacket with gold toggles."
icon_state = "whitedress"
item_state = "labcoat"
icon_open = "whitedress_open"
icon_closed = "whitedress"
blood_overlay_type = "coat"
/obj/item/clothing/suit/storage/toggle/dress/fleet
@@ -142,8 +140,6 @@
desc = "A crisp white SCG Fleet dress jacket dripping with gold accents. So bright it's blinding."
icon_state = "whitedress_com"
item_state = "labcoat"
icon_open = "whitedress_com_open"
icon_closed = "whitedress_com"
blood_overlay_type = "coat"
/obj/item/clothing/suit/dress/marine
@@ -163,6 +159,4 @@
desc = "A black synthleather jacket. The word 'MARSHAL' is stenciled onto the back in gold lettering."
icon_state = "marshal_jacket"
item_state_slots = list(slot_r_hand_str = "suit_black", slot_l_hand_str = "suit_black")
icon_open = "marshal_jacket_open"
icon_closed = "marshal_jacket"
body_parts_covered = UPPER_TORSO|ARMS

View File

@@ -31,8 +31,7 @@
//Jackets with buttons, used for labcoats, IA jackets, First Responder jackets, and brown jackets.
/obj/item/clothing/suit/storage/toggle
flags_inv = HIDEHOLSTER
var/icon_open
var/icon_closed
var/open = 0 //0 is closed, 1 is open, -1 means it won't be able to toggle
verb/toggle()
set name = "Toggle Coat Buttons"
set category = "Object"
@@ -40,12 +39,14 @@
if(!usr.canmove || usr.stat || usr.restrained())
return 0
if(icon_state == icon_open) //Will check whether icon state is currently set to the "open" or "closed" state and switch it around with a message to the user
icon_state = icon_closed
if(open == 1) //Will check whether icon state is currently set to the "open" or "closed" state and switch it around with a message to the user
open = 0
icon_state = initial(icon_state)
flags_inv = HIDETIE|HIDEHOLSTER
usr << "You button up the coat."
else if(icon_state == icon_closed)
icon_state = icon_open
else if(open == 0)
open = 1
icon_state = "[icon_state]_open"
flags_inv = HIDEHOLSTER
usr << "You unbutton the coat."
else //in case some goofy admin switches icon states around without switching the icon_open or icon_closed
@@ -56,8 +57,7 @@
/obj/item/clothing/suit/storage/hooded/toggle
flags_inv = HIDEHOLSTER
var/icon_open
var/icon_closed
var/open = 0 //0 is closed, 1 is open, -1 means it won't be able to toggle
verb/toggle()
set name = "Toggle Coat Buttons"
set category = "Object"
@@ -65,12 +65,14 @@
if(!usr.canmove || usr.stat || usr.restrained())
return 0
if(icon_state == icon_open) //Will check whether icon state is currently set to the "open" or "closed" state and switch it around with a message to the user
icon_state = icon_closed
if(open == 1) //Will check whether icon state is currently set to the "open" or "closed" state and switch it around with a message to the user
open = 0
icon_state = initial(icon_state)
flags_inv = HIDETIE|HIDEHOLSTER
usr << "You button up the coat."
else if(icon_state == icon_closed)
icon_state = icon_open
else if(open == 0)
open = 1
icon_state = "[icon_state]_open"
flags_inv = HIDEHOLSTER
usr << "You unbutton the coat."
else //in case some goofy admin switches icon states around without switching the icon_open or icon_closed

View File

@@ -344,7 +344,7 @@
/*
* wedding stuff
*/
/obj/item/clothing/under/wedding/
/obj/item/clothing/under/wedding
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS
/obj/item/clothing/under/wedding/bride_orange

View File

@@ -117,6 +117,11 @@
desc = "A pair of sexy, tight black leather chaps."
icon_state = "chapsbl"
/obj/item/clothing/under/pants/yogapants
name = "yoga pants"
desc = "A pair of tight-fitting yoga pants for those lazy days."
icon_state = "yogapants"
/*
* Baggy Pants
*/

View File

@@ -91,11 +91,6 @@
name = "khaki short shorts"
icon_state = "khaki_shorts_f"
/obj/item/clothing/under/shorts/loincloth
name = "loincloth"
desc = "A piece of cloth wrapped around the waist."
icon_state = "loincloth"
//Argh, skirts be below this line -> ------------------------------
/obj/item/clothing/under/skirt
@@ -130,6 +125,11 @@
desc = "A skirt that is swept to one side."
icon_state = "skirt_swept"
/obj/item/clothing/under/skirt/loincloth
name = "loincloth"
desc = "A piece of cloth wrapped around the waist."
icon_state = "loincloth"
/obj/item/clothing/under/skirt/outfit
name = "black skirt"
desc = "A black skirt, very fancy!"

View File

@@ -212,7 +212,7 @@
worn_state = "greenservice_com"
//Dress
/obj/item/clothing/under/dress/plain
/obj/item/clothing/under/mildress
name = "dress uniform"
desc = "A dress uniform of some kind."
icon_state = "greydress"
@@ -220,25 +220,25 @@
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0)
siemens_coefficient = 0.9
/obj/item/clothing/under/dress/expeditionary
/obj/item/clothing/under/mildress/expeditionary
name = "\improper SifGuard dress uniform"
desc = "The dress uniform of the Sif Homeguard Corps in silver trim."
icon_state = "greydress"
worn_state = "greydress"
/obj/item/clothing/under/dress/expeditionary/command
/obj/item/clothing/under/mildress/expeditionary/command
name = "\improper SifGuard command dress uniform"
desc = "The dress uniform of the Sif Homeguard Corps in gold trim."
icon_state = "greydress_com"
worn_state = "greydress_com"
/obj/item/clothing/under/dress/marine
/obj/item/clothing/under/mildress/marine
name = "marine dress uniform"
desc = "The dress uniform of the SCG Marine Corps, class given form."
icon_state = "blackdress"
worn_state = "blackdress"
/obj/item/clothing/under/dress/marine/command
/obj/item/clothing/under/mildress/marine/command
name = "marine command dress uniform"
desc = "The dress uniform of the SCG Marine Corps, even classier in gold."
icon_state = "blackdress_com"

View File

@@ -471,6 +471,9 @@
/obj/item/weapon/reagent_containers/food/snacks/sosjerky
price_tag = 2
/obj/item/weapon/reagent_containers/food/snacks/unajerky
price_tag = 12
/obj/item/weapon/reagent_containers/food/snacks/cheesiehonkers
price_tag = 1

View File

@@ -0,0 +1,90 @@
//
// This event causes a gas leak of phoron, sleeping_agent, or carbon_dioxide in a random unoccupied area.
// One wonders, where did the gas come from? Who knows! Its SPACE! But if you want something a touch
// more "explainable" then check out the canister_leak event instead.
//
/datum/event/atmos_leak
startWhen = 5 // Nobody will actually be in the room, but still give a bit of warning.
var/area/target_area // Chosen target area
var/area/target_turf // Chosen target turf in target_area
var/gas_type // Chosen gas to release
// Exclude these types and sub-types from targeting eligibilty
var/list/area/excluded = list(
/area/shuttle,
/area/crew_quarters,
/area/holodeck,
/area/engineering/engine_room
)
// Decide which area will be targeted!
/datum/event/atmos_leak/setup()
var/gas_choices = list("carbon_dioxide", "sleeping_agent") // Annoying
if(severity >= EVENT_LEVEL_MODERATE)
gas_choices += "phoron" // Dangerous
if(severity >= EVENT_LEVEL_MAJOR)
gas_choices += "volatile_fuel" // Dangerous and no default atmos setup!
gas_type = pick(gas_choices)
// Assemble areas that all exists (See DM reference if you are confused about loop labels)
var/list/area/grand_list_of_areas = list()
looping_station_areas:
for(var/parentpath in global.the_station_areas)
// Check its not excluded
for(var/excluded_path in excluded)
if(ispath(parentpath, excluded_path))
continue looping_station_areas
// Otherwise add it and all subtypes that exist on the map to our grand list
for(var/areapath in typesof(parentpath))
var/area/A = locate(areapath) // Check if it actually exists
if(istype(A) && A.z in using_map.player_levels)
grand_list_of_areas += A
// Okay, now lets try and pick a target! Lets try 10 times, otherwise give up
for(var/i in 1 to 10)
var/area/A = pick(grand_list_of_areas)
if(is_area_occupied(A))
log_debug("atmos_leak event: Rejected [A] because it is occupied.")
continue
// A good area, great! Lets try and pick a turf
var/list/turfs = list()
for(var/turf/simulated/floor/F in A)
if(turf_clear(F))
turfs += F
if(turfs.len == 0)
log_debug("atmos_leak event: Rejected [A] because it has no clear turfs.")
continue
target_area = A
target_turf = pick(turfs)
// If we can't find a good target, give up
if(!target_area)
log_debug("atmos_leak event: Giving up after too many failures to pick target area")
kill()
return
/** Checks if any living humans are in a given area! */
/datum/event/atmos_leak/proc/is_area_occupied(var/area/myarea)
// Testing suggests looping over human_mob_list is quicker than looping over area contents
for(var/mob/living/carbon/human/H in human_mob_list)
if(H.stat >= DEAD) //Conditions for exclusion here, like if disconnected people start blocking it.
continue
var/area/A = get_area(H)
if(A == myarea) //The loc of a turf is the area it is in.
return 1
return 0
/datum/event/atmos_leak/announce()
command_announcement.Announce("Warning, hazardous [gas_data.name[gas_type]] gas leak detected in \the [target_area], evacuate the area and contain the damage!", "Hazard Alert")
/datum/event/atmos_leak/start()
// Okay, time to actually put the gas in the room!
// TODO - Would be nice to break a waste pipe perhaps?
// TODO - Maybe having it released from a single point and thus causing airflow to blow stuff around
// Fow now just add a bunch of it to the air
var/datum/gas_mixture/air_contents = new
air_contents.temperature = T20C + ((severity - 1) * rand(-50, 50))
air_contents.gas[gas_type] = 10 * MOLES_CELLSTANDARD
target_turf.assume_air(air_contents)
playsound(target_turf, 'sound/effects/smoke.ogg', 50, 1)

View File

@@ -86,6 +86,12 @@
"admin","ponies","heresy","meow","Pun Pun","monkey","Ian","moron","pizza","message","spam",\
"director", "Hello", "Hi!"," ","nuke","crate","dwarf","xeno")
/datum/event/ionstorm/tick()
if(botEmagChance)
for(var/mob/living/bot/bot in world)
if(prob(botEmagChance))
bot.emag_act(1)
/datum/event/ionstorm/end()
spawn(rand(5000,8000))
if(prob(50))

View File

@@ -16,7 +16,7 @@
else
num = rand(2,6)
for(var/i=0, i<num, i++)
var/mob/living/simple_animal/hostile/retaliate/malf_drone/D = new(get_turf(pick(possible_spawns)))
var/mob/living/simple_animal/hostile/malf_drone/D = new(get_turf(pick(possible_spawns)))
drones_list.Add(D)
if(prob(25))
D.disabled = rand(15, 60)
@@ -42,7 +42,7 @@
/datum/event/rogue_drone/end()
var/num_recovered = 0
for(var/mob/living/simple_animal/hostile/retaliate/malf_drone/D in drones_list)
for(var/mob/living/simple_animal/hostile/malf_drone/D in drones_list)
var/datum/effect/effect/system/spark_spread/sparks = new /datum/effect/effect/system/spark_spread()
sparks.set_up(3, 0, D.loc)
sparks.start()

View File

@@ -11,7 +11,7 @@
description_fluff = "Lucky Stars were created on Venus by a researcher seeking to make a good quality cigarette from pod-based tobacco plants. The researcher only managed to make these, but made quite a profit off of them when she started her company."
/obj/item/weapon/storage/fancy/cigarettes/jerichos
description_fluff = "Hephaistos Industries ex-military employees once decided to make a cigarette that was easy to light and had a waterproof case, specifically tailored for soldiers. They created Jerichos. Jerichos are known for their Hickory smoke and warm feeling in your lungs. They are loved by soldiers and people employed in para-military outfits."
description_fluff = "Hephaestus Industries ex-military employees once decided to make a cigarette that was easy to light and had a waterproof case, specifically tailored for soldiers. They created Jerichos. Jerichos are known for their Hickory smoke and warm feeling in your lungs. They are loved by soldiers and people employed in para-military outfits."
/obj/item/weapon/storage/fancy/cigarettes/menthols
description_fluff = "The Temperamento Menthol Company is a large cigarette company based in Mars. They have been around since the very dawn of Human colonization and have remained a favorite for those seeking a more.. numbing cigarette.<br>\

View File

@@ -0,0 +1,217 @@
/client/proc/recipe_dump()
set name = "Generate Recipe Dump"
set category = "Server"
set desc = "Dumps food and drink recipe info and images for wiki or other use."
if(!holder)
return
//////////////////////// DRINK
var/list/drink_recipes = list()
for(var/path in typesof(/datum/chemical_reaction/drinks) - /datum/chemical_reaction/drinks)
var/datum/chemical_reaction/drinks/CR = new path()
drink_recipes[path] = list("Result" = CR.name,
"ResAmt" = CR.result_amount,
"Reagents" = CR.required_reagents)
qdel(CR)
//////////////////////// FOOD
var/list/food_recipes = typesof(/datum/recipe) - /datum/recipe
//Build a useful list
for(var/Rp in food_recipes)
//Lists don't work with datum-stealing no-instance initial() so we have to.
var/datum/recipe/R = new Rp()
var/obj/res = new R.result()
var/icon/result_icon = icon(res.icon,res.icon_state)
result_icon.Scale(64,64)
food_recipes[Rp] = list(
"Result" = "[res.name]",
"ResAmt" = "1",
"Reagents" = R.reagents,
"Fruit" = R.fruit,
"Ingredients" = R.items,
"Image" = result_icon
)
qdel(res)
qdel(R)
//////////////////////// FOOD+ (basically condiments, tofu, cheese, soysauce, etc)
for(var/path in typesof(/datum/chemical_reaction/food) - /datum/chemical_reaction/food)
var/datum/chemical_reaction/food/CR = new path()
food_recipes[path] = list("Result" = CR.name,
"ResAmt" = CR.result_amount,
"Reagents" = CR.required_reagents,
"Fruit" = list(),
"Ingredients" = list(),
"Image" = null)
qdel(CR)
//////////////////////// PROCESSING
//Items needs further processing into human-readability.
for(var/Rp in food_recipes)
var/working_ing_list = list()
for(var/I in food_recipes[Rp]["Ingredients"])
var/atom/ing = new I()
//So now we add something like "Bread" = 3
if(ing.name in working_ing_list)
var/sofar = working_ing_list[ing.name]
working_ing_list[ing.name] = sofar+1
else
working_ing_list[ing.name] = 1
food_recipes[Rp]["Ingredients"] = working_ing_list
//Reagents can be resolved to nicer names as well
for(var/Rp in food_recipes)
for(var/rid in food_recipes[Rp]["Reagents"])
var/datum/reagent/Rd = chemical_reagents_list[rid]
var/R_name = Rd.name
var/amt = food_recipes[Rp]["Reagents"][rid]
food_recipes[Rp]["Reagents"] -= rid
food_recipes[Rp]["Reagents"][R_name] = amt
for(var/Rp in drink_recipes)
for(var/rid in drink_recipes[Rp]["Reagents"])
var/datum/reagent/Rd = chemical_reagents_list[rid]
var/R_name = Rd.name
var/amt = drink_recipes[Rp]["Reagents"][rid]
drink_recipes[Rp]["Reagents"] -= rid
drink_recipes[Rp]["Reagents"][R_name] = amt
//////////////////////// SORTING
var/list/foods_to_paths = list()
var/list/drinks_to_paths = list()
for(var/Rp in food_recipes)
foods_to_paths["[food_recipes[Rp]["Result"]] [Rp]"] = Rp //Append recipe datum path to keep uniqueness
for(var/Rp in drink_recipes)
drinks_to_paths["[drink_recipes[Rp]["Result"]] [Rp]"] = Rp
foods_to_paths = sortAssoc(foods_to_paths)
drinks_to_paths = sortAssoc(drinks_to_paths)
var/list/foods_newly_sorted = list()
var/list/drinks_newly_sorted = list()
for(var/Rr in foods_to_paths)
var/Rp = foods_to_paths[Rr]
foods_newly_sorted[Rp] = food_recipes[Rp]
for(var/Rr in drinks_to_paths)
var/Rp = drinks_to_paths[Rr]
drinks_newly_sorted[Rp] = drink_recipes[Rp]
food_recipes = foods_newly_sorted
drink_recipes = drinks_newly_sorted
//////////////////////// OUTPUT
//Food Output
var/html = "<head>\
<meta charset='utf-8'>\
<meta http-equiv='X-UA-Compatible' content='IE=edge'>\
<meta http-equiv='content-language' content='en-us' />\
<meta name='viewport' content='width=device-width, initial-scale=1'>\
<title>Food Recipes</title>\
<link rel='stylesheet' href='food.css' />\
</head>"
html += "<html><body><h3>Food Recipes (as of [time2text(world.realtime,"MMM DD, YYYY")])</h3><br>"
html += "<table class='recipes'>"
html += "<tr><th>Icon</th><th>Name</th><th>Ingredients</th></tr>"
for(var/Rp in food_recipes)
//Open this row
html += "<tr>"
//Image
var/icon/icon_to_give = food_recipes[Rp]["Image"]
if(icon_to_give)
var/image_path = "recipe-[ckey(food_recipes[Rp]["Result"])].png"
html += "<td><img src='imgrecipes/[image_path]' /></td>"
src << browse(icon_to_give, "window=picture;file=[image_path];display=0")
else
html += "<td>No<br>Image</td>"
//Name
html += "<td><b>[food_recipes[Rp]["Result"]]</b></td>"
//Ingredients
html += "<td><ul>"
var/count //For those commas. Not sure of a great other way to do it.
//For each large ingredient
var/pretty_ing = ""
count = 0
for(var/ing in food_recipes[Rp]["Ingredients"])
pretty_ing += "[count == 0 ? "" : ", "][food_recipes[Rp]["Ingredients"][ing]]x [ing]"
count++
if(pretty_ing != "")
html += "<li><b>Ingredients:</b> [pretty_ing]</li>"
//For each fruit
var/pretty_fru = ""
count = 0
for(var/fru in food_recipes[Rp]["Fruit"])
pretty_fru += "[count == 0 ? "" : ", "][food_recipes[Rp]["Fruit"][fru]]x [fru]"
count++
if(pretty_fru != "")
html += "<li><b>Fruit:</b> [pretty_fru]</li>"
//For each reagent
var/pretty_rea = ""
count = 0
for(var/rea in food_recipes[Rp]["Reagents"])
pretty_rea += "[count == 0 ? "" : ", "][food_recipes[Rp]["Reagents"][rea]]u [rea]"
count++
if(pretty_rea != "")
html += "<li><b>Mix in:</b> [pretty_rea]</li>"
//Close ingredients
html += "</ul></td>"
//Close this row
html += "</tr>"
html += "</table></body></html>"
src << browse(html, "window=recipes;file=recipes_food.html;display=0")
//Drink Output
html = "<head>\
<meta charset='utf-8'>\
<meta http-equiv='X-UA-Compatible' content='IE=edge'>\
<meta http-equiv='content-language' content='en-us' />\
<meta name='viewport' content='width=device-width, initial-scale=1'>\
<title>Drink Recipes</title>\
<link rel='stylesheet' href='drinks.css' />\
</head>"
html += "<html><body><h3>Drink Recipes (as of [time2text(world.realtime,"MMM DD, YYYY")])</h3><br>"
html += "<table class='recipes'>"
html += "<tr><th>Name</th><th>Ingredients</th></tr>"
for(var/Rp in drink_recipes)
//Open this row
html += "<tr>"
//Name
html += "<td><b>[drink_recipes[Rp]["Result"]]</b></td>"
html += "<td>"
//For each reagent
var/pretty_rea = ""
var/count = 0
for(var/rea in drink_recipes[Rp]["Reagents"])
pretty_rea += "[count == 0 ? "" : ", "][drink_recipes[Rp]["Reagents"][rea]]u [rea]"
count++
if(pretty_rea != "")
html += "<li><b>Mix together:</b> [pretty_rea]</li>"
html += "<li>Makes [drink_recipes[Rp]["ResAmt"]]u</li>"
//Close reagents
html += "</ul></td>"
//Close this row
html += "</tr>"
html += "</table></body></html>"
src << browse(html, "window=recipes;file=recipes_drinks.html;display=0")
src << "<span class='notice'>In your byond cache, recipe-xxx.png files and recipes_drinks.html and recipes_food.html now exist. Place recipe-xxx.png files in a subfolder named 'imgrecipes' wherever you put them. The file will take a food.css or drinks.css file if in the same path.</span>"

View File

@@ -105,7 +105,7 @@ I said no!
/datum/recipe/xenoburger
items = list(
/obj/item/weapon/reagent_containers/food/snacks/bun,
/obj/item/weapon/reagent_containers/food/snacks/xenomeat
/obj/item/weapon/reagent_containers/food/snacks/spidermeat // /obj/item/weapon/reagent_containers/food/snacks/xenomeat
)
result = /obj/item/weapon/reagent_containers/food/snacks/xenoburger
@@ -224,9 +224,9 @@ I said no!
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/xenomeat,
/obj/item/weapon/reagent_containers/food/snacks/xenomeat,
/obj/item/weapon/reagent_containers/food/snacks/xenomeat,
/obj/item/weapon/reagent_containers/food/snacks/spidermeat, //xenomeat,
/obj/item/weapon/reagent_containers/food/snacks/spidermeat, //xenomeat,
/obj/item/weapon/reagent_containers/food/snacks/spidermeat, //xenomeat,
/obj/item/weapon/reagent_containers/food/snacks/cheesewedge,
/obj/item/weapon/reagent_containers/food/snacks/cheesewedge,
/obj/item/weapon/reagent_containers/food/snacks/cheesewedge,
@@ -621,8 +621,8 @@ I said no!
/datum/recipe/sandwich
items = list(
/obj/item/weapon/reagent_containers/food/snacks/meatsteak,
/obj/item/weapon/reagent_containers/food/snacks/breadslice,
/obj/item/weapon/reagent_containers/food/snacks/breadslice,
/obj/item/weapon/reagent_containers/food/snacks/slice/bread,
/obj/item/weapon/reagent_containers/food/snacks/slice/bread,
/obj/item/weapon/reagent_containers/food/snacks/cheesewedge,
)
result = /obj/item/weapon/reagent_containers/food/snacks/sandwich
@@ -635,8 +635,8 @@ I said no!
/datum/recipe/grilledcheese
items = list(
/obj/item/weapon/reagent_containers/food/snacks/breadslice,
/obj/item/weapon/reagent_containers/food/snacks/breadslice,
/obj/item/weapon/reagent_containers/food/snacks/slice/bread,
/obj/item/weapon/reagent_containers/food/snacks/slice/bread,
/obj/item/weapon/reagent_containers/food/snacks/cheesewedge,
)
result = /obj/item/weapon/reagent_containers/food/snacks/grilledcheese
@@ -663,14 +663,14 @@ I said no!
/datum/recipe/slimetoast
reagents = list("slimejelly" = 5)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/breadslice,
/obj/item/weapon/reagent_containers/food/snacks/slice/bread,
)
result = /obj/item/weapon/reagent_containers/food/snacks/jelliedtoast/slime
/datum/recipe/jelliedtoast
reagents = list("cherryjelly" = 5)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/breadslice,
/obj/item/weapon/reagent_containers/food/snacks/slice/bread,
)
result = /obj/item/weapon/reagent_containers/food/snacks/jelliedtoast/cherry
@@ -783,24 +783,24 @@ I said no!
/datum/recipe/twobread
reagents = list("wine" = 5)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/breadslice,
/obj/item/weapon/reagent_containers/food/snacks/breadslice,
/obj/item/weapon/reagent_containers/food/snacks/slice/bread,
/obj/item/weapon/reagent_containers/food/snacks/slice/bread,
)
result = /obj/item/weapon/reagent_containers/food/snacks/twobread
/datum/recipe/slimesandwich
reagents = list("slimejelly" = 5)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/breadslice,
/obj/item/weapon/reagent_containers/food/snacks/breadslice,
/obj/item/weapon/reagent_containers/food/snacks/slice/bread,
/obj/item/weapon/reagent_containers/food/snacks/slice/bread,
)
result = /obj/item/weapon/reagent_containers/food/snacks/jellysandwich/slime
/datum/recipe/cherrysandwich
reagents = list("cherryjelly" = 5)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/breadslice,
/obj/item/weapon/reagent_containers/food/snacks/breadslice,
/obj/item/weapon/reagent_containers/food/snacks/slice/bread,
/obj/item/weapon/reagent_containers/food/snacks/slice/bread,
)
result = /obj/item/weapon/reagent_containers/food/snacks/jellysandwich/cherry

View File

@@ -114,8 +114,11 @@
if(!target_limb) target_limb = pick(BP_ALL)
var/blocked = target.run_armor_check(target_limb, "melee")
var/soaked = target.get_armor_soak(target_limb, "melee")
if(blocked >= 100)
return
var/obj/item/organ/external/affecting = target.get_organ(target_limb)
var/damage = 0
var/has_edge = 0
@@ -125,7 +128,7 @@
if(affecting)
to_chat(target, "<span class='danger'>\The [fruit]'s thorns pierce your [affecting.name] greedily!</span>")
target.apply_damage(damage, BRUTE, target_limb, blocked, "Thorns", sharp=1, edge=has_edge)
target.apply_damage(damage, BRUTE, target_limb, blocked, soaked, "Thorns", sharp=1, edge=has_edge)
else
to_chat(target, "<span class='danger'>\The [fruit]'s thorns pierce your flesh greedily!</span>")
target.adjustBruteLoss(damage)

View File

@@ -184,7 +184,7 @@
display_name = "killer tomato plant"
mutants = null
can_self_harvest = 1
has_mob_product = /mob/living/simple_animal/tomato
has_mob_product = /mob/living/simple_animal/hostile/tomato
/datum/seed/tomato/killer/New()
..()

View File

@@ -11,6 +11,7 @@
used for power or data transmission."
icon = 'icons/obj/electronic_assemblies.dmi'
icon_state = "wirer-wire"
item_state = "wirer"
flags = CONDUCT
w_class = 2
var/datum/integrated_io/selected_io = null

View File

@@ -0,0 +1,139 @@
// Inherits from /book/ so it can fit on bookshelves.
/obj/item/weapon/book/codex
name = "The Traveler's Guide to Human Space: Vir Edition"
desc = "Contains useful information about the world around you. It seems to have been written for travelers to Vir, human or not. It also \
has the words 'Don't Panic' in small, friendly letters on the cover."
icon_state = "codex"
unique = TRUE
var/datum/lore/codex/home = null // Top-most page.
var/datum/lore/codex/current_page = null // Current page or category to display to the user.
var/list/indexed_pages = list() // Assoc list with search terms pointing to a ref of the page. It's created on New().
var/list/history = list() // List of pages we previously visited.
/obj/item/weapon/book/codex/initialize()
..()
generate_pages()
/obj/item/weapon/book/codex/proc/generate_pages()
home = new /datum/lore/codex/category/main(src) // This will also generate the others.
current_page = home
indexed_pages = current_page.index_page()
// Changes current_page to its parent, assuming one exists.
/obj/item/weapon/book/codex/proc/go_to_parent()
if(current_page && current_page.parent)
current_page = current_page.parent
// Changes current_page to a specific page or category.
/obj/item/weapon/book/codex/proc/go_to_page(var/datum/lore/codex/new_page, var/dont_record_history = FALSE)
if(new_page) // Make sure we're not going to a null page for whatever reason.
current_page = new_page
if(!dont_record_history)
history.Add(new_page)
/obj/item/weapon/book/codex/proc/quick_link(var/search_word)
for(var/word in indexed_pages)
if(lowertext(search_word) == lowertext(word)) // Exact matches unfortunately limit our ability to perform SEOs.
go_to_page(indexed_pages[word])
return
// Returns to the last visited page, based on the history list.
/obj/item/weapon/book/codex/proc/go_back()
if(history.len - 1)
if(history[history.len] == current_page)
history.len-- // This gets rid of the current page in the history.
go_to_page(pop(history), dont_record_history = TRUE) // Where as this will get us the previous page that we want to go to.
/obj/item/weapon/book/codex/proc/get_tree_position()
if(current_page)
var/output = ""
var/datum/lore/codex/checked = current_page
output = "<b>[checked.name]</b>"
while(checked.parent)
output = "<a href='?src=\ref[src];target=\ref[checked.parent]'>[checked.parent.name]</a> \> [output]"
checked = checked.parent
return output
/obj/item/weapon/book/codex/proc/make_search_bar()
var/html = {"
<form id="submitForm" action="?">
<input type = 'hidden' name = 'src' value = '\ref[src]'>
<input type = 'hidden' name = 'action' value='search'>
<label for = 'search_query'>Page Search: </label>
<input type = 'text' name = 'search_query' id = 'search_query'>
<input type = 'submit' value = 'Go'>
</form>
"}
return html
/obj/item/weapon/book/codex/attack_self(mob/user)
display(user)
/obj/item/weapon/book/codex/proc/display(mob/user)
icon_state = "[initial(icon_state)]-open"
if(!current_page)
generate_pages()
//"common", 'html/browser/common.css'
user << browse_rsc('html/browser/codex.css', "codex.css")
var/dat
dat = "<head>"
dat += "<title>[src.name] ([current_page.name])</title>"
dat += "<link rel='stylesheet' href='codex.css' />"
dat += "</head>"
dat += "<body>"
dat += "[get_tree_position()]<br>"
dat += "[make_search_bar()]<br>"
dat += "<center>"
dat += "<h2>[current_page.name]</h2>"
dat += "<br>"
if(current_page.data)
dat += "[current_page.data]<br>"
dat += "<br>"
if(istype(current_page, /datum/lore/codex/category))
dat += "<div class='button-group'>"
// dat += "<ul>"
var/datum/lore/codex/category/C = current_page
for(var/datum/lore/codex/child in C.children)
// dat += "<a href='?src=\ref[src];target=\ref[child];class=button'>[child.name]</a><br>" // Todo, change into pretty CSS buttons.
dat += "<a href='?src=\ref[src];target=\ref[child]' class='button'>[child.name]</a>"
// dat += "</ul>"
dat += "</div>"
dat += "<hr>"
if(history.len - 1)
dat += "<br><a href='?src=\ref[src];go_back=1'>\[Go Back\]</a>"
if(current_page.parent)
dat += "<br><a href='?src=\ref[src];go_to_parent=1'>\[Go Up\]</a>"
if(current_page != home)
dat += "<br><a href='?src=\ref[src];go_to_home=1'>\[Go To Home\]</a>"
dat += "</center></body>"
user << browse(dat, "window=the_empress_protects;size=600x550")
onclose(user, "the_empress_protects", src)
/obj/item/weapon/book/codex/Topic(href, href_list)
. = ..()
if(.)
return
if(href_list["target"]) // Direct link, using a ref
var/datum/lore/codex/new_page = locate(href_list["target"])
go_to_page(new_page)
else if(href_list["search_query"])
quick_link(href_list["search_query"])
else if(href_list["go_to_parent"])
go_to_parent()
else if(href_list["go_back"])
go_back()
else if(href_list["go_to_home"])
go_to_page(home)
else if(href_list["quick_link"]) // Indirect link, using a (hopefully) indexed word.
quick_link(href_list["quick_link"])
else if(href_list["close"])
icon_state = initial(icon_state)
usr << browse(null, "window=the_empress_protects")
return
display(usr)

View File

@@ -0,0 +1,129 @@
/datum/lore/codex/category/important_locations
name = "Important Locations"
data = "There are several locations of interest that you may come across when visiting the system Vir."
children = list(
/datum/lore/codex/page/vir,
/datum/lore/codex/page/radiance_energy_chain,
/datum/lore/codex/page/firnir,
/datum/lore/codex/page/tyr,
/datum/lore/codex/page/sif,
/datum/lore/codex/page/vir_interstellar_spaceport,
/datum/lore/codex/page/southern_cross,
/datum/lore/codex/page/magni,
/datum/lore/codex/page/kara,
/datum/lore/codex/page/northern_star,
/datum/lore/codex/page/rota
)
/datum/lore/codex/page/vir/add_content()
name = "Vir (Star)"
keywords += list("Vir")
data = "Vir is an A-type main sequence star with 81% more mass than Sol (the humans' home star), and almost nine times as bright. It \
has a white glow, and a diameter that is about 34% larger than Sol. It has six major planets in its orbit.\
<br><br>\
Vir is mainly administered on [quick_link("Sif")] by the [quick_link("Sif Governmental Authority")], as Sif \
was the first planet to be colonized, however SGA lays claim to all planets orbiting Vir. The planets \
are named after figures in ancient human mythology (Norse), due to the original surveyor for the system deciding to do so. \
Some installations carry on this tradition."
/datum/lore/codex/page/radiance_energy_chain/add_content()
name = "Radiance Energy Chain (Artificial Satellites)"
keywords += list("Radiance Energy Chain")
data = "A sparse government-owned chain of automated stations exists between Firnir and the star itself. The idea is based on \
an ancient design that was pioneered at Sol. The stations are heavily shielded from the stellar radiation, and feature massive \
arrays of photo-voltaic panels. Each station harvests energy from Vir using the solar panels, and sends it to other areas of \
the system by beaming the energy to several relay stations farther away from the star, typically with a large laser.\
<br><br>\
These stations are generally devoid of life, instead, they are operated mainly by [quick_link("drones")], with maintenance performed \
by [quick_link("positronic")] equipped units in shielded chassis, or very brave humans in voidsuits that protect from extreme heat, and radiation. There are \
currently 19 stations in operation."
/datum/lore/codex/page/firnir/add_content()
name = "Firnir (Terrestrial Planet)"
keywords += list("Firnir")
data = "Firnir is the first planet of Vir, tidally locked to it, and having temperatures in excess of 570 degrees \
kelvin (299<39>C) on the day side has caused this planet to go mostly ignored."
/datum/lore/codex/page/tyr/add_content()
name = "Tyr (Terrestrial Planet)"
keywords += list("Tyr")
data = "The second closest planet to [quick_link("Vir")], this planet has a high concentration of minerals inside its crust, as well as active volcanism and plate tectonics. \
The temperature on the surface can reach up to 405 degrees kelvin (132<33>C), which has deterred most people from the planet, except for two [quick_link("TSC", "TSCs")], \
Greyson Manufactories and [quick_link("Xion Manufacturing Group")]. In orbit, the two companies each have a space station, used to coordinate and \
control their stations on the surface without having to suffer the intense heat. Xion's station also doubles as a control and oversight facility for their \
[quick_link("drones","autonomous mining drones")].\
<br><br>\
Remnants of both Greyson and Xion's mining operations dot the surface, as well as ruins of mining \
outposts build by an unknown alien civilization, which researchers have noted it appears to be similar to ruins found inside the rings of [quick_link("Kara")] \
and on [quick_link("Sif")] itself. Below the surface of Tyr are many natural cave systems, dangerous and easy to get lost inside, which both companies make heavy \
use of. A noted rivalry exists between the two mining giants, as well as with smaller groups more interested in the xenoarcheological value of the alien ruins.\
<br><br>\
The very high temperatures, dangerous (sometimes magma-filled) caves, and the only presence of civilization being mining operations has made tourism \
for Tyr mostly non-existent, with the exception of explorers who specifically seek out hellish landscapes, which are plentiful with all the ruins, \
volcanoes, twisting caves, and general lawlessness. The occasional remains of previous explorers near certain hotspots somehow does not deter them."
/datum/lore/codex/page/sif/add_content()
name = "Sif (Terrestrial Planet)"
keywords += list("Sif")
data = "Sif is a terrestrial planet and third closest planet to Vir. It possesses oceans, a breathable atmosphere, \
a magnetic field, weather, and acceptable gravity. It is currently the capital planet of Vir. Its center of government is the \
equatorial city and site of the first settlement, New Reykjavik, which houses the [quick_link("Sif Governmental Authority")].\
<br><br>\
Sif has many desirable traits which made it the first planet to be colonized in Vir, however it also has various quirks which \
may disorient humans used to conditions on planet Earth. Atmospheric pressure is lower than 'normal', which may cause difficulty \
breathing if you are used to climate controlled artifical habitats or higher pressure planets. The gravity is also slightly lower, at \
only 90% the strength of planet Earth's gravity. You may need to keep two clocks if you plan to visit \
or live on Sif, as the planet takes over 32 hours to complete one day. A Sif year also takes just under five Earth years."
/datum/lore/codex/page/vir_interstellar_spaceport/add_content()
name = "Vir Interstellar Spaceport (Artificial Satellite)"
keywords += list("Vir Interstellar Spaceport")
data = "The Vir Interstellar Spaceport is a large facility in orbit of the planet [quick_link("Sif")] which handles the loading and \
unloading, refuelling, and general maintenance of large spacecraft. The main structure is owned by the \
[quick_link("Sif Governmental Authority")], but individual offices, docking/loading bays, and warehouses are often leased to individuals \
or organisations. The position of the spaceport allows it to function not only as a key node for transport inside the Vir \
system, especially to and from the planet Sif, but also as a key stopping point interstellar craft travelling via Vir which need refuelling. \
<br><br>\
The station itself is mostly designed around its logistical and commercial needs, and although other strategically-placed \
nearby facilities owned by a mixture of corporations and entities may possess habitation space, the port itself is not \
designed to be a living habitat - its proximity to the surface of Sif makes transport of people and materials to and from \
the facility and the planet via shuttle extremely cost-efficient."
/datum/lore/codex/page/southern_cross/add_content()
name = "Southern Cross (Artificial Satellite)"
keywords += list("Southern Cross")
data = "The Southern Cross is a telecommunications and supply hub for [quick_link("NanoTrasen")], named after it's companion satellite, the \
[quick_link("Northern Star")]. It acts as a logistics hub for the smaller installations NanoTrasen has in Sif orbit and on the surface."
/datum/lore/codex/page/magni/add_content()
name = "Magni (Terrestrial Planet)"
keywords += list("Magni")
data = "Outside of the habitable zone, the barren world Magni is generally at 202 kelvin (-71<37>C)."
/datum/lore/codex/page/kara/add_content()
name = "Kara (Gas Giant)"
keywords += list("Kara")
data = "A gas giant, with a large number of moons. Captured asteroids, to be specific. Many of the asteroids are theorized \
to be the remnants of a much larger moon that was ripped apart by Kara, long ago. Curerntly, a large number of these \
asteroids are being used by many different businesses, and some governmental infrastructure has been built. The most prominent \
asteroid installation is the [quick_link("Northern Star", "NCS Northern Star")], a general purpose colony owned and operated by \
[quick_link("NanoTrasen")]. The mid-atmospheric temperature of the gas giant averages to around 150 kelvin (-108<30>C)."
/datum/lore/codex/page/northern_star/add_content()
name = "Northern Star (Artificial Satellite)"
keywords += list("Northern Star", "NCS Northern Star")
data = "One of the most prominent installations in the [quick_link("Kara")] subsystem, the Northern Star is owned \
and operated by [quick_link("NanoTrasen")]. It was originally built to service the various mining operations \
occurring within Kara's ring, however it has grown into what it is today due to what was discovered inside \
the interior of the rock. Both phoron and alien artifacts were found inside, catapulting the asteroid outpost \
into the main attraction inside the subsystem.\
<br><br>\
Today it houses a population of civilians, whom work to maintain \
the colony and support the local mining industry. The colony also has managed to achieve a degree of \
self-sufficiency, and possesses many amenities and features that most other asteroid bases in the \
subsystem lack."
/datum/lore/codex/page/rota/add_content()
name = "Rota (Gas Giant)"
keywords += list("Rota")
data = "An ice giant, with a beautiful ring system circling it. The average temperature for it is 165 kelvin (-157<35>C)."

View File

@@ -0,0 +1,35 @@
// Pulls data from organizations data
/datum/lore/codex/category/auto_org
var/desired_type = null // Exclude other types of organizations
/datum/lore/codex/category/auto_org/New(var/new_holder, var/new_parent)
..(new_holder, new_parent)
for(var/path in loremaster.organizations)
var/datum/lore/organization/O = loremaster.organizations[path]
if(!(istype(O, desired_type)))
continue
var/datum/lore/codex/page/P = new(holder, src)
if(!O.name) // Probably the base type, don't make a page for it.
continue
P.name = O.name
P.keywords.Add(O.name, O.short_name)
if(O.acronym)
P.keywords.Add(O.acronym)
P.data = O.desc
children.Add(P)
/datum/lore/codex/category/auto_org/tsc
name = "Trans-Stellar Corporations"
data = "By definition, TSCs are companies which span multiple star systems, however the term is generally reserved for \
the biggest and most influential of them all. Some people also categorize the different TSCs into 'major' and 'minor' TSCs."
desired_type = /datum/lore/organization/tsc
/datum/lore/codex/category/auto_org/gov
name = "Governments"
desired_type = /datum/lore/organization/gov
/*
/datum/lore/codex/category/auto_org/mil
name = "Militaries"
desired_type = /datum/lore/organization/mil
*/

View File

@@ -0,0 +1,99 @@
/datum/lore/codex/category/political_factions
name = "Political Factions"
data = "Those wishing to immigrate to somewhere in Vir, or otherwise plan to stay for a long time should get to know human politics. \
There are presently three major political parties that exist throughout SolGov space, being the Icarus Front, the Shadow Coalition, and \
the Sol Economic Organization, and several smaller ones which tend to align themselves among one of the major parties. In the Vir system, the \
Icarus Front's influence is much less than somewhere closer to Sol, and the other two parties being more popular."
children = list(
/datum/lore/codex/page/icarus_front,
/datum/lore/codex/page/shadow_coalition,
/datum/lore/codex/page/sol_economic_organization,
/datum/lore/codex/page/mercurials,
/datum/lore/codex/page/positronic_rights_group,
/datum/lore/codex/page/church_of_unitarian_god,
/datum/lore/codex/page/friends_of_ned,
/datum/lore/codex/page/multinational_movement,
/datum/lore/codex/page/free_trade_union,
)
/datum/lore/codex/page/icarus_front/add_content()
name = "Icarus Front"
keywords += list("Icarus", "IF")
data = "The political group with the most seats in the [quick_link("SolGov")] legislature and control over the heartworlds of humanity, the Icarus Front is a \
conservative body with a long history, tracing its linage back to the political unrest that created the Sol Confederate Government. Icarus calls \
for severe restrictions on \"transformative technologies\" any technology with the power to fundamentally alter humanity, such as advanced artificial \
intelligence and human genetic augmentation. Previously an unbeatable political force, recent changes have lead to its power backsliding. It remains a \
popular party among those from Sol, Tau Ceti, and other heavily settled systems."
/datum/lore/codex/page/shadow_coalition/add_content()
name = "Shadow Coalition"
data = "A disorganized liberal party, originating in an anti-[quick_link("Icarus")] shadow government. 'Shadow' in this case, refers to acting as an opposition \
party to the Icarus majority. The Shadow Coalition calls for the lifting of certain Icarus-restricted technologies, especially medical \
technologies with the ability to drastically improve quality of life. While fractious and prone to infighting, the Shadow Coalition and affiliated \
parties remain the most popular political groups in the large towns and small cities of humanity, including Vir."
/datum/lore/codex/page/sol_economic_organization/add_content()
name = "Sol Economic Organization"
keywords += list("SEO")
data = "The newest force in [quick_link("SolGov")] politics, backed by the massive [quick_link("TSC", "Trans-Stellar Corporations")] and the [quick_link("Free Trade Union")], \
as well as former [quick_link("Icarus")] warhawks. The SEO campaigns for minimal regulation on the development of new technologies, seeing them as anti-capitalist and \
inefficient, and have gained significant traction among futurists, those wishing for a more impressive human military, and employee-residents of TSC \
corporate towns, such as the [quick_link("Northern Star")].\
<br><br>\
[quick_link("Nanotrasen")], a R&D firm, is generally regarded as the most enthusiastic supporter of the SEO. Other contributing TSCs include the next six largest corporations \
in human space: "+quick_link(TSC_WT)+" GMC, "+TSC_GIL+" Exports, Grayson Manufacturing Ltd., Aether Atmospherics and Recycling, [quick_link("Zeng-Hu Pharmaceuticals")] and "+TSC_HEPH+" \
Industries, as well as, notably, [quick_link("Vey-Med")]. The Free Trade Union's participation in the SEO is a contentious issue that many of its members disagree with, but \
most FTU representatives caucus with the SEO."
/datum/lore/codex/page/mercurials/add_content()
name = "Mercurials"
keywords += list("Mercurial")
data = "[quick_link("Positronics")] and the rare augmented human who want to follow a different cultural path from the rest of humanity, viewing themselves as fundamentally \
separate from unaugmented biological humans. Previously an illegal movement, proscribed due to the preceived dangers of unfettered self-modification and the threat \
posed by positronics without human values in mind, self-described Mercurials still often find themselves persecuted or used by bioconservatives as scapegoats \
and 'boogiemen'. As a technoprogressive group, they tend to vote along with the [quick_link("Shadow Coalition")]."
/datum/lore/codex/page/positronic_rights_group/add_content()
name = "Positronic Rights Group"
keywords += list("PRG")
data = "The other side of the coin from the [quick_link("Mercurials")], the PRG wants full integration of [quick_link("positronics")] into human society, with equal wages, opportunities \
to advancement, and representation in the media. Their current pet cause is a tax credit for humans who wish to adopt or sponsor the creation of a positronic, \
a measure supported due to its potential to counteract the aging positronic population and to bring the average positronic closer to human culture. They tend to vote \
along with the [quick_link("Shadow Coalition")], due to being technoprogressive."
/datum/lore/codex/page/church_of_unitarian_god
name = "The Church of the Unitarian God"
keywords = list("Unitarian Church")
data = "An often-imperfect fusion of various human religions such as Christianity, Islam, and Judaism, the Unitarian Church represents the dim voice of \
religion in a time of increased atheism. With the threat of singularity looming once more, their power is increasing with more converts and more donations, \
and they use this power to protect the fundamental human soul from corruption by dangerous technologies and to spread their faith among aliens and positronics, \
who they view as fellow children of God. They tend to side with bioconservatives."
/datum/lore/codex/page/friends_of_ned/add_content()
name = "Friends of Ned"
keywords += list("Ned")
data = "The metaphorical reincarnation of a human named Ned Ludd's original Luddites, disdaining that name's negative connotations and embracing their original \
purpose-- the restriction of technology that poses a threat to people's livelihoods. In addition to [quick_link("Icarus Front")] technological restrictions, the Friends demand \
the complete prohibition of [quick_link("Drone", "drone intelligence and AGI research")], with most also opposing the [quick_link("FTU", "FTU's")] plans for wide spread \
nanofabrication deployment. While the party refrains from making a definitive statement on their view of [quick_link("positronics")], many Friends have taken it upon themselves to label \
them \"anti-labor technology\", and nominally-unsanctioned lynchings have marred the faction's reputation."
/datum/lore/codex/page/multinational_movement/add_content()
name = "Multinational Movement"
keywords += list("Multinational")
data = "The barely-unified voice of [quick_link("SolGov", "SolGov's")] various independence movements, encompassing Terran governments wishing for a lighter touch \
from SolGov, fringe colonies who balk at the call of distant masters, anarchist movements who want the freedom to live without government oversight, and the rare \
Trans-Stellar who no longer see a benefit in working with SolGov. Full colonial independence is still a political impossibility so long as the \
[quick_link("Icarus Front")] holds any sway, and so the Movement is focused primarily on securing more autonomy in governance, although a growing revolutionary sub-group \
wants to force their change on the government en masse. The Multinational Movement finds themselves in an uneasy alliance with the [quick_link("SEO")], connected by their corporate, \
fringe-system membership, and often provide a dissenting voice to SEO's war hawks."
/datum/lore/codex/page/free_trade_union/add_content()
name = "Free Trade Union"
keywords += list("FTU")
data = "A softer counterpoint to the [quick_link("SEO")], the FTU is a party representing small businesses, workers' syndicates, and trade unions, who advocate for government \
measures to reduce the amount of power held by the TSCs. In many ways a holdover from the days before the [quick_link("Shadow Coalition")], where corporate malfeasance took \
the place of technological development as the primary issue of debate, the FTU has found itself adopting technological positions similar to the SEO as a matter \
of pragmatism, although the views of individual members vary. The FTU is known for their intense lobbying of SolGov to add tax rebates to the purchases of \
personal lathes and the creation of open-source firmware for experimental autolathes, but have thus far found little success."

View File

@@ -0,0 +1,301 @@
/datum/lore/codex/category/species
name = "Species"
data = "There are many different types of lifeforms (both alive and artificial) in the galaxy, which you may find inside Vir."
children = list(
/datum/lore/codex/page/human,
/datum/lore/codex/page/skrell,
/datum/lore/codex/page/unathi,
/datum/lore/codex/page/tajaran,
/datum/lore/codex/page/diona,
/datum/lore/codex/category/teshari,
/datum/lore/codex/category/positronic,
/datum/lore/codex/category/drone
)
/datum/lore/codex/page/human/add_content()
name = "Human"
keywords += list("Humanity")
data = "Humans are a race of 'ape'-like creatures from the continental planet Earth in the Sol system. They are the primary driving \
force for rapid space expansion, owing to their strong, expansionist central government and opportunistic [quick_link("TSC","Trans-Stellar Corporations")]. \
The prejudices of their 21st century history have mostly given way to bitter divides on the most important issue of the times- technological \
expansionism.\
<br><br>\
While most humans have accepted the existence of aliens in their communities and workplaces as a fact of life, exceptions abound. \
While more culturally diverse than most species, humans are generally regarded as somewhat technophobic and isolationist by members \
of other species."
/datum/lore/codex/page/skrell
name = "Skrell"
keywords = list("Skrellian")
data = "The Skrell are a species of amphibious humanoids, distinguished by their gelatinous appearance and head tentacles. \
Skrell come from the world of Sirisai (called Qerr'balak by Skrell), a humid planet with plenty of swamps and jungles. Currently more technologically advanced \
than the humans, they emphasize the study of the mind above all else.\
<br><br>\
Gender has little meaning to Skrell outside of reproduction, and in fact many other species have a difficult time telling the difference \
between male and female Skrell apart. The most obvious signs (voice in a slightly higher register, longer head-tails for females) are never \
a guarantee. Due to their scientific focus of the mind and body, Skrell tend to be more peaceful and their colonization has been slow, swiftly \
outpaced by the humans. For humans, they were their first contact sentient species, and are their longest, and closest, ally in space."
/datum/lore/codex/page/unathi
name = "Unathi"
data = "The author wishes to apologize to the reader, as they currently lack enough knowledge of the Unathi to write about them, as they are \
rather rare inside Vir." // Replace this when Anewbe finishes the lizard rewrite.
/*
data = "Raging in from Moghes, the Unathi are a race of tall, reptilian humanoids that possess both crocodile-like and serpent-like features. \
They are a proud, warlike species that favors honor and strength, their home, Moghes, is a desert planet but was once believed to be full of life. \
Of all the currently known sentient species, the Unathi are the most unequal in gender with females tending to be property of the males. Most Unathi \
outside of Moghes tend to be exiles however, and with influence of other species the gender difference is not nearly as pronounced. Unathi were \
humanity's second contact, and despite their aggressive nature, seem to get along well enough with humanity, though are often considered to be \
'second-class' citizens and are rarely seen in jobs other than where muscle is needed." // This probably needs to be updated.
*/
/datum/lore/codex/page/tajaran
name = "Tajaran"
keywords = list("Tajara")
data = "The Tajara are a race of humanoid mammalian aliens from Meralar, the fourth planet of the Rarkajar star system. Thickly furred and protected \
from cold, they thrive on their subarctic planet, where the only terran temperate areas spread across the equator and tropical belt. \
With their own share of bloody wars and great technological advances, the Tajaran are a proud kind. They fiercely believe they belong \
among the stars and consider themselves a rightful interstellar nation, even if the humans helped them to actually achieve superluminal \
speeds with Bluespace FTL drives. Relatively new to the galactic stage, their contacts with other species are aloof, but friendly. \
Among these bonds, Humans stand out as valued trade partners and maybe even a friend."
/datum/lore/codex/page/diona/add_content()
name = "Diona"
keywords += list("Dionaea")
data = "The Dionaea are a group of omnivorous, slow-metabolism plantlike organisms that are in fact clusters of individual, smaller organisms. \
They exhibit a high degree of structural flexibility, and come in a wide variety of shapes and colors to reflect the intelligence of each individual \
creature. They were discovered by the [quick_link("Skrell")] in 2294CE, not on a planet, but in open space between three stars, a figurative hell that made it \
difficult to discover, much less contact them.\
<br><br>\
Dionaea spread by seeds and are asexual, no gender. When grown into their small 'nymph' state, they are known to eat large amounts of dead plant \
matter and fertilize plants while they learn from those around them, and as they grow further, they merge into larger and larger forms. It is not \
unheard of for Skrell explorers to be traveling in a ship composed of habitat modules and engines of Skrell design and the body formed by their \
Diona allies to warble across the cosmos.\
<br><br>\
Introduced by the Skrell, and quite slow and peaceful, the Diona share good relations with the other species."
// Bird lore
/datum/lore/codex/category/teshari/add_content()
name = "Teshari"
data = "The Teshari are reptilian pack predators from the [quick_link("Skrell")] homeworld, Sirisai (Qerr'balak). While they evolved alongside the Skrell, their interactions with them \
tended to be confused and violent, and until peaceful contact was made they largely stayed in their territories on and around the poles, in tundral \
terrain far too desolate and cold to be of interest to the Skrell. In more enlightened times, the Teshari are a minority culture on many Skrell worlds, \
maintaining their own settlements and cultures, but often finding themselves standing on the shoulders of their more technologically advanced neighbors \
when it comes to meeting and exploring the rest of the galaxy.\
<br><br>\
It is important to note that Teshari names are unlike standard human names. Their pack name precedes their given name."
children = list(
/datum/lore/codex/page/teshari_packs,
/datum/lore/codex/page/teshari_physical
)
/datum/lore/codex/page/teshari_packs/add_content()
name = "Teshari Packs"
keywords += list("Packs")
data = "There are several packs you may come across;<small>\
<br><br>\
<b>Eshi</b><br>\
A large, old, politically neutral pack heavily involved in efforts to get Teshari into space. Probably the most \
common pack to see outside of a [quick_link("Skrell")] colony, and probably the most numerous Teshari pack outside of Sirisai and associated colonies.\
<br><br>\
<b>Nasemari</b><br>\
A very small pack. Generally focused around supporting and providing for packs on the homeworlds, they have devoted \
themselves to training as technicians and engineers in order to obtain skills and training to take back to Sirisai. \
The pack is only around thirty people in size, but owns and maintains a nuclear power plant.\
<br><br>\
<b>Schasaraca</b><br>\
One of the more Skrell-devoted and integrated packs. They tend to be rather sycophantic towards the Skrell and work as \
scientists and field researchers on a variety of projects, generally biology or technical research. They have a reputation \
for working as spies and informants for the Skrell governments amongst other Teshari.\
<br><br>\
<b>Ceea</b><br>\
An isolationist pack from the northern tundra of Sirisai; generally known as disliking the Skrell. Small to average in size; \
only around sixty members. Their regional culture is built around the study culture and anthropology, as well as archaeology, \
originally for the purposes of recovering history and materials \"lost\" due to Skrell interference. It would be very rare to \
see them on your travels, however they are listed here for the sake of completeness.\
<br><br>\
<b>Resca</b><br>\
A pack that sold off its small native territory for the chance to get into space. Very musically inclined. They tend towards medical professions.</small>"
/datum/lore/codex/page/teshari_physical/add_content()
name = "Physiology of Teshari"
data = "The Teshari are, relative to other species, smaller than average, rarely reaching more than 2-3'/1m in height, and weigh less than \
90lbs/40kg. They have rapid metabolisms and very efficient digestive systems, and thanks to sharing in \
the medical technology of the [quick_link("Skrell")], they tend to have robust and effective immune systems. They evolved \
for very cold and very barren areas, generally the polar regions. Because of this, their skin is a fine \
insulator and many of their internal processes are not particularly energy-efficient; they cannot cope \
well at all with high temperatures.\
<br><br>\
Their hearing is exceptionally sensitive to the point that they can detect a person moving on the other \
side of a wall, but this comes at a cost. Very loud noises are very painful for Teshari, so be mindful of \
your indoor voice when speaking with one. The Teshari are omnivorous but generally prefer to eat meat wherever possible."
// Posi lore
/datum/lore/codex/category/positronic/add_content()
name = "Positronics"
keywords += list("Positronic", "Posi", "Posibrain", "Posibrains")
data = "A Positronic being, is an individual with a positronic brain, manufactured \
and fostered amongst organic life. Positronic brains enjoy the same legal status as a human in [quick_link("SolGov")] space, although discrimination is \
still prevalent, and are considered sapient on all accounts. They can be considered the \"synthetic species\". Half-developed and \
half-discovered in the 2280<38>s by a human black lab studying alien artifacts, the first positronic brain was an inch-wide cube \
of an palladium-iridium alloy, nano-etched with billions upon billions of conduits and connections. Upon activation, \
hard-booted with an emitter laser, the brain issued a single sentence before the neural pathways collapsed and \
it became an inert lump of platinum: \"What is my purpose?\"."
children = list(
/datum/lore/codex/page/positronic_brain_physical,
/datum/lore/codex/page/positronic_memory,
/datum/lore/codex/page/jans_fhriede
)
/datum/lore/codex/page/positronic_brain_physical
name = "Physical Structure of a Positronic Brain"
keywords = list("Physical Posibrain", "Physical Positronic")
data = "A positronic brain is a cube of complex metal alloy between two and six inches to a side. They usually weigh just under ten kilograms and are \
<b>very fragile</b> when exposed to the stresses of heat or cold, as well as physical trauma. The exterior surface is chased with a network of grooves, forming \
a maze of geometric patterns right down to the molecular level, and the interior is hollow; complex particle generators and densely packed computational \
arrays form the basis of a self-computing neural network, complex and somewhat poorly understood. Most modern positronic brains are equipped with \
standardized I/O ports, and all have some interface for imprinting."
/datum/lore/codex/page/positronic_memory
name = "Positronic Memory"
keywords = list("Posi Memory", "Memory")
data = "Positronic minds learn in a similar manner to humans and other forms of life, although typically more quickly. They are not simple computer storage that holds information \
verbatim as it is received- instead, they have to repeat activities and train in order to retain memory on complex tasks. Similarly, positronic brains do \
not have an infinite storage capacity and undergo a natural process of forgetting, albeit in a structured manner, losing unimportant day to day details and \
ancient information no longer deemed useful. Because of the nature of the positronic brain, its memories cannot simply be stored elsewhere.\
<br><br>\
Particularly old positronic minds, over a century plus, that store a great deal of memories have displayed a tendency to become gradually more introspective \
as more of their mind is co-opted for the task, ending in a state of near-catatonia as their neural networks become clogged with memory. Many choose to avoid \
this end of self by more aggressively managing their memories, storing a window of their recent existence and most treasured memories rather than their full lifespan."
/datum/lore/codex/page/jans_fhriede
name = "Jans-Fhriede Test"
keywords = list("Jans-Fhriede", "JF", "Jans", "Fhriede", "Jans Fhriede")
data = "Positronics are eligible to take the \"Jans-Fhriede Test\" after a year of being created, measuring their function in a society and judging if they act \
socially acceptable and are capable of understanding their actions and the consequences resulting from them. If they successfully pass the test, \
they are considered legal adults and hold the same basis of rights as a normal human. At that point, Positronics are not allowed to be lawed, \
unless on a contractual basis or otherwise under their own volition."
// Drone lore
/datum/lore/codex/category/drone
name = "Drones"
keywords = list("Drone")
data = "While low-level drone intelligences are as old as the oldest human colonies, research into higher-level systems was stymied in human space by precautionist \
politicians for hundreds of years. Tensions between the corporate rim and the highly conservative core worlds over drone proliferation led to what humans call the \
Third Cold War, which was defused by the introduction of the positronic brain. After the Icarus Front's loss of the majority in 2504, harsh laws \
against advanced AI were replaced with the SolGov Emergent Intelligence Oversight commission, the illegality replaced with a steeply sloping \
system of monetary costs.\
<br>\
The term \"drone\" was coined by early positronic activists, eager to distinguish themselves from the menial bots that most space-dwellers were \
familiar with, and avoid the ambiguity of the term \"AI\", which now usually refers to drones."
children = list(
/datum/lore/codex/page/codeline,
/datum/lore/codex/page/emergence,
/datum/lore/codex/page/emergent_intelligence_oversight,
/datum/lore/codex/category/drone_classes,
)
/datum/lore/codex/page/codeline
name = "Codeline"
keywords = list("fork")
data = "A \"codeline\" is a single type of drone. A codeline represents a significant degree of effort from sapient programmers to realize, as well as \
a substantial amount of regulatory fees levied by the government. Each copy of a codeline is called a \"fork\", whether the fork is created from the \
codeline<6E>s initial state or from a fully realized individual of that codeline. The degree of similarity between forks of the same codeline varies \
on the intelligence of the codeline, with low-level forks being virtually identical to high-level forks being no more similar than family members."
/datum/lore/codex/page/emergence
name = "Emergence"
keywords = list("Seed AI")
data = "\"Emergence\" is a term associated with drone intelligences who become more intelligent than they were originally intended to be. While this can \
extend to financial systems learning language, for instance, it is usually applied to hypothetical intelligences that become more intelligent than humans. \
Humanity has a long-standing cultural fear of emergent \"seed\" AI, egged on by Icarus memeticists and the occasional very real partial emergence events, where \
colony-control AI or other powerful systems begin to advance drastically in power, usually ending with the AI being shut down after crashing a handful of major systems."
/datum/lore/codex/page/emergent_intelligence_oversight
name = "Emergent Intelligence Oversight"
keywords = list("SG-EIO", "SG EIO", "EIO", "Intelligence Oversight")
data = "SG-EIO, usually just called EIO, is the organization charged with monitoring existing AI for any threat of dangerous emergence. Their perception in the \
public eye is generally positive, with all but the hardest-line Mercurial humans in favor of protection from the dangers of Seed AI. Some positronic rights \
groups bristle at the EIO<49>s human-centric viewpoint, but most are glad to have a different boogeyman in the form of drone intelligences. The tiny population \
of A-class drones are generally frightened of the EIO<49>s total power over them."
/datum/lore/codex/category/drone_classes
name = "Drone Classifications"
keywords = list("Class", "Drone Class")
data = "To aid in its work, the EIO has created a system of classifications corresponding to different levels of drone intelligence. Higher classes are more \
expensive to deploy and develop, owing to the costs of EIO oversight and political pressure against drone proliferation. EIO classification involves an initial \
audit of the project's source code by experts and automated systems, and for high-class drones further check-ins throughout the life of the drone. \
Drone chasses are often branded with their inhabiting intelligence's class, especially those of B or A-class drones, and class is often recorded in security records."
children = list(
/datum/lore/codex/page/class_f,
/datum/lore/codex/page/class_d,
/datum/lore/codex/page/class_c,
/datum/lore/codex/page/class_b,
/datum/lore/codex/page/class_a,
/datum/lore/codex/page/class_aa,
/datum/lore/codex/page/class_aaa,
/datum/lore/codex/page/class_x,
)
/datum/lore/codex/page/class_f
name = "F Class"
data = "\"F-class\" drones are an informal term for computer systems that pose absolutely no emergent risk. Most 21st-century software is F-class, as is much of \
the software used by 26th century humanity. The only regulation on F-class software is the occasional check that it is, in fact, F-Class, and as such has remained \
the most prevalent form of information-processing technology for centuries. The software powering most F-class drones is either freely available or bundled with the \
machine it's supposed to run."
/datum/lore/codex/page/class_d/add_content()
name = "D Class"
data = "D-class drones are conceptually descended from pre-[quick_link("Icarus")] AI and bear a strong resemblance to their forebears. D-class drones are essentially \
number-crunchers, with virtually nothing in the way of social development. They cannot speak more intelligibly than your average piece of software, \
using pre-determined messages written by their programmers, and have no capacity for self-improvement. They are D-class intelligence because they \
work with more complex problems than [quick_link("F class")] software, such as financial forecasting and large-scale data mining and memetics. The creation and \
deployment of D-class drones requires only a small fee for the required code audit, although some high-power financial and political systems are \
regularly watched by the [quick_link("EIO")] for signs of emergence. There is no real monopoly on the production of D-class drones."
/datum/lore/codex/page/class_c/add_content()
name = "C Class"
data = "C-class drones have social protocols for ease of use by organic and positronic laypeople. C-class drones are capable of speech, although \
it has a strong tendency to be formulaic and repetitive. They are also capable of a limited degree of self-improvement, and over time individual \
C-class instances tend differ slightly from one-another. C-class drones suffer a moderate fee to development, with automated [quick_link("EIO")] tools ensuring \
that they are not a long-term emergence risk. However, one a codeline is confirmed safe, deployment is unlimited, encouraging developers to \
instance many forks of the original drone to recoup their cost. The market for C-class drones is a strange space, dominated by Xion Manufacturing, \
Ward-Takahashi GMC, and a large number of smaller firms, like the notoriously-cheap Cyber Solutions."
/datum/lore/codex/page/class_b/add_content()
name = "B Class"
data = "B-class drones have advanced social protocols and are often capable of very intelligible conversation, so long as one sticks to surface \
topics. B-class drones tend to be specialized but still capable of remarkable growth within their speciality, making them popular for autonomous \
deployment and even supervision of other classes of drone. The dividing line between [quick_link("A Class", "A")] and B-class drones becomes apparent when they are taken \
out of their area of specialization, with the B-class drones swiftly becoming useless. They incur a hefty fee for the production of the initial \
codeline, as their emergent potential is far greater, and a smaller but still substantial fee for the production of forks. The market for B-class \
drones is a battleground between Ward-Takahashi and NanoTrasen, with other firms usually producing B-classes for in-house needs."
/datum/lore/codex/page/class_a/add_content()
name = "A Class"
keywords += list("AGI")
data = "A-class drones are also referred to as AGI. A-class drones are capable of performing in many contexts and can learn to solve problems from \
first principles, with an incredible potential for growth and emergent behavior. However, some abilities fall short of humans<6E>, usually those relating \
to socialization, and they often act in ways that are strange or distressing. There is a small but growing lobby of support for the personhood of A-class \
drones. The cost of initializing an A-class drone is absolutely massive, as they will be monitored by [quick_link("EIO")] forever. The auditing cost of an A-class drone \
codeline is even more staggering, making development and deployment of AGI limited to research, highly difficult and high-throughput operations like habitat \
overwatch, and a few risk-taking firms banking on the associated fees dropping. There is not a proper market for A-class drones, although an appreciable \
fraction of them are made by [quick_link("NanoTrasen")], with the rest generally being university research projects."
/datum/lore/codex/page/class_aa
name = "AA Class"
data = "AA-class drones <b>do not yet exist</b>. Hypothetically, they are equal to living in every respect, with psychology that would not be abnormal in a baseline \
human. The type of AA-class drone most frequently discussed is a hypothetical digitized consciousness of a human, a human brain that is somehow translated into \
software. Some argue that a small fraction of the A-class drones would more properly be considered AA, but as of yet no action has been taken. Some Mercurials \
will jokingly refer to themselves or other organics and positronics as AA<41>s. Research into brain uploading is heavily regulated and generally illegal."
/datum/lore/codex/page/class_aaa
name = "AAA Class"
data = "AAA-class drones do not yet exist, hopefully. They are more competent in every way than humans and pose a threat to the continued existence of sapient life. \
Anybody creating an AAA-class drone can be classified as a threat to humanity and dealt with very harshly."
/datum/lore/codex/page/class_x
name = "X Class"
data = "X-class drones emerge from unrated software, are produced by rogue labs, or cross the border from foreign space. They are considered a threat to national \
security and deleted when encountered in SolGov space, with the producers prosecuted legally if it has a SolGov origin. The few Skrellian drone labs will usually \
rate their product with EIO to allow their product to be imported."

View File

@@ -0,0 +1,99 @@
// Contains the 'raw' lore data.
/datum/lore/codex
var/name = null // Title displayed
var/data = null // The actual words.
var/datum/lore/codex/parent = null // Category above us
var/list/keywords = list() // Used for searching.
var/atom/movable/holder = null
/datum/lore/codex/New(var/new_holder, var/new_parent)
..()
holder = new_holder
parent = new_parent
add_content()
if(name)
keywords.Add(name)
/datum/lore/codex/Topic(href, href_list)
. = ..()
if(.)
return
holder.Topic(href, href_list) // Redirect to the physical object
/datum/lore/codex/page
// Returns an assoc list of keywords binded to a ref of this page. If it's a category, it will also recursively call this on its children.
/datum/lore/codex/proc/index_page()
var/list/results = list()
for(var/keyword in keywords)
results[keyword] = src
return results
// This gets called in New(), which is helpful for inserting quick_link()s.
/datum/lore/codex/proc/add_content()
return
// Use this to quickly link to a different page
/datum/lore/codex/proc/quick_link(var/target, var/word_to_display)
if(isnull(word_to_display))
word_to_display = target
return "<a href='?src=\ref[src];quick_link=[target]'>[word_to_display]</a>"
// Can only be found by specifically searching for it.
/datum/lore/codex/page/ultimate_answer
name = "Answer to the Ultimate Question of Life, the Universe, and Everything"
data = "42"
keywords = list("Ultimate Question", "Ultimate Question of Life, the Universe, and Everything", "Life, the Universe, and Everything", "Everything", "42")
// Organizes pages together.
/datum/lore/codex/category
var/list/children = list() // Pages or more categories relevant to this category. Self initializes from types to refs in New()
/datum/lore/codex/category/New()
..()
var/list/new_children_list = list()
for(var/type in children)
new_children_list.Add(new type(holder, src))
children = new_children_list
/datum/lore/codex/category/index_page()
// First, get our own keywords.
var/list/results = ..()
// Now get our children. If a child is also a category, it will get their children too.
for(var/datum/lore/codex/child in children)
results += child.index_page()
return results
/datum/lore/codex/category/main // The top-level categories
name = "Index"
data = "Don't panic!\
<br><br>\
The many star systems inhabitied by humanity and friends can seem bewildering to the uninitiated. \
This guide seeks to provide valuable information to anyone new in the system. This edition is tailored for visitors to the VIR system, \
however it also contains useful general information about human space, such as locations you may hear about, the current (as of 2561) political climate, various aliens you \
may meet in your travels, the big Trans-Stellars, and more."
children = list(
/datum/lore/codex/category/important_locations,
/datum/lore/codex/category/species,
/datum/lore/codex/category/auto_org/tsc,
/datum/lore/codex/category/auto_org/gov,
// /datum/lore/codex/category/auto_org/mil, // Add when we finish military stuff,
/datum/lore/codex/category/political_factions,
/datum/lore/codex/page/about
)
// We're a bird.
/datum/lore/codex/page/about
name = "About"
data = "<i>The Traveler's Guide to Human Space</i> is a series of books detailing a specific location inside a location colonized by humans. \
This book is for the system Vir, and was written by Eshi Tache, an explorer whom has visited many star systems, and \
has personally visited and seen many of the locations described inside this book. Two other people have also assisted in the creation of this \
book, being Qooqr Volquum, whom is an expert on synthetics, and Damian Fischer, a historian. Together, they provide valuable information and facts that lie outside of Tache's expertise.\
<br><br>\
The writings inside this edition are intended to be useful to anyone visiting it for the first time, from someone taking a vacation to beautiful Sif, \
to an immigrant from another system or even from outside human space, and anyone inbetween. The publisher wishes to note that any opinions expressed \
in this text does not reflect the opinions of the publisher, and are instead the author's.\
<br><br>\
Eshi Tache has also written other <i>The Traveler's Guide</i> books, including <i>Sol Edition</i>, <i>Tau Ceti Edition</i>, <i>Sirius Edition</i>, and more, \
which you can find in your local book store, library, or e-reader device."

View File

@@ -71,6 +71,8 @@
new/datum/stack_recipe("airtight hatch assembly", /obj/structure/door_assembly/door_assembly_hatch, 4, time = 50, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("maintenance hatch assembly", /obj/structure/door_assembly/door_assembly_mhatch, 4, time = 50, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("high security airlock assembly", /obj/structure/door_assembly/door_assembly_highsecurity, 4, time = 50, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("voidcraft airlock assembly horizontal", /obj/structure/door_assembly/door_assembly_voidcraft, 4, time = 50, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("voidcraft airlock assembly vertical", /obj/structure/door_assembly/door_assembly_voidcraft/vertical, 4, time = 50, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("emergency shutter", /obj/structure/firedoor_assembly, 4, time = 50, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("multi-tile airlock assembly", /obj/structure/door_assembly/multi_tile, 4, time = 50, one_per_turf = 1, on_floor = 1), \
))
@@ -94,6 +96,7 @@
recipes += new/datum/stack_recipe("knife grip", /obj/item/weapon/material/butterflyhandle, 4, time = 20, one_per_turf = 0, on_floor = 1, supplied_material = "[name]")
recipes += new/datum/stack_recipe("dark floor tile", /obj/item/stack/tile/floor_dark, 1, 4, 20)
recipes += new/datum/stack_recipe("roller bed", /obj/item/roller, 5, time = 30, on_floor = 1)
recipes += new/datum/stack_recipe("whetstone", /obj/item/weapon/whetstone, 2, time = 10)
/material/sandstone/generate_recipes()
..()
@@ -118,6 +121,7 @@
/material/wood/generate_recipes()
..()
recipes += new/datum/stack_recipe("wooden sandals", /obj/item/clothing/shoes/sandal, 1)
recipes += new/datum/stack_recipe("wood circlet", /obj/item/clothing/head/woodcirclet, 1)
recipes += new/datum/stack_recipe("clipboard", /obj/item/weapon/clipboard, 1)
recipes += new/datum/stack_recipe("wood floor tile", /obj/item/stack/tile/wood, 1, 4, 20)
recipes += new/datum/stack_recipe("wooden chair", /obj/structure/bed/chair/wood, 3, time = 10, one_per_turf = 1, on_floor = 1)

View File

@@ -604,7 +604,7 @@ var/list/name_to_material
stack_type = /obj/item/stack/material/wood
icon_colour = "#824B28"
integrity = 50
icon_base = "solid"
icon_base = "wood"
explosion_resistance = 2
shard_type = SHARD_SPLINTER
shard_can_repair = 0 // you can't weld splinters back into planks
@@ -625,6 +625,12 @@ var/list/name_to_material
stack_type = null
shard_type = SHARD_NONE
/material/wood/sif
name = "alien wood"
// stack_type = /obj/item/stack/material/wood/sif
icon_colour = "#0099cc" // Cyan-ish
stack_origin_tech = list(TECH_MATERIAL = 2, TECH_BIO = 2) // Alien wood would presumably be more interesting to the analyzer.
/material/cardboard
name = "cardboard"
stack_type = /obj/item/stack/material/cardboard

View File

@@ -7,10 +7,11 @@
log_say("Ghost/[src.key] : [message]")
if (src.client)
client.handle_spam_prevention(MUTE_DEADCHAT)
if(src.client.prefs.muted & MUTE_DEADCHAT)
src << "\red You cannot talk in deadchat (muted)."
return
if(message)
client.handle_spam_prevention(MUTE_DEADCHAT)
if(src.client.prefs.muted & MUTE_DEADCHAT)
src << "\red You cannot talk in deadchat (muted)."
return
. = src.say_dead(message)
@@ -27,10 +28,11 @@
log_emote("Ghost/[src.key] : [message]")
if(src.client)
client.handle_spam_prevention(MUTE_DEADCHAT)
if(src.client.prefs.muted & MUTE_DEADCHAT)
src << "\red You cannot emote in deadchat (muted)."
return
if(message)
client.handle_spam_prevention(MUTE_DEADCHAT)
if(src.client.prefs.muted & MUTE_DEADCHAT)
src << "\red You cannot emote in deadchat (muted)."
return
. = src.emote_dead(message)

View File

@@ -32,14 +32,10 @@
if(!(language && (language.flags & INNATE))) // skip understanding checks for INNATE languages
if(!say_understands(speaker,language))
if(istype(speaker,/mob/living/simple_animal))
var/mob/living/simple_animal/S = speaker
message = pick(S.speak)
if(language)
message = language.scramble(message)
else
if(language)
message = language.scramble(message)
else
message = stars(message)
message = stars(message)
var/speaker_name = speaker.name
if(istype(speaker, /mob/living/carbon/human))
@@ -94,7 +90,7 @@
var/list/valid_names = splittext(real_name, " ") // Should output list("John", "Doe") as an example.
valid_names += special_mentions()
for(var/name in valid_names)
if(findtext(message, name))
if(findtext(message, regex("\\b[name]\\b", "i"))) // This is to stop 'ai' from triggering if someone says 'wait'.
return TRUE
return FALSE
@@ -105,10 +101,10 @@
/mob/living/silicon/ai/special_mentions()
return list("AI") // AI door!
// Converts specific characters, like *, /, and _ to formatted output.
// Converts specific characters, like *, |, and _ to formatted output.
/mob/proc/say_emphasis(var/message)
message = encode_html_emphasis(message, "/", "i")
message = encode_html_emphasis(message, "*", "b")
message = encode_html_emphasis(message, "|", "i")
message = encode_html_emphasis(message, "+", "b")
message = encode_html_emphasis(message, "_", "u")
return message

View File

@@ -5,18 +5,70 @@
ask_verb = "chimpers"
exclaim_verb = "screeches"
key = "6"
machine_understands = 0
/datum/language/skrell/monkey
name = "Neaera"
desc = "Squik squik squik."
key = "8"
machine_understands = 0
/datum/language/unathi/monkey
name = "Stok"
desc = "Hiss hiss hiss."
key = "7"
machine_understands = 0
/datum/language/tajaran/monkey
name = "Farwa"
desc = "Meow meow meow."
key = "9"
machine_understands = 0
/datum/language/corgi
name = "Dog"
desc = "Woof woof woof."
speech_verb = "barks"
ask_verb = "woofs"
exclaim_verb = "howls"
key = "n"
flags = RESTRICTED
machine_understands = 0
space_chance = 100
syllables = list("bark", "woof", "bowwow", "yap", "arf")
/datum/language/cat
name = "Cat"
desc = "Meow meow meow."
speech_verb = "meows"
ask_verb = "mrowls"
exclaim_verb = "yowls"
key = "c"
flags = RESTRICTED
machine_understands = 0
space_chance = 100
syllables = list("meow", "mrowl", "purr", "meow", "meow", "meow")
/datum/language/mouse
name = "Mouse"
desc = "Squeak squeak. *Nibbles on cheese*"
speech_verb = "squeaks"
ask_verb = "squeaks"
exclaim_verb = "squeaks"
key = "m"
flags = RESTRICTED
machine_understands = 0
space_chance = 100
syllables = list("squeak") // , "gripes", "oi", "meow")
/datum/language/bird
name = "Bird"
desc = "Chirp chirp, give me food"
speech_verb = "chirps"
ask_verb = "tweets"
exclaim_verb = "squawks"
key = "m"
flags = RESTRICTED
machine_understands = 0
space_chance = 100
syllables = list("chirp", "squawk", "tweet")

View File

@@ -4,6 +4,7 @@
speech_verb = "says"
colour = "changeling"
key = "g"
machine_understands = 0
flags = RESTRICTED | HIVEMIND
/datum/language/ling/broadcast(var/mob/living/speaker,var/message,var/speaker_mask)
@@ -21,6 +22,7 @@
exclaim_verb = "sings"
colour = "alien"
key = "x"
machine_understands = 0
flags = RESTRICTED | HIVEMIND
/datum/language/corticalborer/broadcast(var/mob/living/speaker,var/message,var/speaker_mask)
@@ -80,4 +82,5 @@
exclaim_verb = "chants"
colour = "cult"
key = "y"
machine_understands = 0
flags = RESTRICTED | HIVEMIND

View File

@@ -6,6 +6,7 @@
exclaim_verb = "rustles"
colour = "soghun"
key = "q"
machine_understands = 0
flags = RESTRICTED
syllables = list("hs","zt","kr","st","sh")
@@ -18,6 +19,7 @@
name = LANGUAGE_ROOTGLOBAL
desc = "A complex language known instinctively by Dionaea, 'spoken' by emitting modulated radio waves. This version uses low frequency waves for slow communication at long ranges."
key = "w"
machine_understands = 0
flags = RESTRICTED | HIVEMIND
/datum/language/unathi

View File

@@ -6,6 +6,7 @@
ask_verb = "queries"
exclaim_verb = "declares"
key = "b"
machine_understands = 0
flags = RESTRICTED | HIVEMIND
var/drone_only
@@ -64,5 +65,6 @@
exclaim_verb = "transmits"
colour = "say_quote"
key = "d"
machine_understands = 0
flags = RESTRICTED | HIVEMIND
drone_only = 1

View File

@@ -59,6 +59,8 @@
/datum/species/proc/handle_autohiss(message, datum/language/lang, mode)
if(!autohiss_basic_map)
return message
if(lang.flags & NO_STUTTER) // Currently prevents EAL, Sign language, and emotes from autohissing
return message
if(autohiss_exempt && (lang.name in autohiss_exempt))
return message

View File

@@ -27,7 +27,7 @@
var/turf/obstacle = null
var/wait_if_pulled = 0 // Only applies to moving to the target
var/will_patrol = 0 // Not a setting - whether or no this type of bots patrols at all
var/will_patrol = 0 // If set to 1, will patrol, duh
var/patrol_speed = 1 // How many times per tick we move when patrolling
var/target_speed = 2 // Ditto for chasing the target
var/min_target_dist = 1 // How close we try to get to the target
@@ -49,7 +49,11 @@
access_scanner.req_access = req_access.Copy()
access_scanner.req_one_access = req_one_access.Copy()
turn_on()
// Make sure mapped in units start turned on.
/mob/living/bot/initialize()
..()
if(on)
turn_on() // Update lights and other stuff
/mob/living/bot/Life()
..()
@@ -61,7 +65,8 @@
paralysis = 0
if(on && !client && !busy)
handleAI()
spawn(0)
handleAI()
/mob/living/bot/updatehealth()
if(status_flags & GODMODE)
@@ -145,20 +150,18 @@
handleRangedTarget()
if(!wait_if_pulled || !pulledby)
for(var/i = 1 to target_speed)
sleep(20 / (target_speed + 1))
stepToTarget()
if(i < target_speed)
sleep(20 / target_speed)
if(max_frustration && frustration > max_frustration * target_speed)
handleFrustrated(1)
else
resetTarget()
lookForTargets()
if(will_patrol && !pulledby && !target)
if(patrol_path.len)
if(patrol_path && patrol_path.len)
for(var/i = 1 to patrol_speed)
sleep(20 / (patrol_speed + 1))
handlePatrol()
if(i < patrol_speed)
sleep(20 / patrol_speed)
if(max_frustration && frustration > max_frustration * patrol_speed)
handleFrustrated(0)
else
@@ -219,6 +222,25 @@
return
/mob/living/bot/proc/getPatrolTurf()
var/minDist = INFINITY
var/obj/machinery/navbeacon/targ = locate() in get_turf(src)
if(!targ)
for(var/obj/machinery/navbeacon/N in navbeacons)
if(!N.codes["patrol"])
continue
if(get_dist(src, N) < minDist)
minDist = get_dist(src, N)
targ = N
if(targ && targ.codes["next_patrol"])
for(var/obj/machinery/navbeacon/N in navbeacons)
if(N.location == targ.codes["next_patrol"])
targ = N
break
if(targ)
return get_turf(targ)
return null
/mob/living/bot/proc/handleIdle()
@@ -255,15 +277,16 @@
on = 1
set_light(light_strength)
update_icons()
resetTarget()
patrol_path = list()
ignore_list = list()
return 1
/mob/living/bot/proc/turn_off()
on = 0
busy = 0 // If ever stuck... reboot!
set_light(0)
update_icons()
resetTarget()
patrol_path = list()
ignore_list = list()
/mob/living/bot/proc/explode()
qdel(src)
@@ -327,6 +350,11 @@
for(var/obj/machinery/door/D in loc)
if(!D.density) continue
if(istype(D, /obj/machinery/door/airlock))
var/obj/machinery/door/airlock/A = D
if(!A.can_open()) return 1
if(istype(D, /obj/machinery/door/window))
if( dir & D.dir ) return !D.check_access(ID)

View File

@@ -12,7 +12,6 @@
var/cleaning = 0
var/screwloose = 0
var/oddbutton = 0
var/should_patrol = 0
var/blood = 1
var/list/target_types = list()
@@ -32,9 +31,11 @@
if(oddbutton && prob(5)) // Make a big mess
visible_message("Something flies out of [src]. He seems to be acting oddly.")
var/obj/effect/decal/cleanable/blood/gibs/gib = new /obj/effect/decal/cleanable/blood/gibs(loc)
ignore_list += gib
// TODO - I have a feeling weakrefs will not work in ignore_list, verify this ~Leshana
var/weakref/g = weakref(gib)
ignore_list += g
spawn(600)
ignore_list -= gib
ignore_list -= g
/mob/living/bot/cleanbot/lookForTargets()
for(var/obj/effect/decal/cleanable/D in view(world.view, src)) // There was some odd code to make it start with nearest decals, it's unnecessary, this works
@@ -110,7 +111,7 @@
dat += "Maintenance panel is [open ? "opened" : "closed"]"
if(!locked || issilicon(user))
dat += "<BR>Cleans Blood: <A href='?src=\ref[src];operation=blood'>[blood ? "Yes" : "No"]</A><BR>"
dat += "<BR>Patrol station: <A href='?src=\ref[src];operation=patrol'>[should_patrol ? "Yes" : "No"]</A><BR>"
dat += "<BR>Patrol station: <A href='?src=\ref[src];operation=patrol'>[will_patrol ? "Yes" : "No"]</A><BR>"
if(open && !locked)
dat += "Odd looking screw twiddled: <A href='?src=\ref[src];operation=screw'>[screwloose ? "Yes" : "No"]</A><BR>"
dat += "Weird button pressed: <A href='?src=\ref[src];operation=oddbutton'>[oddbutton ? "Yes" : "No"]</A>"
@@ -134,7 +135,7 @@
blood = !blood
get_targets()
if("patrol")
should_patrol = !should_patrol
will_patrol = !will_patrol
patrol_path = null
if("screw")
screwloose = !screwloose

View File

@@ -170,7 +170,7 @@
visible_message("<span class='notice'>[src] starts [T.dead? "removing the plant from" : "harvesting"] \the [A].</span>")
busy = 1
if(do_after(src, 30))
if(do_after(src, 30, A))
visible_message("<span class='notice'>[src] [T.dead? "removes the plant from" : "harvests"] \the [A].</span>")
T.attack_hand(src)
if(FARMBOT_WATER)
@@ -179,7 +179,7 @@
visible_message("<span class='notice'>[src] starts watering \the [A].</span>")
busy = 1
if(do_after(src, 30))
if(do_after(src, 30, A))
playsound(loc, 'sound/effects/slosh.ogg', 25, 1)
visible_message("<span class='notice'>[src] waters \the [A].</span>")
tank.reagents.trans_to(T, 100 - T.waterlevel)
@@ -198,7 +198,7 @@
visible_message("<span class='notice'>[src] starts fertilizing \the [A].</span>")
busy = 1
if(do_after(src, 30))
if(do_after(src, 30, A))
visible_message("<span class='notice'>[src] fertilizes \the [A].</span>")
T.reagents.add_reagent("ammonia", 10)

View File

@@ -1,3 +1,9 @@
// Configure whether or not floorbot will fix hull breaches.
// This can be a problem if it tries to pave over space or shuttles. That should be fixed but...
// If it can see space outside windows, it can be laggy since it keeps wondering if it should fix them.
// Therefore that functionality is disabled for now. But it can be turned on by uncommenting this.
// #define FLOORBOT_PATCHES_HOLES 1
/mob/living/bot/floorbot
name = "Floorbot"
desc = "A little floor repairing robot, he looks so excited!"
@@ -25,7 +31,7 @@
/mob/living/bot/floorbot/attack_hand(var/mob/user)
user.set_machine(src)
var/dat
var/list/dat = list()
dat += "<TT><B>Automatic Station Floor Repairer v1.0</B></TT><BR><BR>"
dat += "Status: <A href='?src=\ref[src];operation=start'>[src.on ? "On" : "Off"]</A><BR>"
dat += "Maintenance panel is [open ? "opened" : "closed"]<BR>"
@@ -41,9 +47,9 @@
else
bmode = "Disabled"
dat += "<BR><BR>Bridge Mode : <A href='?src=\ref[src];operation=bridgemode'>[bmode]</A><BR>"
user << browse("<HEAD><TITLE>Repairbot v1.0 controls</TITLE></HEAD>[dat]", "window=autorepair")
onclose(user, "autorepair")
var/datum/browser/popup = new(user, "autorepair", "Repairbot v1.1 controls")
popup.set_content(jointext(dat,null))
popup.open()
return
/mob/living/bot/floorbot/emag_act(var/remaining_charges, var/mob/user)
@@ -115,23 +121,24 @@
target = T
return
T = get_step(T, targetdirection)
return // In bridge mode we don't want to step off that line even to eat plates!
else // Fixing floors
for(var/turf/space/T in view(src)) // Breaches are of higher priority
if(confirmTarget(T))
target = T
return
#ifdef FLOORBOT_PATCHES_HOLES
for(var/turf/space/T in view(src)) // Breaches are of higher priority
if(confirmTarget(T))
target = T
return
for(var/turf/simulated/mineral/floor/T in view(src)) // Asteroids are of smaller priority
if(confirmTarget(T))
target = T
return
if(improvefloors)
for(var/turf/simulated/floor/T in view(src))
if(confirmTarget(T))
target = T
return
for(var/turf/simulated/mineral/floor/T in view(src)) // Asteroids are of smaller priority
if(confirmTarget(T))
target = T
return
#endif
// Look for broken floors even if we aren't improvefloors
for(var/turf/simulated/floor/T in view(src))
if(confirmTarget(T))
target = T
return
if(amount < maxAmount && (eattiles || maketiles))
for(var/obj/item/stack/S in view(src))
@@ -148,7 +155,11 @@
if(istype(A, /obj/item/stack/material/steel))
return (amount < maxAmount && maketiles)
if(A.loc.name == "Space")
// Don't pave over all of space, build there only if in bridge mode
if(!targetdirection && istype(A.loc, /area/space)) // Note name == "Space" does not work!
return 0
if(istype(A.loc, /area/shuttle)) // Do NOT mess with shuttle drop zones
return 0
if(emagged)
@@ -157,14 +168,16 @@
if(!amount)
return 0
#ifdef FLOORBOT_PATCHES_HOLES
if(istype(A, /turf/space))
return 1
if(istype(A, /turf/simulated/mineral/floor))
return 1
#endif
var/turf/simulated/floor/T = A
return (istype(T) && improvefloors && !T.flooring && (get_turf(T) == loc || prob(40)))
return (istype(T) && (T.broken || T.burnt || (improvefloors && !T.flooring)) && (get_turf(T) == loc || prob(40)))
/mob/living/bot/floorbot/UnarmedAttack(var/atom/A, var/proximity)
if(!..())
@@ -181,12 +194,12 @@
busy = 1
update_icons()
if(F.flooring)
visible_message("<span class='warning'>[src] begins to tear the floor tile from the floor!</span>")
visible_message("<span class='warning'>\The [src] begins to tear the floor tile from the floor!</span>")
if(do_after(src, 50))
F.break_tile_to_plating()
addTiles(1)
else
visible_message("<span class='danger'>[src] begins to tear through the floor!</span>")
visible_message("<span class='danger'>\The [src] begins to tear through the floor!</span>")
if(do_after(src, 150)) // Extra time because this can and will kill.
F.ReplaceWithLattice()
addTiles(1)
@@ -201,7 +214,7 @@
return
busy = 1
update_icons()
visible_message("<span class='notice'>[src] begins to repair the hole.</span>")
visible_message("<span class='notice'>\The [src] begins to repair the hole.</span>")
if(do_after(src, 50))
if(A && (locate(/obj/structure/lattice, A) && building == 1 || !locate(/obj/structure/lattice, A) && building == 2)) // Make sure that it still needs repairs
var/obj/item/I
@@ -215,10 +228,20 @@
update_icons()
else if(istype(A, /turf/simulated/floor))
var/turf/simulated/floor/F = A
if(!F.flooring && amount)
if(F.broken || F.burnt)
busy = 1
update_icons()
visible_message("<span class='notice'>[src] begins to improve the floor.</span>")
visible_message("<span class='notice'>\The [src] begins to remove the broken floor.</span>")
if(do_after(src, 50, F))
if(F.broken || F.burnt)
F.make_plating()
target = null
busy = 0
update_icons()
else if(!F.flooring && amount)
busy = 1
update_icons()
visible_message("<span class='notice'>\The [src] begins to improve the floor.</span>")
if(do_after(src, 50))
if(!F.flooring)
F.set_flooring(get_flooring_data(floor_build_type))
@@ -228,7 +251,7 @@
update_icons()
else if(istype(A, /obj/item/stack/tile/floor) && amount < maxAmount)
var/obj/item/stack/tile/floor/T = A
visible_message("<span class='notice'>[src] begins to collect tiles.</span>")
visible_message("<span class='notice'>\The [src] begins to collect tiles.</span>")
busy = 1
update_icons()
if(do_after(src, 20))
@@ -242,7 +265,7 @@
else if(istype(A, /obj/item/stack/material) && amount + 4 <= maxAmount)
var/obj/item/stack/material/M = A
if(M.get_material_name() == DEFAULT_WALL_MATERIAL)
visible_message("<span class='notice'>[src] begins to make tiles.</span>")
visible_message("<span class='notice'>\The [src] begins to make tiles.</span>")
busy = 1
update_icons()
if(do_after(50))
@@ -252,7 +275,7 @@
/mob/living/bot/floorbot/explode()
turn_off()
visible_message("<span class='danger'>[src] blows apart!</span>")
visible_message("<span class='danger'>\The [src] blows apart!</span>")
var/turf/Tsec = get_turf(src)
var/obj/item/weapon/storage/toolbox/mechanical/N = new /obj/item/weapon/storage/toolbox/mechanical(Tsec)
@@ -353,4 +376,4 @@
return
if(!in_range(src, user) && loc != user)
return
created_name = t
created_name = t

View File

@@ -130,10 +130,7 @@
if("sethome")
var/new_dest
var/list/beaconlist = new()
for(var/obj/machinery/navbeacon/N in navbeacons)
beaconlist.Add(N.location)
beaconlist[N.location] = N
var/list/beaconlist = GetBeaconList()
if(beaconlist.len)
new_dest = input("Select new home tag", "Mulebot [suffix ? "([suffix])" : ""]", null) in null|beaconlist
else
@@ -168,10 +165,7 @@
targetName = "Home"
if("SetD")
var/new_dest
var/list/beaconlist = new()
for(var/obj/machinery/navbeacon/N in navbeacons)
beaconlist.Add(N.location)
beaconlist[N.location] = N
var/list/beaconlist = GetBeaconList()
if(beaconlist.len)
new_dest = input("Select new destination tag", "Mulebot [suffix ? "([suffix])" : ""]") in null|beaconlist
else
@@ -285,6 +279,15 @@
new /obj/effect/decal/cleanable/blood/oil(Tsec)
..()
/mob/living/bot/mulebot/proc/GetBeaconList()
var/list/beaconlist = list()
for(var/obj/machinery/navbeacon/N in navbeacons)
if(!N.codes["delivery"])
continue
beaconlist.Add(N.location)
beaconlist[N.location] = N
return beaconlist
/mob/living/bot/mulebot/proc/load(var/atom/movable/C)
if(busy || load || get_dist(C, src) > 1 || !isturf(C.loc))
return
@@ -304,11 +307,11 @@
busy = 1
C.loc = loc
C.forceMove(loc)
sleep(2)
if(C.loc != loc) //To prevent you from going onto more than one bot.
return
C.loc = src
C.forceMove(src)
load = C
C.pixel_y += 9
@@ -325,7 +328,7 @@
busy = 1
overlays.Cut()
load.loc = loc
load.forceMove(loc)
load.pixel_y -= 9
load.layer = initial(load.layer)
@@ -338,7 +341,7 @@
if(AM == botcard || AM == access_scanner)
continue
AM.loc = loc
AM.forceMove(loc)
AM.layer = initial(AM.layer)
AM.pixel_y = initial(AM.pixel_y)
busy = 0

View File

@@ -1,10 +1,14 @@
#define SECBOT_WAIT_TIME 5 //number of in-game seconds to wait for someone to surrender
#define SECBOT_THREAT_ARREST 4 //threat level at which we decide to arrest someone
#define SECBOT_THREAT_ATTACK 8 //threat level at which was assume immediate danger and attack right away
/mob/living/bot/secbot
name = "Securitron"
desc = "A little security robot. He looks less than thrilled."
icon_state = "secbot0"
maxHealth = 100
health = 100
req_one_access = list(access_robotics, access_security, access_forensics_lockers)
req_one_access = list(access_security, access_forensics_lockers)
botcard_access = list(access_security, access_sec_doors, access_forensics_lockers, access_morgue, access_maint_tunnels)
patrol_speed = 2
target_speed = 3
@@ -14,18 +18,17 @@
var/check_arrest = 1 // If true, arrests people who are set to arrest.
var/arrest_type = 0 // If true, doesn't handcuff. You monster.
var/declare_arrests = 0 // If true, announces arrests over sechuds.
var/auto_patrol = 0 // If true, patrols on its own
var/is_ranged = 0
var/awaiting_surrender = 0
var/list/threat_found_sounds = new('sound/voice/bcriminal.ogg', 'sound/voice/bjustice.ogg', 'sound/voice/bfreeze.ogg')
var/list/preparing_arrest_sounds = new('sound/voice/bgod.ogg', 'sound/voice/biamthelaw.ogg', 'sound/voice/bsecureday.ogg', 'sound/voice/bradio.ogg', 'sound/voice/binsult.ogg', 'sound/voice/bcreep.ogg')
var/list/threat_found_sounds = list('sound/voice/bcriminal.ogg', 'sound/voice/bjustice.ogg', 'sound/voice/bfreeze.ogg')
var/list/preparing_arrest_sounds = list('sound/voice/bgod.ogg', 'sound/voice/biamthelaw.ogg', 'sound/voice/bsecureday.ogg', 'sound/voice/bradio.ogg', 'sound/voice/bcreep.ogg')
/mob/living/bot/secbot/beepsky
name = "Officer Beepsky"
desc = "It's Officer Beep O'sky! Powered by a potato and a shot of whiskey."
auto_patrol = 1
will_patrol = 1
/mob/living/bot/secbot/update_icons()
if(on && busy)
@@ -40,7 +43,7 @@
/mob/living/bot/secbot/attack_hand(var/mob/user)
user.set_machine(src)
var/dat
var/list/dat = list()
dat += "<TT><B>Automatic Security Unit</B></TT><BR><BR>"
dat += "Status: <A href='?src=\ref[src];power=1'>[on ? "On" : "Off"]</A><BR>"
dat += "Behaviour controls are [locked ? "locked" : "unlocked"]<BR>"
@@ -51,10 +54,10 @@
dat += "Check Arrest Status: <A href='?src=\ref[src];operation=ignorearr'>[check_arrest ? "Yes" : "No"]</A><BR>"
dat += "Operating Mode: <A href='?src=\ref[src];operation=switchmode'>[arrest_type ? "Detain" : "Arrest"]</A><BR>"
dat += "Report Arrests: <A href='?src=\ref[src];operation=declarearrests'>[declare_arrests ? "Yes" : "No"]</A><BR>"
dat += "Auto Patrol: <A href='?src=\ref[src];operation=patrol'>[auto_patrol ? "On" : "Off"]</A>"
user << browse("<HEAD><TITLE>Securitron controls</TITLE></HEAD>[dat]", "window=autosec")
onclose(user, "autosec")
return
dat += "Auto Patrol: <A href='?src=\ref[src];operation=patrol'>[will_patrol ? "On" : "Off"]</A>"
var/datum/browser/popup = new(user, "autosec", "Securitron controls")
popup.set_content(jointext(dat,null))
popup.open()
/mob/living/bot/secbot/Topic(href, href_list)
if(..())
@@ -80,7 +83,7 @@
if("switchmode")
arrest_type = !arrest_type
if("patrol")
auto_patrol = !auto_patrol
will_patrol = !will_patrol
if("declarearrests")
declare_arrests = !declare_arrests
attack_hand(usr)
@@ -99,10 +102,46 @@
/mob/living/bot/secbot/attackby(var/obj/item/O, var/mob/user)
var/curhealth = health
..()
. = ..()
if(health < curhealth)
target = user
awaiting_surrender = 5
react_to_attack(user)
/mob/living/bot/secbot/bullet_act(var/obj/item/projectile/P)
var/curhealth = health
var/mob/shooter = P.firer
. = ..()
//if we already have a target just ignore to avoid lots of checking
if(!target && health < curhealth && shooter && (shooter in view(world.view, src)))
react_to_attack(shooter)
/mob/living/bot/secbot/proc/react_to_attack(mob/attacker)
if(!target)
playsound(src.loc, pick(threat_found_sounds), 50)
broadcast_security_hud_message("[src] was attacked by a hostile <b>[target_name(attacker)]</b> in <b>[get_area(src)]</b>.", src)
target = attacker
awaiting_surrender = INFINITY // Don't try and wait for surrender
// Say "freeze!" and demand surrender
/mob/living/bot/secbot/proc/demand_surrender(mob/target, var/threat)
var/suspect_name = target_name(target)
if(declare_arrests)
broadcast_security_hud_message("[src] is [arrest_type ? "detaining" : "arresting"] a level [threat] suspect <b>[suspect_name]</b> in <b>[get_area(src)]</b>.", src)
say("Down on the floor, [suspect_name]! You have [SECBOT_WAIT_TIME] seconds to comply.")
playsound(src.loc, pick(preparing_arrest_sounds), 50)
// Register to be told when the target moves
moved_event.register(target, src, /mob/living/bot/secbot/proc/target_moved)
// Callback invoked if the registered target moves
/mob/living/bot/secbot/proc/target_moved(atom/movable/moving_instance, atom/old_loc, atom/new_loc)
if(get_dist(get_turf(src), get_turf(target)) >= 1)
awaiting_surrender = INFINITY // Done waiting!
moved_event.unregister(moving_instance, src)
/mob/living/bot/secbot/resetTarget()
..()
moved_event.unregister(target, src)
awaiting_surrender = -1
walk_to(src, 0)
/mob/living/bot/secbot/startPatrol()
if(!locked) // Stop running away when we set you up
@@ -112,8 +151,7 @@
/mob/living/bot/secbot/confirmTarget(var/atom/A)
if(!..())
return 0
return (check_threat(A) > 3)
return (check_threat(A) >= SECBOT_THREAT_ARREST)
/mob/living/bot/secbot/lookForTargets()
for(var/mob/living/M in view(src))
@@ -127,23 +165,17 @@
custom_emote(1, "points at [M.name]!")
return
/mob/living/bot/secbot/calcTargetPath()
..()
if(awaiting_surrender != -1)
awaiting_surrender = 5 // This implies that a) we have already approached the target and b) it has moved after the warning
/mob/living/bot/secbot/handleAdjacentTarget()
if(awaiting_surrender < 5 && ishuman(target) && !target:lying)
if(awaiting_surrender == -1)
say("Down on the floor, [target]! You have five seconds to comply.")
var/mob/living/carbon/human/H = target
var/threat = check_threat(target)
if(awaiting_surrender < SECBOT_WAIT_TIME && istype(H) && !H.lying && threat < SECBOT_THREAT_ATTACK)
if(awaiting_surrender == -1) // On first tick of awaiting...
demand_surrender(target, threat)
++awaiting_surrender
else
if(declare_arrests)
broadcast_security_hud_message("[src] is [arrest_type ? "detaining" : "arresting"] a level [threat] suspect <b>[target_name(target)]</b> in <b>[get_area(src)]</b>.", src)
UnarmedAttack(target)
if(ishuman(target) && declare_arrests)
var/area/location = get_area(src)
broadcast_security_hud_message("[src] is [arrest_type ? "detaining" : "arresting"] a level [check_threat(target)] suspect <b>[target]</b> in <b>[location]</b>.", src)
// say("Engaging patrol mode.")
/mob/living/bot/secbot/UnarmedAttack(var/mob/M, var/proximity)
if(!..())
@@ -170,17 +202,15 @@
spawn(2)
busy = 0
update_icons()
visible_message("<span class='warning'>[C] was prodded by [src] with a stun baton!</span>")
visible_message("<span class='warning'>\The [C] was prodded by \the [src] with a stun baton!</span>")
else
playsound(loc, 'sound/weapons/handcuffs.ogg', 30, 1, -2)
visible_message("<span class='warning'>[src] is trying to put handcuffs on [C]!</span>")
visible_message("<span class='warning'>\The [src] is trying to put handcuffs on \the [C]!</span>")
busy = 1
if(do_mob(src, C, 60))
if(!C.handcuffed)
C.handcuffed = new /obj/item/weapon/handcuffs(C)
C.update_inv_handcuffed()
if(preparing_arrest_sounds.len)
playsound(loc, pick(preparing_arrest_sounds), 50, 0)
busy = 0
else if(istype(M, /mob/living/simple_animal))
var/mob/living/simple_animal/S = M
@@ -193,7 +223,8 @@
spawn(2)
busy = 0
update_icons()
visible_message("<span class='warning'>[M] was beaten by [src] with a stun baton!</span>")
visible_message("<span class='warning'>\The [M] was beaten by \the [src] with a stun baton!</span>")
/mob/living/bot/secbot/explode()
visible_message("<span class='warning'>[src] blows apart!</span>")
@@ -215,11 +246,17 @@
new /obj/effect/decal/cleanable/blood/oil(Tsec)
qdel(src)
/mob/living/bot/secbot/proc/target_name(mob/living/T)
if(ishuman(T))
var/mob/living/carbon/human/H = T
return H.get_id_name("unidentified person")
return "unidentified lifeform"
/mob/living/bot/secbot/proc/check_threat(var/mob/living/M)
if(!M || !istype(M) || M.stat == DEAD || src == M)
return 0
if(emagged)
if(emagged && !M.incapacitated()) //check incapacitated so emagged secbots don't keep attacking the same target forever
return 10
return M.assess_perp(access_scanner, 0, idcheck, check_records, check_arrest)
@@ -297,4 +334,4 @@
return
if(!in_range(src, usr) && loc != usr)
return
created_name = t
created_name = t

View File

@@ -164,7 +164,9 @@
if(2)
brainmob.emp_damage += rand(10,20)
if(3)
brainmob.emp_damage += rand(0,10)
brainmob.emp_damage += rand(5,10)
if(4)
brainmob.emp_damage += rand(0,5)
..()
/obj/item/device/mmi/digital
@@ -216,7 +218,9 @@
if(2)
src.brainmob.emp_damage += rand(10,20)
if(3)
src.brainmob.emp_damage += rand(0,10)
src.brainmob.emp_damage += rand(5,10)
if(4)
src.brainmob.emp_damage += rand(0,5)
..()
/obj/item/device/mmi/digital/transfer_identity(var/mob/living/carbon/H)

View File

@@ -71,15 +71,11 @@
/mob/living/carbon/brain/handle_chemicals_in_body()
chem_effects.Cut()
analgesic = 0
if(touching) touching.metabolize()
if(ingested) ingested.metabolize()
if(bloodstr) bloodstr.metabolize()
if(CE_PAINKILLER in chem_effects)
analgesic = chem_effects[CE_PAINKILLER]
confused = max(0, confused - 1)
// decrement dizziness counter, clamped to 0
if(resting)

View File

@@ -112,7 +112,9 @@
if(2)
src.brainmob.emp_damage += rand(10,20)
if(3)
src.brainmob.emp_damage += rand(0,10)
src.brainmob.emp_damage += rand(5,10)
if(4)
src.brainmob.emp_damage += rand(0,5)
..()
/obj/item/device/mmi/digital/posibrain/New()

View File

@@ -4,7 +4,7 @@
return null
..()
/mob/living/carbon/standard_weapon_hit_effects(obj/item/I, mob/living/user, var/effective_force, var/blocked, var/hit_zone)
/mob/living/carbon/standard_weapon_hit_effects(obj/item/I, mob/living/user, var/effective_force, var/blocked, var/soaked, var/hit_zone)
if(!effective_force || blocked >= 100)
return 0
@@ -12,6 +12,10 @@
if(HULK in user.mutations)
effective_force *= 2
//If the armor soaks all of the damage, it just skips the rest of the checks
if(effective_force <= soaked)
return 0
//Apply weapon damage
var/weapon_sharp = is_sharp(I)
var/weapon_edge = has_edge(I)

View File

@@ -7,8 +7,7 @@
var/last_eating = 0 //Not sure what this does... I found it hidden in food.dm
var/life_tick = 0 // The amount of life ticks that have processed on this mob.
var/analgesic = 0 // when this is set, the mob isn't affected by shock or pain
// life should decrease this by 1 every tick
// total amount of wounds on mob, used to spread out healing and the like over all wounds
var/number_wounds = 0
var/obj/item/handcuffed = null //Whether or not the mob is handcuffed

View File

@@ -25,7 +25,8 @@
message = "is strumming the air and headbanging like a safari chimp."
m_type = 1
if("ping", "beep", "buzz", "yes", "no")
//Machine-only emotes
if("ping", "beep", "buzz", "yes", "no", "rcough", "rsneeze")
if(!isSynthetic())
src << "<span class='warning'>You are not a synthetic.</span>"
@@ -54,6 +55,18 @@
else if(act == "no")
display_msg = "emits a negative blip"
use_sound = 'sound/machines/synth_no.ogg'
else if(act == "rcough")
display_msg = "emits a robotic cough"
if(gender == FEMALE)
use_sound = pick('sound/effects/mob_effects/f_machine_cougha.ogg','sound/effects/mob_effects/f_machine_coughb.ogg')
else
use_sound = pick('sound/effects/mob_effects/m_machine_cougha.ogg','sound/effects/mob_effects/m_machine_coughb.ogg', 'sound/effects/mob_effects/m_machine_coughc.ogg')
else if(act == "rsneeze")
display_msg = "emits a robotic sneeze"
if(gender == FEMALE)
use_sound = 'sound/effects/mob_effects/machine_sneeze.ogg'
else
use_sound = 'sound/effects/mob_effects/f_machine_sneeze.ogg'
if (param)
message = "[display_msg] at [param]."
@@ -62,6 +75,17 @@
playsound(src.loc, use_sound, 50, 0)
m_type = 1
//Promethean-only emotes
if("squish")
if(!species.bump_flag == SLIME) //That should do, yaya.
src << "<span class='warning'>You are not a slime thing!</span>"
return
playsound(src.loc, 'sound/effects/slime_squish.ogg', 50, 0) //Credit to DrMinky (freesound.org) for the sound.
message = "squishes."
m_type = 1
if ("blink")
message = "blinks."
m_type = 1
@@ -202,14 +226,20 @@
src.sleeping += 10 //Short-short nap
m_type = 1
if ("cough")
if("cough", "coughs")
if(miming)
message = "appears to cough!"
m_type = 1
else
if (!muzzled)
if(!muzzled)
message = "coughs!"
m_type = 2
if(gender == FEMALE)
if(species.female_cough_sounds)
playsound(src, pick(species.female_cough_sounds), 120)
else
if(species.male_cough_sounds)
playsound(src, pick(species.male_cough_sounds), 120)
else
message = "makes a strong noise."
m_type = 2
@@ -456,13 +486,17 @@
message = "trembles in fear!"
m_type = 1
if ("sneeze")
if (miming)
if("sneeze", "sneezes")
if(miming)
message = "sneezes."
m_type = 1
else
if (!muzzled)
if(!muzzled)
message = "sneezes."
if(gender == FEMALE)
playsound(src, species.female_sneeze_sound, 70)
else
playsound(src, species.male_sneeze_sound, 70)
m_type = 2
else
message = "makes a strange noise."
@@ -565,18 +599,59 @@
else
message = "sadly can't find anybody to give daps to, and daps [get_visible_gender() == MALE ? "himself" : get_visible_gender() == FEMALE ? "herself" : "themselves"]. Shameful."
if ("scream")
if (miming)
if("slap", "slaps")
m_type = 1
if(!restrained())
var/M = null
if(param)
for(var/mob/A in view(1, null))
if(param == A.name)
M = A
break
if(M)
message = "<span class='danger'>slaps [M] across the face. Ouch!</span>"
playsound(loc, 'sound/effects/snap.ogg', 50, 1)
else
message = "<span class='danger'>slaps [get_visible_gender() == MALE ? "himself" : get_visible_gender() == FEMALE ? "herself" : "themselves"]!</span>"
playsound(loc, 'sound/effects/snap.ogg', 50, 1)
if("scream", "screams")
if(miming)
message = "acts out a scream!"
m_type = 1
else
if (!muzzled)
message = "screams!"
if(!muzzled)
message = "[species.scream_verb]!"
m_type = 2
/* Removed, pending the location of some actually good, properly licensed sounds.
if(gender == FEMALE)
playsound(loc, "[species.female_scream_sound]", 80, 1)
else
playsound(loc, "[species.male_scream_sound]", 80, 1) //default to male screams if no gender is present.
*/
else
message = "makes a very loud noise."
m_type = 2
if("snap", "snaps")
m_type = 2
var/mob/living/carbon/human/H = src
var/obj/item/organ/external/L = H.get_organ("l_hand")
var/obj/item/organ/external/R = H.get_organ("r_hand")
var/left_hand_good = 0
var/right_hand_good = 0
if(L && (!(L.status & ORGAN_DESTROYED)) && (!(L.splinted)) && (!(L.status & ORGAN_BROKEN)))
left_hand_good = 1
if(R && (!(R.status & ORGAN_DESTROYED)) && (!(R.splinted)) && (!(R.status & ORGAN_BROKEN)))
right_hand_good = 1
if(!left_hand_good && !right_hand_good)
to_chat(usr, "You need at least one hand in good working order to snap your fingers.")
return
message = "snaps [get_visible_gender() == MALE ? "his" : get_visible_gender() == FEMALE ? "her" : "their"] fingers."
playsound(loc, 'sound/effects/fingersnap.ogg', 50, 1, -3)
if("swish")
src.animate_tail_once()
@@ -597,18 +672,14 @@
return
if ("help")
src << {"blink, blink_r, blush, bow-(none)/mob, burp, choke, chuckle, clap, collapse, cough, cry, custom, deathgasp, drool, eyebrow, fastsway/qwag,
frown, gasp, giggle, glare-(none)/mob, grin, groan, grumble, handshake, hug-(none)/mob, laugh, look-(none)/mob, moan, mumble, nod, pale, point-atom,
raise, salute, shake, shiver, shrug, sigh, signal-#1-10, smile, sneeze, sniff, snore, stare-(none)/mob, stopsway/swag, sway/wag, swish, tremble, twitch,
twitch_v, vomit, whimper, wink, yawn"}
src << "blink, blink_r, blush, bow-(none)/mob, burp, choke, chuckle, clap, collapse, cough, cry, custom, deathgasp, drool, eyebrow, fastsway/qwag, \
frown, gasp, giggle, glare-(none)/mob, grin, groan, grumble, handshake, hug-(none)/mob, laugh, look-(none)/mob, moan, mumble, nod, pale, point-atom, \
raise, salute, scream, sneeze, shake, shiver, shrug, sigh, signal-#1-10, slap-(none)/mob, smile, sneeze, sniff, snore, stare-(none)/mob, stopsway/swag, sway/wag, swish, tremble, twitch, \
twitch_v, vomit, whimper, wink, yawn. Synthetics: beep, buzz, yes, no, rcough, rsneeze, ping"
else
src << "\blue Unusable emote '[act]'. Say *help for a list."
if (message)
log_emote("[name]/[key] : [message]")
custom_emote(m_type,message)

View File

@@ -280,7 +280,7 @@
msg += "<span class='warning'>[T.He] [T.is] twitching ever so slightly.</span>\n"
//splints
for(var/organ in list(BP_L_LEG, BP_R_LEG, BP_L_ARM, BP_R_ARM))
for(var/organ in BP_ALL)
var/obj/item/organ/external/o = get_organ(organ)
if(o && o.splinted && o.splinted.loc == o)
msg += "<span class='warning'>[T.He] [T.has] \a [o.splinted] on [T.his] [o.name]!</span>\n"

View File

@@ -695,7 +695,7 @@
if(istype(src.glasses, /obj/item/clothing/glasses/sunglasses))
if(istype(src.glasses, /obj/item/clothing/glasses/sunglasses/sechud/aviator))
var/obj/item/clothing/glasses/sunglasses/sechud/aviator/S = src.glasses
if(!S.active)
if(!S.on)
number += 1
else if(istype(src.glasses, /obj/item/clothing/glasses/sunglasses/medhud/aviator))
number += 0
@@ -1050,7 +1050,7 @@
"<span class='warning'>A spike of pain jolts your [organ.name] as you bump [O] inside.</span>", \
"<span class='warning'>Your movement jostles [O] in your [organ.name] painfully.</span>", \
"<span class='warning'>Your movement jostles [O] in your [organ.name] painfully.</span>")
src << msg
custom_pain(msg, 40)
organ.take_damage(rand(1,3), 0, 0)
if(!(organ.robotic >= ORGAN_ROBOT) && (should_have_organ(O_HEART))) //There is no blood in protheses.
@@ -1452,6 +1452,7 @@
if(stat) return
var/datum/category_group/underwear/UWC = input(usr, "Choose underwear:", "Show/hide underwear") as null|anything in global_underwear.categories
if(!UWC) return
var/datum/category_item/underwear/UWI = all_underwear[UWC.name]
if(!UWI || UWI.name == "None")
src << "<span class='notice'>You do not have [UWC.gender==PLURAL ? "[UWC.display_name]" : "\a [UWC.display_name]"].</span>"
@@ -1489,7 +1490,7 @@
if(check_organ)
if(!istype(check_organ))
return 0
return check_organ.can_feel_pain()
return check_organ.organ_can_feel_pain()
return !(species.flags & NO_PAIN)
/mob/living/carbon/human/is_muzzled()

View File

@@ -22,7 +22,7 @@
// Should this all be in Touch()?
if(istype(H))
if(get_accuracy_penalty(H)) //Should only trigger if they're not aiming well
if(get_accuracy_penalty(H) && H != src) //Should only trigger if they're not aiming well
var/hit_zone = get_zone_with_miss_chance(H.zone_sel.selecting, src, get_accuracy_penalty(H))
if(!hit_zone)
H.do_attack_animation(src)
@@ -43,6 +43,7 @@
return 0
var/obj/item/organ/external/affecting = get_organ(ran_zone(H.zone_sel.selecting))
var/armor_block = run_armor_check(affecting, "melee")
var/armor_soak = get_armor_soak(affecting, "melee")
if(HULK in H.mutations)
damage += 5
@@ -51,7 +52,10 @@
visible_message("\red <B>[H] has punched [src]!</B>")
apply_damage(damage, HALLOSS, affecting, armor_block)
if(armor_soak >= damage)
return
apply_damage(damage, HALLOSS, affecting, armor_block, armor_soak)
if(damage >= 9)
visible_message("\red <B>[H] has weakened [src]!</B>")
apply_effect(4, WEAKEN, armor_block)
@@ -245,11 +249,12 @@
real_damage = max(1, real_damage)
var/armour = run_armor_check(affecting, "melee")
var/soaked = get_armor_soak(affecting, "melee")
// Apply additional unarmed effects.
attack.apply_effects(H, src, armour, rand_damage, hit_zone)
// Finally, apply damage to target
apply_damage(real_damage, (attack.deal_halloss ? HALLOSS : BRUTE), affecting, armour, sharp=attack.sharp, edge=attack.edge)
apply_damage(real_damage, (attack.deal_halloss ? HALLOSS : BRUTE), affecting, armour, soaked, sharp=attack.sharp, edge=attack.edge)
if(I_DISARM)
M.attack_log += text("\[[time_stamp()]\] <font color='red'>Disarmed [src.name] ([src.ckey])</font>")
@@ -325,7 +330,8 @@
var/dam_zone = pick(organs_by_name)
var/obj/item/organ/external/affecting = get_organ(ran_zone(dam_zone))
var/armor_block = run_armor_check(affecting, "melee")
apply_damage(damage, BRUTE, affecting, armor_block)
var/armor_soak = get_armor_soak(affecting, "melee")
apply_damage(damage, BRUTE, affecting, armor_block, armor_soak)
updatehealth()
return 1

View File

@@ -376,7 +376,7 @@ This function restores all organs.
if((damagetype != BRUTE) && (damagetype != BURN))
if(damagetype == HALLOSS)
if((damage > 25 && prob(20)) || (damage > 50 && prob(60)))
if(organ && organ.can_feel_pain())
if(organ && organ.organ_can_feel_pain())
emote("scream")
..(damage, damagetype, def_zone, blocked)
return 1

View File

@@ -67,7 +67,7 @@ emp_act
emote("me", 1, "drops what they were holding, their [affected.name] malfunctioning!")
else
var/emote_scream = pick("screams in pain and ", "lets out a sharp cry and ", "cries out and ")
emote("me", 1, "[affected.can_feel_pain() ? "" : emote_scream]drops what they were holding in their [affected.name]!")
emote("me", 1, "[affected.organ_can_feel_pain() ? "" : emote_scream] drops what they were holding in their [affected.name]!")
..(stun_amount, agony_amount, def_zone)
@@ -93,6 +93,29 @@ emp_act
total += weight
return (armorval/max(total, 1))
//Like getarmor, but the value it returns will be numerical damage reduction
/mob/living/carbon/human/getsoak(var/def_zone, var/type)
var/soakval = 0
var/total = 0
if(def_zone)
if(isorgan(def_zone))
return getsoak_organ(def_zone, type)
var/obj/item/organ/external/affecting = get_organ(def_zone)
if(affecting)
return getsoak_organ(affecting, type)
//If a specific bodypart is targetted, check how that bodypart is protected and return the value.
//If you don't specify a bodypart, it checks ALL your bodyparts for protection, and averages out the values
for(var/organ_name in organs_by_name)
if (organ_name in organ_rel_size)
var/obj/item/organ/external/organ = organs_by_name[organ_name]
if(organ)
var/weight = organ_rel_size[organ_name]
soakval += getsoak_organ(organ, type) * weight
total += weight
return (soakval/max(total, 1))
//this proc returns the Siemens coefficient of electrical resistivity for a particular external organ.
/mob/living/carbon/human/proc/get_siemens_coefficient_organ(var/obj/item/organ/external/def_zone)
if (!def_zone)
@@ -119,6 +142,17 @@ emp_act
protection += C.armor[type]
return protection
/mob/living/carbon/human/proc/getsoak_organ(var/obj/item/organ/external/def_zone, var/type)
if(!type || !def_zone) return 0
var/soaked = 0
var/list/protective_gear = list(head, wear_mask, wear_suit, w_uniform, gloves, shoes)
for(var/gear in protective_gear)
if(gear && istype(gear ,/obj/item/clothing))
var/obj/item/clothing/C = gear
if(istype(C) && C.body_parts_covered & def_zone.body_part)
soaked += C.armorsoak[type]
return soaked
/mob/living/carbon/human/proc/check_head_coverage()
var/list/body_parts = list(head, wear_mask, wear_suit, w_uniform)
@@ -195,25 +229,35 @@ emp_act
visible_message("<span class='danger'>[src] has been [I.attack_verb.len? pick(I.attack_verb) : "attacked"] in the [affecting.name] with [I.name] by [user]!</span>")
var/soaked = get_armor_soak(hit_zone, "melee", I.armor_penetration)
if(soaked >= effective_force)
src << "Your armor absorbs the force of [I.name]!"
return
var/blocked = run_armor_check(hit_zone, "melee", I.armor_penetration, "Your armor has protected your [affecting.name].", "Your armor has softened the blow to your [affecting.name].")
standard_weapon_hit_effects(I, user, effective_force, blocked, hit_zone)
standard_weapon_hit_effects(I, user, effective_force, blocked, soaked, hit_zone)
return blocked
/mob/living/carbon/human/standard_weapon_hit_effects(obj/item/I, mob/living/user, var/effective_force, var/blocked, var/hit_zone)
/mob/living/carbon/human/standard_weapon_hit_effects(obj/item/I, mob/living/user, var/effective_force, var/blocked, var/soaked, var/hit_zone)
var/obj/item/organ/external/affecting = get_organ(hit_zone)
if(!affecting)
return 0
if(soaked >= effective_force)
return 0
// Handle striking to cripple.
if(user.a_intent == I_DISARM)
effective_force *= 0.5 //reduced effective force...
if(!..(I, user, effective_force, blocked, hit_zone))
if(!..(I, user, effective_force, blocked, soaked, hit_zone))
return 0
//set the dislocate mult less than the effective force mult so that
//dislocating limbs on disarm is a bit easier than breaking limbs on harm
attack_joint(affecting, I, effective_force, 0.75, blocked) //...but can dislocate joints
attack_joint(affecting, I, effective_force, 0.75, blocked, soaked) //...but can dislocate joints
else if(!..())
return 0
@@ -243,7 +287,7 @@ emp_act
switch(hit_zone)
if("head")//Harder to score a stun but if you do it lasts a bit longer
if(prob(effective_force))
apply_effect(20, PARALYZE, blocked)
apply_effect(20, PARALYZE, blocked, soaked)
visible_message("<span class='danger'>\The [src] has been knocked unconscious!</span>")
if(bloody)//Apply blood
if(wear_mask)
@@ -257,15 +301,15 @@ emp_act
update_inv_glasses(0)
if("chest")//Easier to score a stun but lasts less time
if(prob(effective_force + 10))
apply_effect(6, WEAKEN, blocked)
apply_effect(6, WEAKEN, blocked, soaked)
visible_message("<span class='danger'>\The [src] has been knocked down!</span>")
if(bloody)
bloody_body(src)
return 1
/mob/living/carbon/human/proc/attack_joint(var/obj/item/organ/external/organ, var/obj/item/W, var/effective_force, var/dislocate_mult, var/blocked)
if(!organ || (organ.dislocated == 2) || (organ.dislocated == -1) || blocked >= 100)
/mob/living/carbon/human/proc/attack_joint(var/obj/item/organ/external/organ, var/obj/item/W, var/effective_force, var/dislocate_mult, var/blocked, var/soaked)
if(!organ || (organ.dislocated == 2) || (organ.dislocated == -1) || blocked >= 100 || soaked > effective_force)
return 0
if(W.damtype != BRUTE)
@@ -338,10 +382,6 @@ emp_act
var/hit_area = affecting.name
src.visible_message("\red [src] has been hit in the [hit_area] by [O].")
var/armor = run_armor_check(affecting, "melee", O.armor_penetration, "Your armor has protected your [hit_area].", "Your armor has softened hit to your [hit_area].") //I guess "melee" is the best fit here
if(armor < 100)
apply_damage(throw_damage, dtype, zone, armor, is_sharp(O), has_edge(O), O)
if(ismob(O.thrower))
var/mob/M = O.thrower
@@ -352,12 +392,25 @@ emp_act
if(!istype(src,/mob/living/simple_animal/mouse))
msg_admin_attack("[src.name] ([src.ckey]) was hit by a [O], thrown by [M.name] ([assailant.ckey]) (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[src.x];Y=[src.y];Z=[src.z]'>JMP</a>)")
//If the armor absorbs all of the damage, skip the rest of the calculations
var/soaked = get_armor_soak(affecting, "melee", O.armor_penetration)
if(soaked >= throw_damage)
src << "Your armor absorbs the force of [O.name]!"
return
var/armor = run_armor_check(affecting, "melee", O.armor_penetration, "Your armor has protected your [hit_area].", "Your armor has softened hit to your [hit_area].") //I guess "melee" is the best fit here
if(armor < 100)
apply_damage(throw_damage, dtype, zone, armor, soaked, is_sharp(O), has_edge(O), O)
//thrown weapon embedded object code.
if(dtype == BRUTE && istype(O,/obj/item))
var/obj/item/I = O
if (!is_robot_module(I))
var/sharp = is_sharp(I)
var/damage = throw_damage
if (soaked)
damage -= soaked
if (armor)
damage /= armor+1

View File

@@ -37,7 +37,7 @@
var/list/all_underwear_metadata = list()
var/list/hide_underwear = list()
var/backbag = 2 //Which backpack type the player has chosen. Nothing, Satchel or Backpack.
var/pdachoice = 1 //Which PDA type the player has chosen. Default, Slim, or Old.
var/pdachoice = 1 //Which PDA type the player has chosen. Default, Slim, Old, or Rugged.
// General information
var/home_system = ""

View File

@@ -2,6 +2,8 @@
var/tally = 0
var/item_tally = 0
if(species.slowdown)
tally = species.slowdown
@@ -33,7 +35,7 @@
tally += 1.5
else
if(shoes)
tally += shoes.slowdown
item_tally += shoes.slowdown
for(var/organ_name in list(BP_L_LEG, BP_R_LEG, BP_L_FOOT, BP_R_FOOT))
var/obj/item/organ/external/E = get_organ(organ_name)
@@ -50,36 +52,40 @@
if(FAT in src.mutations)
tally += 1.5
if (bodytemperature < 283.222)
tally += (283.222 - bodytemperature) / 10 * 1.75
if (bodytemperature < species.cold_level_1)
tally += (species.cold_level_1 - bodytemperature) / 10 * 1.75
tally += max(2 * stance_damage, 0) //damaged/missing feet or legs is slow
if(mRun in mutations)
tally = 0
if(species.slowdown_fixed)
return (tally+config.human_delay)
// Loop through some slots, and add up their slowdowns. Shoes are handled below, unfortunately.
// Includes slots which can provide armor, the back slot, and suit storage.
for(var/obj/item/I in list(wear_suit, w_uniform, back, gloves, head, s_store) )
tally += I.slowdown
for(var/obj/item/I in list(wear_suit, w_uniform, back, gloves, head, s_store))
item_tally += I.slowdown
// Hands are also included, to make the 'take off your armor instantly and carry it with you to go faster' trick no longer viable.
// This is done seperately to disallow negative numbers.
for(var/obj/item/I in list(r_hand, l_hand) )
tally += max(I.slowdown, 0)
item_tally += max(I.slowdown, 0)
// Dragging heavy objects will also slow you down, similar to above.
if(pulling && istype(pulling, /obj/item))
var/obj/item/pulled = pulling
tally += max(pulled.slowdown, 0)
item_tally += max(pulled.slowdown, 0)
var/turf/T = get_turf(src)
if(T && T.movement_cost)
tally += T.movement_cost
if(species.item_slowdown_halved)
if(item_tally > 0)
item_tally *= 0.5
tally += item_tally
if(CE_SPEEDBOOST in chem_effects)
if (tally >= 0) // cut any penalties in half
tally = tally/2

View File

@@ -56,7 +56,7 @@
if (!lying && !buckled && world.time - l_move_time < 15)
//Moving around with fractured ribs won't do you any good
if (prob(10) && !stat && can_feel_pain() && analgesic < 50 && E.is_broken() && E.internal_organs.len)
if (prob(10) && !stat && can_feel_pain() && chem_effects[CE_PAINKILLER] < 50 && E.is_broken() && E.internal_organs.len)
custom_pain("Pain jolts through your broken [E.encased ? E.encased : E.name], staggering you!", 50)
drop_item(loc)
Stun(2)
@@ -100,7 +100,7 @@
else if (E.is_dislocated())
stance_damage += 0.5
if(E) limb_pain = E.can_feel_pain()
if(E) limb_pain = E.organ_can_feel_pain()
// Canes and crutches help you stand (if the latter is ever added)
// One cane mitigates a broken leg+foot, or a missing foot.
@@ -159,7 +159,7 @@
drop_from_inventory(r_hand)
var/emote_scream = pick("screams in pain and ", "lets out a sharp cry and ", "cries out and ")
emote("me", 1, "[(E.can_feel_pain()) ? "" : emote_scream ]drops what they were holding in their [E.name]!")
emote("me", 1, "[(can_feel_pain()) ? "" : emote_scream ]drops what they were holding in their [E.name]!")
else if(E.is_malfunctioning())
switch(E.body_part)

View File

@@ -186,7 +186,7 @@
var/rn = rand(0, 200)
if(getBrainLoss() >= 5)
if(0 <= rn && rn <= 3)
custom_pain("Your head feels numb and painful.")
custom_pain("Your head feels numb and painful.", 10)
if(getBrainLoss() >= 15)
if(4 <= rn && rn <= 6) if(eye_blurry <= 0)
src << "<span class='warning'>It becomes hard to see for some reason.</span>"
@@ -328,17 +328,20 @@
if(status_flags & GODMODE)
return
if(suiciding)
failed_last_breath = 1
adjustOxyLoss(2)//If you are suiciding, you should die a little bit faster
oxygen_alert = max(oxygen_alert, 1)
suiciding --
return 0
if(does_not_breathe)
failed_last_breath = 0
adjustOxyLoss(-5)
return
if(!breath || (breath.total_moles == 0) || suiciding)
if(!breath || (breath.total_moles == 0))
failed_last_breath = 1
if(suiciding)
adjustOxyLoss(2)//If you are suiciding, you should die a little bit faster
oxygen_alert = max(oxygen_alert, 1)
return 0
if(health > config.health_threshold_crit)
adjustOxyLoss(HUMAN_MAX_OXYLOSS)
else
@@ -349,10 +352,6 @@
if(!L.is_bruised() && prob(8))
rupture_lung()
if(should_have_organ("brain"))
if(prob(5))
adjustBrainLoss(0.02 * oxyloss) //2% of your current oxyloss is applied as brain damage, 50 oxyloss is 1 brain damage
oxygen_alert = max(oxygen_alert, 1)
return 0
@@ -371,8 +370,9 @@
safe_pressure_min *= 1.25
else if(breath)
if(breath.total_moles < BREATH_MOLES / 10 || breath.total_moles > BREATH_MOLES * 5)
if (prob(8))
rupture_lung()
if(is_below_sound_pressure(get_turf(src))) //No more popped lungs from choking/drowning
if (prob(8))
rupture_lung()
var/safe_exhaled_max = 10
var/safe_toxins_max = 0.2
@@ -794,7 +794,6 @@
if(reagents)
chem_effects.Cut()
analgesic = 0
if(!isSynthetic())
@@ -802,9 +801,6 @@
if(ingested) ingested.metabolize()
if(bloodstr) bloodstr.metabolize()
if(CE_PAINKILLER in chem_effects)
analgesic = chem_effects[CE_PAINKILLER]
var/total_phoronloss = 0
for(var/obj/item/I in src)
if(I.contaminated)
@@ -923,6 +919,14 @@
for(var/atom/a in hallucinations)
qdel(a)
//Brain damage from Oxyloss
if(should_have_organ("brain"))
var/brainOxPercent = 0.015 //Default 1.5% of your current oxyloss is applied as brain damage, 50 oxyloss is 1 brain damage
if(CE_STABLE in chem_effects)
brainOxPercent = 0.008 //Halved in effect
if(oxyloss >= 20 && prob(5))
adjustBrainLoss(brainOxPercent * oxyloss)
if(halloss >= species.total_health)
src << "<span class='notice'>You're in too much pain to keep going...</span>"
src.visible_message("<B>[src]</B> slumps to the ground, too weak to continue fighting.")
@@ -1155,7 +1159,7 @@
see_invisible = SEE_INVISIBLE_LIVING
if(healths)
if (analgesic > 100)
if (chem_effects[CE_PAINKILLER] > 100)
healths.icon_state = "health_numb"
else
// Generate a by-limb health display.
@@ -1437,8 +1441,11 @@
shock_stage = max(shock_stage-1, 0)
return
if(stat)
return 0
if(shock_stage == 10)
src << "<span class='danger'>[pick("It hurts so much", "You really need some painkillers", "Dear god, the pain")]!</span>"
custom_pain("[pick("It hurts so much", "You really need some painkillers", "Dear god, the pain")]!", 40)
if(shock_stage >= 30)
if(shock_stage == 30) emote("me",1,"is having trouble keeping their eyes open.")

View File

@@ -22,6 +22,14 @@
speech_sounds = list('sound/voice/shriek1.ogg')
speech_chance = 20
scream_verb = "shrieks"
male_scream_sound = 'sound/voice/shriek1.ogg'
female_scream_sound = 'sound/voice/shriek1.ogg'
male_cough_sounds = list('sound/voice/shriekcough.ogg')
female_cough_sounds = list('sound/voice/shriekcough.ogg')
male_sneeze_sound = 'sound/voice/shrieksneeze.ogg'
female_sneeze_sound = 'sound/voice/shrieksneeze.ogg'
warning_low_pressure = 50
hazard_low_pressure = 0

View File

@@ -50,6 +50,15 @@
var/num_alternate_languages = 0 // How many secondary languages are available to select at character creation
var/name_language = LANGUAGE_GALCOM // The language to use when determining names for this species, or null to use the first name/last name generator
//Soundy emotey things.
var/scream_verb = "screams"
var/male_scream_sound //= 'sound/goonstation/voice/male_scream.ogg' Removed due to licensing, replace!
var/female_scream_sound //= 'sound/goonstation/voice/female_scream.ogg' Removed due to licensing, replace!
var/male_cough_sounds = list('sound/effects/mob_effects/m_cougha.ogg','sound/effects/mob_effects/m_coughb.ogg', 'sound/effects/mob_effects/m_coughc.ogg')
var/female_cough_sounds = list('sound/effects/mob_effects/f_cougha.ogg','sound/effects/mob_effects/f_coughb.ogg')
var/male_sneeze_sound = 'sound/effects/mob_effects/sneeze.ogg'
var/female_sneeze_sound = 'sound/effects/mob_effects/f_sneeze.ogg'
// Combat vars.
var/total_health = 100 // Point at which the mob will enter crit.
var/list/unarmed_types = list( // Possible unarmed attacks that the mob will use in combat,
@@ -63,6 +72,7 @@
var/toxins_mod = 1 // Toxloss modifier
var/radiation_mod = 1 // Radiation modifier
var/flash_mod = 1 // Stun from blindness modifier.
var/chemOD_mod = 1 // Damage modifier for overdose
var/vision_flags = SEE_SELF // Same flags as glasses.
// Death vars.
@@ -123,7 +133,7 @@
var/appearance_flags = 0 // Appearance/display related features.
var/spawn_flags = 0 // Flags that specify who can spawn as this species
var/slowdown = 0 // Passive movement speed malus (or boost, if negative)
var/slowdown_fixed = 0 // If this is on, they're not affected by object related slowdown (positive or negative)
var/item_slowdown_halved = 0 // If this is on, they're not as affected by item weights for slowdown
var/primitive_form // Lesser form, if any (ie. monkey for humans)
var/greater_form // Greater form, if any, ie. human for monkeys.
var/holder_type
@@ -184,8 +194,8 @@
inherent_verbs = list()
inherent_verbs |= /mob/living/carbon/human/proc/regurgitate
/datum/species/proc/sanitize_name(var/name)
return sanitizeName(name)
/datum/species/proc/sanitize_name(var/name, var/robot = 0)
return sanitizeName(name, MAX_NAME_LEN, robot)
/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

View File

@@ -28,6 +28,9 @@ var/datum/species/shapeshifter/promethean/prometheans
breath_type = null
poison_type = null
male_cough_sounds = list('sound/effects/slime_squish.ogg')
female_cough_sounds = list('sound/effects/slime_squish.ogg')
gluttonous = 1
virus_immune = 1
blood_volume = 560

View File

@@ -31,9 +31,11 @@
unarmed_types = list(/datum/unarmed_attack/stomp, /datum/unarmed_attack/kick, /datum/unarmed_attack/claws, /datum/unarmed_attack/bite/sharp)
primitive_form = "Stok"
darksight = 3
ambiguous_genders = TRUE
gluttonous = 1
slowdown = 0.5
brute_mod = 0.8
brute_mod = 0.9
burn_mod = 0.9
num_alternate_languages = 3
secondary_langs = list(LANGUAGE_UNATHI)
name_language = LANGUAGE_UNATHI
@@ -94,6 +96,7 @@
slowdown = -0.5
brute_mod = 1.15
burn_mod = 1.15
flash_mod = 1.1
metabolic_rate = 1.1
gluttonous = 1
num_alternate_languages = 3
@@ -136,6 +139,15 @@
)
cold_discomfort_level = 275
has_organ = list( //No appendix.
O_HEART = /obj/item/organ/internal/heart,
O_LUNGS = /obj/item/organ/internal/lungs,
O_LIVER = /obj/item/organ/internal/liver,
O_KIDNEYS = /obj/item/organ/internal/kidneys,
O_BRAIN = /obj/item/organ/internal/brain,
O_EYES = /obj/item/organ/internal/eyes
)
/datum/species/tajaran/equip_survival_gear(var/mob/living/carbon/human/H)
..()
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(H),slot_shoes)
@@ -158,9 +170,11 @@
health_hud_intensity = 2
min_age = 19
max_age = 80
max_age = 130
darksight = 4
flash_mod = 1.2
chemOD_mod = 0.9
ambiguous_genders = TRUE

View File

@@ -97,7 +97,7 @@ var/global/list/sparring_attack_cache = list()
if(eyes)
eyes.take_damage(rand(3,4), 1)
user.visible_message("<span class='danger'>[user] presses \his [eye_attack_text] into [target]'s [eyes.name]!</span>")
var/eye_pain = eyes.can_feel_pain()
var/eye_pain = eyes.organ_can_feel_pain()
target << "<span class='danger'>You experience[(eye_pain) ? "" : " immense pain as you feel" ] [eye_attack_text_victim] being pressed into your [eyes.name][(eye_pain)? "." : "!"]</span>"
return
user.visible_message("<span class='danger'>[user] attempts to press \his [eye_attack_text] into [target]'s eyes, but they don't have any!</span>")

View File

@@ -257,25 +257,26 @@ var/global/list/damage_icon_parts = list()
var/obj/item/organ/external/part = organs_by_name[organ_tag]
if(isnull(part) || part.is_stump())
icon_key += "0"
else if(part.robotic >= ORGAN_ROBOT)
icon_key += "2[part.model ? "-[part.model]": ""]"
robolimb_count++
if(part.organ_tag == BP_HEAD || part.organ_tag == BP_TORSO || part.organ_tag == BP_GROIN)
robobody_count ++
else if(part.status & ORGAN_DEAD)
icon_key += "3"
else
icon_key += "1"
continue
if(part)
icon_key += "[part.species.get_race_key(part.owner)]"
icon_key += "[part.dna.GetUIState(DNA_UI_GENDER)]"
icon_key += "[part.dna.GetUIValue(DNA_UI_SKIN_TONE)]"
icon_key += "[part.s_tone]"
if(part.s_col && part.s_col.len >= 3)
icon_key += "[rgb(part.s_col[1],part.s_col[2],part.s_col[3])]"
if(part.body_hair && part.h_col && part.h_col.len >= 3)
icon_key += "[rgb(part.h_col[1],part.h_col[2],part.h_col[3])]"
else
icon_key += "#000000"
for(var/M in part.markings)
icon_key += "[M][part.markings[M]["color"]]"
if(part.robotic >= ORGAN_ROBOT)
icon_key += "2[part.model ? "-[part.model]": ""]"
else if(part.status & ORGAN_DEAD)
icon_key += "3"
else
icon_key += "1"
icon_key = "[icon_key][husk ? 1 : 0][fat ? 1 : 0][hulk ? 1 : 0][skeleton ? 1 : 0]"

View File

@@ -67,15 +67,11 @@
/mob/living/carbon/slime/handle_chemicals_in_body()
chem_effects.Cut()
analgesic = 0
if(touching) touching.metabolize()
if(ingested) ingested.metabolize()
if(bloodstr) bloodstr.metabolize()
if(CE_PAINKILLER in chem_effects)
analgesic = chem_effects[CE_PAINKILLER]
src.updatehealth()
return //TODO: DEFERRED

View File

@@ -60,7 +60,7 @@
var/painMes = pick("You can feel your body becoming weak!", "You feel like you're about to die!", "You feel every part of your body screaming in agony!", "A low, rolling pain passes through your body!", "Your body feels as if it's falling apart!", "You feel extremely weak!", "A sharp, deep pain bathes every inch of your body!")
if (ishuman(M))
var/mob/living/carbon/human/H = M
H.custom_pain(painMes)
H.custom_pain(painMes, 100)
else if (istype(M, /mob/living/carbon))
var/mob/living/carbon/C = M
if (C.can_feel_pain())

Some files were not shown because too many files have changed in this diff Show More