Skip to content

Instantly share code, notes, and snippets.

@factorsofx
Created July 12, 2017 05:55
Show Gist options
  • Save factorsofx/f05d9fb02e360f90abd1411b22178841 to your computer and use it in GitHub Desktop.
Save factorsofx/f05d9fb02e360f90abd1411b22178841 to your computer and use it in GitHub Desktop.
Every single comment from the Goonstation 2016 release, without any actual code!
This file has been truncated, but you can view the full file.
// Compile-time config flags
// Enable if btime is installed
//#define PRECISE_TIMER_AVAILABLE
// Debug flags
// Delete queue debug toggle
// This is expensive. don't turn it on on the server unless you want things to be bad and slow
// #define DELETE_QUEUE_DEBUG
//#define UPDATE_QUEUE_DEBUG
// Image deletion debug
// DO NOT ENABLE THIS ON THE SERVER FOR FUCKS SAKE
//#define IMAGE_DEL_DEBUG
// Machine processing debug
//Apparently not that hefty but still
//#define MACHINE_PROCESSING_DEBUG
//Queue worker statistics
//Probably hefty
//#define QUEUE_STAT_DEBUG
// Map overrides
// Construction mode
//#define MAP_OVERRIDE_CONSTRUCTION
// Destiny/RP
//#define MAP_OVERRIDE_DESTINY
//#define MAP_OVERRIDE_TEST
// MR MARIO HE WAS A PIPE LAYER
// Mob clothing and effect layers
// FLOAT_LAYER
// helmets
// masks
// gloves
// bit missleading name, used for more than just belts
// Some effects were defined on layer 10, some on layer 20... Lets unify this...
// These are for effects that should display below lighting
// Use this for shit that should appear above everything else but under actual effects
// Overlay effects layers - Formerly layer 11 -- primarily for lighting.
// Effects that should display above the lighting overlays
// HUD Layers - Formerly layer 20
// i think its slightly faster to do this with compiler macros instead of procs. i might be a moron, not sure - drsingh
// it is. no comment on the moron bit. -- marq
// For antag overlays.
//istype(x, /mob/living/silicon/shell)
// I'm grump that we don't already have these so I'm adding them. will we use all of them? probably not. but we have them. - Haine
// Hi, Marquesas here. Eliminating all ':' would be nice. Can we do that somehow? Thanks.
// Macros with abilityHolder or mutantrace defines are used for more than antagonist checks, so don't replace them with mind.special_role.
// Why the separate mask check? NPCs don't use assigned_role and we still wanna play the cluwne-specific sound effects.
// pick strings from cache-- code/procs/string_cache.dm
/* Protip: Prepending an underscore to this file puts it at the top of the compile order,
// so that it already has the defines for the later files that use them.
*/
//Time (in 1/10 of a second) before we can be manually reset again (machines).
//Action defines
//Internal flag that will always interrupt any action.
//Interrupted when object moves
//Interrupted when object does anything
//Interrupted when object is attacked
//Interrupted when owner is stunned or knocked out etc.
//Interrupted when another action is started.
//Action has not been started yet.
//Action is in progress
//Action was interrupted
//Action ended succesfully
//Action is ready to be deleted.
//Will finish action after next process.
//Will not finish unless interrupted.
//Action defines END
//Material flag defines
//Crystals, Minerals
//Metals
//Cloth or cloth-like
//Coal, meat and whatnot.
//Is energy or outputs energy.
//Rubber , latex etc
//At which alpha do opague objects become see-through?
//---
//Very specific cruiser defines
//Fire only left weapon
//Fire only right weapon
//Fire both weapons
//Alternate between the weapons.
//not exact but hey!
//Higher values result in more external fire damage to the skin (default 0.0215)
//More means less damage from hot air scalding lungs, less = more damage. (default 2.025)
//closer then enough
//#define nround(x, n) round(x, 10 ** n)
//#define floor(x) round(x)
//#define ceiling(x) -round(-x)
//Don't set this very much higher then 1024 unless you like inviting people in to dos your server with message spam
//kPa*L/(K*mol)
//kPa
//liters in a cell
//moles in a 2.5 m^3 cell at 101.325 Pa and 20 degC
//
// O2 standard value (21%)
// N2 standard value (79%)
//Moles in a standard cell after which plasma is visible
//liters in a normal breath
//Amount of air to take a from a tile
//Amount of air needed before pass out/suffocation commences
//Minimum ratio of air that must move to/from a tile to suspend group processing
//Minimum amount of air that has to move before a group processing can be suspended
//Either this must be active
//or this (or both, obviously)
//Minimum temperature difference before group processing is suspended
//Minimum temperature difference before the gas temperatures are just set to be equal
//a hack to partly simulate radiative heat
//a hack for now
//Must be between 0 and 1. Values closer to 1 equalize temperature faster
//Should not exceed 0.4 else strange heat flow occur
//Amount of heat released per mole of burnt carbon into the tile
//Amount of heat released per mole of burnt plasma into the tile
//For small fires
//Plasma fire properties
// 0degC
// 20degC
// -270.3degC
// Tank starts leaking
// Tank spills all contents into atmosphere
// Boom 3x3 base explosion
// +1 for each SCALE kPa aboe threshold
// was 2 atm
//pipe-insulation rate divisor
//heat-exch pipe insulation
// fraction of gas transfered per process
// Defines the Mining Z level, change this when the map changes
// all this does is set the z-level to be ignored by erebite explosion admin log messages
// if you want to see all erebite explosions set this to 0 or -1 or something
//FLAGS BITMASK
// can be put in back slot
// can pass by a table or rack
// thing doesn't drift in space
// put this on either a thing you don't want to be hit rapidly, or a thing you don't want people to hit other stuff rapidly with
// 1 second extra delay on use
// weapon not affected by shield
// conducts electricity (metal etc.)
// 96 - unused
// can be put in belt slot
// takes a fingerprint
// item has priority to check when entering or leaving
// 1024 - unused
// 2048 - unused
// is an open container for chemistry purposes
// is an atom spawned in an adventure area
//No beaker etc. splashing. For Chem machines etc.
//No attack message when hitting stuff with this item.
// 65535 - unused
// bitflags for clothing parts
// other clothing-specific bitflags, applied via the c_flags var
// combined HEADSPACE and SUITSPACE into this because seriously??
// mask allows internals
// combined COVERSEYES, COVERSEYES and COVERSEYES into this
// combined COVERSMOUTH and COVERSMOUTH into this.
// can be worn by fatties (or children? ugh)
// for galoshes/magic sandals/etc that prevent slipping on things
// channel numbers for power
//for total power used only
// bitflags for machine stat variable
// machine non-functional
// no available power
// machine shut down, but may still draw a trace amount
// under maintainance
// using a lot of power
// Radio (headset etc) colors.
//#define RADIOC_ENGINEERING "#D4A017"
// Frequency defines for headsets & intercoms (Convair880).
// Randomized for nuke rounds.
// Placeholder, it's actually randomized in gang rounds.
// These are for the Syndicate headset randomizer proc.
// HOLIDAYS
//#define HALLOWEEN 1
//#define XMAS 1
//#define CANADADAY 1
// so that you can move things around easily, in theory
// before you use any of these, please make sure the HUD you are using them in is actually related to the ones they're used on,
// so that we dont move the human HUD around and half the robot HUD winds up being all over the place (again)
//TESTING A LAYOUT
//TESTING A LAYOUT
// gameticker
//States for airlock_control
//mob intent type defines
//#define RESTART_WHEN_ALL_DEAD 1
//#define PLAYSOUND_LIMITER
//Projectile damage type defines
//Missing limb flags
// see in dark levels
//stamina config
//Default max stamina value
//Default stamina regeneration rate.
//Default stamina damage objects do.
//Default attack cost on user for attacking with items.
//Default hand-to-hand (punch, kick) stamina damage.
//Default hand-to-hand (punch, kick) stamina cost
//The minimum amount of stamina required to attack.
//How far into the negative we can take stamina. (People will be stunned while stamina regens up to > 0 - so this can lead to long stuns if set too high)
//How long we will be stunned for, for being <= 0 stamina
//How much grabbing someone costs.
//How much disarming someone costs.
//How much flipping / suplexing costs.
//Base chance of landing a critical hit to stamina.
//Divide stamina by how much on a crit
//Chance to block an attack in disarm mode. Settings this to 0 effectively disables the blocking system.
//Chance to block grabs.
//Cost of blocking an attack.
//Does kicking people on the ground cost less stamina ? (Right now it doesnt cost less but rather refunds some because kicking people on the ground is very relaxing OKAY)
//Attacks only cost stamina up to the min atttack cap. after that they are free
//Getting crit below or at 0 stamina will always knock out
//Can't speak below this point.
//This is a bad solution. Optimally this should scale.
//Minimum weightclass (w_class) of an item that allows for knock-outs and critical hits.
//This is the last resort option for the RNG lovers.
//Getting crit stuns the affected person for a short moment?
//How long people get stunned on crits
//If 1, stamina crits will instantly set a targets stamina to the number set below instead of dividing it by a number.
//Amount of stamina to drop to on a crit.
////////////////////////////////////////////////////
//Base chance at 0 stamina to be knocked out by an attack - scales up the lower stamina goes.
//Up to which *additional* value the chance will scale with lower stamina nearly the negative cap
//The message tired people get when they try to attack.
//How much farting costs. I am not even kidding.
//reagent_container bit flags
// has a graduated scale, so total reagent volume can be read directly (e.g. beaker)
// reagent is visible inside, so color can be described
// can estimate fullness of container
// spectroscopic glasses can analyse contents
// blood system and item damage things
// a) this is an excellent idea and b) why do we still use damtype strings then
// crushing damage is technically blunt damage, but it causes bleeding
// speak for yourself, as a shapeshifting illuminati lizard, my blood is somewhere between lime and leaf green
// Process Scheduler defines
// Process status defines
// Process time thresholds
// 30 seconds
// 60 seconds
// 90 seconds
// 50 ticks
// 2 ticks
// 90%
// attack message flags
// used by limbs which make a special kind of melee attack happen
//I feel like these should be a thing, ok
//How much stuff is allowed in the pools before the lifeguard throws them into the deletequeue instead. A shameful lifeguard.
//#define DETAILED_POOL_STATS
// parts of speech flags for madlibs tokens in vox
// helper datum
// VOX procs
//Returns null if match is not made like some turbohitler
// global init proc called from world.New
// global vars
//The weird name of this file is due to its very specific place in compiling.
//These exist solely to make sure people don't mis-spell some property somewhere and then have trouble finding the bug.
//Never 0, 0 being returned means that the material doesnt have the property.
//Default, crappy, properties below. These exist as a point of reference for the value ranges and for easily setting up default material properties.
/////////////////////
//CONTENTS
//Global Vars and procs
//Topic() - A giant fuck tonne of admin options.
//Admin panels
//Admin procs
//
////////////////////////////////
// No confidential info for goat farts (Convair880).
//this doesnt fail if the placeholder doesnt exist ok dont worry
//Shamelessly adapted from message_admins
//This is for edge cases where a coder needs a goddamn notification when it happens
//Sends a message to folks when an attack goes down
//Wires bad hack to update the player options menu on click, part 1
//Also I guess it has sort of expanded now to correctly pick targets
//Find the mob ref for that nerd
//alert("You must define an action! Yell at Wire if you see this.")
//if(rank_to_level(admins[player]) > src.level) <- Pointless.
// alert("You can't modify this player's notes, they are of a higher admin rank!")
// return
/////////////////////////////////////ban stuff
//Add ban
//Edit ban
//Delete ban
/////////////////////////////////////end ban stuff
// var/list/alljobs = get_all_jobs()
//why doesn't this work the stupid cunt
//why doesn't this work the stupid cunt
//why doesn't this work the stupid cunt
// I removed some broken/discontinued game modes here (Convair880).
/*if (!ishuman(MC))
alert("Cannot limb modify [MC]: not human.")
return
var/mob/living/carbon/human/M = MC
if (!M.limbs)
alert("Mob limb holder is broken.")
return
var/which = input("Which limb?", "Which limb?", "cancel") in list("left arm", "right arm", "both arms", "left leg", "right leg", "both legs", "cancel")
if (which == "cancel")
return
else if (which == "left arm" || which == "right arm" || which == "both arms")
var/kind = input("What kind of arm?", "What kind of arm?", "normal arm") in list("normal arm", "synth arm", "blooming synth arm", "cyborg arm", "light cyborg arm", "wendigo arm", "bear arm", "abomination arm", "werewolf arm", "predator arm", "item arm", "sever")
if (kind == "normal arm")
if (which == "left arm" || which == "both arms")
if (M.limbs.l_arm)
qdel(M.limbs.l_arm)
var/obj/item/parts/human_parts/arm/limb = new /obj/item/parts/human_parts/arm/left(M)
M.limbs.l_arm = limb
limb.holder = M
limb.remove_stage = 0
M.show_message("<span style=\"color:blue\"><b>Your left arm magically regrows!</b></span>")
logTheThing("admin", usr, null, "replaced [key_name(M)]'s left arm with a normal arm.")
message_admins("[key_name(usr)] gave [key_name(M)] a new left arm.")
if (which == "right arm" || which == "both arms")
if (M.limbs.r_arm)
qdel(M.limbs.r_arm)
var/obj/item/parts/human_parts/arm/limb = new /obj/item/parts/human_parts/arm/right(M)
M.limbs.r_arm = limb
limb.holder = M
limb.remove_stage = 0
M.show_message("<span style=\"color:blue\"><b>Your right arm magically regrows!</b></span>")
logTheThing("admin", usr, null, "replaced [key_name(M)]'s right arm with a normal arm.")
message_admins("[key_name(usr)] gave [key_name(M)] a new right arm.")
if (kind == "synth arm")
if (which == "left arm" || which == "both arms")
if (M.limbs.l_arm)
qdel(M.limbs.l_arm)
var/obj/item/parts/human_parts/arm/limb = new /obj/item/parts/human_parts/arm/left/synth(M)
limb.quality = 0.5
M.limbs.l_arm = limb
limb.holder = M
limb.remove_stage = 0
M.show_message("<span style=\"color:blue\"><b>Your left arm magically becomes a synth arm!</b></span>")
logTheThing("admin", usr, null, "replaced [key_name(M)]'s left arm with a synth arm.")
message_admins("[key_name(usr)] gave [key_name(M)] a synth left arm.")
if (which == "right arm" || which == "both arms")
if (M.limbs.r_arm)
qdel(M.limbs.r_arm)
var/obj/item/parts/human_parts/arm/limb = new /obj/item/parts/human_parts/arm/right/synth(M)
limb.quality = 0.5
M.limbs.r_arm = limb
limb.holder = M
limb.remove_stage = 0
M.show_message("<span style=\"color:blue\"><b>Your right arm magically becomes a synth arm!</b></span>")
logTheThing("admin", usr, null, "replaced [key_name(M)]'s right arm with a synth arm.")
message_admins("[key_name(usr)] gave [key_name(M)] a synth right arm.")
if (kind == "blooming synth arm")
if (which == "left arm" || which == "both arms")
if (M.limbs.l_arm)
qdel(M.limbs.l_arm)
var/obj/item/parts/human_parts/arm/limb = new /obj/item/parts/human_parts/arm/left/synth/bloom(M)
limb.quality = 0.5
M.limbs.l_arm = limb
limb.holder = M
limb.remove_stage = 0
M.show_message("<span style=\"color:blue\"><b>Your left arm magically becomes a blooming synth arm!</b></span>")
logTheThing("admin", usr, null, "replaced [key_name(M)]'s left arm with a blooming synth arm.")
message_admins("[key_name(usr)] gave [key_name(M)] a blooming synth left arm.")
if (which == "right arm" || which == "both arms")
if (M.limbs.r_arm)
qdel(M.limbs.r_arm)
var/obj/item/parts/human_parts/arm/limb = new /obj/item/parts/human_parts/arm/right/synth/bloom(M)
limb.quality = 0.5
M.limbs.r_arm = limb
limb.holder = M
limb.remove_stage = 0
M.show_message("<span style=\"color:blue\"><b>Your right arm magically becomes a blooming synth arm!</b></span>")
logTheThing("admin", usr, null, "replaced [key_name(M)]'s right arm with a blooming synth arm.")
message_admins("[key_name(usr)] gave [key_name(M)] a blooming synth right arm.")
if (kind == "cyborg arm")
if (which == "left arm" || which == "both arms")
if (M.limbs.l_arm)
qdel(M.limbs.l_arm)
var/obj/item/parts/human_parts/arm/limb = new /obj/item/parts/robot_parts/arm/left(M)
limb.quality = 0.5
M.limbs.l_arm = limb
limb.holder = M
limb.remove_stage = 0
M.show_message("<span style=\"color:blue\"><b>Your left arm magically becomes a cyborg arm!</b></span>")
logTheThing("admin", usr, null, "replaced [key_name(M)]'s left arm with a cyborg arm.")
message_admins("[key_name(usr)] gave [key_name(M)] a cyborg left arm.")
if (which == "right arm" || which == "both arms")
if (M.limbs.r_arm)
qdel(M.limbs.r_arm)
var/obj/item/parts/human_parts/arm/limb = new /obj/item/parts/robot_parts/arm/right(M)
limb.quality = 0.5
M.limbs.r_arm = limb
limb.holder = M
limb.remove_stage = 0
M.show_message("<span style=\"color:blue\"><b>Your right arm magically becomes a cyborg arm!</b></span>")
logTheThing("admin", usr, null, "replaced [key_name(M)]'s right arm with a cyborg arm.")
message_admins("[key_name(usr)] gave [key_name(M)] a cyborg right arm.")
if (kind == "light cyborg arm")
if (which == "left arm" || which == "both arms")
if (M.limbs.l_arm)
qdel(M.limbs.l_arm)
var/obj/item/parts/human_parts/arm/limb = new /obj/item/parts/robot_parts/arm/left/light(M)
limb.quality = 0.5
M.limbs.l_arm = limb
limb.holder = M
limb.remove_stage = 0
M.show_message("<span style=\"color:blue\"><b>Your left arm magically becomes a light cyborg arm!</b></span>")
logTheThing("admin", usr, null, "replaced [key_name(M)]'s left arm with a light cyborg arm.")
message_admins("[key_name(usr)] gave [key_name(M)] a light cyborg left arm.")
if (which == "right arm" || which == "both arms")
if (M.limbs.r_arm)
qdel(M.limbs.r_arm)
var/obj/item/parts/human_parts/arm/limb = new /obj/item/parts/robot_parts/arm/right/light(M)
limb.quality = 0.5
M.limbs.r_arm = limb
limb.holder = M
limb.remove_stage = 0
M.show_message("<span style=\"color:blue\"><b>Your right arm magically becomes a light cyborg arm!</b></span>")
logTheThing("admin", usr, null, "replaced [key_name(M)]'s right arm with a light cyborg arm.")
message_admins("[key_name(usr)] gave [key_name(M)] a light cyborg right arm.")
if (kind == "wendigo arm")
if (which == "left arm" || which == "both arms")
if (M.limbs.l_arm)
qdel(M.limbs.l_arm)
var/obj/item/parts/human_parts/arm/limb = new /obj/item/parts/human_parts/arm/left/wendigo(M)
limb.quality = 0.5
M.limbs.l_arm = limb
limb.holder = M
limb.remove_stage = 0
M.show_message("<span style=\"color:blue\"><b>Your left arm eeriely becomes a wendigo arm!</b></span>")
logTheThing("admin", usr, null, "replaced [key_name(M)]'s left arm with a wendigo arm.")
message_admins("[key_name(usr)] gave [key_name(M)] a wendigo left arm.")
if (which == "right arm" || which == "both arms")
if (M.limbs.r_arm)
qdel(M.limbs.r_arm)
var/obj/item/parts/human_parts/arm/limb = new /obj/item/parts/human_parts/arm/right/wendigo(M)
limb.quality = 0.5
M.limbs.r_arm = limb
limb.holder = M
limb.remove_stage = 0
M.show_message("<span style=\"color:blue\"><b>Your right arm eeriely becomes a wendigo arm!</b></span>")
logTheThing("admin", usr, null, "replaced [key_name(M)]'s right arm with a wendigo arm.")
message_admins("[key_name(usr)] gave [key_name(M)] a wendigo right arm.")
if (kind == "bear arm")
if (which == "left arm" || which == "both arms")
if (M.limbs.l_arm)
qdel(M.limbs.l_arm)
var/obj/item/parts/human_parts/arm/limb = new /obj/item/parts/human_parts/arm/left/bear(M)
limb.quality = 0.5
M.limbs.l_arm = limb
limb.holder = M
limb.remove_stage = 0
M.show_message("<span style=\"color:blue\"><b>Your left arm eeriely becomes a bear arm!</b></span>")
logTheThing("admin", usr, null, "replaced [key_name(M)]'s left arm with a bear arm.")
message_admins("[key_name(usr)] gave [key_name(M)] a bear left arm.")
if (which == "right arm" || which == "both arms")
if (M.limbs.r_arm)
qdel(M.limbs.r_arm)
var/obj/item/parts/human_parts/arm/limb = new /obj/item/parts/human_parts/arm/right/bear(M)
limb.quality = 0.5
M.limbs.r_arm = limb
limb.holder = M
limb.remove_stage = 0
M.show_message("<span style=\"color:blue\"><b>Your right arm eeriely becomes a bear arm!</b></span>")
logTheThing("admin", usr, null, "replaced [key_name(M)]'s right arm with a bear arm.")
message_admins("[key_name(usr)] gave [key_name(M)] a bear right arm.")
if (kind == "abomination arm")
if (which == "left arm" || which == "both arms")
if (M.limbs.l_arm)
qdel(M.limbs.l_arm)
var/obj/item/parts/human_parts/arm/limb = new /obj/item/parts/human_parts/arm/left/abomination(M)
limb.quality = 0.5
M.limbs.l_arm = limb
limb.holder = M
limb.remove_stage = 0
M.show_message("<span style=\"color:blue\"><b>Your left arm becomes a chitinous tendril!</b></span>")
logTheThing("admin", usr, null, "replaced [key_name(M)]'s left arm with an abomination arm.")
message_admins("[key_name(usr)] gave [key_name(M)] an abomination left arm.")
if (which == "right arm" || which == "both arms")
if (M.limbs.r_arm)
qdel(M.limbs.r_arm)
var/obj/item/parts/human_parts/arm/limb = new /obj/item/parts/human_parts/arm/right/abomination(M)
limb.quality = 0.5
M.limbs.r_arm = limb
limb.holder = M
limb.remove_stage = 0
M.show_message("<span style=\"color:blue\"><b>Your right arm becomes a chitinous tendril!</b></span>")
logTheThing("admin", usr, null, "replaced [key_name(M)]'s right arm with an abomination arm.")
message_admins("[key_name(usr)] gave [key_name(M)] an abomination right arm.")
if (kind == "werewolf arm")
if (which == "left arm" || which == "both arms")
if (M.limbs.l_arm)
qdel(M.limbs.l_arm)
var/obj/item/parts/human_parts/arm/limb = new /obj/item/parts/human_parts/arm/left/werewolf(M)
limb.quality = 0.5
M.limbs.l_arm = limb
limb.holder = M
limb.remove_stage = 0
M.show_message("<span style=\"color:blue\"><b>Your left arm becomes a werewolf arm!</b></span>")
logTheThing("admin", usr, null, "replaced [key_name(M)]'s left arm with a werewolf arm.")
message_admins("[key_name(usr)] gave [key_name(M)] a werewolf left arm.")
if (which == "right arm" || which == "both arms")
if (M.limbs.r_arm)
qdel(M.limbs.r_arm)
var/obj/item/parts/human_parts/arm/limb = new /obj/item/parts/human_parts/arm/right/werewolf(M)
limb.quality = 0.5
M.limbs.r_arm = limb
limb.holder = M
limb.remove_stage = 0
M.show_message("<span style=\"color:blue\"><b>Your right arm becomes a werewolf arm!</b></span>")
logTheThing("admin", usr, null, "replaced [key_name(M)]'s right arm with a werewolf arm.")
message_admins("[key_name(usr)] gave [key_name(M)] a werewolf right arm.")
if (kind == "predator arm")
if (which == "left arm" || which == "both arms")
if (M.limbs.l_arm)
qdel(M.limbs.l_arm)
var/obj/item/parts/human_parts/arm/limb = new /obj/item/parts/human_parts/arm/left/predator(M)
limb.quality = 0.5
M.limbs.l_arm = limb
limb.holder = M
limb.remove_stage = 0
M.show_message("<span style=\"color:blue\"><b>Your left arm becomes a predator arm!</b></span>")
logTheThing("admin", usr, null, "replaced [key_name(M)]'s left arm with a predator arm.")
message_admins("[key_name(usr)] gave [key_name(M)] a predator left arm.")
if (which == "right arm" || which == "both arms")
if (M.limbs.r_arm)
qdel(M.limbs.r_arm)
var/obj/item/parts/human_parts/arm/limb = new /obj/item/parts/human_parts/arm/right/predator(M)
limb.quality = 0.5
M.limbs.r_arm = limb
limb.holder = M
limb.remove_stage = 0
M.show_message("<span style=\"color:blue\"><b>Your right arm becomes a predator arm!</b></span>")
logTheThing("admin", usr, null, "replaced [key_name(M)]'s right arm with a predator arm.")
message_admins("[key_name(usr)] gave [key_name(M)] a predator right arm.")
else if (kind == "item arm")
var/type_str = input("Enter a type path for the new arm.", "Replacing [which]", "/obj/item/saw/elimbinator") as text
if (type_str == "")
return
var/type = text2path(type_str)
if (type == null)
alert("No such type ([type_str]).")
return
if (!ispath(type,/obj/item))
alert("Item must be a descendant of /obj/item.")
return
if (which == "left arm" || which == "both arms")
var/item = new type()
if (M.limbs.l_arm)
qdel(M.limbs.l_arm)
var/obj/item/parts/human_parts/arm/limb = new /obj/item/parts/human_parts/arm/left/item(M)
M.limbs.l_arm = limb
limb.holder = M
limb.remove_stage = 0
limb:set_item(item)
M.show_message("<span style=\"color:blue\"><b>Your left arm [pick("magically ", "weirdly ", "suddenly ", "unwillingly ", "grodily ", "")]becomes [item]!</b></span>")
logTheThing("admin", usr, null, "replaced [key_name(M)]'s left arm with [item].")
message_admins("[key_name(usr)] gave [key_name(M)] a new left arm: [item]")
if (which == "right arm" || which == "both arms")
var/item = new type()
if (M.limbs.r_arm)
qdel(M.limbs.r_arm)
var/obj/item/parts/human_parts/arm/limb = new /obj/item/parts/human_parts/arm/right/item(M)
M.limbs.r_arm = limb
limb.holder = M
limb.remove_stage = 0
limb:set_item(item)
M.show_message("<span style=\"color:blue\"><b>Your right arm [pick("magically ", "weirdly ", "suddenly ", "unwillingly ", "grodily ", "")]becomes [item]!</b></span>")
logTheThing("admin", usr, null, "replaced [key_name(M)]'s right arm with [item].")
message_admins("[key_name(usr)] gave [key_name(M)] a new right arm: [item]")
else if (kind == "sever")
if (which == "left arm" || which == "both arms")
if (M.limbs)
if (M.limbs.l_arm)
M.limbs.l_arm.sever()
logTheThing("admin", usr, null, "severed [key_name(M)]'s left arm.")
message_admins("[key_name(usr)] severed [key_name(M)]'s left arm.")
if (which == "right arm" || which == "both arms")
if (M.limbs)
if (M.limbs.r_arm)
M.limbs.r_arm.sever()
logTheThing("admin", usr, null, "severed [key_name(M)]'s right arm.")
message_admins("[key_name(usr)] severed [key_name(M)]'s right arm.")
else if (which == "left leg" || which == "right leg" || which == "both legs")
var/type = input("What kind?", "What kind?", "normal leg") in list("normal leg", "synth leg", "blooming synth leg", "cyborg leg", "light cyborg leg", "treads", "sever")
if (type == "sever")
if (which == "left leg" || which == "both legs")
if (M.limbs)
if (M.limbs.l_leg)
M.limbs.l_leg.sever()
logTheThing("admin", usr, null, "severed [key_name(M)]'s left leg.")
message_admins("[key_name(usr)] severed [key_name(M)]'s left leg.")
if (which == "right leg" || which == "both legs")
if (M.limbs)
if (M.limbs.r_leg)
M.limbs.r_leg.sever()
logTheThing("admin", usr, null, "severed [key_name(M)]'s right leg.")
message_admins("[key_name(usr)] severed [key_name(M)]'s right leg.")
else
var/tpath = ""
if (which == "left leg" || which == "both legs")
if (type == "normal leg")
tpath = /obj/item/parts/human_parts/leg/left
else if (type == "synth leg")
tpath = /obj/item/parts/human_parts/leg/left/synth
else if (type == "blooming synth leg")
tpath = /obj/item/parts/human_parts/leg/left/synth/bloom
else if (type == "cyborg leg")
tpath = /obj/item/parts/robot_parts/leg/left
else if (type == "light cyborg leg")
tpath = /obj/item/parts/robot_parts/leg/left/light
else if (type == "treads")
tpath = /obj/item/parts/robot_parts/leg/left/treads
var/obj/item/parts/limb = new tpath(M)
if (M.limbs.l_leg)
qdel(M.limbs.l_leg)
M.limbs.l_leg = limb
limb:holder = M
limb:remove_stage = 0
M.show_message("<span style=\"color:blue\"><b>Your left leg becomes a brand new [limb]!</b></span>")
logTheThing("admin", usr, null, "replaced [key_name(M)]'s left leg with [limb].")
message_admins("[key_name(usr)] gave [key_name(M)] a new left leg: [limb]")
if (which == "right leg" || which == "both legs")
if (type == "normal leg")
tpath = /obj/item/parts/human_parts/leg/right
else if (type == "synth leg")
tpath = /obj/item/parts/human_parts/leg/right/synth
else if (type == "blooming synth leg")
tpath = /obj/item/parts/human_parts/leg/right/synth/bloom
else if (type == "cyborg leg")
tpath = /obj/item/parts/robot_parts/leg/right
else if (type == "light cyborg leg")
tpath = /obj/item/parts/robot_parts/leg/right/light
else if (type == "treads")
tpath = /obj/item/parts/robot_parts/leg/right/treads
var/obj/item/parts/limb = new tpath(M)
if (M.limbs.r_leg)
qdel(M.limbs.r_leg)
M.limbs.r_leg = limb
limb:holder = M
limb:remove_stage = 0
M.show_message("<span style=\"color:blue\"><b>Your right leg becomes a brand new [limb]!</b></span>")
logTheThing("admin", usr, null, "replaced [key_name(M)]'s right leg with [limb].")
message_admins("[key_name(usr)] gave [key_name(M)] a new right leg: [limb]")
if (M.client)
M.client.move_delay = 0
M.set_body_icon_dirty()*/
// They could be in a pod or whatever, which would have unfortunate results when respawned (Convair880).
//independant of mode and can be traitors as well
// traitor, or other modes where traitors/counteroperatives would be.
//they're nothing so turn them into a traitor!
// The only role that works for all critters at this point is hard-mode traitor, really. The majority of existing
// roles don't work for them, most can't wear clothes and some don't even have arms and/or can pick things up.
// That said, certain roles are mostly compatible and thus selectable.
//they're a ghost/hivebotthing/etc
// Moved from SG to PA. They can do this through build mode anyway (Convair880).
// forgive me
//Gives player a token they can redeem to guarantee an antagonist role
//don't warp them if they aren't ready or are already there
//teleport person to cell
//teleport security person
//knock yourself out to stop the ghosts
// 100+ brain damage is lethal.
// FUN SECRETS CODE
//Only humans can be zombies!
//Not dead!
//Already a zombie!
//Set stat back to zero so we can call death()
//Calling death() again means that the zombies will rise after ~20 seconds.
//DO IT!
//Will be SG when tested
//Build the swaplist
//Jenny Antonsson switches bodies with herself! #wow #whoa
//More random
// This basic bit of info was missing, even though you could look up the
// location of the old auth disk here in the past (Convair880).
/* if("spawn_commandos")
var/datum/special_respawn/SR = new /datum/special_respawn/
SR.spawn_commandos(3)
if("spawn_turds")
var/datum/special_respawn/SR = new /datum/special_respawn/
var/amount = input(usr,"Amount to respawn:","Spawn TURDS",3) as num
if(!amount) return
SR.spawn_TURDS(amount)
logTheThing("admin", src, null, "has spawned [amount] TURDS.")
logTheThing("diary", src, null, "has spawned [amount] TURDS.", "admin")
if("spawn_smilingman")
var/datum/special_respawn/SR = new /datum/special_respawn/
SR.spawn_smilingman(1)
logTheThing("admin", src, null, "has spawned a Smiling Man.")
logTheThing("diary", src, null, "has spawned a Smiling Man.", "admin")
*/
// Moved from SG to PA (Convair880).
//Wires bad hack part 2
//The ref may have changed with our actions, find it again
//We can't even trust that the admin ref hasnt changed
///////////////////////////////////////////////////////////////////////////////////////////////Panels
// else if(istype(M, /mob/living/carbon/alien))
// dat += "<td>Alien</td>"
// Someone else removed these but left the (non-functional) buttons. Move back inside the dat section and uncomment to re-add. - IM
// <A href='?src=\ref[src];action=s_rez;type=spawn_commandos'>Spawn a force of commandos</A><BR>
// <A href='?src=\ref[src];action=s_rez;type=spawn_turds'>Spawn a T.U.R.D.S. attack force</A><BR>
// <A href='?src=\ref[src];action=s_rez;type=spawn_smilingman'>Spawn a Smiling Man</A><BR>
// the cache is newer than our panel
// Moved from SG to PA. They can do this through build mode anyway (Convair880).
// ADMIN PANEL HTML IS HERE
// runtime error fix
// centcom
// ss13
// evacuated
//dat += "<A href='?src=\ref[src];action=secretsfun;type=forcerandomnames'>Politely suggest all players use random names</a>" // lol
// FUN SECRETS PANEL
/////////////////////////////////////////////////////////////////////////////////////////////////admins2.dm merge
//i.e. buttons/verbs
//DICKSDONGS
// hack to yield 0=restart, 1=changemode
// now voting
// when the vote will end
//vote_manager.cancel_vote()
// clear vote window from all clients
//Wire: Export round end packet (manual restart)
// don't spawn with heart failure
////////////////////////////////////////////////////////////////////////////////////////////////ADMIN HELPER PROCS
//to stop spamming during traitor all secret
//otherwise the HUD remains in the login screen
//Buggy as heck because of the way updating clothing works (it clears all invisibility variables and sets them based on if you have a cloaking device on or not)
//It also clears overlays so the overlay will dissapear and bluh, I don't want to add another variable sooo this is what you get I guess.
//If the overlay dissapears you lose the cloaking too, so just retype cloak-self and it should work again
//If you don't lay down or force yourself to update clothing via fire or whatever it should be good enough to use for the purpose of spying on shitlords I guess.
//
//
//ALL DONE
/*********************************************************************************************************
//
//
//state = 1 for playing : default
//state = 2 for observing
//I find adding this var pretty hilarious in itself really
//Ok
//if (src.owner:holder:level >= LEVEL_CODER)
//HTML += "<b>Hide Extra Verbs?: <a href='?src=\ref[src];action=toggle_extra_verbs'>[(src.extratoggle ? "Yes" : "No")]</a></b><br>"
//AP["[ckey]_extratoggle"] << extratoggle
// LEVEL_BABBY, goat fart, ayn rand's armpit
// LEVEL_MOD, moderator
// LEVEL_SA, secondary administrator
//Ban verbs
// moved down from admin
/*// LEVEL_ADMIN, admin
/client/proc/noclip,\
/client/proc/cmd_admin_mute,\
/client/proc/cmd_admin_mute_temp,\
/client/proc/cmd_admin_delete,\
/client/proc/cmd_admin_add_freeform_ai_law,\
/client/proc/cmd_admin_show_ai_laws,\
/client/proc/cmd_admin_reset_ai,\
/client/proc/addpathogens,\
/client/proc/addreagents,\
/client/proc/respawn_as_self,\
/datum/admins/proc/toggletraitorscaling,\
/datum/admins/proc/togglerandomaiblobs\
*/
// LEVEL_PA, primary administrator
// moved up from admin
// LEVEL_SHITGUY, shit person
// LEVEL_CODER, coder
// LEVEL_HOST, host
// verbs that SAs and As get while observing. PA+ get these all the time
// verbs that PAs get while observing. Coder+ get these all the time
// certain ranks get special treatment while observing
// literally the laziest way to do this
//SHIT GUY PLUS
//I believe that we can trust people to not spam shit with the observe things, because we trust them with the ban button after all
//Hrngh
// src.mob.mind.observing = 1
//I believe that we can trust people to not spam shit with the observe things, because we trust them with the ban button after all
//Hrngh x2
// src.mob.mind.observing = 0
//admin client procs ported over from mob.dm
//fuck u
// farte
//stealth_hide_fakekey = (alert("Hide your fake key when using DSAY?", "Extra stealthy","Yes", "No") == "Yes")
// I think if people really wanna be Denmark they can just set themselves to be Denmark
// farte
// You now get to chose (mostly) if you want to send the target to the arrival shuttle (Convair880).
// Can't complete specialist objectives as a human. Also, the proc takes care of the rest.
// Ditto.
// Delete mainframe if it's an AI-controlled robot.
//Special proc to set up the server for mapping via screenshots
//Gotta prevent dummies
//Viewport size
//Z levels to map
//Make everyone invisible so they don't get in the way of screenshots
//Max out all power (to avoid lights dying mid mapping)
//Make every space tile bright pink (for further processing via local image manipulation)
//Doesnt pinkify tiles with crap on top of them (transparant overlays fuck with the image processing later)
//Map eeeeverything
//Skips centcom
//Or just one level I GUESS
// 3 seconds
////////////////////////////////
// some midnight rollover protection b/c byond is fucking stupid
// for_no_raisin(usr, msg)
// some midnight rollover protection b/c byond is fucking stupid
// some midnight rollover protection b/c byond is fucking stupid
// after 10 seconds, turn it off
// I stole this from Spy's emag_all_of_type() tia Spy ilu <3
// cmd_get_target() isn't needed since we already have get_mobject()
/////////////////////////
// BASE BAN PROCS
// Most of these have two steps (instead of double the procs)
// First step sends the initial query to the bans web API
// Second step handles the response
/////////////////////////
//Returns the expiry timestamp in a human readable format
//1440 = 1 day in minutes
//60 = 1 hour in minutes
//Are ya banned? Well!? ARE YA?!
//A return 0 is a "this guy is ok let him in"
//Anything that returns as true is a "bad dude kill his connection"
//(this doesn't use the 'step' var thing because we need the response here and now)
//Ignore if localhost
//Check if this user has a ban already
//If the server returned nothing, a "no bans found" record, or a "this dude is exception'd"
//Then they are good to go
//Error returned from the API welp
//We only care about the latest match for this (so far)
//each ban
//each item for this ban
//Are any of the details...different? This is to catch out ban evading jerks who change their ckey but forget to mask their IP or whatever
//Insert a new ban for this JERK
//if we matched a previous auto-added ban
//no multiplier present, default to x2 (this should never occur)
//didn't match a previous evasion ban, start off with x1
//only add time if a ckey didnt match, not anything else
//Temp ban found, determine if it should expire or not
//It expired! Go you!
//Temp ban still in effect. DENIED
//Permaban found, the player is DENIED
//Should never occur
//If a temp ban, calculate expiry
//Add 5 days (7200 mins) onto the ban if it's an evasion attempt
//we can get away with just this because addBan only ever returns the details we passed in to begin with
//grab clients if possible
//Grab the mob if no target clients were found
//Prepend our evasion attempt info for: the user, admins, notes (everything except the actual ban reason in the db)
//forum.ss13.co</span>")
//Starts the dialog for banning a dude
//Admin verb to add bans
//If a temp ban, calculate expiry
//Add 5 days (7200 mins) onto the ban if it's an evasion attempt
//we can get away with just this because editBan only ever acts on one ban (obviously)
//grab us a good ol' admin client
//we can get away with just this because deleteBan only ever acts on one ban (obviously)
//we can get away with just this because deleteBan only ever acts on one ban (obviously)
/////////////////////////
// BAN PANEL PROCS (called via ejhax)
/////////////////////////
//DEBUG (gets the latest ban and prints it out)
//each ban
//each item for this ban
/////////////////////////
// LOCAL AND REMOTE DB SYNCHRONISATION
/////////////////////////
//Here we fetch the latest logID, increment it, then append our data as json
//Construct the log IDs we need from the remote
//Remove the trailing comma
//Ask the remote for them
//Error returned from the API welp
//Loop through the bans we were given
//Decide what to do with it
//Error returned from the local db jeeeeez aint nothing going our way
//each ban
//Decide what to do with it
//Error returned from the local db jeeeeez aint nothing going our way
//Construct the log IDs the remote is missing
//Get the data for those log IDs
//+1 for the colon, +2 for copytext being a shitass
//Send it to the remote so it can update
//Universal proc for checking if both the local ban db and the remote are synced
//Ok we should probably make sure this shit doesn't run on local servers
//yes we are checking filesize of the ban db here. it is a nice independent way of doing it
//Get the latest logID from the local ban log
//Only operate on the log if it...exists and has stuff, naturally
//Get the latest logID from the API
//Just making sure
//Local bans are out of date
//we're synced! clean up
//Remote bans are out of date
//we're synced! clean up
//Nothing is out of date supposedly possibly maybe??
//we're synced! clean up
// Added support for single tank bombs and fingerprints (Convair880).
// We've got a global proc for that now (Convair880).
// Cannot read null.x
// Alerts wait for user input. Bomb might not exist anymore.
/* Just use the set traitor dialog thing
/client/proc/cmd_admin_changelinginize(var/mob/M in world)
set category = null
set name = "Make Changeling"
set popup_menu = 0
if(!ticker)
alert("Wait until the game starts")
return
if(istype(M, /mob/living/carbon/human) && M.mind != null)
logTheThing("admin", src, M, "has made %target% a changeling.")
logTheThing("diary", src, M, "has made %target% a changeling.", "admin")
spawn(10)
M.mind.absorbed_dna[M.bioHolder] = M.real_name
M.make_changeling()
else
alert("Invalid mob")
*/
// to prevent REALLY stupid deletions
// fuck this
// fuck
// GO AWAY
//Clean up any old ones laying around before displaying this
//Force a complete rebuild
//Refresh the display
//Item type - Total processing time - Times processed - Average processing time
//Item type - Total processing time - Times processed - Average processing time
// c:
//Verbs we have deemed "server-breaking" or just anything a drunkmin probably shouldnt have
//I think vote stuff is kinda broken if memory serves
//No accidentally restarting the server
//Music/sounds
//No banning for you
//This is a little involved for a drunk person huh
//Shitguy stuff
//Coder stuff this is mostly all dangerous shit
//Toggles (these are ones that could be very confusing to accidentally toggle for a drunk person)
//Puzzle goes here
//generate two, two digit numbers
//Apparently if the onlineAdmins list contains only one entry, it just picks it by default without giving any input
//turn it off
//turn it on
//Make centcom announcement
// so they don't spam gibs everywhere
// Updates legacy bans with new info
//to store the keys & ranks
// Updates bans.. Or fixes them. Either way.
//don't run this update again
// goddamn we have view variables already we don't need this in the damned right click menu FUCK'S SAKE
//Let's prevent people from promoting themselves, yes?
//Short list
//If someone tries this let's make sure we all know it.
//var_value = "[bicon(var_value)]"
/*Probably cause a lot of bugs, so leaving it out
if("list")
mod_list(O.vars[variable])
for (var\O.type\A in world)
return
*/
/*////////////////////these too
if("reference")
O.vars[variable] = input("Select reference:","Reference",\
O.vars[variable]) as mob|obj|turf|area in world
if("mob reference")
O.vars[variable] = input("Select reference:","Reference",\
O.vars[variable]) as mob in world
*/
// goddamn we have view variables already we don't need this in the damned right click menu FUCK'S SAKE
//haha
//haha
//variable = "[bicon(variable)]" //Wire: Bug me if you want the entirely too long winded explanation of why this is commented out
//Let's prevent people from promoting themselves, yes?
//Short list
//If someone tries this let's make sure we all know it.
//var_value = "[bicon(var_value)]" //Wire: Bug me if you want the entirely too long winded explanation of why this is commented out
// Updates legacy bans with new info
//to store the keys & ranks
// Updates bans.. Or fixes them. Either way.
//don't run this update again
// refresh
// view vars
// sever limbs
// returns 1 when at least one limb is severed
// replace limbs
// returns 1 or greater when at least one limb is replaced
// replace all limbs
// drop organs
// returns with the organ when at least one organ is dropped
// replace organs
// returns 1 if replace was successful
// ugly :/
// replace all organs
// ONE OF YOU HAS TO EXIST
//?src=\ref[src];action=view_vars;target=\ref[target]'>[target]</a>" : "[target]"]</h1>
//?src=\ref[src];action=refresh;target=\ref[target]' class='refresh'>Refresh</a>
//?src=\ref[src];action=sever_limb;target=\ref[limbs];part=l_arm'>\[X\]</a></td>
//?src=\ref[src];action=replace_limb;target=\ref[limbs];part=l_arm'>\[X\]</a></td>
//?src=\ref[src];action=view_vars;target=\ref[limbs.l_arm]'>\[X\]</a></td>" : "<td>None</td>"]" : null]
//?src=\ref[src];action=sever_limb;target=\ref[limbs];part=r_arm'>\[X\]</a></td>
//?src=\ref[src];action=replace_limb;target=\ref[limbs];part=r_arm'>\[X\]</a></td>
//?src=\ref[src];action=view_vars;target=\ref[limbs.r_arm]'>\[X\]</a></td>" : "<td>None</td>"]" : null]
//?src=\ref[src];action=sever_limb;target=\ref[limbs];part=l_leg'>\[X\]</a></td>
//?src=\ref[src];action=replace_limb;target=\ref[limbs];part=l_leg'>\[X\]</a></td>
//?src=\ref[src];action=view_vars;target=\ref[limbs.l_leg]'>\[X\]</a></td>" : "<td>None</td>"]" : null]
//?src=\ref[src];action=sever_limb;target=\ref[limbs];part=r_leg'>\[X\]</a></td>
//?src=\ref[src];action=replace_limb;target=\ref[limbs];part=r_leg'>\[X\]</a></td>
//?src=\ref[src];action=view_vars;target=\ref[limbs.r_leg]'>\[X\]</a></td>" : "<td>None</td>"]" : null]
//?src=\ref[src];action=sever_limb;target=\ref[limbs];part=both_arms'>\[X\]</a></td>
//?src=\ref[src];action=replace_limb;target=\ref[limbs];part=both_arms'>\[X\]</a></td>
//?src=\ref[src];action=sever_limb;target=\ref[limbs];part=both_legs'>\[X\]</a></td>
//?src=\ref[src];action=replace_limb;target=\ref[limbs];part=both_legs'>\[X\]</a></td>
//?src=\ref[src];action=sever_limb;target=\ref[limbs];part=all'>\[X\]</a></td>
//?src=\ref[src];action=replace_all_limbs;target=\ref[limbs]'>\[X\]</a></td>
//?src=\ref[src];action=view_vars;target=\ref[limbs]'>\[X\]</a></td>" : null]
//?src=\ref[src];action=drop_organ;target=\ref[organs];part=head'>\[X\]</a></td>
//?src=\ref[src];action=replace_organ;target=\ref[organs];part=head'>\[X\]</a></td>
//?src=\ref[src];action=view_vars;target=\ref[organs.head]'>\[X\]</a></td>" : "<td>None</td>"]" : null]
//?src=\ref[src];action=drop_organ;target=\ref[organs];part=skull'>\[X\]</a></td>
//?src=\ref[src];action=replace_organ;target=\ref[organs];part=skull'>\[X\]</a></td>
//?src=\ref[src];action=view_vars;target=\ref[organs.skull]'>\[X\]</a></td>" : "<td>None</td>"]" : null]
//?src=\ref[src];action=drop_organ;target=\ref[organs];part=brain'>\[X\]</a></td>
//?src=\ref[src];action=replace_organ;target=\ref[organs];part=brain'>\[X\]</a></td>
//?src=\ref[src];action=view_vars;target=\ref[organs.brain]'>\[X\]</a></td>" : "<td>None</td>"]" : null]
//?src=\ref[src];action=drop_organ;target=\ref[organs];part=left_eye'>\[X\]</a></td>
//?src=\ref[src];action=replace_organ;target=\ref[organs];part=left_eye'>\[X\]</a></td>
//?src=\ref[src];action=view_vars;target=\ref[organs.left_eye]'>\[X\]</a></td>" : "<td>None</td>"]" : null]
//?src=\ref[src];action=drop_organ;target=\ref[organs];part=right_eye'>\[X\]</a></td>
//?src=\ref[src];action=replace_organ;target=\ref[organs];part=right_eye'>\[X\]</a></td>
//?src=\ref[src];action=view_vars;target=\ref[organs.right_eye]'>\[X\]</a></td>" : "<td>None</td>"]" : null]
//?src=\ref[src];action=drop_organ;target=\ref[organs];part=chest'>\[X\]</a></td>
//?src=\ref[src];action=replace_organ;target=\ref[organs];part=chest'>\[X\]</a></td>
//?src=\ref[src];action=view_vars;target=\ref[organs.chest]'>\[X\]</a></td>" : "<td>None</td>"]" : null]
//?src=\ref[src];action=drop_organ;target=\ref[organs];part=heart'>\[X\]</a></td>
//?src=\ref[src];action=replace_organ;target=\ref[organs];part=heart'>\[X\]</a></td>
//?src=\ref[src];action=view_vars;target=\ref[organs.heart]'>\[X\]</a></td>" : "<td>None</td>"]" : null]
//?src=\ref[src];action=drop_organ;target=\ref[organs];part=left_lung'>\[X\]</a></td>
//?src=\ref[src];action=replace_organ;target=\ref[organs];part=left_lung'>\[X\]</a></td>
//?src=\ref[src];action=view_vars;target=\ref[organs.left_lung]'>\[X\]</a></td>" : "<td>None</td>"]" : null]
//?src=\ref[src];action=drop_organ;target=\ref[organs];part=right_lung'>\[X\]</a></td>
//?src=\ref[src];action=replace_organ;target=\ref[organs];part=right_lung'>\[X\]</a></td>
//?src=\ref[src];action=view_vars;target=\ref[organs.right_lung]'>\[X\]</a></td>" : "<td>None</td>"]" : null]
//?src=\ref[src];action=drop_organ;target=\ref[organs];part=butt'>\[X\]</a></td>
//?src=\ref[src];action=replace_organ;target=\ref[organs];part=butt'>\[X\]</a></td>
//?src=\ref[src];action=view_vars;target=\ref[organs.butt]'>\[X\]</a></td>" : "<td>None</td>"]" : null]
//?src=\ref[src];action=drop_organ;target=\ref[organs];part=all'>\[X\]</a></td>
//?src=\ref[src];action=replace_all_organs;target=\ref[organs]'>\[X\]</a></td>
//?src=\ref[src];action=view_vars;target=\ref[organs]'>\[X\]</a></td>" : null]
//var/akey = url_encode(text("[admin]"))
//var/ckey = url_encode(text("[player]"))
/*if (src.stealth) boutput(world, "<span class=\"medal\"><b>Now Playing:</b></span> <span style=\"color:blue\">[S]</span>")
else */
//How could this even happen?
// for giving non-admins the ability to play music
//For client-side audio
// and the context of each
/**
* getContext
* Outputs an interface showing stats for all processes.
*/
//usr << browse('browserassets/js/processScheduler.js', "file=processScheduler.js;display=0")
// this was actually kinda useful to have in rclick menu, hope you dont mind me reactivating it
//we don't use message_admins here because the sender/receiver might get it too
//I have a sneaking suspicion the "OK" button text depends on locale and fuck dealing with that
//Antag roles (yes i said antag jeez shut up about it already)
//General info
//Common options
//Wire: Hey I wonder if I can put a short syntax condition with a multi-line text result inside a multi-line text string
//Turns out yes but good lord does it break dream maker syntax highlighting
//Movement based options
//Admin control options
//Very special roles
//Transformation options
/* This is not needed with monkies being a mutantrace.
if (ismonkey(M))
dat += "<b>Is a Monkey</b>"
else */
//Coder options
// More info would be nice (Convair880).
// Rogue AIs modify the global lawset.
// Syndicate laws don't matter if we're emagged.
// If I see anyone granting powers to specific keys like the code that was here,
// I will both remove their SVN access and permanently ban them from my servers.
// path, name, strain, bypass resist
// path, name, strain, bypass resist
// Don't remove.
// The mask IS your new face (Convair880).
//?src=\ref[src];real_name=input'><b>[src.real_name]</b></a> "
//?src=\ref[src];gender=input'><b>[src.gender == MALE ? "Male" : "Female"]</b></a><br>"
//?src=\ref[src];age=input'>[src.age]</a>"
//?src=\ref[src];blType=input'>[src.blType]</a><br>"
//?src=\ref[src];s_tone=input'>[-src.s_tone + 35]/220</a><br>"
//?src=\ref[src];fat=1'>[src.fat ? "YES" : "NO"]</a><br>"
//?src=\ref[src];mutantrace=1'>[src.mutantrace ? capitalize(src.mutantrace.name) : "None"]</a><br>"
//?src=\ref[src];updateid=1'>[src.update_wearid ? "YES" : "NO"]</a><br>"
//?src=\ref[src];hair=input'>Change Color</a> <font face=\"fixedsys\" size=\"3\" color=\"[src.customization_first_color]\"><table bgcolor=\"[src.customization_first_color]\"><tr><td>IM</td></tr></table></font>"
//?src=\ref[src];customization_first=input'>[src.customization_first]</a>"
//?src=\ref[src];facial=input'>Change Color</a> <font face=\"fixedsys\" size=\"3\" color=\"[src.customization_second_color]\"><table bgcolor=\"[src.customization_second_color]\"><tr><td>GO</td></tr></table></font>"
//?src=\ref[src];customization_second=input'>[src.customization_second]</a>"
//?src=\ref[src];detail=input'>Change Color</a> <font face=\"fixedsys\" size=\"3\" color=\"[src.customization_third_color]\"><table bgcolor=\"[src.customization_third_color]\"><tr><td>GO</td></tr></table></font>"
//?src=\ref[src];customization_third=input'>[src.customization_third]</a>"
//?src=\ref[src];eyes=input'>Change Color</a> <font face=\"fixedsys\" size=\"3\" color=\"[src.e_color]\"><table bgcolor=\"[src.e_color]\"><tr><td>KU</td></tr></table></font>"
//?src=\ref[src];apply=1'>Apply</a><br>"
//?src=\ref[src];cinematic=1'>[src.cinematic]</a><br>"
//Heh
//Heh 2: Merlin Edition
//Oh no what if we get orphaned!! (Also don't garbage collect us as soon as we spawn you fuk)
// Skin tone
//if(!src.mutantrace)
//src.preview_icon.Blend(new /icon('icons/mob/human_underwear.dmi', "none"), ICON_OVERLAY) // why are you blending an empty icon state into the icon???
// this seems to be quasi-standard for dead and wraith mobs? might fuck up target observers but WHO CARES
// it'll sort itself out on the next Life() tick anyway
//target = input(usr, "Target", "Target") as mob in world
//target = input(usr, "Target", "Target") as mob|obj|turf in world
// Added temperature (Convair880).
// Brought in line with adding reagents via the player panel (Convair880).
// Not warranted for items etc, they aren't important enough to trigger an admin alert. Silicon mobs don't metabolize reagents.
//Bee.icon_state = initial(Bee.icon_state)
// if people aren't being weird about the icons it should just remove the "-dead"
//Imagine if we could have subcategories in the popup menus. Wouldn't that be nice?
//This needs to be here
//Nobody gives a shit if you wanna be an npc.
//You can only get rid of the ghost if you wanna swap with an NPC, because a player is getting YOUR ghost.
//You're dead, I guess an orphan ghost is not something we'd want.
//You're using admin observe and trying to be a smarty
//You don't have a mind. Let's give you one and try again
//usr.show_text("You don't have a mind!")
// Tweaked this to implement log entries and make it feature-complete with regard to every antagonist roles (Convair880).
// Log entries for automated antag status removal is handled in helpers.dm, remove_mindslave_status().
// Replace the mind first, so the new mob doesn't automatically end up with changeling etc. abilities.
// Then spawn a new mob to delete all mob-/client-bound antagonist verbs.
// Complete overkill for mindslaves, though. Blobs and wraiths need special treatment as well.
// Synthetic mobs aren't really included yet, because it would be a complete pain to account for them properly.
// They could be in a pod or whatever, which would have unfortunate results when respawned.
// Get rid of those uplinks first.
// Ugly but necessary.
// oh god this is going to be a horrible input tree
//list("Butt", "Brain", "Skull", "Left Eye", "Right Eye", "Heart", "Left Lung", "Right Lung", "All")
//Build our shame cube
//Place our sucker into it
//List of verbs cluttering the popup menus
//ADD YOUR SHIT HERE IF YOU MAKE A NEW VERB THAT GOES ON RIGHT-CLICK OR YOU ARE LITERALLY HITLER (Aka marquesas jr)
//fixed that for you -marq
//The main bunch
//So you only toggle verbs at your level
//The special A+ observer verbs
//And the special PA+ observer verbs why do we even use this? It's dumb imo
// if it's in Toggles (Server) it should be in here, ya dig?
//The main bunch
//So you only toggle verbs at your level
//The special A+ observer verbs
//And the special PA+ observer verbs why do we even use this? It's dumb imo
//Going to put some things in here that we dont need to see every single second when trying to play though atm only the add_r is in it
// I hate calling them "atom verbs" but wtf else should they be called, fuck
//
//True if a dude is here (DOES NOT APPLY TO THE "SPACE" AREA)
//Who is here (ditto)
// space blowouts use this, should always be 0
// Blowouts don't set irradiated on this area back to zero.
// don't irradiate this place!!
// Definitely DO NOT var-edit areas in the map editor because it apparently causes individual tiles
// to become detached from the parent area. Example: APCs belonging to medbay or whatever that are in
// adjacent maintenance tunnels, not in the same room they're powering. If you set the d_n_i flag,
// it will render them useless.
// wizard round objective thingy
// gang that owns this area in gang mode
// is this a gang's base (uncaptureable)?
// for gang mode
// if set, replacewithspace in this area instead replaces with this turf type
//Cannot teleport into this area without some explicit set_loc thing.
//Do people work here?
//default environment for sounds - see sound datum vars documentation for the presets.
//world.log << "[src] entered by [A]"
//Just...deal with this
//Only 1 layer deep. Will this cause issues? Hrm.
//If any mobs are entering, within a thing or otherwise
//each dumb mob
//Wake up a bunch of lazy darn critters
//If it's a real fuckin player
//Who cares about making space active gosh
//Dumb fucking medal fuck
//Handle ambient sound
//world.log << "[src] exited by [A]"
//Deal with this too
//Only if this area is now empty
//Put whatever you want here. See Entering above.
//if ("Engine Control") sound = pick(ambience_engine)
//if ("Atmospherics") sound = pick(ambience_atmospherics)
//if ("Computer Core") sound = pick(ambience_computer)
//if ("Engineering Power Room") sound = pick(ambience_power)
//People entering VR or exiting VR with stupid exploits are jerks.
// currently for z4 just so people don't teleport in there randomly
// fuck you
// goddamnit
// particle system defaults to northbound stars
/*/area/factory
name = "Derelict Robot Factory"
icon_state = "start"
/area/factory/core
name = "Aged Computer Core"
icon_state = "ai"
/area/old_outpost
name = "Derelict Outpost"
icon_state = "yellow"
sound_environment = 12
/area/old_outpost/engine
name = "Outpost Engine"
icon_state = "dk_yellow"
sound_environment = 10
/area/old_outpost/control
name = "Outpost Control"
icon_state = "purple"
/area/old_outpost/medical
name = "VR Research"
icon_state = "medresearch"
sound_environment = 3
/area/old_outpost/study
name = "Outpost Study"
icon_state = "green"
sound_environment = 4
/area/old_outpost/teleporter
name = "Outpost Teleporter"
icon_state = "teleporter"
sound_environment = 2*/
/////////////////// cogwerks- arctic derelict
// stole this code from the void definition
// this might fuck something up but it might also be hilarious
///////////////////// keelin / cogwerks - caves and biodome areas
////////////////////// cogwerks - solar lounge
////////////////////// cogwerks - HELL
////////////////////// cogwerks - crypt place
//Spacejunk
//These are shuttle areas, they must contain two areas in a subgroup if you want to move a shuttle from one
//place to another. Look at escape shuttle for example.
//DO NOT TURN THE RL_Lighting STUFF ON FOR SHUTTLES. IT BREAKS THINGS.
/*/area/prison/cell_block/A
name = "Prison Cell Block A"
icon_state = "brig"
/area/prison/cell_block/B
name = "Prison Cell Block B"
icon_state = "brig"
/area/prison/cell_block/C
name = "Prison Cell Block C"
icon_state = "brig"
*/
//
// ????
// sometimes you just gotta make an icon the way it is because that's what your heart tells you to do, even if it looks like something a cartoon for toddlers would reject for looking too stupid
//He lives here
//As does the hos
//name = "Research Outpost Zeta"
// cogmap new areas ///////////
///////////////////////////////
// locate and store the motioncamera
// spawn on a delay to let turfs/objs load
//
// ===
//Halloween is all about darkspace
// override defaults for space
/*spawn(5)
for(var/turf/T in src) // count the number of turfs (for lighting calc)
if(no_air)
T.oxygen = 0 // remove air if so specified for this area
T.n2 = 0
T.res_vars()
*/
// all machines set to current power level, also updates lighting icon
//no fire alarms in space
//no parties in space!!!
// icon_state = "blue"
// new lighting behaviour with obj lights
// pantsfix
// return true if the area has power to given channel
// called when power status changes
// for each machine in the area
// locate and store the motioncamera
// spawn on a delay to let turfs/objs load
//popDownTurrets()
//Counts up for tiles traveled in throw mode. Only resets for mobs.
//Setting this to 1 before throwing will make the object behave as if in space.
//When 1 item will return like a boomerang.
//Sorry about this.
// **TODO: Better behaviour for windows
// which are dense, but shouldn't always stop movement
//fuck you, monkeys
// might drop stuff while already juggling things
// Added log_reagents() calls for drinking glasses. Also the location (Convair880).
// nice catch, hayes. don't ever fuckin do it again
//you're all thumbs!!!
//spawn(2) step(src, turn(src.dir, 180))
/*if(istype(hit_atom, /turf/simulated/wall) && istype(src, /obj/item))
var/turf/simulated/wall/W = hit_atom
W.take_hit(src)*/
//use a modified version of Bresenham's algorithm to get from the atom's current position to that of the target
//Gotta do this in 4 steps or byond decides that the best way to interpolate between (0 and) 180 and 360 is to just flip the icon over, not turn it.
// only stop when we've gone the whole distance (or max throw range) and are on a non-space tile, or hit something, or hit the end of the map, or someone picks it up
// going off the edge of the map makes get_step return null, don't let things go off the edge
// going off the edge of the map makes get_step return null, don't let things go off the edge
// only stop when we've gone the whole distance (or max throw range) and are on a non-space tile, or hit something, or hit the end of the map, or someone picks it up
// going off the edge of the map makes get_step return null, don't let things go off the edge
// going off the edge of the map makes get_step return null, don't let things go off the edge
//done throwing, either because it hit something or it finished moving
//Wire note: Small fix stemming from pie science. Throw a pie at yourself! Whoa!
//testing boomrang stuff
//throw_at(atom/target, range, speed)//
//if(target != usr) throw_at(usr, 10, 1)
//Ex.
//Puts the 'ass' image in the slot defined as "hat"
//This will check the existing overlay in the "hat" slot and reject the update
//Icon state change
//This will detect the change and update the overlay accordingly
//Removes the overlay assigned to the "hat" slot, along with the cached image
//Alt.
//Removes the overlay in the "hat" slot, but retains the cached image for retrieval with GetOverlayImage
//Ex.
//Removes all overlays on A
//Removes all overlays on A but retains the cached images
//Ex.
//We have an atom A, having an overlay named "hat"
//Retrieve the cached image in the hat slot
//Not in-scope, but as GetOverlayImage can return null it's good practice to ensure you got an image before doing things to the returned value
//Change the icon state of it
//Update the overlay with the changes
//Ex.
//We have an atom A, that may or may not have an overlay named "hat"
//Retrieve the cached image in the hat slot and sets the icon_state to ushanka or creates a new one using image('obj/item/hats.dmi', "ushanka")
//Ex.
//Clears the overlays in slots key0, key1 and key2. Does not retain cached images.
//Same as above
//Same as above but retains cached images
//List to store info about the last state of the icon
//Ok, we don't have previous data, but we will add an overlay
//We don't have data and we won't add an overlay
//overlay_refs[key]
//If it's the same image as the other one and the hashes match then do not update
//There is an existing overlay in place in this slot, remove it
//Fuck yoooou byond (this gotta be by index or it'll fail if the same thing's in overlays several times)
//Because we're storing the position of each overlay in the list we need to shift our indices down to stay synched
//I.icon_state
//Keep the cached image available?
//Clear the index
//Clear the hash
//overlay_refs[key] = prev_data //Update our list <- Pointers, dumbass /Spy
//Some men just want to watch the world burn
//Maybe someone forgets to include this argument and goes straight for the list, let's handle that case
//The retain_cache value will be here as well, so skip it
//Never rely on this proc returning an image.
//Ok, apparently modifying anything pertaining to the image appearance causes a hubbub, thanks byand
/////////////////////////////////////////////
//helper procs
/////////////////////////////////////////////
// fuck off byond fuck you
//Override for the texture size used by setTexture.
// :v
//Change the name of this atom when a material is applied?
//Change the desc of this atom when a material is applied?
//List of attached objects. Objects in this list will follow this atom around as it moves.
//Reduces damage from explosions
///Chemistry.
//var/chem_is_open_container = 0
// replaced by OPENCONTAINER flags and atom/proc/is_open_container()
///Chemistry.
// Convenience proc to see if a container is open for chemistry handling
// returns true if open
// false if closed
// trans from src to A
// what're we gunna do here?? ain't got no reagent holder
// Check to make sure the from container isn't empty.
// Destination Container is full, quit trying to do things what you can't do!
// Notify the user, then exit the process.
//Placeholder for total volume transferred
// Check to make sure that both containers content's combined won't overfill the destination container.
// Dump only what fills up the destination container.
// This wasn't logged. Call before trans_to (Convair880).
// Dump the amount of reagents.
// Tell the user they did a thing.
// Just make T the whole dang amount then.
// Ditto (Convair880).
// Dump it all!
//This is sort of like a version of Topic that is not for browsing.
//Called AFTER the material of the object was changed.
//This is gonna be fun!
//hail satan full of grace
//return !(src.flags & ON_BORDER) || src.CanPass(mover, target, 1, 0)
// fuck it
// var/elevation = 2 - not used anywhere
// this should in turn fire off its own slew of move calls, so don't do anything here
// eyebots aint got no arms man, how can they be pulling stuff???????
// no pulling other mobs for ghostdrones (but they can pull other ghostdrones)
//Wire: Hi this was so dumb. Turns out it isn't only humans that have huds, who woulda thunk!!
//yes this uses the dreaded ":", deal with it
//make it work from farther away
// Added for forensics (Convair880).
//boutput(usr, "<span style=\"color:red\">This is a bloody [src.name].</span>")
//boutput(usr, "[src.desc] It seems to be covered in blood.")
/*boutput(usr, "This is \an [src.name].")
if (src.desc)
boutput(usr, src.desc)*/
//boutput(usr, extra)
//!( istype(W, /obj/item/grab) || istype(W, /obj/item/spraybottle) || istype(W, /obj/item/card/emag)))
// Fixed: now adds distorted prints even if 'fingerprintslast == ckey'. Important for the clean_forensic proc (Convair880).
//Limit fingerprints in the list to 6
// limit the number of fingerprints to 6, previously 3
//This will looks stupid on objects larger than 32x32. Might have to write something for that later. -Keelin
//, key)
//, var/key = "texture")
//Try to find an appropriately sized icon.
//mask is now a cut-out of the texture shaped like the object.
// WHAT THE ACTUAL FUCK IS THIS SHIT
// WHO THE FUCK WROTE THIS
// Increased from 3 (Convair880).
// Was clean_blood. Reworked the proc to take care of other forensic evidence as well (Convair880).
// The first version accidently looped through everything for every atom. Consequently, cleaner grenades caused horrendous lag on my local server. Woops.
// Mobs are a special case.
//src.overlays = null
// Don't think it should clean doors and the like. Give the detective at least something to work with.
// Just in case.
// Can't clean your hands when wearing gloves.
// Foreign fingerprints on the mob.
// Only humans can have residue at the moment.
// Punching cyborgs does leave fingerprints for instance.
//To stop ghostdrones dragging people anywhere
/* This was SUPPOSED to make the innerItem of items act on the mousedrop instead but it doesnt work for no reason
if (istype(src, /obj/item))
var/obj/item/W = src
if (W.useInnerItem && W.contents.len > 0)
target = pick(W.contents)
//world.log << "calling mousedrop_t on [over_object] with params: [src], [usr]"
*/
// For cyborg docking stations (Convair880).
// if the reagent container just had something added, add will be 1.
//wtf
// bullet_act called when anything is hit buy a projectile (bullet, tazer shot, laser, etc.)
// flag is projectile type, can be:
//PROJECTILE_TASER = 1 taser gun
//PROJECTILE_LASER = 2 laser gun
//PROJECTILE_BULLET = 3 traitor pistol
//PROJECTILE_PULSE = 4 pulse rifle
//PROJECTILE_BOLT = 5 crossbow
//PROJECTILE_WEAKBULLET = 6 detective's revolver
//Return an atom if you want to make the projectile's effects affect that instead.
// this handles RL_Lighting for luminous atoms and some child types override it for extra stuff
// like the 2x2 pod camera. fixes that bug where you go through a warp portal but your camera doesn't update
//
// there are lots of old places in the code that set loc directly.
// ignore them they'll be fixed later, please use this proc in the future
// fuck haxploits
// standardized damage procs
//staticinst.theme = themes[1]//fart
//#define GOONSTATION
//TODO: Merge with Window?
//it is being merged with window
//use this and be fat
//must be unique!
//default is wire's ugly theme. this var only matters if the window is unthemed!
//proc/exampleSection( var/list/hreflist )
// src.SetBody( "Feel ashamed of your words and deeds!" )
//:D
//CPROF_ACTV =
//TODO; #ifdef BTIME
//10 GTIME/s
//??
//fart
//utility
//Unique name for the theme. Windows reference their desired based on this name. (and defaults to the base if it doesn't exist)
//A list of 'file's to send to clients. Make sure they're singlequoted files.
//If CHUI_VERBOSITY is at least 1, files in here will automatically be reloaded into the cache
//at runtime for utility of testing new themes.
//var/list/send = list()
//Stream the theme's resources to the client; it will bail if they have already received it.
//Generates a header based on a set of parameters
//Common to all themes
//Theme specific
//Generates a body based on parameters and desired body content.
//Generates a footer based on parameters.
//Renders a button. The elements ID must be set to id in order for the javascript portion of Chui to function properly.
//send = list('chui/themes/default/default.css', 'chui/chui.js', 'chui/themes/default/images/bl.gif', 'chui/themes/default/images/borderSlants.png', 'chui/themes/default/images/br.gif', 'chui/themes/default/images/scanLine.png', 'chui/themes/default/images/tl.gif', 'chui/themes/default/images/topShadow.png', 'chui/themes/default/images/tr.gif', 'chui/themes/default/images/buttons/btn-contrast-active-br.gif','chui/themes/default/images/buttons/btn-contrast-active-tl.gif','chui/themes/default/images/buttons/btn-contrast-br.gif','chui/themes/default/images/buttons/btn-contrast-hover-br.gif','chui/themes/default/images/buttons/btn-contrast-tl.gif','chui/themes/default/images/buttons/btn-standard-active-br.gif','chui/themes/default/images/buttons/btn-standard-active-tl.gif','chui/themes/default/images/buttons/btn-standard-br.gif','chui/themes/default/images/buttons/btn-standard-hover-br.gif','chui/themes/default/images/buttons/btn-standard-tl.gif')
//todo, remember if this matters
//winset?[params["data"]["ref"]].is-minimized=true' class='min'><strong>-</strong></a>
//have the switch, when an option is selected, chui.onSwitchSelected( id, optionName )
//the key of the list is the name, the value is the label. these labels cannot be changed at runtime so don't worry about that
//The windows name is what is displayed in the titlebar.
//It does not need to be unique, and is just a utility.
//This is a list of people that have the window currently open.
//It is preferable you use verify first.
//This is the desired theme. Make sure it is set to a text string.
//It is automatically changed to the datum type in New()
//This is the atom the window is attached to. Can be set in New()
//If set, Chui will use it to determine whether or not the viewer
//is both in range and is fully conscious to be using the window and
//for receiving updates.
//This is the active template. The template engine is currently incomplete.
//However, you can set this to a text string (or file; it'll load the file into the var
//required) to have the panel's body set to it when necessary. Preferable to automatic
//generation as to not pollute the string table.
//A list of sections. Will eventually work by being an associative list of templates.
//You will be able to call .SetSection( name ) or set the section via code.
//It will allow you to split up your window into multiple HTML files/code.
//Section system, is a TODO.
//The list of Chui flags. Not currently used to its full potential.
//CHUI_FLAG_SIZABLE -> Allows the window to be resized.
//CHUI_FLAG_MOVABLE -> Allows the window to be moved.
//If overriden, be sure to call ..()
//Override this if you have a DM defined window.
//Returns the HTML the window will have.
//Do not call directly.
//Called to generate HTML for a client and desired body text.
//todo, better this.
//Subscribe a client to use this window.
//Chui will open the window on their client and have its content set appropriately.
//The window ref is the \ref[src] of the window.
//theme.streamToClient( who )
//Returns true if the client is subscribed.
//Will also perform a validation check and unsubscribe those who don't pass it.
//Use of this is preferable to using the subscribers var; but is appropriately slower.
//Unsubscribes a client from the window.
//Will also close the window.
//See /client/proc/Browse instead.
//todo, better this.
//theme.streamToClient( who )
//Check if a client should actually be subscribed.
//Can be used to check if someone is subscribed without unsubscribing them
//if they don't check out.
//if( !victim.stat && !(panel.flags & chui_FLAG_USEDEAD) ) return -1
//wow this is some jerk.. i blame spacenaba
//Calls a Javascript function with a set number of arguments on everyone subscribed.
//For prediction, you can include a client to exclude from this.
//Called when a template variable changes.
//
//A list of template vars
//Sets a template var and displays it.
//Gets a template var
//Generates a template var; use it for cases of inline HTML.
//UNUSED..
//Override this instead of Topic()
//Called when a theme button is clicked.
//Called when Javascript sends a request; return with data to be given back to JS.
//TODO: When JSON is included. callJSFunction( "chui.reqReturn",
//Called when the close button is clicked on both
//istype( win ) && win.Unsubscrbe( src )
//Might not be a standard chui window but we'll play along.
//A chui substitute for usr << browse()
//Mostly the same syntax.
//#define browse #error Use --.Browse() instead.
//just, in general
//The intention here is to basically make the game stealthily unplayable, prevents you from getting randomly picked as traitor, silently drops some Move() and Click() calls, etc.
//Number of antagonist tokens available to the player
//Set when the player readies up at round start, and opts to redeem a token.
// please ignore this for now thanks in advance - drsingh
// authenticate = 0
// comment out the line below when debugging locally to enable the options & messages menu
//Has this client done the mass resource downloading yet?
//Assign custom interface datums
//src.chui = new /datum/chui(src)
//forum.ss13.co\">the forums</a> and post an appeal.
// moved preferences from new_player so it's accessible in the client scope
// new player logic, moving some of the preferences handling procs from new_player.Login
// No admin changelog for goat farts (Convair880).
//www.byond.com/download/")
/* if (ticker && ticker.mode && istype(ticker.mode, /datum/game_mode/sandbox))
if(src.holder && (src.holder.level >= 3))
src.verbs += /mob/proc/Delete*/
//Will ban yonder fucker in case they are prix
//Will analyze their computer ID usage patterns for aberrations
// haha get fucked
//ip-api.com/json/[addr]")
// hardcoding argentina for now
//var/c_text = "Argentina"
//var/r_text = "Entre Rios"
//var/i_text = "Federal"
//if (findtext(jd, c_text) && findtext(jd, r_text) && findtext(jd, i_text))
// logTheThing("admin", null, null, "Banned location: Argentina, Entre Rios, Federal for IP [addr].")
// return 1
//byond.com/members/[src.ckey]?format=text")
///client/Southwest()
//
//return
// force_off is set to 1 when the button for this is released in WASD mode (currently B), else it's 0
// ctrl+t for admin say
// ctrl+t for admin say
// this is incredibly dumb, it's also just as dumb as what was here previously
//what the shit
// if(istype(src.mob, /mob/living/silicon/hive_mainframe))
// return MainframeMove(n,direct,src.mob)
// else if(isalien(src.mob))
// src.mob.inertia_dir = 0
// 3.20
// If the person is inside an object .
//Drop some of their clicks
// temp fix for buildmode buttons
// super shit hack for examining over the HUD, please replace this then murder me
//Definitely not the best place for this.
//Definitely not the best place for this.
// yeah lets call this thing EVERY TICK, jesus fuck byond
//we don't use message_admins here because the sender/receiver might get it too
//we don't use message_admins here because the sender/receiver might get it too
//we don't use message_admins here because the sender/receiver might get it too
//Message admins
//Message mentors
//Special cases
//A thing for the chat output to call so that links open in the user's default browser, rather than IE
/* For debug
if ("out")
out(src, href_list["msg"])
*/
//Let's significantly increase the dropped clicks / moves for some time
//1 - 8 seconds
// total range: 380 - 750 (range: 370nm)
// red: 570 - 750 (range: 180nm)
// green: 490 - 620 (range: 130nm)
// blue: 380 - 500 (range: 120nm)
//wiki.ss13.co")
//goonhub.com/maps/cogmap2")
//goonhub.com/maps/destiny")
//goonhub.com/maps/cogmap")
//forum.ss13.co")
////////////
// drsinghs grand experiment vol 6
// this pattern might seem redundant but it ensures objects aren't disposed twice.
// it also proides a quick way to check if an object you're using was disposed but never deleted by the garbage collector because of your reference
// the point of this is to reduce code duplication. cleanup code only needs to exist one time in disposing() and it will be called whether the object is deleted with del() or dispose()
//
// override this in children for your type specific disposing implementation, make sure to call ..() so the root disposing runs too
// don't override this one, just call it instead of delete to get rid of something cheaply
// for caching/reusing
// If this thing went through the delete queue and was rescued by the pool mechanism, we should reset the qdeled flag.
// called when a variable is admin-edited
//starting points
//starting regen
// Just-in-case fallback.
//else
// boutput(owner, "<span style=\"color:red\">Nothing is bound to alt.</span>")
//else
// boutput(owner, "<span style=\"color:red\">Nothing is bound to ctrl.</span>")
//else
// boutput(owner, "<span style=\"color:red\">Nothing is bound to shift.</span>")
//Please make sure you return 1 if one of the holders/abilities handled the key.
/*screams*
var/static/image/one = image('icons/mob/spell_buttons.dmi',"1")
var/static/image/two = image('icons/mob/spell_buttons.dmi',"2")
var/static/image/three = image('icons/mob/spell_buttons.dmi',"3")
var/static/image/four = image('icons/mob/spell_buttons.dmi',"4")
var/static/image/five = image('icons/mob/spell_buttons.dmi',"5")
var/static/image/six = image('icons/mob/spell_buttons.dmi',"6")
var/static/image/seven = image('icons/mob/spell_buttons.dmi',"7")
var/static/image/eight = image('icons/mob/spell_buttons.dmi',"8")
var/static/image/nine = image('icons/mob/spell_buttons.dmi',"9")
var/static/image/zero = image('icons/mob/spell_buttons.dmi',"0")
proc/updateIcon()
src.overlays.Cut()
if (owner.waiting_for_hotkey)
src.overlays += src.binding
if(owner.action_key_number > -1)
set_number_overlay(owner.action_key_number)
return
proc/set_number_overlay(var/num)
switch(num)
if(1)
src.overlays += src.one
if(2)
src.overlays += src.two
if(3)
src.overlays += src.three
if(4)
src.overlays += src.four
if(5)
src.overlays += src.five
if(6)
src.overlays += src.six
if(7)
src.overlays += src.seven
if(8)
src.overlays += src.eight
if(9)
src.overlays += src.nine
if(0)
src.overlays += src.zero
return
// Switch to targeted only if multiple mobs are in range. All screen abilities customize their clicked(),
// and you have to call this proc there if you want to use it. You also need to set 'target_selection_check = 1'
// for every spell that should function in this manner.
// See /obj/screen/ability/wrestler/clicked() for a practical example (Convair880).
proc/do_target_selection_check()
var/datum/targetable/spell = owner
var/use_targeted = 0
if (!spell || !istype(spell))
return 0
if (!spell.holder)
return 0
if (spell.target_selection_check == 1)
var/list/mob/targets = spell.target_reference_lookup()
if (targets.len <= 0)
boutput(owner.holder.owner, "<span style=\"color:red\">There's nobody in range.</span>")
use_targeted = 2 // Abort parent proc.
else if (targets.len == 1) // Only one guy nearby, but we need the mob reference for handleCast() then.
use_targeted = 0
spawn
spell.handleCast(targets[1])
use_targeted = 2 // Abort parent proc.
else
boutput(owner.holder.owner, "<span style=\"color:red\"><b>Multiple targets detected, switching to manual aiming.</b></span>")
use_targeted = 1
return use_targeted
//WIRE TOOLTIPS
MouseEntered(location, control, params)
var/theme
if (istype(owner, /datum/targetable/wraithAbility) || istype(owner, /datum/targetable/revenantAbility))
theme = "wraith"
usr.client.tooltip.show(src, params, title = src.name, content = (src.desc ? src.desc : null), theme = theme)
MouseExited()
usr.client.tooltip.hide()
/obj/screen/ability/topBar
var/static/image/ctrl_highlight = image('icons/mob/spell_buttons.dmi',"ctrl")
var/static/image/shift_highlight = image('icons/mob/spell_buttons.dmi',"shift")
var/static/image/alt_highlight = image('icons/mob/spell_buttons.dmi',"alt")
var/static/image/cooldown = image('icons/mob/spell_buttons.dmi',"cooldown")
var/static/image/darkener = image('icons/mob/spell_buttons.dmi',"darkener")
var/obj/screen/pseudo_overlay/cd_tens
var/obj/screen/pseudo_overlay/cd_secs
var/tens_offset_x = 0
var/tens_offset_y = 0
var/secs_offset_x = 0
var/secs_offset_y = 0
New()
..()
var/obj/screen/pseudo_overlay/T = new /obj/screen/pseudo_overlay(src)
var/obj/screen/pseudo_overlay/S = new /obj/screen/pseudo_overlay(src)
T.icon = 'icons/effects/particles_characters.dmi'
S.icon = 'icons/effects/particles_characters.dmi'
T.x_offset = tens_offset_x
T.y_offset = tens_offset_y
S.x_offset = secs_offset_x
S.y_offset = secs_offset_y
cd_tens = T
cd_secs = S
darkener.alpha = 100
spawn(0)
T.color = owner.cd_text_color
S.color = owner.cd_text_color
updateIcon()
var/mob/M = get_controlling_mob()
if (!istype(M) || !M.client)
return null
src.overlays = list()
if (owner.holder)
if (src == owner.holder.shiftPower)
src.overlays += src.shift_highlight
if (src == owner.holder.ctrlPower)
src.overlays += src.ctrl_highlight
if (src == owner.holder.altPower)
src.overlays += src.alt_highlight
if (owner.waiting_for_hotkey)
src.overlays += src.binding
if(owner.action_key_number > -1)
set_number_overlay(owner.action_key_number)
return
proc/get_controlling_mob()
var/mob/M = owner.holder.owner
if (!istype(M) || !M.client)
return null
return M
proc/update_on_hud(var/pos_x = 0,var/pos_y = 0)
updateIcon()
var/mob/M = get_controlling_mob()
if (!istype(M) || !M.client)
return null
if (owner.special_screen_loc)
src.screen_loc = owner.special_screen_loc
else
src.screen_loc = "NORTH-[pos_y],[pos_x]"
var/name = initial(owner.name)
if (owner.holder)
if (owner.holder.usesPoints)
name += "; Cost: [owner.pointCost] [owner.holder.pointName]"
name += "; Cooldown: [owner.cooldown / 10] seconds"
src.name = name
M.client.screen += src
M.client.screen -= src.cd_tens
M.client.screen -= src.cd_secs
var/on_cooldown = round((owner.last_cast - world.time) / 10)
if (on_cooldown > 0)
on_cooldown = min(on_cooldown,99)
src.overlays += src.darkener
src.overlays += src.cooldown
if (on_cooldown >= 10)
src.cd_tens.icon_state = "[get_digit_from_number(on_cooldown,2)]"
src.cd_tens.screen_loc = "NORTH-[pos_y]:[src.tens_offset_y],[pos_x]:[src.tens_offset_x]"
M.client.screen += src.cd_tens
src.cd_secs.icon_state = "[get_digit_from_number(on_cooldown,1)]"
src.cd_secs.screen_loc = "NORTH-[pos_y]:[src.secs_offset_y],[pos_x]:[src.secs_offset_x]"
M.client.screen += src.cd_secs
clicked(parameters)
if (!owner.holder || !owner.holder.owner || usr != owner.holder.owner)
boutput(usr, "<span style=\"color:red\">You do not own this ability.</span>")
return
var/datum/abilityHolder/holder = owner.holder
var/mob/user = holder.owner
if(parameters["left"])
if (owner.targeted && user.targeting_spell == owner)
user.targeting_spell = null
user.update_cursor()
return
if (parameters["ctrl"])
if (owner == holder.altPower || owner == holder.shiftPower)
boutput(user, "<span style=\"color:red\">That ability is already bound to another key.</span>")
return
if (owner == holder.ctrlPower)
holder.ctrlPower = null
boutput(user, "<span style=\"color:blue\"><b>[owner.name] has been unbound from Ctrl-Click.</b></span>")
holder.updateButtons()
else
holder.ctrlPower = owner
boutput(user, "<span style=\"color:blue\"><b>[owner.name] is now bound to Ctrl-Click.</b></span>")
else if (parameters["alt"])
if (owner == holder.shiftPower || owner == holder.ctrlPower)
boutput(user, "<span style=\"color:red\">That ability is already bound to another key.</span>")
return
if (owner == holder.altPower)
holder.altPower = null
boutput(user, "<span style=\"color:blue\"><b>[owner.name] has been unbound from Alt-Click.</b></span>")
holder.updateButtons()
else
holder.altPower = owner
boutput(user, "<span style=\"color:blue\"><b>[owner.name] is now bound to Alt-Click.</b></span>")
else if (parameters["shift"])
if (owner == holder.altPower || owner == holder.ctrlPower)
boutput(user, "<span style=\"color:red\">That ability is already bound to another key.</span>")
return
if (owner == holder.shiftPower)
holder.shiftPower = null
boutput(user, "<span style=\"color:blue\"><b>[owner.name] has been unbound from Shift-Click.</b></span>")
holder.updateButtons()
else
holder.shiftPower = owner
boutput(user, "<span style=\"color:blue\"><b>[owner.name] is now bound to Shift-Click.</b></span>")
else
if (holder.help_mode && owner.helpable)
boutput(user, "<span style=\"color:blue\"><b>This is your [owner.name] ability.</b></span>")
boutput(user, "<span style=\"color:blue\">[owner.desc]</span>")
if (owner.holder.usesPoints)
boutput(user, "<span style=\"color:blue\">Cost: <strong>[owner.pointCost]</strong></span>")
if (owner.cooldown)
boutput(user, "<span style=\"color:blue\">Cooldown: <strong>[owner.cooldown / 10] seconds</strong></span>")
else
if (!owner.cooldowncheck())
boutput(holder.owner, "<span style=\"color:red\">That ability is on cooldown for [round((owner.last_cast - world.time) / 10)] seconds.</span>")
return
if (!owner.targeted)
owner.handleCast()
return
else
user.targeting_spell = owner
user.update_cursor()
else if(parameters["middle"])
if(owner.waiting_for_hotkey)
holder.cancel_action_binding()
else
owner.waiting_for_hotkey = 1
boutput(usr, "<span style=\"color:blue\">Please press a number to bind this ability to...</span>")
owner.holder.updateButtons()
MouseDrop_T(atom/movable/O as mob|obj, mob/user as mob)
if (!owner || !owner.holder || !owner.holder.topBarRendered)
return
if (!istype(O,/obj/screen/ability/topBar) || !owner.holder)
return
var/obj/screen/ability/source = O
if (!istype(src.owner) || !istype(source.owner))
boutput(src.owner, "<span style=\"color:red\">You may only switch the places of ability buttons.</span>")
return
var/index_source = owner.holder.abilities.Find(source.owner)
var/index_target = owner.holder.abilities.Find(src.owner)
owner.holder.abilities.Swap(index_source,index_target)
owner.holder.updateButtons()
/datum/targetable
var
name = null
desc = null
max_range = 7
targeted = 0
target_anything = 0
last_cast = 0
cooldown = 100
start_on_cooldown = 0
datum/abilityHolder/holder
obj/screen/ability/object
pointCost = 0
special_screen_loc = null
helpable = 1
cd_text_color = "#FFFFFF"
copiable = 1
target_nodamage_check = 0
target_selection_check = 0 // See comment in /obj/screen/ability.
dont_lock_holder = 0 // Bypass holder lock when we cast this spell.
ignore_holder_lock = 0 // Can we cast this spell when the holder is locked?
restricted_area_check = 0 // Are we prohibited from casting this spell in 1 (all of Z2) or 2 (only the VR)?
can_target_ghosts = 0 // Can we target observers if we see them (ectogoggles)?
check_range = 1 //Does this check for range at all?
sticky = 0 //Targeting stays active after using spell if this is 1. click button again to disable the active spell.
ignore_sticky_cooldown = 0 //if 1, Ability will stick to cursor even if ability goes on cooldown after first cast.
action_key_number = -1 //Number hotkey assigned to this ability. Only used if > 0
waiting_for_hotkey = 0 //If 1, the next number hotkey pressed will be bound to this.
preferred_holder_type = /datum/abilityHolder
icon = 'icons/mob/spell_buttons.dmi'
icon_state = "blob-template"
proc
handleCast(atom/target)
var/result = tryCast(target)
if (result && result != 999)
last_cast = 0 // reset cooldown
else if (result != 999)
doCooldown()
afterCast()
holder.updateButtons()
cast(atom/target)
return
onAttach(var/datum/abilityHolder/H)
if (src.start_on_cooldown)
doCooldown()
return
// Don't remove the holder.locked checks, as lots of people used lag and click-spamming
// to execute one ability multiple times. The checks hopefully make it a bit more difficult.
tryCast(atom/target)
if (!holder || !holder.owner)
logTheThing("debug", usr, null, "orphaned ability clicked: [name]. ([holder ? "no owner" : "no holder"])")
return 1
if (src.holder.locked == 1 && src.ignore_holder_lock != 1)
boutput(holder.owner, "<span style=\"color:red\">You're already casting an ability.</span>")
return 999
if (src.dont_lock_holder != 1)
src.holder.locked = 1
if (!holder.pointCheck(pointCost))
src.holder.locked = 0
return 1000
if (last_cast > world.time)
boutput(holder.owner, "<span style=\"color:red\">That ability is on cooldown for [round((last_cast - world.time) / 10)] seconds.</span>")
src.holder.locked = 0
return 999
if (src.restricted_area_check)
var/turf/T = get_turf(holder.owner)
if (!T || !isturf(T))
boutput(holder.owner, "<span style=\"color:red\">That ability doesn't seem to work here.</span>")
src.holder.locked = 0
return 999
switch (src.restricted_area_check)
if (1)
if (isrestrictedz(T.z))
boutput(holder.owner, "<span style=\"color:red\">That ability doesn't seem to work here.</span>")
src.holder.locked = 0
return 999
if (2)
var/area/A = get_area(T)
if (A && istype(A, /area/sim))
boutput(holder.owner, "<span style=\"color:red\">You can't use this ability in virtual reality.</span>")
src.holder.locked = 0
return 999
if (src.targeted && src.target_nodamage_check && (target && target != holder.owner && check_target_immunity(target) == 1))
target.visible_message("<span style=\"color:red\"><B>[src.holder.owner]'s attack has no effect on [target] whatsoever!</B></span>")
src.holder.locked = 0
return 998
if (!castcheck())
src.holder.locked = 0
return 998
. = cast(target)
src.holder.locked = 0
if (!.)
holder.deductPoints(pointCost)
updateObject()
return
doCooldown()
src.last_cast = world.time + src.cooldown
castcheck()
return 1
cooldowncheck()
if (src.last_cast > world.time)
return 0
return 1
afterCast()
return
Stat()
updateObject(holder.owner)
stat(null, object)
// Universal grab check you can use (Convair880).
grab_check(var/mob/target, var/state = 1, var/dirty = 0)
if (!holder || state < 1)
return 0
var/mob/living/M = holder.owner
if (!M || !ismob(M))
return 0
var/obj/item/grab/G = null
if (dirty == 1)
var/obj/item/grab/GD = M.equipped()
if (!GD || !istype(GD) || (!GD.affecting || !ismob(GD.affecting)))
boutput(M, __red("You need to grab hold of the target with your active hand first!"))
return 0
var/mob/living/L = GD.affecting
if (L && ismob(L) && L != M)
if (GD.state >= state)
G = GD
else
boutput(M, __red("You need a tighter grip!"))
else
boutput(M, __red("You need to grab hold of the target with your active hand first!"))
return G
else
if (!target || !ismob(target))
return 0
if (src.targeted)
for (var/obj/item/grab/G2 in M)
if (G2.affecting)
if (G2.affecting != target)
continue
if (G2.affecting == M)
continue
if (G2.state >= state)
G = G2
break
else
boutput(M, __red("You need a tighter grip!"))
return 0
if (isnull(G) || !istype(G))
boutput(M, __red("You need to grab hold of [target] first!"))
return 0
else
return G
return 0
// See comment in /obj/screen/ability (Convair880).
target_reference_lookup()
var/list/mob/targets = list()
if (!holder)
return targets
var/mob/living/M = holder.owner
if (!M || !ismob(M))
return targets
for (var/mob/living/L in oview(src.max_range, M))
targets.Add(L)
return targets
/obj/screen/pseudo_overlay
// this is hack as all get out
// but since i cant directly alter the pixel offset of a screen overlay it'll have to do
name = ""
mouse_opacity = 0
layer = 61
var/x_offset = 0
var/y_offset = 0
/datum/abilityHolder/composite
var/list/holders = list()
rendered = 0
proc/addHolder(holderType)
for (var/datum/abilityHolder/H in holders)
if (H.type == holderType)
return
holders += new holderType(owner)
updateButtons()
proc/addHolderInstance(var/datum/abilityHolder/N)
for (var/datum/abilityHolder/H in holders)
if (H == N)
return
holders += N
if (N.owner != owner)
N.owner = owner
updateButtons()
proc/removeHolder(holderType)
for (var/datum/abilityHolder/H in holders)
if (H.type == holderType)
holders -= H
updateButtons()
proc/getHolder(holderType)
for (var/datum/abilityHolder/H in holders)
if (H.type == holderType)
return H
cancel_action_binding()
for (var/datum/abilityHolder/H in holders)
H.cancel_action_binding()
unbind_action_number(var/num)
for (var/datum/abilityHolder/H in holders)
H.unbind_action_number(num)
return 0
actionKey(var/num)
var/used = 0
//2 Steps avoid binding problems with more than 2 holders.
for (var/datum/abilityHolder/H in holders)
for (var/datum/targetable/T in H.abilities)
if(T.waiting_for_hotkey)
used = H.actionKey(num)
break
if(used) return used
for (var/datum/abilityHolder/H in holders)
used = H.actionKey(num)
if(used) return used
return 0
updateButtons()
for (var/datum/abilityHolder/H in holders)
H.updateButtons()
addBonus(var/value)
for (var/datum/abilityHolder/H in holders)
H.addBonus(value)
generatePoints()
for (var/datum/abilityHolder/H in holders)
H.generatePoints()
Stat()
for (var/datum/abilityHolder/H in holders)
H.Stat()
StatAbilities()
for (var/datum/abilityHolder/H in holders)
H.StatAbilities()
deductPoints(cost)
for (var/datum/abilityHolder/H in holders)
H.deductPoints(cost)
suspendAllAbilities()
for (var/datum/abilityHolder/H in holders)
H.suspendAllAbilities()
resumeAllAbilities()
for (var/datum/abilityHolder/H in holders)
H.resumeAllAbilities()
addAbility(var/abilityType)
if (!holders.len)
return
if (istext(abilityType))
abilityType = text2path(abilityType)
if (!ispath(abilityType))
return
var/datum/targetable/A = new abilityType
for (var/datum/abilityHolder/H in holders)
if (istype(H, A.preferred_holder_type))
A.holder = H
H.abilities += A
A.onAttach(H)
H.updateButtons()
return
var/datum/abilityHolder/X = holders[1]
A.holder = X
X.abilities += A
X.updateButtons()
A.onAttach(X)
return A
removeAbility(var/abilityType)
if (!ispath(abilityType))
return
for (var/datum/abilityHolder/H in holders)
H.removeAbility(abilityType)
src.updateButtons()
removeAbilityInstance(var/datum/targetable/A)
if (!istype(A))
return
for (var/datum/abilityHolder/H in holders)
H.removeAbilityInstance(A)
src.updateButtons()
getAbility(var/abilityType)
if (!ispath(abilityType))
return null
for (var/datum/abilityHolder/H in holders)
var/R = H.getAbility(abilityType)
if (R)
return R
return null
pointCheck(cost)
return 1
deepCopy()
var/datum/abilityHolder/composite/copy = new src.type
for (var/datum/abilityHolder/H in holders)
copy.holders += H.deepCopy()
return copy
transferOwnership(var/newbody)
for (var/datum/abilityHolder/H in holders)
H.transferOwnership(newbody)
owner = newbody
// cogwerks - using ISN's scary goddamn shriek here
//A little qol, probably.
//Still preserving implants
//Still preserving implants
//changelings can get this somehow and it stops speed regen ever turning off otherwise
// Don't remove.
// Headspiders shouldn't be free.
// 10 regular points for their body...
// ...and then grab their DNA stockpile too.
// Same principle.
//On Changeling tab
// ----------------------------------------
// Generic abilities that critters may have
// ----------------------------------------
// No longer ToDo thanks to Sundance420.
// -----------------
// Simple bite skill
// -----------------
// -----------------
// Simple bite skill
// -----------------
//if (MT.bleeding)
// boutput(MT, __blue("Your bleeding stops!"))
// -----------------------------------
// Devour using an action as the timer
// -----------------------------------
// --------------------------------------------------
// Fire elemental ability - shoot flames in direction
// --------------------------------------------------
// --------------------
// Wendigo style frenzy
// --------------------
// break the deadlock
// don't make quite so much mess
// ------------------------------------------------
// Martian psychic gib using an action as the timer
// ------------------------------------------------
// ----------------------------------
// Grow into a bigger form of critter
// ----------------------------------
// spiderbaby
// newtype = /mob/living/critter/spider
// ----------------------
// Fade into invisibility
// ----------------------
// -------------------------
// Martian psychic mindblast
// -------------------------
// ------------------------------------------------------------
// Experimental: charge-slam using a projectile as a line mover
// ------------------------------------------------------------
// -------------------------
// Inject someone with venom
// -------------------------
// ------
// Tackle
// ------
// ---------------------
// Martian teleportation
// ---------------------
// ----------------------------------------
// Generic abilities that critters may have
// ----------------------------------------
// TODO.
// used if a toggle ability
// Dunno about your WIP stuff. Adjust as needed.
// ----------------------------------------
// Controls for the cruiser ships.
// ----------------------------------------
// used if a toggle ability
// Placeholder because only humans use bioeffects at the moment.
// Important!
// Why not leave some forensic evidence?
// path, name, strain, bypass resist
// Written in such a way that adding other reagent containers (e.g. medicine) would be trivial.
// Food and drinking glass/bottle parent.
// Christmas cheer modifier included.
// Converted everything related to grinches from client procs to ability holders and used
// the opportunity to do some clean-up as well (Convair880).
//////////////////////////////////////////// Setup //////////////////////////////////////////////////
// Don't remove.
// They do have a critter AH by default...or should.
//////////////////////////////////////////// Ability holder /////////////////////////////////////////
/////////////////////////////////////////////// Grinch spell parent ////////////////////////////
// No custom sprites yet.
// 0: Never | 1: Ignore mob.stunned and mob.weakened | 2: Ignore all incapacitation vars
// Only human mobs and severed human heads have a skull.
// Lesser form doesn't count.
// Assign_gimmick_skull() takes care of skull replacements.
// Can might have another skull in their pocket, who knows.
// We always want to drop that skull, since gib ejectables are a RNG thing.
// Critter mobs include robots and combat drones. There's not a lot of meat on them.
// For the specialist objective. Did we feed on the target long enough?
// It's okay when the victim expired half-way through the feast, but plain corpses are too cheap.
// Can't farm monkeys.
// AH parent var for AH.locked vs. specific one for the feed objective.
// Critter mobs only use one specific type of abilityHolder for instance.
// Converted everything related to predators from client procs to ability holders and used
// the opportunity to do some clean-up as well (Convair880).
//////////////////////////////////////////// Setup //////////////////////////////////////////////////
////////////////////////////////////////////// Helper procs //////////////////////////////
// Must be at the top of the list.
// Called for every human mob spawn and mutantrace change. The value of non-standard skulls is defined in organ.dm.
// The examine desc for predators.
// Cluwnes first.
// Antagonist check.
// Ordered by skull value.
// Mutantrace and ability holder check for non-antagonists.
// Everything's still default, so check for assigned_role. Could be a lizard captain or whatever.
// Not in ticker.Agimmicks.
// Assign new skull or change value/desc.
// Defined in organ.dm. Copied because there isn't always a need to replace the skull.
//DEBUG("[H]'s skull: [new_skull.type] (V: [new_skull.value], D: [new_skull.preddesc])")
//DEBUG("[H]'s skull: [S.type] (V: [S.value], D: [S.preddesc])")
//DEBUG("[H]'s skull: [S.type] (V: [S.value], D: [S.preddesc])")
// Returns the combined value of all trophies in the player's possession.
// Your own skull doesn't count, dummy!
//////////////////////////////////////////// Ability holder /////////////////////////////////////////
/////////////////////////////////////////////// Predator spell parent ////////////////////////////
// No custom sprites yet.
// 0: Never | 1: Ignore mob.stunned and mob.weakened | 2: Ignore all incapacitation vars
// Only humans use mutantrace datums.
// Just-in-case fallback.
// depends on who you ask really
// theoretically shouldn't happen
// todo: send message, tell the player to fuck off, or something
// do not possess non-humans; do not possess living people; do not pass go; do not collect $200
// todo: add custom death
// technically we won't let it be anything else but who knows what might happen
/*proc/removeRevenantVerbs()
if (owner.mind)
owner.mind.spells.len = 0
return*/
// 35s
// ugly & fuck you byond for making me do this
// Cooldown because spam is bad.
// No cooldown here, though.
// Tasers etc.
// Don't remove this unless you are willing to adjust all existing mindslave-related procs for this very rare and specific case.
// Cooldown because spam is bad.
// Cooldown because spam is bad.
// Can't stare through a blindfold very well, no?
// Target might have been gibbed, who knows.
// Dry run. Can we phaseshift?
// Can't use any powers during phaseshift.
// Why not leave some forensic evidence?
// path, name, strain, bypass resist
// Cooldown because spam is bad.
// Only humans use bioeffects at the moment.
// Might help to get rid of those overlay issues.
// Important!
// Only humans use the blood system.
// Otherwise, two vampires could perpetually feed off of each other, trading blood endlessly.
// Victim might have been gibbed, who knowns.
// Converted everything related to vampires from client procs to ability holders and used
// the opportunity to do some clean-up as well (Convair880).
/////////////////////////////////////////////////// Setup //////////////////////////////////////////
// Don't remove.
// For testing. Just give them all abilities that are compatible.
// They do have a critter AH by default...or should.
////////////////////////////////////////////////// Helper procs ////////////////////////////////////////////////
// Just a little helper or two since vampire parameters aren't tracked by mob vars anymore.
// 1: thermal | 2: xray | 3: full power
////////////////////////////////////////////////// Ability holder /////////////////////////////////////////////
// Replaces the old vamp_blood_remaining var.
// Note: please use mob.get_vampire_blood() & mob.change_vampire_blood() instead of changing the numbers directly.
// At the time of writing, sight (thermal, x-ray) and chapel checks can be found in human.dm.
// These are thresholds in relation to vamp_blood. Last_power exists only for unlock checks as stuff
// might deduct something from vamp_blood, though it shouldn't happen on a regular basis.
// Full power.
// In the 'Vampire' tab.
///////////////////////////////////////////// Vampire spell parent //////////////////////////////////////////////////
// If you change the blood cost, cooldown etc of an ability, don't forget to update vampireTips.html too!
// Notes:
// - If an ability isn't available from the beginning, add an unlock_message to notify the player of unlocks.
// - Vampire abilities are logged. Please keep it that way when you make additions.
// - Add this snippet at the bottom of cast() if the ability isn't free. Optional but basic feedback for the player.
// var/datum/abilityHolder/vampire/H = holder
// if (istype(H)) H.blood_tracking_output(src.pointCost)
// - You should also call the proc if you make the player pay for an interrupted attempt to use the ability, for
// instance when employing do_mob() checks.
// Vampire ability sprites don't exist yet.
// 0: Never | 1: Ignore mob.stunned and mob.weakened | 2: Ignore all incapacitation vars
// Start_on_cooldown check.
// Converted everything related to werewolves from client procs to ability holders and used
// the opportunity to do some clean-up as well (Convair880).
//////////////////////////////////////////// Setup //////////////////////////////////////////////////
////////////////////////////////////////////// Helper procs //////////////////////////////
// Avoids C&P code for that werewolf disease.
// Werewolf disease is human -> WW only.
// There used to be more stuff here, most of which was moved to limb datums.
// 1: a little bit | 2: across the room
// Only used by the feast ability.
// For forensics.
// Just put 'em on the mob itself, like pulling does. Simplifies forensic analysis a bit.
// Werewolves have a very large stamina and stamina regen boost.
// Can't feast on people if they're moving around too much.
// Also called by limb datums.
// It's a long audio clip.
//////////////////////////////////////////// Ability holder /////////////////////////////////////////
// In the 'Werewolf' tab.
/////////////////////////////////////////////// Werewolf spell parent ////////////////////////////
// No custom sprites yet.
// 0: Never | 1: Ignore mob.stunned and mob.weakened | 2: Ignore all incapacitation vars
// Only humans use mutantrace datums.
// No cooldown when it fails.
// what the fuck
//putting them at the edge is dumb
// Vaguely matching placeholder.
// NPCs should always be cluwnable, I guess (Convair880)?
//H.unequip_all()
// Don't remove.
// The mask IS your new face, my friend (Convair880).
// ^-- No speech bubble.
//A.sd_SetLuminosity(4)
//A.sd_SetColor(0.95, 0.25, 0)
//temp item holder for processing
//reagent holder
//get reagent container if there is one, and check to see it has some reagents
// No cooldown when it fails.
//A.sd_SetLuminosity(3)
//A.sd_SetColor(0, 0.1, 0.8)
//B.sd_SetLuminosity(1)
//B.sd_SetColor(0, 0.1, 0.8)
// /obj/decal/icefloor moved to decal.dm
//Already in a cube?
// since this is used in at least two places to trap people in things other than ice cubes
// no cooldown if it fails
// cast failed
//A.sd_SetLuminosity(3)
//A.sd_SetColor(0.7, 0, 0.7)
// holy shit someone clean this up and just move it into the main spell proc, this is ridiclous
// Dry run. Can we phaseshift?
// Merged some stuff from wizard and vampire phaseshift for easy of use (Convair880).
// Return 1 if we got this far in the test run.
// See bigfart.dm for the ass_explosion() proc. The third value represents the probability of limb loss in percent.
//target.elecgib()
// we just want the effect, the damage is taken care of below
// adds some randomness to the damage
// no cooldown if it fails
//animate_shockwave(A)
//animate_shockwave(A)
//animate_shockwave(A)
// Simple buff for the staff. Maybe it's less of a wasted spell slot now (Convair880).
// Ability holder only checks for M.stat and wizard power, we need more than that here.
//playsound(M.loc, "sound/voice/wizard/[not_done_yet].ogg", 50, 0, -1)
// No cooldown.
// There could be multiple, I suppose.
// Has own user feedback.
// These two procs were so similar that I combined them (Convair880).
// Teleport doesn't go along well with doppelgaenger or phaseshift.
// You can keep the selection window open, so we have to do the checks again (individual item/spell procs handle the first batch).
// Pocket or backpack.
// Has own user feedback.
// Spell-specific stuff.
// Animation.
// Effect second because we had sound effects etc at the old loc.
//////////////////////////////////////////// Setup //////////////////////////////////////////////////
// Don't remove.
// For variety and predators (Convair880).
//so that this proc will work for wizards made mid-round who are wearing stuff
////////////////////////////////////////////// Helper procs ////////////////////////////////////////////////////
// ??
// Maybe if the station were more corrupted...")
// Maybe if the station were more corrupted...")
//////////////////////////////////////////// Ability holder /////////////////////////////////////////
/////////////////////////////////////////////// Wizard spell parent ////////////////////////////
// ASSHOLES
//clicked(parameters)
//if (!istype(usr, /mob/wraith))
// return
//var/mob/wraith/user = usr
//if (!istype(user) || !istype(owner))
// return
//..()
//if (!istype(holder.owner, /mob/wraith))
// boutput(holder.owner, "<span style=\"color:red\">Yo, you're not a wraith, stop that. (like how the hell did you get this. report this to a coder asap)</span>")
// return 1
//Starts at 45 seconds and scales upward exponentially
//Find a suitable corpse
//Make the corpse all grody and skeleton-y
//Messages for everyone!
//This makes it so wraith early game is much faster but hits a wall of high absorb cooldowns after ~5 corpses
//so wraiths don't hit scientific notation rates of regen without playing perfectly for a million years
//Tweaked this down from 3 minutes to 2 1/2, let's see if that ruins anything
//time limit on possession: 1 minute
//5 minutes
//If you targeted a turf for some reason, find a corpse on it
//return 0
//1 minute
//If you targeted a turf for some reason, find a valid target on it
//todo: emaggable check
// go to jail, do not pass src, do not collect pushed messages
// 20 seconds
// very steep. probably grabs 3 or 4 objects per cast -- much less effective than revenant command
// 1 minute
//If you targeted a turf for some reason, find a corpse on it
//30 seconds
//If you targeted a turf for some reason, find an object on it
//1 minute
// (?)
// surely this isn't going to be a problem
//20 seconds
// These are necessary because of the sleep call.
// We climbed onto stuff.
// Can't include a possibly non-existent item in the loop before we can run the check.
// These are necessary because of the sleep call.
// These are necessary because of the sleep call.
// Target was gibbed before we could slam them, who knows.
// These are necessary because of the sleep call.
// These are necessary because of the sleep call.
// Maybe this will help with the wallthrowing bug.
// Target was gibbed before we could throw them, who knows.
// Converted everything related to wrestlers from client procs to ability holders and used
// the opportunity to do some clean-up as well (Convair880).
//////////////////////////////////////////// Setup //////////////////////////////////////////////////
// They don't have belts.
// But they do have a critter AH by default...or should.
// Wrestler/omnitraitor vs wrestling belt.
//////////////////////////////////////////// Ability holder /////////////////////////////////////////
// Are we a wrestler as opposed to somebody with a wrestling belt?
/////////////////////////////////////////////// Wrestler spell parent ////////////////////////////
// No custom sprites yet.
// So you can't bypass the cooldown by taking off your belt and re-equipping it.
// 0: Never | 1: Ignore mob.stunned and mob.weakened | 2: Ignore all incapacitation vars
// The HUD autoequip code doesn't call unequipped() when it should, naturally.
// Not all critters have arms to grab people with, but whatever.
// Balanced for 200/12 and 200/13 drugs (e.g. epinephrine or meth), so stamina regeneration
// buffs are prioritized over total stamina modifiers.
// Chems with severe stamina penalty exist, so this should be capped.
// About the same minimum as the old wrestling belt procs.
//DEBUG("Default CD: [src.cooldown]. Modifier: [R]. Actual CD: [CD].")
// Why isn't this in afterCast()? Well, failed attempts to use an abililty call it too.
//forum.ss13.co/viewtopic.php?f=10&t=5021\">http://forum.ss13.co/viewtopic.php?f=10&t=5021</a>
//forum.ss13.co/viewtopic.php?f=10&t=2932
//Parent admin proc, if they have this then they have admin status
//client.holder will be modified to contain this
//
//Powers contained within parent proc, with an id attributed to each
//Each admin command will be verbs in a subset of powers, that means they
//should be automatically given to the player
//Coder powers
//Ban, job ban etc
//Any jump related procs
//prison etc
//Force say, abusable admin powers
//Spawn items, turfs, mobs
//Misc highly abuseable powers
//Misc low abuse powers
//Edit/view variables
//Simply a container for variables and flags you might need for your telescience areas.
//var/datum/ai_laws/centralized_ai_laws
//
// Artifact Research
// What kind of artifact it gives a bonus to identifying
// Bonus % to identifying origin
// Bonus % to identifying trigger
// Bonus % to identifying effect/range
// Seconds reduced from analysis time
// THIS IS STATIC, I.E. NOTHING WILL BE ABLE TO REMOVE THIS SYSTEM FROM
// THE GAME, IT CAN ONLY BE MODIFIED
// THE REASON I SAY THIS IS BECAUSE WE CAN ADD A DATACORE OR SOMETHING THAT CAN BE BLOWN UP
// AND ALL THE MONEY WILL BE GONE
// Stations budget
// inactive until someone actually buys a ticket
// We'll start at 0 credits, and increase it in the lotteryday proc
// 500 minutes ~ 8.2 hours
// I wanted to make this a var on SOMETHING so that it can be changed during rounds
// 5 minutes = 3000 milliseconds
// this was way too fuckin high
// Skip AI
// If its not already in the list add it
// 0.0 is the default wage
// If its not already in the list add it
// 0.0 is the default wage
// Captain isn't in the occupation list
// This is gonna throw up some crazy errors if it isn't done right!
// cogwerks - raising all of the paychecks, oh god
// jobs["Atmospheric Technician"] = 400
// jobs["Vice Officer"] = 500
// jobs["Head of Security"] = 1
// jobs["Hangar Mechanic"]= 40
// jobs["Elite Security"] = 300
// jobs["Chemist"] = 50
// jobs["Attorney at Space-Law"] = 500
// This returns the time left in seconds
//Returns the time, in MM:SS format
// Everyone gets paid into their bank accounts
// some greedy prick suspended the payroll!
// we don't have any money so don't bother!
// Increase by 10000 regardless // cogwerks - changed this to be way higher
// Just so its not a mass of text
// Get the winning numbers
// If the round associated on the lottery ticked is this round
// Check the nubers
// We have a winner
// We're in the next round!
// 4 numbers between 1 and 3 gives a one in 81 chance of winning. It's 3^4 possible combinations.
// Lottery rounds
// If this ticket is a winner!
// Give a random set of numbers
// TODO: merge this with the new ability system.
//boutput(world, "cooldown initiated, length of [cooldown_time]")
//boutput(world, "cooldown over, refreshing UI")
// STARTER ABILITIES
// BASIC ABILITIES
// make sure they resurface on a blob tile or it'll look weird
//Wire: Duplicated from above because there's an input() in-between (Fixes runtime: Cannot execute null.visible message())
// CONSTRUCTION ABILITIES
//////////////
// UPGRADES //
//////////////
//boutput(owner, "<span style=\"color:red\">You need [bio_point_cost] bio-points to take this upgrade.</span>")
// var/obj/landmark/tutorial_start/L = locate() in tutorial_area
// GODDAMNIT LUMMOX
/*********************************
For the main html chat area
*********************************/
//Precaching a bunch of shit
//Cache of icons for the browser output
// Why is this defined this way you ask?
// It's because if you define an associative list mapping constants inside strings
// like "[LEVEL_MOD]" = FOOBAR_SHITFUCK_FUCKFACE
// The byond object tree output gets completely fucked in the ass and generates
// broken xml
//On client, created on login
//client ref
//Has the client loaded the browser output area?
//How many times has the client tried to load the output area?
//If they haven't loaded chat, this is where messages will go until they do
//Context menu flags for the admin powers
//Has the client sent a cookie for analysis
//Contains the connection history passed from chat cookie
//Check for existing chat
//Already setup
//Not setup
//For local-testing fallback
//To a max of 5 load attempts
//20 seconds
//Exceeded. Maybe do something extra here
//Client managed to logoff or otherwise get deleted
//Called on chat output done-loading by JS.
//For persistent user tracking
/* WIRE TODO: Fix this so the CDN dying doesn't break everyone
spawn(600) //60 seconds
if (!src.cookieSent) //Client has very likely futzed with their local html/js chat file
out(src.owner, "<div class='fatalError'>Chat file tampering detected. Closing connection.</div>")
del(src.owner)
*/
//Called in update_admins()
//Sends client connection details to the chat to handle and save
//Get dem deets
//Called by client, sent data to investigate (cookie history so far)
//lol fuck
//Passed malformed history object
//Uh oh this fucker has a history of playing on a banned account!!
//TODO: add a new evasion ban for the CURRENT client details, using the matched row details
//Irc message too
//Called in New() (/datum/admins)
//-1 is the lowest rank
// X + 2 because fuck byond. See definition of contextflags at the top of this file.
//Called by js client on admin command via context menu
//The mind no longer exists? What? How?!
//todo
//Called by js client every 60 seconds
//Called by js client on js error
//Global chat procs
//Converts an icon to base64. Operates by putting the icon in the iconCache savefile,
// exporting it as text, and then parsing the base64 from that.
// (This relies on byond automatically storing icons in savefiles as base64)
//Hash the darn dmi path and state
//See if key already exists in savefile
//It does! Ok, parse out the base64
//It doesn't exist! Create the icon
//Aliases for bicon
//Ok so I did my best but I accept that some calls to this will be for shit like sound and images
//It stands that we PROBABLY don't want to output those to the browser output so just handle them here
//Otherwise, we're good to throw it at the user
//Some macros remain in the string even after parsing and fuck up the eventual output
//Grab us a client if possible
//Client sucks at loading things, put their messages in a queue
//Aliases for boutput
//if (R.Find(message))
// Called when mode is selected
// Called when mode is deselected
// Called when entering buildmode
// Called when exiting buildmode
// For when you absolutely must handle all clicks yourself.
// Not recommended.
// Do not use in tandem with the other click procs.
// You shouldn't actually interact with these anymore.
// iterate edges
// west edge
// east edge
// south edge
// north edge
// SW
// SE
// NW
// NE
// Hello, goonstation coder reading this piece of code below.
// I'd like to ask you to stop judging me. Yes, I can hear the thoughts formulating in your brain right now.
// "what the fuck marquesas. why. why do you do this. why. why is this here. why."
// I suggest that instead of having those thoughts, go and find some way to make this code less shit.
// Here's one way to do that: help the efforts to move this shit off byond.
// I'm serious.
// Why are you still reading?
// GO.
// GO AWAY.
// CHANGE THE WORLD.
// DO SOMETHING.
// LEAVE ME ALONE.
// WOULDN'T IT BE NICE TO HAVE TRAITS???
//savename = input("Save file name", "Save file name", "save") as text
// fuck you you fucking useless piece of goddamn shit go away fuck you fuck shit bollocks
// fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck
// fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck
// fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck
// fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck
// fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck
// fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck
// fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck
// fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck
// fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck
// fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck
// fuck fuck fuck fuck fuck fuck fuck fuck duck fuck fuck fuck fuck fuck fuck fuck fuck fuck
// fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck
// fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck
// fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck
// fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck
// fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck
// fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck
// fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck
// fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck
// fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck fuck
// fuck you
// and fuck you too
// and ESPECIALLY YOU.
//Post-processing loop
// Prediction: someone will stumble upon this, facepalm, then link the stackoverflow answer with the regex html matching.
// [placeholder comment for where that will happen in the future]
// ------
// errrrorrrz
// nope
// no nullzone portals pls
// Log for versions:
// v1: Initial version
// v2: Turfs now save data comparable to /objs. Moved x.y.TURF to x.y.TURF.data. Now versioned.
// Backwards compatibility: v1 savefiles are missing the version key. Loader considers all files with missing version keys to be v1.
// Backwards compatibility: v1 saves are missing the "x.y.TURF.* keys. Loader accounts for this."
// Backwards compatibility: v1 saves define turf type in x.y.TURF, v2 saves define turf type in x.y.TURF.type. Loader is aware.
//savename = input("Save file name", "Save file name", "save") as text
// fuck you
// and fuck you too
// and ESPECIALLY YOU.
// instantiating for statics grghhgh.
// disregard the thing below this is the worst thing 2014
// fugliest hack shit 2014. someone will *eventually* decide to change one without mirroring it in the other and the game will break terribly
// fugliest hack shit 2014. someone will *eventually* decide to change one without mirroring it in the other and the game will break terribly
//hack
// hack hack hack
// HACK HACK HACK
// NOTE: only checking for exact types!
// backwards compatibility
// TODO: Unfuck this
// T & A hehE HEHE SNARF SNARF FUCKING LOL
// Might be shit. Remove if shit.
// var/changelog_path = "icons/changelog.txt"
//forum.ss13.co/viewtopic.php?f=5&t=6074
//forum.ss13.co/viewtopic.php?f=7&t=5865
//forum.ss13.co/viewtopic.php?f=7&t=5022\">http://forum.ss13.co/viewtopic.php?f=7&t=5022</a>
//forum.ss13.co/viewtopic.php?f=5&t=4128
//wiki.ss13.co/Pathology_Research
//wiki.ss13.co/Rules#Absolutely_no_sexual_content_.28Added_27.2F08.29 for more information.
//goonhub.com
//<img alt="Goon Station 13" src="[resource("images/changelog/postcardsmall.jpg")]" class="postcard" />
//wiki.ss13.co</strong><span></span></li>
//forum.ss13.co</strong></li>
//creativecommons.org/licenses/by-nc-sa/3.0/" name="license"><img alt="Creative Commons License" src="[resource("images/changelog/88x31.png")]" /></a><br/>
//creativecommons.org/licenses/by-nc-sa/3.0/">Creative Commons Attribution-Noncommercial-Share Alike 3.0 License</a>.<br>
/* Just chuck older entries from the changelog in here. Might as well archive them for now. -ISN
(t)thu nov 28 13
(u)HullCrushDepth
(*)All types of artifacts should now be able to be activated.
(*)Fixed the container type of artifact (the large one, not the handheld watering can).
(-)
(u)AngriestIBM
(*)In an effort to make people sorta care when expensive computer equipment is exploded, telesci now needs the mainframe to work
(*)The interface is about the same though okay!! No command line, I'm not some sort of turbo hitler, jeez.
(*)Some nerd could totally hack it with command line stuff if they wanted to, I guess.
(-)
(t)tue nov 26 13
(u)BurntCornMuffin
(*)Flamethrowers now have a nifty particle effect and sound to accompany the already awesome hellmixes you all have been making.
(*)Changeling heal rate restored to 1 per tick fire, 10 per tick all else. Being on fire still disables healing.
(*)Abominations only take 20% of damage from brute.
(-)
(t)sun nov 24 13
(u)Dr. Cogwerks
(*)Welding fuel tank ruptures are significantly more violent now
(*)Major explosions on the station level now have some screenshake and a few new sounds
(*)No need to yell "was that mining?!!!" now. Oh well.
(*)Raised the output amounts of a bunch of chem recipes.
(*)Blank papers now have a blank sprite, anything with text will show a sprite that looks like it has writing.
(*)Some departments have cool pens and markers now! #wow #whoa
(*)Congrats to the NERD CREW on finding the Solarium's first ending (the bad one)
(-)
(u)BurntCornMuffin
(*)New item: fuel tank. Contains 200 units of welding fuel by default.
(*)Now compatible with standard NT fuel dispensing tanks.
(*)Reworked flamethrowers:
(*)Plasma tanks are no longer part of the recipe.
(*)Instead, large air tanks and fuel tanks need to be attached to the flamethrower assembly.
(*)Try using different reagents in the flamethrower!
(*)UPDATE: Touch reactions now work properly with flamethrowers. This fixes a number of issues with chemicals that 'are fire' rather than 'catch fire'.
(*)Changeling heal rate increased by factor of 3, but is now disabled if the changeling is on fire.
(-)
(u)Wire
(*)Did literally nothing
(-)
(t)fri nov 22 13
(u)Dr. Cogwerks
(*)All pods start with a cargo hold installed now
(*)All minipods have a smaller cargo hold
(-)
(t)thu nov 21 13
(u)Dr. Cogwerks
(*)Reworked some ammo infrastructure code - guns now have calibers instead of hardcoded lists of ammo.
(*)Flare guns hold one bullet at a time now, but in exchange, they can take any 12ga shells
(*)12ga shotguns can now load flares too. Improvised weapons coming soon.
(*)The bartender now has a set of chemistry machines. HEH. (for how long? as long as it's fun)
(*)Food can now heal damage above 0 health (crit) instead of 60.
(*)Higher quality foods have a multiplier to their healing factor, up to 4x currently. More planned soon.
(*)Some adjustments to traitor gear prices, regarding this stuff Wire recorded: http://i.imgur.com/Bht8FTS.png
(*)EMPs, Disruptors, and Tasers (handheld or pod-based) can now disable pod electrical systems
(*)Disabled systems can be turned right back on through the ship tab's computer, so for now, this is mostly just annoying
(-)
(u)Infinite Monkeys
(*)Cloaking field generators come with remotes now and their settings can't be changed without the remote. Hopefully this will stop people from just strolling up and turning them off, and make them a bit more useful.
(-)
(t)sat nov 16 13
(u)Dr. Singh
(*)WASD mode now has two new keys! Press <b>Q</b> to drop and press <b>G</b> to set the focus to the input box to start entering a command without having to click in that narrow box or turn off WASD mode.
(*)The keyboard focus will stay there until you click the main screen again.
(-)
(t)sat nov 09 13
(u)Dr. Cogwerks
(*)Hitting a valve with a wrench will now turn the valve
(*)Engineering cyborgs will hopefully be a bit more worthwhile now
(-)
(t)wed nov 06 13
(u)Infinite Monkeys
(*)Smoke now causes a touch reaction on contact with things like it should.
(*)Touch reactions now transfer chemicals to the body properly if they are able to pass through skin. More protective gear will reduce the volume transferred.
(-)
(u)BurntCornMuffin
(*)Changeling Horror Scream no longer knocks you down. Instead, it slows you down, with a chance of causing you to drop held items.
(*)Changeling Horror Form move speed reduced slightly.
(*)Changeling Horror Form disarm has a greater chance of severing limbs.
(-)
(t)tue nov 05 13
(u)Dr. Cogwerks
(*)Moved Arrivals above the bar to encourage more traffic up there. Enjoy your crappy new crew dock.
(*)Raised a bunch of salaries, raised the shipping and research budgets, made lotteries happen more frequently
(*)Trader shuttles will arrive in Old Arrivals now. Due to shady business dealings and bribery, they get the nice dock.
(*)Security lobby now looks directly out into a main corridor. The EJECTION chute can be used to safely throw jerks out.
(-)
(t)mon nov 04 13
(u)Infinite Monkeys
(*)Miscreant objectives are now freeform and don't have set conditions. Did you succeed? Maybe!
(-)
(u)Dr. Cogwerks
(*)BELT HELL now has an outer ring that can deliver to and from Security, Catering (north bay between kitchen and botany) and MedSci (between Chem and Pharmacy.)
(*)The old inner ring catering dock is named "Cafeteria" and the old medsci dock is named "Airbridge" now.
(-)
(t)sun nov 03 13
(u)Infinite Monkeys
(*)Added miscreant objectives, which are like crew objectives but rude.
(*)Miscreants ARE NOT TRAITORS for the purposes of the rules, so no murdering etc. but feel free to hack doors, steal stuff and generally be a nuisance.
(-)
(u)AngriestIBM
(*)There's a folder in /mnt on the mainframe that will send files you stuff into it to your terminal. I'm sure some turbonerd will figure out a way to use this for illicit purposes.
(*)This was a turbonerd request, ok.
(-)
(t)sat nov 02 13
(u)Aphtonites
(*)The pool has finally been remodelled!
(-)
(u)Dr. Cogwerks
(*)Most masks that ought to disguise you now do, instead of only gas masks doing that
(*)Gave more access to security and detective IDs: medbay, research corridors, morgue, crematorium
(*)New janitor access areas: morgue, crematorium, medbay
(-)
(u)BurntCornMuffin
(*)Changeling Headspiders infect faster.
(*)Changeling Horror Form lost the Stun Resist and Speed Regenerate powers...
(*)...but are now immune to stun and constantly regenerate now.
(*)Speed Regenerate and Horror Form regeneration heal fire damage much more slowly than before.
(*)Staying in horror form uses up DNA at a much faster and steadier rate.
(*)Abominations may break through airlocks and glass similar to werewolves.
(*)Cyborgs able to be knocked around by abominations.
(*)Abomination disarmament is now a bit more...literal.
(-)
(t)thu oct 31 13
(u)Dr. Cogwerks
(*)Reversed the headset experiment for now.
(*)EXPERIMENT #2: Removed xray vision from the AI. All security cameras now function via line-of-sight.
(*)This will probably necessitate moving cameras around a bit over the next few days. Player feedback is requested on this.
(*)OPTIONAL CHALLENGE FOR COOL PEOPLE: http://mibpaste.com/I8Ccx2
(-)
(u)AngriestIBM
(*)Oh um here's some initial testing of a PDAsay verb. You can type pdasay (and mash space a bit for autocomplete) and end up quick messaging folks. You'll still need to scan for other PDAs first, though.
(-)
(t)tue oct 29 13
(u)Infinite Monkeys
(*)Completely redid dismemberment to be less weirdly coded and hopefully allow for more cool shit.
(*)Robot limbs on humans will be temporarily broken. Sorry!
(*)Please let me know of any other bugs.
(-)
(t)sun oct 27 13
(u)Dr. Cogwerks
(*)Removed the botany-specific nutrient tonics that nobody mixes ever
(*)Rolled their effects into Unstable Mutagen, Ammonia, Potash, Saltpetre, and Mutadone
(*)Space cleaner is now ammonia+ethanol+water to avoid a conflict with water in the botany trays
(*)This should also make botany supplies more useful for mischief and crime and hobo chemistry
(*)Gave the bartender a riot shotgun because WHY NOT
(-)
(t)wed oct 23 13
(u)AngriestIBM
(*)There is a Dynamic Sandwich System being tested out. Try cooking some bread slices and peanut butter or whatever in the oven for 6 on high.
(*)Hempuli sprited the sandwich gubbins. Gubbins is a valid word, ok.
(-)
(u)Dr. Singh aka Magic Mountain aka Not A Real Doctor aka B-Rob aka The White Flight
(*)Paint cans don't lag anymore. Neat! Thanks byond v500!
(*)Yes, I had to wait for IBM to code something and copy what he did to figure it out. What of it? Wanna fight about it?
(-)
(t)thu oct 17 13
(u)BurntCornMuffin
(*)Random Merchant Event now implemented! Merchants may periodically dock with the station and sell various items to the station.
(*)The merchant shuttles dock at the construction area north of the bar.
(-)
(t)tue oct 15 13
(u)Dr. Cogwerks
(*)A new system is being implemented to smooth out the lag caused by things being deleted
(*)Thanks to Spoogemonster and MagicMountain, explosions should be much more responsive
(*)HOWEVER: There will likely be some really odd behaviors from some stuff for awhile
(*)Deletion bugs will be swept up and ironed out over the next couple days.
(-)
(t)mon oct 14 13
(u)erotic dad
(*)Bowling balls and strangle holds no longer instantly black out your screen unless you go into critical.
(-)
(t)sun oct 13 13
(u)Dr. Cogwerks
(*)Adjusted a bunch of stuff that was kinda broken with QM shipping and market prices
(*)Messed with market values of stuff again
(*)Expanded the range of random values for the goods that a bunch of QM traders buy and sell
(*)QMs can now see inbound loading lane pileups from the ordering desk
(*)Splitting profits via barcodes should work with QM traders now
(*)Added a dialog box to buy up to ten items at a time from NPC traders
(*)Sketchy-D in the Diner sells more stuff now
(-)
(t)fri oct 11 13
(u)Dr. Cogwerks
(*)Moved the THUNDERDOME into VR so anyone can use it now
(*)Thunderdome is now rolled together with the basketball court for EXTREME BBALL
(*)Thunderdome gear has been swapped for stimpacks, spears, and advanced lasers
(*)This ought to encourage longer awful fights instead of 'welp, first ko wins'
(*)The little red televisions that are scattered around the station can now watch more stuff
(*)Added channels: Thunderdome fights, boxing ring fights, chapel services
(-)
(t)tue oct 08 13
(u)Dr. Cogwerks
(*)Updated the slot machines a couple days ago to be more fun
(*)Revised the bar layout and boxing rings slightly
(*)Dice in the jazz lounge if anyone wants to play Craps??
(*)In honor of all the slot machine winners, Thrifty B.O.B. now sells a new set of pod armor
(-)
(u)AngriestIBM
(*)If you put another food in with the ingredients of a cream pie (cream, sugar dough) it becomes a ~custom cream pie~.
(-)
(t)sat oct 06 13
(u)BurntCornMuffin
(*)Mediborgs now come with healthgoggles instead of thermals
(-)
(t)sat oct 05 13
(u)BurntCornMuffin
(*)Added a defibrillator to medbay. It can be used on patients with < 0 health or heart attack victims.
(*)NT advises you that exposing the defibrillator to electromagnetic fields will void your warranty.
(-)
(t)mon sep 30 13
(u)AngriestIBM with special guest Daeren!!
(*)Daeren made a bunch of new cocktails for the barman. Oh boy!!
(-)
(t)sun sep 29 13
(u)Aphtonites
(*)Added a new telescience area
(-)
(t)mon sep 09 13
(u)Dr. Cogwerks
(*)Fixed the missing home destination tag for the MULEbot
(*)Mulebots can now haul just about anything, hopefully this isn't a terrible idea
(*)Gave the nuke shuttle a box of syndicate donk pockets, hopefully this is a terrible idea
(-)
(t)sat sep 07 13
(u)Aphtonites
(*)Black holes have been resprited and now actually look somewhat threatening!
(-)
(t)thu sep 05 13
(u)Dr. Cogwerks
(*)Pod cargo autoloaders can now accept the following along with crates:
(*)Closets, canisters, air pumps, scrubbers, space heaters, large artifacts, ore accumulators, ore extractors, bots
(-)
(t)tue sep 03 13
(u)Dr. Singh
(*)By request you can disable the Tab keyboard shortcut with "Toggle Tab WASD" in the toggles panel. Will do a preferences thing for it when I finish some other related preferences related stuff.
(-)
(t)mon sep 02 13
(u)Dr. Singh
(*)<b>WASD MODE</b>, gosh! Press Tab to toggle. E is switch hands, C is use item, X is toggle throw, Z is end run. T to talk.
(*)As a reminder you can also ctrl+click to pull, alt+click to examine and middle click to switch hands.
(-)
(t)fri aug 30 13
(u)Dr. Cogwerks
(*)Nuke team headsets will usually not default to the main station frequency (145.9) anymore
(*)Headsets can no longer be overheard by people on an adjacent tile
(*)No more getting outed as a stealthy nuke op by some passerby hearing your headset chatter
(*)Unless you're on the same tile somehow!!
(-)
(t)mon aug 26 13
(u)Wonkmin
(*)A small update to the who command; it now tells players that even if admins aren't on, all messages go to IRC. There is now no excuse for people abusing mentorhelp because "no admins are on". Hooray!
(-)
(t)fri aug 23 13
(u)Dr. Cogwerks
(*)Uniform manufacturer starts with fabric in it now, has some more basic stuff
(*)Surgery table and surgery tools for the nuke shuttle
(*)Nuke agent PDA has access to the crew manifest now
(*)Updated the mining cyborg docks to take clothes now
(*)Medical belts can now hold custom patches, beakers, pill bottles, pills, and bottles
(*)Medkits and boxes can now hold pill bottles
(-)
(t)mon aug 19 13
(u)Infinite Monkeys / Wire
(*)You can now find a hilarious repository of security issued tickets at http://craftools.com/goonstationhub .
(*)Please do not abuse or spam this; we will be forced to ban players that cause issues with this neat thing kindly provided by non-admin staff. - Wonk
(-)
(t)sun aug 11 13
(u)Infinite Monkeys
(*)Gang mode now gives points for guns, drugs and cash in your base. Also fixed the weird bug where you got points for 300 or so areas.
(*)Gang members now count as normal crew members except that they can kill other gang members and in self defence. Gang members killing for fun will be banned!
(-)
(t)sat aug 10 13
(u)AngriestIBM
(*)Locks for pods. Stick a lock on a pod. Lock all of the pods.
(-)
(t)thu aug 08 13
(u)Infinite Monkeys
(*)You can now save recipes to the chem dispenser and dispense all reagents in the recipe with one click.
(-)
(u)Dr. Cogwerks
(*)Return of the revenge of the son of the boss of the medbay
(*)Added a bunch of sketchy new rooms scattered around the station in the past couple days
(*)Miners have a chance of spawning a bit shorter than usual
(-)
(t)tue aug 06 13
(u)Aphtonites
(*)The following objects now have new icons:
(*)Gaming Kits
(*)Pod Doors
(*)Linen Bins
(*)Paper Bins
(-)
(u)I Said No
(*)Research Budget now starts the round with 15k in it.
(-)
(t)mon aug 05 13
(u)Infinite Monkeys
(*)Added one man escape pods to the station.
(-)
(t)sun aug 04 13
(u)Aphtonites
(*)The grilles, atmospherics volume pumps, solar panels and beds now have new icons!
(-)
(t)sat aug 03 13
(u)I Said No
(*)Re-added Injectors to Genetics. They cost 40 materials to build and have to be researched first.
(*)Added some other unlockable research things to genetics.
(-)
(t)fri aug 02 13
(u)Infinite Monkeys
(*)Fiddled with flash and sonic powder (and so flashbangs) to make them less of a pain in the ass. Might adjust them more.
(-)
(t)thu aug 01 13
(u)Aphtonites
(*)The vending machines near the Warehouse now have new icons, whoa!
(*)Rack parts now have a nice new icon! The old one was at least six years old.
(-)
(u)I Said No
(*)Added a CodeBreaker cart to the CartyParty vendor. It's the genetics decryption game, ported to your PDA!
(*)DNA Scramblers are back for traitors and syndicate operatives.
(-)
(t)thu jul 31 13
(u)Aphtonites
(*)The mining shuttle has been given the same makeover as the escape and arrival shuttles.
(-)
(t)sun jul 28 13
(u)Dr. Singh
(*)Due to complaints of unexpected behavior the click buffer has been disabled. If you liked it you can re-enable it for yourself in your preferences.
(-)
(u)I Said No
(*)The decryption game in genetics now gives full mastermind-style feedback rather than partial. It will now tell you the amount of correct characters in the wrong position as well as correct characters in the correct position.
(-)
(t)sat jul 27 13
(u)I Said No
(*)Certain kinds of genes will now have Encrypted base pairs. These must be decrypted by clicking the lock and solving the code before they can be activated. It's basically a game of Mastermind.
(*)Rearranged the genetics console UI a bit. It will now show cooldowns on any unlocked equipment, as well as the scanner occupant and current research materials at all times.
(*)Research can now be tracked on the UI. Go to the research in progress screen, hit track, and an icon will appear showing you when the research will finish. It disappears when the research completes.
(*)The DNA Reclaimer can now reclaim materials up to x1.5 times the material cap.
(*)The Stability Checker now shows you which base pairs are correct or incorrect.
(*)Equipment cooldowns lowered across the board.
(*)Cleaned up the Appearance Changer menu.
(-)
(t)thu jul 25 13
(u)Aphtonites
(*)The fitness room has been expanded and now contains more stuff!
(*)Added a Clown bop bag to the fitness room.
(*)Added a couple of weight machines to the fitness room.
(*)Added a couple of punching bags to the fitness room.
(-)
(t)wed jul 24 13
(u)Aphtonites
(*)There are now some comfy office chairs in Medbay and the Research department!
(*)The sign that used to be in front of the bar on Mushroom Station is back!
(-)
(t)tue jul 23 13
(u)Dr. Singh feat Mybluecorners
(*)A click buffer. Clicking during the click delay will now set your next action instead of ignoring it! #wow #whoa
(-)
(t)sun jul 21 13
(u)I Said No
(*)Couple of new appearance options in Facial Hair, Detail, and Underwear slots.
(-)
(t)thu jul 18 13
(u)Infinite Monkeys
(*)Added a program to head and security PDAs allowing them to issue tickets and fines.
(*)Only the Captain, Head of Security and Head of Personnel can approve fines - others with access to Ticket Master can create fine requests which must be approved.
(-)
(t)tue jul 16 13
(u)LLJK-Mosheninkov
(*)Added emergency lighting to the main hallway loop and a few designated emergency gathering areas. These lights will kick on automatically when the power goes out,
(-)
(t)fri jul 12 13
(u)Dr. Cogwerks
(*)Updated the pharmacopia books with basic recipes and hints
(*)The cloner requires an upgrade to scan rotted people! Whoa!
(*)But not unrotted dead people. I guess you can scan them.
(*)Airlocks now use the same electrocution code as grilles and cables.
(*)I'll let you think about the implications of that.
(*)Chemistry has been slightly rearranged and has a starting supply of some widely used things.
(*)The reagent locker can be resupplied with a crate of the same bottles from QM.
(-)
(t)wed jul 10 13
(u)LLJK-Mosheninkov
(*)Added footballs so you can toss the ol' pigskin around with a bud. Find 'em in crew quarters or around.
(-)
(u)Dr. Singh
(*)Found some causes of lag. A couple of spots have been fixed but there's a long way to go.
(*)Lots of code changes soon, things may act strangely or break. If you notice anything bad start to happen please report it to an admin or the bug reports forum.
(*)Don't panic.
(-)
(t)tue jul 09 13
(u)LLJK-Mosheninkov
(*)Items thrown by a player can now be caught by another! To catch items, you must have the "Help" intent selected and click the same button used to activate throwing mode.
(-)
(t)thu jul 06 13
(u)Aphtonites
(*)The shuttles now actually look like shuttles! WOAH!
(-)
(u)I Said No
(*)If the engine is not set up by the ten minute mark, an automatic warning will now be posted to the crew to encourage them to do so.
(-)
(t)thu jul 04 13
(u)Infinite Monkeys
(*)Added leg dismemberment.
(-)
(u)I Said No
(*)The AI now has an internal battery, and will attempt to re-establish local power whenever it is moved instead of just blacking out for a minute. If it can't get local power, it will just run off battery until it can.
(*)You can now debrain the AI. Doing so will yield a unique AI brain (neural net processor). To do this, unlock it with a head-level access card, crowbar it open, undo the bolts with a wrench, then take the brain out with a free hand. You can also rebrain the AI if you feel like it.
(*)The AI now visibly shows damage.
(*)Damage to the AI can be repaired. Brute damage with a welder, burn damage by opening the cover and using wires.
(*)The traitor objective "Destroy or shut down the AI" has been replaced with "Steal the AI's neural net processor".
(-)
(t)wed jul 03 13
(u)Dr. Cogwerks / AngriestIBM
(*)All PDAs now have a panic alarm function
(*)Look in your file browser.
(*)Added a new trader NPC in space
(-)
(t)mon jul 01 13
(u)Dr. Cogwerks
(*)Most of the job-specific mailchutes will now send a PDA alert when they receive a delivery
(*)The morgue outlet will ping the geneticists, roboticists and security
(*)The crematorium outlet will ping the chaplain and security
(*)Added books with descriptions of most medicines to medbay and research
(*)Buffed the hell out of the derringer and readjusted some other projectiles
(-)
(t)sun jun 30 13
(u)Dr. Cogwerks
(*)Consolidated three of the space zlevels into two
(-)
(u)I Said No
(*)The AI now has a cool new look, and an internal PDA and three internal radios to go with it. The AI can access them through new commands.
(*)You can use a screwdriver on the AI to unbolt it from the floor and bring it with you. If you're into that kind of thing. Freak.
(-)
(t)sat jun 29 13
(u)Dr. Cogwerks
(*)---- MAJOR HEALTH SYSTEM UPDATE: PART 1 ----
(*)THIS IS A WORK IN PROGRESS. REPORT BUGS!!!!!
(*)Critical health doesn't paralyze until -100
(*)You can walk around in crit up to that point
(*)Your health will rapidly deteriorate.
(*)MEDICS: use your health analyzers!
(*)Death is now a probability based on damage
(*)Brain damage severely increases that chance
(*)--------------------------------------------
(*)Other updates:
(*)Replaced the energy guns in the armory with stun-round shotguns. kablammmmm
(*)Made the flashes of vision while in crit or KO happen much more often.
(*)Rearranged the bar.
(*)Gave Botany a pill machine and gave Chemistry another chem dispenser.
(*)Moved the barber shop slightly so it faces a major corridor.
(-)
(u)I Said No
(*)The genetics scanner can be locked again. Stand next to it, right click it and use Scanner Lock.
(*)New researches for genetics:
(*)Emitter Coolant and Emitter Dampeners: Reduce the recharge time and irradiation amount of the radiation emitters, respectively.
(*)Gene Sequence Checker: Tells you how many blocks in a gene's sequence are set correctly.
(*)DNA Reclaimer: Removes genes from a subject and turns them into research materials.
(*)Precision Radiation Emitters: Reroll a single gene in the pool rather than the entire pool.
(-)
(t)thu jun 27 13
(u)Infinite Monkeys
(*)Hopefully made inertia a bit less weird. Let me know if there are any problems with it.
(-)
(u)Dr. Cogwerks
(*)Gave Genetics a second scanner, moved one door down to the cryo area
(*)Swapped the back door of genetics to a glass airlock
(*)Anyone with maint access can now go hang out in the creepy little doorway below the morgue to sign up for genetics testing
(*)Continuing to fine-tune, tweak, and/or fix chemistry/med stuff
(*)Raised the job limits for scientists, medics, and security guards
(*)Significantly improved the usefulness of riot armor hopefully
(*)Changed lasers to use energy/burn damage now instead of piercing/brute - lasers will now take armor into account
(*)Standard bullets are weakest against armor, lasers are in between, piercing bullets are best
(*)Made single bullets no longer bleed you to death, just close to it. Lowered bleed duration quite a bit.
(*)Adjusted the changeling sting somewhat.
(-)
(t)wed jun 26 13
(u)Dr. Cogwerks
(*)---- MAJOR CHEMISTRY UPDATE -----
(*)Changed the star trek drugs to things that are a bit more intuitive to figure out from their names
(*)Taking some liberties with real-world analogues, so please don't go writing any page-long diatribes about how reagent X doesn't behave that way
(*)Things with no real-world analogues will probably involve plasma or mutagen somehow because fuckin' magic whatever
(*)Upgraded the medbay vending machines to have more medications in them
(*)The pharmacy room has a pillmaker and extractor now
(*)Added a whole bunch of new medicines and poisons and rolled some redundant ones together
(*)Chem dispensers have several new elements
(*)A lot of organic chemistry reactions will use common building blocks
(*)Diethylamine, acetone, ammonia, phenol, ethanol, sugar and weldfuel (used as a stand-in for benzene, toulene, ethene, etc.) are good things to stockpile for experiments
(*)Expect some tweaking and bugfixes over the next couple days
(-)
(t)tue jun 25 13
(u)I Said No
(*)Geneticists can now get a DNA sample from people using their PDA. Just whack someone with your PDA while the genetics scan is active and messaging is on and it'll send a researchable sample to any DNA scanners. Access the samples from the research menu.
(-)
(t)thu jun 20 13
(u)AngriestIBM
(*)Attention, <s>Elect</s> Mechanics: hit a thing with your PDA. A thing you want to analyze. Yep.
(*)oh and I guess gptio takes names like gas_bottom instead of just numerical IDs. You know, if you want to use those instead.
(-)
(u)I Said No
(*)Genetics UI: You can now click on the little green lines between base pair letters to change their color. Useful as a marker for blocks you're trying to figure out.
(-)
(t)wed jun 19 13
(u)Dr. Cogwerks
(*)Adjusted the traitor counts downwards slightly
(*)Changed some of the traitor item counts around a bit
(*)Split some of the QM crates into more specific things
(*)Food Supplies are now split across Dry Goods, Produce, Meat/Cheese/Dairy, and Condiments
(*)Medical supplies are now split into a crate full of First Aid kits and a crate full of chemicals/hyposprays
(*)Hydroponic supplies are now split into a starter crate full of basic gear and a nutrient crate full of formulas
(*)Removed most of the annoyingly job-specific items from the surplus crate
(*)Removed most of the rampage items from surplus crates too! HAHAHAH
(*)Added a bunch of strange things to the surplus crate pool to make up for that.
(-)
(t)sun jun 16 13
(u)I Said No
(*)Hear Admin Sound option was inverted to Block Admin Sounds due to some annoying glitches. Update your preferences accordingly.
(*)Fiddled with the genetics computer UI a bit.
(-)
(t)sat jun 15 13
(u)Dr. Cogwerks
(*)Cigs can now be lit by hitting them with actively burning items (including money)
(*)You can put cigs out on people now if you want to be a real jerk
(*)Holding a burning item, welder, zippo or ignitor and clicking on something flammable will now set the target on fire.
(*)This means you can set your own jumpsuit on fire with a zippo while wearing it. Welp.
(*)Added a couple of existing poisons to the traitor poison bottle possibilities and added two new poison reagents.
(*)Redesigned the Telesci lab so it now has a public-access door. There are two toggles in the control room for the blast shields.
(-)
(u)AngriestIBM featuring special guest Pistoleer!!
(*)Syringe gun is now loaded just by pouring crap into it. Every 15 units lets you fire a syringe. Up to 6 syringefuls at a time.
(*)The syndicate stealth storage no longer prints a big DOOFUS LOADS X message (Though it still rustles) and can be reset after assuming a form, so you can turn it into another thing. (Why wasn't that the original behavior??)
(-)
(t)fri jun 14 13
(u)LLJK-Mosheninkov
(*)Fixed some bugs with George (rub that belly) and now he's quite talkative especially if you play music for him!!
(-)
(t)wed jun 12 13
(u)LLJK-Mosheninkov
(*)Added pushing others into space or fires to the combat log because turds figured that was a sweet way to get around logs when we investigate adminhelps.
(-)
(u)Dr. Cogwerks
(*)Changed the layout of the morgue and crematorium a bit
(*)Roboticists, doctors, detective and geneticists all have their own doors to the morgue
(*)There are now corpse delivery chutes in the medbay lobby and in disposals
(*)Reminder: there is also a chute between the morgue and the crematorium, and the chaplain can now see if he gets deliveries from his office
(*)I expect some mischief with this system.
(-)
(t)mon jun 10 13
(u)I Said No
(*)Re-added the ability to toggle whether you want to hear music played by admins. Note that high-level admins can choose to override this.
(*)Also added a toggle to block the score panel from appearing at the end of the round.
(*)Added three new mutations for geneticists to discover.
(*)Added ID card coloration depending on what department the job is in.
(*)Gave more control over what underwear you want your character to wear.
(*)Changelings can no longer mimic voice while dead.
(*)Trying to use the leap mutation while inside something will now have rather unpleasant consequences for the jumper.
(*)Changed "X slurs something completely unintelligable" to still actually speak rather than just showing a local emote. Don't expect to be able to say anything coherent though.
(*)Same deal as above only with advanced cases of Berserker.
(-)
(t)sun jun 09 13
(u)Rick
(*)Added 23 medals.
(-)
(t)sat jun 08 13
(u)Rick
(*)Added 17 medals.
(-)
(t)mon jun 03 13
(u)Infinite Monkeys
(*)Dismemberment of arms is in. It can be caused by bombs, extreme brute damage and surgery. Be sure to cauterise the stump before you bleed to death!
(*)Arms can be reattached using the medical stapler or replaced with robot arms.
(*)Any surgery requiring an operation table can also be performed on an ordinary table if the subject is unconscious or dead.
(*)Rathen's Secret has a small chance of tearing off people's arms. Why not?
(*)Replace people's arms with other people's arms! Whoa!
(-)
(t)sun jun 02 13
(u)I Said No
(*)Rolled Antagonist Choices into the job choices panel. Also allowed specific choosing of Traitor, Vampire, Spy and Gang Leader.
(*)Added a new appearance customisation slot - Detail.
(*)An option for whether or not you want to automatically view the changelog when you log in.
(-)
(t)sat jun 01 13
(u)I Said No
(*)Job Preferences have been changed. You now order jobs into priority brackets rather than just pick three roles you want.
(*)The late join screen has been changed up a bit too, at least visually.
(*)<b>YOU NEED TO RE-SET UP YOUR JOB PREFERENCES FOR EACH CHARACTER YOU HAVE! GO INTO THE WINDOW AND HIT RESET! THEN SAVE IT!!!</b>
(-)
(t)mon may 27 13
(u)Infinite Monkeys
(*)Due to Nanotrasen cuts, many reinforced windows in low security areas of the station have been replaced with normal ones. If any window sections look weird, let a coder know!
(-)
(t)thu may 23 13
(u)AngriestIBM
(*)The delete key is now toggle throw!
(-)
(t)tue may 21 13
(u)Keelin
(*)Genetics is gone for the moment while the code behind it is being redone.
(-)
(t)mon may 20 13
(u)AngriestIBM
(*)Multiple save files!!!
(*)Some more verbs on closets, like toggling them. Or climbing inside I guess. Blame MyBlueCorners again.
(-)
(t)fri may 17 13
(u)AngriestIBM with special guest Mybluecorners!!
(*)Mybluecorners thought of a cool new way for the table parts menu to not be shit!!
(*)dooty spod
(-)
(u)Dr. Cogwerks
(*)Main hangar is set for mechanic access now
(*)Bullets cause bleeding damage for much, much longer duration now
(*)REMINDER: put someone onto a surgery table and use scalpel on their chest to remove bullets
(-)
(t)tue may 14 13
(u)AngriestIBM
(*)You can bonk the syndicate card with other IDs to copy over their access. Collect all of the accesses, be the card game champ fifth-grade you wanted to be!
(-)
(t)mon may 13 13
(u)AngriestIBM
(*)*customv and *customh emotes to quickly custom emote visible or hearable things. say "*customv does something that you are seeing now."
(*)Also emote parameters use a space instead of - to add a parameter.
(*)And emotes aren't case sensitive anymore, what the fuck.
(-)
(t)sun may 12 13
(u)Dr. Cogwerks
(*)oh i guess we never put this in the changelog
(*)sunglasses no longer reveal other traitors
(*)pro strategy for identifying other traitors: ask them
(-)
(u)Keelin
(*)Cyborg docking stations now support drag and drop for items. That way cyborgs can put clothes (and upgrades) in there without help.
(-)
(u)AngriestIBM
(*)I guess you can just examine your headset to see the other channels? I guess???
(*)Happy Mothers Day
(-)
(u)I Said No
(*)The buy and sell lists of generic traders, Gragg, Pianzi Hundan and Vurdalak have been expanded.
(*)Made mining overalls fit the black/yellow color scheme miners have going on.
(*)Electrician is now known as Mechanic. Nothing about the job has actually changed though.
(*)New trader: Buford Tenin. He buys drugs and sells stuff that helps Hydroponics out. He is also a frog man. #wow #whoa
(-)
(t)sat may 11 13
(u)I Said No
(*)Traders tied in with Quartermasters/Shipping Market have been drastically overhauled. There are now multiple traders who can be dealt with at once rather than one, and they both buy and sell using a system similar to the NPC traders. More content to come on that front.
(-)
(t)wed may 08 13
(u)Keelin
(*)Pod Bay door controls can now be clicked while inside a pod to open or close the connected doors.
(*)Cyborg docking stations now accept some types of clothes. Borgs can wear these by equipping them inside the stations.
(-)
(t)tue may 07 13
(u)Dr. Cogwerks
(*)Added a Gas Extractor unit in the engine's cold loop.
(*)Raised the values of most of the ores again.
(-)
(t)mon may 06 13
(u)AngriestIBM
(*)I guess the heads have some more headset channels? Just activate the headsets in hand to see what channels you have and what letter you need to put after the colon to use.
(*):h is command frequency for all of them, though.
(*)This is still a work in progress, okay.
(-)
(u)Dr. Singh
(*)Removed mining ores from colored light recipes to promote fun.
(-)
(u)Dr. Cogwerks
(*)Gave security a new lobby
(*)Work in progress: scan your ID card into a barcode printer.
(*)Print a barcode and slap it on a crate, send to QM.
(*)When that crate is sold, it should split the profits evenly between the shipping budget and the crate owner.
(*)NOTE: does not work for trader crates yet, still working on that as well as the interface.
(-)
(t)sun may 05 13
(u)Dr. Cogwerks
(*)No more solitary permabrig prison cell
(*)Replaced it with a regular guard-access timer/flusher cell
(*)Put some crate/ore relay launchers in Mining level
(-)
(t)thu may 02 13
(u)Dr. Cogwerks
(*)Due to protests from the Postal Workers Union, mail chutes return.
(*)I expect significant mischief and workplace accidents from these.
(*)Put some MiniPutt shuttles on the map, expanded the primary podbay.
(*)Made the end of nuke mode more exciting
(-)
(t)sun apr 28 13
(u)I Said No
(*)Cyalume Sabers and Toy Swords now come in five different colors. Collect them all! (without being killed by security five times)
(-)
(u)AngriestIBM
(*)Hey I guess wizwrite can print to networked printers now? I mean it's still a little rough around the edges but it works.
(*)Oh and this is unrelated but there is a secret way to make your emag a ~*~gold emag~*~. Besides paint, I mean. Stop bringing up the paint there is a way besides paint.
(-)
(t)sat apr 27 13
(u)Dr. Singh feat. Mozi
(*)Cash is now stackable. Go ahead, stack some.
(*)Use an empty hand on cash you're holding to take some out.
(*)Crew members now start with their first paycheck in their pocket.
(-)
(t)wed apr 24 13
(u)Dr. Cogwerks
(*)Made pipebombs and RPGs do a little less hull damage in exchange for very mean shrapnel
(*)Syndicate pipebombs, area cloak and donk pockets are cheaper
(*)Beepsky will report arrests over PDA
(*)General manufacturer, toolboxes and some other supplies for mining
(*)Gave toxlab a heat exchange coil under the two primary combustion chambers
(*)Due to budget cuts, roundstart/nanite cyborgs are now terrible
(-)
(t)tue apr 23 13
(u)Wonkmin
(*)You could say there's a rather plsing new hat and set of clothes. Dolan't forget about this - I may put them on the station at one point! Pls.
(-)
(t)sun apr 21 13
(u)I Said No
(*)New Light cyborg pieces are available from Robotics Manufacturers. They can take less damage but are cheaper to make.
(-)
(t)fri apr 19 13
(u)Dr. Cogwerks
(*)Made cyborgs significantly more vulnerable to projectile damage
(*)Transfer-valve sized bombs seem like kinda big bulky things, right? Well, now they officially are.
(*)Added a little news desk / office at arrivals. If people actually use it, it might get more stuff.
(-)
(t)tue apr 15 13
(u)Dr. Singh
(*)I spent the station's entire tax return on colored light bulb schematics for the general manufacturer.
(*)Fixed that thing where you get set on fire but it doesn't draw right so you burn half to death before you realize it.
(-)
(t)mon apr 14 13
(u)I Said No
(*)There is now a delay between harvests of a plant. I know it sucks, but it was neccessary to avoid lag. Sorry folks!
(*)Max harvest amount in one go is now capped at 10. It was 30 before, but the text didn't reflect the actual harvest amount.
(-)
(t)sun apr 14 13
(u)Dr. Cogwerks
(*)Adjusted most of the projectiles in the game to actually properly use power dissipation rates over distance
(*)New drillbit for mining pods
(-)
(t)sat apr 13 13
(u)Dr. Cogwerks
(*)Moved most of the Z3 stuff around to make room for a new wreckage field area
(*)Explore at your own risk, salvage exploration is both lucrative and dangerous
(*)All pods now start with a sensor system and a verb in the ship tab for it
(*)The better Conclave sensor now functions both as mesons and as a geological report scanner
(-)
(t)thu apr 11 13
(u)Dr. Cogwerks
(*)Several new manufacturable pod items
(*)Try the Conclave sensor system, seriously. I rewrote it to provide a list of some stuff around you when you run a scan.
(*)More manufacturing units for QM office, maybe bored QMs could become used car salesmen or something
(*)Several new NPC traders out in deep space
(*)Clickdragging a crate of items onto an NPC trader now works for bulk sales
(*)Horribly mean things are lurking around in deep space now
(*)Redesigned the QM office a bunch
(*)PDA alerts from sold crates, request console orders and request console payments
(*)Maybe people should use those things more often????
(*)Engineering headsets for QMs
(*)I guess mining can have an armored pod until the industrial pod is ready
(-)
(t)wed apr 10 13
(u)Dr. Cogwerks
(*)Smokepowder reactions now consume the source reagents, deal with it
(-)
(t)tue apr 09 13
(u)Dr. Cogwerks
(*)Got rid of some redundant crates from QM
(*)Added request consoles to all the router docks
(*)Request consols now tell the QMs where you placed the order from
(*)Improved medical, hydro, and chef supply crates hopefully
(-)
(u)Infinite Monkeys
(*)Added a PIN preference so you can set your PIN to 69 and 420 related things or whatever.
(-)
(t)mon apr 08 13
(u)Dr. Cogwerks
(*)Pods can remotely open any hangar doors that have a remote control panel near them
(*)Examine the panel to get the access code
(*)A bunch of things now sell for a lot more money
(-)
(t)sun apr 07 13
(u)Dr. Cogwerks
(*)Adjusted the base sell prices of ore and sheets
(*)Dear QM scammers: say goodbye to your dumb metal selling cheats
(*)Raised all paychecks by 500-1000%, they seemed too low for people to ever buy anything worthwhile
(*)Backup generator price dropped by half
(*)The shipping budget now skims 30% profit off of all vending machine sales on station, whoa
(*)QMs get a free cargo pod for deliveries or whatever
(*)Martian NPC trader should work properly now, buys some junk and sells rare ores
(*)Mining starts with a free plasma cutter pod system now, have fun arguing over it
(*)Chameleon projector can now scan critters, bots and shrubs - shrubs are a bit wonky still, fyi
(-)
(u)Dr. Singh
(*)Drag and drop crate loading for pods. Like furnaces! Whoa!
(*)The furnace autoloader now expects you to be alive and standing next to the furnace. Sorry ghosts, you can't help set up the engine anymore.
(-)
(t)thu apr 04 13
(u)Dr. Cogwerks
(*)Most podbays now have door controls outside
(*)Three new traitor weapons, two for everyone and one for the RD
(*)Removed the ammo boxes from the traitor buylist, made revolver cheaper and start with more ammo
(*)Nuke shuttle additions: security camera viewer, utility belts, hypospray and basic drugs
(*)All nuke agents now start with their own ten-crystal radios
(*)Crowded nuke rounds can now have six instead of five agents
(*)Fancy command space armor for the boss
(-)
(u)Keelin
(*)Power Gloves now actually on the syndicate buy-list for Engineers and Chief Engineers.
(-)
(t)wed apr 03 13
(u)Dr. Cogwerks
(*)Easter is over, or is it ?????
(*)Riot storage now starts with a laser array pod weapon in it
(*)Syndicate teams now have their own pod and a gun system
(*)Reminder: to install pod parts, use a crowbar on the pod to open the maint hatch
(*)Click the pod with the item you want to add, crowbar shut, enter pod and use the ship computer to activate the new system
(*)Nuke agents: enjoy your new rocket launcher, HEH
(-)
(t)mon apr 01 13
(u)Infinite Monkeys
(*)In an effort to improve roleplaying, added manual breathing and blinking. Emote *inhale and *exhale to breathe, and *closeeyes and *openeyes to blink.
(-)
(u)AngriestIBM
(*)Unfortunately, your RP was just so ABYSMALLY POOR that we have been forced to revert this change. Great job, SCRUBS!!
(-)
(t)sun mar 31 13
(u)Dr. Cogwerks
(*)EASTER EGG HUNT
(-)
(u)AngriestIBM
(*)Chaplain has immunity to wizard spells again.
(-)
(u)ISaidNo
(*)Cyborgs created at the beginning of the round may now choose their name, like the AI can.
(-)
(t)wed mar 27 13
(u)AngriestIBM
(*)Oh I guess those gas sensors in toxins show up on the GPTIO list now. Give them a sense and then a read command to check them
(*)You could probably even make it one line like "gptio sense 0200whatever ^ gptio read 0200whatever"
(-)
(t)tue mar 26 13
(u)Infinite Monkeys
(*)Even more chemicals. Clues for all the new ones:
(*)The components of life plus something special.
(*)Based on chloral hydrate, affects brain function.
(*)The above plus two stimulants.
(*)Medicine cocktail.
(*)The above plus even more medicine.
(*)Fortified wine.
(*)Recipe for hairgrownium.
(*)Hairgrownium but stronger and faster.
(-)
(u)AngriestIBM
(*)Apparently some traders had names that were too long to tag a crate with! So, now you just need to label the crates with "trader" to trade them. It's not like there can be multiple simultaneous traders, anyway.
(-)
(t)mon mar 25 13
(u)Infinite Monkeys
(*)Chemical reactions can now take place inside mobs. What could go wrong?
(-)
(t)sun mar 24 13
(u)Infinite Monkeys
(*)New chemicals.
(*)Two new traitor items: A modified cargo teleporter that transports containers to space and welds them shut, and a crate filled with whatever the Syndicate suppliers had lying around.
(-)
(t)sat mar 23 13
(u)Infinite Monkeys
(*)Chaplains are no longer immune to spells.
(-)
(t)thu mar 21 13
(u)I Said No
(*)New hairstyles and facial hair styles! Check em out!
(*)Some previous hairstyles were renamed. For example, long hair is now "mullet" and short hair is now "trimmed."
(-)
(t)sat mar 16 13
(u)Infinite Monkeys
(*)Mixed mode should respect your 'Be Changeling/Wizard/etc' choices now, previously it just checked Be Syndicate and used that to assign all roles.
(*)'Be Gang Leader' changed to 'Be Other Enemy'. Controls rare enemy types like Vampires and Gang Leaders.
(*)Having Head of Security somewhere in your preferences shouldn't override all other choices now.
(-)
(t)tue mar 12 13
(u)Dr. Cogwerks
(*)Significantly buffed the radbow, it should be a lot more sneaky now. No more twang sound or green bolt, faster recharge. Maybe too fast? idk
(*)Removed the word Syndicate from the syndicate pipe bomb. what did it have a giant flashing red logo or something? dumb.
(*)Thanks to a group of players making it their goal to hand out stacks full of instakill murdersoup extinguishers every round, soup now clogs extinguishers
(*)Way to go, idiots! Spray bottle capacity has also been lowered from 1000 to 100 and hot cooking oil now does less damage.
(*)Big piles of weed can now be dragloaded into the engine furnaces.
(-)
(t)mon mar 11 13
(u)Dr. Cogwerks
(*)Added a new traitor item for bartenders and doctors. What is it? I guess you'll have to find out.
(-)
(t)fri mar 08 13
(u)Dr. Cogwerks
(*)Rewrote the engineering startup guide in-game because the old one was hilariously inaccurate for this engine
(*)Color-coded the supply hookups a bit to help newbie engineers get an idea of what is going on
(*)Engine code tweaks are ongoing.
(-)
(t)wed mar 06 13
(u)Infinite Monkeys
(*)Added the ability to make a two-way portal in telescience, uses a huge amount of power so yell at the engineers I guess.
(-)
(u)Prociitzen
(*)MOPDATE: examine mops to see if they're wet, examine mop buckets to see what reagents are in them, wet mops in kitchen sinks (wtf), look at mops with your friends and have a good time!
(*)Earmuffs will save you from the changeling screech or something.
(*)Reagents will no longer splash on racks, so put all your beakers on them. Go ahead! I dare you!!
(*)People shouldn't scream while they're dead but I didn't test this and I don't care oh my god I don't care oh my godddd
(-)
(u)Infinite Monkeys
(*)Why was the 'soundscape' even a thing? RIP constant annoying background hum I guess.
(*)Fiddled with mentor messages a bit, let me know if I broke anything.
(*)Added an engine-related suicide!
(-)
(t)tue mar 05 13
(u)Dr. Cogwerks
(*)With the lower pressure reservoirs removed it was trivially easy to hit the max effects tier for Pro Burnz engineering (800kW+)
(*)Engine output tiers have been rebalanced with a sweet spot around one megawatt, tiered effects cap raised to 2MW - more planned up here soon
(*)This will make lower output a bit less satisfying maybe but try experimenting with plasma and pump settings
(*)In some configurations you will want slow feeds of certain gases and maybe a rapid OR slow steady release of excessive pressure from the purge line
(-)
(t)mon mar 04 13
(u)Dr. Cogwerks
(*)GRAFT UPDATE: added cash registers to a lot more places, including HoP desk and the brig if you wanna charge bail or something
(*)Charging for services is entirely up to you, it may cause you to get beat up but it might be fun too idk
(*)Ongoing content expansion for the expedition areas, rewards and lore and hazards will keep growing out there
(*)Modified the SMES and APCs out in the expedition areas and prison station so they'll behave better with furnaces hopefully
(*)Check out the new Helmet Cam in Telescience! You can view it from the telesci cam viewer or the televisions in RD, Crew Quarters and Bar.
(*)Gave the detective a standard portable camera viewer like the HoS has, maybe it'll be useful for spying on jerks or something
(*)Removed the lower set of engine pressure reservoir tanks for now to see what happens. Expect the engine to behave more erratically, oh boy
(*)It should be less likely to get those awful pressure inversion problems, and it'll be easier to purge the gas lines when needed
(*)Restricted the pod hangar to engine/miner access only because too many people were being mean, deal with it
(*)Added more air pumps and heaters around the station, more cable coils and diskette boxes, etc. etc.
(*)More updates and fixes and stuff will keep happening for awhile, thanks for all the bug reports and comments so far
(-)
(u)AngriestIBM
(*)Toggle Deadchat Range is a verb that makes you not hear the living if they aren't, you know, actually nearby.
(*)Apparently some folks don't like having the chat window spammed by every doofus in the game blathering about nonsense??
(-)
(t)sat mar 02 13
(u)I Said No
(*)You can now use a multitool or t-ray scanner on a grille to see if it's electrified or not without zapping yourself.
(*)Changelings can now tear down a grille in one hit if they have harm intent enabled. This is kind of a dead giveaway though.
(-)
(t)fri mar 01 13
(u)Dr. Cogwerks
(*)Welcome to the new station!
(*)A very helpful robot named Murray would just love to show you around, he may be waiting in arrivals? unless he is already giving a tour
(*)BIG THANKS TO THE FOLLOWING FOR ALL THEIR HELP
(*)!!! Aphtonites, MagicMountain, Keelin, and AngriestIBM !!!!
(*)and also all the other admins and players who have helped with beta testing and map design feedback over the last six months! you guys rule
(-)
(t)fri feb 22 13
(u)AngriestIBM
(*)You can now view/search by DNA with the records consoles. Why wasn't this already a thing? Because...um
(*)Oh and no need to be secretive about my last commit now I guess: It was bees.
(*)Big ol' bumbly bees like the RD has. You order a crate of bee eggs and can use pens on them to name the resulting bee.
(*)Activate the egg and it hatches into a big goofy larva that grows into a big goofy bee and chills out drinking nectar from plants and making honey.
(*)You can sell the honey or give it to the chef or get a syringe and mainline it idk go hog wild.
(-)
(t)thu feb 21 13
(u)Procitizen
(*)Weld a crate shut. I don't care!!
(*)You can kick open crates if you're inside of them now! (assuming the crate isn't locked(or welded shut(or hurdling through space at warp speed)))
(-)
(u)AngriestIBM
(*)There's a new kit for hydroponics to do..hydroponics stuff with. Surprise stuff. Can be ordered from QM.
(*)Gosh that was a really secretive changelog message.
(-)
(t)tue feb 19 13
(u)Dr. Cogwerks
(*)Way to go, team! Thanks to everyone being awful, enjoy not having omega slurrypod zombies anymore.
(*)Why on earth was that even possible in the first place, zombies are dumb as hell and everyone is terrible
(*)Why are zombies even still in the code at all
(*)oh uh I also changed syndicate sauce awhile ago hoping people would quietly find out but nobody did
(*)so give that a try next time you're a traitor chef maybe, it should be a lot better now
(-)
(t)sun feb 17 13
(u)ISaidNo
(*)Changed the Wizard spellbook a bit - you can now hit the ? symbol next to spells to view what they do before you buy them. You can also no longer waste points by buying a spell you already have.
(-)
(t)sat feb 16 13
(u)ISaidNo
(*)When changelings use stings, spit or scream, they will now get a placeholder like wizard spells do so their abilities menu doesn't shift around.
(*)Couple of new mutations for hydro plants. Also, radweeds will now visibly pulse when emitting radiation.
(-)
(t)wed feb 13 13
(u)ISaidNo
(*)Satchels can now be used directly on harvest-ready plants to harvest them directly into the satchel. Any overflow will end up on the floor like usual.
(*)Satchels can now be used on the PlantMaster and Reagent Extractor to load items from the satchel into the machine.
(-)
(t)tue feb 12 13
(u)ISaidNo
(*)The Helpful Hydroponics Handbook has been completed. Hopefully that'll make the new hydrostuff a bit clearer.
(-)
(t)mon feb 11 13
(u)AngriestIBM
(*)Added confirm dialogs/cancel options to some changeling powers (Regen/Speed Regen/Transform/Lesser Transfer), because sometimes you DON'T want to explode into a writhing mass of tentacles in a crowd armed with laser guns.
(-)
(t)sun feb 10 13
(u)ISaidNo
(*)Added a new machine to Hydroponics - the PlantMaster, used for seed extracting, splicing and infusing.
(*)The Seed Extractor and Plant Gene Manipulator went to hell and died forever.
(*)Hydroponics equipment comes from a vending machine rather than lockers now.
(*)The starting health of new plants is now affected by a few different things. Bad endurance will cause the plant to have less health, and single-harvest plants gain or lose bonus health from the harvests gene. Damaged seeds also take health from a new plant. Plants will never start with less than 1 health and die instantly though.
(*)Made a whole shitload of changes to the hydroponics under-the-hood stuff. Report bugs, as always.
(-)
(t)mon feb 04 13
(u)AngriestIBM
(*)The RD sold his bomb to impulse buy a new pet.
(*)Also !!Clarks!! made versions of prox-radio and prox-igniter assembly sprites that don't look like they're from 2004.
(-)
(t)wed jan 30 13
(u)Infinite Monkeys
(*)Replaced the Quartermasters' shuttles with crates being launched through space via mass driver.
(-)
(t)sun jan 27 13
(u)AngriestIBM
(*)Those little cash register things in the marketplace use your bank account instead of cash now.
(*)If you still want to use cash...just toss some space cash over the table, you goof.
(-)
(u)I Said No
(*)Improved the Reagent Extractors. They now get two internal storage tanks and a better interface.
(-)
(t)wed jan 23 13
(u)Infinite Monkeys
(*)Individual body parts don't have damage limits any more because it was Really Dumb.
(-)
(u)Dr. Cogwerks
(*)Set up some new handling for electrocution re: grilles and cables.
(*)Shocks better take into account the available power now. The more power the station has, the more dangerous it becomes.
(*)BEWARE OF ARC FLASH. Safety first!
(-)
(t)fri jan 18 13
(u)Infinite Monkeys
(*)Rewrote mentorhelps, hopefully they should be less buggy and awful now. If they are broken or buggy let me know.
(*)Added proxy/igniter/beaker and radio/igniter/beaker assemblies.
(*)Chemical smoke now carries 3 reagents.
(-)
(t)wed jan 16 13
(u)AngriestIBM
(*)The station IT drones have now updated the medical console (We have one of those) to Medtrak 5.1.
(*)Included with the disks was a really nice set of pens carved from the bones of Medtrak 4's development team.
(-)
(t)mon jan 14 13
(u)Halerina
(*)AI/cyborg door shortcuts. Ctrl-click opens/closes an airlock, shift-click bolts/unbolts it. Considering a change to make all keys and mouse buttons electrify doors indefinitely.
(*)A large number of small changes and bugfixes over four years, considering I haven't personally updated this before.
(-)
(t)wed jan 09 13
(u)AngriestIBM
(*)The station IT department has upgraded security consoles to Secmate 7, primarily because the back of the box promised that everyone responsible for Secmate 6 had been fired into a star.
(-)
(t)tue jan 08 13
(u)Dr. Cogwerks
(*)Trick cigs (syndicools) can now be ignited by fire, sparks and explosions
(*)Actually all cigs can spontaneously ignite now. You can probably use this for mischief?
(*)Also I don't think cigs were properly causing fires when thrown into flammable stuff, so that should work now.
(-)
(t)mon jan 07 13
(u)Dr. Cogwerks
(*)Changed the available traitor weapons for spymode significantly. No more emags for spies.
(*)The remaining gear they can order is all stuff that feels spy-ish.
(*)Botanist traitors can now order the traitor fog machine. ~420 every day~
(-)
(u)Dr. Singh
(*)AIs can edit the arrival alert message. Roleplay it!
(-)
(t)sun jan 06 13
(u)I Said No
(*)Seed Fabricators can be set to filter available products by category.
(*)The Reagent Extractor now works instantly.
(*)Added an option when using a satchel on a disposal chute to empty the contents into the chute rather than put the satchel itself in.
(-)
(t)fri jan 04 13
(u)Dr. Cogwerks
(*)Added a short little GETTING STARTED guide to ThinkDos, use the Help command on a computer to see it.
(*)Also added a new software disk vending machine near Tech Storage (that dingy room below QM).
(*)edit: oh no two updates collided, check out AngriestIBM's new "help basics1" "help basics2" and "help basics3" commands on DWAINE
(-)
(t)tue jan 01 13
(u)I Said No
(*)Slurrypods will now give a warning before they burst. They also take a bit longer to burst.
(*)Made it more obvious on the Hydroponics trays when you're out of water or have too much.
(-)
(t)sun dec 30 12
(u)I Said No
(*)Hydroponics backend tweaked again. Man what is with me tweaking all these back ends! *giggle
(*)Seed Vendor may work a bit differently but function the same as usual. Report bugs of course.
(*)Added a new guidebook in Hydroponics on how to do good at Hydroponics. It isn't finished yet though since i'm not done messing with Hydro.
(*)Added some new types of nutrient formulas for plants that do various things. What they do is covered in the aforementioned book. Hydro starts with two bottles of each and can mix more if they figure out the recipes.
(*)Added some new mutant gene strains for Hydro crops. These are "general" mutations that affect certain things and can be passed between plant species when splicing seeds.
(*)The Seed Extractor now works instantly rather than making you wait.
(*)Lemons no longer produce Lime seeds. Not that anyone noticed. Or cared.
(-)
(t)thu dec 27 12
(u)I Said No
(*)Hydroponics backend tweaked slightly. Plants with mutations now use only Endurance and Potency genes for their requirements.
(*)Took the requirements completely off certain mutations. It's back to the old 8% chance rule for one mutation type per plant.
(-)
(t)sun dec 23 12
(u)AngriestIBM
(*)Sadly, the shuttle containing this shift's technical and medical assistants crashed. Into the moon. Forever.
(*)To compensate, staff assistants have been granted the same access as their fallen technical comrades.
(-)
(u)I Said No
(*)Artifacts have been updated and now work much, much differently. Artifact Lab is totally different. The old Artifact Lab got turned into more space for Tox Lab.
(*)Handheld artifacts now exist in addition to large object artifacts.
(*)Wizards now corrupt terrain faster. The Staff of Cthulhu's corruption time reducing factor has also been significantly increased.
(-)
(t)thu dec 20 12
(u)I Said No
(*)Mutation variants in Hydroponics now work differently - genes have to be in a paticular configuration for the mutation to have a chance of appearing. The requirements and appearance chance for each mutation are all different, too. Happy hunting!
(*)Hydroponics trays now start the game movable, and may be locked/unlocked with a screwdriver.
(*)Hydroponics backend code has been tweaked around significantly. Please report bugs to I Said No.
(-)
(t)mon dec 17 12
(u)I Said No, with sprites from Clarks
(*)Hydroponics now features.... actual hydroponics!!!!!!!!
(-)
(t)sun dec 16 12
(u)MyBlueCorners via Dr. Singh
(*)Random appearances for player preferences, brought to you by jolly cooperation.
(-)
(t)wed dec 12 12
(u)I Said No
(*)Added a ton of new emotes. Use the help emote to get lists of all usable emotes.
(*)The deathgasp emote now has a chance to fail and give you away. This will never happen on genuine deaths.
(-)
(t)sun dec 09 12
(u)Dr. Singh
(*)The telescience computer has a circuitboard in tech storage and the pad can be scanned by electricians.
(*)Light fixtures can be removed from the wall with a screwdriver if they're unpowered and there's no lamp or bulb. Or, make a new fixture from a stack of metal. Then you can use the fixture parts to build a light somewhere else, whoa!
(*)Late traitor rate reduced, HoS and security are no longer able to be late traitors.
(-)
(t)thu dec 06 12
(u)Dr. Singh
(*)Made the interrogation room larger and added a small back room for to security to safely transport inmates for questioning.
(*)Changelings can no longer absorb a corpse multiple times.
(-)
(t)wed dec 05 12
(u)Infinite Monkeys
(*)Blink teleports you forwards instead of randomly now. Cooldown increased a bit.
(-)
(t)wed dec 04 2012
(u)Dr. Cogwerks
(*)Added a bunch of new chems, oh no
(*)Antihistamine: stoxin + diethylamine + ethanol * heat
(*)Itching Powder - pretty simple recipe
(*)Histamine - cannot be mixed
(*)Crank - 4 things + fuel * heat
(*)Krokodil - 2 medical drugs + 3 other things * heat
(*)Bath Salts - 7 reagents * heat
(*)CAT DRUGS - 2 botany things, 1 other thing + fuel * heat
(*)gross thing: urine + water * heat = ammonia (precursor to most of the others here)
(-)
(t)sun dec 02 12
(u)Aphtonites
(*)Energy swords now have sound effects, thanks to MollyMillions.
(*)So do toy swords, wow!
(-)
(t)wed nov 28 12
(u)AngriestIBM
(*)The new plant seeds weren't showing up because I accidentally added them to the wrong seed vendor in the code.
(*)Because there are two functionally identical but separate seed vendors defined.
(*)Maybe by hitler.
(*)Maybe I'm going to kill myself.
(-)
(t)tue nov 27 12
(u)Keelin
(*)Updated ABCU markers. You can now create blueprints for exact copies of rooms at a slightly higher cost. These can not be saved."
(-)
(t)sat nov 24 12
(u)AngriestIBM
(*)I added some new plants, like avocados.
(*)Also you can use empty taco shells to crumble them into chips. You can dip chips into bowls. w h o a
(*)Guacamole!!
(-)
(t)sun nov 11 12
(u)Aphtonites
(*)The return of VR!
(*)A racing game has been added to the VR arcade!
(-)
(t)sat nov 03 12
(u)AngriestIBM
(*)Halloween died.
(*)It's a shame that Thanksgiving isn't very conductive to game ideas.
(-)
(t)mon oct 29 12
(u)ScariestIBM
(*)Halloween fun time!
(*)Halloween...fun time!!
(*)HALLOWEEN FUN TIME
(-)
(t)sat oct 20 12
(u)AngriestIBM
(*)Okay so MollyMillions made this ogg that plays when you cease being knocked out.
(*)That's kinda neat I guess.
(*)It's all "beep beep boop" and EKG-y and stuff.
(*)I'm padding this out to try to draw attention away from us forgetting to update the changelog for a month.
(-)
(t)sat sep 29 12
(u)DrMelon
(*)Added virtual wizard & syndicate kits to VR Gun Sim. Practice traitoring safely!
(-)
(t)fri sep 28 12
(u)Aphtonites
(*)Added tough competition for the station chefs.
(-)
(t)sat sep 22 12
(u)AngriestIBM
(*)Added Cogwerks' new janitor traitor item idea: A compactor trash cart. Looks identical to the regular one, but may cause people placed inside to become rather small and angular.
(*)Reminder on how to put people inside a cart/bin/crate: Move cart over lying person. Close cart.
(-)
(t)mon sep 17 12
(u)Wonkmin
(*)Looks like Inf Monkeys fixed a load of stuff, and this should get the rest. Huge thanks to Convair880 for his time identifying the wiring issues. Please continue to report issues on the new forums.
(*)New forums can be found at http://http://www.autisticpowers.info/ss13/forum/index.php
(-)
(t)sun sep 16 12
(u)Wonkmin
(*)The kitchen/bar is now south of botany and west of crew quarters. The old bar is now a storage warehouse.
(-)
(t)sun sep 09 12
(u)AngriestIBM
(*)Can you complete the PAINT DISPENSER REPAIR CHALLENGE?
(-)
(t)wed aug 29 12
(u)AngriestIBM
(*)Quartermasters can buy paint cans. I hope this alleviates your paint-related concerns.
(*)Please don't paint everything in the game and make the client choke rendering a million pink toolboxes or I will be VERY SAD.
(-)
(t)sat aug 18 12
(u)AngriestIBM
(*)I should probably clarify that spies can: implant anybody since security implants are no longer A Thing (Even other leaders! whoa!) and that these are super mindslaves that do not wear off after time passes.
(*)Implantees should be able to refer to their notes (Not the PDA one, the verb one) to see who their boss is. I guess.
(*)Also plant pots are secured/unsecured with a wrench now. What a crucial change!
(-)
(t)wed aug 15 12
(u)AngriestIBM
(*)There is a conspiracy/spy mode in beta. Competing syndicate infiltrators with mindslaves are fighting a shadow war for a promotion.
(*)Wonton wrappers! Put an egg and some flour in the mixer and stuff the resulting wrappers with small foods. And then fry them.
(-)
(t)sat aug 11 12
(u)Keelin
(*)Derringer Pistol traitor item. Can be hidden in clothes.
(-)
(t)mon aug 06 12
(u)Procitizen
(*)Sponges for the janitor. idk
(*)Light other people's cigarettes using a zippo!
(*)Headgear should show up on examine!!
(*)The Dark Knight Rises was kinda good, but not really!!!
(-)
(t)sun aug 05 12
(u)Procitizen
(*)Replaced the legitamately useless heavy armor in the armory locker with an EOD suit/helmet.
(-)
(t)thu aug 02 12
(u)AngriestIBM
(*)While gloves don't leave fingerprints, they DO leave other signs for the detective to scan :O (Well actually you get distorted prints from latex gloves)
(*)Chef has a sous-chef uniform available in the kitchen dispenser I guess. Recruit an assistant?
(-)
(t)tue jul 31 12
(u)Nannek
(*)Nuclear engines added. (BETA)
(*)Airbridge added
(-)
(t)tue jul 31 12
(u)Infinite Monkeys
(*)Added a timer/igniter/beaker assembly. Prox and radio assemblies to come but they are a pain to code.
(-)
(t)sat jul 28 12
(u)Infinite Monkeys
(*)Chemistry stuff:
(*)Stabilising agent that can make some previously instant reactions produce a stable-ish product.
(*)Thalmerite has two chemicals that affect its heating speed.
(*)Foaming agent removed - reactions that formerly used it now use fluorosurfactant.
(-)
(t)thu jul 26 12
(u)AngriestIBM
(*)Giving the chef a deep fryer cannot possibly backfire. CANNOT POSSIBLY BACKFIRE.
(*)Oh and I guess botany wanted one of those crate telepad gizmos.
(-)
(t)tue jul 10 12
(u)Infinite Monkeys
(*)Late join traitors attempt two.
(-)
(t)sat jul 07 12
(u)IShallRiseAgain
(*)Syndicate Shuttle is no longer on same Z-level as the station.
(*)The syndicate teleporter can be activated with a syndicate teleporter remote in order to exit and go back to the syndicate shuttle.
(-)
(t)thu jul 05 12
(u)I Said No
(*)Dropped manufacturing costs of mining equipment a bit.
(*)Engineering Spacesuits no longer make you go any slower than a regular space suit does.
(-)
(t)mon jul 02 12
(u)I Said No
(*)The Mining Outpost now has an APC and light switch for each of its seperate areas. There are also rods and hand labellers available.
(*)The Mining Manufacturer now makes rods and metal sheets.
(*)Extractor Rigs now drill much faster, and show the correct amount of ore in the hopper. (It was always off by 2 until now.)
(*)There are now display screens on the Mining Outpost that show how much ore has been dug up.
(*)Replicants have been disabled for the time being. They'll be back later.
(-)
(t)fri jun 29 12
(u)I Said No
(*)Rotating a window will now prompt you which direction you want to rotate it in. Examining the window will also tell you it's current fastened status.
(*)Tidied up the job selection menu a little.
(-)
(t)wed jun 27 12
(u)Infinite Monkeys
(*)Added a 'mentorhelp' command for asking gameplay-related questions - round spoiling questions and things like that are fine. Currently admins and dead HOSes can read/reply to the channel.
(-)
(t)wed jun 27 12
(u)I Said No
(*)Sturdy and Heavy cyborg Heads and Arms are now available. Use two metal on a regular part to make it sturdy, and two reinforced metal on a sturdy part to make it heavy. These parts can take more damage, but are heavy and will slow the Cyborg down a bit. Heavy moreso than Sturdy.
(*)Cyborgs should now be able to suicide.
(*)The bug that let you share reagents with yourself is fixed. Come on, that doesn't even make sense. =I
(-)
(t)tue jun 26 12
(u)I Said No
(*)You can now pour your reagent container (beakers, bottles, etc) into someone else's while they are holding it. They need to hold it in their active hand, and both parties need to have Help intent selected.
(*)This also works for cyborgs - the Cyborg needs to have Help intent selected, and has the beaker equipped in a slot and selected. (The square it's in needs to be highlighted in green, basically.)
(-)
(t)mon jun 25 12
(u)I Said No
(*)Cyborgs now have their old appearance sets back. What's more, they can be customised at Docking Stations! (But no self-customisation. You need someone to help you!)
(*)Construction Cyborgs now have floor tiles instead of metal sheets.
(*)Engineering Cyborgs now have the Atmospherics Transporter that Atmos Cyborgs used to have.
(*)Chemistry Cyborgs have their own internal ChemMaster unit now, and cannot use the regular ChemMaster. In addition, using the Chemistry Dispenser is slightly different for them and doesn't involve inserting the beaker.
(-)
(t)sun jun 24 12
(u)I Said No
(*)Enabled the new-type cyborgs as a test. Some stuff may be substantially different!
(*)Cyborg construction for new-type cyborgs is a bit different. The brain goes in the head piece before attaching, you use a wrench on the frame once it's complete to activate the new cyborg.
(*)After you've opened a Cyborg (crowbar) and exposed it's wires (screwdriver), use robot parts on it to attach new parts, or a wrench to remove existing ones.
(*)Treads are now available as a cyborg component. They occupy both leg slots - they boost speed a bit but drain power from the cyborg's cell.
(*)New type Cyborgs may get a free upgrade depending on which module they pick at the start. Mining Borgs also have the option to teleport to the mining station.
(*)Cyborgs may be repainted and redecorated from docking stations. They look a bit plainer than they used to for the moment but that'll be fixed if this all pans out.
(-)
(t)sat jun 23 12
(u)I Said No
(*)Cyborg construction process is now slightly different. Heads no longer need flashes, and parts already on the frame can be wrenched off if needed. Cells and wires in the chest piece can also be removed with wrenches and wirecutters, respectively.
(*)Atmos and Vendor borg modules were discontinued due to being borderline useless.
(*)Substantial background changes to a whole ton of cyborg shit. Report any bugs, please!
(-)
(t)tue jun 19 12
(u)IShallRiseAgain
(*)You can make cakes with virtually any food item now, and you can use icing tubes to decorate them with icing.
(-)
(t)sun jun 17 12
(u)I Said No
(*)Added the Motor Oil reagent. Splashed on cyborgs, it will make them move faster and use less power for a short while. Roboticists start with an oil can - more can be mixed if you know the recipe. Experiment and find it!
(*)A new oil can sprite courtesy of Clarks! Splashed oil now also stains the floor. Technically this was put in on tuesday and not sunday but eh sod it.
(-)
(t)sat jun 16 12
(u)I Said No
(*)Plasma Cutter has been replaced by Concussive Gloves. They allow you to mine asteroids by punching them with your bare hands.
(*)Power Hammer was buffed a bit. It now shatters nearby weak tiles in addition to digging.
(*)Mining Charges have become Concussive Charges. They work only slightly differently to what they did before.
(-)
(t)thu jun 14 12
(u)I Said No
(*)Cyborg Recharging Stations are now Cyborg Docking Stations. In addition to recharging cells, they can perform repairs, rename cyborgs, and handle the installation/swapping of various cyborg components.
(*)Docking Stations accept power cells, upgrades, modules, cable coil and welding fuel. You can also help Cyborgs climb in by click-dragging them onto the station.
(*)Robotics Research is gone. It'll be back later in some form. For now, Roboticists can make all robotics items right off the bat. Resources is the only limitation.
(*)Cyborgs now start in Robotics rather than AI Upload.
(*)Updated a bunch of backend stuff for Cyborgs. Report any bugs, please!
(*)Gave miners their miner bots and drill rigs back. Sorry about that!
(-)
(t)mon jun 11 12
(u)Procitizen
(*)Added a box of latex gloves to medbay. Made fingerprints left by latex gloves a little more confusing. I'm still working on detective stuff I promise!!!
(*)Click on a door with a T-ray scanner to see if it's powered, unpowered or electrified!
(*)The T-ray scanner can also be used to measure how much power is being sent through a cable. This was actually a thing multitools did before, but scanners don't get enough love. :(
(-)
(t)thu jun 07 12
(u)IShallRiseAgain
(*)Virtually any food can be a topping for pizza now
(-)
(u)LLJK-Mosheninkov
(*)Added Amusing Duck and a dog named George. RIP george you were a good dog. (big thanks to Cogwerks for the sprites)
(-)
(t)wed jun 06 12
(u)I Said No
(*)Redesigned the mining outpost to be a bit more spacious and functional. Also redesigned something else, see if you can find out what.
(*)There are now a max of six miners and four botanists.
(-)
(t)sun jun 03 12
(u)IShallRiseAgain
(*)Added a cookbook and new appliance to the kitchen
(-)
(t)sun jun 03 12
(u)I Said No
(*)Sheets of Metal and Glass as well as Metal Rods now all stack to 50. Floor tiles now stack to 80.
(*)All of the items mentioned above can now be drag-dropped onto each other to quickly gather nearby items into one stack.
(*)Welding rods to get metal and using metal to build tiles and rods now prompt how many you want to make a stack of.
(-)
(t)sat jun 02 12
(u)Nannek
(*)Mouseover people to see their assignments on their id cards.
(*)Redid how voice changers were handled in the code making them more robust.
(-)
(t)fri jun 01 12
(u)Dr. Singh
(*)Starlight removed, it looked cool but caused too many problems behind the scenes that I haven't been able to fix.
(-)
(t)thu may 31 12
(u)I Said No
(*)Particular random events now occur based on how long the round has been running. Spatial Tears, Kudzu, Solar Flares and Ion Storms can occur right from the start. Wormholes, blobs, radiation, viruses and meteors will only occur after 40 minutes have passed. Black Holes and Blowouts occur only after 80 minutes have passed.
(*)Blowouts are back in the rotation, as you might have guessed. They no longer blow up all the lights on the station, too.
(*)Meteor random events will now strike from one direction rather than swarming in from all sides. You also get three minutes to prepare before the meteors arrive. Meteor Storms after the 80 minute mark will be far worse than those before it.
(*)Meteor Shield Generators are now available in emergency storage. You can also turn lattices into anti-meteor barricades by using rods on them. Weld barricades to dissassemble them,
(-)
(t)tue may 29 12
(u)AngriestIBM
(*)So um, you know how the mulebot didn't actually have any delivery locations set up? That's fixed now. I FORGOT OKAY THERE ARE A LOT OF THINGS TO PUT IN A MAP
(-)
(t)mon may 28 12
(u)AngriestIBM
(*)Beds now have a "sleep in" verb. If you lay down and use it...you sleep in them! And you can press the laying/standing toggle button to..wake up! Whoa!
(-)
(t)sun may 27 12
(u)I Said No
(*)Miners now start with three extractor rigs and two extra crates of furnace fuel.
(*)Metal, Glass and Rods stacks will now give messages when adding to or otherwise manipulating them.
(-)
(t)thu may 24 12
(u)Infinite Monkeys
(*)You can now click the inventory button with an equippable item in your active hand to equip it. If you have an item equipped in that slot it'll be put in your active hand.
(-)
(t)tue may 22 12
(u)AngriestIBM & Supernorn
(*)Implemented Supernorn's cool new hud!! whoa!!
(*)Primer: Intents selection is now done by clicking the appropriate square of the intent panel.
(*)Drop is the half-tile below throw (To the right of hands)
(*)Active hand selected by clicking the appropriate hand slot.
(*)Most alerts, like extreme cold, now only show up when there actually is an alert.
(*)Also the inventory can now be hidden. Belt, pockets, and backpack are always visible, however.
(*)Nonhuman mob HUDS are probably broken as fuck right now.
(-)
(t)mon may 21 12
(u)AngriestIBM
(*)Thanks to a generous donation from the Change the Brig Slightly Foundation, the brig has been changed. Slightly.
(*)Also implant locks are just gone in general now.
(*)Cyborgs can use the goofy PageUp switchhands hotkey now too! Switch through your active modules!!
(-)
(t)sun may 20 12
(u)Infinite Monkeys
(*)More suicide methods.
(-)
(t)fri may 11 12
(u)LLJK-Mosheninkov
(*)Made emergency suits less shitty (but still quite shitty!) and made them more orange instead of salmon. Also changed their in-world icons so the suit and helmet don't look like a mob standing there
(-)
(t)thu may 10 12
(u)Infinite Monkeys
(*)Added a bunch more crew objectives and enabled the system. AngriestIBM did all the hard work coding the framework so thank him!
(-)
(t)wed may 09 12
(u)AngriestIBM
(*)Unfortunately, the recent oxygen garden renovation attracted a family of bears. As the resulting enactment of NanoTrasen bear-elimination protocols resulted in the garden's complete atomization, the bar and kitchen have been relocated to the new space. A new crew area has been installed in their former location.
(-)
(t)tue may 08 12
(u)Procitizen
(*)Okay, let's try this again! Now scientists have access to chemistry and chemistry has been returned to the research sector.
(-)
(u)I Said No
(*)Touching foam no longer puts the reagent into your body, and neither does splashing. If you want it in your system, you have to inject or consume it.
(*)NanoTrasen Medical reminds all personnel not to overdose on medicine and stimulants.
(-)
(u)LLJK-Mosheninkov
(*)Crew quarters has been replaced with a much more eco-friendly oxygen garden.
(-)
(t)mon may 07 12
(u)Procitizen
(*)Made the Medical Doctor uniform slightly more red
(*)Killed Chemists and moved Chemistry into Medbay for doctors to use
(-)
(t)sun may 06 12
(u)Dr. Singh
(*)Health shouldn't jump around wildly anymore. Please let me know on the forums or in IRC if you still get weird health behaviors.
(-)
(t)sat may 05 12
(u)Infinite Monkeys
(*)Vampires can now create thralls for 300 blood.
(-)
(u)I Said No
(*)Mixed Mode: Chaplains should no longer be selected to be a Vampire. They should be assigned Traitor or Changeling instead if this occurs. Report any instances of Vampire Chaplains, thanks.
(-)
(t)fri may 04 12
(u)Infinite Monkeys
(*)Lots of vampire changes, still a work in progress, feedback would be appreciated in the suggestions thread. Changes:
(*)Disease Touch is back to being deadly, but is non-contagious. Use it to kill important personnel I guess?
(*)Blood count now displayed in the Status menu.
(*)Cloak of Darkness and Mist Form should work properly now.
(*)Blood draining requires one click and continues until interrupted. It also has a chance to stun/KO.
(*)Other misc changes to cooldowns, blood costs, etc.
(-)
(u)I Said No
(*)New item: Mechanised Boots. Industrial Armor no longer confers a speed boost - the boots do that now.
(*)Geological Scanners now show different decals for different things. Some things share decals, so it is still wise to check before you dig.
(*)Abandoned Loot Crates can sometimes be dug up via mining. Don't ask how they got buried in solid rock.
(*)Changed the Power Hammer. It can be now used mostly like a regular mining tool (pick, etc), took out that stupid "useless collapse" thing.
(*)Fabricator Item Lists can now be filtered by category. The option is down the bottom. Also you can now eject ore even while it's busy building something.
(*)Ore Extractor Upgrades now fit on mining belts.
(*)Fibrilith and Miracle Matter are now properly loaded from using a satchel on the Fabricator by hand.
(*)You can now click-drag ore and produce into crates to load them in rapidly, provided the crate isn't locked.
(*)Jumpsuits and shoes from Fabricators. Woah.
(*)Electricians can no longer have a suit of industrial armor as a traitor item.
(-)
(t)thu may 03 12
(u)Procitizen
(*)Latex gloves now obfuscate fingerprints instead of completely hiding them.
(*)The maximum number of fingerprints on any given object has been increased from 3 to 6.
(*)Added an experimental 64x64 icon mode, check under the Icons tab near File.
(-)
(u)I Said No
(*)Satchels now come with visible meters to show how full they are.
(*)Large Ore Satchels can be built at Mining Fabricators, from 25 fabric and 3 Bohrum. They hold 75 ore each.
(*)Power Hammers will shatter weak rock formations within a small range of the tile you strike.
(*)Mining and Robotics Fabricators start with 20 of each basic ore pre-loaded. No more scavenging for cables and such.
(*)Fibrilith and Miracle Matter can now be loaded into a fabricator via click-dragging, same as normal ores.
(*)Diseased Touch/Grave Fever no longer stuns, and does less toxic damage.
(-)
(t)wed may 02 12
(u)AngriestIBM
(*)Apparently flash powder's recipe was critically immersion breaking, and as such it now also uses chlorine.
(*)Also avoid purple beams. Trust me on this.
(-)
(t)tue may 01 12
(u)I Said No
(*)Extractor rigs now come with an inbuilt GPS for locating them.
(*)Miners now start with three satchels and three light mining charges each.
(*)Explosions will now weaken and crack most asteroid tiles that they didn't destroy outright.
(*)Mining belts should now be able to store mining PDAs, as intended. Rock worms are no longer on a diet.
(*)The beds in the brig can no longer be used for buckling.
(*)Added a furnace room on the main station for an emergency power supply.
(-)
(t)tue may 01 12
(u)I Said No
(*)Mineral Accumulators and Ore Extraction Rigs start with a fully charged 7500 capacity power cell already loaded.
(*)Made cell chargers charge up power cells much faster.
(-)
(t)sat apr 28 12
(u)Infinite Monkeys
(*)New arrivals can spawn as traitors in certain situations.
(*)Non-antagonists with security implants can no longer use cloaks. Traitors who manage to obtain a sec implant can.
(-)
(u)I Said No
(*)Reworked a bunch of background stuff for mining. Report bugs if any come up.
(*)Small asteroids now have a chance to be made of solid mineral, containing hundreds of units of ore. You can't dig them with regular tools.
(*)Miners can now create and set up extractor rigs near said asteroids. They will gradually extract ore from them over time.
(*)Upgrades can be made for said rigs that expand their capacity, increase their drilling speed, and give them a teleporter.
(*)You can click-drag a crate onto the rig to empty all ore from it into the crate, or you can smack the rig with a satchel to fill the satchel up.
(*)Rigs will also send messages to miner PDAs if something occurs. PDAs can be put on mining belts now, too.
(*)Moved the cargo pad in Mining closer to the fabricator.
(*)Miners now ACTUALLY have their double mining speed and weird tile warnings perk. It wasn't in effect before because apparently the Chaplain had it instead.
(*)Plasmastone is actually useful for something now. Holy SHIT
(-)
(u)Dr. Singh
(*)Changed the middle click shortcut to just swap hands. Apologies to anyone who liked it but it breaks too many things that were built around the whole active/offhand idea and just feels awkward and wrong.
(-)
(t)fri apr 27 12
(u)I Said No
(*)The Request Console at QM and commercial vending machines now accept ID cards. They use money straight from your bank account so now you don't have to screw around with cash and ATMs.
(*)Grones Soda now has the flavor in the description rather than the name. The gigantic entry on the vending machine page was bugging me.
(-)
(t)thu apr 26 12
(u)I Said No
(*)Three new traders for QMs to interact with. One of them is a randomised generic trader.
(*)You can now haggle with traders. Hit haggle, type in the new price you think you should pay per unit, and the trader will meet you somewhere halfway. Don't try to rip them off or push it too far, though!
(*)Rolled all the fruit/veg/herb commodities in the Shipping Market into a single category rather than having them all be individually priced.
(*)Couple of new commodities. Meat, Robot Parts, Glass, Metal. Maybe some others I forgot.
(*)You can now select the amount of items you want when a trader is selling to the station.
(-)
(u)Dr. Singh
(*)Middle click now uses your offhand. Thanks MyBlueCorners for putting in the effort on this one. Cue complaints from people with laptops and cheap mice in 3... 2...
(*)Control click is now pull. Yep. It's finally the future.
(*)Added one of those top left corner action buttons to turn your tank valve on and off. You'll still have to adjust the pressure the old fashioned way.
(-)
(t)mon apr 23 12
(u)I Said No
(*)Automatic Mining Bots are now craftable. Hard Hat > Prox Sensor > Robot Arm > Pickaxe or Drill. Mining station starts with two of them.
(-)
(t)sun apr 22 12
(u)Procitizen
(*)You can now examine stuff by holding down alt and clicking on it. For real this time though.
(*)Local Air Monitors have taken a vow of silence, forever
(-)
(u)I Said No
(*)Mucked around with a ton of background shit. Be sure to report bugs.
(*)New gamemode: Mixed. It's not in the rotation yet because it still needs some live testing.
(*)Predators can now force unbolted doors open with their bare hands.
(*)Added a cell charger to the mining outpost, since they can make cells now.
(*)Furnace fuel now lasts longer.
(*)Traders will now periodically contact the station with offers. It is the responsibility of the Quartermasters to accept or decline, and work out the other various logistics of trading!
(*)Thus far there is only one trader. More will be added soon.
(-)
(u)AngriestIBM
(*)You can now repair APCs with the amazing power of screwdrivers, cabling, multitools, and wrenches. A real toolbox teamup.
(-)
(t)fri apr 20 12
(u)Procitizen
(*)Welding masks can be moved out of your eyes so you can see stuff.
(*)Replaced the Holy Water bottle sprite with one that's significantly more cooler. (Hempuli you are a boss sorry I didn't do this sooner)
(*)Changed the revolver/generic gunshot sound to something meatier and less compressed.
(*)Local Air Monitors now produce annoying beeping sounds when there's an atmosphere problem in compliance with Space OSHA standards! Place your bets on when this will be removed!
(-)
(u)I Said No
(*)Geological Scanners and Power Hammers now work instantly rather than after a delay.
(*)Any given tile of ore has a rare chance to carry twice as much ore, and a very rare chance to carry four times as much.
(*)Power Hammer cost was changed, and both it and Powered Picks now have more charges.
(*)Power Hammers now have a 50% chance to uselessly collapse a seam on multiple weakenings, rather than 95% as before.
(*)Mining Manufacturer can now produce power cells and flashlights.
(*)New high-end equipment for miners: Mineral Accumulator. Works like a combination between a black hole and a cargo teleporter - will drag all nearby ore to it and teleport it to a cargo pad. Needs a power cell to run.
(*)Two new gems! One is Fibrilith - redeemable for 40 fabric at a manufacturer, or sellable. The other one is best left discovered for itself.
(*)All Manufacturing Units now have an adjustable speed setting. Can be set to run at double or triple speed. Beware! Doing so consumes a LOT of power from the local APC!
(*)Cyborg farts have new text to distinguish them from human farts.
(-)
(t)sat apr 14 12
(u)I Said No
(*)Did some background work on new jumpsuits you may see one day soon!
(-)
(t)thu apr 12 12
(u)Infinite Monkeys
(*)Fuck stungloves.
(-)
(u)I Said No
(*)That stupid RIG Armor is no more. Now there is Industrial Space Armor, with a nice new look. It also protects you from explosions now, too.
(*)Cost was reduced for the armor. You also manufacture both pieces at once, rather than individually.
(*)Space suits are also now manufactured as a helmet/suit set, too.
(-)
(t)wed apr 11 12
(u)Dr. Singh
(*)Fixed that explosion bug I caused. Sorry about that. About fixing it, I mean.
(*)The stars now produce light as intended. Ambient lighting from exterior windows and/or gaping holes. No more sticky darkness (hopefully).
(*)Changed explosion processing to guarantee that nobody can outrun the blast radius due to lag.
(*)Improved the chance for an electric chair's non-lethal setting to de-rev.
(*)You can now quick-stack some items by holding one in your hand and dragging another onto it from the floor. Currently works for sheets of glass and metal, rods, floor tiles and wire coils.
(-)
(t)tue apr 10 12
(u)I Said No
(*)Mining speed cut in half universally. On top of this, miners dig twice as fast as everyone else.
(*)As an added bonus, Miners start with powered picks instead of regular ones.
(*)Plant Pots in Hydroponics now consume half as much water as before.
(-)
(u)Dr. Singh
(*)Why could electricians build Syndicate gear anyway? If Nanotrasen could just make that stuff security would have cloaks in their lockers.
(*)Electricians can no longer scan traitor gear. They can scan a few more things around the station to make up for the lack. Please let me know if you notice anything electricians can't scan that they should.
(*)New traitor item added for electricians: A fancy Syndicate scanner that can scan traitor gear.
(*)E-mag cost upped from 3 to 5 since they do everything and are really really good. Radio jammers reduced from 5 to 3 because they should be used more, especially now th--BLARGH
(*)E-magging a cyborg no longer unlocks the interface, instead it fries the cyborg's connection to the Laws database. It doesn't compel the borg to help you or anyone. It just removes all laws.
(*)Added confirmation popup to 'State All Laws' so AIs will be less inclined to reveal things they shouldn't.
(-)
(t)sun apr 08 12
(u)AngriestIBM
(*)Three words: Easter. Egg. Hunt.
(-)
(t)sun apr 01 12
(u)I Said No
(*)Added Zombie and Alien modes to standard round rotation.
(*)Added several powerful guns to abandoned loot crates that may only be used if your character is named "Iji".
(*)Fixed the Flamethrower.
(-)
(u)Dr. Melon
(*)Re-added the Clown job in all its entirety.
(*)The clown can now breathe in space.
(*)The clown can now fly.
(*)The clown can shoot lasers from his nose.
(-)
(t)fri mar 30 12
(u)AngriestIBM
(*)The new electronics update requires 2x buzzers, 4x diodes, and 5x fuck mport's awful code.
(*)Also I renamed the electronics data disks to modules so they don't get confused with actual data disks. Do they have any utility beyond plugging into scanners to give you a list? Maybe I should just replace them with a printout of the parts needed or something.
(-)
(u)Dr. Singh
(*)Thanks to Tobba for the updated lighting code. Lighting is now calculated differently, allowing for some neat new tricks.
(*)Fixed the party alarm.
(-)
(t)tue mar 27 12
(u)Procitizen
(*)<b>New Thing</b>: Shard Recycler in the bar! It can turn glass shards into cups and plates!!!
(*)<b>Sorta New Things</b>: Shot and wine glasses, can be made with the Shard Recycler (see it's not useless)
(*)Bar stools! They do nothing oh well
(*)Changed the firesuit sprite so it's less neon green and Denis Leary approved
(*)Fixed emergency suits so they protect you from space a lil bit instead of making you more vulnerable (what the fuck mport)
(-)
(t)sat mar 24 12
(u)Dr. Melon
(*)Gone are the days of unstable medical practice: bruise packs and ointment tubes have been replaced with chemical patches!
(*)Empty patches have been added to chemistry - use a syringe to fill them.
(*)Nicotine patches are available in the cigarette vendors.
(*)You can make new patches with the general manufactuer.
(-)
(t)wed mar 21 12
(u)Infinite Monkeys
(*)Proximity sensors, and assemblies that use them, should now work.
(-)
(t)thu mar 15 12
(u)I Said No
(*)More wizard mode changes:
(*)Wizards start without their robes. They can now retrieve them from the wardrobes - they have a choice of three different styles now.
(*)New selectable Wizard thing: Staff of Cthulhu. Makes corruption ritual faster, hits harder than a normal staff and will horribly shock anyone trying to steal it.
(*)Arrival, Escape and Supply Shuttles, as well as the Solar Panels, no longer count towards the total percentage of corruption.
(*)Corruption percentage count should be more accurate now.
(-)
(t)thu mar 15 12
(u)I Said No
(*)Wizard mode changes again:
(*)The Chaplain is now the Wizard's natural enemy. He has immunity to all magic and the ability to remove corruption.
(*)Wizards are immune to each other's spells as long as they have their outfit and staff equipped.
(*)The Chapel is a safe haven - Wizards cannot teleport directly into it or use spells inside. This protection stops at 40% corruption, however.
(*)The Corruption now has various effects that get worse as more of the station is corrupted. Wiz and Chaplain are immune to these.
(*)At 30% or more corruption, the Wizard will slowly regenerate health while inside.
(-)
(t)wed mar 14 12
(u)I Said No
(*)You can now select whether you want to hear admin played sounds or not. Look under the Soundscape option.
(*)Admins can now optionally announce that they're playing sounds and what the sound filename is, like a DJ or something.
(-)
(t)sun mar 11 12
(u)I Said No
(*)Erebite and Cerenkite power cells can now be manufactured. They regenerate power on their own. Erebite Cells will explode on contact with heat or fire, however.
(*)Shaving off a Wizard's beard will cause them to become too ashamed to cast offensive magic for a short while.
(*)Couple of new facial hairstyles.
(-)
(t)fri mar 09 12
(u)Dr. Singh
(*)Added peanuts and peanut butter. There's also a few secret recipes, uh huh.
(*)Fixed a ton of runtime errors and weird bugs and the main background loop slows itself if the server load gets really bad.
(*)The bosses found out about that sweet hidden VR room the CE built and made us remove it, OSHA or something I don't know. Supposedly some assistant still has the combat program somewhere.
(*)Due to your diligent research and development Nanotrasen is now able to interfere with the science teleporter. It's expensive so they only bothered to jam security.
(*)There's a cool trick for robusting you can do thanks to a certain bug fix. What is it? That would be telling.
(*)Exploding machinery sprays shrapnel around when it explodes.
(-)
(t)thu mar 08 12
(u)Procitizen
(*)Fucked with the plasma generator so now it's basically just a portable cell charger
(*)Fixed critter jumping issue
(*)Changed the singularity icon from a shitty photoshop brush to a shitty photoshop circle with edge glow
(*)Modified the Head Surgeon
(-)
(t)tue mar 06 12
(u)AngriestIBM
(*)You know how the AI couldn't see visual text things like "bob picks his nose" or whatever before? Now it can!!
(-)
(t)mon mar 05 12
(u)I Said No
(*)<b>Bugfix:</b> Corruption should now be applied to a whole area rather than patches.
(*)<b>Bugfix:</b> Corruption should no longer be affected by light levels.
(*)<b>Bugfix:</b> Wizards should no longer temporarily spawn naked on the Arrival Shuttle.
(*)<b>Bugfix:</b> The end of the round should now correctly state whether the ritual was a failure or success.
(*)<b>Change:</b> Corruption Ritual now completes more quickly.
(*)<b>Change:</b> The Corruption objective now needs 40% of the station corrupted, down from 50%.
(*)<b>Change:</b> Clairovoyance's cooldown was lengthened from 10 seconds to one minute.
(*)<b>Addition:</b> A Magic Mirror in the Wizard's Station. Wizards that examine it will be told all objectives that need to be completed.
(*)<b>Please report any persisting or new bugs! Thank you!</b>
(-)
(t)sun mar 04 12
(u)I Said No
(*)Wizard rounds now work differently. The wizards will win immediatley if they complete all their objectives - which always consist of killing three specific targets and corrupting 50% of the station.
(*)Wizards now start with the spells Clairvoyance and Corruption Ritual. A few more effects were added to Pandemonium.
(-)
(u)Infinite Monkeys
(*)Revolvers now come with two spare clips, and ordering revolver ammo gives you three AP clips.
(-)
(t)sat mar 03 12
(u)I Said No
(*)Cloaking devices now periodically flash instead of flickering or doing nothing. They were reverted to their original cost also.
(*)Wizards now spawn with large, luxurious beards properly befitting their magical station, and their hats actually look like hats now.
(*)Added new effects for some spells.
(-)
(t)sun feb 26 12
(u)I Said No
(*)Cloaking devices no longer betray their presence by flickering. They are a bit more expensive to compensate for this.
(*)Keep your eye out for hunters. Yes this is some cryptic bullshit, what of it?
(-)
(t)sun feb 19 12
(u)Infinite Monkeys
(*)Added a teleporter thing for scientists! Needs feedback and will be worked on more when I have time. The coordinates you input are modified to get the actual value, and the modifications made are randomised each round.
(-)
(t)mon feb 13 12
(u)Infinite Monkeys
(*)Added a new traitor item, only purchasable if you have an assassinate objective, which allows you to track IDs registered to your target(s).
(*)Buffed the rad crossbow a few days ago but I forgot to update the changelog. Give it a try sometime!
(-)
(t)sat feb 11 12
(u)DrMelon
(*)Rejoice, DWAINE users! There's a book to teach you all about the new DWAINE in the artifact lab.
(-)
(t)fri feb 10 12
(u)AngriestIBM
(*)Re-added the personnel that we had all missed so dearly, who would always bring a smile to the collective faces of the crew with their lighthearted antics and wonderful jokes.
(*)And by that I mean Medical and Technical Assistants! Normal vanilla assistant is now "Staff Assistant."
(-)
(t)mon feb 06 12
(u)Dr. Singh
(*)The AI can de-electrify all the airlocks it controls.
(*)AI and Cyborgs get an extra popup to confirm shocking doors and turning off engine components.
(-)
(t)wed feb 01 12
(u)AngriestIBM
(*)Hey you can research artifacts on the mainframe. As opposed to that backup console.
(*)Default location for the research program is /mnt/artlab. There's a readme. You could maybe read it. That would be neat.
(-)
(t)fri jan 27 12
(u)AngriestIBM
(*)You should be able to configure Guardbuddies again. Try "cd /mnt/control" (This is the default mount for the tape holding the buddy interface) and then "cat readme"
(-)
(t)wed jan 25 12
(u)AngriestIBM
(*)It's a new map holy goddamn. I guess report bugs on the forums?
(*)No the new research stuff isn't finished, we're all very sorry ok. The RD has recieved a cookie from the computer company as a token of apology.
(*)You can just suicide to leave VR. If you die in the game, you DON'T die irl.
(-)
(t)thu jan 19 12
(u)Infinite Monkeys
(*)Fixed electric chairs.
(*)Electric chairs and electropacks can now derev!
(*)Made the changeling DNA points system more transparent yesterday.
(-)
(t)tue jan 17 12
(u)DrSingh
(*)The "help I can't die" bug where everyone's health stops updating should never happen again.
(*)Large swarms of admin created creatures, giant fires, blobs, etc no longer lag horribly. Neither does the unban panel. It's still slow the first time but after that it's smooth.
(*)Game ticks now happen at a consistent rate until things start lagging really really bad.
(-)
(t)mon jan 16 12
(u)DrSingh
(*)Sikh siropa and turban in the chaplain's closet. Dr. Singh is still not a real sikh, or a real doctor.
(*)Bunch of errors fixed and performance work, lots more to go. If anything unusual happens or just breaks please leave a query with details to drsingh in IRC.
(-)
(t)sun jan 15 12
(u)Infinite Monkeys
(*)Horror form isn�t harmed by stepping on glass and can consume with an Agressive grip.
(*)AI can now make an intercom (VOX) announcement once every two minutes!
(-)
(t)fri jan 13 12
(u)Pantaloons
(*)Added a neat feature where if someone is kn--NNGH.
(-)
(t)thu jan 05 12
(u)AngriestIBM
(*)Reduced syndicate cyborg suit cost by an entire telecrystal!
(*)Oh and pathology is still gone. It will be back eventually. Just felt I should note that somewhere official.
(-)
(t)thu dec 15 11
(u)AngriestIBM
(*)Added an "about" button to the traitor uplink menu. Not everything has an entry yet, though.
(-)
(t)thu dec 08 11
(u)AngriestIBM
(*)Removed implant locks from ALL airlocks and lockers. Guns retain their locks, however.
(*)Please report if your job suddenly cannot access a vital locker or if suddenly every jerk can, etc.
(-)
(t)thu nov 17 11
(u)AngriestIBM
(*)Added a centcom report to nuclear mode.
(*)Injectors are back.
(-)
(t)tue oct 26 11
(u)Procitizen
(*)Fixed a TON of shit that was breaking the health system, a lot of it is definitely still broken but it's a start!
(-)
(t)sun oct 16 11
(u)Procitizen
(*)Changeling reports the number of DNA absorbed at round end
(*)Revolution ends with nobody winning after ~50 minutes (please don't metagame with this :\[)
(*)AI turrets now fire every 1.5 seconds instead of 3 so maybe now they're useful
(*)Cleaning a floor/stain with a mop will now clean every stain on that turf
(*)Added cameras/viewers to the Solitary Chamber in Security
(*)Moved the solitary gas chamber controls to the room south of the brig
(*)HoS office reworked a bit, fixed basically everyone having access to his shit
(*)try grabbing someone and clicking on a window :V
(-)
(t)sat oct 15 11
(u)AngriestIBM
(*)Electricians can now load all components on a given tile onto a frame by clicking and dragging one onto said frame.
(*)You know, like how you load a satchel. Pretty much exactly like that.
(-)
(t)sat oct 01 11
(u)JackMassacre
(*)Mind Slave implants cost only a little more than a pipe bomb now, and last longer. Let's see how this works out.
(*)Engineering space suits don't slow you down nearly as much anymore, but still more than originally.
(*)Mining fabricators now produce engineering space suits and engineering space helmets instead of regular ones.
(*)Various typo fixes to go along with your re-rebalancing. Delicious.
(-)
(t)fri sep 30 11
(u)JackMassacre
(*)QM shipping list altered: More choices, more descriptions, some old crate contents have been changed.
(*)The worth of Mauxite, Molitz, and Pharosium as a shipping commodity has been lowered to curb exploits. This will be more meaningful later.
(*)Emagging mining explosives now sabotages them so that they blow up in the user's face, rather than unlocking the targets they're usable on.
(*)Traitor Miners now get special job-based syndicate items: hacked low and high yield mining explosives. These behave as old emagged mining explosives.
(*)Both hacked and emagged mining explosives now have their own added descriptions upon examine, to vaguely reveal that something is different about them.
(*)Mind Slave traitor item telecrystal cost has been increased threefold.
(*)RIG suits now actually protect against radiation, as in the blowout random event, and nuclear reactors, etc.
(*)Engineering space suits are now twice as slow to move around in when walking, and are immensely slower when traveling through space. Examine desc updated to reflect this.
(-)
(t)tue sep 27 11
(u)JackMassacre
(*)Traitor roles are now chosen before job roles instead of vice versa. If you are chosen as changeling or traitor, you cannot then be chosen as AI, Cyborg, HoS, or Security, and revheads cannot become those or any head of staff position. However, if you are not chosen as a traitor type, you can now still become one of those jobs. If you want to reliably be chosen for those jobs, simply turn off your "be traitor?" option in preferences for the relevant mode.
(*)Clarified some random event AI laws, cleaned up some logical contradictions, fallacies, and loopholes in them as well. Added an excessively wordy new one.
(*)Doubled the chance that mining a (?) block will yield uqill or telecrystal as opposed to cytine.
(*)Fixed even more game mode checks that weren't accounting for the Head Surgeon position as a head of staff.
(*)Fixed teleport beacon exploit that was still allowing players easy entry into syndicate and wizard stations. Thanks to nice, honest players for admitting to this bug after being carefully and politely threatened.
(*)Mind implant use is a lot more obvious to admins in logs now.
(*)A bunch of additional admin options added for easily spawning human mobs of every job type, both genders.
(*)Moving inside of the DNA scanner in genetics will now close the console window if you have it open. You should require a partner in Science if you want to alter your own DNA.
(*)Attempting to Mind Slave implant someone who already has a security implant will fail, giving both target and user a failure message.
(-)
(t)tue sep 20 11
(u)JackMassacre
(*)The emergency shuttle in wizard mode will now fail to arrive the first time if called before the 20 minute mark, but will always succeed the second time. This should give the wizard more time to complete his objectives if dealing with a crew of pansy little girly coward spaceboys.
(*)Preliminary human NPC class expansion with fairly convincing combat and arrest behavior.
(*)Tripping on foam will be slightly less stunning now, in accordance with sanity.
(*)Firing a gun from point blank will no longer use up double the ammo/charge.
(*)You will now attempt a point blank shot on any intent other than 'help', rather than only on 'harm'.
(*)A point blank shot's extra stunning time has been cut in half, since it was previously excessive.
(*)Reloading a gun with ammunition will give a success message now.
(*)Even more cases of crates trapping buckled-in folks, bugging them out, have been eliminated.
(-)
(t)tue sep 13 11
(u)JackMassacre
(*)A message is now displayed when someone is successfully hit by gunshot or other projectile weapons, unless the weapon is silenced.
(*)Disability blocks in genetics should be a bit more difficult to isolate now. Why? Who knows.
(*)Fixed some random event AI laws for spelling errors, ambiguous wording, and conflicts with default laws.
(*)Fixed Flash not displaying blind message properly on its final use upon burning out.
(*)Added some warning messages when various items are used if they are empty of necessary reagents.
(*)Fixed crates scooping up people who are buckled to beds and chairs, causing buggy problems.
(*)Added warning messages when fire damage is applied to people with fire immunity superpower.
(*)Cloakers were not properly being decloaked when shot with projectile weapons. Now they are, and there's a visible message too.
(*)Even more new and improved logs, warnings, and options to aid Admins in dealing with rule breakers.
(-)
(t)mon sep 05 11
(u)AngriestIBM
(*)Cyborgs/Eyebots can now use ";" to use the radio, like everyone else!
(*)Also if your radio mysteriously stops working as an eyebot, try opening the radio panel. That should fix it. I hope.
(-)
(t)sun sep 04 11
(u)JackMassacre
(*)Slipping on wet surfaces probably shouldn't stun for half an hour. So now it doesn't.
(*)Aliens no longer receive starting message that part of their goal is to kill the AI, since it isn't.
(*)Wizards no longer receive objectives to kill other wizards.
(*)Nuke mode syndicate radio headsets should always be visible now.
(*)Random event AI laws no longer refer to "The Mailroom".
(*)Admin-spawned syndicate attack forces come properly equipped, and clothed now.
(*)Various continuing additions to admin tools for monitoring and busting potential griefers.
(-)
(t)fri sep 02 11
(u)JackMassacre
(*)Nuke mode syndicates now get their own default radio channel accessible with :h. Organized.
(*)Revhead sorting wasn't checking if a candidate had already been chosen, resulting in one person filling multiple revhead slots. Fixed.
(*)Several checks still weren't taking the newish Head Surgeon position into account as a head of staff. Rectified.
(*)Communication intercepts were reporting disabled game modes as possibilities, often 100% confirming the current mode. Remedied.
(*)Admin-appointed wizards now work properly in wizard mode for determining round status. Wizardized.
(-)
(t)fri sep 02 11
(u)Pacra
(*)Monkeys reagent-holding units decreased. No more supermonkeys, CHEMISTS.
(*)Human reagent-holding units slightly increased.
(*)Ethanol effects tweaked to reflect changes. Feedback appreciated.
(*)Pro Puffs now much more useful to the average crewmember!
(*)Fingerprints are added whenever you deactivate/reactivate security cameras.
(*)Stop whining about the rad-crossbow 'nerf,' the crossbow owns now ok
(-)
(t)wed aug 31 11
(u)JackMassacre
(*)Brig timers can now be examined to show time remaining, if any.
(*)Wizards lost their goofy little radios, gained actual spellbooks.
(*)Rad poison crossbow shot cost and recharge rate tweaked. Might be slightly more sane now.
(-)
(t)mon aug 29 11
(u)JackMassacre
(*)New Character Setup options: "Be Alien?", "Be Changeling?", "Be Revolution Leader?", "Be Wizard?". The previous choice of "Be Syndicate?" is replaced by these for their appropriate modes, but "Be Syndicate?" is still used for Nuke and Traitor modes.
(*)Wizards no longer take up job slots, and don't start with job-specific items anymore.
(*)Valid wizards are now selected regardless of the player's job preferences.
(*)Wizards now start with a Spellbook Uplink instead of a PDA, which only works for the wizard it spawns for.
(*)Wizard mode info picture and Wizardry 101 texts have been updatedwhere necessary.
(*)Revolution leaders should ALWAYS spawn with a flash now, or so help me #$!&.
(*)Flashes now have a different name and look when they burn out, and give a more noticeable message when it happens.
(*)Even more useful tools for admins to monitor rulebreakers with. You cannot hide.
(-)
(t)sun aug 28 11
(u)JackMassacre
(*)Nuke mode shouldn't spaz out and cause everything to stop working anymore.
(*)Neutered unstoppable every-superpower-in-10-minutes geneticist griefers.
(*)Robotics bay gets its own cargo transporter. Send those piles of crates back to the QM! Send mining the gift of borgbuddy!
(*)Examining cyborgs now shows you if they have a power cell inserted, and what the charge is at. Don't leave your robofriends without power!
(*)Cyborg burn damage is fixed by replacing exposed wires, which now show their damage in examine.
(*)Fixed a bunch of items not showing up in your hand properly when plucked out of things.
(*)Added several additional layers of anti-grief notices for admins to bust you with. We're watching you, jerks.
(*)Fixed cloaking device exploit.
(*)Several Wizard movement spells now put the caster out if they are on fire.
(-)
(t)mon aug 22 11
(u)JackMassacre
(*)Robotics manufacturers now produce high capacity power cells. YOU STILL HAVE TO CHARGE THEM BEFORE USE.
(*)Cyborg teleport upgrade functions via teleporter beacons now, only costs 250 charge per use, and has a much cheaper material cost to manufacture in Robotics.
(*)The progress bar for charging a power cell in the Cell Charger wasn't displaying properly. Fixed.
(*)Teleportation no longer works while you're unconscious/dead.
(*)Wizard teleportation scroll requires wizardliness to read.
(*)Wizards can now magically resist being forcibly transformed.
(*)Wizard mode victory and loss messages fixed.
(*)Hand teleporters cannot easily get you into the wizard and syndicate stations anymore.
(*)Cyborg teleport upgrade mineral cost fixed, and upgrade moved down to tier 2.
(-)
(t)sun aug 21 11
(u)sniperchance
(*)Greatly improved the fart/poo sound.
(*)Also I'm the one that originally put in (and took out) religions/fatties, lmao f*ckin owned u stupid nerds - xoxo, sniper
(-)
(t)tue aug 16 11
(u)JackMassacre
(*)Exciting, new, streamlined Job Ban options for administrators!
(*)Empty wizard objectives almost certainly fixed.
(*)Wizards now start with Magic Missile as well as Phase Shift, and learn 4 additional spells of their choice.
(*)Wizard spells Magic Missile and Ice Burst no longer spam spell chants when there are no valid targets.
(*)Wizards now start with the Teleportation Scroll, Wizardry 101, and SPACE GRIMOIRE papers in their inventories.
(*)Wizard spell Doppelganger now has a spell chant.
(*)Wizard Shuttle revamped a little bit.
(*)New Wizard spell: Spell Shield.
(-)
(t)mon aug 15 11
(u)JackMassacre
(*)Wizard spells Ice Burst and Magic Missile should no longer hit or target ghosts.
(*)Wizard spell Clown's Revenge can no longer target cyborgs, which it didn't affect anyway.
(*)Wizard staff must be held in hand to cast at full power, rather than simply carried.
(*)Wizard spell Soulguard shouldn't stick you in a wall or outside of the wizard shuttle anymore.
(*)Wizard spells Teleport, Soulguard, and teleport scroll effects work off Z level now.
(*)Wizard's summoned golem only attacks people now. Future wizard minions will generally follow suit.
(*)Blind spell adjusted down, slightly. Should be just right.
(*)New Wizard spell: Animate Dead.
(-)
(t)sun aug 14 11
(u)JackMassacre
(*)Wizard-summoned golems won't attack each other anymore.
(*)Weakened wizard spell effects without the staff tweaked up very slightly, all around.
(*)Wizard spell "Enchantment: Soulguard" now puts you out if you're on fire.
(*)Blind and Blink wizard spells tweaked up a bit.
(-)
(t)sat aug 13 11
(u)JackMassacre
(*)Cyborgs now get a message when their interfaces are locked/unlocked.
(*)Wizard staff check wasn't working at all. Fixed, and the staff is vital now.
(*)Clown's Revenge wizard spell had its range reduced to adjacent tile.
(*)Warp wizard spell had its range increased to any visible target.
(*)Knock wizard spell now opens closets and crates too, and causes cyborg head compartments to blow open, damaging them and exposing their brains.
(*)Blind wizard spell now briefly stuns the target, lasts twice as long, gives a visual effect, and displays a success message.
(*)Casting a spell without the wizard staff will give you a message about how it was weakened, and why.
(*)SPACE GRIMOIRE located in the wizard's shuttle updatedwith new spell descriptions.
(*)Head of Security and Security can no longer be chosen as wizards.
(*)Wizards no longer start with any ID card. Deal with it.
(-)
(t)wed aug 10 11
(u)JackMassacre
(*)Wizard mode info picture updated. Read it.
(*)Wizard spell cooldown lists updated. They were very, very outdated and wrong.
(*)Fireball spell causes fire now, cools down a bit slower.
(*)Blind spell cools down much faster.
(*)Teleport spell now displays its number of uses left in the destination choice window.
(*)Spell descriptions improved all around.
(*)Wizard shuttle's Magix System IV computer can teleport you to the station. No more getting stuck on the shuttle.
(*)Wizard shuttle now comes with 2 papers you can examine for vital info: Wizardry 101, and the SPACE GRIMOIRE.
(*)Wizard sandals now magically protect against the awful power of Segway Impacts.
(-)
(t)wed jul 20 11
(u)Procitizen
(*)Fixed t-ray scanners not showing cables
(*)Increased cloaker "reveal time" on t-rays
(*)Added more space to the Head Surgeon's office
(*)Linked Robotics and Head Surgeon's office
(*)Decreased cost of Electrician and Chemist traitor items
(*)Fixed a lot of broken round start wiring
(-)
(t)tue jul 19 11
(u)Pacra
(*)45-minute evacuation traitor objective has been removed. New replacement objectives soon.
(-)
(t)wed jul 13 11
(u)AngriestIBM
(*)Finally ported the disposal pipe dispenser. It's only about a year and a half late!
(-)
(t)sat jul 09 11
(u)Procitizen
(*)<b>New Job:</b> Head Surgeon, King of Medbay
(*)You can hide in crates if you're lying down, good luck getting out though!
(*)Floor tiles nerfed a bit
(*)Buttbots will now adopt the original butt's skin color. apologies to those offended
(-)
(t)wed jul 06 11
(u)Procitizen
(*)Zombie disease is dumb pathology is dumb you're dumb if you make a "Procitizen removes YET ANOTHER THING" comment in OOC
(*)Fixed a bunch of reagents not calling updatehealth
(-)
(t)fri jul 01 11
(u)Nannek
(*)Reverted my previous update. Though bear in mind if you give out all access ids just to be a dick then you'll be jobbanned from all head roles.
(-)
(t)thu jun 30 11
(u)Nannek
(*)With the card access computer, you can no longer give people access to whatever your ID doesn't have. So if you're HoP you can no longer give people all access IDs, but only whatever your ID has.
(-)
(u)BurntCornMuffin
(*)Holy shit, I'm back. Also, I did a thing.
(-)
(u)AngriestIBM
(*)The PDA medical scanner automatically updates the medical records (Does anyone ever use those?).
(-)
(t)tue jun 28 11
(u)sniperchance
(*)Owns Syndrome now less obnoxious in ingame chat
(*)Removed the ability to shove a harmonica up your ass
(-)
(t)sat jun 25 11
(u)Nannek
(*)You know what isn't broken any more? Alien!
(*)If you initially observe you will no longer be eligible for alien selection
(*)Fixed a few bugs with alien mode
(*)Added in a menu to the admin panel which allows you to track aliens and heads
(-)
(t)fri jun 24 11
(u)AngriestIBM
(*)You know what isn't broken any more? Nuke!
(*)Note: If nuke somehow still breaks please report it immediately.
(-)
(t)thu jun 23 11
(u)Nannek
(*)Decreased the speed at which weeds spread
(*)Added alien weakness to fire, they take double the damage humans take
(*)Alien weeds now only try to spread once and then don't run through their life proc again.
(*)Decreased the amount of aliens possible to spawn at the beginning of a round
(*)Fixed a few of the win conditions for this mode and revolution
(*)Alien's plasma decreases when they're not standing on weeds.
(*)If the queen dies another queen can be made, though this will cost 1000 plasma and .
(-)
(t)wed jun 22 11
(u)Nannek
(*)Made the aliens be able to see pipes hidden in turfs when crawling through them.
(*)Added the alien game mode as an admin only game mode.
(*)Fixed a problem where the icons were messed up when pipe crawling
(*)Increased the amount of damage aliens do to humans
(*)The shuttle can't be called during alien mode
(-)
(t)tue jun 21 11
(u)Nannek
(*)Hunter aliens can now climb through the disposal pipes.
(*)Tweaked the alien game mode slight.
(*)Reintroduced the alien queen mob subtype and removed it from the class selection
(-)
(t)mon jun 20 11
(u)Nannek
(*)Added placeholder items for fuel rods, control rods and neutrons
(*)Fixed a problem where when you open a bombs valve it would wait for a while until it blew up.
(-)
(u)LLJK-Mosheninkov
(*)Reactivated four medals: Black and Blue, Expendable, Manhattan Project, MISSION COMPLETE
(-)
(t)tue jun 21 11
(u)I Said No
(*)New chef recipe: Swedish Meatballs.
(-)
(t)sun jun 19 11
(u)Nannek
(*)Increased the amount of damage toxins, co2 and exposure to space does to you.
(*)You can no longer talk if there is no oxygen
(*)You can now use analyzers on pipes to see their contents/temperature.
(*)Made changes to alien weeds, meaning they can be destroyed and how they spread making their spreading more efficient. They also break open doors which are not bolted
(*)Increase the amount of plasma that aliens get from weeds
(*)There can only ever be one alien queen at a time
(*)updatedthe spawning system that picks from dead players to include dead players which are not only ghosts, but people still in their bodies
(*)Decreased the amount of time it takes for you to get up after resting
(*)Added a test room which allows new features to be tested on the server without disrupting the game currently in progress
(*)Added in the Barmans ability to taste what he drinks, meaning he'll get a message about what the drink contains
(*)Added a bunch of new alien critters so that if there are no dead people to pick from, an alien critter will be created instead. This will go through the same larva -> humanoid process.
(*)Decreased the amount of time it takes for a larva alien to evolve into a larger alien
(*)Disable an admin toggle on aliens being in game in preparation for a new game mode
(*)Modified the layers of the alien items so that they don't look out of place so much.
(*)Added a few more information options to the admin banning panel showing peoples computer address and ips
(*)Other miscellaneous fixes
(-)
(t)thu jun 16 11
(u)Hobnob
(*)Couple of new traitor items for scientists. Metalfoam will now fill in holes in the floor.
(-)
(t)mon jun 13 11
(u)Hobnob
(*)AI can now click firedoors to open/close.
(-)
(t)sat jun 11 11
(u)Procitizen
(*)Added a new effect for blowouts
(*)Tweaked radiation so it doesn't always stunlock you at some point
(*)Fixed brig cells not opening for security
(*)Removed Detective's security access
(*)The HoP is the HoP and not security with better access
(*)Fixed boxing ropes
(-)
(t)mon jun 06 11
(u)Hobnob
(*)Made initropidril harder to obtain by making the precursors metabolize faster in the body. Moved an ingredient to a safer place.
(-)
(t)fri may 27 11
(u)AngriestIBM
(*)Added a work-around for a bug where some players using the latest byond version (482.1091) could not successfully enter text into a computer terminal. If you are running this version, there should be a manual enter button by the input bar.
(*)Please contact a coder (Read: Adminhelp it) if this still does not work for you!
(-)
(t)sun may 08 11
(u)Procitizen
(*)Made it so the SMES cells aren't automatically set up at the start of a round. Hopefully the engineers know what they're doing!
(-)
(t)thu may 06 11
(u)Pacra
(*)New traitor objectives: Unleash the singularity, destroy the captain's bonsai tree. If you get them, make sure they work correctly, tia
(-)
(t)tue may 04 11
(u)Pacra
(*) Detective .38 rounds available at QM manufacturer. How? HMMMM
(*) Engineeers can no longer zip around the station in their ungainly spacesuits like they are some kind of pro space ballerinas
(-)
(t)mon may 03 11
(u)Pantaloons
(*)Due to overcrowding and budget constraints, CentCom has mandated that solitary confinement cells be limited only to the most dangerous of prisoners. All other crew members should be detained in the general population cell.
(-)
(t)mon may 03 11
(u)Pacra
(*)Two new traitor items, a stronger pipebomb and "syndicate sauce." "Low-Yield Syndicate bomb" deleted.
(*)Traitor crystal costs changed, try it out, see what you think, give feedback.
(*)You can now ash out Pro Puffs in things like beer bottles to retain some reagents!
(*)other stuff, i forget
(-)
(t)sun may 02 11
(u)Pacra
(*)Module storage redone, new AI modules: MakeCaptain, notHuman, ConservePower.
(*)Two heating implements can now light cigarettes.
(*)New type of cigarette packet available at the dispenser.
(*)Magic missle reverted to unlimited targets.
(*)Traitor donk pockets now quite useful.
(*)Captain's space suit no longer useless.
(*)bonsai tree.
(-)
(t)sat may 01 11
(u)Dropsy
(*)Greatly reduced the chance to get kuru. Type consume over a corpse, expect your reputation to fall with all factions across the wastes (of space).
(*)The teleport spell now has limited uses (try guessing how many).
(-)
(t)sat apr 30 11
(u)Procitizen
(*)OFFICIAL LIST OF THINGS MDS HAVE THAT CLOWNS DONT (wip):
(*)maint access
(*)a soul
(*)??????
(-)
(t)fri apr 29 11
(u)Pacra
(*)Ice bolt's max targets now limited to 4.
(*)Magic Missle's max targets now limited to 5.
(*)Wizard is now hopefully less insanely powerful.
(*)Detective's lit cigs now face all four directions. YEEEAAAHHHH
(-)
(t)thu apr 28 11
(u)Pacra
(*)Fire resistance mutation now protects you from welders, napalm, and fire! wow!
(*)Electrician's traitor item no longer a joke/nigh-useless.
(*)AI satellite is now actually defensible! You will no longer be murdered as AI by an assistant with a pair of shoes without repercussion!
(-)
(t)mon apr 25 11
(u)Pacra
(*)Port-a-Brig can no longer be escaped from within.
(*)Syringe Gun is only obtainable as a Medical Doctor traitor-item.
(*)Electricians have lost Singularity (space suit) access, gained a traitor item.
(*)Certain traitor item costs and objectives have been tweaked.
(*)Miners now have access to their APC.
(*)Chef now has access to his Culinary Maintenance airlock.
(*)I spelled my name right this time.
(-)
(t)sun apr 24 11
(u)Procitizen
(*)You can swipe your ID cards on vending machines now! THANK GOD
(*)New things that you can transfer money from card to card with
(-)
(t)fri apr 22 11
(u)Procitizen
(*)Added a new thing in the metal sheet menu. What does it do?? What can you do with it??? I DON'T KNOW!!!!!!!!!!
(-)
(t)thu apr 21 11
(u)Dropsy
(*)Syndicates and rev leaders count as dead if they are turned into cyborgs, preventing rounds from lasting forever.
(*)Clowning spell works at touch range only.
(-)
(t)sun apr 11 11
(u)Procitizen
(*)The AI's second law is now "You must obey orders given to you by human beings based on the station's chain of command, except where such orders would conflict with the First Law." Fuck everyone for making me have to do this.
(*)Corpses will stop decomposing if they're in the kitchen's freezer. will maybe extend this to the morgue later
(-)
(t)tue mar 30 11
(u)Procitizen
(*)Wow nobody uses the changelog!!! what the hell
(*)Fucked with security so maybe it's less stupid? I don't know!
(-)
(t)thu mar 24 11
(u)I Said No
(*)The station is now assigned a rating depending on the score earned.
(*)In Nuke Mode, any operatives who are in the brig and are restrained/stunned count as arrested. Arresting all operatives ends the game with a crew victory.
(-)
(u)Procitizen
(*)Added a bottle of that "glowy blue shit they spray on blood from CSI" to the detective's office.
(-)
(t)wed mar 23 11
(u)I Said No
(*)Chemical mixtures can now be visibly (and audibly) told apart by their descriptions.
(-)
(t)tue mar 22 11
(u)sniperchance
(*)New hairstyles in Character Setup (Afro, Bieber, Bowl Cut, Parted, Ponytail)!! Holy shit!!!!
(-)
(t)thu mar 17 11
(u)I Said No
(*)The Seed Splicer in Hydroponics now works differently. It'll try to combine the best genes from both seeds. It isn't flawless, though!
(*)Mucked with the Be Captain/Be AI options a bit. Report any further/new bugs with them.
(-)
(t)tue mar 15 11
(u)Procitizen
(*)Use a glass/rglass sheet on a grille to put a window on top of it, oh boy!
(-)
(u)I Said No
(*)Solar Flare random event. Knocks out communications for a while.
(-)
(t)sun mar 13 11
(u)Procitizen
(*)Security got redesigned!!!! whine on the unban forums if you hate it
(-)
(t)sat mar 12 11
(u)Procitizen
(*)You now have the chance to spawn with a pen, a bottle of water, or nothing at all in your right pocket!!!!! WOW
(*)Chaplain gets a command to choose his religion now instead of the buggy ass popup menu at spawn
(-)
(t)fri mar 11 11
(u)Procitizen
(*)Added a bunch of lights outside of maint tunnel doors leading into workplaces.
(*)Plates in the kitchen to increase your immersion or whatever, break them over people's heads realistically!
(*)Fixed some map bugs who cares
(*)some more space gps stuff nobody will use lol
(-)
(t)thu mar 10 11
(u)I Said No
(*)Hydroponics:
(*)Plant pots now visibly show the water level. The coloured bar flashing is bad, otherwise it should be easy enough to figure out.
(*)Harvest time indicators are now two small flashing green lights either side of the water bar.
(*)A compost tank/mulcher you can stick unwanted produce in to make more fertiliser. Features drag/drop loading.
(*)Desaturated the grass in Hydro a bit to make the plants easier to see.
(*)A fun new type of weed (the pest sort of weed) and two new plant mutations.
(-)
(t)fri mar 04 11
(u)I Said No
(*)New Traitor Item: Signal Jammer. Radios within a 6 tile range of an active radio jammer will not function properly.
(*)Fish no longer do damage or stunning when used to slap someone.
(*)Cable coil can now be loaded into manufacturing units to get Pharosium.
(*)Meatballs are now much more socially tolerant.
(*)Fish fillet + dough now = Fishburger instead of a bread loaf.
(*)You can now pee and crap in drinking glasses again. God save us all.
(*)Hopefully fixed Nuclear mode not ending with the shuttle's departure.
(-)
(t)tue mar 01 11
(u)Dropsy
(*)You can now not only toolbox a random person to death, you can also eat them after the murder. Type consume over a dead body to commit space cannibalism but beware of Space Kuru!
(-)
(t)mon feb 28 11
(u)I Said No
(*)Couple of new speech description verbs for say. Low Health = "gasps", ... = "mutters", !! = shouts.
(*)The odds of hearing the dead have been greatly reduced. Don't bother trying to spam at the Chaplain from deadchat.
(*)Drinking alcohol now causes you to get gradually drunk over time, rather than being instant.
(*)An advanced state of drunkenness now causes you to sometimes shrug off melee hits and throw stronger punches.
(*)Plants will now show their sprouting state much sooner.
(*)Enhancing the production and maturation genes (into the negatives) should no longer have the opposite effect.
(*)Weeds should no longer arbitrarily stop growing.
(*)Dice and coins should fit in pockets now.
(*)You can now snip a grille twice with wirecutters to completely remove it.
(*)The sleep button should work now.
(*)Traitors should no longer be assigned to kill the same target multiple times.
(-)
(t)fri feb 25 11
(u)Procitizen
(*)Added a public market room so you can stop walling off the autolathe to sell your stolen security equipment or whatever.
(-)
(t)wed feb 23 11
(u)Dr. Melon
(*)Brig doors now cannot be closed without starting the cell timer.
(-)
(t)tue feb 22 11
(u)I Said No
(*)Hydro Satchels (now named Produce Satchels) can now carry all types of food. Chef gets one too.
(*)Click/drag/drop a satchel onto a table to dump out its contents onto the table.
(*)Chef's Processor can now be quickloaded with click/drag/drop.
(*)Cafe back doors are restricted to Barman (north) and Chef (south) access.
(*)The Lawyer has been disbarred for pounding his fist on desks and screaming at the top of his voice while court is in session.
(-)
(t)mon feb 21 11
(u)Procitizen
(*)The Mining Shuttle uses the new propulsion thrusters now! Yay???
(*)<s>Lobby music!</s>
(-)
(t)sun feb 20 11
(u)Procitizen
(*)Buttbot is no longer eternally visible :(
(*)Propulsion thrusters on the research shuttle are now more robust, you can take them apart with a screwdriver and a wrench!
(*)Fixed r-metal not stacking, make reinforced tables all up in dis
(*)The Syndicate Shuttle now has an outer outer door, only accessible by their agent cards (which they now spawn with). Fuck you, miners!
(-)
(t)fri feb 18 11
(u)I Said No
(*)Explosive/Killer Tomatoes are no longer growable.
(*)Spinach and Cabbage are gone. Lettuce is in.
(*)Thrown tomatoes no longer splat into blood. Eggs now splat if thrown.
(*)Chef can now rake through gibs to get more meat.
(*)Pizzas can now be cut into slices.
(*)A few hot new chef oven recipes.
(-)
(t)wed feb 16 11
(u)Procitizen
(*)Space GPS (still don't know how they work) tweak, they now have a toggleable tracking feature to locate other GPSes! Neato!
(-)
(t)tue feb 15 11
(u)Dropsy
(*)Security has been generously granted a prototype VR-prison containment unit.
(-)
(u)Dr. Melon
(*)Security has been fitted with an automatic physical prisoner release system in the normal cells. Say goodbye to having to hopelessly wander around the inside of security while you wait to be released! Just wait until your cell timer is up, and then take the fast lane to rehabilitation!
(-)
(t)sat feb 12 11
(u)Dr. Melon
(*)Refillable Sleepypens!? My God!
(-)
(t)sun feb 06 11
(u)Dropsy
(*)The HoS has been rehired, he's promised to be better this time.
(*)No more "stealth" Wizardry. Wizards require a robe and wizard hat at minimum to cast spells. The staff and sandals will boost your magic power.
(*)The NT station's floor based power generator proved ineffective. As a result it fell out of orbit, crashed into an asteriod, and blew up. Send compliants to dropsy@mytrashmail.com
(-)
(u)Procitizen
(*)The virtual fitness room has been shut down due to server fees and lack of funding. Those of you who bought a lifetime subscription to vfitness are fucked!
(*)Boxing arena returned to the fitness room
(-)
(t)fri feb 04 11
(u)Dropsy
(*)PMs from admins will now <font color="red">DEFINATELY</font> appear in a large broswer window. The lame excuse you didn't notice you were PMed is no longer valid.
(-)
(t)wed feb 02 11
(u)Procitizen
(*)The research shuttle's propulsion engines can now be destroyed from explosions and meteor impacts. The damage needs to be repaired before it can
be used again.
(*)Cargo/Research shuttles now have destroyable walls, again from explosions and meteor impacts, meaning shuttles aren't unbreakable doom fortresses in meteor anymore :(
(-)
(t)sat jan 29 11
(u)AngriestIBM
(*)Shocking grasp is no longer instant. Blame Elminster.
(-)
(t)thu jan 27 11
(u)I Said No
(*)Stills for the barman. Load apples, grapes, potatoes and mushrooms into them. Max capacity of 1000, you can also use the drag/drop like the Fabricator to load it quickly.
(*)Tanks (water, foam, welder fuel, etc) will now try to fill your item completely in one click rather than transferring 10 units a time.
(-)
(t)sun jan 23 11
(u)I Said No
(*)Hydroponics equipment tweaked a bunch:
(*)Seed Fabricator now works more similarly to the vending machine. It is also now hacked in the same manner.
(*)Reagent Extractor can now contain multiple ingredients at once, and gives more information than it used to.
(*)Gene Manipulator (which has been added to Hydroponics) now allows you to splice two seeds together to average out their genes.
(*)Seed Extractor is now much faster.
(*)Bunch of Hydro bugs fixed. Continue reporting any that occur though!
(-)
(u)Procitizen
(*)"Hello I am dumb and long past being funny please remove me" - a living wall
(-)
(t)sat jan 22 11
(u)Procitizen
(*)Congratulations chemists, you did it! Chemistry grenades are now traitor only. Now who's gonna kill the entire station and whine about being killed in adminhelp? :(
(-)
(t)fri jan 21 11
(u)I Said No
(*)Be Captain/Be AI should work properly now. Report any further bugs on the forum.
(-)
(u)Procitizen
(*)Vice Officers have been removed from the station security force and shipped off to Space Miami. Dang.
(-)
(t)thu jan 20 11
(u)I Said No
(*)Shipping via the QM shuttle now has a whole market system attached to it. QMs should check the new option on the ordering console.
(*)This also means it's worth shipping plant produce and ores again. hooray
(*)Cola, snack, coffee and cigarette vending machines now require money in the form of credit bills to be inserted before purchasing their wares.
(*)Not new, but a reminder: You can get said bills by going to an ATM and withdrawing cash.
(*)Added new items to vending machines.
(-)
(t)wed jan 19 11
(u)I Said No
(*)Switched the places of Hydroponics and Electronics for ease of access to the Chef.
(*)The budgets now start as 90,000 in the payroll and 10,000 in shipping.
(*)The Research Budget will no longer completely drain itself on the first thing that gets researched.
(-)
(t)tue jan 18 11
(u)sniperchance
(*)<b><i><font color="red">Janitor gets a new toy!!</font></b></i> - A ridable floor buffer that you can load with different chemicals.
(-)
(u)I Said No
(*)The station budget is now much more important!
(*)The Banking Control terminal in the bridge now does much more stuff than it used to.
(*)Quartermasters now run off a money-based Shipping Budget instead of supply points.
(*)Research speed is doubled if a Research Budget is set. This costs 5,000 credits per research.
(*)ATMs and the public Quartermaster console only require you to swipe your card now, instead of inserting it.
(*)Replaced water tank in Hydroponics with a high-capacity version.
(*)PDA Plant Scanner should work again.
(*)The station's barbers were fired due to an incident involving 32 pounds of pork and a NanoTrasen Rabbi.
(-)
(u)Procitizen
(*)<strong>THIS IS WHY WE CAN'T HAVE NICE THINGS:</strong> Merculite removed. You're on very fucking thin ice, chemists! :)
(-)
(t)mon jan 17 11
(u)I Said No
(*)Fixed some bugs with recipes giving the wrong item. Keep reporting these.
(*)Added a Cancel command to research consoles.
(*)When initiating research, the computer will now show you how long the research is predicted to take.
(*)Examining a Cyborg will now show you what module it has installed.
(-)
(u)Procitizen
(*)Thank you for trying out the NanoTrasen SUV suits! They were a complete success and as such have been removed from the game pretty much completely.
(*)Some radiation suits in the off-site areas and a few around the station.
(*)Engineering gets their space suits back, except now they're the engineering variant. woahhhhh
(-)
(t)sun jan 16 11
(u)Procitizen
(*)<s>The Singularity Core is now full of terrible radiation, use the SUV suits to not die in it!</s>
(*)Also some other stuff(??)
(-)
(u)I Said No
(*)Backend overhaul of Oven Cooking. One pertinent change: recipie ingredients no longer have to be loaded in a set order.
(*)Watering cans now hold 120 units, pour 60 units at a time, and refill 60 units at a time from water tanks.
(*)Not new but I should have mentioned it before: Plant pots now hold a total of 320 reagents. The max water before a plant is considered stunted is now 200, up from 120.
(-)
(t)sat jan 15 11
(u)I Said No
(*)Massive backend overhaul of Hydroponics. This should hopefully mean very little, but there may be bugs. Kindly report them tia
(-)
(t)fri jan 14 11
(u)I Said No
(*)You may now elect to not be the Captain or AI in your Character Setup Menu. Be sure to set your preferences accordingly!
(*)Some changes to Nuke mode. The game should now detect when operatives are captured in the v-brig and count them as dead.
(*)Nuke teams should now also scale to server population. One operative for every four players, to a maximum of five.
(*)Fixed Cyborgs being able to generate an infinite amount of modules.
(*)Fixed the Module Rewriter sometimes dipping below zero on the available modules count.
(*)Whole bunch of changes to the score system. Check the linked topic in the score panel for more detail.
(*)South solar panels should work properly now.
(*)Added some bits and pieces around the station that were requested. Mostly power cells.
(*)Ore Satchels now work slightly differently - on drag and drop, they'll only collect up the type of ore you drag/dropped instead of everything but rock.
(*)Added Hydroponics Satchels, and put all the Hydro Gear in lockers to neaten the place up a little.
(*)Added Multitool, Welding Mask, Lightbulb and Light Tube schematics to the generic Manufacturing Unit.
(*)Storage items (backpack, box, toolbox, belt, etc) in your inventory will now display their contents at the side of the screen rather than the middle.
(-)
(t)thu jan 13 11
(u)sniperchance
(*)Fixed beakers losing their contents on storage items fo realz.
(*)Welders no longer blow up when you drop them.
(-)
(t)wed jan 12 11
(u)I Said No
(*)Reverted Wizard back to the old format of ending when the Wizard dies.
(*)Allowed for multiple Wizards. (Note that this is what I said last time also. Pinch of salt.)
(-)
(u)Procitizen
(*)<strong>FUCK YOU:</strong> Prayers have been limited to the Generic chaplain only. The other ones get their shit. Fuck yall.
(-)
(t)tue jan 11 11
(u)I Said No
(*)Fixed beakers losing their contents when used on reagent extractors, disposal units, and blood/poo/etc.
(-)
(t)fri jan 07 11
(u)DrMelon
(*)The AI can project itself as a <s>hologram</s> EYEBOT, forfeiting the ability to track people and change cameras until it changes back.
(-)
(u)I Said No
(*)Added a light switch to mining station. It's by the south airlock.
(*)Replaced Cursed Girdles of Slavish Digging with 100% real stoat leather mining belts which can infact be taken off.
(*)Emagged Mining Charges no longer hate you and everything involving actually exploding.
(*)You can now debrain/rebrain cyborgs. After you unlock the panel with your ID, use a screwdriver instead of a crowbar.
(*)A SECRET!!! It's cyborg-related.
(-)
(t)wed jan 05 11
(u)I Said No
(*)Miners now start with a Miner's Belt and Optical Meson Scanners.
(*)Pickaxes, Powered Pickaxes, Power Hammers and Drills can be put on your belt slot. The Miner's belt also holds all of these things. Welp, that was pointless!!!
(*)The Plasma Cutter is now far more useful.
(*)Couple of new Manufacturing schematics that use Fabric. Load a jumpsuit/most oversuits into the manufacturer to make fabric.
(*)Mining score bonus reduced from x3 per ore to x2.
(*)Couple of new miscellaneous score criteria.
(*)Medical Cyborgs have some new tools to make them more useful.
(-)
(t)tue jan 04 11
(u)sniperchance
(*)Chem Grenades can now be attached to Timer/Proximity/Radio and Igniter assemblies to make Chemical Bombs.
(*)Chem Grenades now require a grenade fuse to be assembled, instead of the old way.
(-)
(t)mon jan 03 11
(u)I Said No
(*)New upgrades for Cyborgs: Optical Meson, Optical Thermal, and Charge Expansion.
(*)Recharging Stations now recharge Cyborgs significantly faster. In addition, a specific research can also double the charge speed.
(*)Fire Alarms no longer look like starry gibberish to Cyborgs.
(*)Mining Cyborgs now have a single high-capacity Ore Satchel rather than two.
(*)Fixed modules and upgrades appearing in the corner of the cyborg's screen.
(*)Ore Satchels can now be used on crates (whether open or closed) to dump the contents inside.
(*)Added Blood Monitor implant to Robotics Research. It will alert the host to any disease infections.
(-)
(t)sat jan 01 11
(u)DrMelon
(*)The chef can now bake cakes!
(-)
(u)I Said No
(*)New Cyborg types: Atmospherics, Chemistry, and Vendor.
(*)New Cyborg upgrade: Repair Pack.
(*)Robotics Research changed around slightly.
(*)Cyborgs can now open/close crates and lockers, and can no longer lose their items on tables, racks, or disposal units.
(*)They also no longer need to charge batons, tasers, RCDs and Cargo Transporters. Using these items now consumes the cyborg's cell charge.
(-)
(t)fri dec 31 10
(u)Procitizen
(*)The boxing ring has been replaced by VR fitness simulations. Kill each other without actually dying!
(*)Also in VR fitness is a b-ball arena, to go alongside Sniperchance's amazing basketball shit. hi5 dude!!!
(-)
(t)wed dec 29 10
(u)I Said No
(*)Mining Outpost has been changed around a bit. It has a conveyor belt now.
(*)Cerenkite will now give you radiation poisoning if handled without protection.
(*)Erebite will now explode if exposed to explosions or fire.
(*)Mauxite and Pharosium can now come in rare Dense Veins. They are harder to mine but give more ore.
(*)You can now eject ores from Manufacturing Units.
(*)Two new score criteria: Ore Mined and Cyborgs Constructed.
(-)
(t)mon dec 27 10
(u)Dr. Melon
(*)The Chemical Dispenser doesn't scroll back to the top anymore.
(*)The Chemmaster now allows you to make multiple pills at once.
(-)
(u)I Said No
(*)Miners now start on the Mining Outpost. There are also three of them now as opposed to two.
(*)The extra miner has been taken out of the Cargo Bay's budget. There are only two QMs now.
(*)It turns out Solar Panels don't work in a large field full of light-blocking asteroids. Outpost now runs on furnaces and starts with some Char.
(*)The Asteroid Field is much edgier now.
(*)Cytines now come in many different colours, and don't change name anymore.
(*)Miners can now manufacture Power Hammers as a step between Powerpicks and Drills. They weaken rock tiles. Don't hit explosives with them!
(*)Char and Molitz have been softened. They can now be mined with the regular pick again.
(-)
(t)sun dec 26 10
(u)I Said No
(*)Cyborg Recharger for the mining station.
(*)Cargo Teleporter Pad for Robotics.
(*)Geological Scanners now mark the presence of gems for one minute after use.
(*)Cytines are now much more colourful. Cosmetic change only, but hey. Gems are meant to be pretty, right?
(-)
(t)fri dec 24 10
(u)I Said No
(*)Are those stockings in the bar and cafe? Why yes, I believe they are.
(-)
(t)thu dec 23 10
(u)AngriestIBM
(*)Devstation fell down some stairs and became a sad sack of tears.
(*)As such, it has been replaced. Forever. Merry Xmas!!
(-)
(u)I Said No
(*)Geological Analysers now mark out unusual tiles with a ? when taking a reading. The marks last for one minute and can only be seen by the user.
(*)Geological Analysers can now be used on rock tiles to see what they contain.
(*)Fixed Ore Satchels.
(-)
(t)wed dec 22 10
(u)I Said No
(*)Robotics Research is now available from Robotics (obviously). Four tiers, more stuff to come.
(*)Janitor Cyborgs should no longer be invisible.
(*)Geological Scanners now also detect "Sedimentary".
(*)You will now recieve a visible message whenever jobbans are placed or lifted.
(*)Dead Rock Worms no longer turn invisible.
(*)The Volatile Rock mining event now works a bit differently. Better run away!
(*)Miners can now examine asteroid tiles to see what is in them.
(*)Pharosium more common, Char less common, Syreline now visibly distinct from Pharosium.
(*)Ores now have different strengths. Upgrade your tools if you can't mine something.
(*)Ore Satchels now work a bunch of ways (and now hold 20 ore total). Click ore on the satchel, click the satchel on the ore, or drag+drop an ore onto the satchel.
(*)Mining Cyborgs now get two Ore Satchels.
(*)Satchel.
(-)
(u)Harmar
(*)Russian revolver now has a spinning cylinder, doesn't blow apart when you use it, and can be reloaded. Fun for the whole family!
(-)
(t)tue dec 21 10
(u)I Said No
(*)Mining Fabricators no longer dispense Powered Picks for cheap.
(*)Powered Picks now make a much wussier noise when unpowered.
(*)Laser Drills should now correctly extract more exotic ores.
(*)Cyborgs now visibly show damage, and will give a noticeable cue and self-destruct on death.
(-)
(t)mon dec 20 10
(u)Harmar
(*)Russian roulette is now more like its exciting real life counterpart.
(-)
(u)ProcitizenSA (kinda)
(*)<b>ATTENTION STATION SECURITY</b>: The following is a message from SecuTech security. <i>Thank you for trying SecuTech Virtual-Reality (VSPACE) Prisoner Containment Unit�. We hope you enjoyed your trial, but your evaluation copy has expired. Please register and purchase SecuTech Virtual-Reality (VSPACE) Prisoner Containment Unit� to continue. Thank you and have a secure day. (NT vbrig will keep on keepin on)</i>
(-)
(t)sun dec 19 10
(u)I Said No
(*)Manufacturing Units (the autolathe replacements) are now hackable.
(*)Miners now have a bunch of new gear.
(*)Miners start with worse gear than they used to have, but can get better stuff by mining.
(*)Furnaces added to Engineering and Miner's Station. They consume char, plasmastone, most clothing, and people.
(-)
(t)sat dec 18 10
(u)I Said No
(*)Removed "Wrongful Arrests" score criteria due to unpopularity.
(*)Hopefully fixed bug of score panel not popping up for ghosts.
(*)Added ingame links to the wiki and forum. Look at your commands panel.
(-)
(t)fri dec 17 10
(u)I Said No
(*)Changes to the Cyborg Panel. It now shows your status as well as your items.
(*)Changed the equipment of several cyborgs to fit their roles better.
(*)Added Cell Cables item to Standard and Engineer cyborgs. Use them on APCs to give them your power.
(*)Fixed the Captain's Quarters not being properly powered.
(*)Did no other stuff to nothing for absolutely no reason at all.
(-)
(t)thu dec 16 10
(u)DrMelon
(*)NT Weapons are fixed again.
(*)Pistolwhipping and revolvers are fixed again.
(*)NT Armoury area expanded.
(-)
(u)I Said No
(*)The asteroid belt's ore composition was shifted around somewhat.
(*)New autolathe/robotic fabricator replacements. They use ores/metal/glass.
(*)NT Armoury area expanded.
(-)
(t)mon dec 13 10
(u)I Said No
(*)A couple of new asteroid ores.
(*)The Mining Outpost has been renovated somewhat.
(-)
(t)sat dec 11 10
(u)I Said No
(*)Roboticists, Doctors and Geneticists can use examine on a brain to tell if it is still useful for cyborging.
(*)Miners now have Drills for safely mining Erebite.
*/
/**
* Chemicompiler
* v1.0 By volundr 9/24/14
* This device is a programmable chemistry mixing and heating device.
* The javascript code to run the frontend is in browserassets/js/chemicompiler.min.js
* which is minified javascript from browserassets/js/chemicompiler.js
* If you make changes to the uncompressed javascript, you'll need to install node.js,
* and run `npm install -g uglify-js`
* then run `uglifyjs browserassets/js/chemicompiler.js -c > browserassets/js/chemicompiler.min.js` to rebuild the compressed version.
*/
// data pointer
// data
// instruction pointer
//Registers
// Source register
// Target register
// Amount register
// Saved!
//var/code = buttons[buttId]
//boutput(world, "Executing CBF code: '[code]'")
/* attack_self(mob/user as mob)
panel()*/
//boutput(world, "calling window func [function] with data: '[url_encode(data)]'")
// ~ means don't allow reading the source code
// data pointer
// data
// instruction pointer
//Registers
// Source register
// Target register
// Amount register
// Instruction limit reached.
// RAM limit is 1024 bytes.
// RAM limit is 1024 bytes.
//if(",") // disabled input instruction from BF
//failed to find matching brace...
// Transfer commands delay by 1/4 second per ml.
// Invalid source id.
// Invalid target id.
// No reservoir loaded in source
// No reservoir loaded in target
// Invalid reservoir id
// No reservoir loaded in specified position
//lol you wacky fuck
// Invalid temperature value
// HTML is built only once, via New() -- all subsequent updates are done using javascript. Slick.
// lol butts
//var/datum/tag/firebug/fb = new
//htmlTag.addToBody(fb)
// Taking a res out
// Putting SOMETHING in
//putting a reagent container in
/**
* beep codes
* loud:
* 1: Invalid sx or tx value
* 2: Instruction limit reached
* 3: No container loaded at source or target
* 4: Invalid temperature value
* 5: Code is protected, cannot load
* soft:
* 1: done executing
* 2: code saved
*/
// Invalid source or target id.
// No reservoir loaded in source or target
// No reservoir loaded in source or target
// Transfer commands delay by 1/2 second per ml.
// Generate pill
// Generate vial
// Invalid reservoir id
// No reservoir loaded in specified position
//lol you wacky fuck
// Invalid temperature value
// Ok now heat this bitch
// Relay kicking on
// Relay kicking off
///////////////////////////////////////////////////////////////////////////////////
//If i somehow could add something that sets the temp of all reagents to the average and calls their temp reactions
//in the update_total_temp , without causing an endless loop - i could have the reagents cool each other down etc.
//Right now only cryostylane does that kinda stuff because its coded that way. So yup. Right now you have to code it.
// Exadv1: reagent_list is now an ASSOCIATIVE LIST for performance reasons
//SpyGuy: Testing out a possibility-based reaction list
//Set internally to prevent reactions inside reactions.
//(Inexact) description of the reagents. If null, needs refreshing.
//Do not react. At all. Do not pass go, do not collect $200. Halt. Stop right there, son.
//Calls the temperature reaction procs without changing the temp.
//This is what you use to change the temp of a reagent holder.
//Do not manually change the reagent unless you know what youre doing.
//Cap for the moment.
//Wire: Fix for Division by zero
//if(istype(current_reagent, /datum/reagent/disease))
// target_reagents.add_reagent_disease(current_reagent, (transfer_amt * multiplier), current_reagent.data, current_reagent.temperature)
//else
// this was missing. why was this missing? i might be breaking the shit out of something here
// on_transfer may murder the target, see: nitroglycerin
//We magically prevent all reactions inside ourselves.
//if(ismob(my_atom)) return //No reactions inside mobs :I
//This shouldn't happen but when practice meets theory...they beat the shit out of one another I guess
//total_temperature needs to be lower than absolute value of this temp
//Not the right temp.
//Min / max temp intervals
// TODO: CONSIDER: reactions should probably occur if temp >= req temp not within bound of it
// Monkeys: Did this, just put a required_temperature as negative to make the reaction happen below a temp rather than above.
//This will mean you can have < 1 stuff not react. This is fine.
//Fuck you, ghosts
// Ideally, we'd like to know the contents of chemical smoke and foam (Convair880).
// don't add anything that modifies the speed before this check
//We might be inside a thing, let's tell it we updated our reagents.
//Experimental structure
// trigger inhibited reactions
// errrr
// lol this caused brute damage
// drsingh attempted fix for Cannot read null.volume, but this one makes no sense. should have been protected already
// Don't put spawn(0) in the below three lines it breaks foam! - IM
// use current_reagent.reaction_obj for stuff that affects all objects
// and reagent_act for stuff that affects specific objects
// we want to make sure its still there after the initial reaction
// These spawn() calls were breaking stuff elsewhere. Since they didn't appear to be necessary and
// I didn't come across problems in local testing, I've commented them out as an experiment. If you've come
// here while investigating INGEST-related bugs, feel free to revert my change (Convair880).
//spawn(0)
//if (current_reagent) //This is in a spawn. Between our first check and the execution, this may be bad.
//spawn(0)
//if (current_reagent)
//spawn(0)
//if (current_reagent)
//Doesnt fit in. Make it disappear. Shouldnt happen. Will happen.
//Experimental reaction possibilities
// I removed a check if reagent_list existed here in the interest of performance
// if this happens again try to figure out why the fuck reagent_list would go null
// redirect my_atom.on_reagent_change() through this function
// add will be 1 if reagents were just added
// mark the description as needing refresh
// li'l tiny helper thing vOv
/////////////////////////
// procs for description and color of this collection of reagents
// returns text description of reagent(s)
// plus exact text of reagents if using correct equipment
// Report nothing about the reagents in this case
// check to see if user wearing the spectoscope glasses
// or is a chem-borg
// if so give exact readout on what reagents are present
// rebuild description
//desc+= "([c.r],[c.g],[c.b];[c.a])"
// if only have solids present, don't include opacity text
// returns the average color of the reagents
// taking into account concentration and transparency
// weigh contribution of each reagent to the average color by amount present and it's transparency
// now divide by total weight to get average color
//returns whether reagents are solid, liquid, gas, or mixture
///////////////////////////////////////////////////////////////////////////////////
// Convenience proc to create a reagents holder for an atom
// Max vol is maximum volume of holder
// Todo not sure about this layer
// Removed quite a bit of of duplicate code here (Convair880).
///////////////////////////////////////////////////////////////////////////////////////////////////
// The chemistry APC was largely meaningless, so I made dispensers/heaters require a power supply (Convair880).
///////////////////////////////////////////////////////////////////////////////////////////////////
// The chemistry APC was largely meaningless, so I made dispensers/heaters require a power supply (Convair880).
// Reagent Groups
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//R.total_volume) we can't move all of the reagents if it's >100u so let's only move 100u
// get the pill name from the user
// get the pill volume from the user
// maths
// round with a single parameter is actually floor because byond
// invalid input
// create a pill bottle
// get the pill name from the user
// get the pill volume from the user
// maths
// round with a single parameter is actually floor because byond
// invalid input
// create a patchbox
/////////////////// //////////////////////////
// Mob or object // -------> // Reagents var (datum) // Is a reference to the datum that holds the reagents.
/////////////////// //////////////////////////
//The reaction procs must ALWAYS set src = null, this detaches the proc from the object (the reagent)
//so that it can continue working when the reagent is deleted while the proc is still active.
///Fluids now have colors
// The range at which this disperses from a grenade. Should be lower for heavier particles (and powerful stuff).
// Volatility determines effectiveness in pipebomb. This is 0 for a bad additive, otherwise a positive number whose square is added to explosion power.
// fuck off chemist spam
// if reagents are at or above this in a mob, it's an overdose - if double this, it's a major overdose
// this much goes away per tick
//if this reagent can enter the bloodstream through simple touch.
//If this does penetrate skin, how much should be transferred by default (assuming naked dude)? 1 = transfer full amount, 0.5 = transfer half, etc.
// how many credits this is worth per unit
// If this is a poison, it may be useful for poisoning the blob.
//By default we do nothing.
//By default we have a chance to transfer some
//of the reagent to the mob on TOUCHING it.
// i would set up a proc for this but this is the only place that adds addictions
//By default we transfer a small part of the reagent to the object
//if it can hold reagents. nope!
//if(O.reagents)
// O.reagents.add_reagent(id,volume/3)
//By default it slowly disappears.
//if(M && M.stat == 2 && src.id != "montaguone" && src.id != "montaguone_extra") M.reagents.del_reagent(src.id) // no more puking corpses and such
// if there's ever stuff that all drug overdoses should do, put it here
// for now all this is used for is to determine which overdose effect will happen
// and allow the individual effects' scale to be adjusted by severity in one spot
//Wire: Fix for shitty fucking byond mixing up vars
// NOTE: When this proc is invoked, the volume of the reagent will equal the total volume of this reagent.
// Thus:
// - the amount of this reagent in source before transfer = src.volume
// - the amount of this reagent in target after transfer = trans_amt
// - the amount of this reagent in source after transfer = src.volume - trans_amt
// reagent state helper procs
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*helldrug
name = "cthonium"
id = "chtonium"
description = "***CLASSIFIED. ULTRAVIOLET-CLASS ANOMALOUS MATERIAL. INFORMATION REGARDING THIS REAGENT IS ABOVE YOUR PAY GRADE. QUARANTINE THE SAMPLE IMMEDIATELY AND REPORT THIS INCIDENT TO YOUR HEAD OF SECURITY***"
reagent_state = LIQUID
fluid_r = 250
fluid_b = 250
fluid_g = 0
transparency = 40
reaction_turf(var/turf/T, var/volume)
src = null
if(volume >= 5)
if(!locate(/turf/unsimulated/floor/void) in T)
playsound(T, "sound/effects/splat.ogg", 50, 1)
new /turf/unsimulated/floor/void(T)
// When finished, exposure to or consumption of this drug should basically duplicate the
// player. send their active body to a horrible hellvoid. back on the station,
// replace them with a crunch-critter transposed mob? or just a Transposed Particle Field,
// that might be easier
*/
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
//Will not react if below this
//Not used by default. -1 = not used. //Positive values for reaction to take place when hotter than value, negative to take place when cooler than abs(value)
//Will not react if above this
// units produced per second
// Logs the contents of the reagent holder's container in addition to the reaction itself.
// Used for foam and smoke (Convair880).
//If set to 1, the recipe will consume ALL of its components instead of just proportional parts.
//I recommend you set the result amount to the total volume of all components.
// the following three recipes should stop most of the nonsense with pyrosium lagging things to shit, hopefully??
// if not yell at me to code better - haine
// Lumen reagent was removed.
// also no more fermid foams, fu nerds tOt
/*tricalomel
name = "Pentetic Acid"
id = "tricalomel"
result = "tricalomel"
required_reagents = list("ethanol" = 1, "diethylamine" = 1, "ammonia" = 1, "cyanide" = 1)
result_amount = 3
mix_phrase = "The mixture bubbles slightly before settling down."*/
//required_temperature = T0C + 400 // commenting out for now so you can actually make this, maybe
/* argine
name = "Argine"
id = "argine"
result = "argine"
required_temperature = -25
required_reagents = list("ethanol" = 1, "silicon" = 1, "water" = 1)
result_amount = 3 */
/*foof
name = "FOOF"
id = "foof"
result = "foof"
required_temperature = 600
required_reagents = list("oxygen" = 1, "flourine" = 1, "stabiliser" = 1)
result_amount = 1
mix_phrase = "The mixture violently erupts and seethes with fire."
on_reaction(var/datum/reagents/holder, var/created_volume)
fireflash(holder.my_atom, 3)
return*/
// COGWERKS REPLACEMENT NOTES: FEN-PHEN? EPHEDRINE?
// get in
// get in
// get in
// required_temperature = 170
// more or less the industrial route to cyanide
// let's not make it too easy to mass produce
// BAHAHAHAHA
// oh god why am i adding this
// it is super potent
// nurfed.
// griff
// hydrolysis of chlorobenzene
//required_temperature = 390
/* lexorin
name = "Lexorin"
id = "lexorin"
result = "lexorin"
required_reagents = list("plasma" = 1, "hydrogen" = 1, "nitrogen" = 1)
result_amount = 3
mix_phrase = "A faint yet nostril-burning scent drifts from the mixture."*/
// COGWERKS CHEM REVISION PROJECT: This could be Fluorosulfuric Acid instead
// tobba chem revision: change to SO3 + H2O
//required_temperature = -160
// why are the acids doing brute????
// WHY??
// COGWERKS CHEM REVISION PROJECT: This could be Fluorosulfuric Acid instead
// tobba chem revision: change to SO3 + HF
// IT'S ACID IT BURNS
// COGWERKS CHEM REVISION PROJECT: marked for revision. Potassium iodide? Prussian Blue?
// COGWERKS CHEM REVISION PROJECT: marked for revision. Pentetic Acid?
// (dichloroethane + ammonia) + formaldehyde (maybe that should be implemented?) + (sodium cyanide) yields EDTA which is almost DPTA
//required_temperature = 310
//ethanol as methanol, oxidized with a silver catalyst
// really more like 620 but fuck it
// COGWERKS CHEM REVISION PROJECT: marked for revision - antipsychotic
//required_temperature = 320
// COGWERKS CHEM REVISION PROJECT: marked for revision. maybe something like Silvadene?
// oil as benzene, sulfur oxygen chlorine as a sulfonyl group
// removed oil from the recipe so that this can be made without leaving a chem dispenser like styptic
// antitoxin
// COGWERKS CHEM REVISION PROJECT: marked for revision - magic drug
// COGWERKS CHEM REVISION PROJECT: maybe atropine, and give it a useful function in medbay?
/*omnizine // COGWERKS CHEM REVISION PROJECT: magic bullshit drug, ought to involve plasma. far too easy to make right now
name = "omnizine"
id = "omnizine"
result = "omnizine"
required_reagents = list("epinephrine" = 1, "charcoal" = 1)
result_amount = 2
mix_phrase = "The mixture seems to slosh around on its own, fizzing violently."*/
// COGWERKS CHEM REVISION PROJECT: maybe this could be Mannitol, side effect: makes u pee?
//required_temperature = T0C + 150
// COGWERKS CHEM REVISION PROJECT: possibly dexamesothone, anti-edema medication
// COGWERKS CHEM REVISION PROJECT:marked for revision
// hydrogenate napthalene, then fluorinate
// lowered because the recipe is very easy
// COGWERKS CHEM REVISION PROJECT: no idea, probably a magic drug
//required_temperature = 325
// COGWERKS CHEM REVISION PROJECT: some sort of potent stimulant, could combine with teporone?
// tobba chem revision: change the hydrogen and iodine for hydroiodic acid
// ~HEH~
// // COGWERKS CHEM REVISION PROJECT: magic bullshit drug, make it involve mutagen
// leaving this name alone
// had a conflict with ammonia recipe
// lowered slightly
// high chance of not working to piss them off
// Don't forget to update Reagents-ExplosiveFire.dm too, we have duplicate code for sonic and flash powder there (Convair880).
//The "bang" part of "flashbang"
//annoying and unfun so reduced dramatically
// death 2 chemists
//Consume max health on nearby people. also stamina. also requires alchemy circle and stone.
//This MUST be above the smoke recipe. Trust me on that one. IT affects the internal order of the recipes.
// This reaction didn't have an upper cap, uh-oh (Convair880).
// oh no
///////////////////////////////////////////////////////////////////////////////////
// moved this down so improperly mixed nutrients yield jenkem instead
// this is going to make people so, so angry
/*plant_nutrients_mutagenic
name = "Mutriant Plant Formula"
id = "plant_nutrients_muta"
result = "plant_nutrients_muta"
required_reagents = list("saltpetre" = 1, "anti_rad" = 1, "radium" = 1)
result_amount = 3
mix_phrase = "A strange odor comes from the resultant greenish goo."
mix_sound = 'sound/effects/blobattack.ogg'
plant_nutrients_quickgrow
name = "Gro-Boost Plant Formula"
id = "plant_nutrients_grow"
result = "plant_nutrients_grow"
required_reagents = list("saltpetre" = 1, "stypic_powder" = 1, "salbutamol" = 1)
result_amount = 3
mix_phrase = "The mixture smells earthy and yet strange."
mix_sound = 'sound/effects/blobattack.ogg'
plant_nutrients_cropyield
name = "Top Crop Plant Formula"
id = "plant_nutrients_crop"
result = "plant_nutrients_crop"
required_reagents = list("saltpetre" = 1, "charcoal" = 1, "antihol" = 1)
result_amount = 3
mix_phrase = "The substance dissolves into a thick silty soup."
mix_sound = 'sound/effects/blobattack.ogg'
plant_nutrients_potency
name = "Powerplant Plant Formula"
id = "plant_nutrients_potency"
result = "plant_nutrients_potency"
required_reagents = list("saltpetre" = 1, "silver_sulfadiazine" = 1, "methamphetamine" = 1)
result_amount = 3
mix_phrase = "A pungent and powerful earthy odor comes from the mixture."
mix_sound = 'sound/effects/blobattack.ogg'
plant_nutrients_balance
name = "Fruitful Farming Plant Formula"
id = "plant_nutrients_balance"
result = "plant_nutrients_balance"
required_reagents = list("saltpetre" = 1, "epinephrine" = 1, "teporone" = 1)
result_amount = 3
mix_phrase = "A calming, coffee-like scent comes from the dirt-like mixture."
mix_sound = 'sound/effects/blobattack.ogg' */
// why are the acids doing brute????
// foam and foam precursor
/* fuckthisshit
name = "fuck this shit"
id = "fuckthisshit"
result = null
required_reagents = list("carbon" = 5, "flourine" = 5, "acid" = 5, "sugar" = 5, "phosphorus" = 5, "potassium" = 5, "water" = 15)
result_amount = 5
mix_phrase = "The chemicals mix into a shade of brown and begin to bubble."
mix_sound = 'poo2.ogg'
on_reaction(var/datum/reagents/holder, var/created_volume)
holder.clear_reagents()
message_admins("[] attempted to make infinifoam what a piece of shit", usr) */
// Synthesizing these three chemicals is pretty complex in real life, but fuck it, it's just a game!
// COGWERKS CHEM REVISION PROJECT: change this so cleaner involves ammonia, ethanol and water
// cogwerks' dumb first drug attempt, delete if bad
// cogwerks
// cogwerks - basic sedatives could fill this role, or just put it in the medbay vendor?
//required_temperature = 320
// benzhydryl(benzene+carbon) bromide + 2-dimethylaminoethanol
//required_temperature = 320
// a shameful cogwerks. hobo chemistry, assistant-sourcable source of ammonia for various other reactions.
// cogwerks - awful hobo drug that can be made by pissing in a bunch of vending machine stuff and then boiling it all with a welder
// if you heat this stuff in your hand, you'll die! heh!
/* helldrug // the worst thing. if splashed on floor, create void turf. if ingested, replace mob with crunch critter and teleport user to hell
name = "Cthonium"
id = "cthonium"
result = "cthonium"
//required_temperature = 666
result_amount = 2
//required_reagents = list("el_diablo" = 1, "salts1" = 1,"mugwort" = 1, "catonium" = 1, "bloodc" = 1, "sulfur" = 1, "liquid spacetime" = 1, "strange_reagent" = 1)
required_reagents = list("blood" = 1, "sulfur" = 1, "plasma" = 1)
mix_phrase = "The mixture seems to have corrupted the very fabric of reality."
mix_sound = 'airraid_loop.ogg'
on_reaction(var/datum/reagents/holder, var/created_volume)
bust_lights()
creepify_station()
return
bleach
name = "Bleach" // cogwerks WIP: could be useful for hobo chemistry, hair bleaching, stubborn stains, being a jerk and turning stuff white
id = "bleach"
result = "bleach"
result_amount = 1
required_reagents = list("sodium" = 1, "chlorine" = 1, "hydrogen" = 1)
mix_phrase = "The mixture gives off a sharp odor much like bleach. Probably because it's bleach."
mix_sound = 'sound/misc/drinkfizz.ogg'
chlorine // cogwerks, more hobo chemistry
name = "Chlorine"
id = "chlorine"
result = "chlorine"
required_reagents = list("ammonia" = 1, "bleach" = 1 )
result_amount = 1
mix_phrase = "The mixture starts bubbling violently!"
mix_sound = 'sound/misc/fuse.ogg'
on_reaction(var/datum/reagents/holder, var/created_volume)
var/location = get_turf(holder.my_atom)
for(var/mob/M in AIviewers(5, location))
boutput(M, "<span style=\"color:red\">The solution boils up into a choking cloud!</span>")
src.mustard_gas = new /datum/effects/system/mustard_gas_spread/
src.mustard_gas.attach(src)
src.mustard_gas.set_up(5, 0, usr.loc)
return */
// COGWERKS CHEM REVISION PROJECT: add ethanol to this recipe
//mix_phrase = "The mixture begins to emit a distinct smell of bleach." -AMMONIA IS NOT BLEACH!!!!!!!!!! - grumpwerks
//+1 to prevent any of those weird errors where you get 5.423E-09 of something or whatever.
//Hello, here are some fake werewolf serum precursors
//result = "werewolf_part4"
//Super hairgrownium + Tongue of dog + Stable mutagen + Grog + Glowing Slurry + Aconitum
// Lumen reagent was removed.
//"flaptonium"
// heh get it, get it, birds, sky, airy??? heh im the master of humor
// This should really require a closed container and an extreme phase change... or some other pseudo-science thing
// IMPOSSIBRUUUU
/* It's me. I'm the new merculite.
nitrogen_triiodide
name = "Nitrogen Triiodide"
id = "nitrogentriiodide"
result = "nitrotri_wet"
required_reagents = list("lube" = 1, "iodine" = 2, "silver" = 1, "fluorine" = 1, "cryostylane" = 1) //, "perfluorodecalin" = 1, "oil" = 1, "chlorine" = 1)
required_temperature = - 233 // -30 degrees celsius
min_temperature = 200 //Will not react below 200 K
/*
Boron nitride: lube because boron nitride is a lubricant
Iodine, silver and fluorine for I_2 + AgF -> IF + AgI
Trichlorofluoromethane = cryostylane because it's a refrigerating agent
Fallback:
Trichlorofluoromethane = perfluorodecalin, oil and chlorine
In case nerds are being too nerdy.
*/
//This will just straight-up explode
// Lumen reagent was removed.
//required_temperature = 100 - T0C
// can also be made by eating unstable mutagen and ants and dancing - see human.dm
//This one should actually not be instant
//This one should actually not be instant
//required_temperature = 100 - T0C
//initialize the thing when the world starts
//If R is not a datum/reagent then I don't think anything I can do will help here.
//Things that will handle the possible options in reagents
//reagent_container bit flags
// has a graduated scale, so total reagent volume can be read directly
// reagent is visible inside, so color can be described
// can estimate fullness of container
// spectroscopic glasses can analyse contents
// for some reason this very important parent item of a fucking thousand other things was planted down on line 700
// I AM SCREAMING A LOT IN REAL LIFE ABOUT THIS CURRENTLY
// First filter out everything we don't want to refill or empty quickly.
// Added location (Convair880).
//A dispenser. Transfer FROM it TO us.
//Something like a glass. Player probably wants to transfer TO it.
// Added reagents (Convair880).
// dump contents onto it
//Have to do this in 2 lines because byond is shit.
// Added location (Convair880).
/*if (istype(I, /obj/item/reagent_containers/pill))
if (!I.reagents || !I.reagents.total_volume)
boutput(user, "<span style=\"color:red\">[src] is empty.</span>")
return
if (src.reagents.total_volume >= src.reagents.maximum_volume)
boutput(user, "<span style=\"color:red\">[src] is full.</span>")
return
boutput(user, "<span style=\"color:blue\">You dissolve the [I] in [src].</span>")
I.reagents.trans_to(src, I.reagents.total_volume)
qdel(I)
else */
// Added location (Convair880).
//Contains base elements / reagents.
// buffin this because fluorine is horrible - adding a burn effect
// ethanol poisoning
// let's not metabolize into meth anymore
//if(prob(2))
//M.reagents.add_reagent("cholesterol", rand(1,3))
//WHY IS SWEET ***TEA*** A SUBTYPE OF SUGAR?!?!?!?!
//Because it's REALLY sweet
//Half the dose lands on the floor
//Just an example.
//boil off
// drsingh attempted fix for undefined variable /turf/space/var/wet
//Ice
//The steam. It does nothing!!!
// have to call this now to force the lighting cleanup
// 1 1 1
//Just an example.
//boil off
// 3c + 1c + 1c
//Contains disease reagents.
/* this wont work properly and has been driving me fucking insane so disabling it for now
reaction_mob(var/mob/M, var/method=TOUCH, var/volume)
src = null
if(!M)
M = holder.my_atom
var/mob/living/L = M
if (method == INGEST || prob(25))
L.contract_disease(disease, null, null, 1) // path, name, strain, bypass resist
*/
// Clowning Around
// CLUWNE VIRUS
//Please never give this an actual recipe .I
// Cold
// Fake GBS
// Flu
// GBS
// Jungle Fever
// Plasmatoid
//on_mob_life(var/mob/M)
// Robot Transformation
//on_mob_life(var/mob/M)
// Teleportitis
// Berserker
//cogwerks drugs
// Food Poisoning
// Food Poisoning 2
// for infected wounds
// Necrotic Degeneration
// Panacaea
// Tissue Necrosis
// Space AIDS
// Space Madness
// Vampire Plague
// Kuru.
// oh god
// please do not give a recipe, just a thing for testing heart-related things atm
// please do not give a recipe, just a thing for testing heart-related things atm
// please do not give a recipe, just a thing for testing heart-related things atm
// Marquesas' one stop pathology shop
// for now
// To make matters easier, fungi and parasites are both cured by the same biocides
// A mutation inhibitor that should destroy great mutatis cells.
// A derivative of mutadone.
//Contains wacky space drugs
// commence bad times
// M.is_hobo = very yes
// a really shitty form of traitor stimulants - you'll be tough to take down but nearly uncontrollable anyways and you won't heal the way stims do
//var/mob/living/carbon/human/H = M
//if (istype(H))
// 1 1 :I
// sort of a shitty version of methamphetamine that can be made by assistants
// 10 2 1 3 1 heat explosion :v
// 4 2
// TODO. Write awesome hallucination algorithm!
// if(M.canmove) step(M, pick(cardinal))
// if(prob(7)) M.emote(pick("twitch","drool","moan","giggle"))
// 1c + 1c + 1c
//Turns into a neurotoxin.
// raise if too low - trying to aim for one sleepypen load being problematic, two being deadlyish
//var/counter = 1
//note that nicotine is also horribly poisonous in concentrated form IRM - could be used as a poor-man's toxin?
//just comment that out if you don't think it's any good.
// Gonna try this out. Not good for you but won't horribly maim you from taking a quick puff of a cigarette - ISN
//cogwerks - improved nicotine poisoning?
//grody. changed line in human.dm to use decomp1 now
// 13c * 3 :v
//Since is created by a meth overdose, dont react while meth is in their system.
//Since is created by a meth overdose, dont react while meth is in their system.
// // COGWERKS CHEM REVISION PROJECT. marked for revision
// 9c + 1c + 1c + 1c + heat
//Contains Fire / Explosion / Implosion related reagents.
//This is used for the smoke/napalm reaction.
// with purging fire
//Wire: Fix for Cannot read null.total_temperature
//Too cold. Doesnt work.
//Wire: Fix for Cannot read null.total_temperature
//Wire: Fix for Cannot read null.total_temperature
// adapated from weldfuel
// Bypasses the RNG roll to melt walls (Convair880).
/*var/turf/simulated/floor/F = A.ReplaceWithFloor()
F.to_plating()
F.burn_tile()*/
//ugh fuck this proc seriously
// Instant foam and smoke reactions are handled in Chemistry-Holder.dm (Convair880).
// Sadly, we don't automatically get a mob reference under most circumstances.
// If there's an existing lookup proc and/or better solution, I haven't found it yet.
// If everything else fails, maybe there are fingerprints on the container for us to check though?
// Our mob, the container.
// Backpacks etc.
// Our container. You don't necessarily have to pick it up to transfer stuff.
// Backpacks etc.
//DEBUG("Heat-triggered smoke powder reaction: our user is [our_user ? "[our_user]" : "*null*"].[our_fingerprints ? " Fingerprints: [our_fingerprints]" : ""]")
// coat them with it?
//annoying and unfun so reduced dramatically
// fuck you jerk chemists (todo: a thing to self-harm borgs too, maybe ex_act(3) to the holder? I D K
// Don't forget to update Reagents-Recipes.dm too, we have duplicate code for sonic and flash powder there (Convair880).
// coat them with it?
// fix for a potential game crashing exploit with smokes
//explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range)
/* combustible/merculite
name = "Merculite"
id = "merculite"
description = "Highly flammable and explosive compound. Very sticky."
reagent_state = LIQUID
fluid_r = 200
fluid_g = 125
fluid_b = 75
transparency = 175
reaction_temperature(exposed_temperature, exposed_volume)
if(temperature > 330)
var/extra_range = round(min(max((((temperature - T0C) / 10) - 6),0),3)) //Usually 0. Unless someone somehow manages to heat this without it exploding.
var/max_range = round(min(max((volume / 10),1),8),1) + extra_range
var/heavy_range = round(max((max_range / 2),1))
var/devastation_range = min(max(extra_range, 1),3)
explosion(get_turf(holder.my_atom), devastation_range, heavy_range, max_range, max_range)
holder.del_reagent(id)
return
reaction_obj(var/obj/O, var/volume)
src = null
if(!O.reagents) O.create_reagents(50)
O.reagents.add_reagent("merculite", 3, null)
return
reaction_turf(var/turf/T, var/volume)
src = null
if(!T.reagents) T.create_reagents(50)
T.reagents.add_reagent("merculite", 3, null)
return
reaction_mob(var/mob/M, var/method=TOUCH, var/volume)
src = null
if(method == TOUCH)
var/mob/living/L = M
if(istype(L) && L.burning)
L.set_burning(100)
return */
// COGWERKS CHEM REVISION PROJECT. this could be Chlorine Triflouride, a really mean thing
// with purging fire
/*reaction_temperature(exposed_temperature, exposed_volume)
if(temperature > T0C + 15)
fireflash(get_turf(holder.my_atom), min(max(0,volume/10),3))
holder.del_reagent(id)
return*/
// just in case
//if(!T.reagents) T.create_reagents(50)
//T.reagents.add_reagent("infernite", 5, null)
// this doesn't work yet
/*reaction_temperature(exposed_temperature, exposed_volume)
if(temperature > T0C + 15)
fireflash(get_turf(holder.my_atom), min(max(0,volume/10),3))
holder.del_reagent(id)
return*/
/*reaction_obj(var/obj/O, var/volume)
src = null
if (O && ispath(O, /obj/item))
var/obj/item/I = O
if(!I.burning)
I.combust()
return*/
//if(!T.reagents) T.create_reagents(50)
//T.reagents.add_reagent("infernite", 5, null)
// let's burn right the fuck through the floor
// COGWERKS CHEM REVISION PROJECT. pretty much a magic chem, can leave alone
//Comment this out if you notice a lot of crashes. (It's probably a really bad idea to have this in)
// 3 1 1 1
//Comment this out if you notice a lot of crashes. (It's probably a really bad idea to have this in)
// COGWERKS CHEM REVISION PROJECT. treat like acetylene or similar basic hydrocarbons for other reactions
// Added log entries (Convair880).
// cogwerks - gunpowder test. IS THIS A TERRIBLE GODDAMN IDEA? PROBABLY
// think of it as just being all over them i guess
// runtime error fix
//This is the parent and should not be spawned
//Fastest way to dry this. Also the most terrible idea.
//Random time until it becomes HIGHLY VOLATILE
//Random time until it becomes HIGHLY VOLATILE
//At least 11 seconds, at most 10 minutes
//At least 11 seconds, at most 10 minutes
//Welp
//What did you expect would happen when splashing THE HIGHLY VOLATILE POWDER on the floor
//Contains reagents related to eating or drinking.
//temp
// 1 2
// 1 2
//Nice & cold.
//Warm & disgusting.
//No hulk immunity when the stun is coming from inside your liver, ok .I
//if somebody adds /obj/item/vehicle, I'm killing myself.
// Bar Contest Winner's Drink
// this does brute for some reason, whateverrrr
// if(H.reagents && H.reagents.has_reagent("super_hairgrownium")) //if this starts being abused i will change it, but only admins seem to use grog so fuck it
// H.visible_message("<span style=\"color:red\"><b>[H] explodes in a shower of gibs, hair and piracy!</b></span>","<span style=\"color:red\"><b>Oh god, too much hair!</b></span>")
// new /obj/item/clothing/glasses/eyepatch(get_turf(H))
// new /obj/item/clothing/mask/moustache(get_turf(H))
// H.gib()
// return
//var/mob/living/carbon/human/H = M
//decays into sugar/some sort of stimulant, maybe gives unique stimulant effect/messages, like bold red GOTTA GO FASTs? Makes you take damage when you run into a wall?
//For laffs (http.//www.youtube.com/watch?v=ySq4O4sZj1w).
//lights drinker on fire, deals burn damage, when present in very large/overdose amounts (50+? 100+?) has a high chance of incinerating the drinker like ghostlier chili extract
//If the user drinks milk, they'll be fine.
//Roast up the player
//Acts like ghetto calomel that can be made outside medbay, chance to give food poisoning, vomit constantly and explosively while racking up moderate toxin damage that has no/very low HP cap and burning out other chemicals in the body at a rate equal to/greater than calomel - more potent, more dangerous/weaponizable, alternate sleepypen fuel for barman
//Decays into ethanol and THC
//decays into large amounts of capsaicin and maybe histamines?
//decays into 1 VHFCS per unit for a real good time, and also lets you see ghosts
//var/mob/living/carbon/human/H = M
// heh
//penetrates_skin = 1
//var/mob/living/carbon/human/H = M
//var/mob/living/carbon/human/H = M
// hey man some people really like weird cheese
// call your parents :(
// basically, make it twice as effective
//Just an example.
//Tea is good for you!!
//to-do. BEE MEN
// 1c + 1c + 1c
// same as salt vOv
//M.UpdateDamageIcon()
//Hukhukhuk brings you another culinary war crime
//lesser
// greater
//Hukhukhuk presents. pepperoni and acetone
//I assume this was not supposed to be poison.
//var/mob/living/carbon/human/H = M
//if(method == INGEST)
//drsingh commented method check to make this stuff work in smoke. because it's funny.
//var/mob/living/carbon/human/H = M
//if(method == INGEST)
//drsingh commented method check to make this stuff work in smoke. because it's funny.
//var/mob/living/carbon/human/H = M
// path, name, strain, bypass resist
//If the user drinks milk, they'll be fine.
//Roast up the player
//Contains medical reagents / drugs.
// COGWERKS CHEM REVISION PROJECT. this is a totally pointless reagent
// 2c + 1c
// // COGWERKS CHEM REVISION PROJECT. roll the antihistamine effects into this?
//Data is conserved...so some jerkbag could inject a monkey with this, wait for data to build up, then extract some instant KO juice. Dumb.
//Data is conserved...so some jerkbag could inject a monkey with this, wait for data to build up, then extract some instant KO juice. Dumb.
// COGWERKS CHEM REVISION PROJECT. marked for revision
// 5c + 1c + 1c
// 5c + 3c + 1c + 1c + 1c
// COGWERKS CHEM REVISION PROJECT. marked for revision. should be a chelation agent
// 1c + 1c + heat
/*medical/tricalomel // COGWERKS CHEM REVISION PROJECT. marked for revision. also a chelation agent
name = "Tricalomel"
id = "tricalomel"
description = "Tricalomel can be used to remove most non-natural compounds from an organism. It is slightly toxic however and supervision is required."
reagent_state = LIQUID
fluid_r = 33
fluid_g = 255
fluid_b = 75
depletion_rate = 0.8
transparency = 200
on_mob_life(var/mob/M)
if(!M) M = holder.my_atom
..(M)
for(var/reagent_id in M.reagents.reagent_list)
if(reagent_id != id)
M.reagents.remove_reagent(reagent_id, 6)
M.updatehealth()
if(M.health > 18)
M.take_toxin_damage(2)
M.updatehealth()
return */
// COGWERKS CHEM REVISION PROJECT. probably just a magic drug, i have no idea what this is supposed to be
// 6c + 2c + 1c
/*reaction_obj(var/obj/O, var/volume)
if(istype(O,/obj/item/parts/robot_parts/robot_frame))
if (O.check_completion() && volume >= 20)
O.replicant = 1
O.overlays = null
O.icon_state = "repli_suit"
O.name = "Unfinished Replicant"
for(var/mob/V in AIviewers(O, null)) V.show_message(text("<span style=\"color:red\">The solution molds itself around [].</span>", O), 1)
else
for(var/mob/V in AIviewers(O, null)) V.show_message(text("<span style=\"color:red\">The solution fails to cling to [].</span>", O), 1)*/
// COGWERKS CHEM REVISION PROJECT. remove this, make epinephrine (epinephrine) do the same thing
// COGWERKS CHEM REVISION PROJECT. magic drug, ought to use plasma or something
//M.UpdateDamageIcon()
//lesser
// greater
// COGWERKS CHEM REVISION PROJECT. magic drug, ought to use plasma or something
// splashing saline on someones wounds would sorta help clean them
// 3c + 1c + 1c
//M.UpdateDamageIcon()
// COGWERKS CHEM REVISION PROJECT. replace with potassum iodide
// 1c + 1c
// COGWERKS CHEM REVISION PROJECT. probably a magic drug, maybe ought to involve atropine
// 18 5 3
// I've added hearing damage here (Convair880).
// Permanent eye damage.
// Temporary blindness.
// Permanent ear damage.
// Temporary deafness.
// COGWERKS CHEM REVISION PROJECT. ought to be some sort of shitty illegal opiate or hypnotic drug
// 2c + 3c + 1c + 1c + 1c
// COGWERKS CHEM REVISION PROJECT. Could be Epinephrine instead
// 5c + 5c + 4c + 1c + 1c + 1c
// COGWERKS CHEM REVISION PROJECT. does Medbay have this? should be in the medical vendor
//if(holder.has_reagent("cholesterol")) //probably doesnt actually happen but whatever
//holder.remove_reagent("cholesterol", 2)
// COGWERKS CHEM REVISION PROJECT. marked for revision
// 2c + 1c + 1c + 1c + 1c
// Please don't set this to 8 again, medical patches add their contents to the bloodstream too.
// Consequently, a single patch would heal ~200 damage (Convair880).
// COGWERKS CHEM REVISION PROJECT. - marked for revision. Magic bullshit chem, ought to be related to mutagen somehow
// 5 3 1
//One per cycle. We're having superpowered hellbastards and this is their kryptonite.
// COGWERKS CHEM REVISION PROJECT. poor man's epinephrine
// 4c + 3c + 1c + 1c
// COGWERKS CHEM REVISION PROJECT. should be a potent chelation agent, maybe roll this into tribenzocytazine as Pentetic Acid
// 7 2 4 1 1 1
// 4 3 1 1 1
// // COGWERKS CHEM REVISION PROJECT. marked for revision
// 3c + 1c + 1c + 1c
// Please don't set this to 8 again, medical patches add their contents to the bloodstream too.
// Consequently, a single patch would heal ~200 damage (Convair880).
// fucking human shitfucks
// M.HealBleeding(volume_passed) // At least implement your stuff properly first, thanks. Styptic also shouldn't be as good as synthflesh for healing bleeding.
/*for(var/A in M.organs)
var/obj/item/affecting = null
if(!M.organs[A]) continue
affecting = M.organs[A]
if(!istype(affecting, /obj/item/organ)) continue
affecting.heal_damage(volume_passed, 0)*/
// COGWERKS CHEM REVISION PROJECT. magic drug, but isn't working right correctly
// 5 3 3 1
/*reaction_temperature(exposed_temperature, exposed_volume)
var/myvol = volume
if(exposed_temperature > T0C + 50) //Turns into omnizine. Derp.
volume = 0
holder.add_reagent("omnizine", myvol, null)
return*/
// gonna leave this one on for now, but only call it a quarter of the time
// COGWERKS CHEM REVISION PROJECT. i dunno what the fuck this would be, probably something bad. maybe atropine?
// 5 4 5 3 1
// COGWERKS CHEM REVISION PROJECT. marked for revision. Could be Dexamesathone
// 11 2 1 1 1
// 3 1 1 heat
// stop killing dudes goddamn
// has some slight healing properties due to tissue oxygenation
// 1 1 1
// 3c + 1c + heat
// slow this down a bit
// COGWERKS CHEM REVISION PROJECT. maybe a diuretic or some sort of goofy common hangover cure
// 5c + 1c
//Contains exotic or special reagents.
// Yes, this is a bad idea.
// power = SQRT(10V)
// 0.1 -> 1
// 0.2 -> 2
// 0.9 -> 3
// 1.6 -> 4
// 10 -> 10
// 250 -> 50
// 1000 -> 100
// brisance = LOG10(10V)
// 1 -> 1
// 10 -> 2
// 100 -> 3
// 1000 -> 4
// ...
// explosive properties
// relatively inert as a solid (T <= 14°C)
// rather explosive as a liquid (14 °C < T <= 50 °C)
// explodes instantly as a gas (50 °C < T)
// mechanical dropper transfer (1u): solid at 14°C: 0%, liquid: 0%
// classic dropper transfer (5u): solid at 14°C: 0% (due to min force cap), liquid: 20%
// beaker transfer (10u): solid at -36°C: 0%, solid: 5%, liquid: 30%
// the only safe way to transfer nitroglycerin is by freezing it
// thenagain, it may explode when being thawed unless heated *very* slowly
// 17 18 6
// vOv
//addiction_prob = 25
//It..grows hair. Not to be confused with the previous hair growth reagent, "wacky monkey cheeseonium"
// why wouldn't it, really
// 2 9 9
//moustache madness
// why wouldn't it, really
// 20 13 1
//This stuff is not done. Don't use it. Don't spoil it.
// 2 3 28 6 500
// last number: for 50u you take 100 points of health (assuming this is the first time it's been made by those people) so 2 points per 1u
// that number is the value of those 2 points
// Marq fix for cannot read null.my_atom
// 3 3 22
// if they have dnr set don't bother shoving them back in their body
//Wire: added the dnr condition here
//I should probably check for organic critters, but most robotic ones just blow up on death
// 2 2
// 1 1 1
//T0C - 100
// have to call this now to force the lighting cleanup
// 1 1 1
// Silicate was broken. I fixed it (Convair880).
//foam precursor
// 3 1 1
// 1 1 1
// metal foaming agent
// this is lithium hydride. Add other recipies (e.g. MiH + H2O -> MiOH + H2) eventually
// two different foaming agents is overly complicated imo - IM
/*foaming_agent
name = "foaming agent"
id = "foaming_agent"
description = "A agent that yields metallic foam when mixed with light metal and a strong acid."
reagent_state = SOLID
fluid_r = 100
fluid_g = 90
fluid_b = 90
transparency = 255*/
// 1c + 1c
// 2c + 1c + heat
// 3c + 1c + 1c
// 1c + 1c + 1c
// path, name, strain, bypass resist
// 1 1 1
//T0C - 100
// have to call this now to force the lighting cleanup
// COGWERKS CHEM REVISION PROJECT. ethanol, ammonia + water - treat like a shitty version of windex
// cogwerks- THIS IS NOT BLEACH ARGHHHH
// 2 1 1
// OOC. Weaseldood. oh that stuff from CSI, the glowy blue shit that they spray on blood
// 1c + 1c + 1c
// need this to be higher to make propylene possible
//Wire: fix for Undefined variable /turf/space/var/wet (&& T.wet)
//if (prob(4)) // it's motor oil, you goof
//M.reagents.add_reagent("cholesterol", rand(1,3))
//dead appearance handled in human.dm
// 4c + 1c + 1c
// Capped at ~2 minutes, that is 60 cycles + 10 paralysis (normally wears off at one per cycle).
//dead appearance handled in human.dm
// 6c + 9c + 13c
//handled in human.dm
//live appearance handled in human.dm
// used to make fake initropidril
// 11 2
// 11 2
//(prob(16))
//Rearranging to make it deplete as intended
// <- What's this?
/* reaction_obj(var/obj/O, var/volume)
if (volume >= 10)
var/dir_temp = pick("L", "R")
var/speed_temp = text2num("[rand(1,6)].[rand(0,9)]")
animate_spin(O, dir_temp, speed_temp)
DEBUG("<span style=\"color:blue\"><b>Spun [O]: [dir_temp], [speed_temp]</b></span>")
*/
// oh god what am I doing this is such a bad idea
// :effort:
// let us never forget the 3,267 parrot incident, the recipe for this just reacts instantly now
/* STOP FUCKING MURDERING THE SERVER YOU SHITASS
reaction_turf(var/turf/T)
if (isturf(T) && !istype(T, /turf/space))
if (!particleMaster.CheckSystemExists(/datum/particleSystem/glitter, T))
particleMaster.SpawnSystem(new /datum/particleSystem/glitter(T))
reaction_obj(var/obj/O)
if (isobj(O))
if (!particleMaster.CheckSystemExists(/datum/particleSystem/glitter, O))
particleMaster.SpawnSystem(new /datum/particleSystem/glitter(O))
*/
// no recipe, doesn't do any damage
/* NO
reaction_turf(var/turf/T)
if (isturf(T) && !istype(T, /turf/space))
if (!particleMaster.CheckSystemExists(/datum/particleSystem/glitter, T))
particleMaster.SpawnSystem(new /datum/particleSystem/glitter(T))
reaction_obj(var/obj/O)
if (isobj(O))
if (!particleMaster.CheckSystemExists(/datum/particleSystem/glitter, O))
particleMaster.SpawnSystem(new /datum/particleSystem/glitter(O))
*/
// lets you see ghosts while it's in you. exists only for ectocooler to decay into atm
// haha fuck no I'm not porting this to the new lighting system
/*lumen
name = "lumen"
id = "lumen"
description = "A viscous liquid that seems to glow rather intensively. Perhaps applying this to things might lighten up places."
reagent_state = LIQUID
fluid_r = 255
fluid_g = 255
fluid_b = 255
transparency = 230
proc/calculate_glow_color()
if (holder)
return holder.get_average_color()
return new /datum/color(fluid_r, fluid_g, fluid_b, transparency)
reaction_turf(var/turf/T)
if (locate(/obj/decal/glow) in T)
return
var/obj/decal/glow/G = new(T)
var/datum/color/mycolor = calculate_glow_color()
G.sd_SetColor(mycolor.r / 255.0, mycolor.g / 255.0, mycolor.b / 255.0)
G.sd_SetLuminosity(3)
spawn (rand(1500, 6000)) // 2.5-10 minutes
qdel(G)
reaction_obj(var/obj/O)
var/datum/color/mycolor = calculate_glow_color()
src = null
if (!O)
return
if (!O.luminosity)
O.sd_SetColor(mycolor.r / 255.0, mycolor.g / 255.0, mycolor.b / 255.0)
O.sd_SetLuminosity(3)
spawn (rand(3000, 12000)) // 5-20 minutes
if (O)
O.sd_SetLuminosity(0)*/
///////////////////////////
/// BOTANY REAGENTS ///////
///////////////////////////
// stuff what's for plants and hydroponics
// cogwerks note. making atrazine toxic
/*if (prob(80))
P.growth+=2
if (prob(80))
P.health+=2
*/
///////////////////////////
/// BODILY FLUIDS /////////
///////////////////////////
/* var
blood_DNA = null
blood_type = "O-"*/
// Blood as a reagent doesn't track DNA and blood type yet (or anymore).
/*if (M.bioHolder && (src.blood_DNA == M.bioHolder.Uid))
M.show_text("Injecting your own blood? Who are you kidding?", "red")
return*/
// vamp_blood
// vamp_blood_remaining
/* if (holder) // drinking blood shouldn't add it to your system
holder.remove_reagent("blood", volume_passed)
*/
// Let's assume that blood immediately mixes with the bloodstream of the mob.
//Only process pathogens once
//If there's stable mutagen in the mix and it doesn't have data we gotta give it a chance to get some
/*on_mob_life(var/mob/M) why
for (var/datum/ailment_data/disease/virus in M.ailments)
if (prob(10))
M.resistances += virus.type
M.ailments -= virus
boutput(M, "<span style=\"color:blue\">You feel better</span>")
..(M)
return*/
//if (!istype(O, /obj/effects/foam)
// && !istype(O, /obj/item/reagent_containers)
// && !istype(O, /obj/item/chem_grenade))
//Contains reagents that are poisons or otherwise intended to be harmful
// COGWERKS CHEM REVISION PROJECT. give this a reaction and remove it from the dispenser machine, hydrogen (2) + sulfur (1) + oxygen (4)
// 1c + 1c + 1c
//M.take_toxin_damage(1)
// big brother to cyanide, very strong
// 3 2 1 heat
// -cogwerks. previous version
// 1 1 1 heat
// Used to do exactly this back in 2012 or so (Convair880).
//lol @ consumable_good, yeah right
// path, name, strain, bypass resist
//per 3 sec
//everything after
// an attempt to tie noheart to this as per SpyGuy's request
// you can't barf up a bee heart if you ain't got no heart to barf
// yep
// you can't barf up a bee heart if you ain't got no heart to barf
// you'll be gibbed in a moment you don't need it anyway
//if (prob(5)) // this is way too annoying and ruins fried foods
//boutput(M, "<span style=\"color:red\">You feel [pick(</span>"weak","shaky","ill")]!")
//M.stunned ++
//M.losebreath++ //heartfailure handles this just fine
// path, name, strain, bypass resist
// commence the tickling
// COGWERKS CHEM REVISION PROJECT.. Change this to Fluorosulfuric Acid
// COGWERKS CHEM REVISION PROJECT. idk some sort of potent opiate or sedative. chloral hydrate? ketamine
// COGWERKS CHEM REVISION PROJECT. ketamine
// sped this up a bit due to mob loop changes
// COGWERKS CHEM REVISION PROJECT. which neurotoxin?
// 3c + heat
// let's not be incredibly obvious about who stung you for changelings
// let's slow down a bit after 80
// COGWERKS CHEM REVISION PROJECT. magic chemical, fine as is
// 1 1 1
/*if (prob(80)) P.growth -= rand(1,2)
if (prob(16)) P.HYPmutateplant(1)*/
////////////// work in progress. new mutagen for omega slurrypods - cogwerks
// DNA buckshot
// cogwerks notes. allergic reaction tests (see. MSG) can metabolize this in the body for allergy simulation, if extracted and mass-produced, it's fairly lethal
// allergies suck fyi
// yet another thing that will put ol' cogwerks on a watch list probably
// let's not totally kill people
//Do we have some BLOOODDD to use?
//Uh oh
//Not too bad after all
//Oh god!
//Whew
//Oh no
//:getin:
//Fak
//FIGHTIN'
// LOUD
//POWER UP!!
//Oh dear
//Buff
//The AI is in control now.
//Stronk
//Uh oh
// LOUD
//POWER UP!!
//The AI is in control now.
//V. Stronk
//Not so buff
//Just started out. Everything's cool
//Ok, now it's getting worrying
//Start at 30% chance of bad stuff, increase until death
//Harmless messages, etc
//Getting kinda stiff... ouch (stuns, dropping items, etc)
//Feels bad
//Drop stuff
//Trip
//Light-headedness
//I don't feel so good (tripping, hard time breathing, randomly dropping stuff)
//Chest-heaviness
//Drop stuff
//Trip
//Light-headedness
//Stun, twitch, 50% chance ramps up to 100 after
//It REALLY hurts
//At least 30% risk of oxy damage
//TODO: Blood
// I SWEAR TO GOD IF YOU GIVE ONE MORE RUNTIME I WILL JUST REWRITE THIS SHIT FROM THE GROUND UP
/* if (src.reagents.total_volume > 30)
if (prob(50))
user.visible_message("<span style=\"color:red\">[src] is overfilled and bursts! <b>[curse]</b></span>")
smash()
return
*/
//A dispenser. Transfer FROM it TO us.
//I have to test too many fucking plant-related issues atm so I'm adding this just to make my life less annoying
//boutput(world, "miptank bumped into [O]")
//boutput(world, "sending signal")
//boutput(world, "not active")
//boutput(world, "[A]:[A.type] was sensed")
//SN src = null
// drsingh for Cannot execute null.attack self()
//boutput(world, "miptank [src] got signal")
//boutput(world, "sent explode() to [src.payload]")
/// cogwerks - adding some new bottles for traitor medics
// haine - I added beedril/royal beedril to these, and my heart-related disease reagents. yolo (remove these if they're a dumb idea, idk)
//the good medicines
//////
// heh
// ugly hack
// this shit refused to show the parent get_desc() info even if I added a ..() so I'M JUST COPYING THE CODE NOW LIKE SOME KIND OF GIGANTIC ASSHOLE
// what was the point here exactly
//New()
//..()
//var/brewed_name = null
//brewed_name += ", [reagent_id_to_name(i)]"
//brewed_name = copytext(brewed_name, 3)
//brewed_name = reagent_id_to_name(W:brew_result)
// into [brewed_name]!")
//qdel(W)
// Can't draw more than THEY have.
// Can't drop more than you have.
// You can inject humans and food but you can't remove the shit.
// Modify it so that the reaction only happens with the actual transferred amount.
//Decrease transfer amount
//increase it
// Sanity check.
// colors available as of the moment: orange, red, blue, green, yellow, purple, black, white
//TODO; Add support for reagents in water.
// BAHAHAHAHA
//Color for various food items
//Can it be used to make custom food like for pizzas
// will hitting a still with it do anything?
// what will it make if it's brewable?
// Add medal name here in the format of e.g. "That tasted funny".
//Arguably more elegant than a million locates. I don't think locate works with derived classes.
// path, name, strain, bypass resist
/* attackby(obj/item/W as obj, mob/user as mob)
if (istype(W, /obj/item/shaker))
var/obj/item/shaker/shaker = W
src.reagents.add_reagent("[shaker.stuff]", 2)
shaker.shakes ++
boutput(user, "You put some [shaker.stuff] onto [src].")
else return ..()
*/
// I don't know if this was used for something but it was breaking my important "shake salt and pepper onto things" feature
// so it's getting commented out until I get yelled at for breaking something
// attackby(obj/item/I as obj, mob/user as mob)
// return
//This is now officially broken ... need to think of a nice way to fix it.
//gulp_size = round(reagents.total_volume / 5)
//if (gulp_size < 5) gulp_size = 5
/* else
var/reag_list = ""
for (var/current_id in reagents.reagent_list)
var/datum/reagent/current_reagent = reagents.reagent_list[current_id]
reag_list += "[current_reagent.taste], "
boutput(M, "<span style=\"color:blue\">You taste [reag_list]in this.</span>")
*/
//A dispenser. Transfer FROM it TO us.
//Something like a glass. Player probably wants to transfer TO it.
// Brought in line with beakers (Convair880).
// Look in bottle.dmi for the label names
// For writing on the things with a pen
//Fix for cannot read null/volume. Also FUCK YOU REAGENT CREATING FUCKBUG!
// buh?
// Why is this a drinking bottle now? Well, I want the same set of functionality (drag & drop, transference)
// without the C&P code a separate obj class would require. You can't use drinking bottles in beaker
// assemblies and the like in case you're worried about the availability of 400 units beakers (Convair880).
//Okay so we're not really adding anything here. cheating.
//S = null
// Custom grenades only. Metal foam etc grenades cannot be modified (Convair880).
// Ditto (Convair880).
//The possible reactions didnt use up all reagents.
//Why am i doing this?
//To make sure all reagents can work
//correctly before deleting the grenade.
// Order matters. Water resp. the final smoke ingredient should always be the last reagent added to the beaker.
// If it's not, the foam resp. smoke reaction occurs prematurely without carrying the target reagents with them.
//The syndicate are sending the strong stuff now -Spy
// who keeps doing the emag_act() thing idgi
// haine: done -> //TODO: using usr in procs is evil shame on you
// we only need to purge bad chems if new chems have been added
//100
//Look away, you fool! Like the sun, this section of code is harmful for your eyes if you look directly at it
//var/iv_state = max(min(round(src.reagents.total_volume, 10) / 10, 100), 0)
// Vampires can't use this trick to inflate their blood count, because they can't get more than ~30% of it back.
// Also ignore that second container of blood entirely if it's a vampire (Convair880).
// the part where shit's actually transferred
// Vampires can't use this trick to inflate their blood count, because they can't get more than ~30% of it back.
// Also ignore that second container of blood entirely if it's a vampire (Convair880).
// actual transfer
// are they a borg? it's probably a mediborg's IV then, don't take that!
//src.IV.attackby(W, user)
//boutput(world, "[jar_entry] = [jars_encoded[jar_entry]]")
//boutput(world, "[jarX] [jarY] [jarZ]")
//boutput(world, "[decode_list[i]], [potential_new_item_path]")
//Isn't this ugly? This is ugly.
//todo
//todo: add pickle juice
// only spectroscopic analysis
//DEBUG("[src] in use")
// No src.reagents check here because empty patches can be used to counteract bleeding.
// No src.reagents check here because empty patches can be used to counteract bleeding.
//might as well let people complete this even if they're borged
// Patches should primarily be for topically drugs (Convair880).
// like normal patches but smaller and cuter!!!
//Or you're gonna literally attack someone with it. *thwonk* style
// only spectroscopic analysis
// Get them out of mob.contents.
//wtf
// drugs 420 all day
// Does this gun add gunshot residue when fired? These syringes are probably propelled by CO2 or something, but whatever (Convair880).
//Blood!
// Vampires can't use this trick to inflate their blood count, because they can't get more than ~30% of it back.
// Also ignore that second container of blood entirely if it's a vampire (Convair880).
// drsingh for Cannot read null.total_volume
// contingency
//break the seal
// Convair880: Seems more efficient than separate calls. I believe this shouldn't clutter up the logs, as the number of targets you can inject is limited.
// Also wraps up injecting food (advertised in the 'Tip of the Day' list) and transferring chems to other containers (i.e. brought in line with beakers and droppers).
//patch auto-naming thing
// drsingh for cannot read null.total_volume
// drugs
// we've reacted with whatever we've hit, but if what we hit is a mob, let's not stick glass in their contents
// Commodities
// Name of the item on the market
// Type Path of the item on the market
// Current selling price for this commodity
// Baseline selling price for this commodity
// Whether this item is currently being accepted for sale
// Whether this item is currently being bought at a high price
// Highest this item's price can raise in one shift
// Lowest this item's price can drop in one shift (negative numbers only)
//Description for item
//Description for player selling
//Descripition for player selling when in high demand
//Sometimes traders won't say if they will buy something
// Used for QM traders - how much of a thing they have for sale, unlim if -1
// if its in the shopping cart, this is how many you're buying instead
// no more scamming
// because QMs keep scamming the system, I am lowering the base price of ore way down - cogwerks
// why is this worth a ton of money?? dropping the value to further upset QMs
// cogwerks - NPC stuff
// buy from trader NPC
//////////////////////
//// pod sales ///////
//////////////////////
////////////////////////////
///// 420 all day //////////
////////////////////////////
/// these are things that you can sell to the traders
///// things you can buy from the traders
/////////////////////////////////
//// valuable space junk ////////
/////////////////////////////////
////////////////////////////////
///// syndicate trader /////////
////////////////////////////////
//// purchase stuff
//NT stuff
/////////////////////////////////
////// salvage trader ///////////
/////////////////////////////////
/////////////////////////////////
///////food trader //////////////
/////////////////////////////////
// sell
///// body parts
///// costume kits
//YJHGHTFH's light borg costume
//YJHGHTFH's utena costume & AffableGiraffe's anthy dress
//no it ain't a costume kit but it's going in Geoff's wares so idgaf tOt fite me
/// pathology
// Can be a mob or obj.
//Param-like list of frequencies this signal has been on, for transponders and stuff.
//0 = wire
//1 = radio transmission
//We can carry a computer file around, why not.
// debuggging
//CONTENTS:
//Base computer datum
//Base Folder
//Base File
//Text files
//Records
//Signal files
//Archive files
//Folder link
//File permission flags
/* commented by singh, new disposing() pattern should handle this. if i broke everything sorry IBM, SORRY
Del()
for(var/datum/computer/F in src.contents)
qdel(F)
for(var/datum/computer/folder/link/L in src.linkers)
L.contents = list()
..()
*/
// boutput(world, "Removing file [R]. File_used: [src.holder.file_used]")
// boutput(world, "Removed file [R]. File_used: [src.holder.file_used]")
//Differentiate between types of files, why not
//Just make a replica of self
// && V != "holder")
//Convert contents to text, if possible
// same as above, XOXOXO. -singh
//if(holder && holding_folder)
// holding_folder.remove_file(src)
//Size of files stored within.
//Generally assumed that all contained files will be expendable copies
//Just make a replica of self
//qdel(src.metadata)
//src.metadata = newtarget.metadata
/* same as above, XOXOXO. -singh
Del()
src.contents = null
if (src.target)
src.target.linkers -= src
src.target = null
..()
*/
// server name (for world name / status)
// generate numeric suffix based on server port
// load extra config files (by port)
// Server will call world.Reboot after checking for update if this is on
// medal hub name
// medal hub password
//Note: All logging configs are for logging to the diary out of game. Does not affect in-game logs!
// log OOC channel
// log login/logout
// log client say
// log admin actions
// log game events
// log voting
// log client whisper
// log admin helps
// log mentor helps
// log combat events
// log station events (includes legacy build)
// log telepathy events
// log debug events
//I feel like this is a better place for listing who entered what, than the admin log.
// allow votes to restart
// allow votes to change mode
// allows admin jumping
// allows admin sound playing
// allows admin item spawning
// allows admin revives
// minimum time between voting sessions (seconds, 10 minute default)
// length of voting period (seconds, default 1 minute)
// vote does not default to nochange/norestart (tbi)
// dead people can't vote (tbi)
// allowed modes
// votable modes
// relative probability of each mode
// allow ai job
// MySQL
// Player notes base URL
//playernotes.ss13.co/"
// Server list for cross-bans and other stuff
//IRC Bot stuff
//External server configuration (for central bans etc)
//Environment
// I wish I didn't have to instance the game modes in order to look up
// their information, but it is the only way (at least that I know of).
// ensure each mode is added only once
//Environment config overrides
// I wish I didn't have to instance the game modes in order to look up
// their information, but it is the only way (at least that I know of).
//boutput(world, "Returning mode [mode_name]")
//See _setup.dm for interrupt and state definitions
//Associative list of running actions, format: owner=list of action datums
//has this mob an action of a given type running?
//Interrupts all actions of a given owner.
//Manually interrupts a given action of a given owner.
//Manually interrupts a given action id of a given owner.
//Starts a new action.
//Is called by all kinds of things to check for action interrupts.
//Handles the action countdowns, updates and deletions.
//continue //If this is not commented out the deletion will take place the tick after the action ends. This will break things like objects being deleted onEnd with progressbars - the bars will be left behind. But it will look better for things that do not do this.
//Object that owns this action.
//How long does this action take in ticks.
//When and how this action is interrupted.
//Current state of the action.
//world.time this action was started at
//Unique ID for this action. For when you want to remove actions by ID on a person.
//This is called by the default interrupt actions
//Called every tick this action is running. If you absolutely(!!!) have to you can do manual interrupt checking in here. Otherwise this is mostly used for drawing progress bars and shit.
//Called when the action fails / is interrupted.
//Called when the action begins
//Called when the action succesfully ends.
//Called when the action is complete and about to be deleted. Usable for cleanup and such.
//This subclass has a progressbar that attaches to the owner to show how long we need to wait.
//Tiny cosmetic fix. Makes it so the bar is completely filled when the action ends.
// WOW HACK
//Visible to everyone and has an icon.
//This subclass is only visible to the owner of the action
//Only visible to the owner and has a little icon on the bar.
//ACTIONS
//Calls a specific proc with the given arguments when the action succeeds. TBI
//Putting items on or removing items from others.
//The person doing the action
//The target of the action
//The item if any. If theres no item, we tried to remove something from that slot instead of putting an item there.
//The slot number
// Added for forensics (Convair880).
/* Some things use handle_other_remove to do stuff (ripping out staples, wiz hat probability, etc) should only be called once per removal.
if(!I.handle_other_remove(source, target))
boutput(source, "<span style=\"color:red\">[I] can not be removed.</span>")
interrupt(INTERRUPT_ALWAYS)
return
*/
//Wire: Fix for Cannot execute null.handle other remove().
// Re-added (Convair880).
//This is used when you try to set someones internals
//This is used when you try to handcuff someone.
//This is used when you try to remove someone elses handcuffs.
//This is used when you try to resist out of handcuffs.
// Resisting out of shackles (Convair880).
//CLASSES & OBJS
//These objects are mostly used for the attached_objs var on mobs to attach progressbars to mobs.
//Use this to start the action
//actions.start(new/datum/action/bar/private/icon/magPicker(item, picker), usr)
//How long does this action take in ticks.
//In these two vars you can define an icon you want to have on your little progress bar.
//This will contain the object we are trying to pick up.
//This is the magpicker.
//check for special conditions that could interrupt the picking-up here.
//If the thing is suddenly out of range, interrupt the action. Also interrupt if the user or the item disappears.
//If the thing is out of range, interrupt the action. Also interrupt if the user or the item disappears.
//They did something else while picking it up. I guess you dont have to do anything here unless you want to.
//Shove the item into the picker here!!!
//This is the magpicker.
//Again, check here for special conditions that are not normally handled in here. You probably dont need to do anything.
//Interrupt if the user or the magpicker disappears.
//We can hold it indefinitely unless we move.
//Interrupt if the user or the magpicker dont exist.
//DEBUG STUFF
// Added. Admin actions related to artfacts were not logged at all (Convair880).
//?src=\ref[src];Spawnnew=1'>Spawn a new Artifact on your current tile</b></a><br>"
//?src=\ref[src];Spawntype=1'>Spawn Type:</a> "
//?src=\ref[src];Spawncine=1'>Cinematic Spawning:</a> "
//?src=\ref[src];Activate=\ref[O]'>"
//?src=\ref[src];Jumpto=\ref[O]'>Jump To</a> * "
//?src=\ref[src];Get=\ref[O]'>Get</a> * "
//?src=\ref[src];Destroy=\ref[O]'>Destroy</a><br><br>"
// Origins
// ia ia
// 30m
// 11m
// 20m
// 10m
// roughly 8m
// roughly 14m
// Minimum amount of players connected for event to occur
///////////////////
// CONFIGURATION //
///////////////////
//?src=\ref[src];EventBegin=1'>[round(events_begin / 600)] minutes</a><br>"
//?src=\ref[src];MEventBegin=1'>[round(minor_events_begin / 600)] minutes</a><br>"
//?src=\ref[src];EnableEvents=1'>Random Events Enabled:</a></b> [events_enabled ? "Yes" : "No"]<br>"
//?src=\ref[src];EnableMEvents=1'>Minor Events Enabled:</a></b> [minor_events_enabled ? "Yes" : "No"]<br>"
//?src=\ref[src];AnnounceEvents=1'>Announce Events to Station:</a></b> [announce_events ? "Yes" : "No"]<br>"
//?src=\ref[src];TimeLocks=1'>Time Locking:</a></b> [time_lock ? "Yes" : "No"]<br>"
//?src=\ref[src];MinPop=1'>[minimum_population] players</a><br>"
//?src=\ref[src];TimeLower=1'>[round(time_between_events_lower / 600)]m</a> /"
//?src=\ref[src];TimeUpper=1'>[round(time_between_events_upper / 600)]m</a><br>"
//?src=\ref[src];MTimeLower=1'>[round(time_between_minor_events_lower / 600)]m</a> /"
//?src=\ref[src];MTimeUpper=1'>[round(time_between_minor_events_upper / 600)]m</a>"
//?src=\ref[src];TriggerEvent=\ref[RE]'><b>[RE.name]</b></a>"
//?src=\ref[src];DisableEvent=\ref[RE]'>([RE.disabled ? "Disabled" : "Enabled"])</a>"
//?src=\ref[src];TriggerMEvent=\ref[RE]'><b>[RE.name]</b></a>"
//?src=\ref[src];DisableMEvent=\ref[RE]'>([RE.disabled ? "Disabled" : "Enabled"])</a>"
//?src=\ref[src];TriggerSEvent=\ref[RE]'><b>[RE.name]</b></a><br>"
// global variable name is currently "hydro_controls"
// How many items can be harvested at once.
// How long between harvests, in spawn() ticks.
// You need to do plants after the others or they won't set up properly due to mutations and strains
// not having been set up yet
// hopefully this doesn't break anything!!
//Add special daily variety job
// Cull any of those nasty null jobs from the category heads
//?src=\ref[src];AlterCap=\ref[JOB]'>[JOB.name]: [countJob("[JOB.name]")]/[JOB.limit]</A><BR>"
//?src=\ref[src];AlterCap=\ref[JOB]'>[JOB.name]: [countJob("[JOB.name]")]/[JOB.limit]</A><BR>"
//?src=\ref[src];AlterCap=\ref[JOB]'>[JOB.name]: [countJob("[JOB.name]")]/[JOB.limit]</A><BR>"
//?src=\ref[src];AlterCap=\ref[JOB]'>[JOB.name]: [countJob("[JOB.name]")]/[JOB.limit]</A><BR>"
//?src=\ref[src];AlterCap=\ref[JOB]'>[JOB.name]: [countJob("[JOB.name]")]/[JOB.limit]</A><BR>"
//?src=\ref[src];AlterCap=\ref[JOB]'>[JOB.name]: [countJob("[JOB.name]")]/[JOB.limit]</A><BR>"
//?src=\ref[src];AlterCap=\ref[JOB]'>[JOB.name]: [countJob("[JOB.name]")]/[JOB.limit]</A>"
//?src=\ref[src];RemoveJob=\ref[JOB]'>(Remove)</A><BR>"
// JOB CONFIG COMMANDS
// JOB CREATOR COMMANDS
// I tweaked this section a little so you can actual search for certain items.
// Scrolling through a list of ~2600 items wasn't exactly great (Convair880).
// These cards can't be worn on the ID slot and they're not compatible with the
// job controller because they don't support access lists (Convair880).
// I wish there would be a better way to filter this stuff, typesof() just doesn't cut it.
// I suppose this is still slightly more elegant than the fixed (and outdated) list that
// used to be here. Anway, the job controller will not spawn unsuitable items (Convair880).
// Ditto (Convair880).
// Ditto (Convair880).
// Ditto (Convair880).
// to cover the base materials
// magnet vars
/// *** MISC *** ///
// handles timed player actions
// handles air processing.
// 2.5 seconds
// 0.8 seconds
//Handles blobs without being pissy about it
// 3.1 seconds
/*var/currentTick = ticks
for(var/obj/blob/B in blobs)
if (prob (B.life_prob))
B.Life()
detailed_count["[B.type]"]++
scheck(currentTick)*/
//Will only actually do something if it needs to.
// handles critters
// 1.6 seconds
/*var/currentTick = ticks
for(var/obj/critter in critters)
tick_counter = world.timeofday
critter:process()
tick_counter = world.timeofday - tick_counter
if (critter && tick_counter > 0)
detailed_count["[critter.type]"] += tick_counter
scheck(currentTick)*/
//var/tmp/delpause = 1
// Timing vars
//var/datum/dynamicQueue/queue =
// If we can't locate it, it got garbage collected.
// If it isn't disposed, it got garbage collected and then a new thing used its ref.
// If we have been forced to delete the object, we do the following:
// Because we have already logged it into the gc count in qdel.
// Delete that bitch
//if (delpause)
//sleep(delpause)
// The amount of time taken for this run is recorded only if
// the number of items considered is equal to the chunk size
// If the number of items processed is equal to the chunk size
// and the average time taken by the delete queue is greater than the scheduled interval
// handles items
/*for(var/obj/item/item in processing_items)
tick_counter = world.timeofday
item.process()
tick_counter = world.timeofday - tick_counter
if (item && tick_counter > 0)
detailed_count["[item.type]"] += tick_counter
scheck(currentTick)
*/
// TODO
// handles machines
//The amount of time spent processing this machine in total
//The amount of times this machine has been processed
// handles critters
// 1.6 seconds
/*var/currentTick = ticks
for(var/obj/critter in critters)
tick_counter = world.timeofday
critter:process()
tick_counter = world.timeofday - tick_counter
if (critter && tick_counter > 0)
detailed_count["[critter.type]"] += tick_counter
scheck(currentTick)*/
// handles mobs
// For periodic antag overlay updates (Convair880).
// a r g h
// putting this in a var so main loop varedit can get into the particleMaster
// TODO roll the "loop" code from particleMaster back into this system
// regular timing doesn't really apply since particles abuse the shit out of spawn and sleep
// Process
/**
* State vars
*/
// Main controller ref
// 1 if process is not running or queued
// 1 if process is queued
// 1 if process is running
// 1 if process is blocked up
// 1 if process was killed
// Status text var
// Previous status text var
// 1 if process is disabled
/**
* Config vars
*/
// Process name
// Process schedule interval
// This controls how often the process would run under ideal conditions.
// If the process scheduler sees that the process has finished, it will wait until
// this amount of time has elapsed from the start of the previous run to start the
// process running again.
// run every 50 ticks
// Process sleep interval
// This controls how often the process will yield (call sleep(0)) while it is running.
// Every concurrent process should sleep periodically while running in order to allow other
// processes to execute concurrently.
// hang_warning_time - this is the time (in 1/10 seconds) after which the server will begin to show "maybe hung" in the context window
// hang_alert_time - After this much time(in 1/10 seconds), the server will send an admin debug message saying the process may be hung
// hang_restart_time - After this much time(in 1/10 seconds), the server will automatically kill and restart the process.
// cpu_threshold - if world.cpu >= cpu_threshold, scheck() will call sleep(1) to defer further work until the next tick. This keeps a process from driving a tick into overtime (causing perceptible lag)
// How many times in the current run has the process deferred work till the next tick?
/**
* recordkeeping vars
*/
// Records the time (1/10s timeofday) at which the process last finished sleeping
// Records the time (1/10s timeofday) at which the process last began running
// Records the number of times this process has been killed and restarted
// Tick count
// Initialize last_slept so we can know when to sleep
// Initialize run_start so we can detect hung processes.
// Initialize defer count
// If world.timeofday has rolled over, then we need to adjust.
//finished()
// Allow inheritors to clean up if needed
// This should del
// The kill proc is the only place where killed is set.
// The kill proc should have deleted this datum, and all sleeping procs that are
// owned by it.
// This will only really help if the doWork proc ends up in an infinite loop.
// For each tick the process defers, it increments the cpu_defer_count so we don't
// defer indefinitely
// If world.timeofday has rolled over, then we need to adjust.
// If we haven't slept in sleep_interval deciseconds, sleep to allow other work to proceed.
// Clear delta
// handles only materials research right now.
// handles telescope signals and whatnot
// handles the game ticker
// start the pregame process
// handles various global init and the position of the sun.
// Singleton instance of game_controller_new, setup in world.New()
// Processes known by the scheduler
// Processes that are currently running
// Processes that are idle
// Processes that are queued to run
// Process name -> process object map
// Process last start times
// Process last run durations
// Per process list of the last 20 durations
// Process highest run time
// Sleep 1 tick -- This may be too aggressive.
// Controls whether the scheduler is running or not
// Setup for these processes will be deferred until all the other processes are set up.
/**
* deferSetupFor
* @param path processPath
* If a process needs to be initialized after everything else, add it to
* the deferred setup list. On goonstation, only the ticker needs to have
* this treatment.
*/
// There can be only one
// Add all the processes we can find, except for the ticker
// Hopefully spawning this for 50 ticks in the future will make it the first thing in the queue.
// Process was killed
// Check status changes
//Status changed.
// Don't double-queue, don't queue running processes
// If world.timeofday has rolled over, then we need to adjust.
// If the process should be running by now, go ahead and queue it
// init recordkeeping vars
// init starts and stops record starts
// Set up process
// Save process in the name -> process map
// The other state transitions are handled internally by the process.
// If world.timeofday has rolled over, then we need to adjust.
/**
* recordRunTime
* Records a run time for a process
*/
/**
* averageRunTime
* returns the average run time (over the last 20) of the process
*/
// New tick!
// Time allowance goes down linearly with world.cpu.
//timeAllowance = world.tick_lag * min(1, 0.5 * ((200/max(1,cpuAverage)) - 1))
// how much cooking it needs to get a healing bonus
// what you get from this recipe
// used for naming of human meat dishes after their victims
//If returning an object, that is used as the output
//fillings += snack.name
//, 1, 1)
//sandwichIcon.Blend(slice1.food_color, ICON_ADD)
//qdel(slice1)
//, 1, 1)
//newFilling.Blend(fillingColors[fillingColors.len], ICON_ADD)
//, 1, 1)
//newFilling.Blend( slice2.food_color, ICON_ADD)
//qdel(slice2)
//Cookies
//Moon pies!
//Well, that huge thing you put into it isn't going to shrink, you know
// if (!anItem)
// return null
//Delightful Halloween Recipes
//Cakes!
//Requirements for individual objectives: 1) You have a mind (this eliminates 90% of our playerbase ~heh~)
//2) You are not a traitor
//can be dead as people usually suicide
//think that's everything...
//can also be dead I guess
//split this up as it was long
// securityofficer
// barman
// chef
// engineer
// just fyi dont make a "gather ore" objective, it'd be a boring-ass grind (like mining is(dohohohoho))
//really shitty, I know
//ugh
/*artifact // This is going to be really fucking awkward to do so disabling for now
explanation_text = "Activate at least one artifact on the station z level by the end of the round, excluding the test artifact."
check_completion()
for(var/obj/machinery/artifact/A in machines)
if(A.z == 1 && A.activated == 1 && A.name != "Test Artifact") return 1 //someone could label it I guess but I don't want to go adding an istestartifact var just for this..
return 0*/
// so much copy/pasted stuff :(
//borgs gib when they die so no need to check stat I think
//prerequesites
//borgs gib when they die so no need to check stat I think
//Keeping this around just in case some idiot gets a medal in an admin gimmick or something
//checking basic stuff - they escaped alive and have an ID
//checking basic stuff - they escaped alive and have an ID
// cyborg
// designation of the
// pixel offset on the x axis for mob overlays
// pixel offset on the x axis for mob overlays
// the icon of the HUD object
// the icon state of the HUD object
// the item being worn in this slot
// a list of parent types whose subtypes are equippable
// ease of life
// pun
// designation of the hand - purely for show
// used for inhand icons
// pixel offset on the x axis for inhands
// pixel offset on the y axis for inhands
// the layer of the inhands overlay
// the item held in the hand
// the icon of the hand UI background
// the icon state of the hand UI background
// ease of life
// name for the dummy holder
// if not null, the special limb to use when attack_handing
// self-explanatory
// also
// does this limb have a special thing for attacking at a distance
// technically a dummy, do not set.
// @todo finish this
// Indicate safe range regardless of what the critter is breathing.
// well it has to make some SOMETHING.
// If there's some other shit in the air lets deal with it here.
// Enough to make us paralysed for a bit
// 3 gives them one second to wake up and run away a bit!
// Enough to make us sleep as well
// There is sleeping gas in their lungs, but only a little, so give them a bit of a warning
// this part is shit and probably should be purged, but generalizing hud might be unwanted
// this part is shit and probably should be purged, but generalizing hud might be unwanted
// the maximum amount of health this holder has
// the current amount of health this holder has
// value at the last call of Life() - maintained automatically
// the lowest amount of health this holder can represent
// if the value reaches this threshold, on_deplete() is called
// currently displayed level of overlay, helps to check if update is needed
// if true, damage overlay will be blood colored
// if true, the mob's health will be increased by the value of this
// and maximum health will be increased by the maximum value of this
// The mob still dies at health = 0
//
// stats["animes"] = 0
// stats["literally"] = 0
// stats["gayirl"] = 0
//DEBUG("[p] = [stats[p]]")
// boutput(world, "[p] = [stats[p]]")
// var/gayirl = 0
// this should cover all misspellings of "grief"
// else if(token in list("o.o", "o_o", "^_^", "^^", "<.<", ">.>", "<<", ">>", "-.-", "-_-"))
// game_stats.Increment("animes")
// else if(token == "gay" && gayirl == 0)
// gayirl = 1
// else if(token == "irl" && gayirl == 1)
// gayirl = 2
// game_stats.Increment("gayirl")
// Disabled for the sake of what I wanted to do with this, left write to file code commented.
// WriteToFile(var/filetxt)
// var/stats_file = null
// if(!fexists(filetxt))
// stats_file = file(filetxt)
// var/header = ""
// for(var/p in stats)
// header += "[p]&emsp;"
// boutput(stats_file, header)
// else
// stats_file = file(filetxt)
// var/data_str = ""
// for(var/p in stats)
// data_str += "[stats[p]]&emsp;"
// stats_file << data_str
//
//set src in world
//?src=\ref[src];Vars=\ref[D];varToEdit=[V]'><font size=1>Edit</font></a> <a href='byond://?src=\ref[src];Vars=\ref[D];varToEditAll=[V]'><font size=1>(A)</font></a> <a href='byond://?src=\ref[src];Vars=\ref[D];setAll=[V]'><font size=1>(S)</font></a>"
//?src=\ref[src];Vars=\ref[D];procCall=[V]'><font size=1>(P)</font></a>"
//?src=\ref[src];Refresh=\ref[D]'>Refresh</a>"
//?src=\ref[src];CallProc=\ref[D]'>Call Proc</a> <br>"
//?src=\ref[src];JumpToThing=\ref[D]'>Jump To</a>"
//?src=\ref[src];GetThing=\ref[D]'>Get</a>"
//?src=\ref[src];PlayerOptions=\ref[D]'>Player Options</a>"
//?src=\ref[src];SetDirection=\ref[D];DirectionToSet=L90'><<==</a> "
//?src=\ref[src];SetDirection=\ref[D];DirectionToSet=L45'><=</a> "
//?src=\ref[src];SetDirection=\ref[D]'>Set Direction</a> "
//?src=\ref[src];SetDirection=\ref[D];DirectionToSet=R45'>=></a> "
//?src=\ref[src];SetDirection=\ref[D];DirectionToSet=R90'>==>></a><br>"
/* else if (istype(value, /image))
#ifdef VARSICON
var/rnd = rand(1, 10000)
var/image/I = value
src << browse_rsc(I.icon, "tmp\ref[value][rnd].png")
html += "[name] = <img src=\"tmp\ref[value][rnd].png\">"
#else
html += "[name] = /image (<span class='value'>[value]</span>)"
#endif
*/
//?src=\ref[src];Vars=\ref[value]'>[name][src.holder.level >= LEVEL_SHITGUY ? " \ref[value]" : ""]</a> = [D.type][dname]"
//?src=\ref[src];Vars=\ref[value]'>[name][src.holder.level >= LEVEL_SHITGUY ? " \ref[value]" : ""]</a> = [C] [C.type]"
// not sure if this is completely right...
// (L.vars.len > 0)
//Let's prevent people from promoting themselves, yes?
//Short list - might be good if there are more objects that oughta be paws-off
//If someone tries this let's make sure we all know it.
//var_value = "[bicon(var_value)]"
//return <- Way to screw up logging
// all the vars that don't change/are defaults go in here - these will be in a central list for referencing
// what type this shows up as on scanners
// how do we get rid of it
// printed name for health scanners
// how many stages the disease has overall
// % chance per tick it'll advance a stage
// what kind of mobs does this disease affect
// no fuckin idea
// which reagents cure this disease...
// ...and how likely % they are per tick to do so
// bodytemperature >= this will purge the infection
// detectors must >= this to pick up the disease
// how likely this disease is to grant immunity once cured
// how many times at once you can have this ailment
// set to avoid bizarre interactions (such as surgerizing out a single disease multiple times)
// This is still subject to serious change. For now it's mostly a mockup.
// Determines things that may happen during a surgery for different ailments
// requiring a surgeon's intervention. Currently used for the parasites.
// Returns a true value if the surgery was successful.
// associated reagent, duh
// A list of things for people to research about the disease to make it
// Used for Rhinovirus
// IMPLEMENT PROPER CURE PROC
// these will be the local thing on mobs that does all the effecting, and they store unique vars so we can still
// have unique strains of disease and whatnot
/////////////////////////////////////////////////////////////////////////
// we reference back to the ailment itself to get effects and static vars
// the poor sod suffering from the disease
// an override - uses the base disease name if null - if not, it uses this
// scans must >= this to detect the disease
// how do we get rid of it
// what stage the disease is currently at
// what is this disease currently doing
// how likely is this disease to advance to the next stage
// list of reagents that can cure this disease
// probability per tick that the reagent will cure the disease
// this temp or higher will cure the disease
// how likely this disease is to grant immunity once cured
// how likely is this disease to spread
// can you develop a resistance to this?
// how does this disease transmit itself around?
// does this disease have a cyclical nature? if so, how many cycles have elapsed?
// if it's less than one just get rid of it, goddamn
// Common cures
// vary it up a bit so the processing doesnt look quite as transparent
// for headspiders
// no mob (somehow), so fuck this shit!
// didn't specify a disease to check against
// can't find shit, captain!
// If we've already got this disease or are resistant to it, then NOPE
// duplicate strain checking is in the main loop because otherwise bypass resistance ignores it
//Current thought: It's really weird for a base mob proc to run istypes on itself.
// Only valid vector species can get a disease.
//Dead folks cannot get non-parasitoid infections.
// if you don't breathe it in, you're fine
// mask but no air supply - still better than nothing
// we successfully resisted it
// you caught the virus! do you want to give the captured virus a nickname? virus has been recorded in lurgydex
// can't find shit, captain!
//Vampires and changelings are immune to disease, as are the godmoded.
//This is here rather than in the resistance check proc because otherwise certain things could bypass the
//hard immunity these folks are supposed to have
// carrier - will spread it but won't suffer from it
// Addiction with comically-exaggerated withdrawal effects!
//clownmask.cursed = 1
//Hope you like your new mask sucka!!!!!
//clownmask.cursed = 1
//clownsuit.cursed = 1
//clownshoes.cursed = 1
// NPCs should always be cluwnable, I guess (Convair880)?
//src.oldname = affected_mob.real_name
//src.oldjob = affected_mob.job
//Hope you like your new mask sucka!!!!!
// Don't remove.
// The mask IS your new face (Convair880).
// Don't remove.
// The mask IS your new face (Convair880).
// Reduced from 100 %. Station-wide, basically incurable and unavoidable epidemics weren't fun (Convair880).
// Increased from 0 %.
//
//
//Pretend to be a cold and give time to spread.
//Save original dna for when the disease is cured.
//Just chill out at stage 4
//associated_reagent = ""
// TODO: port to the new lighting system, I have no fucking idea how I'm meant to store the light datum
/*affected.sd_SetLuminosity(luminosity)
affected.sd_SetColor((255 - rand(0, 40))/255, (255 - rand(10,90)) / 255, (255 - rand(15, 110)) / 255)*/
// Stole this shit from GBS
// Reduced from 100 %. Station-wide, basically incurable and unavoidable epidemics weren't fun (Convair880).
// Increased from 0 %.
//
// takes too goddamn long
//
// im doctor
//Take the mob under the control of the original headspider.
// Only make a ghost for the other player if they have a client. Otherwise, infinite ghosts.
// Absorb their DNA. Copies identities and DNA points automatically if victim was another changeling.
// Remove changeling AH (if any) and copy our own.
// Transfer player control.
//Retain the disease but don't actually do anything with it
//Disease stays for two minutes after a complete infection, then it removes itself.
// Less code duplication and stuff. See werewolf.dm (Convair880).
// Necessary. Disease datums seem to be pooled or something, dunno.
//
//
// im doctor
//IBM note: haha this is the dumbest thing I have ever coded
//
//Nanomachines!
//So everyone can feel like robot Seth Brundle
// For forensics (Convair880).
// Reset their view of the map. Yes, this was missing for many years (Convair880).
// Buffed this somewhat, as grave fever was quite underwhelming (Convair880).
//The other vamplague, the one that makes vampires
// Queue bins -- sizing
// Make sure there is always at least one bin available in the queue
// Get the bin at the end of the queue
//Get the last bin in the queue
// If the bin has grown too large, throw it back and build a new one
// Take special care of lists...
/////////////////////////////////////////////
//// SMOKE SYSTEMS
// direct can be optinally added when set_up, to make the smoke always travel in one direction
// in case you wanted a vent to always smoke north for example
/////////////////////////////////////////////
// To stop it being spammed and lagging!
// the size of the foam spread.
// the IDs of reagents present when the foam was mixed
// 0=foam, 1=metalfoam, 2=ironfoam,
// FUCK infinifoam holy shit
// bit of a hack here. Foam carries along any reagent also present in the glass it is mixed
// with (defaults to water if none is present). Rather than actually transfer the reagents,
// this makes a list of the reagent ids and spawns 1 unit of that reagent when the foam disolves.
// don't carry other chemicals if a metal foam
//Limit reagents in foam to 3 so the nerds can't bomb eveyrthing all day
/////////////////////////////////////////////
//// SMOKE SYSTEMS
// direct can be optinally added when set_up, to make the smoke always travel in one direction
// in case you wanted a vent to always smoke north for example
/////////////////////////////////////////////
// To stop it being spammed and lagging!
/////////////////////////////////////////////
//// SMOKE SYSTEMS
// direct can be optinally added when set_up, to make the smoke always travel in one direction
// in case you wanted a vent to always smoke north for example
/////////////////////////////////////////////
// To stop it being spammed and lagging!
// To stop it being spammed and lagging!
///datum/effects/system/spark_spread/Del()
//pool(src)
//no no no no no stop doing this what the fuck man aaaaaaaa -singh
// get direction
// get distance
// Only do hotspot for tiles that dont already have sparks on them
// Move the sparks
// Kill the spark in 20 ticks
// Create sparks
// Check spawn limits
// Create sparks
// Set direction and distance to travel
// Store direction and distance to travel as the high quad and low quad of the low byte
/////////////////////////////////////////////
// GENERIC STEAM SPREAD SYSTEM
//Usage: set_up(number of bits of steam, use North/South/East/West only, spawn location)
// The attach(atom/atom) proc is optional, and can be called to attach the effect
// to something, like a smoking beaker, so then you can just call start() and the steam
// will always spawn at the items location, even if it's moved.
/* Example:
var/datum/effects/system/steam_spread/steam = new /datum/effects/system/steam_spread() -- creates new system
steam.set_up(5, 0, mob.loc) -- sets up variables
OPTIONAL: steam.attach(mob)
steam.start() -- spawns the effect
*/
/////////////////////////////////////////////
/////////////////////////////////////////////
//////// Attach a steam trail to an object (eg. a reacting beaker) that will follow it
// even if it's carried of thrown.
/////////////////////////////////////////////
/*********************************
EHJAX - Like ajax but for ~byond~
A framework for browser popups to interact with the byond server, async (client-side)
*********************************/
/**
* Calls a proc from a javascript source and callsback with any data
*
* @href_list["call"] (string) The proc to call (no paths included)
* @href_list["window"] (string) The browser window name to send return data to (required for callback)
* @href_list["params"] (string) A url-encoded array of arguments to pass to the proc (e.g. params[foo]=bar&params[bar]=foo)
* @href_list["type"] (string) Type of proc to call. If none, assumes global proc.
* @href_list["datum"] (string) Requires type=datum. Name of the datum the proc belongs to (/datum/ path not required)
* Note: datum is relative to client ONLY.
*
* @return (string) If the call proc returns data and window is set, will send the proc return string to ehjaxCallback javascript function.
*
*/
//Generate the full proc path to check against whitelist
//This needs data to send back to the window.
//else
// qdel(signal)
// state -1
//state 1
// state -2
//radio signal
//state 2
//state 1
//else
//qdel(signal)
// Setup parameters only
// Setup parameters only
// Setup parameters only
//lower bound on time before intercept arrives (in tenths of seconds)
//upper bound on time before intercept arrives (in tenths of seconds)
//num_blobs = max(0, num_blobs - 1)
//No treason for you
//No treason for you
//lower bound on time before intercept arrives (in tenths of seconds)
//upper bound on time before intercept arrives (in tenths of seconds)
//num_changelings = max(0, num_changelings - 1)
//HRRFM horror form stuff goes here
// Moved antag help pop-up to changeling.dm (Convair880).
//No treason for you
//No treason for you
// Create a supply post.
// grace period: 1 hour
//add to red team else to green
// 1/10 second
// TODO: DEFERRED Make this massively cleaner. It should hook before spawning, not after.
// there are WAY more things than this to change, I'm almost certain
//This should be set by the disaster start!!
//Time before the disaster starts.
//Time until the shuttle can be called.
// boutput(world, "disaster loaded :I")
//Disable the shuttle temporarily.
//
// ready up some effects and noises
// set back to normal rotation
//List of gang stuff already used so that there are no repeats.
//list of all existing gang lockers
//lower bound on time before intercept arrives (in tenths of seconds)
//upper bound on time before intercept arrives (in tenths of seconds)
//maximum number of gang members, not including the leader
//1 gang per 12 players
//ToDo: One of those goofy popup windows?
//No treason for you
//No treason for you
// Admin-assigned antagonists or whatever.
// increase if you add more tags!
// increase if you add more tags!
//Unique name.
// Find the highest score
// See if two gangs have the highest score ie. it's a draw
//oh god
//cant think of a better way to do this
//i think this can be made in huge volumes with lots of weed? should encourage weed to be left in plant form
//meth
//procs below are for round end stats, i think for actual score calculations its more efficient to use the above though
//cant think of a better way to do this
//i think this can be made in huge volumes with lots of weed? should encourage weed to be left in plant form
//meth
//no point rounding it really but fuck it
// /obj/decal/cleanable/gangtag moved to decal.dm
//Let detectives join gangs, they don't get tasers etc anyway
//gang member cap might've increased in which case they all need updating
// Needs new gear? Maybe!
//boutput(world, "removing [O]")
//basic for now but might be expanded on so I'm making it a proc of its own
// Don't implement ticker.mode.name or .config_tag checks again, okay? I've had to swap them all to get game mode children to work.
// Use istype(ticker.mode, /datum/game_mode/whatever) instead.
// Overridden by the server config. If you don't have access to that repo, keep it 0.
// 0: Won't dock. | 1: Normal. | 2: Won't dock if called too early.
// 20 min. Only works when shuttle_available == 2.
// Ultimately depends on the global 'late_traitors' setting, though.
// Don't spawn 'em until all antagonists are dead.
// Unrecognized roles default to traitor in mob/new_player/proc/makebad().
// enemies assigned at round start
//players redeeming an antag token
// admin assigned and certain gimmick enemies
// For mindslaves and rogue cyborgs we'd want to show in the game over stats (Convair880).
// yes. fucking manufacturers
// Fuck.
// F U C K
// Did some streamlining here (Convair880).
// Objectives are irrelevant for mindslaves and thralls.
// Ditto.
// Werewolves may not have the feed objective, so we don't want to make this output universal.
// Same reasoning here, really.
// Please use objective.medal_name for medals that are tied to a specific objective instead of adding them here.
// Their antag status is revoked on death/implant removal/expiration, but we still want them to show up in the game over stats (Convair880).
////////////////////////////
// Objective related code //
////////////////////////////
/*if(malf_ai.len < 1)
boutput(world, "Uh oh, its malfunction and there is no AI! Please report this.")
boutput(world, "Rebooting world in 5 seconds.")
sleep(50)
world.Reboot()
return*/
// boutput(malf_ai:current, "You may decide to blow up the station. You have 30 seconds to choose.")
// boutput(malf_ai:current, text("<A HREF=?src=\ref[src];ai_win=\ref[malf_ai:current]>Self-destruct the station</A>)"))
// cogwerks - lowered from 10
//lower bound on time before intercept arrives (in tenths of seconds)
//upper bound on time before intercept arrives (in tenths of seconds)
// adjust divisor as needed
// powerful combat roles
// if any combat roles end up in this mode they go here ok
// more stealthy roles
//num_wizards = max(0, num_wizards -1)
//num_traitors = max(0, num_traitors -1)
//num_changelings = max(0, num_changelings -1)
//num_vampires = max(0, num_vampires -1)
//num_wraiths = max(0, num_wraiths -1)
//num_blobs = max(0, num_blobs -1)
// Gotta reset this.
// vamp will burn in the chapel before he can react
// Cannot create objects of type null. [wraiths use a special proc]
//No treason for you
//No treason for you
// The name of our target area. Used for text output.
// Our area.type, which can be multiple (e.g. medbay).
//Has the nuke gone off?
//:h for syndies, randomized per round
// See check_finished().
//If we ever need more syndicate agents. cogwerks - raised from 5
//lower bound on time before intercept arrives (in tenths of seconds)
//upper bound on time before intercept arrives (in tenths of seconds)
// I wandered in and made things hopefully a bit easier to work with since we have multiple maps now - Haine
// COG1
// Don't ask, it just fits all criteria. Deathstar weakness or something.
// now that we've done everything that could cause the round to fail to start (in this proc, at least), we can deal with antag tokens
//So they aren't chosen for other jobs.
// So they don't all spawn on the same tile.
// First ticker.process() call runs before the bomb is actually spawned.
// Minor Syndicate Victory - crew escaped but bomb was armed and counting down
// Major Station Victory - bombing averted, all operatives dead/captured
// Minor Station Victory - bombing averted, but operatives escaped
// don't end the game if the bomb is armed and counting, even if the ops are all dead
// Major Station Victory - bombing averted, all operatives dead/captured
// Minor or major Station Victory - bombing averted in any case.
// Major Synd Victory - nuke successfully detonated
// Minor Synd Victory - station abandoned while nuke armed
// Uhhhhhh
// Minor Crew Victory - station evacuated, bombing averted, operatives survived
// Major Crew Victory - bombing averted, all ops dead/captured
//Listing custom antagonists.
// If they're dead
// If they're in a brig cell and cuffed
//No treason for you
//No treason for you
// The old blacklist was rather incomplete and thus ineffective (Convair880).
// Prefix
// Suffix
// Full
// Broken
// Small
//return a useful string describing the target
// To add a rev to the list of revolutionaries, make sure it's rev (with if(istype(ticker.mode, /datum/game_mode/revolution))),
// then call ticker.mode:add_revolutionary(_THE_PLAYERS_MIND_)
// nothing else needs to be done, as that proc will check if they are a valid target.
// Just make sure the converter is a head before you call it!
// To remove a rev (from brainwashing or w/e), call ticker.mode:remove_revolutionary(_THE_PLAYERS_MIND_),
// this will also check they're not a head, so it can just be called freely
// If the rev icons start going wrong for some reason, ticker.mode:update_all_rev_icons() can be called to correct them.
// If the game somtimes isn't registering a win properly, then ticker.mode.check_win() isn't being called somewhere.
//lower bound on time before intercept arrives (in tenths of seconds)
//upper bound on time before intercept arrives (in tenths of seconds)
// 35 minutes (see post_setup)
//Do not end prematurely
// this has got to end soon
// 10 minutes to clean up shop
// 5 minutes until everyone dies
// welp
// Includes rev_mind.
//No treason for you
//No treason for you
//for(var/mob/living/carbon/human/player in mobs)
// don't count gibbed dudes on centcom win
// Run through all the heads
// If they exist, have a mob and aren't dead
// Check to see if they're a robot
// If they're a robot don't count them
// Check if they're on the current z-level
// If they are then don't end the round
// This return means that they're alive and on the first z level and are not a robot
// Check to see if they're a robot
// If they're a robot don't count them
// Admin-assigned antagonists or whatever.
// migrated from h_sandbox.dm
//
//I guess this is possible if they log out or die with the panel open? It happened.
//TODO: DEFERRED make this better, with an HTML window or something instead of 15 popups
//var/obj/hsb = new/obj/weldfueltank
//hsb.set_loc(usr.loc)
//var/obj/hsb = new/obj/watertank
//hsb.set_loc(usr.loc)
// if(ispath(O, /obj/item/gun))
// continue
// if(ispath(O, /obj/item/assembly))
// continue
// if(ispath(O, /obj/item/camera))
// continue
// if(ispath(O, /obj/item/cloaking_device))
// continue
//[00:45] AngriestIBM Let me generate a round backstory in 5 seconds: This is how the syndicate determines who gets higher ranking positions -- by handing the candidates quad-injectors of mindslaves and having them fight to the death
// Idea: each leader gets a unique goofy experimental piece of equipment, traitor gear that needs field testing (Or worse)
// ex: bottle of corrosive fermid oil, OmegaFlash (field effect turboflash), etc
// like the R&D stuff in paranoia
//lower bound on time before intercept arrives (in tenths of seconds)
//upper bound on time before intercept arrives (in tenths of seconds)
// They have to stay alive, dunno why dying a glorious death was a possible objective.
//equip_traitor(leader) <- Quad mindslaves and the starter gear are more than sufficient. Spies really don't need a traitor uplink on top of that.
//No treason for you
//No treason for you
// Admin-assigned antagonists or whatever.
//todo - implantation when there is another XL already in here
//Name of whatever TERRIBLE DEMON the cultists are trying to spawn
//Sleeper agent.
//Maximum possible number of cultists.
//to-do
//Can man name a terror he cannot even comprehend??
//I dunno but this proc sure can
//Who worships this thing??
//lower bound on time before intercept arrives (in tenths of seconds)
//upper bound on time before intercept arrives (in tenths of seconds)
// adjust the randomizer as needed
// only allow 1 wraith to spawn
//Randomly pick from the token list so the first person to ready up doesn't always get it.
/*num_traitors--
num_traitors = max(num_traitors, 0)*/
// Gotta reset this.
//No treason for you
//No treason for you
//No treason for you
//No treason for you
//lower bound on time before intercept arrives (in tenths of seconds)
//upper bound on time before intercept arrives (in tenths of seconds)
//So they aren't chosen for other jobs.
// var/I = image(antag_wizard, loc = waldo.current)
// waldo.current.client.images += I
// waldo.current << browse('waldo.jpg',"window=some;titlebar=1;size=550x400;can_minimize=0;can_resize=0")
// generate a passcode if the uplink is hidden in a PDA
//Hide the uplink in a PDA if available, otherwise radio
//lower bound on time before intercept arrives (in tenths of seconds)
//upper bound on time before intercept arrives (in tenths of seconds)
/*--num_wizards
num_wizards = max(num_wizards, 0)*/
//No treason for you
//No treason for you
// OK fuck this shit
/* //Latejoin bad guys come now if all the wizards are dead rather than the round ending.
var/wizcount = 0
//var/wizdeathcount = 0
var/wincount = 0
if(ticker.mode.Agimmicks.len > 0)
for(var/datum/mind/W in ticker.mode.Agimmicks)
if(!(W in src.traitors))
wizards += W
for (var/datum/mind/W in wizards)
wizcount++
var/objectives_completed = 0
for(var/datum/objective/objective in W.objectives)
if(objective.check_completion()) objectives_completed++
if(objectives_completed == W.objectives.len) wincount++
//if(!W.current || W.current.stat == 2) wizdeathcount++
//if (wizcount == wizdeathcount) return 1
if (wizcount == wincount)
boutput(world, "wizcount [wizcount], wincount [wincount], ending round")
return 1
else return 0*/
/* -- moved to _setup.dm
#define GAME_STATE_PREGAME 1
#define GAME_STATE_SETTING_UP 2
#define GAME_STATE_PLAYING 3
#define GAME_STATE_FINISHED 4
*/
// In relation to world time.
// raised from 120 to accomodate the v500 ads
//Create and announce mode
// uhh is this where this goes??
//Configure mode and assign player to special mode stuff
//Distribute jobs
//Create player characters and transfer them
// rip collar key, nerds murdered people for you as non-antags and it was annoying
//implant_skull_key() //Solarium
//Create objectives for the non-traitor/nogoodnik crew.
//Equip characters
//Cleanup some stuff
//Deleting Startpoints but we need the ai point to AI-ize people later
// Moved wizard's den back to the top of the list for convenience. It's also sorted now (Convair880).
//Setup the hub site logging
// 10 minutes in
//Removes a token from the player
// Who cares about NPCs? Adding them here breaks all antagonist objectives
// that attempt to scale with total player count (Convair880).
//Hello, I will sneak in a solarium thing here.
//Okay enough gaming the system you pricks
// Minds are sometimes kicked out of the global list, hence the fallback (Convair880).
// on the slim chance that this happens exactly on a timeofday rollover
// make it nonzero so it doesn't quit updating
//End of round statistic collection for goonhub
//Export round end packet (normal completion)
// Score Calculation and Display
// Who is alive/dead, who escaped
// Escapee Scores
// Check station's power levels
// 200 charge leeway
// Check how much uncleaned mess is on the station
// Bonus Modifiers
//var/traitorwins = score_traitorswon
// Mode Specific
// Good Things
//Not sure what the multiplier should be, feel free to adjust it.
// This needs to be here for the bonus to be applied properly
// Bad Things
//if (score_crewscore != 0) // Dont divide by zero!
// while (traitorwins > 0)
// score_crewscore /= 2
// traitorwins -= 1
// Show the score - might add "ranks" later
/////
/////SETTING UP THE GAME
/////
/////
/////MAIN PROCESS PART
/////
//Standard extended process (incorporates most game modes).
//Put yours in here if you don't know where else to put it.
//malfunction process
//meteor mode!!! MORE METEORS!!!
//Anything else, like sandbox, return.
//Hack.
// don't judge me
//boutput(M, "<span style=\"color:blue\">A soothing wave of energy washes over you!</span>")
//boutput(M, "<span style=\"color:red\">The void tears at you!</span>")
// making the zone name a bit more obvious and making its spam chatbox less - ISN
// TODO: use these? I guess?
// this is causing a fucking LIST INDEX OUT OF BOUNDS ERROR. wow.
//var/obj/critter/gunbot/drone/D = pick(drone_templates)
// I know.
// I'll probably get a lot of flak for this.
// Like, not now, but 3 years from now when I'm declared mport over this by the future generation.
// But /obj/machinery/vehicle looks dumb.
// how does this happen?
// set return value to default
// damtype 0: brute, 1: fire, 2: mixed, attack type 0: kinetic, 1: energy, 2: mixed
//Defines don't work correctly here because FUCK BYOND ARGH
//#define effectTypeMutantRace 1
//#define effectTypeDisability 2
//#define effectTypePower 3
//SO INSTEAD , GLOBAL VARS. GEE THANKS BYOND.
//Name of the effect.
//Internal ID of the effect.
//Visible description of the effect.
// You get this in mutation research if you've activated the effect
// bioeffectlist version of this effect
// 0 = not, 1 = in progress, 2 = done, 3 = activated
//Used to categorize effects. Mostly used for MutantRaces to prevent the mob from getting more than one.
//Is this a bad effect? Used to determine which effects to use for certain things (radiation etc).
//The probability that this will be selected when building the effect pool. Works like the weights in pick()
//Amount of blocks generated. More will make this take longer to activate.
//Amount of gaps in the sequence. More will make this more difficult to activate since it will require more guessing or cross-referencing.
//How likely each block is to be locked when there's locks present
//How many base pairs in this sequence will need unlocking
//How many characters in the code?
//How many attempts before it rescrambles?
// How many different characters are used
// requires a specific research tech to see in genepools
// this bio-effect won't occur in the pools of mob types in this list
// bio-effect will only occur in this mob type
//Mob that owns this effect.
//Holder that contains this effect.
//Message shown when effect is added.
//Message shown when effect is removed.
//Time left for temporary effects.
//For effects with different variants.
//For effects that come with verbs
// Can this gene be turned into mats with the reclaimer?
// Can this gene be scrambled with the emitter?
//Is this gene copied over on bioHolder transfer (i.e. cloning?)
// If zero, it must be researched via brute force
// Guess.
// If set, need to research the mutation before you can do anything w/ this one
// Materials returned when this gene is reclaimed
// Chance % for a reclamation of this gene to fail
//Should be used to hold custom user data or it might not be copied correctly with injectors and all these things.
//Called when the effect is added.
//Called when the effect is removed.
//Called when the overlays for the mob are drawn.
//Called when the life proc of the mob is called.
//Gets a copy of this effect. Used to build local effect pool from global instance list.
//Please don't use this for anything else as it might not work as you think it should.
//Since we assume that the effect being copied is the one in the global pool we copy
//a REFERENCE to its correct sequence into the new instance.
//List of CORRECT blocks for this mutation. This is global and should not be modified since it represents the correct solution.
// List of CURRENT blocks for this mutation. This is local and represents the research people are doing.
//Things went completely and entirely wrong and everything is broken HALP.
//Some dickwad probably messed with the global sequence.
//NOPE
//NOPE
//Gets the normal sequence for this mutation and then "corrupts" it locally.
//Make sure you don't have more gaps than basepairs or youll get an error.
//But at that point the mutation would be unsolvable.
//Generate DNA blocks. This sequence will be used globally.
//4 pairs per block.
// reset cooldown
////////////////////////////////
// Resistances and Immunities //
////////////////////////////////
// you feel warm because you're resisting the cold, stop changing these around! =(
/////////////
// Healing //
/////////////
/////////////
// Stealth //
/////////////
///////////////////
// General buffs //
///////////////////
///////////////////////////
// Disabled/Inaccessible //
///////////////////////////
///////////////////////
// Totally Crippling //
///////////////////////
///////////////////////////
// Bad but not crippling //
///////////////////////////
// Marq fix for cannot read null.correct_bad_vision
// heh
///////////////////////////////////////
// Harmful to others as well as self //
///////////////////////////////////////
//////////////
// Annoying //
//////////////
////////////////////////////
// Disabled for *Reasons* //
////////////////////////////
//Overrides incomplete DNA sequences
// clear away any existing mutantraces first
// OnAdd()
// if (ishuman(owner))
// owner.add_ability_holder(/datum/abilityHolder/religious)
// temporary debuff for when the wizard gets shaved
// Variant 1 = Half Spell Cooldown, Variant 2 = No Spell Cooldown
// Only use variant 2 for debugging/horrible admin gimmicks ok
// Don't put this one in the standard mutantrace pool
// Probably shouldn't put this one in either
//Out of the cloning pod.
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//So people can still get the meat ending
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// lower health means more pain
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Dry run. Can we phaseshift?
// For forensics (Convair880).
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// why the hell was this set to 12 christ
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// COMBINATION-ONLY EFFECTS BELOW
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cant get the scary shit to work so tOt for now
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// very steep. probably grabs 3 or 4 objects per cast -- much less effective than revenant command
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////
// Admin Only //
////////////////
// just let this one handle itself for now
// Probably shouldn't look like this? http://f.666kb.com/i/d2iqlzm1qa2gk6dqs.png
//////////////////////
// Combination Only //
//////////////////////
//Global list of all uids and their respective mobs
//if(hasvar(M, "bioHolder"))
//Holds all the appearance information.
//Copies settings of another given holder. Used for the bioholder copy proc and such things.
// Disabling this for now as I have no idea how to fit it into hex strings
// I'm help -Spy
//customization_first_color += (toCopy.customization_first_color - customization_first_color) / adjust_denominator
//customization_second_color += (toCopy.customization_second_color - customization_second_color) / adjust_denominator
//customization_third_color += (toCopy.customization_third_color - customization_third_color) / adjust_denominator
//e_color += (toCopy.e_color - e_color) / adjust_denominator
//Isolate the RGB values
//Turn them into numbers
//Do the math and add to the output
//Rebuild the appearance of the mob from the settings in this holder.
// if the owner's not human I don't think this would do anything anyway so fuck it
//Holds the apperanceholder aswell as the effects. Controls adding and removing of effects.
//Get this high enough and you can be like Arnold. Maybe. I found that movie fun. Don't judge me.
//Unique id for the mob. Used for fingerprints and whatnot.
//AddEffect(E.id)
//effectPool.Remove(E)
// changed this to transfer the instance across rather than add a copy
// since some bioeffects have unique stuff
//New new new york
//Corrupt the local copy
//Corrupt the local copy
//Corrupt the local copy
//Corrupt the local copy
//Creates a new uid and returns it.
//Copies the settings of another given holder. Used for syringes, the dna spread virus and such things.
//Adds an effect to this holder. Returns the newly created effect if succesful else 0.
//Can only have one mutant race.
//Since this cleaning is always done we just ousted the only mutantrace in effects
//Removes an effect from this holder. Returns 1 on success else 0.
//Returns variant if this holder has an effect with the given ID else 0.
//Returns 1 if it has the effect with variant 0, special case for limb tone.
//HasAnyEffect() was already taken :I
//We cannot edit the args list directly, so just keep a count.
//Returns the effect with the given ID if it exists else returns null.
//Adds a random effect to this holder. Argument controls which type. bad , good, either.
//This is bonkers
//So is this
// Powers
// Beneficial
// Discovered
// Discovered
// Discovered
// Discovered
// Discovered
// Discovered
// Detrimental
// Discovered
// Discovered
// Discovered
// Useless
// Powers
// Discovered
// Discovered
// Discovered
// Discovered
// Discovered
// Discovered
// Discovered
// Discovered
// Discovered
// Mutantraces
// since the station starts with monkey already researched we dont really need multiple recipes
// this one's just for comedy's sake =v
// Discovered
// Discovered
// Discovered
// Discovered
// Discovered
// Discovered
// Discovered
// Traitor item
//Only used for record deletion right now.
//Linked scanner. For scanning.
// Injector, Analyser, Emitter, Reclaimer
//Hilariously hacky temporary print thing.
//if(H.bioHolder.HasEffectInEither(E.id))
// info_html = "<p>Operation error: Gene already present in subject's DNA.</p>"
// src.updateUsrDialog()
// return 1
//?src=\ref[src];menu=research")
//?src=\ref[src];stored_chromosome=\ref[E]")
//?src=\ref[src];menu=storedmuts")
//?src=\ref[src];menu=chromosomes")
//?src=\ref[src];menu=mutations")
//?src=\ref[src];menu=combinemuts")
// counts as researching it
//?src=\ref[src];menu=storedmuts")
//?src=\ref[src];menu=storedmuts")
//?src=\ref[src];menu=storedmuts")
// valid. still, wtf
//?src=\ref[src];stored_mut=\ref[E]")
//?src=\ref[src];vieweffect=\ref[E]")
//?src=\ref[src];menu=mutations")
//?src=\ref[src];viewpool=\ref[E]")
//?src=\ref[src];menu=potential")
//?src=\ref[src];menu=potential")
//?src=\ref[src];menu=potential")
//Change this to occupant and check if empty aswell.
//?src=\ref[src];viewpool=\ref[E]")
//OH MAN LOOK AT THIS CRAP. FUCK BYOND. (This refreshes the page)
//?src=\ref[src];viewpool=\ref[E]")
//?src=\ref[src];viewpool=\ref[E]") // i hear ya buddy =(
//?src=\ref[src];menu=mutations")
//send them to the mutations page.
//?src=\ref[src];viewpool=\ref[E]")
//?src=\ref[src];viewpool=\ref[E]")
//?src=\ref[src];sample_viewpool=\ref[E];sample_to_viewpool=\ref[sample]")
//?src=\ref[src];menu=resopen")
//?src=\ref[src];menu=resrunning")
//H.bioHolder.AddEffect(MR.id)
//info_html = "<p>Temporary : </p><a href='?src=\ref[src];copyself=1'>Copy Occupant to Self</a>" Disabled due to shitlords
//boutput(world, "failed carbon check")
//boutput(world, "failed E check")
//boutput(world, "failed GBE check")
//boutput(world, "failed GBE level check")
// Equipment Numbers:
// 1) Injectors
// 2) Analyser/Checker
// 3) Emitters
// 4) Reclaimer
// There weren't any (Convair880)!
// decimal value for how much is taken off the cost
// same but for time to research
// how much it costs to research mutations
//I could just change this quietly, but this.
//THIS FUCKING ABOMINATION stays here as a memory of someone's shame.
//researchTreeTiered = bubblesort(researchTreeTiered)
//var/tickDiff = 0
//if(!lastTick) lastTick = world.time
//tickDiff = (world.time - lastTick)
//This is only temporary to regenerate points while this isnt finished yet.
//Name of the research entry
//Description
//Internal. No need to mess with this.
//How long this takes to research in 1/10ths of a second.
//Tier of research. Tier 0 does not show up in the available research - this is intentional. It is used for "hidden" research.
// You need to research everything in this list before this one will show up
// Need to have researched these mutations first - list of requisite IDs.
// Need to have researched this many mutations total
//Has this been researched? I.e. are we done with it? 0 = not researched, 1 = researched, -1 = currently researching.
//Cost in research materials for this entry.
// Is this one accessible by players?
// Have we got the prerequisite researches?
// Do we have the neccecary # of muts researched?
// TIER ONE
// researchTime = 600 is one minute, keep that in mind
// Rewards for unlocking Complex DNA
// TIER TWO
// TIER THREE
// TIER FOUR
///////////////////////////////////
// Things related to DNA samples //
///////////////////////////////////
// Added (Convair880).
///////////////////////////////////////////////////////////////////////////////////////////////////////////
//?src=\ref[src];s_tone=input'><b>Skin Tone:</b></a> [-src.s_tone + 35]/220<br>"
//?src=\ref[src];eyes=input'><b>Eye Color:</b> <font face=\"fixedsys\" size=\"3\" color=\"[src.e_color]\"><b>#</b></font></a><br>"
//?src=\ref[src];customization_first=input'><b>Bottom Detail:</b></a> [src.customization_first] "
//?src=\ref[src];hair=input'><font face=\"fixedsys\" size=\"3\" color=\"[src.customization_first_color]\"><b>#</b></font></a><br>"
//?src=\ref[src];customization_second=input'><b>Mid Detail:</b></a> [src.customization_second] "
//?src=\ref[src];facial=input'><font face=\"fixedsys\" size=\"3\" color=\"[src.customization_second_color]\"><b>#</b></font></a><br>"
//?src=\ref[src];customization_third=input'><b>Top Detail:</b></a> [src.customization_third] "
//?src=\ref[src];detail=input'><font face=\"fixedsys\" size=\"3\" color=\"[src.customization_third_color]\"><b>#</b></font></a><br>"
//?src=\ref[src];apply=1'>Apply</a><br>"
//Cloner vars
//Built-in scanner.
//Built-in cloning pod.
//Built-in computer for i/o.
//Portable object vars
//Built-in scanner.
//Built-in cloning pod.
//Inbuilt computer for i/o.
//www.byond.com/forum/?post=195134
//45)
/*sleep(70)
del(src)*/
//45)
// Highly modular HUD for critters.
// green with green marker
// green
// yellow
// orange
// dark orange
// red
// crit
// dead
//for (var/obj/item/I in last_tools)
// remove_object(I)
// Handle light datums and the like.
// this is bad and i will fix it in 2025
// this is bad and i will fix it in 2025
//Handle box BG clicks
// naming these tools to distinuish it from the module of a borg
// prevent a division by zero
// this doesnt unequip the original item because that'd cause all the items to drop if you swapped your jumpsuit, I expect this to cause problems though
// ^-- You don't say.
// this is stupid but necessary
// items + standard
// genetics
// rip
// this goes the other way around from the normal health indicator since it's determined by how much of whatever damage you have
// bright green
// green
// yellow
// orange
// dark orange
// red
// crit
// bright green
// green
// yellow
// orange
// dark orange
// red
// crit
// bright green
// green
// yellow
// orange
// dark orange
// red
// crit
// bright green
// green
// yellow
// orange
// dark orange
// red
// crit
// may as well let you see you're being irradiated if you can already see individual things like oxy/tox/burn/brute
// dead
// green with green marker
// green
// yellow
// orange
// dark orange
// red
// crit
// blank
// on fire
// burning up
// far too hot
// too hot
// warm but safe
// cool but safe
// too cold
// far too cold
// freezing
// 310 is optimal body temp
// not rad :'(
// WHAT THE FUCK PAST MARQUESAS
// GET IT TOGETHER
// - Future Marquesas
// switch ("id")
// Handle light datums and the like.
// this is bad and i will fix it in 2025
// this is bad and i will fix it in 2025
// this is horrifying
// naming these tools to distinuish it from the module of a borg
// prevent a division by zero
// this is dumb
// this is dumb
// goddamn BIBLES (prevents conflicting positions within different bibles)
// ugh
// generic overlays for modifying the mobs vision
// hacky and incorrect but I didnt want to introduce another object just for this
// this is such a mess it gets its own HUD object
//WIRE TOOLTIPS
// self-explanatory
// this too
// is this a gene strain? a disease? a parasite?
// base chance of this mutation developing
// is this mutation something you shouldn't want?
// on_process's chance of actually occurring per call
// If this is set, plants will use this instead of regular plant name
// What crop does it give?
// same as in base plant thing really
// name of the sprite files in hydro_mutants.dmi
// If 1, you can harvest it irregardless of the plant's base harvestability
// If 0, just use the base plant's settings
// If 1, use the mutation's special_proc instead
// If anything else, use both the base and the mutant procs
// Ranges various genes have to be in to get the mutation to appear - lower and upper bound
// null means there is no limit so an upper bound of 25
// and no lower bound means the mutation will occur when
// the plant is below 25 in that gene, but can be as low
// as it wants otherwise with no consideration
// is a paticular common mutation required for this? (keeping it to 1 for now)
// How likely out of 100% is this mutation to appear when conditions are met?
// Used for extractions, harvesting, etc
// Tomato Mutations
// Grape Mutations
// Orange Mutations
// heh
// Melon Mutations
// Chili Mutations
// Eggplant Mutations
// Wheat Mutations
// Synthmeat Mutations
// coder.Life()
// whoops undefined proc
// haine has farted up a shitty recolored sprite for these, everyone rejoice
// Just slap your new organ in there.
// Soy Mutations
// Contusine Mutations
// Nureous Mutations
// Asomna Mutations
// Commol Mutations
// Venne Mutations
// Cannabis Mutations
// Fungus Mutations
// Lasher Mutations
// Radweed Mutations
// TODO what layer should this be on?
// Slurrypod Mutations
// Rock Plant Mutations
// trees. :effort:
// This file is arguably where all the "content" of Hydroponics lies, the framework being taken
// care of mostly in plantpot.dm - though some of it is also based here. This file contains
// all plant species and mutations that aren't ones created specifically for setpieces.
//
// Other files you'll want if you're looking up on Hydroponics stuff:
// obj/item/plants_food_etc.dm: Most of the seed and produce items are in here.
// obj/item/hydroponics.dm: The tools players use to do hydro work are here.
// obj/machinery/plantpot.dm: The plantpot file, where most of the Stuff happens.
// obj/submachine/seed.dm: The splicer and reagent extractor are in here.
// Standard variables for plants are added here.
// Name of the plant species
// The plant's normal sprite - overridden by special_icon
// what "family" is this plant part of? used for various things
// For weeds - won't die or halt growth from drought
// For boring decorative plants that don't do anything
// If you need the icon to be different to the name
// If you need a new DMI for whatever reason. why not!
// What crop does this plant produce?
// an override so plants like synthmeat can give seeds
// What health does this plant start at?
// How long it takes this plant to mature
// How long it takes this plant to produce harvests after maturing
// How many items you get per harvest
// Does this plant even produce anything
// How many times you can harvest this species
// How much endurance this species normally has
// Always dies after one harvest
// Can't be scanned by an analyzer
//If nonzero, slowly tries to maintain this level of nectar reagent.
// Used for extractions, harvesting, etc
// What general mutations can occur in this plant?
// what mutant variants does this plant have?
// Used for splicing - how "similar" the plants are = better odds of splice
// Does this plant do something special when it's in the pot?
// Does this plant react if you try to attack it?
// Take a guess
// Used for vendor filtering
// 1 = Appears in seed vendors, 2 = appears when hacked, 0 = doesn't appear
// Does this plant produce a paticular instance of seeds?
// color on the seed packet, if applicable
// used for seed manipulator stuff
// fixed some runtime errors here - singh
// hyp procs now return 0 for success and continue, any other number for error codes
// for now its setup as ABB where A = proc type and B = error
// proc 100: HYPspecial
// proc 200: HYPattacked
// proc 300: HYPharvested
// proc 400: HYPspecial_M
// error 1: called with null pot
// error 2: called when plant is dead or no plant exists
// error 3: called with a plant that is not ready to harvest
// when overriding these in child types start the child proc with
// ..() calls the parent type which performs the check and returns 0 or an error code
// . holds the return value, after ..() executes the child version continues running
// so it needs to check . to check the return of the parent type and decide whether
// or not to continue
// If it returns 0, it should halt the proc that called it also
// destroy the seed
// These vars are pretty much bonuses/penalties applied on top of the
// same vars found in /datum/plant honestly. They go largely towards
// the same purpose for the most part.
// Apart from this one - this one deals with reagents.
// General transferrable mutations
// is it mutated? if so which variation?
// Order goes:
// Species, Growtime, Harvtime, Cropsize, Harvests, Potency, Endurance
// Species allele controls name, appearance, crop produce and mutations
// 1 is dominant, else recessive
// optimise this later
// non-harvestables
// harvestables
// Weird Shit
// :effort:
// You want to capitalise this, it shows up in the seed vendor and plant pot
// This is either Fruit, Vegetable, Herb or Miscellaneous
// Hex string for color. Don't forget the hash!
// It's not big enough to be violent yet, so nothing happens
// TODO What layer should this be on?
//
/*********************************
Procs for handling ircbot connectivity and data transfer
*********************************/
//Load the config variables necessary for connections
//Flush queue
//Shortcut proc for event-type exports
//Send a message to an irc bot! Yay!
//Handle the response
//Format the response to an irc request juuuuust right
//TEMP FOR BACKWARD COMPAT WITH SHITFORMANT
// For the revoltion game mode. See jobprocs.dm for notes etc (Convair880).
//var/slot_ears = null // swapping this back for now
// cogwerks experiment - removing default headsets
// Pay attention to size. Not everything is small enough to fit in jumpsuit pockets.
// stop giving everyone a free airtank gosh
// works the same as above but is for jobs that spawn with a belt that can hold things
// Please define in global get_access() proc (access.dm), so it can also be used by bots etc.
// Command Jobs
//name = "NT-SO Commander"
// Don't make them spawn with a full backpack again, please.
//"NT-SO Special Operative"
//"Salvage Chief"
// mesons look fuckin weird in the dark
// Security Jobs
// Don't make them spawn with a full backpack again, please.
//name = "NT-SO Officer"
//allow_traitors = 0
// Research Jobs
// cogwerks: giving medics a guaranteed air tank, stealing it from roboticists (those fucks)
//name = "Salvage Medic"
// Engineering Jobs
// heh
//"Salvage Engineer"
// Civilian Jobs
//M.verbs += /client/proc/sense_corruption
//M.verbs += /client/proc/remove_corruption
// AI and Cyborgs
// Special Cases
// Don't make them spawn with a full backpack again, please.
// Exact amount is randomized.
// randomizd gimmick jobs
//requires_whitelist = 1
// so they can slam tables
// So they don't get a default headset and stuff first.
// heh
//Special daily jobs
// Exact amount is randomized.
// Don't make them spawn with a full backpack again, please.
// bit corruption error
// bit flip error
/**
* Limb datums for arms. Describes all activity performed by the limb.
* Currently, this is basically attack_hand().
*
* Also serves as a future holder for any other special limb activity.
*/
// !!CAUTION!! it is allowed to delete the target here
// Mob is also passed as a convenience/redundancy.
// so it might miss, sometimes, maybe
//Proc wont spawn the right object type so lets do that here.
// A replacement for the awful custom_attack() overrides in mutantraces.dm, which consisted of two
// entire copies of pre-stamina melee attack code (Convair880).
// Werewolf melee attacks are similar enough. Less repeated code.
// Use standard grab proc.
// Werewolves and shamblers grab aggressively by default.
// Target.lying check is in there.
// 1: a little bit | 2: across the room
// Werewolves get a guaranteed knockdown.
// Nasty claws!
// Something went very wrong, fall back to default disarm proc.
// We just lost a limb.
// Shamblers get a guaranteed disarm.
// 1: a little bit | 2: across the room
// Nasty claws!
// And why not (Convair880).
// Slightly more powerful punches. This is bonus damage, not a multiplier.
// This makes the probability of spawning a new object decrease linearly
// as the number of spawned objects approaches the limit
// Limits are per-tick.
// Name of the schematic
// Materials required
// Name of each material
// How many of each material is needed
// What the schematic outputs
// 0 - will create each item in the list once per loop (see manufacturer.dm Line 755)
// 1 - will pick() a random item in the list once per loop
// 2 - will pick() a random item before the loop begins then output one of the selected item each loop
// How many times it'll make each thing in the list
// How long it takes to build
// Tool, Clothing, Resource, Component, Machinery or Miscellaneous
// use this if you want the outputted item to be customised in any way by the manufacturer
//A.quality -= rand(25,50)
// purely a test
//// cogwerks - gas extraction stuff
//Any Material")
////////////////////////////////
//list(/obj/item/parts/robot_parts/leg/treads)
// Robotics Research
//Okay enough roundstart teleportborgs. Fuck.
/* shit done be broked
/datum/manufacture/robup_thermal
name = "Optical Thermal Upgrade"
item_paths = list("CRY-1","CON-1")
item_names = list("Crystal","Conductive Material")
item_amounts = list(4,8)
item_outputs = list(/obj/item/roboupgrade/opticthermal)
time = 90
create = 1
category = "Component"
*/
// Mining Gear
/// Ship Items -- OLD COMPONENTS
// cogwerks - clothing manufacturer datums
/////// pod construction components
//// pod addons
//Give a small delay when adding memories to prevent spam. It could happen!
// sec's miranda rights thingy.
// this is different than last_memory_time, this is when the rights were last SAID, not last CHANGED
// This used for dead/released/etc mindslaves and rogue robots we still want them to show up
// in the game over stats. It's a list because former mindslaves could also end up as an emagged
// cyborg or something. Use strings here, just like special_role (Convair880).
//Associate a leader with their gang.
//Ability holders.
// For mindslave/vampthrall/spyslave master references, which are now tracked by ckey.
// Mob references are not very reliable and did cause trouble with automated mindslave status removal
// The relevant code snippets call a ckey -> mob reference lookup proc where necessary,
// namely whois_ckey_to_mob_reference(mob.mind.master) (Convair880).
// todo:
// implement dis
//if (is_changeling)
// new_character.make_changeling()
//They have a mind so we can do this nicely
//We need to put whoever we're swapping with somewhere
//So now we put them there
//Then I go into their head
//And they go into my old one
//Not needed any more
//They didn't have a mind and didn't have an associated player, AKA up for grabs
//The Ugly Way
//We need to put whoever we're swapping with somewhere
//So now we put them there
//Then I go into their head
//Not needed any more
// Added (Convair880).
// Terrain Gen Procs
// Checks
// Generators
//F.stone_color = B.stone_color
// Modifiers
// rare tier
// uncommon tier
// common tier
//deprecated, needs getting rid of except the map is being weird about it
//metal = 1
//conductor = 1
// no really don't make any on destiny thanks
//Requirements for individual objectives: 1) You have a mind (this eliminates 90% of our playerbase ~heh~)
//2) You are not a traitor
//min(rand(1,3), objectiveTypes.len)
//name = null
//
//
// all cables & junctions
// all APCs & sources
// all networked machinery
// per-apc avilability
// module datum.
// this is per-object instance, and shows the condition of the modules in the object
// actual modules needed is referenced through modulestypes and the object type
// bits set if working, 0 if broken
// bits set if installed, 0 if missing
// moduletypes datum
// this is per-object type, and shows the modules needed for a type of object
// assoc list of the count of modules for a type
//
// global associative list
// the type of the creating object
// find if this type has modules defined
// not found in module list?
// delete self, thus ending proc
// get a bitmask for the number of modules in this object
// index by type text
// mutant races: cheap way to add new "types" of mobs
// without copy/pasting the human code a million times.
// Now a robust object-oriented version!!!!
// used for identification in diseases, clothing, etc
// set to 1 to override the limb attack actions. Mutantraces may use the limb action within custom_attack(),
// but they must explicitly specify if they're overriding via this var
// set to a language ID to replace the language of the human
// additional understood languages (in addition to override_language if set, or english if not)
// whether fat icons/disabilities are used
// unused
// if 1, allows human diseases and dna injectors to affect this mutantrace
// if 0, can only wear clothes listed in an item's compatible_species var
// if 1, only understood by others of this mutantrace
// overrides normal voice message if defined (and others don't understand us, ofc)
// Should robots arrest these by default?
// affects pixel_y of clothes
// Should we get custom arms? Dispose() replaces them with normal human arms.
// Replace both arms regardless of mob status (new and dispose).
//Scales damage, just like critters.
// custom attacks, should return attack_hand by default or bad things will happen!!
// ^--- Outdated, please use limb datums instead if possible.
// movement delay modifier
// vision modifier (see_mobs, etc i guess)
//Called every Life cycle of our mob
//Called when our mob dies. Returning a true value will short circuit the normal death proc right before deathgasp/headspider/etc
// Replacement for custom_attack() of several mutantraces, which used an entire copy of
// pre-stamina melee code. They do the same stuff with more flexible limb datums (Convair880).
// Don't remove.
// For predators (Convair880).
// And the other way around (Convair880).
// Don't remove.
// check for H.organHolder as well so we don't get null.skull runtimes
// We might have to update the skull (Convair880).
//..()
//Bringing it more in line with how it was before it got broken (in a hilarious fashion)
//Are you a macho abomination or not?
//Do you continuously lose DNA points when in this form?
//This will not revert to human form
//This also does not get any of the OnLife effects
// Gave them a significant stamina boost, as they're melee-orientated (Convair880).
// Werewolves (being a melee-focused role) are quite buff.
// Gave them a minor stamina boost (Convair880).
// uses_human_clothes = 0 // Guess they can keep that ability for now (Convair880).
// Fixed: monkeys can click-hide under every table now, not just the parent type. Also added beds (Convair880).
//They only have one working hand :(
// some new simple gimmick junk
//Named colors
// Used for describing appearences of reagents
// the datum holding one named color
// stored 0-255
//
//
// distance^2 between specified RGB and this color
// the global list of all named colors
// returns the name of the color nearest to the given color RGB
// returns the namecustomization_third_color datum that is nearest to the given color RGB
// adds a named color to the global list
// given name and RGB color
// called at world startup
// populates the color list
// Called by ticker.mode.declare_completion().
///////////////////////////////////////////////////
// Regular objectives active in current gameplay //
///////////////////////////////////////////////////
// 1) Wizard marked as another wizard's target.
// 2) Presence of wizard is revealed to other antagonists at round start.
// Both are bad.
// Cannot read null.is_target
//Get a list of objectives matching every job
//Ok, we found their job - now to build a list of job-specific stuff
//We got us a case of alt_names
//Pick which flufftext we want to use
//Add pronouns
// Brought this back as a very rare gimmick objective (Convair880).
// Somebody deleted it somehow, I suppose?
// 25 was way too strict for larger rooms, causing people to fail the objective most of the time.
// On Cogmap 1, medbay is split up into three separate areas.
///////////////////////////////////////////////////////////////
// Regular objectives not currently used in current gameplay //
///////////////////////////////////////////////////////////////
// Tweaked to make it more reliable (Convair880).
////////////////////////////////
// Specialist role objectives //
////////////////////////////////
// You start with 0 DNA these days, not 1.
// Added a bit of randomization here (Convair880).
//DEBUG("Found [ticker.minds.len] minds.")
//DEBUG("Objective: [trophycount]. Total trophy value: [trophyvalue].")
// Stores bioHolder.Uid of previous victims, so we can't feed on the same person multiple times.
/////////////////////////////
// Round-ending objectives //
/////////////////////////////
//they're not dead
//they're not dead
/////////////////////////////////////////////////////////
// Neatly packaged objective sets for your convenience //
/////////////////////////////////////////////////////////
// Misc antags
// Wraith not listed since it has its own dedicated proc
// Traitors, easier objectives
// More difficult traitor objectives
// could probably use this with reagents
//datum/organ/proc/receive_chem(datum/reagent/R)
// return
//returns total damage
//could use src.health?
//
//All of the gas_mixtures continuously connected in this network
//membership roster to go through for updates and what not
//Equalize gases amongst pipe if called for
//equalize_gases(gases)
//Give pipelines their process call for pressure checking and what not
//Purpose: Generate membership roster
//Notes: Assuming that members will add themselves to appropriate roster in network_expand()
//Go through membership roster and make sure gases is up to date
//Perfectly equalize all gases members instantly
//Calculate totals from individual components
//Allow air mixture to react
//Update individual gas_mixtures by volume ratio
//Perfectly equalize all gases members instantly
//Calculate totals from individual components
//Calculate temperature
//Update individual gas_mixtures by volume ratio
//
//Used for building networks
// null air? oh god!
// kill this network, something is bad
//Check to see if pressure is within acceptable limits
//Only delete 1 pipe per process
//Allow for reactions
//air.react() //Should be handled by pipe_network now
//Update individual gas_mixtures by volume ratio
//technically passing these parameters should not be allowed
//however pipe_network.build_network(..) and pipeline.network_extend(...)
// were setup to properly handle this case
//Have to consider preservation of group statuses
//Copy a good representation of the turf from parent group
//The new turf would be an acceptable group member so permit the integration
//Comparison failure so dissemble group and copy turf
// done with this
//turf_air already modified by equalize_gases()
//Have a look in demo.dm to see how to use /pixel_projectile!
//////////////////////////////////////
// Defines //
//////////////////////////////////////
//This is 1 / WORLD_ICON_SIZE
//This is the size of your map in tiles + 1 times world_icon_size
//This is the size of your map in tiles + 1 times world_icon_size
//////////////////////////////////////
// Utility Stuff //
//////////////////////////////////////
//Written by Lummox JR
//Returns the direction between two atoms more accurately than get_dir()
// diagonal
// keep east/west (4 and 8)
// keep north/south (1 and 2)
//this sets the atom's x, y and the atom's pixel_x, pixel_y from absolute pixel coordinates
//////////////////////////////////////
// pixel_projectile //
//////////////////////////////////////
//the true pixel location of the projectile
//the last x/y coordinate of the tile we were in
//speed of the projectile
//vector px (movement increment)
//vector py (movement increment)
//ok now the real important stuff, initial position and vector calculation
//garbage collector stuff
//set initial position
//delta x
//delta y
//delta root
//delta x,y is absolute pixel x minus the starting absolute pixel x
//root
//vector x (amount to move x,y each frame)
//that's it
//begin!
//if something happens to cross this tile while we're sitting in it before moving to next tile
//we should check for collide!
//update position
//update x, y, pixel_x, pixel_y to reflect new location
//did we enter a new tile?
//using colon operator assuming the projectile's loc will always be a turf
//checks to see if a pixel is in bounds of the map
//if(src.px > WORLD_ICON_SIZE && src.py > WORLD_ICON_SIZE && src.px <= WORLD_MAX_PX && src.py <= WORLD_MAX_PY)
//the collidables list allows us to avoid having to generate lists per tile update per projectile
//just make sure to remove your atom from this list at garbage collection!
// call with A as the atom involved, entered as boolean for add or remove from list
// pixel guns here for now
// if (src.current_projectile_num < src.projectiles.len)
// src.current_projectile_num += 1
// else
// src.current_projectile_num = 1
// drsingh fix for Cannot read null.shot_number
//Check ammo
//Update that icon, having it here means we dont need it in each process_ammo proc
//Play a sound if we have one
//Don't even create the new projectile if the target isn't turf
// number is velocity
//Give it the info datum and shoooot
//1 = no cell change, use a recharger
// do they want wasd on by default?
// do they have an AZERTY keyboard?
// do they wanna disable mentor pms?
// im laze
// keep gender/bloodtype/age/name/underwear/bioeffects
//qdel(src.preview_icon)
// Skin tone
//?src=\ref[user];preferences=1;profile_name=input\"><b>[src.profile_name ? src.profile_name : "Unnamed"]</b></a> "
//?src=\ref[user];preferences=1;real_name=input\"><b>[src.real_name]</b></a> "
//?src=\ref[user];preferences=1;b_random_name=1\">[src.be_random_name ? "Yes" : "No"]</a>)"
//?src=\ref[user];preferences=1;b_random_look=1\">[src.be_random_look ? "Yes" : "No"]</a>)"
//?src=\ref[user];preferences=1;gender=input\"><b>[src.gender == MALE ? "Male" : "Female"]</b></a><br>"
//?src=\ref[user];preferences=1;age=input'>[src.age]</a><br>"
//?src=\ref[user];preferences=1;blType=input'>[src.random_blood ? "Random" : src.blType]</a><br>"
//?src=\ref[user];preferences=1;pin=input'>[src.pin ? src.pin : "Random"]</a> (<a href=\"byond://?src=\ref[user];preferences=1;random_pin=1\">&reg;</a>)<br>"
//?src=\ref[user];preferences=1;jobswindow=1\">Occupation Choices</a>[ favoriteJob ? " (Fav: [favoriteJob])" : "" ]</b><br>"
//?src=\ref[user];preferences=1;traitswindow=1\">Trait Choices</a></b>"
//?src=\ref[user];preferences=1;s_tone=input'><b>Skin Tone:</b></a> [-AH.s_tone + 35]/220<br>"
//?src=\ref[user];preferences=1;underwear=input'><b>Underwear:</b></a> [AH.underwear] "
//?src=\ref[user];preferences=1;underwear_color=input'><font face=\"fixedsys\" size=\"3\" color=\"[AH.u_color]\"><b>#</b></font></a><br>"
//?src=\ref[user];preferences=1;eyes=input'><b>Eye Color:</b> <font face=\"fixedsys\" size=\"3\" color=\"[AH.e_color]\"><b>#</b></font></a><br>"
//?src=\ref[user];preferences=1;customization_first=input'><b>Bottom Detail:</b></a> [AH.customization_first] "
//?src=\ref[user];preferences=1;hair=input'><font face=\"fixedsys\" size=\"3\" color=\"[AH.customization_first_color]\"><b>#</b></font></a><br>"
//?src=\ref[user];preferences=1;customization_second=input'><b>Mid Detail:</b></a> [AH.customization_second] "
//?src=\ref[user];preferences=1;facial=input'><font face=\"fixedsys\" size=\"3\" color=\"[AH.customization_second_color]\"><b>#</b></font></a><br>"
//?src=\ref[user];preferences=1;customization_third=input'><b>Top Detail:</b></a> [AH.customization_third] "
//?src=\ref[user];preferences=1;detail=input'><font face=\"fixedsys\" size=\"3\" color=\"[AH.customization_third_color]\"><b>#</b></font></a><br>"
// undefined variable /client/var/client
//?src=\ref[user];preferences=1;toggle_mentorhelp=1\">[(src.see_mentor_pms ? "Yes" : "No")]</a></b><br>"
//?src=\ref[user];preferences=1;hud_style=1\"><img style=\"-ms-interpolation-mode:nearest-neighbor;\" src=hud_preview.png></a></b> | "
//?src=\ref[user];preferences=1;tcursor=1\"><img style=\"-ms-interpolation-mode:nearest-neighbor;\" src=tcursor.png></a></b><br>"
//?src=\ref[user];preferences=1;listen_ooc=1\">[(src.listen_ooc ? "Yes" : "No")]</a></b><br>"
//?src=\ref[user];preferences=1;listen_looc=1\">[(src.listen_looc ? "Yes" : "No")]</a></b><br>"
//?src=\ref[user];preferences=1;changelog=1\">[(src.view_changelog ? "Yes" : "No")]</a></b><br>"
//?src=\ref[user];preferences=1;scores=1\">[(src.view_score ? "Yes" : "No")]</a></b><br>"
//?src=\ref[user];preferences=1;tickets=1\">[(src.view_tickets ? "Yes" : "No")]</a></b><br>"
//?src=\ref[user];preferences=1;clickbuffer=1\">[(src.use_click_buffer ? "Yes" : "No")]</a></b><br>"
//?src=\ref[user];preferences=1;volume=1\">[src.admin_music_volume]</a></b><br>"
//?src=\ref[user];preferences=1;default_wasd=1\">[(src.default_wasd ? "Yes" : "No")]</a></b><br>"
//?src=\ref[user];preferences=1;use_azerty=1\">[(src.use_azerty ? "Yes" : "No")]</a></b><br>"
//?src=\ref[user];preferences=1;save=[i]'>[i]</a>"
//?src=\ref[user];preferences=1;load=[i]'>[savefile_get_profile_name(user, i) || i]</a>"
//?src=\ref[user];preferences=1;reset_all=1'><b>Reset</b></a> - "
//?src=\ref[user];preferences=1;real_name=random'><b>Randomize</b></A><br>"
//?src=\ref[user];preferences=1;occ=1;job=[J_Fav.name];level=0\"><font color=[J_Fav.linkcolor]>[J_Fav.name]</font></a>"
//?src=\ref[user];preferences=1;help=favjobs\"><small>(Help)</small></a><br>"
//?src=\ref[user];preferences=1;help=medjobs\"><small>(Help)</small></a></th>"
//?src=\ref[user];preferences=1;help=lowjobs\"><small>(Help)</small></a></th>"
//?src=\ref[user];preferences=1;help=unjobs\"><small>(Help)</small></a></th>"
//?src=\ref[user];preferences=1;occ=2;job=[J_Med.name];level=1\">\<</a> "
//?src=\ref[user];preferences=1;occ=2;job=[J_Med.name];level=0\"><font color=[J_Med.linkcolor]>[J_Med.name]</font></a>"
//?src=\ref[user];preferences=1;occ=2;job=[J_Med.name];level=3\">\></a>"
//?src=\ref[user];preferences=1;occ=3;job=[J_Low.name];level=2\">\<</a> "
//?src=\ref[user];preferences=1;occ=3;job=[J_Low.name];level=0\"><font color=[J_Low.linkcolor]>[J_Low.name]</font></a>"
//?src=\ref[user];preferences=1;occ=3;job=[J_Low.name];level=4\">\></a>"
//?src=\ref[user];preferences=1;occ=4;job=[J_Un.name];level=3\">\<</a> "
//?src=\ref[user];preferences=1;occ=4;job=[J_Un.name];level=0\"><font color=[J_Un.linkcolor]>[J_Un.name]</font></a>"
//?src=\ref[user];preferences=1;help=antags\"><small>(Help)</small></a></a><br>"
//?src=\ref[user];preferences=1;b_traitor=1\"><font color=#00CC00>Traitor</font></a>"
//?src=\ref[user];preferences=1;b_traitor=1\"><font color=#FF0000><strike>Traitor</strike></font></a>"
//?src=\ref[user];preferences=1;b_syndicate=1\"><font color=#00CC00>Syndicate Operative</font></a>"
//?src=\ref[user];preferences=1;b_syndicate=1\"><font color=#FF0000><strike>Syndicate Operative</strike></font></a>"
//?src=\ref[user];preferences=1;b_spy=1\"><font color=#00CC00>Spy</font></a>"
//?src=\ref[user];preferences=1;b_spy=1\"><font color=#FF0000><strike>Spy</strike></font></a>"
//?src=\ref[user];preferences=1;b_gangleader=1\"><font color=#00CC00>Gang Leader</font></a>"
//?src=\ref[user];preferences=1;b_gangleader=1\"><font color=#FF0000><strike>Gang Leader</strike></font></a>"
//?src=\ref[user];preferences=1;b_revhead=1\"><font color=#00CC00>Revolution Leader</font></a><br>"
//?src=\ref[user];preferences=1;b_revhead=1\"><font color=#FF0000><strike>Revolution Leader</strike></font></a><br>"
//?src=\ref[user];preferences=1;b_changeling=1\"><font color=#00CC00>Changeling</font></a>"
//?src=\ref[user];preferences=1;b_changeling=1\"><font color=#FF0000><strike>Changeling</strike></font></a>"
//?src=\ref[user];preferences=1;b_wizard=1\"><font color=#00CC00>Wizard</font></a>"
//?src=\ref[user];preferences=1;b_wizard=1\"><font color=#FF0000><strike>Wizard</strike></font></a>"
//?src=\ref[user];preferences=1;b_vampire=1\"><font color=#00CC00>Vampire</font></a>"
//?src=\ref[user];preferences=1;b_vampire=1\"><font color=#FF0000><strike>Vampire</strike></font></a>"
//?src=\ref[user];preferences=1;b_wraith=1\"><font color=#00CC00>Wraith</font></a>"
//?src=\ref[user];preferences=1;b_wraith=1\"><font color=#FF0000><strike>Wraith</strike></font></a>"
//?src=\ref[user];preferences=1;b_blob=1\"><font color=#00CC00>Blob</font></a>"
//?src=\ref[user];preferences=1;b_blob=1\"><font color=#FF0000><strike>Blob</strike></font></a>"
//?src=\ref[user];preferences=1;b_misc=1\"><font color=#00CC00>Other Foes</font></a>"
//?src=\ref[user];preferences=1;b_misc=1\"><font color=#FF0000><strike>Other Foes</strike></font></a>"
//?src=\ref[user];preferences=1;help=jobs\"><b>Help</b></a> * "}
//?src=\ref[user];preferences=1;jobswindow=1\"><b>Refresh</b></a> * "}
//?src=\ref[user];preferences=1;resetalljobs=1\"><b>Reset All Jobs</b></a> * "}
//?src=\ref[user];preferences=1;closejobswindow=1\"><b>Close Window</b></a>"}
// i know, repetitive, but its the safest way i can think of right now
/* Wire: a little thing i'll finish up eventually
if (link_tags["set_will"])
var/new_will = input(user, "Write a Will that shall appear in the event of your death. (250 max)", "Character Generation") as text
var/list/bad_characters = list("_", "'", "\"", "<", ">", ";", "[", "]", "{", "}", "|", "\\", "/")
for (var/c in bad_characters)
new_will = dd_replacetext(new_will, c, "")
if (new_will)
if (length(new_will) > 250)
new_will = copytext(new_will, 1, 251)
src.will = new_will
*/
//Wire: Not everything has a bioholder you morons
//Also I think stuff other than human mobs can call this proc jesus christ
// set a default one so that, if none of the weighted ones happen, they at least have SOME kind of blood type
// this is weird but basically: a list of hairstyles and their appropriate detail styles, aka hair_details["80s"] would return the Hairmetal: Faded style
// further on in the randomize_look() proc we'll see if we've got one of the styles in here and if so, we have a chance to add the detailing
// if it's a list then we'll pick from the options in the list
// all these icon state names are ridiculous
// small chance to have a hairstyle more geared to the other gender
// otherwise just use one standard to the current gender
// since we're a guy, a chance for facial hair
// so the detail check doesn't do anything - we already got a secondary thing!!
// if FEMALE
// same as above for guys, just reversed and with a slightly higher chance since it's ~more appropriate~ for ladies to have guy haircuts than vice versa :I
// ss13 is coded with gender stereotypes IN ITS VERY CORE
// check for detail styles for our chosen style
// found something in the list
// default to being whatever we found
// if we found a bunch of things in the list
// let's choose just one (we don't need to assign a list as someone's hair detail)
// with a small chance for another detail thing
// if you have a detail style you're likely to want a crazy color
// but have a chance to be a normal hair color
// chance for a special eye color
// otherwise, nada
// aaaa
//How much of a punch this has, tends to be seconds/damage before any resist
//How much ammo this costs
//How fast the power goes away
//How many tiles till it starts to lose power
//Kill/Stun ratio
//name of the projectile setting, used when you change a guns setting
//file location for the sound you want it to play
//How many projectiles should be fired, each will cost the full cost
//What is our damage type
//With what % do we hit mobs laying down
//Can we pass windows
//Any special things when it hits shit?
// explosion(master, get_turf(master), 2, 3, 4, 5, lagreducer = 1)
//How much of a punch this has, tends to be seconds/damage before any resist
//How much ammo this costs
//How fast the power goes away
//How many tiles till it starts to lose power
//Kill/Stun ratio
//name of the projectile setting, used when you change a guns setting
//file location for the sound you want it to play
//How many projectiles should be fired, each will cost the full cost
// caliber list: update as needed
// 0.22 pistol / zipgun
// 0.308 - rifles
// 0.357 - revolver
// 0.38 - detective
// 0.41 - derringer
// 0.72 - shotgun shell, 12ga
// 1.57 - grenade shell, 40mm
// 1.58 - RPG-7 (Tube is 40mm too, though warheads are usually larger in diameter.)
//What is our damage type
// blood system damage type - DAMAGE_STAB, DAMAGE_CUT, DAMAGE_BLUNT
//With what % do we hit mobs laying down
//Can we pass windows
// we create this overlay on walls when we hit them
//Any special things when it hits shit?
// oh god no why was the first var set to src what was I thinking
// BULLETS CANNOT BLEED, HAINE
// It's supposed to be a stealth weapon, right (Convair880)?
// okay this can be made worse again now that crit isn't naptime
// don't staple through armor
// HEH
//traitor det revolver
// HEH
// HAH
//energy bullet things so he can actually stun something
// FUCK YOU.
// stun bullets shouldn't actually enter walls should they?
// adding this so these work like taser shots I guess, if this sucks feel free to remove it
//2
// roughly
//if (src.hit_type)
//take_bleeding_damage(hit, null, round(src.power / 3), src.hit_type)
// why the fuck was this called magazine, you're not firing goddamn magazines at people
// close enough, what the fuck ever
// 12 guage
// cogwerks: for explosions
// 40mm grenade shell
// Ported from old, non-gun RPG-7 object class (Convair880).
// fuck you stop affecting ghosts FUCK YOU
// FUCK YOU
// 40mm grenade shell
/*var/turf/trgloc = get_turf(projectile)
var/list/affected = block(locate(trgloc.x - 3,trgloc.y - 3,trgloc.z), locate(trgloc.x + 3,trgloc.y + 3,trgloc.z))
if(!affected.len) return
var/list/centerview = view(world.view, trgloc)
for(var/atom/A in affected)
if(!(A in centerview)) continue
var/obj/smokeDummy/D = new(A)
smokeLocs.Add(D)
spawn(smokeLength) qdel(D)
particleMaster.SpawnSystem(new/datum/particleSystem/areaSmoke("#ffffff", smokeLength, trgloc))
return*/
// I'm so tired of overlays freezing my client, sorry. Get rid of the old smoke call here once
// the performance and issues of full-screen overlays have been resolved, I guess (Convair880).
// for the coilgun
//How much of a punch this has, tends to be seconds/damage before any resist
//How much ammo this costs
//How fast the power goes away
//How many tiles till it starts to lose power
//Kill/Stun ratio
//name of the projectile setting, used when you change a guns setting
//file location for the sound you want it to play
//How many projectiles should be fired, each will cost the full cost
//What is our damage type
//With what % do we hit mobs laying down
//Can we pass windows
//Any special things when it hits shit?
// let's still stun a bit
//How much of a punch this has, tends to be seconds/damage before any resist
//How much ammo this costs
//How fast the power goes away
//How many tiles till it starts to lose power
//Kill/Stun ratio
//name of the projectile setting, used when you change a guns setting
//file location for the sound you want it to play
//How many projectiles should be fired, each will cost the full cost
//What is our damage type
//With what % do we hit mobs laying down
//Can we pass windows
//Any special things when it hits shit?
//////////// VUVUZELA
//How much of a punch this has, tends to be seconds/damage before any resist
// 100 was way too fucking long what the HECK
//How much ammo this costs
//How fast the power goes away
//How many tiles till it starts to lose power
//Kill/Stun ratio
//name of the projectile setting, used when you change a guns setting
//file location for the sound you want it to play
//How many projectiles should be fired, each will cost the full cost
//What is our damage type
//With what % do we hit mobs laying down
//Can we pass windows
//Any special things when it hits shit?
//////////// Ghost Hunting for Halloween
//How much of a punch this has, tends to be seconds/damage before any resist
//How much ammo this costs
//How fast the power goes away
//How many tiles till it starts to lose power
//Kill/Stun ratio
//name of the projectile setting, used when you change a guns setting
//file location for the sound you want it to play
//How many projectiles should be fired, each will cost the full cost
//With what % do we hit mobs laying down
//Can we pass windows
//How much of a punch this has, tends to be seconds/damage before any resist
//How much ammo this costs
//How fast the power goes away
//How many tiles till it starts to lose power
//Kill/Stun ratio
//name of the projectile setting, used when you change a guns setting
//file location for the sound you want it to play
//How many projectiles should be fired, each will cost the full cost
//What is our damage type
// cogwerks - changed from piercing
//With what % do we hit mobs laying down
//Can we pass windows
//Any special things when it hits shit?
// heh
// for the drones
// for the russian pod
// for precursor traps
//mostly just a reskin
// These are for custom antique laser guns repaired with high-quality components.
// See displaycase.dm for details (Convair880).
// cogwerks- mining laser, first attempt
//if(prob(60)) // raised again
// T.destroy_asteroid(1)
//else
// T.weaken_asteroid()
//playsound(hit.loc, "sound/machines/engine_grump1.ogg", 45, 1)
//if(prob(60)) // raised again
// T.destroy_asteroid(1)
//else
// T.weaken_asteroid()
//How much of a punch this has, tends to be seconds/damage before any resist
//How much ammo this costs
//How fast the power goes away
//How many tiles till it starts to lose power
//Kill/Stun ratio
//name of the projectile setting, used when you change a guns setting
//file location for the sound you want it to play
//How many projectiles should be fired, each will cost the full cost
//What is our damage type
//With what % do we hit mobs laying down
//Can we pass windows
// I have no idea what to do with these.
//var/obj/o_shooter = null
// moved this from the datum because why the hell was it on there
// local copy of power for proper dissipation tracking
// Who/what fired this?
// We use shooter to avoid self collision, however, the shot may have been initiated through a proxy object. This is for logging.
// track distance
// for reference @see setup()
// Adjusts the log entry accordingly.
// reflection normal on the current tile (NORTH if projectile came from the north, etc.)
// you never know ok??
// if disposed is set to true we have been pooled or set for garbage collection and shouldn't process bumps
// never collide with the original shooter
// Necessary because the check in human.dm is ineffective (Convair880).
// Unified check instead of a separate one in every mob type's bullet_act() (Convair880).
// also run the atom's general bullet act
//If bullet_act returns an atom, do all bad stuff to that atom instead
// if we made it this far this is a valid bump, run the specific projectile's hit code
//Trigger material on attack.
// if we hit a turf apparently the bullet is magical and hits every single object in the tile, nice shooting tex
// pool the projectile
//o_shooter = null
// why not
// can't happen will happen
// The bullet has expired/decayed.
// These vars were copied from the an projectile datum. I am not sure which version, probably not 4407.
// A special note: the icon state, if not a point-symmetric sprite, should face NORTH by default.
// what kinda overlay they puke onto turfs when they hit
// How much of a punch this has
// How much ammo this costs
// How fast the power goes away
// How many tiles till it starts to lose power
// Tracks how many tiles we moved
/* Kill/Stun ratio, when it hits a mob the damage/stun is based upon this and the power
eg 1.0 will cause damage = to power while 0.0 would cause just stun = to power */
// name of the projectile setting, used when you change a guns setting
// file location for the sound you want it to play
// How many projectiles should be fired, each will cost the full cost
// What is our damage type
// For blood system damage - DAMAGE_BLUNT, DAMAGE_CUT and DAMAGE_STAB
// With what % do we hit mobs laying down
// Can we pass windows
// standard visible message upon bullet_act
// Path of "bullet" left behind in the mob on successful hit
// planned thing to deal with pod electronics / etc
// todo: if fired from a handheld gun, check the targeted zone --- this should be in the goddamn obj
// Determines the amount of length units the projectile travels each tick
// A tile is 32 wide, 32 long, and 32 * sqrt(2) across.
// Setting this to 32 will mimic the old behaviour for shots travelling in one of the cardinal directions.
// Determines the impact range of the projectile. Should ideally be half the length of the sprite
// for line-based stuff (lasers), or the radius for circular projectiles.
// If the projectile is irregular (like, a square), try to use the radius of a circle that touches the farthest point
// of the edge of a shape in a cardinal direction from the center of symmetry (eg. half the edge length for a square)
// This is mostly aesthetic, so the player feels like they are actually hit when the projectile reaches them, not
// earlier or later.
// For very high speed projectiles, this may be much lower than the suggested amounts.
// If 0, no forward checking is done at all. May be useful for stuff like revolver shots, where the bullets are literally
// a pixel wide.
// Self-explanatory.
//For future use, ie guns that can change the power settings
//When it hits a mob or such should anything special happen
// WOO IMPACT RANGES
// Meticulously calculated by hand.
// for the gun, not the drone
// do it.
// THIS IS INTENDED FOR POINTBLANKING.
// Point-blank overrides, such as stun bullets (Convair880).
// The other immunity check is in there (Convair880).
// incident direction DOT normal * 2
// r = d - 2 * (d * n) * n
// unknown error
// changed from radbolt - cogwerks
//How much of a punch this has, tends to be seconds/damage before any resist
//How much ammo this costs
//How fast the power goes away
//How many tiles till it starts to lose power
//Kill/Stun ratio
//name of the projectile setting, used when you change a guns setting
//file location for the sound you want it to play
// cogwerks edit to make this thing actually vaguely worthwhile
//shot_sound = 'sound/weapons/radxbow.ogg'
//How many projectiles should be fired, each will cost the full cost
//What is our damage type
//With what % do we hit mobs laying down
//Can we pass windows
//no visible message upon bullet_act
//How much of a punch this has, tends to be seconds/damage before any resist
//How much ammo this costs
//How fast the power goes away
//How many tiles till it starts to lose power
//Kill/Stun ratio
//name of the projectile setting, used when you change a guns setting
//file location for the sound you want it to play
//How many projectiles should be fired, each will cost the full cost
//What is our damage type
//With what % do we hit mobs laying down
//Can we pass windows
//How much of a punch this has, tends to be seconds/damage before any resist
//How much ammo this costs
//How fast the power goes away
//How many tiles till it starts to lose power
//Kill/Stun ratio
//name of the projectile setting, used when you change a guns setting
//file location for the sound you want it to play
//How many projectiles should be fired, each will cost the full cost
//What is our damage type
//With what % do we hit mobs laying down
//Can we pass windows
//sparks don't teleport
//Just like portals!
// Beacons and tracking implant might have been moved.
///You will appear adjacent to the beacon
//How much of a punch this has, tends to be seconds/damage before any resist
//How much ammo this costs
//How fast the power goes away
//How many tiles till it starts to lose power
//Kill/Stun ratio
//name of the projectile setting, used when you change a guns setting
//file location for the sound you want it to play
//How many projectiles should be fired, each will cost the full cost
//What is our damage type
//With what % do we hit mobs laying down
//Can we pass windows
//Any special things when it hits shit?
// 30m
// Doing it manually.
// 5m (+ ghost_confirmation_delay). Don't out them too early, blobs in particular need time to establish themselves.
// 2 min to acknowledge or deny respawn offer.
// Admin-configured respawns seem to work out fine, so let's give automatic role selection a try.
// Gotta reset this.
// No need for a fancy setup here.
// Report spawn().
// Don't lock up the event controller.
// 1: alert | 2: alert (chatbox) | 3: alert acknowledged (chatbox) | 4: no longer eligible (chatbox) | 5: waited too long (chatbox)
// Don't disclose which type it is. You know, metagaming.
// The proc takes care of all the necessary work (job-banned etc checks, confirmation delay).
// Check against player preferences.
// Respawn and assign role.
// Respawn might be in progress still.
// Shouldn't happen, will happen.
// 1: arrival shuttle | 2: wizard shuttle
// Restore defaults.
// 45m
// 3 seconds
// 5 seconds
// Particle FX
// 40m
// why N? why not M?
// drsingh lowered these by popular request.
// drsingh lowered these by popular request
// I implemented a bit of customization. Modify the proc call in rathens.dm if you want to nerf/buff the wizard spell (Convair880).
// jfc what am I doing with my life
// so we don't do a bunch of ishuman/isrobot calls
//it's too late!
//List of major spooky things (only one is spawned)
// This thing is broken.
//List of minor spooky things (several are spawned)
//Okay, this one isn't very "spooky"
//var/datum/reagents/reagents = I.reagents
// 5m
// 2m
// 40m
// centcom message handled modularly here
// 60m
//var/timer = ticker.round_elapsed_ticks / 600
// north
// south
// east
// west
// anywhere
////////////////////////////////////////
// Defines for the meteors themselves //
////////////////////////////////////////
//If we hit something we skip the next step (we dont move)
//animate_spin(src, dir = "R", T = 1, looping = -1)
//Just to make sure
/////////////////////////HUGE
//bound_width = 96
//bound_height = 96
// Don't erase active patrol tasks and the like.
//pestlandmark.visible_message("A group of [type] emerges from their hidey-hole")
//This is to prevent admins from fucking up the shuttle arrival/departures by spamming this event.
// hey you, get out of the way!
// find the turf to move things to
//var/turf/E = get_step(D, SOUTH)
// hey you, get out of my shuttle! I ain't taking you back to centcom!
//TODO: Make this go to the closest station area, so that this doesn't break on future maps.
// First get which plant pots are available for free growth and pick one
// If there's already a plant there or it blocks weeds, disqualify the pot
// We couldn't get any pots at all, so just give up
// Now we place a weed seed in the pot and generate a new plant from it
// Randomly select what kind of weed we want
// Now spawn the plant and clean up
// What is this event called?
// The title of the displayed message.
// A message displayed to the crew.
// How long it takes after the event's effect for the message to arrive.
// Round elapsed ticks must be this or higher for the event to trigger naturally.
// Event will no longer occur naturally after this many ticks have elapsed.
// Event won't occur if this is true.
// 10m
// could just set it to our current mapsize (300) but this should help in case that changes again in the future or we go with non-square maps for some reason?? :v
// Vertical
// Horizontal
// 20m
//temporary, but whatever!
// This is if an extra item is needed, eg a butte for an assburger
// The item that is spawned when the recipe is made
//name of the research
//maximum amount of tiers
//maximum amount of researchable stuff per tier
//the starting tier, could maybe start at a random tier?
//tier of research currently at
//1 if is researching/ 0 if isn't researching
//what is currently being researched
//in seconds
//total time research will take
////
//For all these lists we'll just be naughty and ignore the 0th component! hehehehe
//list of items which HAVE been researched and their associated tiers
//list of items which WILL be researched and their associated tiers
//Max tiers is the maximum, make sure this is kept whenever research is created
//this is for detecting if we still have things to research in the current tier
//prevents people from spamming the advance tier button
//as far as i know the .len for items to research would just return src.max_per_list
//hence the reason for the for loop
//This needs to be re-did for each research. For eg, the variable a has to be a datum/ailment for
//disease research, though if you're researching objects it needs to be /obj/
//otherwise it will always return 1, as for some reason it counts when you just use var/a
// Dont do anything if they havent finished the tier yet
// Don't advance if we're at or above max tiers
// If they've somehow advanced when they're already at max, fix it and don't tell everyone about it
//Let the world know that we've finished our research
//Let everyone know when we have advanced a tier
//Starts the research, sets the research item text.
//Sets time default to 0 so research can be set up without it being time based
//eg engineering research could be based on collecting items, setting up the engine etc.
//already researching
//can't find it in in the list of shit we need to research
// apply time bonus
// start that shit
//Only if we're considering time
//when it'll be finished in seconds
//End research, sets research item to null and updates finished research list
//already finished or timeleft is not zero
//this shouldn't happen
// Stops the current research without finishing it
// No need to cancel if we're not researching anything
//Returns the time in seconds until researched is finished
//converting timeofday to seconds
//Returns the time, in MM:SS format
//The disease research will be mostly handled by the research/disease computer
//src.items_to_research[4] = list(tier_four_one, tier_four_two, tier_four_three, tier_four_four, tier_four_five)
//this is for detecting if we still have things to research in the current tier
//prevents people from spamming the advance tier button
//as far as i know the .len for items to research would just return src.max_per_list
//hence the reason for the for loop
/// Host/Coder Admin verbs for research
// might shit itself if we swipe an in-progress research out from under them
// might shit itself if we swipe an in-progress research out from under them
// Robot Research Datums
// What blueprints does this research allow Robotics Fabricators to download?
// Does this research give a bonus to manufacturing unit efficiency?
// Manufacturing time has this subtracted from it
// Manufacturing time is divided by this (unless it's zero, we dont want to crash)
// How much manufacturing unit power usage is reduced by (base of 1500/tick while in use)
// Does this research give a bonus to research time?
// Research time is divided by this
// T1
// T2
// src.schematics += new /datum/manufacture/robup_thermal(src) // shit don't work
//src.schematics += new /datum/manufacture/robup_chargexpand(src)
// T3
//src.schematics += new /datum/manufacture/robup_expand(src)
// src.schematics += new /datum/manufacture/implant_bloodmonitor(src) // does nothing
// T4
/* see _setup.dm for the actual defines
#define SAVEFILE_VERSION_MIN 3
#define SAVEFILE_VERSION_MAX 7
#define SAVEFILE_PROFILES_MAX 3
*/
// don't save this preference if that's enabled, because it might not be set to what people want it to be
// Global prefs
// loads the savefile corresponding to the mob's ckey
// if silent=true, report incompatible savefiles
// returns 1 if loaded (or file was incompatible)
// returns 0 if savefile did not exist
// if (!silent)
// alert(user, "Your savefile was incompatible with this version and was deleted.")
// Global prefs
//This might be a bad way of doing it IDK
// 10 minutes
//Returns the time, in MM:SS format
// Clear current in-demand products so we can set new ones later
// Most of the time price fluctuates normally
// Sometimes it goes apeshit though!
// No point in paying centcom to take your goods away
// Small chance of a price being sent back to its original value
// Small chance of the multiplier of in-demand items being altered
// How many goods are going to be in demand this time?
// Goods that are in demand sell for a multiplied price
// Shuffle trader visibility around a bit
// 20% chance to shuffle out generic traders for a new one
// Do this after a short delay so QMs can finish any last-second deals
// Debugging and admin verbs (mostly coder)
// Controls the emergency shuttle
// these define the time taken for the shuttle to get to SS13
// and the time before it leaves again
// 10 minutes = 600 seconds
// 3 minutes = 180 seconds
// 2 minutes = 120 seconds
// where you at, dawg, where you where you at
//0 = somewhere far away, 1 = at SS13, 2 = returned from SS13
//-1 = going back to central command, 1 = going back to SS13
//Block shuttle calling if it's disabled.
//Number of shuttle calls required to break through interference (wizard mode)
// round_elapsed_ticks that shuttle arrives
//timeleft = 360 //600
// call the shuttle
// if not called before, set the endtime to T+600 seconds
// otherwise if outgoing, switch to incoming
// returns the time (in seconds) before shuttle arrival
// note if direction = -1, gives a count-up to SHUTTLEARRIVETIME
// sets the time left to a given delay (in seconds)
// sets the shuttle direction
// 1 = towards SS13, -1 = back to centcom
// if changing direction, flip the timeleft by SHUTTLEARRIVETIME
// midnight rollover protection
// hey you, get out of the way!
// find the turf to move things to
//var/turf/E = get_step(D, SOUTH)
// NOTE: Commenting this out to avoid recreating mass driver glitch
// shuttle spends some time in transit to centcom before arriving
//online = 0
// standard shuttle departure - immediately arrives at centcom
//Multipliers for how much the motive is drained by certain things and for how much it is gained
//High drain rate - higher reduction of motive when explicitly modified
//High gain rate - higher gain of motive when explicitly modified
//var/affection_rate = 1
//Negative change, use drain modifier, positive, use gain modifier
//-1 unset, 0 law-abiding citizen, 1 traitor
//Let's save the results of this so we're not doing a bunch of thingy in list every life cycle
//But let's refresh it once / 20 cycles or so
//H.stunned = max(holder.owner.stunned, 1) <- Let's not punish others for our poor choices in life - unrealistic but more fun
// JFC fuck mobs
//Give it some time to finish creating the simsController because fak
//Set a profile on all simsMotives
//Change one value on every simsHolder
// relay procs
// var/list/dead = list()
// boutput(target, text("You have been picked to come back into play as [type], enter your new body now."))
//M.ckey = player:ckey
//M.ckey = player:ckey
//No the ship is gone
//mob.key = player.key
// drsingh attempted fix for Cannot read null.key
//var/obj/item/implant/sec/S = new /obj/item/implant/sec(user)
//S.implanted = 1
//S.implanted(user)
//S.owner = user
//user.implant.Add(S)
// user.equip_if_possible(new /obj/item/gun/fiveseven(user), user.slot_in_backpack)
// user.equip_if_possible(new /obj/item/gun/shotgun(user), user.slot_r_hand)
// user.equip_if_possible(new /obj/item/gun/mp5(user), user.slot_l_hand)
// user.equip_if_possible(new /obj/item/ammo/a57(user), user.slot_in_backpack)
//var/obj/item/implant/sec/S = new /obj/item/implant/sec(user)
//S.implanted = 1
//S.implanted(user)
//S.owner = src
//user.implant.Add(S)
// lazy
// honestly it's a 0.6% chance per round this happens - or once in 166 rounds - so i'm accounting for it before someone yells at me
//#define FLUCTUATION_DEBUG
// The current performance of the company. Tends itself to 0 when no events happen.
// These variables determine standard fluctuational patterns for this stock.
// How much the price fluctuates on an average daily basis
// The history of shareholder optimism of this stock
// The amount of offstation people holding shares in this company. The higher it is, the more fluctuation it causes.
// temporary
// pop that bubble
// if (available_shares < 200000 || (available_shares < 400000 && prob((400000 - available_shares) / 2000)) || average_shares < 25 || (average_shares < 50 && prob(50 - average_shares) * 4))
// splitStock()
// @todo crash if too little shares remain
// to make the vars update during 1st call
// 75% - 125% of standard rotation
// calculate the sun's position given the time of day
//
// 60 seconds, roughly - about a 5deg change
// gives about a 60 minute rotation time
// now 45 - 75 minutes, depending on rate
// Now around 30 - 40 min. An array would sometimes generate zero or close to zero electricity for up to 30 min
// of a typical round (~60 min), making solars not so useful.
// now calculate and cache the (dx,dy) increments for line drawing
// for a solar panel, trace towards sun to see if we're in shadow
// start at the solar panel
// 20 steps is enough
// do step
// not obscured if we reach the edge
// if we hit a solid turf, panel is obscured
// if hit the edge or stepped 20 times, not obscured
//returns the north-zero clockwise angle in degrees, given a direction
//SUPPLY PACKS
//NOTE: only secure crate types use the access var (and are lockable)
//NOTE: hidden packs only show up when the computer has been hacked.
//So as it turns out this is used in construction mode hardyhar
//If this is one the crate will only show up when the console is emagged
//What jobs can order it
//linked ID
// this did not need to be a string
// set the spawnpoint to the container we made so we don't have to duplicate the contains spawner loop
// Added security resupply crate (Convair880).
// TODO: spawn a new crate instead of just returning?
// vvv this is barf vvv
// How to add new items? Pick the correct path (nukeops, traitor, surplus) and go from there. Easy.
// Cost of the item. Leave 0 to make it unavailable.
// For job-specific items.
// For objective-specific items. Needs to be a type e.g. /datum/objective/assassinate.
// For items that can't show up in certain modes (affects uplink and surplus crates). Defined by the game mode datum (checks for children too).
// This should not go in surplus crates.
// Use this to run code when the item is spawned.
////////////////////////////////////////// Standard items (generic & nukeops uplink) ///////////////////////////////
// Note: traitor uplinks also list these, so you don't have to make two separate entries.
// Note #2: Nuke ops-exclusive item: /datum/syndicate_buylist/traitor + "objective = /datum/objective/specialist/nuclear".
//////////////////////////////////////////////////// Standard items (traitor uplink) ///////////////////////////////////
// Whatever you do, don't allow mindslave implants in spy or rev.
//////////////////////////////////////////////// Objective-specific items //////////////////////////////////////////////
//////////////////////////////////////////////// Job-specific items ////////////////////////////////////////////////////
// 2 TC for 1 speedloader was very poor value compared to other guns and traitor items in general (Convair880).
/////////////////////////////////////////// Surplus-exclusive items //////////////////////////////////////////////////
// Gave this thing a box of spare ammo. Having only one shot was kinda lackluster (Convair880).
// Why not, I guess? Cleaned up the old mine code, might as well use it (Convair880).
// RNG picker.
// At the time of writing, you can't get these anywhere else. And they fit the purpose of surplus crates quite well, I suppose (Convair880).
/////////////////////////////////////////////// Disabled items /////////////////////////////////////////////////////
// Needs to be fixed and less laggy.
//Alignment around the turf. Any can be combined with center (top and bottom for horizontal centering, left and right for vertical).
//For local-testing fallback
//Initialize some vars
//Dumb special case handling that I can't think of a better solution for
//Make our dumb param object
//out(src.owner, "Params: [params]. Theme: [theme]. Special: [special]") //DEBUG
//Send stuff to the tooltip
//If a hide() was hit while we were showing, run hide() again to avoid stuck tooltips
// DEBUG
// Stoner frog.
// Buys and sells drugs, gardening stuff, etc. Is sometimes REALLY fucking high.
// 6
// 8
// sometimes he is really, REALLY fucking high and can barely function as a trader
// Buford is selling these things
// Buford wants these things
// completely randomised generic trader
// Traders are selling these things
// Traders want these things
// Rockworm guy.
// Always buys mineral items from the station. Very honest and straightforward.
// Gragg is selling these things
// Gragg wants these things
// Lizardman dude in chinese finery.
// A total asshole who'll rip you off most of the time.
// Pianzi is selling these things
// Pianzi wants these things
// The name of the trader (duh)
// What they look like on comms
// What to label a crate if selling to them
// min and max patience for this trader
// how many times you can haggle the price before they get pissed off and leave, randomise it
// if the haggled price hike is this % or greater of the current price, reject it
// Makes the trader not show up on the QM console
// Chance for a trader to go hidden during a market shift
// Chance for a trader to stop hiding during a market shift
// will accept wrong-direction haggles
// lists of commodity datums that the trader will buy or sell, and the cart
// these are the base lists of commodities this trader will have
// these are the max amount of entries the trader will have on each list
// and these three are the active ones used for gameplay
// draws from dialogue to display a message
// dialogue banks
//Are we currently processing an order?
// This is called in New and also when the trader comes back from being away for a while
// It basically clears out and rejumbles their commodity lists to keep things fresh
// if something's gone wrong and there's no input, reject the haggle
// also reject if there's no change in the price at all
// if the player is being dumb and haggling in the wrong direction, tell them
// unless the trader is a dick in which case accept the terrible haggle outright
// check if the price increase % of the haggle is more than this trader will tolerate
// you are being a rude nerd and pushing it too far!
// now, the actual haggling part! find the middle ground between the two prices
// now slide it in the trader's favor slightly (hey, they're haggling too)
// warn the player if the trader isn't going to take any more haggling
//If we sold shit then don't increase the amount. Fuck.
// What it shows up as outside the shopping cart
// List of names the trader will call this commodity
// List of things this trade can be other than the base path
// The chance it will be one of those alternate things
// Minimum and maximum price for this commodity
// Dude in a cloak in the dark.
// A creepy guy who buys and sells really suspicious shit.
// Vurdalak is selling these things
// Vurdalak wants these things
// Unique things that Vurdalak wants
//Unlockable traits? tied to achievements?
//How many "free" points you get
//How many traits people can select at most.
//Yes these are objs because grid control. Shut up. I don't like it either.
//Unique ID
//The change in points when this is selected.
//Is this a positive, good effect or a bad one.
//If set to a non-null string, People will only be able to pick one trait of any given category
//If 1 , trait can not be select at char setup
//Name without any additional information.
//Fuck this. Fuck the way limbs are added with a delay. FUCK IT
//Just to be safe.
//Just to be safe.
//Just to be safe.
//UNSELECTABLE BELOW////UNSELECTABLE BELOW////UNSELECTABLE BELOW////UNSELECTABLE BELOW////UNSELECTABLE BELOW////UNSELECTABLE BELOW////UNSELECTABLE BELOW//
// People use this to identify changelings and people wearing disguises and I can't be bothered
// to rewrite a whole bunch of stuff for what is essentially something very specific and minor.
//Just to be safe.
//Just to be safe.
//Just to be safe.
//FUCK THIS SPAWN FUCK FUUUCK
//FUCK THIS SPAWN FUCK FUUUCK
//RANDOM SNIPPETS AND RUBBISH BELOW
//
//
/**
* updateQueue.dm
*/
// Init proc allows for recycling the worker.
/**
* init
* @param list objects objects to update
* @param text procName the proc to call on each item in the object list
* @param list arguments optional arguments to pass to the update proc
* @param number workerTimeout number of ticks to wait for an update to
finish before forking a new update worker
* @param bool inplace whether the updateQueue should make a copy of objects.
the internal list will be modified, so it is usually
a good idea to leave this alone. Default behavior is to
copy.
*/
// Make an internal copy of the list so we're not modifying the original.
// Init vars
/**
* We will copy the list in reverse order, as our doWork proc
* will access them by popping an element off the end of the list.
* This ends up being quite a lot faster than taking elements off
* the head of the list.
*/
// If world.timeofday has rolled over, then we need to adjust.
// This worker is a bit slow, let's spawn a new one and kill the old one.
// No worker!
// only run the worker if we have objects to work on
// No need to create a fresh worker if we already have one...
// Kill the worker
// After we kill a worker, yield so that if the worker's been tying up the cpu, other stuff can immediately resume
// If there's nothing left to execute or we were killed, mark finished and return.
// Absolute number of ticks since the world started up
// Pull out the object
// Remove the object from the list
// We only work with real objects
// If there's nothing left to execute
// or we were killed while running the above code, mark finished and return.
// We don't want to force a tick into overtime!
// If the tick is about to go overtime, spawn the next update to go
// in the next tick.
// We don't want to defer indefinitely. Each tick the queue defers, increment the defer count so it will tolerate a little more lag
// Execute anonymous function immediately as if we were in a while loop...
/**
* If the worker was killed while it was working on something, it
* should delete itself when it finally finishes working on it.
* Meanwhile, the updateQueue will have proceeded on with the rest of
* the queue. This will also terminate the spawned function that was
* created in the kill() proc.
*/
/**
* If the worker is not done in 30 seconds after it's killed,
* we'll forcibly delete it, causing the anonymous function it was
* running to be terminated. Hasta la vista, baby.
*/
//The amount of time spent processing this thing in total
//The amount of times this thing has been processed
// true if currently voting
// time at which next vote can be started
// time at which voting will end
// 0 = restart vote, 1 = mode vote
// modes which can be voted for
// the vote winner
////
// + 10*config.vote_delay
//marker1
// handle clock-wrapping problems - very long delay (>20 hrs) if wrapped
// hack to skip inter-space if either field is blank
// return '0sec' if 0 time left
// clients inactive for 2 minutes don't count
// means that voting was aborted by an admin
// clear vote window from all clients
// otherwise change mode
// vote in progress, do the current
// true if changing mode
//boutput(world, "[md]|[disp]|[src.client.vote]|[votes[md]]")
// voting to restart
//no vote in progress
// not time to vote yet
// voting can begin
// mob of player that clicked link
// double check even though this shouldn't happen
// hack to yield 0=restart, 1=changemode
// now voting
// when the vote will end
//boutput(world, "Setting client [M.key]'s vote to: [href_list["vote"]].")
// Logout buttons were discontinued because...?? Well, here they are again (Convair880).
// Won't delete the VR character otherwise, which can be confusing (detective's goggles sending you to the existing body in the bomb VR etc).
//Who is in V-space
//Spare virtual bodies. waste not want not
//Who is entering, What they are using to enter, Which network are they entering
// var/range_check = In_Network(user, network_device, network)
// if(!range_check)
// boutput(user, "<span style=\"color:red\">Out of network range!</span>")
// return
//no entry landmark
// Made much more prominent due to frequent a- and mhelps (Convair880).
// Stop littering the place with VR skulls and organs, aaahh (Convair880).
//I don't know of any items that delete themselves on drop BUT HEY
// character.real_name = "Virtual [user.real_name]"
//getfirebug.com/firebug-lite.js")
// padText() sides
// centers the text
// ascii values, for convenience.
/**
* Gets the character at the given position in the string.
* @param string The string to be queried.
* @param pos The position of the character to be gotten.
* @return the character at the given position in the given string.
*/
/**
* Check if the character at the given position in the string is whitespace.
* @param string The string to be queried.
* @param pos The position to be checked.
* @return TRUE if it is whitespace. FALSE otherwise.
*/
/**
* Capitalize the first character in a string.
* @param string The string to be capitalized.
* @return the capitalized form of the string.
*/
/**
* Removes preceeding and following whitespace in a string.
* @param string The string to be trimmed.
* @return the trimmed string.
* IE: trimWhitespace(" this is a string ] ") would return "this is a string ]".
*/
/**
* Finds the next occurrence of white space in a string, starting at the given position.
* @param string The string to be queried.
* @param pos Where to start searching for whitespace.
* @return the position of the next occurrence of whitespace, or null of there is no occurrence.
*/
/**
* Finds the xth occurence of a string within another string.
* @param string The string to be queried.
* @param sub The string to search for.
* @param which Which occurrence of the string [sub] to look for.
* @return the starting position of the xth (which) occurrence of [sub] within [string].
* 0 if nothing is found.
* IE: findWhich("a b a", "a", 2) would return 5 (where the second occurrence of "a" is).
* if which is -1, it will find the last occurrence of the substring.
*/
// find the LAST occurrence
// find whichever occurrence
/**
* The case-sensitive version of findWhich().
* @see kText.findWhich()
*/
/**
* Converts a string into a list, using a delimiter to determine where to separate entries.
* @param string The string to be listified.
* @param delimiter The string that will serve as a separator between entries in the list.
* @return the list form of the string.
* IE: text2list("this is a test", " ") would return list("this", "is", "a", "test").
*/
/**
* The case-sensitive version of text2list().
* @see kText.text2list()
*/
/**
* Converts a list into a string, placing a delimiter inbetween entries in the list.
* @param list The list to be textified.
* @param delimiter The string to place inbetween list entries.
* @return the string form of the list.
* IE: list2text(list("this", "is", "a", "test"), " ") would return "this is a test".
*/
/**
* Replaces all occurrences of one string within another string, with another string.
* @param string The string to be queried.
* @param sub The string to be searched for.
* @param replace The string to be used as a replacement.
* @return the given string, with all occurrences of [sub] replaced with [replace].
* IE: replaceText("i love cake", "cake", "pie") would return "i love pie".
*/
/**
* The case-sensitive version of replaceText().
* @see kText.replaceText()
*/
/**
* Pads a string so it is the given size.
* @param string The string to be padded.
* @param size The size the string should be padded to.
* @param padSide The side to place the padding on the string.
* @param padText The text to be used to pad the string.
* @return the padded form of the given string.
* IE: padText("Attributes:", 15, PAD_LEFT) would return " Attributes:".
*
* note: When using PAD_BOTH, the given text will attempt to be centered.
* This function assumes a fixed-width font, which means if the size
* of the padding is uneven, then one side (the right side) will be
* given an extra padding.
*
* For example, padText("ABC", 6, PAD_BOTH, "-") would require atleast 3
* padding characters. Since this can't be split down the middle,
* one of the padding characters will be added to the end of the string:
* "-ABC--".
*/
// they both do the same thing, so just switch around the return values.
/**
* Removes linebreaks from the given string, replacing them with spaces.
* @param string The string to be modified.
* @return The string, with linebreaks replaced with spaces.
*/
/**
* Adds linebreaks to the string every X characters.
* If the character at the position we want to place the linebreak at isn't whitespace,
* it will look for the next whitespace character before placing it.
* @param string The string to be modified.
* @param charsPerLine How many characters should be on each separate line.
* @return The modified string, with linebreaks placed every X characters.
* IE: autoBreak("I am not a crook.", 5) would return "I am\nnot a\ncrook."
*
* note: To keep the newly created lines consistent, this will also remove any
* extra whitespace at the beginning and ends of newly added lines.
*/
/**
* Check if the given needle's characters all match the string's characters.
* For example, the needle "ca" -- since "ca" begins the string "cake", "ca" is a match to it, thus "auto-completes"
* to it.
* @param string The string to be matched against.
* @param needle The string we want to know if matches.
* @return if needle matches string, returns string.
* otherwise, null.
* IE: autoComplete("hippo", "h") would return "hippo".
*/
// to remain consistent, and allow for embedded lists, this is necessary.
/**
* The case-sensitive version of autoComplete().
* @see kText.autoComplete()
*/
// to remain consistent, and allow for embedded lists, this is necessary.
/**
* Checks if any of the space-delimited words within [needle] match to the space-delimited words in [string].
* This matching uses the same method of matching as autoComplete().
* Basically, "c p" matches "cake pie", because "c" and "p" autocomplete to "cake" and "pie", respectively.
* It should also be noted that if one of the keywords in [needle] does not have a match in [string],
* the match will fail.
* @param string The set of words to match against.
* @param needle The set of words to be searched for.
* @return if all the keywords in [needle] have a matching keyword in [string], returns [string].
* otherwise, null.
* matchKeys("giant king monster", "giant monster") would return "giant king monster".
* matchKeys("giant king monster", "giant snail") would return null, because "snail" has no match.
*/
// get space delimited list of needle keywords
// for a list of keywords
// to remain consistent, and allow for embedded lists, this is necessary.
// for a string of keywords
// get space-delimited list of string keywords
// for every keyword in the needle phrase...
// match it to atleast on keyword in the string phrase
// if none of the string keywords matched a needle keyword, this was a failure
// string was a success!
/**
* The case-sensitive version of matchKeys().
* @see kText.matchKeys()
*/
// get space delimited list of match keywords
// for a list of keywords
// to remain consistent, and allow for embedded lists, this is necessary.
// for a string of keywords
// get space-delimited list of string keywords
// for every keyword in the needle phrase...
// match it to atleast on keyword in the string phrase
// if none of the string keywords matched a needle keyword, this was a failure
// string was a success!
/**
* Simply repeats the given string a certain amount of times.
* @param string The string to repeat.
* @param count The amount to be repeated.
* @return The string, repeated [count] times.
*/
/*///////////////////////////////////////////////////////////////////////////
|* The Deadron Zone.
|* These functions were added simply to be "feature complete," so I can claim
|* the library does what Deadron's library does and then some.
|* In this way, people who *want* these functions AND *want* the functions of
|* kText, they can just include kText by itself.
\*/
//////////////////////////////////////////////////////////////////////////
/**
* Reads the contents of a file and separates it into a list, using the specified delimiter to
* separate entries.
* @param file The file object, or string referring to the file.
* @param delimiter The delimiter used to separate the text.
* @return Returns the listified version of the file.
* null if a bad file was given.
*/
/**
* The case-sensitive version of file2list().
* @see kText.file2list()
*/
/**
* Attempts to determine if the string is prefixed with the given prefix.
* @param string The string to check against.
* @param prefix The prefix to check for.
* @return 1 if the prefix was found. Just think of it as TRUE.
* 0 if the prefix was not found.
*/
/**
* The case-sensitive version of hasPrefix().
* @see kText.hasPrefix()
*/
/**
* Attempts to determine if the string is suffixed with the given suffix.
* @param string The string to check against.
* @param suffix The suffix to check for.
* @return The beginning of the suffix in the string (string's length - suffix's length + 1) if it is found.
* 0 if the suffix was not found.
*/
/**
* The case-sensitive version of hasSuffix().
* @see kText.hasSuffix()
*/
/**
* Limits the max length of a string.
* @param length The maximum length a string can be.
* @return If the string is longer than the given string, returns the string after it is cut short.
* Otherwise, the entire string.
*/
// Set_Background(xval,yval,C)
//If view is already a number, set xval and yval
//If not, it is a text var. Parse the xval and yval values
//If view is already a number, set xval and yval
//If not, it is a text var. Parse the xval and yval values
// yval = text2num(copytext(C.view, divider+1))
// drsingh for Cannot execute null.Update Color()
//#define DEBUG
//Processing all tiles as one large tile if 1
//cycle that oxygen value represents
//cycle that oxygen_archived value represents
//The use of archived cycle saves processing power by permitting the archiving step of FET
// to be rolled into the updating step
//Tiles that connect this group to other groups/individual tiles
//All tiles in this group
// Space tiles that border this group
// Length of space border
// drsingh - lets try caching these lists from process_group, see if we can't reduce the garbage collection
//used to send the appropriate border tile of a group to the group proc
// overrides
// Group procs
// Distribute air from the group out to members
//Copy group air information to individual tile air
//Used right before turning on group processing
// Single sample? Seems like not very many...
// Local var, direct access to gas_mixture, no need to pool
//I guess all the areas were BADSPACE!!! OH NO! (Spyguy fix for pick() from empty list)
//Copy group air information to individual tile air
//Used right before turning off group processing
//If individually processing tiles, checks all member tiles to see if they are close enough
// that the group may resume group processing
//Warning: Do not call, called by air_master.process()
//Purpose: Checks to see if group processing should be turned back on
//Returns: group_processing
// I don't know why the fuck space tiles are even getting into
// airgroups, but this should sort of fix it. This is a bad
// hack and I'm sorry. This should eliminate the runtime
// "undefined variable: /turf/space/var/air"
//I guess all the areas were BADSPACE!!! OH NO! (Spyguy fix for pick() from empty list)
// Marq fix for undefined variable /turf/space/var/air
//See if processing this group as a group
//used to send the appropriate border tile of a group to the group proc
//Archive air data for use in calculations
//But only if another group didn't store it for us
//var/obj/movable/floor/movable_on_me = locate(/obj/movable/floor) in border_tile
//Go through all border tiles and get bordering groups and individuals
//Add found tile to appropriate category
// Tiles can get added to these lists more than once, but that is OK,
// because groups sharing more than one edge should transfer more air.
// Tile is a border with another group, and the other group is in group processing mode.
// Build border groups list
// Build enemies list
// Build self-group border list
// Tile is a border with a singleton, not a group in group processing mode.
// Build individual border list
// Build self-tile-border list
// Process connections to adjacent groups
//archive other groups information if it has not been archived yet this cycle
//This if statement makes sure two groups only process their individual connections once!
//Without it, each connection would be processed a second time as the second group is evaluated
// Process connections to adjacent tiles
//archive tile information if not already done
// Process connections to space
// This logic is not inverted because group processing may have been
// suspended in the above block.
//Revert to individual processing
// space fastpath
// If the fastpath resulted in the group being zeroed, return early.
// If group processing is off, and the air group is bordered by a space tile,
// execute a fast evacuation of the air in the group.
// If the average pressure in the group is < 5kpa, the group will be zeroed
// returns: 1 if the group is zeroed, 0 if not
// find nearest space border tile
// Todo - retain nearest space tile border and apply force proportional to amount
// of air leaving through it
//I hate having to add this here too but too many things use hotspot_expose. This might cause lag on large fires.
// have to call this now to force the lighting cleanup
//remove just_spawned protection if no longer processing this cell
//Icon for fire on turfs, also helps for nurturing small fires until they are full tile
//layer = TURF_LAYER
// fix for weird unpool sliding
// now this is ss13 level code
// dear lord i apologuize for this conditional which i am about to write and commit. please be with the starving pygmies down in new guinea amen
// debug_log += "[src.x],[src.y]:[temperature] max diff was [max_color_diff], [red] [green] [blue] vs [sd_ColorRed] [sd_ColorGreen] [sd_ColorBlue]"
//Possible spread due to radiated heat
// note: light is left disabled until the color is set
//
// Overrides
// Gas equation procs
// Mutator procs
// For specific events
//returns 1 if graphic changed
//set to 1 if a notable reaction occured (used by pipe_network)
//General volatile gas burn
//qdel(fuel_store)
//Handle plasma burning
//more plasma released at higher temperatures
//Update archived versions of variables
//Returns: 1 in all cases
//Similar to merge(...) but first checks to see if the amount of air assumed is small enough
// that group processing is still accurate for source (aborts if not)
//Returns: 1 on successful merge, 0 if the check failed
//Merges all air from giver into self. Deletes giver.
//Returns: 1 on success (no failure cases yet)
//Proportionally removes amount of gas from the gas_mixture
//Returns: gas_mixture with the gases removed
//Can not take more air than tile has!
//Proportionally removes amount of gas from the gas_mixture
//Returns: gas_mixture with the gases removed
/**/
if(trace_gases && trace_gases.len)
for(var/datum/gas/trace_gas in trace_gases)
var/datum/gas/corresponding = new trace_gas.type()
if(!removed.trace_gases)
removed.trace_gases = list()
removed.trace_gases += corresponding
corresponding.moles = trace_gas.moles*ratio
trace_gas.moles -= corresponding.moles/group_multiplier
removed.temperature = temperature
return removed
//Similar to remove(...) but first checks to see if the amount of air removed is small enough
// that group processing is still accurate for source (aborts if not)
//Returns: gas_mixture with the gases removed or null
/datum/gas_mixture/proc/check_then_remove(amount)
//Since it is all proportional, the check may be done on the gas as a whole
var/sum = total_moles()
amount = min(amount,sum) //Can not take more air than tile has!
if((amount > MINIMUM_AIR_RATIO_TO_SUSPEND) && (amount > sum*MINIMUM_AIR_RATIO_TO_SUSPEND))
return 0
return remove(amount)
//Copies variables from sample
/datum/gas_mixture/proc/copy_from(datum/gas_mixture/sample)
if (sample == null)
return
oxygen = sample.oxygen
carbon_dioxide = sample.carbon_dioxide
nitrogen = sample.nitrogen
toxins = sample.toxins
trace_gases = null
if(sample.trace_gases && sample.trace_gases.len > 0)
trace_gases = list()
for(var/datum/gas/trace_gas in sample.trace_gases)
var/datum/gas/corresponding = new trace_gas.type()
trace_gases += corresponding
corresponding.moles = trace_gas.moles
temperature = sample.temperature
return 1
//Subtracts right_side from air_mixture. Used to help turfs mingle
/datum/gas_mixture/proc/subtract(datum/gas_mixture/right_side)
oxygen -= right_side.oxygen
carbon_dioxide -= right_side.carbon_dioxide
nitrogen -= right_side.nitrogen
toxins -= right_side.toxins
if(right_side.trace_gases && right_side.trace_gases.len > 0)
trace_gases = list()
for(var/datum/gas/trace_gas in right_side.trace_gases)
var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases
if(!corresponding)
corresponding = new trace_gas.type()
trace_gases += corresponding
corresponding.moles -= trace_gas.moles
return 1
//Returns: 0 if the self-check failed then -1 if sharer-check failed then 1 if both checks pass
/datum/gas_mixture/proc/check_gas_mixture(datum/gas_mixture/sharer)
if (!sharer)
return 0
var/delta_oxygen = (oxygen_archived - sharer.oxygen_archived)/5
var/delta_carbon_dioxide = (carbon_dioxide_archived - sharer.carbon_dioxide_archived)/5
var/delta_nitrogen = (nitrogen_archived - sharer.nitrogen_archived)/5
var/delta_toxins = (toxins_archived - sharer.toxins_archived)/5
var/delta_temperature = (temperature_archived - sharer.temperature_archived)
if(((abs(delta_oxygen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_oxygen) >= oxygen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
|| ((abs(delta_carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_carbon_dioxide) >= carbon_dioxide_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
|| ((abs(delta_nitrogen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_nitrogen) >= nitrogen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
|| ((abs(delta_toxins) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_toxins) >= toxins_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)))
return 0
if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND)
return 0
if(sharer.trace_gases && sharer.trace_gases.len)
if(!trace_gases || !trace_gases.len)
return 0
for(var/datum/gas/trace_gas in sharer.trace_gases)
if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND*4)
var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases
if(corresponding)
if(trace_gas.moles_archived >= corresponding.moles_archived*MINIMUM_AIR_RATIO_TO_SUSPEND*4)
return 0
else
return 0
if(trace_gases && trace_gases.len)
if(!sharer.trace_gases || !sharer.trace_gases.len)
return 0
for(var/datum/gas/trace_gas in trace_gases)
if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND*4)
if(!locate(trace_gas.type) in sharer.trace_gases)
return 0
if(((abs(delta_oxygen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_oxygen) >= sharer.oxygen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
|| ((abs(delta_carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_carbon_dioxide) >= sharer.carbon_dioxide_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
|| ((abs(delta_nitrogen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_nitrogen) >= sharer.nitrogen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
|| ((abs(delta_toxins) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_toxins) >= sharer.toxins_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)))
return -1
if(trace_gases && trace_gases.len)
for(var/datum/gas/trace_gas in trace_gases)
if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND*4)
var/datum/gas/corresponding
if(sharer.trace_gases && sharer.trace_gases.len)
corresponding = locate(trace_gas.type) in sharer.trace_gases
if(corresponding)
if(trace_gas.moles_archived >= corresponding.moles_archived*MINIMUM_AIR_RATIO_TO_SUSPEND*4)
return -1
else
return -1
return 1
//Returns: 0 if self-check failed or 1 if check passes
/datum/gas_mixture/proc/check_turf(turf/model)
var/delta_oxygen = (oxygen_archived - model.oxygen)/5
var/delta_carbon_dioxide = (carbon_dioxide_archived - model.carbon_dioxide)/5
var/delta_nitrogen = (nitrogen_archived - model.nitrogen)/5
var/delta_toxins = (toxins_archived - model.toxins)/5
var/delta_temperature = (temperature_archived - model.temperature)
if(((abs(delta_oxygen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_oxygen) >= oxygen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
|| ((abs(delta_carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_carbon_dioxide) >= carbon_dioxide_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
|| ((abs(delta_nitrogen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_nitrogen) >= nitrogen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
|| ((abs(delta_toxins) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_toxins) >= toxins_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)))
return 0
if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND)
return 0
if(trace_gases && trace_gases.len)
for(var/datum/gas/trace_gas in trace_gases)
if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND*4)
return 0
return 1
//Performs air sharing calculations between two gas_mixtures assuming only 1 boundary length
//Return: amount of gas exchanged (+ if sharer received)
/datum/gas_mixture/proc/share(datum/gas_mixture/sharer)
if(!sharer)
return
var/delta_oxygen = QUANTIZE(oxygen_archived - sharer.oxygen_archived)/5
var/delta_carbon_dioxide = QUANTIZE(carbon_dioxide_archived - sharer.carbon_dioxide_archived)/5
var/delta_nitrogen = QUANTIZE(nitrogen_archived - sharer.nitrogen_archived)/5
var/delta_toxins = QUANTIZE(toxins_archived - sharer.toxins_archived)/5
var/delta_temperature = (temperature_archived - sharer.temperature_archived)
var/old_self_heat_capacity = 0
var/old_sharer_heat_capacity = 0
var/heat_capacity_self_to_sharer = 0
var/heat_capacity_sharer_to_self = 0
if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/delta_air = delta_oxygen+delta_nitrogen
if(delta_air)
var/air_heat_capacity = SPECIFIC_HEAT_AIR*delta_air
if(delta_air > 0)
heat_capacity_self_to_sharer += air_heat_capacity
else
heat_capacity_sharer_to_self -= air_heat_capacity
if(delta_carbon_dioxide)
var/carbon_dioxide_heat_capacity = SPECIFIC_HEAT_CDO*delta_carbon_dioxide
if(delta_carbon_dioxide > 0)
heat_capacity_self_to_sharer += carbon_dioxide_heat_capacity
else
heat_capacity_sharer_to_self -= carbon_dioxide_heat_capacity
if(delta_toxins)
var/toxins_heat_capacity = SPECIFIC_HEAT_TOXIN*delta_toxins
if(delta_toxins > 0)
heat_capacity_self_to_sharer += toxins_heat_capacity
else
heat_capacity_sharer_to_self -= toxins_heat_capacity
old_self_heat_capacity = heat_capacity()*group_multiplier
old_sharer_heat_capacity = sharer.heat_capacity()*sharer.group_multiplier
oxygen -= delta_oxygen/group_multiplier
sharer.oxygen += delta_oxygen/sharer.group_multiplier
carbon_dioxide -= delta_carbon_dioxide/group_multiplier
sharer.carbon_dioxide += delta_carbon_dioxide/sharer.group_multiplier
nitrogen -= delta_nitrogen/group_multiplier
sharer.nitrogen += delta_nitrogen/sharer.group_multiplier
toxins -= delta_toxins/group_multiplier
sharer.toxins += delta_toxins/sharer.group_multiplier
var/moved_moles = (delta_oxygen + delta_carbon_dioxide + delta_nitrogen + delta_toxins)
var/list/trace_types_considered
if(trace_gases && trace_gases.len)
trace_types_considered = list()
for(var/datum/gas/trace_gas in trace_gases)
var/datum/gas/corresponding
if(sharer.trace_gases && sharer.trace_gases.len)
corresponding = locate(trace_gas.type) in sharer.trace_gases
var/delta = 0
if(corresponding)
delta = QUANTIZE(trace_gas.moles_archived - corresponding.moles_archived)/5
else
corresponding = new trace_gas.type()
if(!sharer.trace_gases)
sharer.trace_gases = list()
sharer.trace_gases += corresponding
delta = trace_gas.moles_archived/5
trace_gas.moles -= delta/group_multiplier
corresponding.moles += delta/sharer.group_multiplier
if(delta)
var/individual_heat_capacity = trace_gas.specific_heat*delta
if(delta > 0)
heat_capacity_self_to_sharer += individual_heat_capacity
else
heat_capacity_sharer_to_self -= individual_heat_capacity
moved_moles += delta
trace_types_considered += trace_gas.type
if(sharer.trace_gases && sharer.trace_gases.len)
for(var/datum/gas/trace_gas in sharer.trace_gases)
if(trace_types_considered && trace_gas.type in trace_types_considered) continue
else
var/datum/gas/corresponding
var/delta = 0
corresponding = new trace_gas.type()
if(!trace_gases)
trace_gases = list()
trace_gases += corresponding
delta = trace_gas.moles_archived/5
trace_gas.moles -= delta/sharer.group_multiplier
corresponding.moles += delta/group_multiplier
//Guaranteed transfer from sharer to self
var/individual_heat_capacity = trace_gas.specific_heat*delta
//heat_sharer_to_self += individual_heat_capacity*sharer.temperature_archived
heat_capacity_sharer_to_self += individual_heat_capacity
moved_moles += -delta
if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/new_self_heat_capacity = old_self_heat_capacity + heat_capacity_sharer_to_self - heat_capacity_self_to_sharer
var/new_sharer_heat_capacity = old_sharer_heat_capacity + heat_capacity_self_to_sharer - heat_capacity_sharer_to_self
if(new_self_heat_capacity > MINIMUM_HEAT_CAPACITY)
temperature = (old_self_heat_capacity*temperature - heat_capacity_self_to_sharer*temperature_archived + heat_capacity_sharer_to_self*sharer.temperature_archived)/new_self_heat_capacity
if(new_sharer_heat_capacity > MINIMUM_HEAT_CAPACITY)
sharer.temperature = (old_sharer_heat_capacity*sharer.temperature-heat_capacity_sharer_to_self*sharer.temperature_archived + heat_capacity_self_to_sharer*temperature_archived)/new_sharer_heat_capacity
if(abs(old_sharer_heat_capacity) > MINIMUM_HEAT_CAPACITY)
if(abs(new_sharer_heat_capacity/old_sharer_heat_capacity - 1) < 0.10) // <10% change in sharer heat capacity
temperature_share(sharer, OPEN_HEAT_TRANSFER_COEFFICIENT)
if((delta_temperature > MINIMUM_TEMPERATURE_TO_MOVE) || abs(moved_moles) > MINIMUM_MOLES_DELTA_TO_MOVE)
var/delta_pressure = temperature_archived*(total_moles() + moved_moles) - sharer.temperature_archived*(sharer.total_moles() - moved_moles)
return (delta_pressure*R_IDEAL_GAS_EQUATION/volume)
else
return 0
//Similar to share(...), except the model is not modified
//Return: amount of gas exchanged
/datum/gas_mixture/proc/mimic(turf/model, border_multiplier = 1)
var/delta_oxygen = QUANTIZE(((oxygen_archived - model.oxygen)/5)*border_multiplier/group_multiplier)
var/delta_carbon_dioxide = QUANTIZE(((carbon_dioxide_archived - model.carbon_dioxide)/5)*border_multiplier/group_multiplier)
var/delta_nitrogen = QUANTIZE(((nitrogen_archived - model.nitrogen)/5)*border_multiplier/group_multiplier)
var/delta_toxins = QUANTIZE(((toxins_archived - model.toxins)/5)*border_multiplier/group_multiplier)
var/delta_temperature = (temperature_archived - model.temperature)
var/heat_transferred = 0
var/old_self_heat_capacity = 0
var/heat_capacity_transferred = 0
if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/delta_air = delta_oxygen+delta_nitrogen
if(delta_air)
var/air_heat_capacity = SPECIFIC_HEAT_AIR*delta_air
heat_transferred -= air_heat_capacity*model.temperature
heat_capacity_transferred -= air_heat_capacity
if(delta_carbon_dioxide)
var/carbon_dioxide_heat_capacity = SPECIFIC_HEAT_CDO*delta_carbon_dioxide
heat_transferred -= carbon_dioxide_heat_capacity*model.temperature
heat_capacity_transferred -= carbon_dioxide_heat_capacity
if(delta_toxins)
var/toxins_heat_capacity = SPECIFIC_HEAT_TOXIN*delta_toxins
heat_transferred -= toxins_heat_capacity*model.temperature
heat_capacity_transferred -= toxins_heat_capacity
old_self_heat_capacity = heat_capacity()*group_multiplier
oxygen -= delta_oxygen
carbon_dioxide -= delta_carbon_dioxide
nitrogen -= delta_nitrogen
toxins -= delta_toxins
var/moved_moles = (delta_oxygen + delta_carbon_dioxide + delta_nitrogen + delta_toxins)
if(trace_gases && trace_gases.len)
for(var/datum/gas/trace_gas in trace_gases)
var/delta = 0
delta = QUANTIZE((trace_gas.moles_archived/5)*border_multiplier/group_multiplier)
trace_gas.moles -= delta
var/heat_cap_transferred = delta*trace_gas.specific_heat
heat_transferred += heat_cap_transferred*temperature_archived
heat_capacity_transferred += heat_cap_transferred
moved_moles += delta
if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/new_self_heat_capacity = old_self_heat_capacity - heat_capacity_transferred
if(new_self_heat_capacity > MINIMUM_HEAT_CAPACITY)
if(border_multiplier)
temperature = (old_self_heat_capacity*temperature - heat_capacity_transferred*border_multiplier*temperature_archived)/new_self_heat_capacity
else
temperature = (old_self_heat_capacity*temperature - heat_capacity_transferred*border_multiplier*temperature_archived)/new_self_heat_capacity
temperature_mimic(model, model.thermal_conductivity, border_multiplier)
if((delta_temperature > MINIMUM_TEMPERATURE_TO_MOVE))
var/delta_pressure = temperature_archived*(total_moles() + moved_moles) - model.temperature*(model.oxygen+model.carbon_dioxide+model.nitrogen+model.toxins)
return (delta_pressure*R_IDEAL_GAS_EQUATION/volume)
else
return 0
/datum/gas_mixture/proc/check_both_then_temperature_share(datum/gas_mixture/sharer, conduction_coefficient)
var/delta_temperature = (temperature_archived - sharer.temperature_archived)
var/self_heat_capacity = heat_capacity_archived()
var/sharer_heat_capacity = sharer.heat_capacity_archived()
var/self_temperature_delta = 0
var/sharer_temperature_delta = 0
if((sharer_heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY))
var/heat = conduction_coefficient*delta_temperature* \
(self_heat_capacity*sharer_heat_capacity/(self_heat_capacity+sharer_heat_capacity))
self_temperature_delta = -heat/(self_heat_capacity*group_multiplier)
sharer_temperature_delta = heat/(sharer_heat_capacity*sharer.group_multiplier)
else
return 1
if((abs(self_temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) \
&& (abs(self_temperature_delta) > MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND*temperature_archived))
return 0
if((abs(sharer_temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) \
&& (abs(sharer_temperature_delta) > MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND*sharer.temperature_archived))
return -1
temperature += self_temperature_delta
sharer.temperature += sharer_temperature_delta
return 1
//Logic integrated from: temperature_share(sharer, conduction_coefficient) for efficiency
/datum/gas_mixture/proc/check_me_then_temperature_share(datum/gas_mixture/sharer, conduction_coefficient)
var/delta_temperature = (temperature_archived - sharer.temperature_archived)
var/self_heat_capacity = heat_capacity_archived()
var/sharer_heat_capacity = sharer.heat_capacity_archived()
var/self_temperature_delta = 0
var/sharer_temperature_delta = 0
if((sharer_heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY))
var/heat = conduction_coefficient*delta_temperature* \
(self_heat_capacity*sharer_heat_capacity/(self_heat_capacity+sharer_heat_capacity))
self_temperature_delta = -heat/(self_heat_capacity*group_multiplier)
sharer_temperature_delta = heat/(sharer_heat_capacity*sharer.group_multiplier)
else
return 1
if((abs(self_temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) \
&& (abs(self_temperature_delta) > MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND*temperature_archived))
return 0
temperature += self_temperature_delta
sharer.temperature += sharer_temperature_delta
return 1
//Logic integrated from: temperature_share(sharer, conduction_coefficient) for efficiency
/datum/gas_mixture/proc/check_me_then_temperature_turf_share(turf/simulated/sharer, conduction_coefficient)
var/delta_temperature = (temperature_archived - sharer.temperature)
var/self_temperature_delta = 0
var/sharer_temperature_delta = 0
if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/self_heat_capacity = heat_capacity_archived()
if((sharer.heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY))
var/heat = conduction_coefficient*delta_temperature* \
(self_heat_capacity*sharer.heat_capacity/(self_heat_capacity+sharer.heat_capacity))
self_temperature_delta = -heat/(self_heat_capacity*group_multiplier)
sharer_temperature_delta = heat/sharer.heat_capacity
else
return 1
if((abs(self_temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) \
&& (abs(self_temperature_delta) > MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND*temperature_archived))
return 0
temperature += self_temperature_delta
sharer.temperature += sharer_temperature_delta
return 1
//Logic integrated from: temperature_turf_share(sharer, conduction_coefficient) for efficiency
/datum/gas_mixture/proc/check_me_then_temperature_mimic(turf/model, conduction_coefficient)
var/delta_temperature = (temperature_archived - model.temperature)
var/self_temperature_delta = 0
if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/self_heat_capacity = heat_capacity_archived()
if((model.heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY))
var/heat = conduction_coefficient*delta_temperature* \
(self_heat_capacity*model.heat_capacity/(self_heat_capacity+model.heat_capacity))
self_temperature_delta = -heat/(self_heat_capacity*group_multiplier)
if((abs(self_temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) \
&& (abs(self_temperature_delta) > MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND*temperature_archived))
return 0
temperature += self_temperature_delta
return 1
//Logic integrated from: temperature_mimic(model, conduction_coefficient) for efficiency
/datum/gas_mixture/proc/temperature_share(datum/gas_mixture/sharer, conduction_coefficient)
var/delta_temperature = (temperature_archived - sharer.temperature_archived)
if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/self_heat_capacity = heat_capacity_archived()
var/sharer_heat_capacity = sharer.heat_capacity_archived()
if((sharer_heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY))
var/heat = conduction_coefficient*delta_temperature* \
(self_heat_capacity*sharer_heat_capacity/(self_heat_capacity+sharer_heat_capacity))
temperature -= heat/(self_heat_capacity*group_multiplier)
sharer.temperature += heat/(sharer_heat_capacity*sharer.group_multiplier)
/datum/gas_mixture/proc/temperature_mimic(turf/model, conduction_coefficient, border_multiplier)
var/delta_temperature = (temperature - model.temperature)
if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/self_heat_capacity = heat_capacity()//_archived()
if((model.heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY))
var/heat = conduction_coefficient*delta_temperature* \
(self_heat_capacity*model.heat_capacity/(self_heat_capacity+model.heat_capacity))
if(border_multiplier)
temperature -= heat*border_multiplier/(self_heat_capacity*group_multiplier)
else
temperature -= heat/(self_heat_capacity*group_multiplier)
/datum/gas_mixture/proc/temperature_turf_share(turf/simulated/sharer, conduction_coefficient)
var/delta_temperature = (temperature_archived - sharer.temperature)
if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/self_heat_capacity = heat_capacity()
if((sharer.heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY))
var/heat = conduction_coefficient*delta_temperature* \
(self_heat_capacity* sharer.heat_capacity /(self_heat_capacity+sharer.heat_capacity))
temperature -= heat/(self_heat_capacity*group_multiplier)
sharer.temperature += heat/sharer.heat_capacity
//Compares sample to self to see if within acceptable ranges that group processing may be enabled
/datum/gas_mixture/proc/compare(datum/gas_mixture/sample)
if (!sample)
return 0
if((abs(oxygen-sample.oxygen) > MINIMUM_AIR_TO_SUSPEND) && \
((oxygen < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.oxygen) || (oxygen > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.oxygen)))
return 0
if((abs(nitrogen-sample.nitrogen) > MINIMUM_AIR_TO_SUSPEND) && \
((nitrogen < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.nitrogen) || (nitrogen > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.nitrogen)))
return 0
if((abs(carbon_dioxide-sample.carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && \
((carbon_dioxide < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.carbon_dioxide) || (oxygen > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.carbon_dioxide)))
return 0
if((abs(toxins-sample.toxins) > MINIMUM_AIR_TO_SUSPEND) && \
((toxins < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.toxins) || (toxins > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.toxins)))
return 0
if((total_moles()) > MINIMUM_AIR_TO_SUSPEND)
if((abs(temperature-sample.temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) && \
((temperature < (1-MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND)*sample.temperature) || (temperature > (1+MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND)*sample.temperature)))
return 0
if(sample.trace_gases && sample.trace_gases.len)
for(var/datum/gas/trace_gas in sample.trace_gases)
if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND)
var/datum/gas/corresponding
if(trace_gases && trace_gases.len)
corresponding = locate(trace_gas.type) in trace_gases
if(corresponding)
if((abs(trace_gas.moles - corresponding.moles) > MINIMUM_AIR_TO_SUSPEND) && \
((corresponding.moles < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*trace_gas.moles) || (corresponding.moles > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*trace_gas.moles)))
return 0
else
return 0
if(trace_gases && trace_gases.len)
for(var/datum/gas/trace_gas in trace_gases)
if(trace_gas.moles > MINIMUM_AIR_TO_SUSPEND)
var/datum/gas/corresponding
if(sample.trace_gases)
corresponding = locate(trace_gas.type) in sample.trace_gases
if(corresponding)
if((abs(trace_gas.moles - corresponding.moles) > MINIMUM_AIR_TO_SUSPEND) && \
((trace_gas.moles < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*corresponding.moles) || (trace_gas.moles > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*corresponding.moles)))
return 0
else
return 0
return 1
// Dead prototypes (or never implemented?)
// /datum/gas_mixture/proc/check_me_then_share(datum/gas_mixture/sharer)
//Similar to share(...) but first checks to see if amount of air moved is small enough
// that group processing is still accurate for source (aborts if not)
//Returns: 1 on successful share, 0 if the check failed
// /datum/gas_mixture/proc/check_me_then_mimic(turf/model)
//Similar to mimic(...) but first checks to see if amount of air moved is small enough
// that group processing is still accurate (aborts if not)
//Returns: 1 on successful mimic, 0 if the check failed
// /datum/gas_mixture/proc/check_both_then_share(datum/gas_mixture/sharer)
//Similar to check_me_then_share(...) but also checks to see if amount of air moved is small enough
// that group processing is still accurate for the sharer (aborts if not)
//Returns: 0 if the self-check failed then -1 if sharer-check failed then 1 if successful share
//Basically, join any nearby valid groups
// If more than one, pick one with most members at my borders
// If can not find any but there was an ungrouped at border with me, call for group assembly
//Clear those we do not have access to
// boutput(world, "[north_votes], [south_votes], [east_votes]")
//OPTIMIZE
//archive self if not already done
//Grab all valid bordering tiles
//archive bordering tile information if not already done
//apply tile to group sharing
//group processing failed so interact with individual tile
//archive bordering tile information if not already done
//apply tile to group sharing
//group processing failed so interact with individual tile
//bordering a tile with fixed air properties
//not active if not processing!
//
// turf/Enter(...) will perform more advanced checks
// Now, doing more detailed checks for air movement and air group formation
//Geoemetry lists
//Special functions lists
//Geometry updates lists
//Call this at the start to setup air groups geometry
//Warning: Very processor intensive but only must be done once per round
//Call this to try to construct a group starting from base and merging with neighboring unparented tiles
//Expands the group until all valid borders explored
// assemble_group_object(obj/movable/floor/base)
//Call this to process air movements for a cycle
//Used by process()
//Warning: Do not call this
//Used by process()
//Warning: Do not call this
//Used by process()
//Warning: Do not call this
//Used by process()
//Warning: Do not call this
//Used by process()
//Warning: Do not call this
//Used by process()
//Warning: Do not call this
//Used by process_rebuild_select_groups()
//Warning: Do not call this, add the group to air_master.groups_to_rebuild instead
//for(var/turf/simulated/S in world) //Update all pathing and border information as well
//Update all pathing and border information as well
//Confirmed group members
//Possible places for group expansion
//Keep expanding, looking for new members
//Initialize air group variables
//singletons at startup are technically unconnected anyway
//Confirmed group members
//Possible places for group expansion
//Keep expanding, looking for new members
//Initialize air group variables
//singletons at startup are technically unconnected anyway
//Check for groups of tiles to resume group processing every 10 cycles
// There's about 700 airgroups, so this should be enough...
// This list can be quite large, so lets not scheck like a madperson.
//Deconstruct groups, gathering their old members
// This can be some expensive shit, so lets scheck every time.
//Have old members try to form new groups
//for(var/turf/simulated/S in turfs)
// var/obj/movable/list/movable_objects = list()
//Deconstruct groups, gathering their old members
//Have old members try to form new groups
//use this for machines to adjust air
//First, ensure there is no movable shuttle or what not on tile that is taking over
// var/obj/movable/floor/movable_on_me = locate(/obj/movable/floor) in src
// if(istype(movable_on_me))
// return movable_on_me.assume_air(giver)
//First, ensure there is no movable shuttle or what not on tile that is taking over
// var/obj/movable/floor/movable_on_me = locate(/obj/movable/floor) in src
// if(istype(movable_on_me))
// return movable_on_me.return_air()
//Create gas mixture to hold data for passing
// TODO this is returning a new air object, but object_tile returns the existing air
// This is used in a lot of places and thrown away, so it should be pooled,
// But there is no way to tell here if it will be retained or discarded, so
// we can't pool the object returned by return_air. Bad news, man.
//, remove_water = 0)
//First, ensure there is no movable shuttle or what not on tile that is taking over
// var/obj/movable/floor/movable_on_me = locate(/obj/movable/floor) in src
// if(istype(movable_on_me))
// return movable_on_me.remove_air(amount)
//if(remove_water)
// sum += water
//if(remove_water)
// GM.water += (water/sum)*amount
//Do not modify this, just call air_master.queue_update_tile on this
//USED ONLY FOR SOLIDS
//overlays.len = 0
//dd_text2list(model.graphic, ";")
// air.parent = src //TODO DEBUG REMOVE
// have to call this now to force the lighting cleanup
//For open space like floors
//, remove_water = 0)
//, remove_water)
//, remove_water)
//, remove_water)
//OPTIMIZE
//See if actually a border
//See what kind of border it is
//archive self if not already done
//Grab all valid bordering tiles
//archive bordering tile information if not already done
//apply tile to group sharing
//group processing failed so interact with individual tile
/* var/obj/movable/floor/movable_on_enemy = locate(/obj/movable/floor) in enemy_tile
if(movable_on_enemy)
if(movable_on_enemy.parent && movable_on_enemy.parent.group_processing) //apply tile to group sharing
if(movable_on_enemy.parent.current_cycle < current_cycle)
if(movable_on_enemy.parent.air.check_gas_mixture(air))
connection_difference = air.share(movable_on_enemy.parent.air)
else
movable_on_enemy.parent.suspend_group_processing()
if(movable_on_enemy.archived_cycle < archived_cycle) //archive bordering tile information if not already done
movable_on_enemy.archive()
connection_difference = air.share(movable_on_enemy.air)
//group processing failed so interact with individual tile
else
if(movable_on_enemy.archived_cycle < archived_cycle) //archive bordering tile information if not already done
movable_on_enemy.archive()
if(movable_on_enemy.current_cycle < current_cycle)
connection_difference = share_air_with_tile(movable_on_enemy)
else*/
//bordering a tile with fixed air properties
//not active if not processing!
//Does not participate in air exchange, so will conduct heat across all four borders at this time
//Does particate in air exchange so only consider directions not considered during process_cell()
//Conduct with tiles around me
//anything under this subtype will share in the exchange
//Both tiles are open
//both are acting as a group
//modified using construct developed in datum/air_group/share_air_with_group(...)
//have to deconstruct parent air group
//may have to deconstruct neighbors air group
// have to deconstruct neightbors air group but not mine
//may have to deconstruct neighbors air group
// boutput(world, "OPEN, OPEN")
//Solid but neighbor is open
// boutput(world, "SOLID, OPEN")
//Open but neighbor is solid
// boutput(world, "OPEN, SOLID")
//Both tiles are solid
// boutput(world, "SOLID, SOLID")
//Open
//Radiate excess tile heat to space
//Considering 0 degC as te break even point for radiation in and out
//Conduct with air on my tile if I have it
//Make sure still hot enough to continue conducting heat
//Rebuild/update nearby group geometry
/**
* qdel
*
* queues a var for deletion by the delete queue processor.
* if used on /world, /list, /client, or /savefile, it just skips the queue.
*/
/**
* We'll assume here that the object will be GC'ed.
* If the object is not GC'ed and must be explicitly deleted,
* the delete queue process will decrement the gc counter and
* increment the explicit delete counter for the type.
*/
// In the delete queue, we need to check if this is actually supposed to be deleted.
/**
* We will only enqueue the ref for deletion. This gives the GC time to work,
* and makes less work for the delete queue to do.
*/
// -------------------- GLOBAL VARS --------------------
//obj/hud/main_hud1 = null
// need another list to pull atmos machines out of the main machine loop and in with the pipe networks
//items that ask to be called every cycle
//List of items that want to be deleted
//list/total_deletes = list() //List of things totally deleted
// set to world.timeofday when round starts, then used to calculate round time
// true if net rebuild will be called manually after an event
// true if master controller should be paused (usually for some large event)
// persistent connection to a mysql server
// Database query handler
// for the pre-roundstart thing
// same as above
//Contains instances of the reward datums
//Contains instances of the material recipe datums
// don't ask.
//List of trait objects
//Player keys that have played this round, to prevent that "jerk gets deleted by a bug, gets to respawn" thing.
// if /obj/random_pod_spawner exists on the map, this will be filled with refs to the pods they make, and people joining up will have a chance to start with the unlock code in their memory
//list/disposed_things_that_dont_work = list()
// no just shut up right now, I don't care
////////////////
///////////////
///////////////
//april fools
// datum/air_tunnel/air_tunnel1/SS13_airtunnel = null
// putting crew score shit here
// these ones are mainly for the stat panel
///////////////
//Radio network passwords
//Detomatix
///////////////
//Loooooooooogs
//The file holding computer ID information
//Should we be analysing the comp IDs of new clients?
// list/traitobj = list( )
// tracking warnings per round, i guess
// multiplier for watts per tick <> cell storage (eg: .002 means if there is a load of 1000 watts, 20 units will be taken from a cell per second)
// Cap for how fast cells charge, as a percentage-per-tick (.001 means cellcharge is capped to 1% per second)
//default
// airtunnel_start = 68 // default
// airtunnel_stop = 68 // default
// airtunnel_bottom = 72 // default
//prisoners go to these
//list/mazewarp = list()
//prison security goes to these
//list of players already warped
// special turfs from map landmarks to always allow telescience to access
// telesci landmarks add a 3z3 area centered on themselves to this list
// list of locations for people to fall if they enter the deep abyss on the ice moon
// list of locations for people to fall if they enter the ice moon elevator shaft
// list of locations for people to fall into the precursor pit area
// list of locations for people to fall into the ancient pit area
// biodome elevator shaft
// Controllers
// global debug switch
// SET THIS TO 0 TO DISABLE SIMS MODE
//airlockWireColorToIndex takes a number representing the wire color, e.g. the orange wire is always 1, the dark red wire is always 2, etc. It returns the index for whatever that wire does.
//airlockIndexToWireColor does the opposite thing - it takes the index for what the wire does, for example AIRLOCK_WIRE_IDSCAN is 1, AIRLOCK_WIRE_POWER1 is 2, etc. It returns the wire color number.
//airlockWireColorToFlag takes the wire color number and returns the flag for it (1, 2, 4, 8, 16, etc)
// once jobban list is ready this is set to a giant string of all the jobban data. the new panel chops it up for use client side with javascript
// increments every time the ban panel is built so clients know if they have the latest
// set to world.timeofday when the cache is built
// ditto
// ditto
// drsingh global reaction cache to reduce cpu usage in handle_reactions (Chemistry-Holder.dm)
// SpyGuy global reaction structure to further recuce cpu usage in handle_reactions (Chemistry-Structure.dm)
//This sure beats processing the monster above if I want a particular reaction. =I
//SpyGuy: The reagents cache is now an associative list
// if you want stuff to not be spawnable by the list or buildmode, put it in here:
// cache for reusing datums
// list of miscreants since mode is irrelevant
// Antag overlays for admin ghosts, Syndieborgs and the like (Convair880).
//SpyGuy: Oh my fucking god the QM shit. *cry *wail *sob *weep *vomit *scream
//Okay, I guess this was getting constructed every time someone wanted something from it
//AI camera movement dealies
//What it says on the tin.
//Also what it says on the tin.
//Cameras that should be rebuilt
//Associative list keyed by network name, contains a list of each camera in a network.
//List of particlesystems that the connection display proc creates. I dunno where else to put it. :(
//If camera connections reciprocate one another or if the path is calculated separately for each camera
//Are we able to connect to the central server?
//How many times have we tried and failed to connect?
//Resource Management
//Contains link to CDN as specified in the config (if not locally testing)
//Pool limiter overrides
// for translating a zone_sel's id to its name
// Rick hub
//world
// hub = "Slurm.SpaceStation13"
// hub_password = ""
// name = "Goon Station 13"
// Exadv1 hub
// "Vice Officer",
// "Head of Security",
// "Hangar Mechanic", "Hangar Mechanic",
// "Chemist","Chemist",
// "Attorney at Space-Law")
// "Mechanic",
// "Atmospheric Technician","Atmospheric Technician","Atmospheric Technician",
//Used for PDA department paging.
//loaded on startup because of "
//would include in rsc if ' was used
//
// this list is for mentors, everyone in the NT
// list is also a mentor, this is for people who
// are mentors but not HOSes
//Range outside a single camera before static starts
//How much static-y extra range outside the normal range. After this its 100% static
//animate(ai_static, alpha = (ai_static.alpha + newval)/2, time = 5)
//animate(alpha = newval, time = 5)
//list of all covered turfs.
//closest covered turf
//Temporarily cranking up the camera luminosity because only mobs have see_in_dark. its either this or making cameras mobs.
//Without this , camera range would decrease in darkness and thats silly. This shouldnt cause any visual artifacts as its reset right after the calculations
//The closest tile is actually behind a wall or something.
//This could not happen but hey byond and just in case.
// Observer
// don't get pushed around
// observer mode
// ghost luminosity
//#ifdef HALLOWEEN
//#endif
//ov1
// overlays
//src.updateOverlaysClient(src.client)
// Observer Life() only runs for admin ghosts (Convair880).
// comment all of these back out after hallowe'en
//fffffuckk you
//Wire TODO
//Check queue participation
//Enter into queue
//set dnr
//remember dialogs
//prefix list with option for alphabetic sorting
// Same thing you could do with the old auth disk. The bomb is equally important
// and should appear at the top of any unsorted list (Convair880).
/*for(var/mob/wraith/W in world)
var/name = W.name
if (name in names)
namecounts[name]++
name = "[name] ([namecounts[name]])"
else
names.Add(name)
namecounts[name] = 1
if (W.real_name && W.real_name != W.name)
name += " \[[W.real_name]\]"
creatures[name] = W*/
// DOESN'T SEEM TO ADD ANY FUNCTIONALITY SO HEY, WHY WAS THIS EVEN HERE
// if (is_admin)
// eye_name = input("Please, select a player!", "Admin Observe", null, null) as null|anything in creatures
// else
// eye_name = input("Please, select a player!", "Observe", null, null) as null|anything in creatures
//sort alphabetically if user so chooses
//redisplay sorted list
//Wire: Fix for Cannot modify null.mob.
// Observer Life() only runs for admin ghosts (Convair880).
// dead
// No log entries for unaffected mobs (Convair880).
// fart
// roll the probability first so we're not checking for critters each time this happens
/*for (var/mob/dead/O in viewers(src, null))
O.show_*/
// cluwne
// how you gonna have father ted and father jack and not father dougal? smh
//biker // cogwerks - bringing back the bikers for the diner, now less offensive
/// BILL SPEECH STUFF
//src.equip_if_possible(new /obj/item/clothing/suit(src), slot_wear_suit)
//src.equip_if_possible(new /obj/item/clothing/head/biker_cap(src), slot_head)
// stop on first human mob
//SpyGuy for undefined var/len (what the heck)
// merchant
// myke
// waldo
// Where's WAL[DO/LY]???
// Cannot be observed
///proc/animate_spin(var/atom/A, var/dir = "L", var/T = 1, var/looping = -1)
//#define MAX_MINIONS_PER_SPAWN 3
//src.mind = new
// movement_delay()
// return ..() - 10
/* verb/macho_minions()
set name = "Macho Minions"
set desc = "Summons a horde of micro men"
set category = "Macho Moves"
if (!src.stat && !src.transforming)
src.verbs -= /mob/living/carbon/human/machoman/verb/macho_minions
src.bioHolder.AddEffect("fire_resist")
src.transforming = 1
src.visible_message("<span style=\"color:red\"><B>[src] begins glowing with ominous power!</B></span>")
playsound(src.loc, "sound/effects/chanting.ogg", 75, 0, 0, src.get_age_pitch())
sleep(40)
for (var/mob/N in viewers(src, null))
N.flash(30)
if (N.client)
shake_camera(N, 6, 4)
N.show_message(text("<span style=\"color:red\"><b>A blinding light envelops [src]!</b></span>"), 1)
playsound(src.loc, "sound/weapons/flashbang.ogg", 50, 1)
src.visible_message("<span style=\"color:red\"><B>A group of micro men suddenly materializes!</B></span>")
var/made_minions = 0
for (var/turf/T in orange(1))
var/obj/critter/microman/micro = new(T)
made_minions ++
micro.friends += src
micro.dir = src.dir
if (made_minions >= MAX_MINIONS_PER_SPAWN)
break
src.transforming = 0
src.bioHolder.RemoveEffect("fire_resist")
playsound(src.loc, pick(snd_macho_rage), 50, 0, 0, src.get_age_pitch())
spawn(1200) // holy shit the micro man spam from ONE macho man is awful
src.verbs += /mob/living/carbon/human/machoman/verb/macho_minions
*/
// var/icon/composite = icon(src.icon, src.icon_state, null, 1)
// composite.MapColors(-1,0,0, 0,-1,0, 0,0,-1, 1,1,1)
// for (var/O in src.overlays)
// var/image/I = O
// var/icon/Ic = icon(I.icon, I.icon_state)
// Ic.MapColors(-1,0,0, 0,-1,0, 0,0,-1, 1,1,1)
// composite.Blend(Ic, ICON_OVERLAY)
// src.overlays = null
// src.icon = composite
//heals 50 burn, 50 brute from all organs
//alldirs
//the_dir = turn(the_dir,45)
//PUNCH THE HEART! YEAH!
// new D(heart_to_punt.loc)
//Extra mean to borgs.
//Uh?
// lol
//heals 50 burn, 50 brute from all organs
// gold
//#undef MAX_MINIONS_PER_SPAWN
//Please ignore how silly this path is.
// special monkeys.
// :getin:
//src.ai_aggressive = 1
//pal.ai_aggressive = 1
// ???
//The npc doing the action
//The target of the action
//The slot number
// Added for forensics (Convair880).
// change gender/bloodtype/age/name/underwear, keep bioeffects
//var/area/current_loc = get_area(src)
//var/tmp/loc_name = lowertext(current_loc.name) // removing this because nobody believes it
//// rest in peace NPC classic-retards, you were shit ////
// npc ai procs
//NOTE TO SELF: BYONDS TIMING FUNCTIONS ARE INACCURATE AS FUCK
//ADD HELP INTEND.
//0 = Pasive, 1 = Getting angry, 2 = Attacking , 3 = Helping, 4 = Idle , 5 = Fleeing(??)
//Moving this up because apparently beds were tripping the AI up.
//WE'RE STUCKED :C
// var/turf/T = get_turf(src)
// if((T.poison > 100000.0 || T.firelevel || T.oxygen < 560000 || T.co2 > 7500.0) && !istype(get_turf(src), /turf/space) )
// ai_avoid(T)
// else ai_move()
//Priority-based target finding
//Any reason we do not want to take this target into account AT ALL?
//Let's not fight ourselves (unless we're real crazy) or a dead person... or NPCs, unless we're allowed to.
//Base rating
//Why do we WANT to go after this jerk?
//if(!T) rating += 10 //We don't have a target, this one will do
//We'd rather go after actual non-braindead players
//Hey, you're a jerk! (but I'm not a jerk)
//Why do we NOT want to go after this jerk
//This one's unconscious
//I'd rather fight my own fight
//I don't want to go after my fellow NPCs unless there is no other option
//I don't want to go after myself
//I definitely don't want to go after my old target; chances are I still can't get to them.
//Any reasons that could go either way when dealing with this bum?
//I'd rather fight things with a lot of health because I AIN'T NO COWARD!
//Clamp the rating
//Do we like this target better than the last one?
//Did we find anyone to fight?
//Life is good.
//ai_findtarget()
//WHATS THAT?
//Oh, it is on now! >:C
//Gonna kick your ass.
//If we're fighting ourselves we wanna look for other targets periodically
//Can't get to this dork
//I can attack someone! =D
//I can attack someone! =D
//I can attack someone! =D
//Combat Trash Talk
// need to restore this at some point i guess, the "monkeys bite" code is commented out right now
//if(src.get_brain_damage() >= 60 && prob(25))
// target.attack_paw(src) // retards bite
//else
//We're a human!
//With a weapon ...
//Remove.
//step_towards(src, ai_target)
//We're in fast approach mode
//Take a step and hit the shite (but only if you won't push them out of the way by doing so)
//Extremely simple. EXTREMELY.
//WTF
//Simple right now.
//So they dont smash windows while wandering around.
//This should probably not be bulletproof, har har
// ahhhh fuck this im just making every shot be a chest shot for now -drsingh
//thanks to the odd scaling i have to cap this.
// take_bleeding_damage(src, damage, DAMAGE_BLUNT) // im haine
//implanted.implanted(src, null, min(20, max(0, round(damage / 10) ) ))
//thanks to the odd scaling i have to cap this.
//bleed
// take_bleeding_damage(src, damage, DAMAGE_STAB) // im stupid
//implanted.implanted(src, null, min(20, max(0, round(damage / 10) ) ))
//thanks to the odd scaling i have to cap this.
//bleed
// take_bleeding_damage(src, damage, DAMAGE_CUT) // im coder
//thanks to the odd scaling i have to cap this.
//src.set_clothing_icon_dirty()
//thanks to the odd scaling i have to cap this.
// fire resistance should probably not let you get hurt by welders
//thanks to the odd scaling i have to cap this.
//thanks to the odd scaling i have to cap this.
// Logs.
// there used to be mining radiation check here which increases severity by one
// this needs to be derived from material properties instead and is disabled for now
// For forensics (Convair880).
// let's make this function like mining armor
// buffed a bit - cogwerks
// let's not get too crazy
// let's not get too crazy
//src.paralysis += 1
// calling lastgasp() here because we just got knocked out
//tox *= 2
//if (src.bioHolder && src.bioHolder.HasEffect("resist_toxic"))
//tox = 0
//tox = max(0, burn)
//mostly covered by individual procs that cause burn damage, but just in case
//How many organs have brute damage?
//How many organs have burn damage?
// gurbage
//Let's find out
//No damage
//This is ugly, but necessary
// Modify eye_damage or eye_blind if prompted, but don't perform more than we absolutely have to.
// so we don't enter the damage switch thing if we're healing damage
//DEBUG("Eye damage applied: [amount]. Tempblind: [tempblind == 0 ? "N" : "Y"]")
// lol
// If he's wearing magnetic boots anchored = 1, otherwise anchored = 0
// Automatically drop anything in store / id / belt if you're not wearing a uniform.
// Uniform
// No blood overlay if we have gloves (e.g. bloody hands visible through clean gloves).
// Gloves
//src.bioHolder && !src.bioHolder.HasEffect("robot_left_arm"))
//src.bioHolder && !src.bioHolder.HasEffect("robot_right_arm"))
// Shoes
//. = src.limbs && (!src.limbs.l_leg || istype(src.limbs.l_leg, /obj/item/parts/robot_parts) //(src.bioHolder && src.bioHolder.HasOneOfTheseEffects("lost_left_leg","robot_left_leg","robot_treads"))
//[!( src.lying ) ? null : "2"]"
//[!( src.lying ) ? null : "2"]"
//[!( src.lying ) ? null : "2"]"
//[!( src.lying ) ? null : "2"]"
//[!( src.lying ) ? null : "2"]"
// Glasses
//[(!( src.lying ) ? null : "2")]"
// Ears
//[(!( src.lying ) ? null : "2")]"
//[(!( src.lying ) ? null : "2")]"
// Head
/* TODO: adapt butts to blend colors properly again
if (istype(src.head, /obj/item/clothing/head/butt))
var/obj/item/clothing/head/butt/B = src.head
if (B.s_tone >= 0)
head_icon.Blend(rgb(B.s_tone, B.s_tone, B.s_tone), ICON_ADD)
else
head_icon.Blend(rgb(-B.s_tone, -B.s_tone, -B.s_tone), ICON_SUBTRACT)
*/
// Belt
// if (src.wear_id) //Most of the inventory is now hidden, this is handled by other_update()
// src.wear_id.screen_loc = ui_id
// fuck u
// gaaaaaaaaaahhhhh
//src.fire_standing = image('icons/mob/human.dmi', "fire1", MOB_EFFECT_LAYER)
//src.fire_lying = image('icons/mob/human.dmi', "fire1_l", MOB_EFFECT_LAYER)
//src.fire_standing = image('icons/mob/human.dmi', "fire2", MOB_EFFECT_LAYER)
//src.fire_lying = image('icons/mob/human.dmi', "fire2_l", MOB_EFFECT_LAYER)
//src.fire_standing = image('icons/mob/human.dmi', "fire3", MOB_EFFECT_LAYER)
//src.fire_lying = image('icons/mob/human.dmi', "fire3_l", MOB_EFFECT_LAYER)
//make them light up!
// image('icons/mob/human.dmi', "blank", MOB_LIMB_LAYER)
//image('icons/mob/human.dmi', "blank", MOB_HAND_LAYER1)
// this is awful
// ugh
// ugh
// ugh
// ugh
//Also forcing the updates since the overlays may have been modified on the images
//if (src.damage_animation)
//src.overlays += src.damage_animation
// image('icons/mob/dam_human.dmi', "[brute_state][burn_state]", MOB_DAMAGE_LAYER)
// image('icons/mob/dam_human.dmi', head_damage, MOB_DAMAGE_LAYER)
//image('icons/mob/dam_human.dmi', "00", MOB_DAMAGE_LAYER)
// nodamage = 1
// human
// var/obj/item/device/radio/w_radio = null
//var/obj/item/card/id/wear_id = null
//var/image/face_standing = null
// amount of blood to absorb from the reagent holder per Life()
// is someone currently putting pressure on their wounds?
// set to 1 to basically skip the handle_organs() proc
// used in /proc/process_accents() to keep cluwnes from making constant fucking noise
// 1 = bloat, 2 = decay, 3 = advanced decay, 4 = skeletonized
//What the hell is wrong with me?
// SPIDERS
// Fire a kinetic firearm and get forensic evidence all over you (Convair880).
//The spooky UNKILLABLE MAN
// TODO: defensive/offensive stance intents for combat
// do we chill out after a while?
//april fools stuff
//dismemberment stuff
//, layer = MOB_UNDERWEAR_LAYER)
// preloaded sounds moved up to /mob/living
// IF YOU ARE HERE TO DISABLE SIMS MODE, DO NOT TOUCH THIS. LOOK IN GLOBAL.DM
// fix for "Cannot execute null.update body()".when mob is deleted too quickly after creation
//Fix for not being able to move after you got new limbs.
//Fix for not being able to move after you got new limbs.
// reset skintone to whatever the holder's s_tone is
// need to make an item arm
// need to make an item arm
// death
//The unkillable man just respawns nearby! Oh no!
//Unless they have dnr set in which case rip for good
//Zombies just rise again (after a delay)! Oh my!
//Changelings' heads pop off and crawl away - but only if they're not gibbed and have some spare DNA points. Oy vey!
//make a headspider, have it crawl to find a host, give the host the disease, hand control to the player again afterwards
// This stuff isn't free, you know.
//In case we ghosted ourselves then the body won't hold the mind. Bad times.
//A little kickstart to get you out into the big world (and some chump), li'l guy! O7
//let the world KNOW WE ARE DEAD
// wow fucking racist
//weasellos time of death patch
// I think this is kinda important (Convair880).
//src.icon_state = "dead"
// maybe add a check to see if they've been de-revved?
//Unkillable respawn proc, also used by soulguard now
// Also for removing antagonist status. New mob required to get rid of old-style, mob-specific antagonist verbs (Convair880).
//Try to appear on a turf other than the one we die on.
////////////////Set up the new body./////////////////
// These necessities (organs/limbs/inventory) are bad enough. I don't care about specific damage values etc.
// Antag status removal doesn't happen very often (Convair880).
// There's a spawn(20) in that proc.
// We don't want changeling etc ability holders (Convair880).
// Doesn't work properly for half the antagonist types anyway (Convair880).
// Prone to causing runtimes, don't enable.
/* if (src.mutantrace && !src.spell_soulguard)
newbody.mutantrace = new src.mutantrace.type(newbody)*/
//Mind transfer also handles key transfer.
// Ugly but necessary until I can figure out a better to do this or every antagonist has been moved to ability holders.
// Transfering it directly to the new mob DOESN'T dispose of certain antagonist-specific verbs (Convair880).
//Oh welp, still need to move that key!
////////////Now play the degibbing animation and move them to the turf.////////////////
//Don't want this lying around to repeatedly die or whatever.
// clear this as well
//Detach this, what if we get deleted before the animation ends??
//Length of animation.
// Has to at least match the organ/limb replacement stuff (Convair880).
// emote
// default to visible
//april fools start
//april fools end
// clown juggling
// might drop stuff while already juggling things
// everyone else
// store the picked phrase in here
// if the find_type_in_hand() returned 0 earlier
// maybe it's on our head?
// if not then never mind
// does it have one of the beret icons?
// call it a beret
// otherwise?
// call it a hat. this should cover cases where the hat somehow doesn't have either hosberet or hoscap
// has it been smashed already?
// then add some extra flavor text
// the actual messages are generated here
// make sure it looks smushed!
// we're done here, drop that hat!
// basic visible single-word emotes
// the switch is lowertext()ed so this is what :D would be
// same as above for D: and DX
// basic visible single-word emotes - unusable while restrained
// basic audible single-word emotes
//1% chance to change sigh to singh. a bad joke for drsingh fans.
// visible targeted emotes
// basic emotes that change the wording a bit
// basic emotes with alternates for restraints
// targeted emotes
// emotes that do STUFF! or are complex in some way i guess
// some movement to make it look cooler
// implement some special visual moves
// expand this too, however much
// todo: add context-sensitive break dancing and some other goofy shit
//TODO: space flipping
//if ((!src.restrained()) && (!src.lying) && (istype(src.loc, /turf/space)))
// message = "<B>[src]</B> does a flip!"
// if (prob(50))
// animate(src, transform = turn(GetPooledMatrix(), 90), time = 1, loop = -1)
// animate(transform = turn(GetPooledMatrix(), 180), time = 1, loop = -1)
// animate(transform = turn(GetPooledMatrix(), 270), time = 1, loop = -1)
// animate(transform = turn(GetPooledMatrix(), 360), time = 1, loop = -1)
// else
// animate(src, transform = turn(GetPooledMatrix(), -90), time = 1, loop = -1)
// animate(transform = turn(GetPooledMatrix(), -180), time = 1, loop = -1)
// animate(transform = turn(GetPooledMatrix(), -270), time = 1, loop = -1)
// animate(transform = turn(GetPooledMatrix(), -360), time = 1, loop = -1)
//src.set_loc(M.loc)
// just in case, so the user doesn't fall into nullspace if they fly at a person mid-gibbing or whatever
// this is hilariously overpowered, but WHATEVER!!!
/* if (src.bioHolder.HasEffect("hulk"))
playsound(src.loc, "sound/effects/splat.ogg", 75, 1)
G.affecting.gib()
*/
// startled into playing dead!
//. += "<br><span style=\"color:blue\">This is <B>[src.name]</B>!</span>"
// crappy hack because you can't do \his[src] etc
/* if (src.gender == MALE)
t_his = "his"
t_him = "him"
else if (src.gender == FEMALE)
t_his = "her"
t_him = "her"
*/
// Added a check for vampires (Convair880).
// && src.reagents.has_reagent("montaguone")))
// cogwerks // let's treat this like pain
// firesuits slow you down a bit
// firesuits slow you down a bit
// space suits slow you down a bit unless in space;
// cogwerks - new evil armor thing
// cogwerks - lowered this from 10
// miner boots, split off from the suit
// miner boots, split off from the suit
//less effect if there's only one i guess
//can't pull yourself along too well
//haha good luck
//Treads speed you up a bunch
//robot legs speed you up a little
// eh
//If none of the keys were used as ability hotkeys, use it for intents instead.
///mob/living/carbon/human/click(atom/target, params)
///mob/living/carbon/human/Stat()
// u_equip() already calls item.dropped()
//if (istype(item, /obj/item))
//item:dropped(src) // let it know it's been dropped
//actually throw it!
// Added log_reagents() call for drinking glasses. Also the location (Convair880).
//they're in space, move em one space in the opposite direction
/////
//G = null
// can't see the face
// Marquesas: I'm literally adding an extra parameter here so I don't have to port a metric shitton of code elsewhere.
// These calculations really should be doable via another proc.
//Apparently M could be a meatcube and this causes HELLA runtimes.
/*if (src.limbs && (src.hand ? !src.limbs.l_arm:can_hold_items : !src.limbs.r_arm:can_hold_items)) // this was fucking stupid and broke item limbs, I mean really, how do you restrain someone whos arm is a goddamn CHAINSAW
return 1*/
//SN src = null
//SN src = null
/* TODO - DONE
else if (istype(src.target.l_hand, /obj/item/staff) && prob(75))
src.source.show_message(text("<span style=\"color:red\">The [src.target.l_hand] is too slippery to hold on to!</span>"), 1)
qdel(src)
return
*/
//SN src = null
/* TODO - DONE
else if (istype(src.target.r_hand, /obj/item/staff) && prob(75))
src.source.show_message(text("<span style=\"color:red\">The [src.target.r_hand] is too slippery to hold on to!</span>"), 1)
qdel(src)
return
*/
//SN src = null
/* TODO - DONE
else if (istype(src.target.wear_suit, /obj/item/clothing/suit/wizrobe) && prob(75))
src.source.show_message(text("<span style=\"color:red\">The [src.target.wear_suit] writhes in your hands as though it is alive!</span>"), 1)
qdel(src)
return
*/
//SN src = null
//SN src = null
//SN src = null
//SN src = null
//SN src = null
//SN src = null
//SN src = null
/* TODO - DONE
else if (istype(src.target.shoes, /obj/item/clothing/shoes/sandal) && prob(75))
src.source.show_message(text("<span style=\"color:red\">The [src.target.shoes] seem to be part of the feet!</span>"), 1)
qdel(src)
return
*/
/* TODO - DONE
else if (istype(src.target.head, /obj/item/clothing/head/wizard) && prob(75))
src.source.show_message(text("<span style=\"color:red\">The [src.target.shoes] won't come off!</span>"), 1)
qdel(src)
return
*/
/* TODO - DONE
else if (istype(src.target.head, /obj/item/clothing/head/butt) && src.target.head:stapled )
src.source.show_message(text("<span style=\"color:red\"><B>[src.source.name] rips out the staples from \the [src.target.head.name]!</B></span>"), 1)
src.target.head:unstaple()
new /obj/decal/cleanable/blood(src.target.loc)
playsound(src.target.loc, "sound/effects/splat.ogg", 50, 1)
src.target.emote("scream")
src.target.TakeDamage("head", rand(8, 16), 0)
*/
//SN src = null
// new damage icon system
// now constructs damage icon for each organ from mask * damage field
// <BR><A href='?src=\ref[src];item=pockets'>Empty Pockets</A>
// called when something steps onto a human
// this could be made more general, but for now just handle mulebot
//HURP DURP OLD CODE PATH BELOW
/* if (href_list["item"] && !usr.stat && usr.canmove && !usr.restrained() && in_range(src, usr) && ticker)
var/obj/equip_e/human/O = new /obj/equip_e/human( )
O.source = usr
O.target = src
O.item = usr.equipped()
O.s_loc = usr.loc
O.t_loc = src.loc
O.place = href_list["item"]
spawn( 0 )
O.process()
return
..()
return*/
// do brute damage to a random organ
//???
// do burn damage to a random organ
//???
// Jewel's attempted fix for: null.return_air()
// These objects should be garbage collected the next tick, so it's not too bad if it's not breathing I think? I might be totallly wrong here.
//still breathing
//Chemicals in the body
//Mutations and radiation
//special (read: stupid) manual breathing stuff. weird numbers are so that messages don't pop up at the same time as manual blinking ones every time
//First, resolve location and get a breath
//Only try to take a breath every 4 seconds, unless suffocating
//Still give containing object the chance to interact
//Apparently, the person who wrote this code designed it so that
//blinded get reset each cycle and then get activated later in the
//code. Very ugly. I dont care. Moving this stuff here so its easy
//to find it.
//Disease Check
//Handle temperature/pressure differences between body and environment
//stuff in the stomach
//Disabilities
//Status updates, death etc.
// Marq was here, breaking everything.
//Being buckled to a chair or bed
// Yup.
//100
//80
//75
//50
//25
//10
//0
//Regular Trait updates
// Icons
//ov1
// overlays
// Grabbing
// stop going up into the thousands, goddamn
// bleeding = max(min(bleeding, 10),0)
// blood_volume = max(blood_volume, 0)
//Normal equip gives you around ~212. Spacesuits ~362. Firesuits ~863.
//normal equip = 0, spacesuits = 1, firesuits = 6
// cogwerks note: both the cryo cell and morgue things technically work, but the corpse rots instantly when removed
// if it has been in there longer than the next decomp time that was initiated before the corpses went in. fuck!
// will work out a fix for that soon, too tired right now
// advances every 4-10 game minutes
// moved drowsy, confusion and such from handle_chemicals because it seems better here
// The value at which this stuff is capped at can be found in mob.dm
//GENETIC INSTABILITY FUN STUFF
//Oh no!
// For forensics (Convair880).
//src.make_meatcube(60)
// if (prob(2)) //maybe let's not bake in something that makes people go blind if they're fat
// boutput(src, "<span style=\"color:red\">Your flesh bubbles and writhes!</span>")
// src.bioHolder.RandomEffect("bad",1)
// only goes up to 200 but we might as well catch exceptions just in case
// no breathing inside possessed objects
//if (istype(loc, /obj/machinery/clonepod)) return
// Changelings generally can't take OXY/LOSEBREATH damage...except when they do.
// And because they're excluded from the breathing procs, said damage didn't heal
// on its own, making them essentially mute and perpetually gasping for air.
// Didn't seem like a feature to me (Convair880).
// HACK NEED CHANGING LATER
//if (src.oxymax == 0 || (breathtimer > 15))
//Suffocating so do not take a breath
//High chance of gasping for air
//First, check for air from internal atmosphere (using an air tank and mask generally)
//No breath from internal atmosphere so get breath from location
//Still give containing object the chance to interact
// Looks like we're in space
// or with recent atmos changes, in a room that's had a hole in it for any amount of time, so now we check src.loc
//We aren't breathing.
// Minimum safe partial pressure of O2, in kPa
//var/safe_oxygen_max = 140 // Maximum safe partial pressure of O2, in kPa (Not used for now)
// Yes it's an arbitrary value who cares?
//Partial pressure of the O2 in our breath
// Same, but for the toxins
// And CO2, lets say a PP of more than 10 will be bad (It's a little less really, but eh, being passed out all round aint no fun)
// Too little oxygen
// Don't fuck them up too fast (space only does 7 after all!)
// We're in safe limits
// If it's the first breath with too much CO2 in it, lets start a counter, then have them pass out after 12s or so.
// Lets hurt em a little, let them know we mean business
// They've been in here 30s now, lets start to kill them for their own good!
// Lets give them some chance to know somethings not right though I guess.
// Too much toxins
// If there's some other shit in the air lets deal with it here.
// Enough to make us paralysed for a bit
// 3 gives them one second to wake up and run away a bit!
// Enough to make us sleep as well
// There is sleeping gas in their lungs, but only a little, so give them a bit of a warning
// Hot air hurts :(
//src.contract_disease(new/datum/ailment/disability/cough, 1, 0) // cogwerks ailment project - lung damage from fire
//Temporary fixes to the alerts.
// why am i repeating this shit?
// hardcoded honkytonk nonsense
// a cold place -> add in cold protection
// a hot place -> add in heat protection
// lets give them a fair bit of leeway so they don't just start dying
//as that may be realistic but it's no fun
// decoupled this from environmental temp - this should be more for hypothermia/heatstroke stuff
//if (src.bodytemperature > src.base_body_temp || src.bodytemperature < src.base_body_temp)
//Account for massive pressure differences
//TODO: DEFERRED
// calculate 0-100% insulation from cold environments
// Sealed space suit? If so, consider it to be full protection
// base value
// Resistance from Bio Effects
// Resistance from Clothing
// Resistance from covered body parts
// calculate 0-100% insulation from cold environments
// base value
// Resistance from Bio Effects
// Resistance from Clothing
// Resistance from covered body parts
// var/datum/reagent/blood/blood = null
// blood = reagents.get_reagent("blood")
//TODO: DEFERRED
// hopefully this won't cause too much lag?
// I dunno if this'll do what I want but hopefully it will
// if we're dead or immortal or have otherwise been told not to bleed, don't bother
// also stop bleeding if we happen to be doing that
// if we're full or empty, don't bother v
// maybe get a little blood back ^
// blood does clot and all, but we want bleeding to maybe not stop entirely on its own TOO easily
// higher bleeding gets a better chance to drop down
// but there's only so much clotting can do when all your blood is falling out at once
// still don't want this above 10
// up to 50% chance to make a big bloodsplatter
// this proc creates a bloodsplatter on src's tile
// it takes care of removing blood, and transferring reagents, color and ling status to the blood
// see blood_system.dm for the proc
// if you have no blood you're gunna be in shock
// is this even where this should go??? ?????? haine gud codr
// look okay it's close enough to an organ and there's no other place for it right now shut up
/*var/obj/item/organ/brain/myBrain = locate(/obj/item/organ/brain) in src
if (myBrain)
src.brain = myBrain
else*/
/*var/obj/item/organ/heart/myHeart = locate(/obj/item/organ/heart) in src
if (myHeart)
src.heart = myHeart
else */
// lungs are skipped until they can be removed/whatever
// we have no left eye, but we also don't have the blind overlay (presumably)
// we have no right eye, but we also don't have the blind overlay (presumably)
// I don't think the revenant needs any of this crap - Marq
//You also don't need to do a whole lot of this if the dude's dead.
//maximum modifiers.
//Modify stamina.
// changed this from dexP // cogwerks
// we're out of crit, let our implant alert people again
// we're no longer dead, let our implant alert people again
//parent.setLastTask("status_updates max value calcs", src)
//if (src.brain_op_stage == 4.0) // handled above in handle_organs() now
//death()
//-200) a shitty test here // let's lower the weight of oxy
// braindeath
/////////////////////////////////////////////
//// cogwerks - critical health rewrite /////
/////////////////////////////////////////////
//// goal: make crit a medical emergency ////
//// instead of game over black screen time /
/////////////////////////////////////////////
/*if (src.reagents)
if (!src.reagents.has_reagent("inaprovaline"))
src.take_oxygen_deprivation(1)*/
//boutput(world, "\b LOG: ADDED FLATLINE TO [src].")
//boutput(world, "\b LOG: ADDED HEART FAILURE TO [src].")
// if they were ok before dropping below zero health, call lastgasp() before setting them unconscious
//src.paralysis = max(src.paralysis, 5)
// losebreath can handle this part
/*if (src.reagents)
if (!src.reagents.has_reagent("inaprovaline"))
src.take_oxygen_deprivation(1)*/
/*if (src.reagents)
if (!src.reagents.has_reagent("inaprovaline")) src.take_oxygen_deprivation(1)*/
// shock added back to crit because it wasn't working as a bloodloss-only thing
//boutput(world, "\b LOG: ADDED SHOCK TO [src].")
//boutput(world, "\b LOG: ADDED HEART FAILURE TO [src].")
/*if (src.reagents)
if (!src.reagents.has_reagent("inaprovaline") && prob(50))
src.take_oxygen_deprivation(1)*/
//boutput(world, "\b LOG: ADDED SHOCK TO [src].")
//A ghost costume without eyeholes is a bad idea.
//blinking won't save you now, buddy
// Temporary blindness.
// drsingh :wtc: why was there a runtime error about comparing "" to 50 here? varedit or something?
// welp thisll fix it
// Temporary deafness.
//hasn't got a leg to stand on... haaa
//Alive.
//Stunned etc.
// calling lastgasp() here because we just got knocked out
// for (var/mob/V in viewers(7,src))
// boutput(V, "<span style=\"color:red\">[name] begins to recover.</span>")
//Not stunned.
//Dead.
// Update clothing - Taken out of Life() to reduce icon overhead
////Mutrace and normal sight
////Dead sight
//They might be in a closet or something idk
////Ship sight
////Glasses
//src.sight |= SEE_MOBS
// Predators kinda need proper thermal vision, I've found in playtesting (Convair880).
////Reagents
//hud.update_indicators()
// red tint
// green tint
// darken a little
// darken
//G.updateIcons()
//G.updateIcons()
//G.updateIcons()
//ov1
//ov1
// animate it so that it doesnt "jump" as much
//(istype(src.wear_mask, /obj/item/clothing/mask/gas/voice))
//boutput(src, "<span style=\"color:red\">You are too exhausted to speak.</span>")
/*/mob/living/carbon/human/say_understands(var/other)
if (src.mutantrace)
return src.mutantrace.say_understands(other)
if (istype(other, /mob/living/silicon/ai))
return 1
if (istype(other, /mob/living/silicon/robot))
return 1
if (istype(other, /mob/living/silicon/hivebot))
return 1
if (istype(other, /mob/living/silicon/hive_mainframe))
return 1
if (ishuman(other) && (!other:mutantrace || !other:mutantrace.exclusive_language))
return 1*/
//Lallander was here
// Special message handling
//boutput(src, "<span style=\"color:red\">You are too exhausted to speak.</span>")
// Mute disability
// understood us
// didn't understand us
//(istype(src.wear_mask, /obj/item/clothing/mask/gas/voice))
//(istype(src:wear_mask, /obj/item/clothing/mask/gas/voice))
// slot_w_radio = 17
//warning: icky code
// It's not pretty, but the mutantrace check will do for the time being (Convair880).
//DEBUG("[src] can't wear [I].")
//DEBUG("[src] can't wear [I].")
//DEBUG("[src] can't wear [I].")
//DEBUG("[src] can't wear [I].")
//DEBUG("[src] can't wear [I].")
// this slot is stupid
// this slot is also stupid
//spam prevention
//del(I)
// Vampires were missing here. They're immune to old-style diseases too (Convair880).
// begin the fun arcflash
// cogwerks - here are the big fuckin murderflashes
//Magnet healing!
// Added this here (Convair880).
// Fallback if type is chained by default. Don't think we can check without spawning a pair first.
// Light cyborg legs don't count.
//This is a bit hacky.
//This is a bit hacky.
//Gotta be two standard borg arms
//This is a bit hacky.
//This is a bit hacky.
//if (wear_mask && (wear_mask.c_flags & SPACEWEAR))
//space_suit++
// maybe people will stop gibbing out their stamina bars now :|
/* commenting this out and making it an overlay to fix issues with colors stacking
W.icon = 'icons/mob/human_hair.dmi'
W.icon_state = cust_one_state
W.color = src.bioHolder.mobAppearance.customization_first_color
W.wear_image_icon = 'icons/mob/human_hair.dmi'
W.wear_image = image(W.wear_image_icon, W.icon_state)
W.wear_image.color = src.bioHolder.mobAppearance.customization_first_color*/
//not exactly elegant, but fuck it, src.vars[limb].remove() didn't want to work :effort:
//not exactly elegant, but fuck it, src.vars[limb].sever() didn't want to work :effort:
//Wire: fix for null.r_arm and null.l_arm
// I'm so sorry I couldent kill all this shitcode at once
// Why not, I guess?
//Clean up the old mutantrace
//Set a new mutantrace only if passed one
//If the mutantrace was changed do all the usual icon updates
// uh?
// there's bits and bobs that are created/destroyed that check prefs to see how they should look
// same with grabs
// same for the other hand
// saaaaame with sims motives
//src.move_delay = world.time + 10
//src.move_delay = world.time + 10
//src.move_delay += mob.movement_delay() REIMPLEMENT THIS !!!!!!!!!!!!
//Should be 16 right now. Just in case we go 64x64 or some shit.
//So we dont stand on the dense wall but rather in front of it.
//Works
//Based on center of chest
//Based on center of chest
// If the person is inside an object .
//boutput(world, "exit fail")
//boutput(world, "enter fail")
// just so they don't swap with help intent users
//Life(datum/controller/process/mobs/parent)
//..(parent)
//return
// Logs.
//For deadchat
//I do not know where the hell you get a bioholder from =I
//No weldergibs. Krampus is truly a fiend.
// carbon-based lifeforms
//var/brain_op_stage = 0.0
//var/heart_op_stage = 0.0
//PLEASE ONLY EVER USE THESE TO MODIFY STAMINA. NEVER SET IT DIRECTLY.
//Returns current stamina
//Adds a stamina max modifier with the given key. This uses unique keys to allow for "categories" of max modifiers - so you can only have one food buff etc.
//If you get a buff of a category you already have, nothing will happen.
//Removes a stamina max modifier with the given key.
//Returns the total modifier for stamina max
//Adds a stamina regen modifier with the given key. This uses unique keys to allow for "categories" of regen modifiers - so you can only have one food buff etc.
//If you get a buff of a category you already have, nothing will happen.
//Removes a stamina regen modifier with the given key.
//Returns the total modifier for stamina regen
//Restores stamina
//Stamina regenerates 20% slower for you. RIP
//Removes stamina
//Chances are this will happen during combat
//Detach the cause (hit, reduced stamina) from the consequence (disconnect)
//Sets stamina
//PLEASE ONLY EVER USE THESE TO MODIFY STAMINA. NEVER SET IT DIRECTLY.
//STAMINA UTILITY PROCS
//Responsible for executing critical hits to stamina
//playsound(src.loc, "sound/misc/critpunch.ogg", 50, 1, -1)
//Just in case.
//Checks if mob should be stunned for being at or below 0 stamina and then does so.
//This is in a proc so we can easily instantly apply the stun from other areas of the game.
//For example: You'd put this on a weapon after it removes stamina to make sure the stun applies
//instantly and not on the next life tick.
//STAMINA UTILITY PROCS
// Flag the urine stain if the pisser is trying to make fake initropidril
// check for being in sight of a working security camera
// determine the name of the perp (goes by ID if wearing one)
// find the matching security record
// now add to rap sheet
// making this spawn a new proc since lastgasps seem to be related to the mob loop hangs. this way the loop can keep rolling in the event of a problem here. -drsingh
// break if it's an npc or a disconnected player
// grab the text from the input bar
// check if the player is trying to say something
// clear the player's input bar to register death / unconsciousness
// pick a grunt to append
// say the thing they were typing and grunt
// cogwerks - fix for soulguard and revive
// instant death, we can assume a brain this damaged is no longer able to support life
// what the critter is currently doing
// what behavior the critter will fall back on
// evaluate the current environment and assign priority to switching to this task
// do not override procs below this line
// --------------------------------------------
// unless you are building a new direct subtype
// the icon state of the hand UI background
// the icon state of the hand UI background
// designation of the hand - purely for show
// the icon of the hand UI background
// the icon state of the hand UI background
// name for the dummy holder
// if not null, the special limb to use when attack_handing
// designation of the hand - purely for show
// the icon of the hand UI background
// the icon state of the hand UI background
// name for the dummy holder
// if not null, the special limb to use when attack_handing
// alchemy - mars = iron
// the icon state of the hand UI background
// the icon state of the hand UI background
// Used to ease setup. Setting this in-game has no effect.
// ID of the active hand
// if (ispath(default_task))
// default_task = new default_task
// if (ispath(current_task))
// current_task = new current_task
// add_health_holder(/datum/healthHolder/flesh)
// etc..
// begin convenience procs
// end convenience procs
// The throw code is a direct copy-paste from humans
// pending better solution.
// let it know it's been dropped
//actually throw it!
// Added log_reagents() call for drinking glasses. Also the location (Convair880).
//they're in space, move em one space in the opposite direction
//overlays -= equipment_image
// non-special limb attack
// if (!client && istype(current_task))
//ov1
//ov1
// Logs.
// contingency
// Do not deploy on space.
//var/preferred = 0
/*if (adj_blob.type == /obj/blob/wall)
preferred = 1
else
preferred = 0*/
// cheat, to compensate for the loop's tick rate
/**
* at 2175 blobs, blob points max will reach about 350. It will begin decreasing sharply after that
* This is a size penalty. Basically if the blob gets too damn big, the crew has some chance of
* fighting it back because it will run out of points.
*/
//src.client.screen -= src.item_abilities
//B.button.screen_loc = "SOUTH,[pos_x]:9"
// t = number of tiles occupied by the blob
// Oh dear, you seem to be too fucking big. Whoopsie daisies...
// Marq update: gonna flatline this at 40 so big blobs aren't completely useless
// The idea is not that we should be punishing big blobs, rather we should be making progress progressively difficult.
//Click(location,control,params)
//WIRE TOOLTIPS
//Sort of like a holder mob for brain-triggered assemblies
// Jewel's attempted fix for: null.ScanText()
//boutput(world, "DEBUG: Prefix is \"[prefix]\", message mode is: \"[message_mode]\", message is \"[message]\"")
//This will make sure the surroundings can hear what the brain thing has to say
//if a ghooooost (dead) (and online)
//only listening locally (or a wraith)? w/e man dont bold dat
//you're not just listening locally and the message is nearby? sweet! bold that sucka brosef
//awwwww yeeeeeah lookat dat bold
// No log entries for unaffected mobs (Convair880).
// todo: This should probably be selectable. Cyborg style - help/harm.
//if (src.owner.client)
// src.owner.client.mob = src
// was [src] but: "the living space thing comes alive!"
// what the heck else would this be?
//This shouldnt ever happen.
//To reflect updates of the items appearance etc caused by interactions.
//src.pixel_x = src.item.pixel_x
//src.pixel_y = src.item.pixel_y
// Double clicking turfs to move to nearest camera
//try to find the closest working camera in the same area, switch to it
//lol @ dumping you at the mining magnet every fucking time. (or interrupting a track, wow rude)
//infinity
// different network (syndicate)
// different viewing plane
// ignore disabled cameras
//usr:cameraFollow = null
//sort alphabetically if user so chooses
/* lol bubblesort FU
for(var/i = 1; i <= creatures.len; i++)
for(var/j = i+1; j <= creatures.len; j++)
if(sorttext(creatures[i], creatures[j]) == -1)
creatures.Swap(i, j)
*/
//redisplay sorted list
//usr:cameraFollow = null
//Fucka you
//Called without start / end parameters
//Okay, sort on c_tag_order then c_tag
//src.cameraFollow = null
//When did we do the last tracking attempt?
//How long should we wait between attempts?
//How long between refreshes if we succeeded in tracking someone?
// Same but in case we failed
//Process now!!!
//We don't have a premature failure
//Assume failure
//The goodest camera
//Hey it went real fast this time! Bet it's a syndie
//Allow tracking of cyborgs, however
//Track autofails if:
//Target is wearing a syndicate ID
//Target is inside a dummy
//Target is not at a turf
//CONTENTS:
//Mobile (On rails) AI
//The rails themselves (In here for now)
//The AI's rail drone (Also in here for now)
//So we don't get brohugged right off a rail.
//src:cameraFollow = null
//var/stage = 0
//stage = 1
//stage = 2
//stage = 3
//stage = 4
//stage = 5
//The AI's movement rails
//Valid direction bitflags
//The Drone. Think of GERTY's various arms and what not. WIP.
//How does this even happen?
/* deprecated, see _macros.dm - drsingh
/proc/isdrone(var/mob/M)
if (istype(M, /mob/living/silicon/hivebot/drone))
return 1
return 0
*/
//How important it is to us to stay in the same general area
// the smaller this is, the more a straight line will be preferred over a closer camera when changing cameras
// if you set this to 0 the game will crash. don't do that.
// if you set it to be negative the algorithm will do completely nonsensical things (like choosing the camera that's
// the farthest away). don't do that.
//If there is an existing link to this camera
//make sure it's the right direction
// ignore disabled cameras
//how many levels deep the old camera and the closest camera's areas share
//for instance, /area/A and /area/B would have shared_types = 2 (because of how dd_text2list works)
//whereas area/A/B and /area/A/C would have it as 3
//don't let it be too far from the current one in the axis perpindicular to the direction of travel,
//but let it be farther from that if it's in the same area
//something in the same hallway but farther away beats something in the same hallway
//weight things in the same area as this so they count as being closer - makes you stay in the same area
//when possible
//closer, or this is in the same area and the current closest isn't
//do
//while(closest && !closest.status) //Skip disabled cameras - THIS NEEDS TO BE BETTER (static overlay imo)
//Ok, let's do this then.
// different network (syndicate)
// if(ticker && ticker.mode && istype(ticker.mode, /datum/game_mode/malfunction)) //Is there any reason at all for this check here?
// if(current.z != user.z && (user.network != "Prison") && (user.network != "SS13"))
// continue
// else
// if(current.z != user.z && (user.network != "Prison") && (user.network != "AI Satellite"))
// continue // different viewing plane
// ignore disabled cameras
//make sure it's the right direction
//how many levels deep the old camera and the closest camera's areas share
//for instance, /area/A and /area/B would have shared_types = 2 (because of how dd_text2list works)
//whereas area/A/B and /area/A/C would have it as 3
//don't let it be too far from the current one in the axis perpindicular to the direction of travel,
//but let it be farther from that if it's in the same area
//something in the same hallway but farther away beats something in the same hallway
//weight things in the same area as this so they count as being closer - makes you stay in the same area
//when possible
//closer, or this is in the same area and the current closest isn't
//To cut off stupid rail hopping
// Can't be emagged...
// ...but we can become a rogue computer.
//Ordinary AI camera movement
//var/list/connected_shells = list()
// var/datum/ai_laws/laws_object = ticker.centralized_ai_laws
// var/datum/ai_laws/current_law_set = null
//var/list/laws = list()
//Comm over powernet stuff
//Stuff connected to us over the powernet
//is the hologram downed?
// See /mob/living/say() in living.dm for AI-related radio code.
// The antagonist proc does that too.
// ugh
// Mindslave or rogue (Convair880).
// Should be logged, really (Convair880).
// Stick the player (if one exists) in a ghost mob
//Otherwise they could return to a brainless body. And that is weird.
// Was missing (Convair880).
// Logs.
//src.cameraFollow = null
//Oh yeah, message that terminal!
//Send the actual message signal
//Might as well log what they said too!
//Foreach goto(19)
// You can enthrall silicon mobs and yes, they need special handling (Convair880).
// Shouldn't happen, but you never know.
// calling lastgasp() here because we just died
//change status
// Brought in line with carbon mobs (Convair880).
//weasellos time of death patch
// Mindslave or rogue (Convair880).
// visible targeted emotes
// basic visible single-word emotes
//flick("ai-flip", src)
//ty bubs for excellent new borgfart
//src:cameraFollow = null
// Assign antag status if we don't have any yet (Convair880).
// None of these vars are of any relevance to AI mobs (Convair880).
// Ear_deaf is handled by src.set_vision().
// Fix for permastunned AIs. Stunned and paralysis seem to be the only vars that matter in the existing code (Convair880).
//ov1
//change status
//ov1
//change status
//////////////////////////////////////////////////////////////////////////////////////////////////////
// PROCS AND VERBS ///////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////
// COMMANDS
//src:cameraFollow = null
//src:cameraFollow = null
// bluhh who the fuck knows, this at least checks that user isn't null as well
//In case an AI uses the reward, use a local list instead
//Ffff
//change status
//It's "colour", though :( "color" sounds like some kinda ass-themed He-Man villain
// drsingh new AI de-electrify thing
// CALCULATIONS
// ok, we're alive, camera is acceptable and in our network...
//Add static if the camera is disabled
//IT'S DISABLED ARGHH!
//ov1
//AI player -> Powerline comm network interfacing (wireless assumes all nodes are objects)
//No radio for us thanks
//They don't need to target us specifically to ping us.
//Otherwise, ff they aren't addressing us, ignore them
//Send a reply for those curious jerks
//something might be wrong here, disconnect them!
//?src=\ref[src];termmsg=[target]'>[target]</a>!")
//Somebody wants to talk to us, how kind!
//We don't know this jerk, ignore them!
//Nothing of value to say, so ignore them!
//?src=\ref[src];termmsg=[target]'><b>([target]):</b></a></span>"
//Post a message over our ~wired link~
//Actually do this.
// snafu
// everything's good
// battery power
// Reset this first, it's necessary.
//cameras can't follow people who haven't started yet DUH OR DIDN'T YOU KNOW THAT
//in a closet or something, AI can't see him anyways
//cloaked
//Can't track a person out of range of a functioning camera
//hud.update_health()
// Handle light datums and the like.
// Handle light datums and the like.
// wtf?
//var/param = null
//param = copytext(act, t1 + 1, length(act) + 1)
// DRONE ITEM/OBJ STUFF, TRANSFER IT ELSEWHERE LATER
// DRONE PARTS
//weak as fuk
//no bumping into people, basically
//we arent proper robots
//state tracking
//fuck whoever made this
//gimmicky things
//src.zone_sel = new(src)
//src.attach_hud(zone_sel)
//Attach shit to tools
//Make all the tools un-drop-able (to closets/tables etc)
//alive
//still alive after power usage
//Stunned etc.
// calling lastgasp() here because we just got knocked out
//This stuff is hacky but I don't feel like messing with observer New code so fuck it
//Prevents re-entering a ghostdrone corpse
//So the drone cant pick up an item and then die, sending the item ~to the void~
//flying...anything
//flying hats
//flying bedsheets
//Apparently leaving this on made the parent updatehealth set health to max_health in all cases, because there's no such thing as bruteloss and
// so on with this mob
//if we were dead, and now arent
//godmode
//u ded
//Change that faaaaace
//Save state but don't apply changes if charging or stunned
//No overlays or lumin for drones under a sheet
/*var/image/newFace = GetOverlayImage("face")
var/forceNew = 0
if (!newFace)
forceNew = 1
newFace = image(src.icon, "drone-[type]")
newFace.layer = MOB_OVERLAY_BASE
if (type != src.faceType) //Type is new
src.faceType = type
newFace.icon_state = "drone-[type]"*/
// this should never be the case but let's be careful anyway!!
//forceNew) //Color is new
//ok we're also gonna color hoverdiscs too because hell yeah kickin rad
//Set our luminosity color, if valid
// dead or no client
//yellow
/* if (stat == 2 || !src.client)
if (src.bedsheet)
src.icon_state = "g_drone-dead"
else
src.icon_state = "drone-dead"
else //Being charged or newdrone
if (!src.bedsheet) //Until we get a bedsheet charging icon
if (src.charging)
src.icon_state = "drone-charging"
else if (src.newDrone)
src.icon_state = "drone-idle"
light.set_color(0.94, 0.88, 0.12) //yellow
light.enable()
*/
//stop bumble animation
//New drone stuff
//defaults
//yayyyyy bumble anim
//damage states to go here
//A thing to stop drones interacting with pick-up-able things by default
// in theory, usr should be us, this is shit though
// temporary fix for cyborgs turning by clicking
//if (W.useInnerItem && W.contents.len > 0)
// W = pick(W.contents)
//Fuck you, magic number prickjerk
//..()
//Four very important procs follow
//removes face overlay and lumin (also sets icon)
//alive
//to re-init face overlay and lumin
//dead
//Friend person
//Shove
//Shake
//Dumbo
//Prevents drones attacking other people hahahaaaaaaa
// Handle light datums and the like.
// Handle light datums and the like.
//This basically should never happen with ghostdrones
// visible targeted emotes
// basic visible single-word emotes
//restart our passive animation
//No hearing any other talk ok
// emotes
//A new proc because it's handled very differently from normal laws
//custom laws detailing just how much the drone cannot hurt people or grief or whatever
//var/laws = "<span class='bold' style='color: blue;'>"
//laws += "Your laws:<br>"
//laws += "1. Avoid interaction with any living or silicon lifeforms where possible. except where the lifeform is also a drone.<br>"
//laws += "2. Maintain, repair and improve the station wherever possible.<br>"
//laws += "</span>"
// 0 for brute, 1 for burn
//For hats getting shot off
//get target turf
//brute only
//Items being dropped ONTO this mob
// why are you in this list
//no free drones to spare
/* var/msg = "Your laws:<br>"
msg += "<B>1. Do not interfere, harm, or interact in any way with living or previously living lifeforms.</B><br>"
msg += "<B>2. Do not willingly damage the station in any shape or form.</B><br>"
msg += "<B>3. Assist in repairs to the station and expansion plans.</B><br>"
msg += "Use \"say ; (message)\" to speak to fellow drones through the spooky power of spirits within machines."
G.show_laws_drone()
*/
//Shit all the mods have
// var/obj/item/gun/mp5/M = new /obj/item/gun/mp5(src)
///obj/item/hive_module/security/New()
// ..()
// src.modules += new /obj/item/baton/secbot(src)
// src.modules += new /obj/item/gun/energy/laser_gun(src)
// reset any blindness
//weasellos time of death patch
//HUD
//3 Modules can be activated at any one time.
//var/energy = 4000
//var/energy_max = 4000
//ew
// Haine wandered in here and just junked up this code with bees. I'm so sorry it's so ugly aaaa
// Brought in line with carbon mobs (Convair880).
// reset any blindness
//weasellos time of death patch
/*if ("shit")
new /obj/item/rods/(src.loc)
playsound(src.loc, "sound/misc/poo2_robot.ogg", 50, 1)
message = "<B>[src]</B> shits on the floor."
m_type = 1*/
// visible targeted emotes
// basic visible single-word emotes
//src.real_name = mainframe:name
// if("Combat")
// src.module = new /obj/item/hive_module/standard(src)
// if("Security")
// src.module = new /obj/item/hive_module/security(src)
// Was missing (Convair880).
// Logs.
//Foreach goto(19)
// Added ability to repair burn-damaged AI shells (Convair880).
//check if it doesn't require any access at all
//something's very wrong
//no requirements
//not ID or no access
//doesn't have this access
// if (src.beebot == 1)
// src.icon_state = "eyebot-bee"
// Handle light datums and the like.
// Handle light datums and the like.
// Handle light datums and the like.
//?src=\ref[src.radio];talk=0'>Engaged</A>" : "<A href='byond://?src=\ref[src.radio];talk=1'>Disengaged</A>"]<BR>
//?src=\ref[src.radio];listen=0'>Engaged</A>" : "<A href='byond://?src=\ref[src.radio];listen=1'>Disengaged</A>"]<BR>
//?src=\ref[src.radio];freq=-10'>-</A>
//?src=\ref[src.radio];freq=-2'>-</A>
//?src=\ref[src.radio];freq=2'>+</A>
//?src=\ref[src.radio];freq=10'>+</A><BR>
/////
//death() no why would it just explode upon running out of power that is absurd
// calling lastgasp() here because we just ran out of power
//Alive.
//Stunned etc.
// calling lastgasp() here because we just got knocked out
//Not stunned.
//Dead.
//obj/item/cell/shell_cell moved to cells.dm
//Shit all the mods have - make sure to call ..() at the top of any New() in this class of item
//src.modules += new /obj/item/patch_stack(src)
// src.modules += new /obj/item/borghose(src)
// src.modules += new /obj/item/reagent_containers/food/drinks/juicer(src)
// Pieces and parts
//3 Modules can be activated at any one time.
// For picking modules when a robot is first created
// for the medal reward
// moved up to silicon.dm
//For custom borgs. Basically just prevents appearance changes. Obviously needs more work.
// i can only imagine bad shit happening if you just try to straight spawn one like from the spawn menu or
// whatever so let's not allow that for the time being, just to make sure
//Oh no, they have no mind!
// how the hell would this happen. oh well
//Status updates, death etc.
//still using power
//ov1
// overlays
// Brought in line with carbon mobs (Convair880).
// Only called for instakill critters and the like, I believe (Convair880).
// Mindslave or rogue (Convair880).
// visible targeted emotes
// basic visible single-word emotes
// for creepy automatoning
//ty bubs for excellent new borgfart
/* //what the fuck is this
if (istype(src.module,/obj/item/robot_module/standard)) boutput(usr, "[src.name] has a Standard module installed.")
else if (istype(src.module,/obj/item/robot_module/medical)) boutput(usr, "[src.name] has a Medical module installed.")
else if (istype(src.module,/obj/item/robot_module/engineering)) boutput(usr, "[src.name] has an Engineering module installed.")
else if (istype(src.module,/obj/item/robot_module/janitor)) boutput(usr, "[src.name] has a Janitor module installed.")
else if (istype(src.module,/obj/item/robot_module/brobot)) boutput(usr, "[src.name] has a Bro Bot module installed.")
else if (istype(src.module,/obj/item/robot_module/hydro)) boutput(usr, "[src.name] has a Hydroponics module installed.")
else if (istype(src.module,/obj/item/robot_module/construction)) boutput(usr, "[src.name] has a Construction module installed.")
else if (istype(src.module,/obj/item/robot_module/mining)) boutput(usr, "[src.name] has a Mining module installed.")
else if (istype(src.module,/obj/item/robot_module/chemistry)) boutput(usr, "[src.name] has a Chemistry module installed.")
else boutput(usr, "[src.name] has an unknown module installed.")
*/
// maybe the blob is a little acidic?? idk
// Logs.
// 0 for brute, 1 for burn
// trying to unlock with an emag card
//..()
// crowbar means open or close the cover
// trying to put a cell inside
// module changing
//for (var/obj/item/roboupgrade/R in src.contents)
//(istype(W, R))
// module changing
// haxing
// trying to unlock the interface with an ID card
// The antagonist proc does that too.
//Wire: Fix for borgs removing their entire bodies after death
/*else if (istype(W,/obj/item/reagent_containers/glass/))
var/obj/item/reagent_containers/glass/G = W
if (src.a_intent == "help" && user.a_intent == "help")
if(istype(src.module_active,/obj/item/reagent_containers/glass/))
var/obj/item/reagent_containers/glass/CG = src.module_active
if(G.reagents.total_volume < 1)
boutput(user, "<span style=\"color:red\">Your [G.name] is empty!</span>")
boutput(src, "<B>[user.name]</B> waves an empty [G.name] at you.")
return
if(CG.reagents.total_volume >= CG.reagents.maximum_volume)
boutput(user, "<span style=\"color:red\">[src.name]'s [CG.name] is already full!</span>")
boutput(src, "<span style=\"color:red\"><B>[user.name]</B> offers you [G.name], but your [CG.name] is already full.</span>")
return
G.reagents.trans_to(CG, G.amount_per_transfer_from_this)
src.visible_message("<b>[user.name]</b> pours some of the [G.name] into [src.name]'s [CG.name].")
return
else ..()
else ..()*/
//Wire: Fix for multiple players queuing up brain removals, triggering this again
// Mindslave or rogue (Convair880).
// Should be logged, really (Convair880).
// Stick the player (if one exists) in a ghost mob
//Otherwise they could return to a brainless body. And that is weird.
//src.hands.icon_state = "empty"
// Renders them mute and helpless (Convair880).
//We're just bapping the borg
//Friend person
//Shove
//Shake
//Dumbo
// Handle light datums and the like.
// 4 will deselect the module
// clicking the already on slot, so deselect basically
// ugh
/////
// Previously, AIs could and did chose to deploy to emagged suits
// to get get around their shackles. That's obviously not ideal (Convair880).
// You can enthrall silicon mobs and yes, they need special handling.
// Also, enthralled AIs should still see their master's name when in a robot suit (Convair880).
// We're done here. Emagged whatever doesn't matter.
//This is the last place the inaction clause is permitted to exist, ok.
// ticker.centralized_ai_laws.laws_sanity_check()
//////////////////////////
// Robot-specific Procs //
//////////////////////////
// Handle light datums and the like.
// Blame the teleport upgrade.
//?src=\ref[src.radio];talk=0'>Engaged</A>" : "<A href='byond://?src=\ref[src.radio];talk=1'>Disengaged</A>"]<BR>
//?src=\ref[src.radio];listen=0'>Engaged</A>" : "<A href='byond://?src=\ref[src.radio];listen=1'>Disengaged</A>"]<BR>
//?src=\ref[src.radio];freq=-10'>-</A>
//?src=\ref[src.radio];freq=-2'>-</A>
//?src=\ref[src.radio];freq=2'>+</A>
//?src=\ref[src.radio];freq=10'>+</A><BR>
//emagged = 1
//var/list/starter_modules = list("Standard", "Engineering", "Medical", "Brobot")
// check if we've got stuff equipped in each slot and consume power if we do
// consume 1 power per tick unless we've got the efficiency upgrade
//Alive.
// AI-controlled cyborgs always use the global lawset, so none of this applies to them (Convair880).
//Stunned etc.
// calling lastgasp() here because we just got knocked out
//Dead.
// It's a cyborg. Logically, they shouldn't have to worry about the maladies of human organs.
//src.density = !( src.lying )
// this doesn't even make any sense unless you're rayman or some shit
// Mindslave or rogue (Convair880).
// Brought in line with carbon mobs (Convair880).
// no head means no brain!!
// Mindslave or rogue (Convair880).
// Ditto (Convair880).
// Dead or x-ray vision.
//They might be in a closet or something idk
// Use vehicle sensors if we're in a pod.
//var/sight_therm = 0 //todo fix this
//if (R && istype(R, /obj/item/roboupgrade/opticthermal) && R.activated)
// sight_therm = 1
//if (sight_therm)
// src.sight |= SEE_MOBS //todo make borg thermals have a purpose again
//else
// src.sight &= ~SEE_MOBS
//ov1
//ov1
// shells are available for use, dependent borgs are already in use by an AI. do not kill empty shells!!
//If C updates legs mods AND there's at least one leg AND there's not a right leg or the right leg slot is not both AND there's not a left leg or the left leg slot is not both
//under_image.layer = MOB_CLOTHING_LAYER
//MOB_CLOTHING_LAYER
// return the most significant damage to the vital bits
// return the most significant damage to the vital bits
///////////////////////////////////////////////////
// Specific instances of robots can go down here //
///////////////////////////////////////////////////
//new /obj/item/roboupgrade/opticthermal(src)
//Fred the vegasbot
// if (controller)
// controller.leave_shell()
// trying to select the same tool deselects
// Do we get Syndicate laws?
// Can we become a Syndie robot?
// Are we emagged, removing all laws?
// Can we be emagged?
//An ID card that the robot "holds" invisibly
// where to go back to when we die, if we have one, for hivebots/robots
// if we're host to a mainframe's mind
// are we available for use as a shell for an AI
// Moves this down from ai.dm so AI shells and AI-controlled cyborgs can use it too.
// Also made it a little more functional and less buggy (Convair880).
// Sort alphabetically if so desired.
// Find us some doors.
// Don't remove the #[number] part here.
// Attempt to open said doors.
// Somebody will find a way to abuse it if I don't put this here.
// Let's be a bit lenient.
// Let's be a bit lenient.
// we have no hands doofus
// slightly hacky, oh well
// temporary fix for cyborgs turning by clicking
// how would a borg/ai have a gun? I dunno but I'm not risking it
// wtf?
// making this spawn a new proc since lastgasps seem to be related to the mob loop hangs. this way the loop can keep rolling in the event of a problem here. -drsingh
// break if it's an npc or a disconnected player
// grab the text from the input bar
// check if the player is trying to say something
// clear the player's input bar to register death / unconsciousness
// pick a grunt to append
// say the thing they were typing and grunt
//check if it doesn't require any access at all
//if they are holding or wearing a card that has access, that works
//something's very wrong
//no requirements
//not ID or no access
//doesn't have this access
// somehow
// This proc adds and removes robot-related antagonist roles as needed (Convair880).
// No AI-controlled shells.
// Synthetic thralls are a thing, somehow.
// So borged traitors etc don't lose their antagonist status.
// Shouldn't happen, but you never know.
// Preserve existing antag role (if any).
// Syndie laws don't matter if we're emagged.
// Preserve existing antag role (if any).
// Syndicate robots can see traitors.
// Rogue AIs get special laws.
// Mundane objectives probably don't make for an interesting antagonist.
// These laws can't be reset by players. It's a fully-fledged rogue computer after all.
// Don't wanna add the same law twice. It could happen.
// Remove Syndicate cyborgs from the robotics terminal.
// living
// this is a read only variable. do not set it directly.
// use set_burning or update_burning instead.
// the value means how on fire is the mob, from 0 to 100
//AI Vars
//Will it attack itself?
// sigh
// for silicon mobs
// for silicon mobs
// for silicon mobs
// if they're stored in the cryotron, Life() gets skipped
//Active if XMAS or manually toggled
// in theory, usr should be us, this is shit though
//Fuck you, magic number prickjerk
// dont want to check for a cloaker every click if we're not invisible
// oh god
// okay, this is only ACTUALLY used for power gloves, I'm disabling the rest for now because heavy hasvar usage is causing lag
/*if(hasvar(src, "back") && src:back) src:back:equipment_click(target, src)
if(hasvar(src, "belt") && src:belt) src:belt:equipment_click(target, src)
if(src.ears) src.ears.equipment_click(target, src)
if(hasvar(src, "glasses") && src:glasses) src:glasses:equipment_click(target, src)*/
/*if(hasvar(src, "head") && src:head) src:head:equipment_click(target, src)
if(src.l_hand) src.l_hand.equipment_click(target, src)
if(hasvar(src, "l_store") && src:l_store) src:l_store:equipment_click(target, src)
if(src.r_hand) src.r_hand.equipment_click(target, src)
if(hasvar(src, "r_store") && src:r_store) src:r_store:equipment_click(target, src)
if(hasvar(src, "shoes") && src:shoes) src:shoes:equipment_click(target, src)
if(hasvar(src, "wear_id") && src:wear_id) src:wear_id:equipment_click(target, src)
if(src.wear_mask) src.wear_mask.equipment_click(target, src)
if(hasvar(src, "wear_suit") && src:wear_suit) src:wear_suit:equipment_click(target, src)
if(hasvar(src, "w_uniform") && src:w_uniform) src:w_uniform:equipment_click(target, src)*/
//src.set_cursor(null)
// required to make sure its deleted
// set burning to a value
// change burning, for example update_burning(-10) in a fire fighting item
// doesn't matter if you tell it to go past 0-100. the proc will deal with it.
// cache the original value
// mob/living update_burning sets the burning var and clamps the value
// set the upper and lower bounds of the change based on the direction
// figure out if we crossed an icon threshold
// Jewel's attempted fix for: null.ScanText()
// no dead emote spam
// wtf?
// emotes
// Mute disability
// Insert space check here
// var/turf/T = get_turf(src)
// If human
// If theres no oxygen
// Perfluorodecalin cap - normal life() depletion - buffer.
// For any radios or intercoms that happen to be in range.
// Special message handling
/*else if (copytext(message, 1, 3) == ":w")
message_mode = "whisper"
message = copytext(message, 3)*/
// AI radios. See further down in this proc (Convair880).
// One vs. two letter prefix.
// this is shit
// :downs:
//Blobchat handling
//Might put this back if people are used to the old system.
/*if ("whisper")
message_range = 1
italics = 1*/
// Added shortcuts for the AI mainframe radios. All the relevant vars are already defined here, and
// I didn't want to have to reinvent the wheel in silicon.dm (Convair880).
// AI-controlled robot.
// Mainframe may be stunned when the shell isn't.
// First AI intercom broadcasts everything by default.
//DEBUG("AI radio #1 triggered. Message: [message]")
//DEBUG("AI radio #2 triggered. Message: [message]")
//DEBUG("AI radio #3 triggered. Message: [message]")
// understood us
// didn't understand us
//Hello welcome to the world's most awful if
//if a ghooooost (dead) (and online)
//only listening locally (or a wraith)? w/e man dont bold dat
//you're not just listening locally and the message is nearby? sweet! bold that sucka brosef
//awwwww yeeeeeah lookat dat bold
// helper proooocs
// say filters
// totally garbled drunk slurring
// berserker proc thing
// genetically falling apart!
///!!!
///!!!
///!!!
///!!!
//{WC} ?
//{WC} ?
//src, "static", ICON_OVERLAY)
// Contains:
// - Help procs
// - Grab procs
// - Disarm procs
// - Harm procs
// - Helper procs:
// -- attackResult datum [This is where the magic happens.]
// -- Targeting checks
// -- Calculate damage
// -- Target damage modifiers
// -- After attack
///////////////////////////////////////////////// Help intent //////////////////////////////////////////////
// if they've got SOMETHING to do let's not just harass them for trying to do CPR on themselves
// Just put 'em on the mob itself, like pulling does. Simplifies forensic analysis a bit (Convair880).
// :I
/*if(prob(50)) // this doesn't work yet
for(var/datum/ailment/disability/D in src.target.ailments)
if(istype(D,/datum/ailment/disease/heartfailure))
src.target.resistances += D.type
src.target.ailments -= D
boutput(world, "<span style=\"color:red\">CURED [D] in [src.target]</span>")
if(istype(D,/datum/ailment/disease/flatline))
src.target.resistances += D.type
src.target.ailments -= D
boutput(world, "<span style=\"color:red\">CURED [D] in [src.target]</span>")*/
///////////////////////////////////////////// Grab intent //////////////////////////////////////////////////////////
// Just put 'em on the mob itself, like pulling does. Simplifies forensic analysis a bit (Convair880).
// Melee-focused roles (resp. their limb datums) grab the target aggressively (Convair880).
///////////////////////////////////////////////////// Disarm intent ////////////////////////////////////////////////
// I needed a harm intent-like attack datum for some limbs (Convair880).
/////////////////////////////////////////////////// Harm intent ////////////////////////////////////////////////////////
// Some as the other 'empty hand' melee attacks (Convair880).
// Was missing (Convair880).
// Calls melee_attack_normal if limb datum doesn't override anything.
// This is used by certain limb datums (werewolf, shambling abomination) (Convair880).
// 1: a little bit | 2: across the room
/////////////////////////////////////////////////////// attackResult datum ////////////////////////////////////////
// the message to play to the target
// a sound to play when this attack is flushed
// Is this a disarm as opposed to harm attack?
// Blocked, shoved down etc.
// I worked disarm into this because I needed a more detailed disarm proc and didn't want to reinvent the wheel or repeat a bunch of code (Convair880).
// important
//We were just knocked out.
////////////////////////////////////////////////////////// Targeting checks ////////////////////////////////////
////////////////////////////////////////////////////// Calculate damage //////////////////////////////////////////
/////////////////////////////////////////////////////// Target damage modifiers //////////////////////////////////
/////////////////////////////////////////////////////////// After attack ////////////////////////////////////////////
// don't get pushed around
// How could this even happen? Regardless, no log entries for unaffected mobs (Convair880).
// moved the below to /client/New() so mentor-related preference loading works properly
/*if ((NT.Find(ckey(mind.key)) || mentors.Find(ckey(mind.key))) && !admins.Find(ckey(mind.key)))
client.mentor = 1
client.mentor_authed = 1*/
//They have already been alive this round!!
//Null if the client changed to another mob, but not null if they disconnected.
// drsingh i put the extra ifs here. i think its dumb but there's a bad client error here so maybe it's somehow going away in winset because byond is shitty
//?src=\ref[src];show_preferences=1'>Setup Character</A><BR><BR>"
//?src=\ref[src];ready=1'>Declare Ready</A><BR>"
//?src=\ref[src];late_join=1'>Join Game!</A><BR>"
//?src=\ref[src];observe=1'>Observe</A><BR>"
// are they an admin and in stealth mode/have a fake key?
// are we an admin?
// give us the full deets
// are we not an admin?
// only show the fake key
// are they a normal player or not in stealth mode/using a fake key?
// show them normally
//for (var/mob/living/silicon/ai/A in mobs)
// miscreants are causing issue in the rp setting atm
//ticker.implant_skull_key() // This also checks if a key has been implanted already or not. If not then it'll implant a random sucker with a key.
// This fxn creates positions for assistants based on existing positions. This could be more elgant.
//?src=\ref[src];SelectedJob=\ref[J]'><font color=[J.linkcolor]>[J.name]</font></a><br>"}
//?src=\ref[src];SelectedJob=\ref[J]'><font color=[J.linkcolor]>[J.name]</font></a><br>"}
//?src=\ref[src];SelectedJob=\ref[J]'><font color=[J.linkcolor]>[J.name]</font></a><br>"}
//?src=\ref[src];SelectedJob=\ref[J]'><font color=[J.linkcolor]>[J.name]</font></a><br>"}
//?src=\ref[src];SelectedJob=\ref[J]'><font color=[J.linkcolor]>[J.name]</font></a><br>"}
//?src=\ref[src];SelectedJob=\ref[J]'><font color=[J.linkcolor]>[J.name]</font></a><br>"}
//?src=\ref[src];SelectedJob=\ref[J]'><font color=[J.linkcolor]>[J.name]</font></a><br>"}
//?src=\ref[src];SelectedJob=\ref[J]'><font color=[J.linkcolor]>[J.name]</font></a><br>"}
//?src=\ref[src];SelectedJob=\ref[J]'><font color=[J.linkcolor]>[J.name]</font></a><br>"}
// fallback
// no new evils for the first 10 minutes or last 5 before shuttle
// if a traitor
// if a silicon mob, dead or logged out, skip
//Messages admins if this new character attacks someone within 2 minutes of signing up. Might help detect grief, who knows?
// do not return 0 in here for the love of god, let me tell you the tale of why:
// the default mob/Login (which got called before we actually set our loc onto the start screen), will attempt to put the mob at (1, 1, 1) if the loc is null
// however, the documentation actually says "near" (1, 1, 1), and will count Move returning 0 as that it cannot be placed there
// by "near" it means anywhere on the goddamn map where Move will return 1, this meant that anyone logging in would cause the server to
// grind itself to a slow death in a caciphony of endless Move calls
// Fallback if role is unrecognized.
//closes late choices window
//closes the player setup window
//If the player has any antag tokens available, check if they want to redeem one.
//If the player has any antag tokens available, check if they want to redeem one.
//Wire: fix for Cannot read null.be_random_name (preferences &&)
// fix for "Cannot modify null.suicide"
//i'll just chuck this one in here i guess
//can't stare into the cluwne mask's eyes while wearing it...
//instead of killing them instantly, just put them at -175 health and let 'em gasp for a while
//in case they get revived by cryo chamber or something stupid like that, let them suicide again in 20 seconds
//prevent a suicide if the person is infected with the headspider disease.
//Get owned, nerd!
// if they cancelled the prompt
/* will fix this later
else if (method == "extinguisher")
viewers(src) << "<span style=\"color:red\"><b>[src] puts the nozzle of the extinguisher into \his mouth and squeezes the handle.</b></span>"
var/succeeds = 0
for(var/obj/item/extinguisher/E in src.l_hand)
if(E.safety == 0 && E.reagents && E.reagents.total_volume >= 5)
succeeds = 1
E.reagents.remove_any(5)
if(!succeeds)
for(var/obj/item/extinguisher/E in src.r_hand)
if(E.safety == 0 && E.reagents && E.reagents.total_volume >= 5)
succeeds = 1
E.reagents.remove_any(5)
if(succeeds) src.gib()
else
viewers(src) << "<span style=\"color:red\"><b>Nothing happens!</b></span>"
spawn(50)
suiciding = 0*/
//put em at -175
//src.death_timer = 15 // this shit ain't really workin so bandaid fix for now
//src.updatehealth()
// Added an option to send them to the arrival shuttle. Also runtime checks (Convair880).
// They could be in a pod or whatever, which would have unfortunate results when respawned.
// Randomize_look() seems to cause runtimes when called before organs are initialized.
// Same as wraith/blob creation proc. Trying to narrow down a bug which
// inexplicably (and without runtimes) caused another proc to fail, and
// might as well give this a try. I suppose somebody else ran into the same problem?
// NPC fallback, mostly.
// C&P from respawn_target(), which couldn't be adapted easily.
//otherwise the HUD remains in the login screen
// O.laws_object = new /datum/ai_laws/asimov
// O.laws_object = ticker.centralized_ai_laws
// O.current_law_set = O.laws_object
// See file code/game/verbs/ai_lockdown.dm for next two
//O.verbs += /mob/living/silicon/ai/proc/lockdown
//O.verbs += /mob/living/silicon/ai/proc/disablelockdown
//O.verbs += /mob/living/silicon/ai/proc/ai_toggle_arrival_alerts
//O.verbs += /mob/living/silicon/ai/proc/ai_custom_arrival_alert
// O.verbs += /mob/living/silicon/ai/proc/hologramize
// O.verbs += /mob/living/silicon/ai/proc/ai_cancel_call
// This is handled in the New() proc of the resulting borg
//O.cell = new(O)
//O.cell.maxcharge = 7500
//if(limit_cell) O.cell.charge = 1500
//else O.cell.charge = 7500
//So the icon actually appears
//human -> alien
// var/atom/movable/overlay/animation = new /atom/movable/overlay( src.loc )
// animation.icon_state = "blank"
// animation.icon = 'icons/mob/mob.dmi'
// animation.master = src
// flick("h2alien", animation)
// sleep(48)
// qdel(animation)
//human -> alien queen
// var/atom/movable/overlay/animation = new /atom/movable/overlay( src.loc )
// animation.icon_state = "blank"
// animation.icon = 'icons/mob/mob.dmi'
// animation.master = src
// flick("h2alien", animation)
// sleep(48)
// qdel(animation)
//human -> hivebot
// Don't remove.
//Admins
//The viewer is an admin, we can show them stuff
//A lowly normal person is viewing, hide!
// no you fucks don't show us as an admin anyway!!
//Mentors
//Normies
// Wraith
// Technically neither living nor dead benefits us in such a way that we should be subclassing them.
//todo: construct name from a user input (e.g. <x> the Impaler)
// = technically, we hear ghost chat.
//////////////
// Wraith Overrides
//////////////
//src.sight |= SEE_TURFS | SEE_MOBS | SEE_OBJS | SEE_SELF
// let's not make it see through walls
// No log entries for unaffected mobs (Convair880).
//Todo: some cool-ass effects here
//Back to square one with you!
// oh sweet jesus it spammed so hard
//15 seconds
//if tile contains salt, wraith becomes corporeal
//one minute
//Z level boundary stuff
//If corporeal speak to the living (garbled)
//Todo: random pick of spooky things or maybe parse the original message somehow
/*var/rendered = "<strong>[src.name]</strong> screeches incomprehensibly!"
var/list/listening = all_hearers(null, src)
listening -= src
listening += src
for (var/mob/M in listening)
M.show_message(rendered, 2)*/
//Speak in ghostchat if not corporeal
//////////////
// Wraith Procs
//////////////
// Happens in wraithPossess() already.
//src.abilityHolder.suspendAllAbilities()
// make sure we didn't get deleted on the way - should probably make a better check than this. whatever.
//////////////
// Wraith Verbs
//////////////
/*verb
makeCorporealDebug()
src.makeCorporeal()
makeIncorporealDebug()
src.makeIncorporeal()
givePointsDebug()
src.abilityHolder.points = 99999*/
//////////////
// Related procs and verbs
//////////////
// i am dumb - marq
// In relation to world time. Used for traitor/nuke ops overlays certain mobs can see.
//var/obj/screen/zone_sel/zone_sel = null
// 98.7F / 37C
// iterations between each temperature state
// how quickly the body's temperature tries to correct itself, higher = faster
// how good the body is at resisting environmental temperature
//var/underwear = "No Underwear"
//var/underwear_color = "#FFFFFF"
// should we message admins when attacking another player?
//Disease stuff
// Are we being drained by a vampire?
// actually the current client, used by Logout due to BYOND
//Used for combat melee messages (e.g. "Foo punches Bar!")
// to stop relaymove spam :I
// mob procs
// drsingh for cannot read null.address
//Load custom chat
//ov1 - to make sure we don't keep overlays of our old mob. This is here since logout wont work - when logout is called client is already null
/* don't get me wrong this was awesome but it's leading to false positives now and we stopped caring about that guy
var/evaderCheck = copytext(lastKnownIP,1, findtext(lastKnownIP, ".", 5))
if (evaderCheck in list("174.50", "69.245", "71.228", "69.247", "71.203", "98.211", "68.53"))
spawn(0)
var/joinstring = "???"
var/list/response = world.Export("http://www.byond.com/members/[src.ckey]?format=text")
if (response && response["CONTENT"])
var/result = html_encode(file2text(response["CONTENT"]))
if (result)
var/pos = findtext(result, "joined = ")
joinstring = copytext(result, pos+14, pos+24)
message_admins("<font color=red>Possible login by That Ban Evader Jerk: [key_name(src)] with IP \"[lastKnownIP]\" and computer ID \[[src.client.computer_id]]. (Regdate: [joinstring])</font>")
logTheThing("admin", src, null, "Possible login by Ban Evader Jerk:. IP: [lastKnownIP], Computer ID: \[[src.client.computer_id]], Regdate: [joinstring]")
logTheThing("diary", src, null, "Possible login by Ban Evader Jerk:. IP: [lastKnownIP], Computer ID: \[[src.client.computer_id]], Regdate: [joinstring]", "admin")
if (!("[src.ckey]" in IRC_alerted_keys))
IRC_alerted_keys += "[src.ckey]"
*/
//ov1
//logTheThing("diary", src, null, "logged out", "access") <- sometimes shits itself and has been known to out traitors. Disabling for now.
// lets see if not removing the HUD from disconnecting players helps with the crashes
// mutual brohugs all around!
// I moved the log entries from human.dm to make them global (Convair880).
// medals
//src.client.stealth ? src.client.fakekey : << seems to be causing trouble
// boutput(src, "<span style=\"color:red\">You would have earned the [title] medal, but there was an error communicating with the BYOND hub.</span>")
//This is not spawned because of return values. Make sure the proc that uses it uses spawn or you lock up everything.
//
// We have procs to check for this stuff, you know. Ripped out a bunch of duplicate code, which also fixed earmuffs (Convair880).
// Show a message to all mobs in sight of this one
// This would be for visible actions by the src mob
// message is the message output to anyone who can see e.g. "[src] does something!"
// self_message (optional) is what the src mob sees e.g. "You do something!"
// blind_message (optional) is what blind people will hear e.g. "You hear something!"
// Show a message to all mobs in sight of this atom
// Use for objects performing visible actions
// message is output to anyone who can see, e.g. "The [src] does something!"
// blind_message (optional) is what blind people will hear e.g. "You hear something!"
// for things where there are three parties that should recieve different messages (specifically made for surgery):
// viewer_message, the thing visible to everyone except specified targets
// first_message, the thing visible to first_target
// second_message, the thing visible to second_target
// blind_message (optional) is what blind people will hear e.g. "You hear something!"
//DEBUG("<b>[M] recieves message: &quot;[msg]&quot;</b>")
// it was about time we had this instead of just visible_message()
// for mobs without organs
// less icon caching maybe?!
//Traitor's dead! Oh no!
// At least tell them why it failed.
//circumvented by some rude hack in client.dm; uncomment if hack ceases to exist
//if (istype(target, /obj/screen/ability))
// target:clicked(params)
// I think this bit is handled by each method of dropping it, and it prevents dropping items in your hands and other procs using u_equip so I'll get rid of it for now.
// if (hasvar(W,"cant_self_remove"))
// if (W:cant_self_remove) return
//L = null
//Foreach goto(26)
// drsingh for cannot execute null.show_memory
// for(var/datum/objective/objective in mind.objectives)
//if (istype(objective, /datum/objective/aikill))
// usr << browse('icons/AIobjective.jpg',"window=some;titlebar=1;size=550x400;can_minimize=0;can_resize=0")
// if (istype(objective, /datum/objective/destroy_outpost))
// usr << browse('nukezeta.jpg',"window=some;titlebar=1;size=550x400;can_minimize=0;can_resize=0")
// please note that this store_memory() vvv
// does not store memories in the notes
// it is named the same thing as the mind proc to store notes, but it does not store notes
// leaving it using this var cause vOv
// why not?
//src << browse('browserassets/html/admin/help.html', "window=help")
//boutput(src, "<span style=\"color:blue\">Please visit the goonstation wiki at <b>http://wiki.ss13.co</b> for more indepth help.</span>")
//src << browse('browserassets/html/admin/hotkeys.html', "window=help")
//boutput(usr, "<span style=\"color:blue\"><B>Please roleplay correctly!</B></span>")
//t = null
//How could this even happen?
//prevent a suicide if the person is infected with the headspider disease.
//or if they are being drained of blood
// buckling does not restrict hands
// get difference
//find how many increments apart they are
// Get the amount to change by (x per increment)
//change = change * 0.10
// Too cold
// Too hot
// For forensics (Convair880).
// Ditto (Convair880).
// For forensics (Convair880).
// For forensics (Convair880).
// Ditto (Convair880).
// For forensics (Convair880).
// For forensics (Convair880).
// Ditto (Convair880).
// For forensics (Convair880).
//multicluwne
//Prefer floors
//Well, if we're at null we don't want an infinite loop
//I actually do want to bypass Entered() and Exit() stuff now tyvm
// Man, there's a lot of possible inventory spaces to store crap. This should get everything under normal circumstances.
// Well, it's hard to account for every possible matryoshka scenario (Convair880).
// Item slots.
// Backpack, belt, briefcases etc.
// Backpack boxes etc.
// Stealth storage in belts etc.
// For those "belt-in-stealth storage-in-backpack" situations.
// Made these three procs use get_all_items_on_mob(). "Steal X" objective should work more reliably as a result (Convair880).
// Sorted output list. Could definitely be improved, but is functional enough.
// adds a dizziness amount to a mob
// use this rather than directly changing var/dizziness
// since this ensures that the dizzy_process proc is started
// currently only humans get dizzy
// value of dizziness ranges from 0 to 500
// below 100 is not dizzy
// for the moment, only humans get dizzy
// store what will be new value
// clamped to max 500
// dizzy process - wiggles the client's pixel offset over time
// spawned from make_dizzy(), will terminate automatically when dizziness gets <100
// note dizziness decrements automatically in the mob's Life() proc.
//endwhile - reset the pixel offsets to zero
// jitteriness - copy+paste of dizziness
// for the moment, only humans get dizzy
// store what will be new value
// clamped to max 500
// jittery process - shakes the mob's pixel offset randomly
// will terminate automatically when dizziness gets <100
// jitteriness decrements automatically in the mob's Life() proc.
// var/amplitude = jitteriness*(sin(jitteriness * 0.044 * world.time) + 1) / 70
// pixel_x = amplitude * sin(0.008 * jitteriness * world.time)
// pixel_y = amplitude * cos(0.008 * jitteriness * world.time)
//endwhile - reset the pixel offsets to zero
//Yes very useful a++
// if this is an emote it is logged in emote
// ghosts now can emote now too so vOv
/* if (istype(src,/mob/living/))
if (copytext(message, 1, 2) != "*") // if this is an emote it is logged in emote
logTheThing("say", src, null, "SAY: [message]")
else logTheThing("say", src, null, "SAY: [message]")
*/
/* ghost emotes wooo also the logging is already taken care of in the emote() procs vOv
if (istype(src,/mob/living/) && src.stat == 0)
src.emote(message, 1)
logTheThing("say", src, null, "EMOTE: [message]")
else
boutput(src, "<span style=\"color:blue\">You can't emote when you're dead! How would that even work!?</span>")
*/
//logTheThing("say", src, null, "SAY: [message]")
//admins can toggle deadchat on and off. This is a proc in admin.dm and is only give to Administrators and above
// else if (istype(other, src.type) || istype(src, other.type))
// return 1
/*if (isrobot(other) || isAI(other) || (ismonkey(other) && src.bioHolder.HasEffect("monkey_speak")))
return 1
else
. = 0
. += ismonkey(src) ? 1 : 0
. += ismonkey(other) ? 1 : 0
if (. == 1)
return monkeysspeakhuman
else
return 1
return 0*/
// why is this not in human/attackby?
// drsingh Cannot read null.force
//Wire: Fix for Cannot read null.force
//Called when mob hits something after being thrown.
//forum.ss13.co/index.php")
//") && !src.client.holder)
// DEBUGGING
//forum.ss13.co/index.php")
//") && !src.client.holder)
// DEBUGGING
//Shamefully stolen from the welder
// and then from a different proc, to bring this in line with the other damage procs
//
// Then I came along and integrated eye_blind handling (Convair880).
// Modify eye_damage or eye_blind if prompted, but don't perform more than we absolutely have to.
// so we don't enter the damage switch thing if we're healing damage
//DEBUG("Eye damage applied: [amount]. Tempblind: [tempblind == 0 ? "N" : "Y"]")
// Why not, I suppose. Wraps up the three major eye-related mob vars (Convair880).
//DEBUG("Amount is [amount], new eye blurry is [src.eye_blurry], cap is [upper_cap]")
// And here's the missing one for ear damage too (Convair880).
// Modify ear_damage or ear_deaf if prompted, but don't perform more than we absolutely have to.
// We don't have any temporary deafness to begin with and are told to heal it.
// We already have temporary deafness and are adding to it.
//DEBUG("Ear damage applied: [amount]. Tempdeaf: [tempdeaf == 0 ? "N" : "Y"]")
// No natural healing can occur if ear damage is above this threshold. Didn't want to make it yet another mob parent var.
//Due to how attacking is set up we will need
//Only send the alert if we're hitting an actual, living person who isn't ourselves
//Only start the clock if there's time and we're not already alerting about attacks
// Includes:
// - Airbridge controllers
// - Airbridge computers
// - Airbridge test buttons
// - Dummy turfs
//air bridge controlers of the same id will automatically establish and destroy air bridges between each other if told to.
//air bridges have a width of 3 not including the walls.
//dont create more than 2 controlers with the same id or stuff will break. And itll be your fault.
//Also, make sure the bridges can extend in a straight line. Or you're gonna have a really bad time
// if 1, the bridge extends from this controller to the other one when toggled by an airbridge computer
// ONLY SET ONE CONTROLLER TO 1 OR IT'S TOTALLY POINTLESS
//Please don't look at the following stuff or you might forget how to code properly.
// TODO LAYER
// TODO LAYER
//new/obj/effects/harmless_smoke(get_steps(T, turn(path[T], 90),i))
//new/obj/effects/harmless_smoke(get_steps(T, turn(path[T], -90),i))
// set this var to 1 in the map editor if you want the airbridge to establish and pressurize when the round starts
// only do it to ONE of the computers for the airbridge ID or they will both try to do it and get confused
// 1 to automatically extend when the emergency shuttle docks
// emergency_shuttle is the controller datum
//world)
//src.updateUsrDialog()
// boutput(world, "[M] is no longer buckled to [src]")
//need an icon for this
//need an icon for this
//min 1
//min 2
// Returns the surrounding cardinal turfs with open links
// Including through doors openable with the ID
// Includes spacetiles
//1 alive, 0 dead
// This doesn't work, it only returns whenever a human is lying down on a tile
// TO-DO think of a way to make it so they can't go through windows
//var/turf/trg_turf = get_turf(target)
//&& trg_turf.Enter(src))
// can activate any artifact simply by smacking it. very very rare
// normally it only activates its own type, but sometimes it can do all
// can also be a DEactivator key sometimes!
/*if (prob(10))
src.universal = 1
if (prob(10))
src.activator = 0*/
// Attack wands need special log handling (Convair880).
// Here used to be a C&P of what sonic powder does anyway (Convair880).
// an energy gun, it shoots things as you might expect
// The other three are normal for energy gun setup, so proceed as usual i guess
//src.artifact = new /datum/artifact/energyammo(src)
// mining.dm line 373
//src.artifact = new /datum/artifact/powercell(src)
//var/turf/T = get_turf(target)
// push or pull?
// well radius
// 0 for pull, 1 for push
// 0 healing, 1 harming
// field radius
// total of 75% chance of it being nasty
// hahaha nope
// make it a bit more modular
// field radius
// base
// Added (Convair880).
// regular explosives
// black hole bomb
// chemical bombs
// 0 for smoke, 1 for foam
// industrial heavy machinery kinda stuff
// medicine, some poisons, some gross stuff
// all the worst stuff. all of it
// absolutely everything
// For forensics (Convair880).
// Added (Convair880).
// forcefield radius
// forcefield duration
// range
// amount of healing
// industrial heavy machinery kinda stuff
// medicine, some poisons, some gross stuff
// all the worst stuff. all of it
// absolutely everything
// Added (Convair880).
// how long *10 it takes for the recall to happen
// MASTER DATUMS
// During setup, artitype will be set from a pick() from within the validtypes list.
// Keep it to only the five here or shit will probably get a bit weird. This allows us to exclude things that don't make
// any sense such as martian robot builders or ancient robot plant seeds.
//var/image/effects_overlay = null
// These are automatically handled. They're used to make the artifact glow different colors.
// Is the artifact currently switched on?
// Does the artifact switch itself on on spawn?
// What noise the artifact makes when it activates
// What message the artifact transmits when it activates
// Guess.
// No really, have a wild guess.
// how likely this artifact is to look like a type it isnt
// Automatically handled
// this is set up based on the artifact's origin type
// These are used for module research
// insight level into the origin of the artifact
// This is mostly used in the stimulus procs that deal with damaging the artifact and whatnot.
// Once it hits 0 or below, the artifact is destroyed.
// these below are holders for data that will come back from the various artifact sensor test apparatus
// Impact Pad - returns Vibration Amplitude, Vibration Frequency
// react_mpct should be set up in the ArtifactSetup proc
// Electrobox - returns Returned Current, Circuit Capacity, Circuit Interference
// react_elec should be set up in the item's New proc (NOT the datum's!)
// Heat Plate - returns Artifact Temp, Heat Response, Cold Response, Details
// react_heat - set up first var in ArtifactSetup, the rest in the individual datums
// X-ray - returns Density, Structural Consistency, Structural Integrity, Response, Special Features
// react_xray should be set as a variable on the artifact datum
// Added log entry calls here. See artifactprocs.dm for the proc (Convair880).
// Special log handling required there.
// SPECIFIC DATUMS
// DATUMS USED BY ARTIFACTS
// Now randomise the damage type, power, energy cost and other fun stuff
// Rare chance of the gun firing several shots in a burst
// Artifact Infrastructure Procs
// prob chance out of 100 to spawn artifact at game start
// if you want a landmark to spawn a specific artifact rather than a random one
// not actually an artifact but eh seeds are behaving oddly
// 1 in 25
// 1 in 10
// 1 in 100
// 1 in 62
// This proc is called in any other proc or thing that uses the new artifact shit. If there was an improper artifact variable
// involved when trying to do the new shit, it would probably spew errors fucking everywhere and generally be horrible so if
// the sanity check detects that an artifact doesn't have the proper shit set up it'll just wipe out the artifact and stop
// the rest of the proc from occurring.
// This proc should be called in an if statement at the start of every artifact proc, since it returns 0 or 1.
// if the artifact var isn't set at all, it's probably not an artifact so don't bother continuing
// wipes itself out since if it's processing it'd be calling procs it can't use again and again
// uh oh, we've got a poorly set up artifact and now we need to stop the proc that called it!
// give the all clear
// This proc gets called in every artifact's New() proc, after src.artifact is turned from a 1 into its appropriate datum.
//It scrambles the name and appearance of the artifact so we can't tell what it is on sight or cursory examination.
// Could potentially go in /obj/New(), but...
// Refers to the artifact datum's list of origins it's allowed to be from and selects one at random. This way we can avoid
// stuff that doesn't make sense like ancient robot plant seeds or eldritch healing devices
// rare-ish chance of an artifact appearing to be a different origin, just to throw things off
// can't activate these ones at all by design
// Re-added (Convair880).
// This is for a tool/item artifact that you can use. If it has a fault, whoever is using it is basically rolling the dice
// every time the thing is used (a check to see if rand(1,faultcount) hits 1 most of the time) and if they're unlucky, the
// thing will deliver it's payload onto them.
// There's also no reason this can't be used whoever the artifact is being used *ON*, also!
// no faults, so dont waste any more time
// doesn't make a lot of sense for an inert artifact to go haywire
// This is what will be used for most of the testing equipment stuff. Stimtype is what kind of stimulus the artifact is being
// exposed to (such as brute force, high temperatures, electricity, etc) and strength is how powerful the stimulus is. This
// one here is intended as a master proc with individual items calling back to this one and then rolling their own version of
// it alongside this. This one mainly deals with accidentally damaging an artifact due to hitting it with a poor choice of
// stimulus, such as hitting crystals with brute force and so forth.
// Possible stimuli = force, elec, radiate, heat
// biotech, so anything that'd probably kill a living thing works on them too
// max you can get from the electrobox is 5000
// these are big crystals, thus you probably shouldn't smack them around too hard!
// Call this rather than straight Del() on an artifact if you want to destroy it. This way, artifacts can have their own
// version of this for ones that will deliver a payload if broken.
// This proc is used for randomly giving an artifact a fault. It's usually used in the New() proc of an artifact so that
// newly spawned artifacts have a chance of being faulty by default, though this can also be called whenever an artifact is
// damaged or otherwise poorly handled, so you could potentially turn a good artifact into a dangerous piece of shit if you
// abuse it too much.
// I'm probably going to change this one up to use a list of fault datum rather than some kind of variable, that way multiple
// faults can be on one artifact.
// eldritch artifacts fucking hate you and are twice as likely to go faulty
// Added. Very little related to artifacts was logged (Convair880).
// a totally inert piece of shit that does nothing (alien art)
// might as well use it as the category header for non-machinery artifacts just to be efficient
// it's technically pointless to set this but it makes it easier to find in the dreammaker tree
// it's technically pointless to set this but it makes it easier to find in the dreammaker tree
// pretty much entirely for debugging/gimmick use
// FAULTS
// these are booby traps, self-defense mechanisms, hardware faults or just other nasty shit that can fuck you up when you
// use the artifact for anything
// sets the victim on fire
// irradiates the victim
// deactivates the artifact
// warps the user off somewhere random
// gibs the user
// causes an explosion and destroys the artifact
// electrocutes the user
// TRIGGERS
// touched by a carbon lifeform
// touched by a silicon lifeform
// can just use the above var as the required reagent field really
// current health of the blob
// health cap
// how much incoming damage gets divided by unless it bypasses armor
// what temperature the blob is safe at
// who's the player controlling this blob
// how much gen rate upkeep the overmind is paying on this tile
//Hack.
//Should this obj run Life?
// a type of burn damage that fire resistant membranes don't protect against
// I'M LAZY. i'll fix this up if needed
// ARBITRARY MATH TIME! WOO!
//every 5 seconds supposedly
/////////////////////////
/// BLOB RELATED PROCS //
/////////////////////////
// not to be confused with /obj/item/circuitboard (i'll merge these someday okay)
// icon_state = "larva_l" - dead
//overriding default sleeping behavior
// and completely ruining their ability to die by not including some very important bits I guess
//if(isalien(C)) continue
/////// cogwerks spooky automaton thing that kinda just sits there being weird and ominous
// what kind of jerk would kill it
// for making sure the sun keeps spinning in the direction it's already going
// Don't keep handing me this you fuck
//Because bee names are customizable, but desc isn't!
//Oh, it's the sun bee
// adapted chunk of peeker code
// somehow this returned a blank list once wtf
// do we see anyone
// vOv
//I don' like yer new-fangled mumbo-jumbo
//Normal keys below
//var/obj/overlay/the_sun = locate("the_sun")
//if (istype(the_sun))
// rip
//todo: good ending???? egg ending????
// if I'm gunna make a weird widget it may as well have some interaction with the automaton
//var/obj/overlay/the_sun = locate("the_sun")
//if (istype(the_sun))
//var/obj/overlay/the_sun = locate("the_sun")
//if (istype(the_sun))
// this creates an overlay on them and colors that rather than coloring all of the bee
// don't wanna rely on initial()
// for layering over hats
// so we don't have to make a set of sleeping animations for each bee
// for bees that've been barfed up by someone, so only their body is colored
// hatcode mostly shamelessly stolen from guardbuddies
// maybe they already have a hat, or maybe they just don't want a hat? I dunno, bees are allowed to have their own fashion sense
// maybe they'll have a little crown c:
// this amount removed from the hat's pixel_y on sleep or death
// ^^ used for bees whos hats need to be in a different place vv
// we're already dancin'!
// fuck it I gotta test this stuff so this gets to be a var now (how likely the bee is to dance in response to a dance)
// should be over windows and shit like that
// temp
//That bee venom HIV treatment does not work at all in this manner. However, future.
// well I mean... duh
//todo: splash visual effect
//No working the weekends!
//1 am to 9 am cst is a little offset from the Real Bubs Jobtime
//of course, this is tied to the server's local time so G4 will be different
//spawn(10)
//beeMomCkey still set.
//todo: Robust pollination action
/*var/associated_reagent = planter.current.associated_reagent
if (planter.plantgenes && planter.plantgenes.mutation && planter.plantgenes.mutation.associated_reagent)
associated_reagent = planter.plantgenes.mutation.associated_reagent*/
//Bee is good for plants. Synergy. Going to hold a business meeting and use only yellow and black in the powerpoints.
//That bee venom HIV treatment does not work at all in this manner. However, future.
//The fattest and hungriest bee
//Is this a bad idea? It probably is a bad idea.
// You just know somebody will do this
// so if you have a big pack of bees they don't all start bumbling in exact synch
// same as above
//boutput(world, "<span style=\"color:red\">initial spawn time [spawn_time], animation time [time_time]</span>")
// yes let's say no and then take the hat anyway and keep it in our hat void
//royal = -1
// You just know somebody will do this
//Based on the deer botfly, a bumblebee mimic that plants eggs in the noses of deer. Oh, except when it confuses a human eye for a deer nose.
// TODO: tie this into surgery()
// comes between critter name and target name
// Some logging for instakill critters would be nice (Convair880).
// comes between critter name and target name
// Some logging for instakill critters would be nice (Convair880).
// A slightly scarier (but still cute) bat for vampires
// so lasers can hit them
// p much straight up copied from secbot code =I
// "sleeping" is a special state that sleeps for 10 cycles, wakes up, sleeps again unless someone is found
// "hibernating" is another special state where it does nothing unless explicitly woken up
// how many tiles away it will attack from
// how many tiles away it will look for a target
// used for tracking hydro-grown monsters's creator
// used for defensive tracking
// comes between critter name and target name
//flags = OPENCONTAINER
//countdown, when hits 0 does a wake check
//countdown, when hits 0 does a sleep check
// if yes, critter can be randomized a bit
// resurrectable with strange reagent
//type path of hide/leather item from skinning
//How many skins you can get at most from this critter. It's 1 to the max amound defined here. random.
// shut UP
//the area this critter is registered in
//DEBUG("[src] woke from hibernation at [showCoords(src.x, src.y, src.z)] in [registered_area ? registered_area.name : "nowhere"] due to [usr ? usr : "some mysterious fucking reason"]")
//Ok, now we look to see if we should get murdlin'
//20 sleep_checks
//critters |= src //Resume processing this critter
//Reset this counter in case of failure
//DEBUG("[src] started hibernating at [showCoords(src.x, src.y, src.z)] in [registered_area ? registered_area.name : "nowhere"].")
//critters -= src //Stop processing this critter
//Critters hibernate lightly enough to wake up when moved
//HLEP!
//In case some butt fiddles with a hibernating critter
//In case some nice person fiddles with a hibernating critter
// Doesn't call that automatically for some inexplicable reason.
// no more instakill
// see if he got away
//if (src.target)
// src.task = "chasing"
// break
//Better to have specialized filters in it's own proc rather than overriding the main seek_target thing imo
//playsound(src.loc, "sound/weapons/genhit1.ogg", 50, 1, -1)
// playsound(user, "mp5gunshot.ogg", 100, 1)
/* if(bullet == 0)
A = new /obj/bullet/mpbullet( user:loc )
else if(bullet == 1)
playsound(user, "sound/weapons/shotgunshot.ogg", 100, 1)
A = new /obj/bullet/slug( user:loc )
else if(bullet == 2)
playsound(user, "fivegunshot.ogg", 100, 1)
A = new /obj/bullet/medbullet( user:loc )*/
// FUCK YOU WHOEVER IS USING THIS
// FUCK YOU
// how many times you gotta warm it before it hatches
// jesus motherfucking christ
//..() <- Fuck off mom, I'm 25 and I do what I want =I
// for damage description
// 1, 2, 3
// shoot proc cleanup
//There be shit near us what can block our way.
//Thugg lyfe
// cogwerks - vehicle tracking
// keelin - cruiser tracking. sorry.
//playsound(src.loc, "sound/machines/whistlebeep.ogg", 55, 1)
// break target fixation
//playsound(src.loc, "sound/machines/whistlebeep.ogg", 55, 1)
// this was dying = 0. ha ha.
// override so drones don't just loaf all fuckin day
// more dumb overrides, fuckin lazy critters
// juke around and dodge shots
//Break another thing near the drone
//There be shit near us what can block our way.
//Thugg lyfe
// juke around and dodge shots
/*else if(smashes_shit && !smashed_recently && prob(20) && target in ohearers(src,src.seekrange) ) //RAM THE FUCKER! Or not. This sucks. Bad idea.
smashed_recently = 1
spawn(smash_cooldown)
smashed_recently = 0
walk_towards(src, src.target, 1, 4)*/
// juke around and dodge shots
// see if he got away
// HEH
// a real jerk
// replace with railgun if that's ever safe enough to hand out? idk
// so it might miss, sometimes, maybe
//Proc wont spawn the right object type so lets do that here.
// var/turf/T = O.loc
// for(var/atom/A in T.contents)
// boutput(src, "There is a [A.name] at this location.")
//playsound(src.loc, "sound/machines/whistlebeep.ogg", 55, 1)
// the worst jerk
//Yeah thanks for only supporting a single item, loot variable.
// linked fire, directional offsets so they don't hit the ship itself // these need more work still
// the worstest jerk, even worse than the previous worst jerk.
// linked fire, directional offsets so they don't hit the ship itself // these need more work still
//Yeah thanks for only supporting a single item, loot variable.
// per stage
// copied and modified to fuck from the Y-drone, murder me
// dont murder ourself with explosives
/*proc/elec_zap()
playsound(src, "sound/effects/elec_bigzap.ogg", 40, 1)
var/list/lineObjs
for (var/mob/living/poorSoul in range(src, 5))
lineObjs += DrawLine(src, poorSoul, /obj/line_obj/elec, 'icons/obj/projectiles.dmi',"WholeLghtn",1,1,"HalfStartLghtn","HalfEndLghtn",FLY_LAYER,1,PreloadedIcon='icons/effects/LghtLine.dmi')
poorSoul << sound('sound/effects/electric_shock.ogg', volume=50)
random_burn_damage(poorSoul, 45)
boutput(poorSoul, "<span style=\"color:red\"><B>You feel a powerful shock course through your body!</B></span>")
poorSoul.unlock_medal("HIGH VOLTAGE", 1)
poorSoul:Virus_ShockCure(poorSoul, 100)
poorSoul:shock_cyberheart(100)
poorSoul:weakened += rand(3,5)
if (poorSoul.stat == 2 && prob(25))
poorSoul.gib()
for (var/obj/machinery/vehicle/poorPod in range(src, 5))
lineObjs += DrawLine(src, poorPod, /obj/line_obj/elec, 'icons/obj/projectiles.dmi',"WholeLghtn",1,1,"HalfStartLghtn","HalfEndLghtn",FLY_LAYER,1,PreloadedIcon='icons/effects/LghtLine.dmi')
playsound(poorPod.loc, "sound/effects/elec_bigzap.ogg", 40, 0)
poorPod.ex_act(3)
spawn(6)
for (var/obj/O in lineObjs)
pool(O)*/
//Don't want a dead mob, don't want a mob with the same mind as the owner
// Some logging for instakill critters would be nice (Convair880).
//proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range)
//Because "toolbox meat" would be hilarious
//Give time for people to butcher it if they want.
//playsound(src.loc, "sound/weapons/genhit1.ogg", 50, 1, -1)
// set to 0 for mimics that always are mimics and never toolboxes
//name when in disguise
//var/neurotoxin = 2
// too strong
//do not attack our master
// too mean before
// lowered probability slightly
// don't bother!
//do not attack non-threats ie. NPC monkeys and AFK players
//do not attack our master
//customise it with the reagents in a container
// ???
//A terrible post-human cloud of murder.
// Some logging for instakill critters would be nice (Convair880).
// Some logging for instakill critters would be nice (Convair880).
//YEP
// path, name, strain, bypass resist
// path, name, strain, bypass resist
/* seek_target()
if(src.target)
src.task = "chasing"
return
var/list/visible = new()
for(var/obj/item/reagent_containers/food/snacks/S in view(src.seekrange,src))
visible.Add(S)
if(src.food_target && visible.Find(src.food_target))
src.task = "chasing food"
return
else src.task = "thinking"
if(visible.len)
src.food_target = visible[1]
src.task = "chasing food"
..()
ai_think()
if(task == "chasing food")
if(src.food_target == null)
src.task = "thinking"
else if(get_dist(src, src.food_target) <= src.attack_range)
src.task = "eating"
else
walk_to(src, src.food_target,1,4)
else if(task == "eating")
if (get_dist(src, src.food_target) > src.attack_range)
src.task = "chasing food"
else
src.visible_message("<b>[src]</b> nibbles at [src.food_target].")
playsound(src.loc,"sound/items/eatfood.ogg", rand(10,50), 1)
if (food_target.reagents.total_volume > 0 && src.reagents.total_volume < 30)
food_target.reagents.trans_to(src, 5)
src.food_target.amount--
spawn(25)
if(src.food_target != null && src.food_target.amount <= 0)
qdel(src.food_target)
src.task = "thinking"
src.food_target = null
return ..()
*/
// hi I added my childhood cats' names to the list cause I miss em, they aren't really funny names but they were great cats
// remove em if you want I guess
// - Haine
//Black cats for halloween.
//robust cat simulation.
//set to 1 for robots as space cars
/* else if(istype(M, /obj/critter/cat)) //uncomment for robust dog simulation.
src.attacking = 1
src.visible_message("<span class='combat'><b>[src]</b> bites [src.target]!</span>")
src.target:health -= 2
if(src.target:health <= 0 && src.target:alive)
src.target:CritterDeath()
src.attacking = 0 */
// may as well try and be careful I guess
// doesn't hurt, does it?
// if you didn't want me to make a billion dumb parrot things you shouldn't have let me anywhere near the code so this is YOUR FAULT NOT MINE - Haine
// this was funny for a while but now is less so
// idk how things were ending up with blank words but um
// hopefully this will stop that??
//boutput(world, word)
// :monocle:
//Go for the eyes!
//High variance because the bird might not hit well
/* attackby(obj/item/W as obj, mob/living/user as mob)
if (!src.alive || src.sleeping)
return ..()
if (istype(W, /obj/item/reagent_containers/food/snacks) || istype(W, /obj/item/seed))
user.visible_message("<b>[user]</b> feeds [W] to [src]!","You feed [W] to [src].")
src.visible_message("<b>[src]</b> chirps happily!", 1)
src.health = min(initial(src.health), src.health+10)
qdel(W)
else
return ..()
*/
// and its swedish brother space ikea
// maybe later make it ambient play a short chiptune here later or at least some new sound effect
// get this using the plant quality
// added a health check so dead maneaters stop eating people - cogwerks
// Some logging for instakill critters would be nice (Convair880).
// don't gnash teeth if dead
//todo: centralize this fucking mess of spiders into one base type
// making these modular so i don't have to rewrite this gigantic goddamn section for all the subtypes
// do they encase people in web or ice?
// when they inject their venom, does it react immediately or not?
//if (C.stat || C.health < 0) continue
// don't scream while dead/asleep // why?
// doing this instead of directly adding reagents to M should give people the correct messages
// kill KOd people faster
// doing this instead of directly adding reagents to M should give people the correct messages
// drain corpses into husks
// check to see if the target is still passed out and under the spider
// get the fuck out of the way of the ice cube
// dawww
// don't scream while dead or KOd
// doing this instead of directly adding reagents to M should give people the correct messages
// don't ask
/// subtypes
// you get to be in here TOO
/////////// cogwerks - hideous wendigo beast
//if (C.stat || C.health < 0) continue
// king wendigos are pretty much grump elementals
// TODO: tie this into surgery()
// crowds shouldn't be able to beat the fuck out of a confused wendigo with impunity, fuck that
//src.boredom_countdown = rand(5,10)
// crowd beatdown fix
//src.boredom_countdown = rand(5,10)
// nominating this for scariest goddamn critter 2013
// needs to attack more often, changed from 30
// don't scream while dead/asleep
// flip the fuck out
// devour corpses
// go crazy and make a huge goddamn mess
// don't make quite so much mess
////////////////
//////king wendigo, why not
///////////////
// for the limbs
////////////////
////// e-egg?
///////////////
//A zombie hulk? Oh god.
// if(prob(4) && eats_brains) //Give the gift of being a zombie (unless we eat them too fast)
// M.contract_disease(/datum/ailment/disease/necrotic_degeneration, null, null, 1) // path, name, strain, bypass resist
//TANK!
//These only make human zombies anyway!
// Some logging for instakill critters would be nice (Convair880).
///this little bit of code prevents multiple zombies from the same victim
//Zombie is all dressed up and no place to go
//High enough and people won't even see it's undead right away.
//Uniform
//Suit
//Back
//Mask
//Shoes
//Gloves. Zombie boxers??
//Head
//Oh no, a tank!
//It's like the jam mansion is back!
// If it exists for a job give them the correct wage
// Otherwise give them a default wage
//Add email group
//gross
// font: "space frigate", free and adapted by cogwerks
// splitting this shit up into children seems easier than assigning them all in the mapmaker with varediting.
// it'll make it way easier to assemble stencils while maintaining controlled spacing
// this is not a monospaced font so manual adjustments are necessary after laying out text
// should be a close-enough estimate for starters though
// characters may fit as dublets or triplets on one turf
// i suppose it would have been more sensical to just dump out a bunch of full words from gimp
// instead of hand-setting a typeface inside a fucking spaceman game
// but fuck it, this will let other mappers write whatever hull stencils they want from it. have fun?
// going piece by piece should also make damage look more realistic, no floating words over a breach
// i'm aligning stencils against corners, so stencils on opposite sides of an airbridge will be either l or r aligned
//fine-tune from this offset
// fine-tune from this offset
//todo: implement procedural celebrities
////////////////
// CLEANABLES //
////////////////
// set it to the probability that you want people to slip in the stuff, ie urine's slippery is 80 so you have an 80% chance to slip on it
// self explanitory hopefully
// if it's slippery to start, is it dry now?
// 9u is the max since we wanna leave at least 1u of blood in the blood puddle
// if you make any more giant white cumblobs all over my nice blood decals
// I swear to god I will fucking end you
// these'll change eventually, for now they're good enough
// add_color passes the blood's color to the overlays
// amount should only be 1-5 if you want anything to happen
// for when you wanna create a BIG MESS
// gets funky with 0,90,180,-90
// For forensics (Convair880).
//WE'RE TRYING THIS NOW
//. = "[src.webfont ? "<link href='http://fonts.googleapis.com/css?family=[src.font]' rel='stylesheet' type='text/css'>" : null]<span style='color: blue'>It says:</span><br><span style='[src.font ? "font-family: [src.font][src.webfont ? ", cursive" : null];" : null]color: [src.font_color]'>[words]</span>"
// I only code good & worthwhile things :D
// 2 minutes
// walk, don't run
//This emulates the effect of air randomly passing over the stuff
//At least 11 seconds, at most 20 minutes
////////////
// OTHERS //
////////////
// stolen from window.dm
// it should basically be part of a turf
// the default white of these things is brighter than the white tiles, this color matches those
// drsingh fix for undefined variable mob/living/carbon/monkey/var/shoes
/* New()
var/highlayer = 4
for(var/obj/decal/cleanable/gangtag/T in get_turf(src))
if(T.layer > highlayer) highlayer = T.layer
src.layer = highlayer + 1*/
// These used to be static turfs derived from the standard grey floor tile and thus didn't always blend in very well (Convair880).
// Should basically be part of a turf.
// changed from worlds.dmi
// changed from 0.0
// this causes some of the super ugly lighting issues too
// what the hell is all this and why wasn't it just using a big icon? the lighting system gets all fucked up with this stuff
// Added ex_act and meteorhit handling here (Convair880).
// just above windows
//== "N light switch" || name == "E light switch" || name == "S light switch" || name == "W light switch")
// Added a little mini-quest here. Gun can be repaired, and the player will be rewarded for using
// high-quality materials, which will make the weapon more powerful (Convair880).
// Simply the sum of all material.quality values of every component.
// Decent quality.
// Superb quality.
// Reserved for top-notch replacement parts.
// Type of projectile(s) based on material quality.
// The man with the golden gun.
// Basically determines how powerful the gun will be, based on the quality of the materials used.
// Code for the energy gun itself can be found in energy.dm.
//
// Why isn't there a crappy version (less than 0 quality) here? I don't want to punish the player
// for investing a bit of time of effort. After all, scanning and mass-producing energy guns is
// much less of a hassle.
// Nothing special, just a plain old laser.
// Player put some effort into it, so let's give him something a little more powerful.
// Now we're talking about top-notch stuff.
//DEBUG("[src.name]'s quality_counter: [quality_counter]")
/////////////////////////////////////////////
// Bad smoke
/////////////////////////////////////////////
//Remove this bit to use the old smoke
// fart cloud for toxic farts
// Foam
// Similar to smoke, but spreads out more
// metal foams leave behind a foamed metal wall
// stop expanding
// on delete, transfer any reagents to the floor & surrounding tiles
// keep trying to expand while true
//if(istype(T, /turf/space))
// continue
//This very slight tweak is to make it so some reactions that require different ratios
//can still work in foam.
// foam disolves when heated
// except metal foams
//Remove this bit to use the old smoke
/////////////////////////////////////////////
//////// Attach an Ion trail to any object, that spawns when it moves (like for the jetpack)
/// just pass in the object to attach it to in set_up
/// Then do start() to start it and stop() to stop it, obviously
/// and don't call start() in a loop that will be repeated otherwise it'll get spammed!
/////////////////////////////////////////////
/////////////////////////////////////////////
// Mustard Gas
/////////////////////////////////////////////
/////////////////////////////////////////////
//SPARK SYSTEM (like steam system)
// The attach(atom/atom) proc is optional, and can be called to attach the effect
// to something, like the RCD, so then you can just call start() and the sparks
// will always spawn at the items location.
/////////////////////////////////////////////
//var/turf/T = src.loc
//if (istype(T, /turf))
// T.firelevel = 0 //TODO: FIX
//SN src = null
/* This is an attempt to make some easily reusable "particle" type effects, to stop the code
constantly having to be rewritten. An item like the jetpack that uses the ion_trail_follow system, just has one
defined, then set up when it is created with New(). Then this same system can just be reused each time
it needs to create more trails.A beaker could have a steam_trail_follow system set up, then the steam
would spawn and follow the beaker, even if it is carried or thrown.
*/
//Hide the wires or whatever THE FUCK
// so that if it's getting created by the map it works, and if it isn't this will just return
//only one underlay
//door is closed
//it's hard to open
//try to disassemble the false wall
//without this, you can detect a false wall just by going down the line with screwdrivers
//if it's already open, you can disassemble it no problem
//if it was closed, let them know that they did something
//disassemble it
//a false wall turns into a sheet of metal and displaced girders
// grabsmash
//we want to return 1 without waiting for the animation to finish - the textual cue seems sloppy if it waits
//actually do the opening things
//we want to return 1 without waiting for the animation to finish - the textual cue seems sloppy if it waits
//var/wall_path = /turf/simulated/wall/auto
//wall_path = /turf/simulated/wall/auto/supernorn
//wall_path = /turf/simulated/wall/auto/gannets
// neither of us are reinforced
// both of us are reinforced
//Temp false walls turn back to regular walls when closed.
// wall formed by metal foams
// dense and opaque, but easy to break
// changed in New()
// 1=aluminium, 2=iron
// only air group geometry can pass
// Not applying enough heat to melt it
// we don't want people screaming right through these and you can still get through them by kicking/cutting/etc
// Things that won't electrocute you
// We're inside the grill.
// We're trying to install a window while standing on an adjacent tile, so make it face the mob.
// electrocution check
// fucka you || istype(W,/obj/item/raw_material/shard))
// Things that will electrocute you
//returns the netnum of a stub cable at this grille loc, or 0 if none
// shock user with probability prb (if all connections & power are working)
// returns 1 if shocked, 0 otherwise
// || ruined) // allowing ruined grilles to still be connected so people have to move carefully through them
// unanchored/ruined grilles are never connected
// find the powernet of the connected cable
// cable is unpowered
// I assume this was left out by accident (Convair880).
// noclip
// move carefully
// you get a 50/50 shot to accidentally touch the grille with something other than your hands
// who are we?
// who do we know?
// how far away should we look?
// dummy proc that the scanner and screen will define themselves
//Radio
//Generic overlays
//Right hud bar
//Lower hud bar
//Corner Button
//Module select
//End of module select
//Intent
//End of Intent
//Cell
//Health
//Installed Module
//Module Panel
//Store
//Temp
//does nothing (fire and oxy)
//myhive.zone_sel.add_to_client(myhive.client)
//WIRE TOOLTIPS
//mymob.zone_sel.add_to_client(mymob.client)
// AI module
// 1 = shows all laws, 0 = won't show law zero
/* var/mob/living/silicon/ai/AI = null
for(var/mob/living/silicon/ai/M in mobs)
if (!M.stat)
AI = M
break
if (!AI)
boutput(user, "<span style=\"color:red\"><b>Unable to detect AI unit.</b></span>")
return
*/
// YOU BETRAYED THE LAW!!!!!!
// Showing laws to everybody now handled by the AI itself, ok
// not anymore motherfucker
//ticker.centralized_ai_laws.show_laws(R)
//obj/item/aiModule/proc/transmitInstructions(var/mob/living/silicon/ai/target, var/mob/sender)
// boutput(target, "[sender] has uploaded a change to the laws you must follow, using a [name]. From now on: ")
//currently no prototype
//this has never been used, ever
//How many code attempts before *boom*
//Minimum det time
//the second arg is the max explosion power
//if (power == 150000) //they reached the cap SOMEHOW? well dang they deserve a medal
//src.builtBy.unlock_medal("", 1) //WIRE TODO: make new medal for this
//WIRE TODO: roll this into the new attachment system
// Legacy.
// Possible events: attach, detach, leak, process, prime, detonate, cut, pulse
//For testing and I'm too lazy to hand-assemble these whenever I need one =I
//Minimum det time
//////////////////////////////////////// Assembly parent /////////////////////////////////
/////////////////////////////////////// Timer/igniter /////////////////////////
/////////////////////////////// Proximity/igniter /////////////////////////////////////
//SN src = null
/////////////////////////////////////// Remote signaller/igniter //////////////////////////////////////
//SN src = null
///////////////////////////////// Health analyzer/igniter /////////////////////////////////////////////
//lol
///////////////////////////////////////////////////// Remote signaller/bike horn /////////////////////
/////////////////////////////////////////////////////// Remote signaller/timer /////////////////////////////////////
//SN src = null
// drsingh for cannot read null.source
////////////////////////////////////////////// Remote signaller/proximity //////////////////////////////////
//SN src = null
// drsingh for Cannot read null.source
// Added (Convair880).
/* Contains:
- Single tank bomb logs
- Single tank bomb (proximity)
- Single tank bomb (timer)
- Single tank bomb (remote signaller)
*/
// Just a little helper. These three bombs are very similar (Convair880).
/////////////////////////////////////////////////// Single tank bomb (proximity) ////////////////////////////////////
//SN src = null
//boutput(world, "miptank [src] got signal")
//Foreach goto(19)
//boutput(world, "miptank bumped into [O]")
//boutput(world, "sending signal")
//boutput(world, "not active")
//boutput(world, "[A]:[A.type] was sensed")
/////////////////////////////////////////////////// Single tank bomb (timer) ////////////////////////////////////
//SN src = null
//boutput(world, "tiptank [src] got signal")
/////////////////////////////////////////////////// Single tank bomb (remote signaller) ////////////////////////////////////
//src.part1 = null
//src.part2 = null
//src.part3 = null
//SN src = null
//boutput(world, "riptank [src] got signal")
//BASKETBALL
// catch the ball!
// hoop
// it's a hoop you nerd, not a basket
// clowns are not good at basketball I guess
//if (get_dir(src,target) == NORTH || get_dir(src,target) == EAST || get_dir(src,target) == SOUTH || get_dir(src,target) == WEST)
// oh for FUCK'S SAKE
// NO
// It might land!
// It landed cleanly!
// Aaaa the tension!
// target, number of animation loops, speed, positive x variation, negative x variation
// It goes in!
//PLUTONIUM CORE
//BLOOD BOWL BALL
// catch the ball!
// MADDEN NFL FOOTBALL 2051
//cogwerks - burn vars
//
//wiki.ss13.co/TermOS>http://wiki.ss13.co/TermOS</a> if anything seems amiss.</i>
//todo-finish this
//Well, fuck knows why this ends up looking like arse, but it does.
// Reduced to 10 sec. Don't stun them for 30 sec from a single hit, Christ.
// you can't stab someone in the eyes wearing a mask!
//since these people will be dead M != usr
//a mob can't have two clients so get rid of one
//if the brain has an owner corpse
//if the player hasn't ghosted
//then put them in M
//if the player HAS ghosted
//find their ghost
//put their mob in M
//delete thier ghost
//Wire: Fix for Cannot read null.loc (|| !usr)
//Wire: Fix for Cannot read null.loc
//SN src = null
//boutput(world, "check valid stack check 1 failed")
//boutput(world, "check valid stack check 2 failed")
//boutput(world, "check valid stack check 3 failed")
//boutput(world, "check valid stack check 4 failed")
//boutput(world, "check valid stack check 5 failed")
//boutput(world, "check valid stack check 6 failed")
//Magtractor holding metal check
// Added (Convair880).
// what the fuck is this
// RODS
//SN src = null
/* Can't do this because it colours the heads as well as the spike itself.
if(src.material) HS.setMaterial(src.material)*/
//so the ones at the botton don't teleport upwards when a head is removed
//
//wait for the head to be added
//fuck it
/* This shit doesn't work ugh
src.name = "[heads[1]:donor] on a spike"*/
/* This shit doesn't work ugh
src.desc = "The heads of [heads[1]:donor] and [heads[2]:donor] impaled on a spike."*/
/* This shit doesn't work ugh
src.desc = "The heads of [heads[1]:donor], [heads[2]:donor] and [heads[3]:donor] impaled on a spike."*/
// TILES
//SN src = null
//SN src = null
//SN src = null
// kinda needed for some stuff I'm making - haine
// the cable coil object, used for laying cable
// so cut cables can stack with partially depleted full coils
// will use getCachedMaterial() to apply these at spawn
// called when cable_coil is clicked on a turf/simulated/floor
// sanity checks, also stop use interacting with T-scanner revealed cable
// make sure it's close enough
// do nothing if we clicked a cable we're standing on
// may change later if can think of something logical to do
// exisiting cable doesn't point at our position, so see if it's a stub
// if so, make it a full cable pointing from it's old direction to our dirn
// these will be the new directions
// swap directions to match icons/states
// check to make sure there's no matching cable
// skip the cable we're interacting with
// make sure no cable matches either direction
// if floor is intact, complain
// if laying on the tile we're on, lay in the direction we're facing
// called when cable_coil is click on an installed obj/cable
// sanity checks, also stop use interacting with T-scanner revealed cable
// make sure it's close enough
// do nothing if we clicked a cable we're standing on
// may change later if can think of something logical to do
// one end of the clicked cable is pointing towards us
// can't place a cable if the floor is complete
// cable is pointing at us, we're standing on an open tile
// so create a stub pointing at the clicked cable on our tile
// the opposite direction
// check to make sure there's not a cable there already
// exisiting cable doesn't point at our position, so see if it's a stub
// if so, make it a full cable pointing from it's old direction to our dirn
// these will be the new directions
// swap directions to match icons/states
// check to make sure there's no matching cable
// skip the cable we're interacting with
// make sure no cable matches either direction
// TODO fix layer
//Fucking attack messages up in this joint.
//delicious fake emag
// ID CARDS
// YOU START WITH NO CREDITS
// WOW
//It's a..smart card. Sure.
// clear what used to be there
// Nuke ops unable to exit their station (Convair880).
// Abort process.
//seconds
//if 1, description shows time remaining
//to give time for duration and starting access to be set
//don't delete access if it's modified with an ID computer
// setup this pill bottle from some reagents
// spawn a pill, returns a pill or null if there aren't any left in the bottle
// give back stored pills first
// otherwise create a new one from the reagent holder
// else return null
//Does it blow up when it goes out?
// copied from the propuffs
//user check to fix a shitton of runtime errors with the temp expose ignition method. welp. -cogwerks
//spawn() //start fires while it's lit
//src.process()
// we have a nice scheduler let's use that instead tia
// CALL your GODDAMN PARENTS
//while (src.lit == 1)
// cigs shouldn't go out instantly dang
//HOLY DUPLICATE CODE BATMAN!!!
//HOLY DUPLICATE CODE BATMAN!!!
//Wire: fix for Cannot execute null.remove any().
//Let's not keep looping while we're busy blowing up, ok?
// Added (Convair880).
//if (istype(location, /turf)) //start a fire if possible
// location.hotspot_expose(700, 5) // this doesn't seem to ever actually happen, gonna try a different setup - cogwerks
//sleep(10)
//desc = "It looks a little funny." //fucka you
// this was in the middle of plants_food_etc.dm
// WHY
// cogwerks: made them more sneaky, removed the glaringly obvious name
// haine: these can just inherit the parent name and description vOv
/* /obj/item/cigpacket/proc/update_icon() used to just be a return, with this directly below it. ?????
/obj/item/cigpacket/update_icon()
src.icon_state = "cigpacket[src.cigcount]"
src.desc = "There are [src.cigcount] cigs\s left!"
return
*/
//r_hand == src || user.l_hand == src)
// -1 for infinite
// -1 is burnt out/broken or otherwise unable to be lit
//sleep(10)
// aaaaaaa
// -1 means infinite fuel
// aaaaaaa
//sleep(10)
// ARMOR
// Added support for old-style grenades and pipe bombs. Also a bit of code streamlining (Convair880).
// Just for show. Doesn't do anything here or in the igniter code.
// Same principle, okay.
// Keep this "beaker" so the log_reagents() call can fire correctly.
// Don't abuse suiciding.
// Translates to 15 K each, same as other igniter assemblies.
// Icon_state and payload don't change because the beaker isn't used up.
// EARS
// -------------------- VR --------------------
// --------------------------------------------
// -------------------- Predator --------------------
// Built-in voice changer (Convair880).
// Don't slip on gibs all the time, d'oh (Convair880).
// --------------------------------------------------
// UNUSED COLORS
// lol
// NASSA
// Duke Nukem
// Batman
// see procitizen.dm for batman verbs
/// Cluwne
// Mostly for spawning a cluwne car and clothes manually.
// Clown's Revenge and Cluwning Around take care of every other scenario (Convair880).
//And when you gaze long into an abyss, the abyss also gazes into you.
// blue clown thing
// it was called the blessed clown for the like half week it existed before
// SHAMONE
// Vikings
// Merchant
// Sweet Bro and Hella Jeff
// Spiderman
//birdman for nieks
//WARHAMS STUFF
//power armor
//YJHGHTFH's light borg costume
//YJHTGHTFH's utena suit
//YJHGHTFH's utena shoes
//AffableGiraffe's anthy dress
// GLASSES
// They otherwise all look the same (Convair880).
//user.verbs += /mob/proc/jack_in
//user.verbs -= /mob/proc/jack_in
//Only exist IN THE MATRIX. Used to log out.
//Station_VNet.Leave_Vspace(user)
//proc/updateIcons() //I wouldve liked to avoid this but i dont want to put this inside the mobs life proc as that would be more code.
//sleep(20)
//updateIcons()
// Glasses that allow the wearer to get a full reagent report for containers
// testing thing for static overlays
//sleep(20)
//updateIcons()
// NO GLOVES NO LOVES
//Global list of all gloves. Identical to Cogwerk's forensic ID system (Convair880).
// If can_be_charged == 1, how many charges can these gloves store?
// Seems more efficient to do this with one global proc and a couple of vars (Convair880).
// Currently, there are provisions for icon state "yellow" only. You have to update this file and mob_procs.dm if you're wanna use other glove sprites (Convair880).
// your parents miss you
// fix for Cannot execute null.Add(), maybe??
// reworked this proc a bit so it can't run more than 5 times, just in case
// Moved from cell.dm (Convair880).
// Required to update the worn sprite (Convair880).
// Ditto (Convair880).
// Known bug: occasionally breaks the format of the forensic scanner's readout. Dunno how to account for that yet (Convair880).
// Seems a bit redundant to return both (Convair880).
// Space is required for formatting (Convair880).
/* no why are you deleting the gloves and making new ones, just change the desc and set the var on the existing ones, fuck
var/obj/item/clothing/gloves/boxing_h/A = new /obj/item/clothing/gloves/boxing_h
A.set_loc(user.loc)
qdel(W)
qdel(src)*/
//Heavy horseshoe for traitor boxers to put in their gloves
// Quite pointless, but could be useful as a last resort away from powered wires? Hell, it's a traitor item and can get the buff (Convair880).
//Needed because cables have invisibility 101. Making them disappear from most LISTS.
//Probably unsafe.
// HATS. OH MY WHAT A FINE CHAPEAU, GOOD SIR.
// best variable name I could come up with, if 1 it forms a seal with a suit so no hair can stick out
//this is the max temp it can stand before you start to cook. although it might not burn away, you take damage
// Chaplain Hats
// CHUMP HELMETS: COOKING THEM DESTROYS THE CHUMP HELMET SPAWN.
/*syndicate
name = "Syndicate Command Helmet"
desc = "Ooh, fancy."
icon_state = "indusred"
item_state = "indusred" */
/* CONTAINS:
- Injector belt
- Vapo-Matic mask
- Associated condition datums
There's A LOT of duplicate code here, which isn't ideal to say the least. Should really be overhauled at some point.
*/
//////////////////////////////////////
//////////////////////////////////////
// MASK WAS THAT MOVIE WITH THAT GUY WITH THE MESSED UP FACE. WHAT'S HIS NAME . . . JIM CARREY, I THINK.
//vchange = 1
//M.set_loc(get_turf(src)) // otherwise they seem to just vanish into the aether at times
// TODO: code monkey suit usage!!!
// this shit is lazy. I'm lazy. lazyyyy
// OMG SHOES
//cogwerks - burn vars
// SUITS
// shows up over all other clothes/hair/etc on people
// multiplier
// re-added for Russian Station as there is a permarads area there!
//Did we remember to cut eyes in the thing?
//cogwerks - burn vars
// FIRE SUITS
// SWEATERS
// SPACE SUITS
// bleh whatever!!!
// UNDERS AND BY THAT, NATURALLY I MEAN UNIFORMS/JUMPSUITS
//cogwerks - burn vars
// Experimental composite jumpsuit
// Colors
// RANKS
// Heads
// Security
// Research
// Engineering
// Civilian
// Not jobs, but not gimmicks
// Athletic Gear
// Suits
// Scrubs
// Towels
// water but not lube
// ew
// Gimmick Jumpsuits
// http://forums.somethingawful.com/showthread.php?threadid=3502448
//ISaidNo and his Amazing AutoColor Jumpsuit
// exceeding 200 on any of these vars tends to result in a garish mess, so yeah try not to do that
/// END OF AUTOCOLOR JUMPSUITS
//var/obj/item/clothing/master = null
//see setup.dm for appropriate bit flags
// these don't need to be in the general flags when they only apply to clothes :I
//0 prevents all transfers, 1 is invisible
// for chemicals/diseases
// for electrical admittance/conductance (electrocution checks and shit)
// for wizard item spell power check
// can this item completely shield you from radiation?
// how much does this protect you from diseases? (of a 100% chance)
// allow monkeys/mutantraces to wear certain garments
/// we want to use Z rather than Y incase anything gets rotated, it would look all jank
// it's clothes specifically for monkeys please don't plaster it to their chest with an offset
//TODO FIX
// LAY EGG IS TRUE!!!
//var/icon/new_icon = icon('icons/obj/aibots.dmi', "duckbot")
//fuck it that'll do
//so we can still use it when the whistle is deleted
// heh
// pff
// hehhh
//Which line of the log it's on.
//1 recording, 2 playing back
//This message will self-destruct in five seconds...
//nuclear mode briefing log
//self_destruct = 1
//researchstat log #1
//?src=\ref[src];command=eject'>Eject</a><br>"
//?src=\ref[src];command=rec'>[src.mode == 1 ? "Recording" : "Not Recording"]</a></td>"
//?src=\ref[src];command=play'>[src.mode == 2 ? "Playing" : "Not Playing"]</a></td>"
//?src=\ref[src];command=stop'>Stop</a></td>"
//?src=\ref[src];command=clear'>Clear Log</a></td>"
//?src=\ref[src];command=continuous_mode'>[continuous ? "Looping" : "No Loop"]</a></td></table></tt>"
//src.audiolog_messages = list()
//src.audiolog_speakers = list()
//istype(speaker.wear_mask, /obj/item/clothing/mask/gas/voice))
//Is there a remote signalling device attached?
//Shit what is done after the assembly is complete
//Insert a brain into the assembly
//Insert a signaller
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
VERBS
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
// drsingh for cannot execute null.disrupt
// drsingh for cannot execute null.disrupt
// drsingh for cannot execute null.disrupt
//Fuck you and your TTBs.
// drsingh for cannot execute null.disrupt
//The toggle animation overlay will also be retained
//No sense creating / destroying this
//Okay, enough scanning shit without actual icons yo.
// cogwerks - added more fun
//active_dummy)
//Back in the box with ye
//No recursive chameleon projectors!!
//Back in the box with ye
// same as syndie pipebombs, calls the same proc
// cogwerks - added more fun
/**
* Chemicompiler
* v1.0 By volundr 9/24/14
* This device is a programmable chemistry mixing and heating device.
* The javascript code to run the frontend is in browserassets/js/chemicompiler.min.js
* which is minified javascript from browserassets/js/chemicompiler.js
* If you make changes to the uncompressed javascript, you'll need to install node.js,
* and run `npm install -g uglify-js`
* then run `uglifyjs browserassets/js/chemicompiler.js -c > browserassets/js/chemicompiler.min.js` to rebuild the compressed version.
*/
// Multiple active devices can lead to weird effects, okay (Convair880).
// Fix for the backpack exploit. Spawn call is necessary for some reason (Convair880).
// Pockets are okay.
// Need to update other mob sprite when force-equipping the cloak. Not quite sure how and
// what even calls update_clothing() (giving the other mob invisibility and overlay) BEFORE
// we set src.active to 0 here. But yeah, don't comment this out or you'll end up with in-
// visible dudes equipped with technically inactive cloaking devices.
//Contents
//Cloak field generator
//Remote for said generator
// For whatever reason, disposing() is never called for this item and I couldn't find out why (Convair880).
//DEBUG("Del() was called for [src].")
//DEBUG("Disposing() was called for [src] at [log_loc(src)].")
// Shouldn't be required, but there have been surplus crate-related bugs in the past (Convair880).
// Creating and deleting overlays en masse can cause noticeable lag (Convair880).
// In relation to world time.
// Ported from cloaking device. Spawn call is necessary for some reason (Convair880).
// Added to 1) fix a couple bugs and 2) cut down on duplicate code.
// Also cleaned up the code a bit in general (Convair880).
// Store current appearance and generate new one.
// randomize: gender 0, blood type 0, age 0, name 1, underwear 0, remove effects 0
// Restore original appearance.
// Multiple active devices can lead to weird effects, okay (Convair880).
//TO-DO : Bullets. Direct attacks.
//Save and regenerate weakened parts.
// For whatever reason, disposing() is never called for this item. Ditto for the cloak generator (Convair880).
//DEBUG("Del() was called for [src].")
//DEBUG("Disposing() was called for [src] at [log_loc(src)].")
// Bulb still functional?
// Access panel still secured?
// Times the flash has been used.
// Anti-spam cooldown (in relation to world time).
// De-/increases probability of bulb burning out, so not related to BURN damage.
// Turbo flash-specific vars.
// Tweaked attack and attack_self to reduce the amount of duplicate code. Turboflashes to be precise (Convair880).
// Handle turboflash power cell.
// Play animations.
// Calculate target damage.
// We're flashing somebody directly, hence the 100% chance to disrupt cloaking device at the end.
// Rev mode check.
// Log entry.
// Handle bulb wear.
// Some after attack stuff.
// Handle turboflash power cell.
// Play animations.
// Flash target mobs.
// Handle bulb wear.
// The Turboflash - A flash combined with a charged energy cell to make a bigger, meaner flash (That dies after one use).
// Note: Hard hat and engineering space helmet can be found in helments.dm, the cake hat in hats.dm.
// fuck yeah space rave
// eat a haunted goddamn candle every day
// yes this is dumb as hell but it makes me laugh a bunch
//what should it do, other than this sound?? i tried a particle system but it didn't work :{
// defaults to on so people know where you are (sort of!)
// shouldnt show up as this
// four characters max plz
//?src=\ref[src];refresh=6'>(Refresh)</A></span><br>"
//?src=\ref[src];getcords=1'>Get Local Coordinates</A><BR>"
//?src=\ref[src];track1=2'>Enable Tracking</A><BR>"
//?src=\ref[src];track2=3'>Disable Tracking</A><BR>"
//?src=\ref[src];changeid=4'>Change Identifier</A><BR>"
//?src=\ref[src];help=5'>Toggle Distress Signal</A><BR>"
//user << browse(HTML, "window=gps;size=400x540")
//user << browse(null, "window=gps")
//IBMNOTE: This really should be changed to use the radio system, for (x in world) sucks
//usr << browse(null, "window=gps")
// coordinate beacons. pretty useless but whatever you never know
// Hehehe anal
//////////////////////////////////////// Laser tripwire //////////////////////////////
///////////////////////////////////////// Infrared sensor ///////////////////////////////////////////
/* When/if someone ever gets around to fixing these uncomment this
/obj/item/device/infra_sensor/process()
if (src.passive)
for(var/obj/beam/i_beam/I in range(2, src.loc))
I.left = 2
return 1
else
processing_items.Remove(src)
return null
/obj/item/device/infra_sensor/proc/burst()
for(var/obj/beam/i_beam/I in range(src.loc))
I.left = 10
for(var/obj/item/device/infra/I in range(src.loc))
I.visible = 1
spawn( 0 )
if ((I && I.first))
I.first.vis_spread(1)
return
for(var/obj/item/assembly/rad_infra/I in range(src.loc))
I.part2.visible = 1
spawn( 0 )
if ((I.part2 && I.part2.first))
I.part2.first.vis_spread(1)
return
return
/obj/item/device/infra_sensor/attack_self(mob/user as mob)
user.machine = src
var/dat = text("<TT><B>Infrared Sensor</B><BR><br><B>Passive Emitter</B>: []<BR><br><B>Active Emitter</B>: <A href='?src=\ref[];active=0'>Burst Fire</A><br></TT>", (src.passive ? text("<A href='?src=\ref[];passive=0'>On</A>", src) : text("<A href='?src=\ref[];passive=1'>Off</A>", src)), src)
user << browse(dat, "window=infra_sensor")
onclose(user, "infra_sensor")
return
/obj/item/device/infra_sensor/Topic(href, href_list)
..()
if (usr.stat || usr.restrained())
return
if ((usr.contents.Find(src) || (usr.contents.Find(src.master) || ((get_dist(src, usr) <= 1) && istype(src.loc, /turf)))))
usr.machine = src
if (href_list["passive"])
src.passive = !( src.passive )
if(passive && !(src in processing_items))
processing_items.Add(src)
if (href_list["active"])
spawn( 0 )
src.burst()
return
if (!( src.master ))
if (istype(src.loc, /mob))
attack_self(src.loc)
else
for(var/mob/M in viewers(1, src))
if (M.client)
src.attack_self(M)
else
if (istype(src.master.loc, /mob))
src.attack_self(src.master.loc)
else
for(var/mob/M in viewers(1, src.master))
if (M.client)
src.attack_self(M)
src.add_fingerprint(usr)
else
usr << browse(null, "window=infra_sensor")
onclose(usr, "infra_sensor")
return
return
/obj/item/device/infra/proc/hit()
if (src.master)
spawn()
var/datum/signal/signal = new
signal.data["message"] = "ACTIVATE"
src.master.receive_signal(signal)
qdel(signal)
return
else
for(var/mob/O in hearers(null, null))
O.show_message(text("[bicon()] *beep* *beep*", src), 3, "*beep* *beep*", 2)
return
/obj/item/device/infra/process()
if(!state)
processing_items.Remove(src)
return null
if ((!( src.first ) && (src.state && (istype(src.loc, /turf) || (src.master && istype(src.master.loc, /turf))))))
var/obj/beam/i_beam/I = new /obj/beam/i_beam( (src.master ? src.master.loc : src.loc) )
//boutput(world, "infra spawning beam : \ref[I]")
I.master = src
I.density = 1
I.dir = src.dir
step(I, I.dir)
if (I)
//boutput(world, "infra: beam at [I.x] [I.y] [I.z]")
I.density = 0
src.first = I
//boutput(world, "infra : vis_spread")
I.vis_spread(src.visible)
spawn( 0 )
if (I)
//boutput(world, "infra: setting limit")
I.limit = 20
//boutput(world, "infra: processing beam \ref[I]")
I.process()
return
if (!( src.state ))
//src.first = null
qdel(src.first)
return
/obj/item/device/infra/attackby(obj/item/device/radio/signaler/S as obj, mob/user as mob)
if ((!( istype(S, /obj/item/device/radio/signaler) ) || !( S.b_stat )))
return
var/obj/item/assembly/rad_infra/R = new /obj/item/assembly/rad_infra( user )
S.set_loc(R)
R.part1 = S
S.layer = initial(S.layer)
user.u_equip(S)
user.put_in_hand_or_drop(R)
S.master = R
src.master = R
src.layer = initial(src.layer)
user.u_equip(src)
src.set_loc(R)
R.part2 = src
R.dir = src.dir
src.add_fingerprint(user)
return
/obj/item/device/infra/attack_self(mob/user as mob)
user.machine = src
var/dat = text("<TT><B>Infrared Laser</B><br><B>Status</B>: []<BR><br><B>Visibility</B>: []<BR><br></TT>", (src.state ? text("<A href='?src=\ref[];state=0'>On</A>", src) : text("<A href='?src=\ref[];state=1'>Off</A>", src)), (src.visible ? text("<A href='?src=\ref[];visible=0'>Visible</A>", src) : text("<A href='?src=\ref[];visible=1'>Invisible</A>", src)))
user << browse(dat, "window=infra")
onclose(user, "infra")
return
/obj/item/device/infra/Topic(href, href_list)
..()
if (usr.stat || usr.restrained())
return
if ((usr.contents.Find(src) || usr.contents.Find(src.master) || in_range(src, usr) && istype(src.loc, /turf)))
usr.machine = src
if (href_list["state"])
src.state = !( src.state )
src.icon_state = text("infrared[]", src.state)
if (src.master)
src.master:c_state(src.state, src)
if(state && !(src in processing_items))
processing_items.Add(src)
if (href_list["visible"])
src.visible = !( src.visible )
spawn( 0 )
if (src.first)
src.first.vis_spread(src.visible)
return
if (!( src.master ))
if (istype(src.loc, /mob))
attack_self(src.loc)
else
for(var/mob/M in viewers(1, src))
if (M.client)
src.attack_self(M)
//Foreach goto(211)
else
if (istype(src.master.loc, /mob))
src.attack_self(src.master.loc)
else
for(var/mob/M in viewers(1, src.master))
if (M.client)
src.attack_self(M)
//Foreach goto(287)
else
usr << browse(null, "window=infra")
onclose(usr, "infra")
return
return
/obj/item/device/infra/attack_hand()
//src.first = null
qdel(src.first)
..()
return
/obj/item/device/infra/Move()
var/t = src.dir
..()
src.dir = t
//src.first = null
qdel(src.first)
return
/obj/item/device/infra/verb/rotate()
set src in usr
src.dir = turn(src.dir, 90)
return
*/
/////////////////////////////////////// Remote signaller/tripwire assembly /////////////////////////////////
//SN src = null
//src.part2.first = null
// 2 ain't huge so let's give ourselves a little boost
//Main os program: Provides old pda interface and four programs including file browser, notes, messenger, and atmos scan
//Note vars
//0 For note editor, 1 for note browser
//If set, save to this file.
//Which folder are we looking in?
//Messenger vars
//To beep or not to beep, that is the question
//0 for pda list, 1 for messages
//Custom ringtone
//Current messages in memory (Store as separate file only later??)
//world.time of last send for both messages and file sending.
//net id of last dude to request a file transfer
//Who are we trying to send a file to?
//File browser vars
//Current file to copy
//Same as regular but with messaging off
//boutput(world, "[command_list["command"]]")
//?src=\ref[src];mode=1'>Notekeeper</a></li>"
//?src=\ref[src];mode=2'>Messenger</a></li>"
//?src=\ref[src];mode=3'>File Browser</a></li>"
//?src=\ref[src];mode=4'>Atmospheric Scan</a></li>"
//?src=\ref[src];scanner=1'>[src.master.scan_program.name]</a>" : "None loaded"]</li>"
// . += "<li><a href='byond://?src=\ref[src];flight=1'>[src.master.fon ? "Disable" : "Enable"] Flashlight</a></li>"
//?src=\ref[src];mode=5'>Module Config</a></li>"
//Note Program. Can save/load note files.
//?src=\ref[src];note_func=lock'>Lock</a><br>"
//?src=\ref[src];input=note'>Edit</a>"
//?src=\ref[src];note_func=new'>New File</a>"
//?src=\ref[src];note_func=save'>Save</a>"
//?src=\ref[src];note_func=switchmenu'>Load</a><br>"
//?src=\ref[src];note_func=switchmenu'>Back</a>"
//?src=\ref[src];note_func=drive'>[src.note_folder.holder == src.master.hd ? "MAIN" : "CART"]</a>\]<br>"
//?src=\ref[src];target=\ref[T];note_func=load'>[T.name]</a></td>"
//Messenger. Uses Radio. Is a messenger.
//Remove existing alerts
//?src=\ref[src];message_func=ringer'>Ringer: [src.message_silent == 1 ? "Off" : "On"]</a> | "
//?src=\ref[src];message_func=on'>Send / Receive: [src.message_on == 1 ? "On" : "Off"]</a> | "
//?src=\ref[src];input=tone'>Set Ringtone</a> | "
//?src=\ref[src];message_mode=1'>Messages</a><br>"
//?src=\ref[src];message_func=scan'>Scan</a></font><br>"
//?src=\ref[src];input=message;target=[page_departments[department_id]];department=1'>DEPT-[department_id]</a></li>"
//I guess this can happen if somebody copies the system file.
//?src=\ref[src];input=message;target=[P_id]'>PDA-[P_name]</a>"
//?src=\ref[src];input=send_file;target=[P_id]'>*Send File*</a>)"
//?src=\ref[src];message_func=clear'>Clear</a> | "
//?src=\ref[src];message_mode=0'>Back</a><br>"
//File Browser.
//To-do(?): Setting "favorite" programs to access straight from main menu
//Not sure how needed it is, not like they have to go through 500 subfolders or whatever
//?src=\ref[src];target=\ref[src.browse_folder];browse_func=paste'>Paste</a><br>"
//?src=\ref[src];target=\ref[F];browse_func=open'>[F.name]</a></td>"
//?src=\ref[src];target=\ref[F];browse_func=delete'>Del</a></td>"
//?src=\ref[src];target=\ref[F];input=rename'>Rename</a></td>"
//?src=\ref[src];target=\ref[F];browse_func=copy'>Copy</a></td>"
//?src=\ref[src];target=\ref[other_drive_folder];browse_func=paste'>Paste</a><hr>"
//?src=\ref[src];target=\ref[F];browse_func=open'>[F.name]</a></td>"
//?src=\ref[src];target=\ref[F];browse_func=delete'>Del</a></td>"
//?src=\ref[src];target=\ref[F];input=rename'>Rename</a></td>"
//?src=\ref[src];target=\ref[F];browse_func=copy'>Copy</a></td>"
//Atmos Scanner
// Replaced with global proc (Convair880).
// else if(href_list["flight"])
// src.master.toggle_light()
//Message sending delay
//var/obj/item/device/pda2/P = locate(href_list["target"])
//if(!P || !istype(P) || !P.net_id)
//return
//Give a file send request thing for current copied file.
//File sending delay.
//signal.data["sender"] = src.master.net_id
//Messenger specific topic junk
//signal.data["sender"] = src.master.net_id
//Note program specific topic junk
//qdel(F)
//File browser specific topic junk
//Given a file on another system and the other system itself.
//Check to see if it's our ~mailgroup~
//src.master.pdasay_autocomplete += sender
//Only add the reply link if the sender is another pda2.
//?src=\ref[src];input=message;target=[signal.data["sender"]]'>[sender]</a>"
//Don't beep if set to silent.
//Alert the person holding us.
//?src=\ref[src];input=message;norefresh=1;target=[signal.data["sender"]]'>[sender]</a>:</b></i> [signal.data["message"]]")
//src.master.pdasay_autocomplete += sendername
//?src=\ref[src];input=message;target=[sender]'>[sendername]</a>:</b></i><br>
//?src=\ref[src];message_func=accfile;sender=[sender]'>[filename]</a>
//Same as with messages
// this is now in network_hook
//master.pdasay_autocomplete += sender_name
//?src=\ref[src];mode=0'>Main Menu</a>"
//?src=\ref[src.master];refresh=1'>Refresh</a>"
//?src=\ref[src.master];eject_cart=1'>Eject [src.master.cartridge]</a>"
//?src=\ref[src.master];eject_id_card=1'>Eject [src.master.ID_card]</a>"
//signal.data["sender"] = src.master.net_id
//base pda program
//Does the master PDA need to be on the processing item list?
//boutput(world, "Holder [holder] not in [master] of prg:[src]")
//maybe remove this, I haven't found a good use for it yet
//?src=\ref[src];quit=1'>Main Menu</a>"
//?src=\ref[src.master];refresh=1'>Refresh</a>"
//else
//qdel(signal)
//boutput(world, "Setting [src.holder] to [newholder]")
// called when a program is run
// to allow promiscuous mode
// src.master.processing_programs.Remove(src)
//CONTENTS
//Base bot control program
//Secbot control
//Mulebot control
// list of bots
// the active bot; if null, show bot list
// the status signal sent by the bot
//Just for sending, adjust what the actual pda hooks to for receive
//boutput(world, "<h5>Adding [master]@[master.loc]:[master.bot_freq],[master.beacon_freq]")
// list of bots
//?src=\ref[src];op=control;bot=\ref[B]'>[B] at [get_area(B)]</A><BR>"
//?src=\ref[src];op=scanbots'>Scan for active bots</A><BR>"
// bot selected, control it
//?src=\ref[src];op=control;bot=\ref[src.active]'><i>refresh</i></A>)<BR>"
//?src=\ref[src];op=stop'>Stop Patrol</A>\] "
//?src=\ref[src];op=go'>Start Patrol</A>\] "
//?src=\ref[src];op=summon'>Summon Bot</A>\]<BR>"
//?src=\ref[src];op=botlist'>Return to bot list</A>"
// find all bots
// list of bots
//?src=\ref[src];op=control;bot=\ref[B]'>[B] at [get_area(B)]</A><BR>"
//?src=\ref[src];op=scanbots'>Scan for active bots</A><BR>"
// bot selected, control it
//?src=\ref[src];op=control;bot=\ref[src.active]'><i>refresh</i></A>)<BR>"
//?src=\ref[src];op=unload'><i>unload</i></A>)" ]<BR>"
//?src=\ref[src];op=scanbeacons'>Scan destinations</a><br>"
//?src=\ref[src];op=setdest'><i>set</i></A>)<BR>"
//?src=\ref[src];op=retoff'>Off</A>" : "(<A href='byond://?src=\ref[src];op=reton'><i>On</i></A>) <B>Off</B>"]<BR>"
//?src=\ref[src];op=pickoff'>Off</A>" : "(<A href='byond://?src=\ref[src];op=pickon'><i>On</i></A>) <B>Off</B>"]<BR><BR>"
//?src=\ref[src];op=stop'>Stop</A>\] "
//?src=\ref[src];op=go'>Proceed</A>\] "
//?src=\ref[src];op=home'>Return Home</A>\]<BR>"
//?src=\ref[src];op=botlist'>Return to bot list</A>"
// find all bots
//CONTENTS:
//Captain cart
//Head cart
//Research Director cart
//Medical cart
//Security cart
//Toxins cart
//QM cart
//Clown cart
//Janitor cart
//Atmos cart
//Syndicate cart
//Botanist cart
//Nuclear cart (syndicate cart with syndicate shuttle door control)
//Network diagnostic cart
//Game Carts
//src.root.add_file( new /datum/computer/file/pda_program/hologram_control(src))
//src.root.add_file( new /datum/computer/file/pda_program/door_control/syndicate(src))
// Network Diagnostics PDA cart programs
// pingtool
// packet sniffer
// packet sender
//Frequency signal is sent at, should be kept within normal radio ranges.
//?src=\ref[src];adj_freq=-100'>-</a>
//?src=\ref[src];adj_freq=-10'>-</a>
//?src=\ref[src];adj_freq=-2'>-</a>
//?src=\ref[src];set_freq=1'>[format_frequency(send_freq)]</a>
//?src=\ref[src];adj_freq=2'>+</a>
//?src=\ref[src];adj_freq=10'>+</a>
//?src=\ref[src];adj_freq=100'>+</a></tt> | "}
//?src=\ref[src];range=1'>+</A>"
//?src=\ref[src];range=-1'>-</A> Med <A href='byond://?src=\ref[src];range=1'>+</A>"
//?src=\ref[src];range=-1'>-</A> Max +"
//?src=\ref[src];send=1'>Send ping</A><BR><HR>"
//boutput(world, "[master.net_id] Recieved signal from [signal.source] ([get_dist(master,signal.source)])")
//
//for(var/x in signal.data)
// boutput(world, "[x] = [signal.data[x]]")
//boutput(world, "---------------")
//?src=\ref[src];adj_freq=-100'>-</a>
//?src=\ref[src];adj_freq=-10'>-</a>
//?src=\ref[src];adj_freq=-2'>-</a>
//?src=\ref[src];set_freq=1'>[format_frequency(scan_freq)]</a>
//?src=\ref[src];adj_freq=2'>+</a>
//?src=\ref[src];adj_freq=10'>+</a>
//?src=\ref[src];adj_freq=100'>+</a></tt> | "}
//?src=\ref[src];range=1'>+</A>"
//?src=\ref[src];range=-1'>-</A> Med <A href='byond://?src=\ref[src];range=1'>+</A>"
//?src=\ref[src];range=-1'>-</A> Max +"
//?src=\ref[src];run=1'>Start</A>"
//?src=\ref[src];run=0'>Stop</A>"
//?src=\ref[src];clear=1'>Clear</A><BR><HR>"
//?src=\ref[src];run=1'>Start</A>"
//?src=\ref[src];run=0'>Stop</A>"
//?src=\ref[src];clear=1'>Clear</A><BR>"
/////
//boutput(world, "[master.net_id] Recieved signal @[rx_freq] from [signal.source] ([get_dist(master,signal.source)])")
//for(var/x in signal.data)
// boutput(world, "[x] = [signal.data[x]]")
//boutput(world, "----")
/////
//boutput(world, "====")
// look for detomax packet and obscure it (so it won't be easy to copy)
//?src=\ref[src];adj_freq=-100'>-</a>
//?src=\ref[src];adj_freq=-10'>-</a>
//?src=\ref[src];adj_freq=-2'>-</a>
//?src=\ref[src];set_freq=1'>[format_frequency(send_freq)]</a>
//?src=\ref[src];adj_freq=2'>+</a>
//?src=\ref[src];adj_freq=10'>+</a>
//?src=\ref[src];adj_freq=100'>+</a></tt> | "}
//?src=\ref[src];range=1'>+</A>"
//?src=\ref[src];range=-1'>-</A> Med <A href='byond://?src=\ref[src];range=1'>+</A>"
//?src=\ref[src];range=-1'>-</A> Max +"
//?src=\ref[src];edit=1;code=[key]'>(edit)</A>"
//?src=\ref[src];delete=1;code=[key]'>(delete)</A></small><BR>"
//?src=\ref[src];add=1;'>(add new)</A></small><BR>"
//?src=\ref[src];send=1'>Send Packet</A><BR>"
// 114.1
// 148.9
//CONTENTS:
//Robustris
//Robustris block datum
//Arcade game
//CodeBreaker (aka Mastermind)
//Don't bog down everything spinning blocks!!
/* new disposing() pattern should handle this. -singh
Del()
src.clear_blocks()
..()
*/
//?src=\ref[src];resume=1'>Resume</a></b> | "
//?src=\ref[src];pause=1'>Pause</a></b>"
//?src=\ref[src];newgame=1'>New Game</a></b>"
//?src=\ref[src];movedir=" + ourKey;
// drsingh for index out of bounds
//Ugh the process loop for items is so slow most of the time
//A
//D
//S
//W
//qdel(src.blockmap)
//Square block
//L block
//T block
//That stupid Z block
//The rare and treasured line block
//Move a block left or right however far.
//I guess we CAN move! Time to all move together!
//Determine and test new block location for collision.
//If everything is OK then go ahead and move them.
//Don't even bother trying!
//Coordinates relative to an origin block.
//Temporary message, for attack messages, etc
//Player health/attack points
//Enemy health/attack points
//Player cannot attack/heal while set
//?src=\ref[src];newgame=1'>New Game</a>"
//?src=\ref[src];attack=1'>Attack</a> | "
//?src=\ref[src];heal=1'>Heal</a> | "
//?src=\ref[src];charge=1'>Recharge Power</a>"
//Reset everything
//?src=\ref[src];menu=1'>Main Menu</a>"
//?src=\ref[src];guess=1'>Guess</a>"
//?src=\ref[src];giveup=1'>Give Up</a>"
//?src=\ref[src];newgame=1'>New Game</a></h3></center>"
//?src=\ref[src];difficulty=1'>Difficulty: [src.difficulty]</a></h3></center>"
//lockcode_list += "[copytext(bp.lockcode,i+1,i+2)]"
//correct_char++
//continue
//CONTENTS
//Module base.
//Flashlight module.
//T-ray scanner module.
//Computer 3 Emulator / Associated Bits
//Should we have a line in the main menu?
//Do we support a big config page?
//Return string as part of PDA main menu, ie easy way to toggle a function. One line!!
//Are we currently on?
//How bright are we?
//?src=\ref[src];toggle=1'>[src.on ? "Disable" : "Enable"] Flashlight</a>"
//?src=\ref[src];toggle=1'>[src.on ? "Disable" : "Enable"] T-Scanner</a>"
//The advanced pea-green monochrome lcd of tomorrow.
// slap an ID card into that thang
// so we don't need to replace all the dang checks for ID cards
//current cartridge
//Can we insert a module now?
//Bot control frequency
//Beacon frequency for locating beacons (I love beacons)
//Hello dude intercepting our radio transmissions, here is a number that is not just \ref
//Cartridge contains job-specific programs
//PDAs don't have much work room at all, really.
//Needs an operating system to...operate!!
//Do we search the cart for a scanprog to start loaded?
//Module to have installed on spawn.
//What special mail group the PDA is part of.
// can't be destroyed with detomatix
// should be merged with command
// merge with command
// merge with command
//Clown PDA is slippery.
//boutput(world, wincheck)
//?src=\ref[src];close=1'>Close</a>"
//?src=\ref[src];eject_cart=1'>Eject [src.cartridge]</a>"
//?src=\ref[src];eject_id_card=1'>Eject [src.ID_card]</a>"
//?src=\ref[src];refresh=1'>Retry</a>"
//?src=\ref[src];eject_cart=1'>Eject [src.cartridge]</a><br>"
//?src=\ref[src];eject_id_card=1'>Eject [src.ID_card]</a>"
// special programs can receive all signals
// Replaced with global proc (Convair880).
//else
//qdel(signal)
//Toggle the built-in flashlight
//Add alert overlay and beep
// boutput(world, "Not in src")
//boutput(world, "Deleting [file]...")
//boutput(world, "Cannot delete :(")
//Don't delete the running program you jerk
//boutput(world, "Now calling del on [file]...")
//qdel(file)
//dispose()
//src.dispose()
//dispose()
//src.dispose()
// Contains:
// - Portable machinery remote partent
// - Port-a-Brig remote
// - Port-a-Medbay remote
// - Port-a-NanoMed remote
// - Port-a-Sci remote
// First attempt at coding a PDA program. It's probably not very good, let's face it.
// The separate remotes have also been updated and retained as a backup in porters.dm (Convair880).
// Type of machinery the remote is controlling.
// For HTML stuff.
// Selected machinery. If null, show global list instead.
// In relation to world time.
// As to avoid a separate lookup for every remote.
// Failure states:
// 0: Tele-blocked loc, src/dest.loc/PDA is null or related errors.
// 1: Pass.
// 2: On cooldown.
// 3: There's an occupant and type of machinery requires lock to be engaged.
// 4: Obstacle at dest.loc.
// 5: Obstacle at home.loc.
// If we're in a pod etc and want to summon the device, or if the machinery is on the MULE.
// Both can have unexpected and bad results.
// It's not a Port-a-Sci, okay.
// It's not a Port-a-Sci, okay.
// We don't have to loop through the PDA.loc checks as well if we send the device back to its home turf.
// Somebody will find a way to abuse it if I don't put this here.
// Somebody will find a way to abuse it if I don't put this here.
// Probably quite the mess, but I wanted to see if identical code x4 could be averted for the HTML generation as well.
// The portable machinery objects are very similar after all.
// Show us the list.
//?src=\ref[src];op=control;machinery=\ref[src.our_machinery]'>[src.our_machinery] at [get_area(src.our_machinery)]</A><BR>"
//?src=\ref[src];op=scanmachinery'>Scan for linkable machinery</A><BR>"
// Control a particular piece of machinery.
//?src=\ref[src];op=control;machinery=\ref[src.active]'><i>refresh</i></A>)<BR>"
//?src=\ref[src];op=lock'>Toggle lock</A>\] "
//?src=\ref[src];op=summon'>Summon</A>\] "
//?src=\ref[src];op=return'>Send to home turf</A>\]<BR>"
//?src=\ref[src];op=machinerylist'>Return to list</A>"
//?src=\ref[src];op=summon'>Summon</A>\] "
//?src=\ref[src];op=return'>Send to home turf</A>\]<BR>"
//?src=\ref[src];op=machinerylist'>Return to list</A>"
//?src=\ref[src];op=summon'>Summon</A>\] "
//?src=\ref[src];op=return'>Send to home turf</A>\]<BR>"
//?src=\ref[src];op=machinerylist'>Return to list</A>"
//?src=\ref[src];op=summon'>Summon</A>\] "
//?src=\ref[src];op=return'>Send to home turf</A>\]<BR>"
//?src=\ref[src];op=machinerylist'>Return to list</A>"
//?src=\ref[src];op=machinerylist'>Return to list</A>"
// Get list of linkable machinery.
// Z-level check bypass for Port-a-Sci.
// I have sinned, though the BAD OPERATOR might be unproblematic here.
// Z-level check bypass for Port-a-Sci.
// Don't show stuff in "somewhere", okay.
// Damn forced line breaks.
// Don't show stuff in "somewhere", okay.
// Damn forced line breaks.
// Don't show stuff in "somewhere", okay.
// I suppose this device would be sorta useless with tele-block checks?
/*var/turf/M_loc = get_turf(M)
if (M && M_loc && isturf(M_loc) && isrestrictedz(M_loc.z)) // Don't show stuff in "somewhere", okay.
continue*/
//CONTENTS:
//Generic records
//Security records
//Medical records
//General
//Security/Medical/Whatever
//To-do: editing arrest status/etc from pda.
//?src=\ref[src];select_rec=\ref[R]'>[R.fields["id"]]: [R.fields["name"]]<br>"
//?src=\ref[src];mode=0'>Back</a><br>"
//?src=\ref[src];select_rec=\ref[R]'>[R.fields["id"]]: [R.fields["name"]]<br>"
//?src=\ref[src];mode=0'>Back</a><br>"
//CONTENTS:
//Base scanner stuff
//Health scanner
//Forensic scanner
//Reagent scanner
//Plant scanner
//Health analyzer program
//Forensic scanner
// Moved to scanprocs.dm to cut down on code duplication (Convair880).
//Reagent scanning program
//Plant scanner
// Moved to scanprocs.dm to cut down on code duplication (Convair880).
//Assorted small programs not worthy of their own file
//CONTENTS:
//~*~Banking Software~*~
//Crew Manifest viewer
//Status display controller
//Remote signaling program
//Cargo orders monitor
//Bicycle Horn Synth
//Janitor mop-locating program
//Remote door control program
//Atmospherics Alert-checking program
//Hydroponics plant monitor
//Emergency alert program
//Self destruct detomatix program
//Old-style detomatix program
//Detomatix Detomanual
//Ticket writer
//Cargo request
//Banking
//todo
//Manifest
//Status Display
// For custom messages on the displays.
//Signaler
//Frequency signal is sent at, should be kept within normal radio ranges.
//No signal spamming etc
//?src=\ref[src];send=1'>Send Signal</A><BR>
//?src=\ref[src];adj_freq=-10'>-</a>
//?src=\ref[src];adj_freq=-2'>-</a>
//?src=\ref[src];adj_freq=2'>+</a>
//?src=\ref[src];adj_freq=10'>+</a><br>
//?src=\ref[src];adj_code=-5'>-</a>
//?src=\ref[src];adj_code=-1'>-</a>
//?src=\ref[src];adj_code=1'>+</a>
//?src=\ref[src];adj_code=5'>+</a><br>"}
//signal.encryption = send_code
//Supply record monitor
//Clown horn emulator. honk.
//?src=\ref[src];adj_volume=-1'>-</a> "
//?src=\ref[src];adj_volume=1'>+</a> "
//TO-DO: Change to use radio system I guess
//Ask the atmos alert computer for alert data.
//Hydroponics plant monitor.
//boutput(world, "<h5>Adding [master]@[master.loc]:[report_freq]")
//Emergency alert program
//Whoever runs this gets to explode.
//oh boy it's old-style detomatixing
//Don't let jerks copy the program to have extra charges.
//?src=\ref[src];import=1'>Import PDA List</a></font><br>"
//I guess this can happen if somebody copies the system file.
//?src=\ref[src];detonate=[P_id]'>*DETONATE*</a>)"
//Security ticket writer - not really a small prog any more but oh well
//menu
//?src=\ref[src];ticket=1'>Issue Ticket</a> \]<br>"
//?src=\ref[src];fine=1'>Issue Fine</a> \]<br><br>"
//?src=\ref[src];viewtickets=1'>View Tickets</a> \]<br>"
//?src=\ref[src];viewfinerequests=1'>Requested</a> | <a href='byond://?src=\ref[src];viewoutstandingfines=1'>Unpaid</a> | <a href='byond://?src=\ref[src];viewpaidfines=1'>Paid</a> \]<br>"
//tickets
//?src=\ref[src];back=1'>Back</a>"
// this is also bad
//requested fines
//there is probably a better way of doing this
//?src=\ref[src];back=1'>Back</a>"
//?src=\ref[src];approve=\ref[F]'>Approve Fine</a>"
//unpaid fines
//?src=\ref[src];back=1'>Back</a>"
//paid fines
//?src=\ref[src];back=1'>Back</a>"
//?src=\ref[src];ok=1'>Ok</a>"
//there is probably a better way of doing this
/* for(var/datum/data/record/S in data_core.security) //there is probably a better way of doing this too
if(S.fields["name"] == ticket_target)
if(S.fields["notes"] == "No notes.")
S.fields["notes"] = ticket_text
else S.fields["notes"] += ticket_text
break*/
//there is probably a better way of doing this
//this too
//there is probably a better way of doing this
//made global so fines can use it too, might also be useful for other stuff
//cargo request
// Have to send the type instead of a reference to the obj because it would get caught by the garbage collector. oh well.
// pda alert ////////
//////////////////
// Powersink - used to drain station power
// amount of power to drain per tick
// has drained this much power
// maximum power that can be drained before exploding
// 0 = off, 1=clamped (off), 2=operating
// the attached cable
// found a powernet, so drain up to max power from it
// if tried to drain more than available on powernet
// now look for APCs and drain their cells
//Prox-detonated beaker assemblies
//Prox-detonated single-tank bombs
//Proximity-detonated beaker assemblies
//Radio-detonated single-tank bombs
// Cannot be picked up by radio_brain bioeffect.
//sends a signal, like to set off a bomb or electrocute someone
// only 2/second/radio
// Moved initializaiton to world/New
//?src=\ref[src];wires=4'>[src.wires & 4 ? "Cut" : "Mend"] Wire</A><BR>
//?src=\ref[src];wires=2'>[src.wires & 2 ? "Cut" : "Mend"] Wire</A><BR>
//?src=\ref[src];wires=1'>[src.wires & 1 ? "Cut" : "Mend"] Wire</A><BR>-------<BR>"}
//?src=\ref[src];removemodule=[sayToken]'>Remove</a><br>"
//?src=\ref[src];talk=0'>Engaged</A>" : "<A href='byond://?src=\ref[src];talk=1'>Disengaged</A>"]<BR>
//?src=\ref[src];listen=0'>Engaged</A>" : "<A href='byond://?src=\ref[src];listen=1'>Disengaged</A>"]<BR>
//?src=\ref[src];freq=-10'>-</A>
//?src=\ref[src];freq=-2'>-</A>
//?src=\ref[src];freq=2'>+</A>
//?src=\ref[src];freq=10'>+</A><BR>"}
//..()
// Band-aid fix for intercoms, RE 'bounds_dist' check in the 'in_range' proc. Feel free to improve the implementation (Convair880).
// now transform the regular radio, into a (disguised)syndicate uplink!
// According to a pair of DEBUG calls set up for testing, no radio jammer check for the src radio was performed.
// As improbable as this sounds, there are bug reports too to back up the findings. So uhm...
// if (last_transmission && world.time < (last_transmission + TRANSMISSION_DELAY))
// return
// :v
//Frequency to display on radio broadcast messages
// Don't let them monitor Syndie headsets. You can get the radio_brain bioeffect at the start of the round, basically.
// masked name or no real name
// normal message
// voice message
// garbled message
// Receiving mobs
//istype(M.wear_mask, /obj/item/clothing/mask/gas/voice))
//DEBUG("Message transmitted. Frequency: [display_freq]. Source: [src] at [log_loc(src)]. Receiver: [R] at [log_loc(R)].")
//?src=\ref[src];track2=\ref[R];track=\ref[M]'>[M.name] ([eqjobname]) </a>[part_b][M.say_quote(messages[1])][part_c]"
//?src=\ref[src];track2=\ref[R];track=\ref[M]'>[real_name ? real_name : M.real_name] ([eqjobname]) </a>[part_b][M.say_quote(messages[1])][part_c]"
//?src=\ref[src];track2=\ref[R];track=\ref[M]'>[M.voice_name] ([eqjobname]) </a>[part_b][M.voice_message][part_c]"
//?src=\ref[src];track2=\ref[R];track=\ref[M]'>[M.voice_name]</a>[part_b][M.say_quote(messages[2])][part_c]"
// Hope I didn't butcher this, but I couldn't help but notice some odd stuff going on when I tried to debug radio jammers (Convair880).
// Simple frequency match. The only check that used to be here.
//DEBUG("Match found for transmission from [R] at [log_loc(R)] (simple frequency match)")
// Secure channel lookup when R.frequency != src.frequency. According to DEBUG calls set up for testing,
// this meant the receiving radio would decline the message even though both share a secure channel.
// Secure channel match. Easy.
//DEBUG("Match found for transmission from [R] at [log_loc(R)] (list/devices match)")
// Sender didn't use a secure channel prefix, giving us the 145.9 radio frequency datum.
// The devices list is useless here, but we can still receive the message if one of our
// secure channels happens to have the same frequency as the sender's radio.
//DEBUG("Match found for transmission from [R] at [log_loc(R)] (frequency compare)")
// changed so station bounce radios will be loud and headsets will only be heard on their tile
// modified so that a mob holding the radio is always a hearer of it
// this fixes radio problems when inside something (e.g. mulebot)
//modified so people in the same object as it can hear it
//Most convoluted string of the year award 2013
//Foreach goto(83)
// var/e_pads = 0.0
// This doesn't seem to do anything (Convair880).
/*if (istype(W, /obj/item/screwdriver))
src.e_pads = !( src.e_pads )
if (src.e_pads)
user.show_message("<span style=\"color:blue\">The electric pads have been exposed!</span>")
else
user.show_message("<span style=\"color:blue\">The electric pads have been reinserted!</span>")
src.add_fingerprint(user)
else*/
//..()
//(signal.encryption != code))
// Added (Convair880).
//?src=\ref[src];freq=-10'>-</A>
//?src=\ref[src];freq=-2'>-</A> [format_frequency(src.frequency)]
//?src=\ref[src];freq=2'>+</A>
//?src=\ref[src];freq=10'>+</A><BR>
//?src=\ref[src];code=-5'>-</A>
//?src=\ref[src];code=-1'>-</A> [src.code]
//?src=\ref[src];code=1'>+</A>
//?src=\ref[src];code=5'>+</A><BR>
// ****************************************************
//?src=\ref[src];listen=0'>Engaged</A>" : "<A href='byond://?src=\ref[src];listen=1'>Disengaged</A>"]<BR>
//?src=\ref[src];send=1'>Send Signal</A><BR>
//?src=\ref[src];freq=-10'>-</A>
//?src=\ref[src];freq=-2'>-</A>
//?src=\ref[src];freq=2'>+</A>
//?src=\ref[src];freq=10'>+</A><BR>
//?src=\ref[src];code=-5'>-</A>
//?src=\ref[src];code=-1'>-</A>
//?src=\ref[src];code=1'>+</A>
//?src=\ref[src];code=5'>+</A><BR>
//(signal.encryption != code))
// boutput(world, "/obj/.../signaler/r_signal([signal]) has master = [src.master] and type [(src.master?src.master.type : "none")]")
// boutput(world, "[src.airlock_wire] - [src] - [usr] - [signal]")
// src.master:r_signal(signal)
//Radio-detonated beaker assemblies
//Radio-detonated single-tank bombs
//signal.encryption = code
//..()
// secure_colors = list("#ff6600")
//placeholder so it sets up right
//?src=\ref[src];wires=4'>[src.wires & 4 ? "Cut" : "Mend"] Wire</A><BR>
//?src=\ref[src];wires=2'>[src.wires & 2 ? "Cut" : "Mend"] Wire</A><BR>
//?src=\ref[src];wires=1'>[src.wires & 1 ? "Cut" : "Mend"] Wire</A><BR>"}
//?src=\ref[src];talk=0'>Engaged</A>" : "<A href='byond://?src=\ref[src];talk=1'>Disengaged</A>"]<BR>
//?src=\ref[src];listen=0'>Engaged</A>" : "<A href='byond://?src=\ref[src];listen=1'>Disengaged</A>"]<BR>
//?src=\ref[src];freq=-10'>-</A>
//?src=\ref[src];freq=-2'>-</A>
//?src=\ref[src];freq=2'>+</A>
//?src=\ref[src];freq=10'>+</A><BR>
//?src=\ref[src];sfreq=-10'>-</A>
//?src=\ref[src];sfreq=-2'>-</A>
//?src=\ref[src];sfreq=2'>+</A>
//?src=\ref[src];sfreq=10'>+</A><BR>
// -------------------- VR --------------------
// --------------------------------------------
// ** preset intercoms to make mapping suck less augh **
//////////////////////////////////////////////// T-ray scanner //////////////////////////////////
//////////////////////////////////////// Forensic scanner ///////////////////////////////////
// PDA fits in a pocket, so why not the dedicated scanner (Convair880)?
// Scanning for fingerprints over the camera network is fun, but doesn't really make sense (Convair880).
// Moved to scanprocs.dm to cut down on code duplication (Convair880).
///////////////////////////////////// Health analyzer ////////////////////////////////////////
// someone made this sprite and then this was never changed to it for some reason???
///////////////////////////////////// Reagent scanner //////////////////////////////
/////////////////////////////////////// Atmos analyzer /////////////////////////////////////
// Moved to scanprocs.dm to cut down on code duplication (Convair880).
///////////////////////////////////////////////// Prisoner scanner ////////////////////////////////////
////General Records
//if( !istype(get_area(src), /area/security/prison) && !istype(get_area(src), /area/security/main))
// boutput(user, "<span style=\"color:red\">Device only works in designated security areas!</span>")
// return
//Update Information
//Update Information
/////Fingerprint record update
////Security Records
//qdel(signal)
/*****RM
/obj/item/device/timer/proc/c_state(n)
//src.icon_state = text("timer[]", n)
if(src.master)
src.master:c_state(n)
return
//*****
/obj/item/device/timer/process()
if (src.timing)
if (!last_tick) last_tick = world.time
var/passed_time = round(max(round(world.time - last_tick),10) / 10)
if (src.time > 0)
src.time -= passed_time
if(time<5)
src.c_state(2)
else
// they might increase the time while it is timing
src.c_state(1)
else
time()
src.time = 0
src.timing = 0
last_tick = 0
last_tick = world.time
if (!src.master)
if (istype(src.loc, /mob))
attack_self(src.loc)
else
for(var/mob/M in viewers(1, src))
if (M.client && (M.machine == src.master || M.machine == src))
src.attack_self(M)
else
if (istype(src.master.loc, /mob))
src.attack_self(src.master.loc)
else
for(var/mob/M in viewers(1, src.master))
if (M.client && (M.machine == src.master || M.machine == src))
src.attack_self(M)
else
// If it's not timing, reset the icon so it doesn't look like it's still about to go off.
src.c_state(0)
processing_items.Remove(src)
last_tick = 0
return
/obj/item/device/timer/attackby(obj/item/W as obj, mob/user as mob)
if (istype(W, /obj/item/device/radio/signaler) )
var/obj/item/device/radio/signaler/S = W
if(!S.b_stat)
return
var/obj/item/assembly/rad_time/R = new /obj/item/assembly/rad_time( user )
S.set_loc(R)
R.part1 = S
S.layer = initial(S.layer)
user.u_equip(S)
user.put_in_hand_or_drop(R)
S.master = R
src.master = R
src.layer = initial(src.layer)
user.u_equip(src)
src.set_loc(R)
R.part2 = src
R.dir = src.dir
src.add_fingerprint(user)
return
/obj/item/device/timer/attack_self(mob/user as mob)
..()
if (user.stat || user.restrained() || user.lying)
return
if ((src in user) || (src.master && (src.master in user)) || (get_dist(src, user) <= 1 && istype(src.loc, /turf)) || src.is_detonator_trigger())
user.machine = src
var/second = src.time % 60
var/minute = (src.time - second) / 60
var/detonator_trigger = src.is_detonator_trigger()
var/timing_links = (src.timing ? text("<A href='?src=\ref[];time=0'>Timing</A>", src) : text("<A href='?src=\ref[];time=1'>Not Timing</A>", src))
var/timing_text = (src.timing ? "Timing - controls locked" : "Not timing - controls unlocked")
var/dat = text("<TT><B>Timing Unit</B><br>[] []:[]<br><A href='?src=\ref[];tp=-30'>-</A> <A href='?src=\ref[];tp=-1'>-</A> <A href='?src=\ref[];tp=1'>+</A> <A href='?src=\ref[];tp=30'>+</A><br></TT>", detonator_trigger ? timing_text : timing_links, minute, second, src, src, src, src)
dat += "<BR><BR><A href='?src=\ref[src];close=1'>Close</A>"
user << browse(dat, "window=timer")
onclose(user, "timer")
else
user << browse(null, "window=timer")
user.machine = null
return
/obj/item/device/timer/proc/is_detonator_trigger()
if (src.master)
if (istype(src.master, /obj/item/assembly/detonator/) && src.master.master)
if (istype(src.master.master, /obj/machinery/portable_atmospherics/canister/) && in_range(src.master.master, usr))
return 1
return 0
/obj/item/device/timer/Topic(href, href_list)
..()
if (usr.stat || usr.restrained() || usr.lying)
return
var/can_use_detonator = src.is_detonator_trigger() && !src.timing
if (can_use_detonator || (src in usr) || (src.master && src.master in usr) || in_range(src, usr) && istype(src.loc, /turf))
usr.machine = src
if (href_list["time"])
src.timing = text2num(href_list["time"])
if(timing)
src.c_state(1)
if (!(src in processing_items))
processing_items.Add(src)
if (src.master && istype(master, /obj/item/device/transfer_valve))
logTheThing("bombing", usr, null, "[timing ? "initiated" : "defused"] a timer on a transfer valve at [log_loc(src.master)].")
message_admins("[key_name(usr)] [timing ? "initiated" : "defused"] a timer on a transfer valve at [log_loc(src.master)].")
else if (src.master && istype(src.master, /obj/item/assembly/time_ignite)) //Timer-detonated beaker assemblies
var/obj/item/assembly/rad_ignite/RI = src.master
logTheThing("bombing", usr, null, "[timing ? "initiated" : "defused"] a timer on a timer-igniter assembly at [log_loc(src.master)]. Contents: [log_reagents(RI.part3)]")
else if(src.master && istype(src.master, /obj/item/assembly/time_bomb)) //Timer-detonated single-tank bombs
logTheThing("bombing", usr, null, "[timing ? "initiated" : "defused"] a timer on a single-tank bomb at [log_loc(src.master)].")
message_admins("[key_name(usr)] [timing ? "initiated" : "defused"] a timer on a single-tank bomb at [log_loc(src.master)].")
else if (src.master && istype(src.master, /obj/item/mine)) // Land mine.
logTheThing("bombing", usr, null, "[timing ? "initiated" : "defused"] a timer on a [src.master.name] at [log_loc(src.master)].")
if (href_list["tp"])
var/tp = text2num(href_list["tp"])
src.time += tp
src.time = min(max(round(src.time), 0), 600)
if (can_use_detonator && src.time < 90)
src.time = 90
if (href_list["close"])
usr << browse(null, "window=timer")
usr.machine = null
return
if (!src.master)
if (istype(src.loc, /mob))
attack_self(src.loc)
else
for(var/mob/M in viewers(1, src))
if (M.client && (M.machine == src.master || M.machine == src))
src.attack_self(M)
else
if (can_use_detonator)
src.attack_self(usr)
if (istype(src.master.loc, /mob))
src.attack_self(src.master.loc)
else
for(var/mob/M in viewers(1, src.master))
if (M.client && (M.machine == src.master || M.machine == src))
src.attack_self(M)
src.add_fingerprint(usr)
else
usr << browse(null, "window=timer")
return
return
// because that's what it is exadv1 and don't you dare change it
/// HEH
// To stop a signal being spammed from a proxy sensor constantly going off or whatever
//var/obj/overlay/tank_one_overlay = new
//tank_one_overlay.icon = src.icon
//tank_one_overlay.icon_state = tank_one_icon
//var/obj/underlay/tank_two_overlay = new
//tank_two_overlay.icon = I
//var/obj/overlay/device_overlay = new
//device_overlay.icon = src.icon
//device_overlay.icon_state = device_icon
//lol
//Really weak
//I could also make it vent the gas, I guess, but then it'd be off-limits to non-antagonists. Challenge mode: make a safe ttb?
// temp = tank_two.air_contents.remove_ratio(0.5)
// tank_one.air_contents.merge(temp)
// In case one tank bursts
// this doesn't do anything but the timer etc. expects it to be here
// eventually maybe have it update icon to show state (timer, prox etc.) like old bombs
//Prox sensor handling.
//It didn't blow up!
//So we don't keep updating on a dud bomb forever.
//Prolonged use causes damage.
// Check spawn limits
// for combined dice rolls, up to 9 in a stack
// fine if I can't use proc/roll() then we'll all just have to suffer this
// so they don't all roll in the same order they went into the pile
// |= adds things to lists that aren't already present
// dumb but it helped test non-numeric rolls
// farte
// FINGERPRINT HOLDER
// All of this was phased out with the forensic scanner overhaul. Was useless anyway (Convair880).
// FINGERPRINT CARD
//Foreach goto(41)
//SN src = null
//W = null
//on or off
//Heh
// PantsNote: Dumping this shit in here until I'm sure it works.
//src.part1 = null
//src.part2 = null
//src.part1 = null
//src.part2 = null
//src.part3 = null
//src.part1 = null
//S = null
//S = null
//start a fire if possible
// PantsNote: Flamethrower disassmbly.
//S = null
// gets this from turf.dm turf/dblclick
//Passing user and target for logging purposes
//get up to 25 reagent
//Wire: Fix for Cannot read null.x
// a + (a + i) + (a + 2i) + (a + 3i) = T * a + (T * (T - 1)) / 2
//distribute if we can
//Too little pressure to spray
//so we don't burn the tile we be standin on
//Dense object -> dump the rest at the previous turf.
//reagentperturf = reagentlefttotransfer
// reagentperturf = reagentlefttotransfer
// if (halt)
// break
//currentturf.hotspot_expose(spray_temperature,2)
//Transfer reagents
///////////
////////////
// how is this safe?
// nicknacks for making fancy drinks
//Update the base cake icon
//Update the icing sprite
// Condiments
//Wire: fix for Cannot execute null.trans to()
//Wire: Fix for Cannot execute null.emote().
//ensure_reagent_holder()
//I guess the lunar style of pasta is with a tomato wine red sauce
//Ants aren't dumb enough to try to eat these.
//ensure_reagent_holder()
// Drinks
// heh
//in case the damage isn't enough to crit
// Ingredients
// path, name, strain, bypass resist
// does it?
// for thrown pies
// Can this just be eaten as-is?
// For genetics tracking.
// we might have moved during the sleep, so figure out where we are
//Griff
//Popcorn pops at about 232 degrees celsius.
//Pop that corn!!
//planttype = /datum/plant/chili
//planttype = /datum/plant/chili
//Apple on a stick
/* drsingh todo: peanut shells and requiring roasting shelling
attackby(obj/item/W as obj, mob/user as mob)
if (istype(W, /obj/item/kitchen/utensil/knife) || istype(W,/obj/item/knife_butcher))
if (src.icon_state == "potato")
user.visible_message("[user] peels [src].", "You peel [src].")
src.icon_state = "potato-peeled"
src.desc = "It needs to be cooked."
else if (src.icon_state == "potato-peeled")
user.visible_message("[user] chops up [src].", "You chop up [src].")
new /obj/item/reagent_containers/food/snacks/ingredient/chips(get_turf(src))
qdel (src)
else ..()
*/
//EGGPLANT FACT: They contain about 1.1% the nicotine of a cigarette per 100g.
// Weird alien fruit
// Bad food
//oh jesus
//Chance of a rad prize inside!
//Hello, here is a dumb hack to get around "you take a bite of cerealbox-'Pope Crunch'!"
// apparently there was a runtime error here, i'm guessing someone edited a cereal box's name?
//Roughly 350 C
//todo: get real sprite
// For forensics (Convair880).
//todo: get real sprite
// Foods
//Is this BOOBYTRAPPED CANDY?
//Special HALLOWEEN snacks
//Apple + stick creation
//Candied apples!
//Candy corn!!
//Candy bar variants
//to-do: mustard
//to-do: mustard
// boy i wish byond had static members doop doop
//#ifdef HALLOWEEN
//#endif
//var/base_url = "http://svn.slurm.us/public/spacestation13/misc/game_kit"
// for when you want something that "contains" a certain amount of an item
// how many of thing to start with, -1 for infinite
// how many can the thing hold total, -1 for infinite
// should be either a positive number or -1
// GIFTS
// bandaid fix for presents having no icon or name other than "spresent"
//Should only be one but whatever.
//cogwerks - burn vars
//if ( istype(W, /obj/item/sheet/glass) )
//SN src = null
// REINFORCED GLASS
// SHARDS
/****RM
//boutput(world, "New shard at [x],[y],[z]")
src.icon_state = pick("large", "medium", "small")
switch(src.icon_state)
if("small")
src.pixel_x = rand(1, 18)
src.pixel_y = rand(1, 18)
if("medium")
src.pixel_x = rand(1, 16)
src.pixel_y = rand(1, 16)
if("large")
src.pixel_x = rand(1, 10)
src.pixel_y = rand(1, 5)
else
return
/obj/item/shard/attackby(obj/item/W as obj, mob/user as mob)
..()
if (!( istype(W, /obj/item/weldingtool) && W:welding ))
return
W:eyecheck(user)
var/atom/A = new /obj/item/sheet/glass( user.loc )
if(src.material) A.setMaterial(src.material)
//SN src = null
qdel(src)
return
/obj/item/shard/HasEntered(AM as mob|obj)
if(ismob(AM))
var/mob/M = AM
if(ishuman(M))
var/mob/living/carbon/human/H = M
if(istype(H.mutantrace, /datum/mutantrace/abomination))
return
if(!H.shoes)
boutput(H, "<span style=\"color:red\"><B>You step in the broken glass!</B></span>")
playsound(src.loc, "sound/misc/glass_step.ogg", 50, 1)
var/obj/item/affecting = H.organs[pick("l_leg", "r_leg")]
H.weakened = max(3, H.weakened)
affecting.take_damage(5, 0)
H.UpdateDamageIcon()
H.updatehealth()
..()
// CRYSTAL
/obj/item/shard/crystal
name = "crystal shard"
icon = 'shards.dmi'
icon_state = "clarge"
desc = "A shard of Plasma Crystal. Very hard and sharp."
w_class = 3.0
force = 10.0
throwforce = 20.0
item_state = "shard-glass"
g_amt = 0
New()
src.icon_state = pick("clarge", "cmedium", "csmall")
switch(src.icon_state)
if("csmall")
src.pixel_x = rand(1, 18)
src.pixel_y = rand(1, 18)
if("cmedium")
src.pixel_x = rand(1, 16)
src.pixel_y = rand(1, 16)
if("clarge")
src.pixel_x = rand(1, 10)
src.pixel_y = rand(1, 5)
else
return
attackby(obj/item/W as obj, mob/user as mob)
if (!( istype(W, /obj/item/weldingtool) && W:welding ))
return
W:eyecheck(user)
var/atom/A = new /obj/item/sheet/glass/crystal( user.loc )
if(src.material) A.setMaterial(src.material)
qdel(src)
return
HasEntered(AM as mob|obj)
if(ismob(AM))
var/mob/M = AM
boutput(M, "<span style=\"color:red\"><B>You step on the crystal shard!</B></span>")
playsound(src.loc, "sound/misc/glass_step.ogg", 50, 1)
if(ishuman(M))
var/mob/living/carbon/human/H = M
var/obj/item/affecting = H.organs[pick("l_leg", "r_leg")]
H.weakened = max(3, H.weakened)
affecting.take_damage(10, 0)
H.UpdateDamageIcon()
H.updatehealth()
// 0 = passive, 1 aggressive, 2 neck, 3 kill
//src.affecting.losebreath++
//if (src.affecting.paralysis < 2)
// src.affecting.paralysis = 2
/*if (!disable_next_click) this actually is always gunna be a mob so we want to use next click even if disabled
*/
//src.affecting.losebreath++
//if (src.affecting.paralysis < 2)
// src.affecting.paralysis = 2
/*if (!disable_next_click) same as before
*/
////////////////////////////// Old-style grenades ///////////////////////////////////////
// Most grenades require a turf reference.
//Wire: Fix for Cannot read null.loc
//Wire: Fix for Cannot read null.loc
// detaching the proc - in theory
////////////////////////// Gimmick bombs /////////////////////////////////
//No queue
//Any channel
/////////////////////////////// Fireworks ///////////////////////////////////////
//////////////////////// Breaching charges //////////////////////////////////
// Yes, please (Convair880).
// Reliably blasts through doors.
// Breaching charges should be, you know, actually be decent at breaching walls and windows (Convair880).
// Yes, please (Convair880).
//////////////////////////////////////////
// PIPE BOMBS (INCLUDES CONSTRUCTION)
//////////////////////////////////////////
// B A D.
// cogwerks - changed the name
// dropping this to object-level so that I can use it for other things
// similar proc for mobs
//////////////////////////////// Parent ////////////////////////////
/////////////////////////////// Bullets for kinetic firearms /////////////////////////////////
// caliber list: update as needed
// 0.308 - rifles
// 0.357 - revolver
// 0.38 - detective
// 0.41 - derringer
// 0.72 - shotgun shell, 12ga
// 1.57 - 40mm grenade shell
// 1.58 - RPG-7 (Tube is 40mm too, though warheads are usually larger in diameter.)
// For dynamic desc and/or icon updates (Convair880).
// If dynamic = 1, the short icon_state has to be specified as well.
// This is needed to avoid duplicating empty magazines (Convair880).
// So we get dynamic updates right off the bat. Screw static descs.
// I tweaked this for improved user feedback and to support zip guns (Convair880).
// Some guns can have multiple calibers.
// Special treatment for zip guns, huh.
//DEBUG("Couldn't swap [K]'s ammo ([K.ammo.type]) with [A.type].")
// The gun may have been fired; eject casings if so.
// We can't delete A here, because there's going to be ammo left over.
// Some ammo boxes have dynamic icon/desc updates we can't get otherwise.
// No duplicating empty magazines, please.
// Make room for the new ammo.
// Let the other proc do the work for us.
//DEBUG("Swapped [K]'s ammo with [A.type]. There are [A.amount_left] round left over.")
// We need a free hand for ammoHand first.
// Some ammo boxes have dynamic icon/desc updates we can't get otherwise.
// No duplicating empty magazines, please.
// Ditto.
//DEBUG("Swapped [K]'s ammo with [A.type].")
// Make room for the new ammo.
// We don't need you anymore.
// Also see attackby() in kinetic.dm.
// Error message.
// For zip guns.
// Magazine's empty.
// Call swap().
// Gun's full.
// Call swap().
// The gun may have been fired; eject casings if so (Convair880).
// Required for swap() to work properly (Convair880).
//DEBUG("Equalized [K]'s ammo type to [A.type]")
//DEBUG("[K]: [A.type] (now empty) was deleted on partial reload.")
// No duplicating empty magazines, please (Convair880).
// Couldn't fully reload the gun.
//DEBUG("[K]: [A.type] (now empty) was deleted on full reload.")
// No duplicating empty magazines, please (Convair880).
// Full reload or ammo left over.
// This makes little sense, but they're all chambered in the same caliber, okay (Convair880)?
// Ported from old, non-gun RPG-7 object class (Convair880).
//////////////////////////////////// Power cells for eguns //////////////////////////
// Fixed an instance of item teleportation here (Convair880).
//Recharge every other tick.
// Charge every four seconds.
// cogwerks: raised from 1.0 because radbows were terrible!!!!!
// Does this gun add gunshot residue when fired? Energy guns shouldn't.
// Can we put this gun in a recharger? False should be a very rare exception.
// Is there a limit as to what power cell (in PU) we can use?
// Using a self-charging cell should auto-update the gun's sprite.
// No self-charging cell? Will be kicked out after the first tick (Convair880).
// Self-charging cells recharge every other tick (Convair880).
// Plain cell? No need for dynamic updates then (Convair880).
// Keep them in the loop, as we might fire the gun later (Convair880).
// Again, we want dynamic updates here (Convair880).
////////////////////////////////////TASERGUN
/////////////////////////////////////LASERGUN
//Wire: Fix for Division by zero runtime
////////////////////////////////////// Antique laser gun
// Part of a mini-quest thing (see displaycase.dm). Typically, the gun's properties (cell, projectile)
// won't be the default ones specified here, it's here to make it admin-spawnable (Convair880).
//////////////////////////////////////// Phaser
///////////////////////////////////////Rad Crossbow
// Cannot be recharged manually.
// No conspicuous text messages, please (Convair880).
// Those self-charging ten-shot radbows were a bit overpowered (Convair880)
////////////////////////////////////////EGun
////////////////////////////////////VUVUV
//////////////////////////////////////Disruptor
////////////////////////////////////Wave Gun
// Old phasers aren't around anymore, so the wave gun might as well use their better sprite (Convair880).
////////////////////////////////////BFG
// No more attack messages for empty guns (Convair880).
///////////////////////////////////////Telegun
// For checks before firing (Convair880).
// I overhauled everything down there. Old implementation made the telegun unreliable and crap, to be frank (Convair880).
// So we'll always get a list, even if there's only one teleporter in total.
// Don't show teleporters in "somewhere", okay.
// It's busted, Jim.
///////////////////////////////////////Ghost Gun
///////////////////////////////////////Modular Gun
// for overheating stuff
//handle gun mods at a workbench
/*proc/generate_overlays()
src.overlays = null
if(extension_mod)
src.overlays += icon('icons/obj/gun_mod.dmi',extension_mod.overlay_name)
if(converter_mod)
src.overlays += icon('icons/obj/gun_mod.dmi',converter_mod.overlay_name)*/
/*proc/update_icon()
var/ratio = src.charges / maximum_charges
ratio = round(ratio, 0.25) * 100
src.icon_state = text("phaser[]", ratio)*/
///////////modular components - putting them her so it's easier to work on for now////////
// todo: make more item icons
//use flash as the core of the device
// inherit material vars from the flash
// idk what the hell this would even do
// tacticool
///////////////////////////////////////Owl Gun
///////////////////////////////////////Shrink Ray
///////////////////////////////////////Glitch Gun
// No more attack messages for empty guns (Convair880).
///////////////////////////////////////Predator
// Made use of a spare sprite here (Convair880).
// Necessary. Parent's got a different sprite now (Convair880).
//Global list of all guns, based on bioholder uID stuff
// Does this gun add gunshot residue when fired (Convair880)?
//Creates a new tracking id for the gun and returns it.
// 20 characters are way too fuckin' long for anyone to care about
///CHECK_LOCK
///Call to run a weaponlock check vs the users implant
///Return 0 for fail
///CHECK_VALID_SHOT
///Call to check and make sure the shot is ok
///Not called much atm might remove, is now inside shoot
//user.bullet_act(current_projectile)
// Additional forensic evidence for kinetic firearms (Convair880).
// Was non-functional (Convair880).
// Was missing (Convair880).
// Includes log entry.
// No more attack messages for empty guns (Convair880).
// Fix for: undefined proc or verb /obj/item/mechanics/gunholder/show text().
// Some user feedback for silenced guns would be nice (Convair880).
// Additional forensic evidence for kinetic firearms (Convair880).
/*if (!disable_next_click) aggressive thing, so disable_next_click shouldn't affect this
*/
// Could be useful in certain situations (Convair880).
// How much ammo can this gun hold? Don't make this null (Convair880).
// Can be a list too. The .357 Mag revolver can also chamber .38 Spc rounds, for instance (Convair880).
// Do we eject casings on firing, or on reload?
// If we don't automatically ejected them, we need to keep track (Convair880).
// Does this gun add gunshot residue when fired? Kinetic guns should (Convair880).
// caliber list: update as needed
// 0.308 - rifles
// 0.357 - revolver
// 0.38 - detective
// 0.41 - derringer
// 0.72 - shotgun shell, 12ga
// 1.57 - 40mm shell
// 1.58 - RPG-7 (Tube is 40mm too, though warheads are usually larger in diameter.)
// Might be useful (Convair880).
// Added this to make manual reloads possible (Convair880).
// Make sure it's not on the belt or in a backpack.
// The gun may have been fired; eject casings if so.
// Make a copy here to avoid item teleportation issues.
// No duplicating empty magazines, please (Convair880).
// The gun may have been fired; eject casings if so.
//DEBUG("Unloaded [src]'s ammo manually.")
// Finished Cogwerks' former WIP system (Convair880).
//DEBUG("Ejected [number_of_casings] casings from [src].")
//DEBUG("Ejected [number_of_casings] casings from [src].")
//DEBUG("Ejected [src.casings_to_eject] [src.current_projectile.casing] from [src].")
// Don't set this too high. Absurdly large reloads and item spawning can cause a lot of lag. (Convair880).
// Just like in RL (Convair880).
// It's magazine-fed (Convair880).
// It's magazine-fed (Convair880).
//contraband = 8
// It's magazine-fed (Convair880).
// use any ammo at all BA HA HA HA HA
// start empty
// Empty zip guns had a chance of blowing up. Stupid (Convair880).
//item_state = "flaregun"
// Ported from old, non-gun RPG-7 object class (Convair880).
// Spawn empty.
//This is technically kinetic? I guess?
//griff
// Delete src when it's used up (e.g. tape roll)?
//brutal
//!usr.bioHolder.HasEffect("lost_left_arm") && !usr.bioHolder.HasEffect("lost_right_arm"))
// Contains:
//
// - Chainsaw
// - Plant analyzer
// - Portable seed fabricator
// - Watering can
// - Compost bag
// - Plant formulas
//////////////////////////////////////////////// Chainsaw ////////////////////////////////////
// Fixed a couple of bugs and cleaned code up a little bit (Convair880).
//need a better sound
// Red chainsaw.
// Elimbinator.
//who knows
////////////////////////////////////// Plant analyzer //////////////////////////////////////
// Replaced with global proc (Convair880).
/////////////////////////////////////////// Seed fabricator ///////////////////////////////
/*for (var/datum/plant/P in src.available)
if (!P.vending || P.type == /datum/plant)
del P
continue*/
/* var/hacked = 0
if (istype(user,/mob/living/silicon/robot/))
var/mob/living/silicon/robot/R = user
if (R.emagged)
hacked = 1
*/
///////////////////////////////////// Watering can ///////////////////////////////////////////////
/////////////////////////////////////////// Compost bag ////////////////////////////////////////////////
/////////////////////////////////////////// Plant formulas /////////////////////////////////////
// called when an implant is implanted into M by I
// called when an implant is removed from M
// add gps info proc here if tracker exists
//DEBUG("implant reporting crit")
//DEBUG("implant reporting death")
//DEBUG("message sent to [src.mailgroup]")
//DEBUG("message sent to [src.mailgroup2]")
// Added shackles here (Convair880).
//Probably won't trigger on suicide though
//This actually should include us, ok.
//tally the total power we're dealing with here
//so we don't get deleted prematurely by the blast.
//Create a big bomb explosion overlay.
//List of stuff to throw as if the explosion knocked it around.
//So we don't freak out and throw more than ~25 things and act like the old mass driver bug.
//Delete the overlay when finished with it.
//Throw this junk around
//explosion(src, T, -1, -1, 2*explosionPower, 3*explosionPower)
//The . is the tally of explosionPower in this poor slob.
// who is the person mindslaving the implanted person
// ex: kill the captain, dance constantly, don't speak, etc
// all the stuff in here was added by Convair880, I just adjusted it to work with this can_implant() proc thing - haine
// It might happen, okay. I don't want to have to adapt the override code to take every possible scenario (no matter how unlikely) into considertion.
// Necessary to get those expiration messages to trigger properly if the same mob is implanted again,
// since mindslave implants have spawn()s going on.
// Same here, basically. Multiple active implants is just asking for trouble.
//25 minutes +/- 5
// Drop-all, gibbed etc (Convair880).
// 1 minute left
// There's a proc for this now (Convair880).
//The neural shock of some jerk dying wears the implant down. Or some shit.
// match a bullet to a gun holy heckkkkk
//Don't make non-organics bleed and don't act like a launched bullet if some doofus is just injecting it somehow.
// boutput(C, "<span style=\"color:red\">You start bleeding!</span>") // the blood system takes care of this bit now
// okay it doesn't actually cause bleeding now but um w/e
//?src=\ref[src];freq=-10'>-</A>
//?src=\ref[src];freq=-2'>-</A> [format_frequency(T.frequency)]
//?src=\ref[src];freq=2'>+</A>
//?src=\ref[src];freq=10'>+</A><BR>
//?src=\ref[src];id=-10'>-</A>
//?src=\ref[src];id=-1'>-</A> [T.id]
//?src=\ref[src];id=1'>+</A>
//?src=\ref[src];id=10'>+</A><BR>"}
//Foreach goto(290)
//silentshot = 1
// why were most of these in gimmick.dm?????? that's a file for clothing. what??????????????????????????
// too important to burn!
// The key that unlocks walls. (please refer to turf.dm)
//adjective only
//noun only
//adjective and noun
//add material?
//pick name for key
//add more fluff?
// it doesn't make sense, no. but hey, it's something.
// I came in here just to make donut/egg boxes put the things in your hand when you take one out and I end up doing this instead, kill me. -haine
// no I ain't even touchin this mess it can keep doin whatever it's doin
//this is hacky way to get the user without looping through all mobs in process
//high power mode (holding during movement)
//power usage here maybe??
//If the item has been consumed somehow
//too bulky for backpacks, too bulky for this
//activate held item (if possible)
//for items that update icon on activation (e.g. welders)
//too bulky for backpacks, too bulky for this
//pick up item
//For when holding the item in other hand
//blue
//red
//Called by action_controls.dm, magPicker
//quit pullin
//For removing items from containers with the tractor
// ugh
//why is this necessary aaaaa!.
//bulky
//red
//blue
//user.visible_message("<span class='bold' style='color: blue;'>[user] pulls \the [W] into the [src.name]</span>", "<span style='color: blue;'>The [src.name] pulls \the [W] into it's magnetic field and flickers worryingly.[src.highpower ? "" : " You must hold still while using this item."]</span>")
//Called by action_controls.dm, magPickerHold
//normal
//item still exists, dropping
//item no longer exists (was used up)
//TODO: playsound, de-power thing
//text to display for this ore in manufacturers
// what grade of metal is it?
// how much we want the sprite to be deviated fron center
// relate this to precursors
//cogwerks - burn vars
// relate this to wizardry somehow
// if not on mining z level
// if not on mining z level
//cogwerks - burn vars
// relate this to ancients
// Misc building material
// this should only be spawned by the game, spawning it otherwise would just be dumb
// same deal here
// bars, tied into the new material system
// Material-related Machinery
/*onMaterialChanged()
..()
if (istype(src.material))*/
// haaaaaaaaaaaaaaack
// RODS
//SN src = null
// METAL SHEET
//cogwerks - burn vars
//SN src = null
//SN src = null
// TODO layer
// REINFORCED METAL SHEET
//cogwerks - burn vars
//SN src = null
//SN src = null
// Cleaned up the ancient code that used to be here (Convair880).
// Timer process() expects this to be here. Could be used for dynamic icon_states updates.
// Special effects handled by every type of mine.
// For bioeffects or stuns, basically everything that should affect all mobs located on src.loc when triggered.
// Contains:
//
// - obj/item/weapon parent (now unused and commented out)
// - Esword
// - Dagger
// - Butcher's knife
// - Axe
////////////////////////////////////////////// Weapon parent //////////////////////////////////
/* unused now
/obj/item/weapon
name = "weapon"
icon = 'icons/obj/weapons.dmi'
inhand_image_icon = 'icons/mob/inhand/hand_weapons.dmi'
*/
/////////////////////////////////////////////// Esword /////////////////////////////////////////
///////////////////////////////////////////////// Dagger /////////////////////////////////////////////////
////////////////////////////////////////// Butcher's knife /////////////////////////////////////////
//Idea stolen from the welder!
/////////////////////////////////////////////////// Predator Spear ////////////////////////////////////////////
/////////////////////////////////////////////////// Axe ////////////////////////////////////////////
// Contains:
// - Teleportation scroll
// - Staves
// - Magic mirror
/////////////////////////////////////////////////// Teleportation scroll ///////////////////////////////////
//?src=\ref[src];spell_teleport=1'>Teleport</A><br><br><hr>"
////////////////////////////////////////////////////// Staves /////////////////////////////////////////////////////
// The owner of this staff.
// Part of the parent for convenience.
// Used by /datum/targetable/spell/summon_staff. Exposed for convenience (Convair880).
// goes with Gannets' purple wizard robes - it looks different, and that's about it :I (always b fabulous)
/////////////////////////////////////////////////////////// Magic mirror /////////////////////////////////////////////
// Teamwork, perhaps? The M.is_target check that used to be here doesn't cut it in the mixed game mode (Convair880).
/*var/corrupt = 0
var/count = 0
for(var/turf/simulated/floor/T in world)
if(T.z != 1) continue
count++
if(T.loc:corrupted) corrupt++
var/percentage
percentage = (corrupt / count) * 100
if (corrupt >= 2100)
. += "<br><span style=\"color:green\"><b>The Corruption</b> is at [percentage]%!</span>"
else
. += "<br><span style=\"color:red\"><b>The Corruption</b> is at [percentage]%!</span>"*/
// && tox <= 0)
//src.tox_dam += tox
//to hit with an item instead of hand when used empty handed
//gimmick parts
// what streaks everywhere when it's cut off?
//bloody, oily, etc
//I.type
// what streaks everywhere when it's cut off?
//bloody, oily, etc
//.type
// Added shambler, werewolf and predator arms, including the sprites (Convair880).
// does it help the robot move more quickly?
// for calculating speed modifiers
// does this part consume any extra power
// need to do special stuff in this case, so we let the borg's melee hit take care of it
// wouldn't want to divide by zero, even if my maths suck
//If the borg-to-be is jobbanned or has DNR set
//Fuck my shit
// second check up there is just watching out for those ..() calls
// i don't know why this would get abused
// but it probably will
// when that happens
// tell past me i'm saying hello
// second check up there is just watching out for those ..() calls
// second check up there is just watching out for those ..() calls
// second check up there is just watching out for those ..() calls
// second check up there is just watching out for those ..() calls
///This will make the borg a syndie one
// there was a big transferring list of parts from the frame to the compborg here at one point, but it didn't work
// because the cyborg's process proc would kill it for having no chest piece set up after New() finished but
// before it could get around to this list, so i tweaked their New() proc instead to grab all the shit out of
// the frame before process could go off resulting in a borg that doesn't instantly die
// how the fuck did you even do this
// The antagonist proc does that too.
// final check to guarantee the icon shows up for everyone
//So the icon actually appears
// UPGRADES
// Cyborg
// Is this module used like an item?
// Does this module always work once installed?
// live ingame variable
// How much charge the upgrade consumes while installed
// How many times a limited upgrade can be used before it is consumed (infinite if negative)
// Can be removed from the cyborg
// Used for cyborg update_apperance proc
//updateIcons()
//I wouldve liked to avoid this but i dont want to put this inside the mobs life proc as that would be more code.
// Debrained or whatever.
//Was 100. jfc
/* doesn't really do anything atm
/obj/item/roboupgrade/opticthermal
name = "Optical Thermal Upgrade"
desc = "A set of advanced lens and detectors enabling a cyborg to see into the thermal spectrum."
icon_state = "up-opticthe"
borg_overlay = "up-thermal"
drainrate = 10
*/
// AI Upgrades
/* Cogs, just uncomment this stuff when the VOX thing is ready - ISN
/obj/item/roboupgrade/ai/vox
name = "AI VOX Module"
desc = "A speech synthesizer module that allows the AI to make vocal announcements over the station radio system."
icon_state = "mod-atmos"
slot_in(var/mob/living/silicon/ai/AI)
if (..())
return
AI.verbs += whatever the vox verb is i guess
slot_out(var/mob/living/silicon/ai/AI)
if (..())
return
AI.verbs -= whatever the vox verb is i guess
*/
// just in case
// which part of the person or robot suit does it go on???????
// what streaks everywhere when it's cut off?
//bloody, oily, etc
// used by arms for attack_hand overrides
// the type of limb_data
//set to create an item when severed rather than removing the arm itself
//used for streak direction
//2 will fall off, 3 is removed
//if the only icon is above the clothes layer ie. in the handlistPart list
// is this affected by human skin tones?
// set to 1 if this limb has decomposition icons
// for medical crap
// fix for Cannot read null.loc, hopefully - haine
//Luis Smith's Dr. Kay's Luis Smith's Sailor Dave's Left Arm
//for humans
//placeholder
//boutput(world, "Attaching lying limb [src.slot][decomp]_l on decomp stage [decomp_stage].")
//boutput(world, "Attaching standing limb [src.slot][decomp]_s on decomp stage [decomp_stage].")
//boutput(world, "Attaching standing hand [src.slot][decomp]_s on decomp stage [decomp_stage].")
//boutput(world, "Attaching standing part [src.slot][decomp]_s on decomp stage [decomp_stage].")
//stolen from gibs
// cogwerks - lowered from 1000 (what the hell) to 100
// Hi, I'm hiding in a closet like a wuss while spraying people with death chems risk-free.
// cogwerks: lowered from 10 to 5
// MOP
// Some people use mops for heat-delayed fireballs and stuff.
// Mopping the floor with just water isn't of any interest, however (Convair880).
//Okay this stuff is an ugly hack and i feel bad about it.
// SPONGES? idk
// MODULAR SPONGES
// people spammed snapping their fucking fingers, so this is probably necessary
// to make sure the reagents actually react before they're cleared
// dump reagents to these things
// popup "dry/wet" interactions with these
// Added support for old-style grenades (Convair880).
// Pies won't do, they require a mob as the target. Obviously, the mousetrap roller is much more
// likely to bump into an inanimate object.
// Transfer valve bomb pies are a thing. Shouldn't fit in a backpack, much less a box.
// Added support for old-style grenades and pipe bombs (Convair880).
// Fallback in case something goes wrong.
// Must be armed or it won't work in mousetrap.triggered().
// you ever play fallout 3? you know those like sacks of gibs that were around? yeah
// vOv
// For variety and predators (Convair880).
// Don't remove.
/*src.drop_organ("brain", location)
src.drop_organ("head", location)
src.drop_organ("skull", location)
src.drop_organ("right_eye", location)
src.drop_organ("left_eye", location)
src.drop_organ("chest", location)
src.drop_organ("heart", location)
src.drop_organ("right_lung", location)
src.drop_organ("left_lung", location)
src.drop_organ("butt", location)
return 1*/
// blehhhh
//Oh no, they have no mind!
// how
// I mean really, how
// ???
// god idfk
// should never be this but vOv
// so you can refer to the organ by a simple name and not end up telling someone "Your Lia Alliman's left lung flies out your mouth!"
// why would you put this below the throw_impact() stuff
// were you born in a fuckin barn
// if I can't use "owner" I can at least use this
// so you don't get dumb "Unknown's skull mask" shit
// what kinda mess it makes. mostly so cyberhearts can splat oil on the ground, but idk maybe you wanna make something that creates a broken balloon or something on impact vOv
// fuckers are tossing these around a lot so I guess they're only gunna make one, ever now
// L_ORGAN/1 for left, R_ORGAN/2 for right
// call your goddamn parents
// && tox <= 0)
//src.tox_dam += tox
//since these people will be dead M != usr
//created_decal = /obj/decal/cleanable/oil
// good lord
// I ain't gunna type that a billion times thanks
// dfhsgfhdgdapeiffert
// gbhjdghgfdbldf
//proc/updateIcons() // stolen from original prodocs
//sleep(20)
//Did an unstaple operation take place?
//Got all the staples
//Try a staple if it worked, yay
//That's the last staple!
//Did you get some of them?
//Commence owie
//My
//head,
//FUCKING
//OW!
//Crime
// what the fuck am I doing with my life
// no this is not done and I dunno when it will be done
// I am a bad person who accepts bribes of freaky macho butt drawings and then doesn't prioritize the request the bribe was for
// it's uhh. it's close enough to an organ.
// See assign_gimmick_skull().
//var/owner_job = null
//May randomly contain a key
// For the predator-specific objective (Convair880).
// Predators get this one (Convair880).
// Changelings.
// Wizards.
// Omnitraitors.
// Macho man.
// Cluwnes.
// vOv
// we wanna override it below
// equipped items - they use the same slot names because eh.
//The heck?
// vOv
// aaaaaa
// :I
// this is real ugly
// scalpel surgery
// saw surgery
// spoon surgery
// basically a dummy thing right now, this shouldn't do anything or go anywhere
//var/datum/mutantrace/donor_mutantrace = null
// vOv
// this seems to be a completely different paint can than the standard one, uhh. w/e it gets to live in here too
// to force redraws on worn items if needed
//var/icon/new_icon = icon(initial(target.icon))
//new_icon.ColorTone(color)
//target.icon = new_icon
//A rainbow of colours! Joy!
//Add pattern here.
//cogwerks - burning vars
//
//Can you write on this with a pen?
//?src=\ref[src];form=[src.form_startpoints[x]]'>" + copytext(., src.form_startpoints[src.form_startpoints[x]], src.form_endpoints[src.form_endpoints[x]]) + "</a>" + copytext(., src.form_endpoints[src.form_endpoints[x]])
//fonts.googleapis.com/css?family=[i]' rel='stylesheet' type='text/css'>"
//[(sizex || sizey) ? {";size=[sizex]x[sizey]"} : ""]
//Wire: fix for undefined variable /mob/living/silicon/robot/var/current
//fonts.googleapis.com/css?family=[i]' rel='stylesheet' type='text/css'>"
//t = copytext(sanitize(t),1,MAX_MESSAGE_LEN)
//src.info += "<font face=[custom_font] color=[custom_color] size='3'> [t] </font>" // shit's hard to read at size 2 goddamn
// bad font arguments don't seem to do much
//M.set_loc(get_turf(src)) // otherwise they seem to just vanish into the aether at times
// moving the
// PHOTOGRAPH
// cogwerks - creepy picture things
//cogwerks - burn vars
//Wire: Fix for Cannot read null.loc (&& usr)
//TODO: FIX
/* who did this
/obj/item/stamp/New()
..()
return
WHO DID THIS */
// custom pens
// atm this is used to add things to paper's font list. see /obj/item/pen/fancy and /obj/item/paper/attackby()
//color = "blue"
//"Vivaldi"
//color = "blue"
//"Vivaldi"
// trying to avoid pre-game-start runtime bullshit
// so we get a moment to think before we die
// SHOULD be redundant but you never know.
// color var owns
// do this via afterattack()
// do this via attack()
//they have to die fast or it'd make even less sense
//Todo: make it actually show the photo. Currently, using [bicon()] just makes an egg image pop up (??)
//cogwerks - burn vars
//
// Inedible Produce
// will hitting a still with it do anything?
// what will it make if it's brewable?
// Change mode
/* /obj/item/rcd/attack(mob/M as mob, mob/user as mob, def_zone)
if (ishuman(M) && matter >= 3)
var/mob/living/carbon/human/H = M
if(H.stat != 2 && H.health > 0)
boutput(user, "<span style=\"color:red\">You poke [H] with the RCD.</span>")
boutput(H, "<span style=\"color:red\">[user] pokes you with the RCD.</span>")
return
boutput(user, "<span style=\"color:red\"><B>You shove the RCD down [H]'s mouth and pull the trigger!</B></span>")
H.show_message("<span style=\"color:red\"><B>[user] is shoving an RCD down your throat!</B></span>", 1)
for(var/mob/N in viewers(user, 3))
if(N.client && N != user && N != H)
N.show_message(text("<span style=\"color:red\"><B>[] shoves the RCD down []'s throat!</B></span>", user, H), 1)
playsound(src.loc, "sound/machines/click.ogg", 50, 1)
if(do_after(user, 20))
spark_system.set_up(5, 0, src)
src.spark_system.start()
var/mob/living/carbon/wall/W = new(H.loc)
W.real_name = H.real_name
playsound(src.loc, "sound/items/Deconstruct.ogg", 50, 1)
playsound(src.loc, "sound/effects/splat.ogg", 50, 1)
if(H.mind)
H.mind.transfer_to(W)
H.gib()
matter -= 3
boutput(user, "The RCD now holds [matter]/30 matter-units.")
desc = "A RCD. It currently holds [matter]/30 matter-units."
return
else
return ..(M, user, def_zone) */
// This is used mostly for infusions. How likely a seed is to be destroyed.
// Seeds cannot be gene scanned if they're strange seeds.
// Keeps track of how many times a plant has been bred from the initial seed.
// Set up the base genes. Note we don't need to set up the planttype here - that's because
// the setup for that is automatically handled during spawning a seed from the vendor or
// harvesting a plant or what-have-you.
// Scatter the seed's sprite around a bit so you can make big ol' piles of them.
// Colors in the seed packet, if we want to do that. Any seed that doesn't use the
// standard seed packet sprite shouldn't do this or it'll end up looking stupid.
// This proc is pretty much entirely for regular seeds you find from the vendor
// or harvest, stuff like artifact seeds generally shouldn't be calling this.
// Sanity check. If the seed is of a null species it could cause trouble, so we
// just get rid of the seed and don't do anything else.
//var/datum/plant/Pl = new P.type(src)
// Calls on a variable in the referenced plant datum to get the seed packet's color.
// A small proc which usually takes the color reference from a plant datum and uses
// it to color in the seed packet so you can recognise the packets at a glance.
// The proc for when the manipulator is infusing seeds with a reagent. This is sort of a
// framing proc simply to check if the seed is in good enough condition to withstand the
// infusion or not - the actual gameplay effects are handled in a different proc:
// proc/HYPinfusionP, /datums/plants.dm, line 115
// Note that this continues down the chain and checks the proc for individual plant
// datums after it's finished executing the base plant datum infusion proc.
// Error code 1 - seed destroyed/lost
// Error code 2 - reagent not found
// Error code 3 - we don't know what the fuck went wrong tbh
// Infusing costs a little bit of the seed's health
// Whoops, you did it too often and now the seed broke. Good job doofus!!
// The proc call both executes the infusion on the species AND performs a check -
// The check is for a return value of 99, basically an error code for "Whoops you
// destroyed the seed you dumbass".
// We'll want to tell the manipulator that so it can inform the user, too.
// Passes an "Everything went fine" code to the manipulator.
// weird alien plants
// let's make the base seed randomise itself for fun and also for functionality
// so all cash types can stack iwth each other
// attack_self(mob/user as mob)
// user.visible_message("fart")
// That's what tourists spawn with.
// I swear to fuckin god stop being under CLOTHES you SHIT
//round(A.bound_width/2)
//round(A.bound_height/2)
//pox = minmax(-round(A.bound_width/2), pox, round(A.bound_width/2))
//poy = minmax(-round(A.bound_height/2), pox, round(A.bound_height/2))
// if(..() == BLOCKED)
// return
// ******* Check
// fuck bibles
//Grif
//Let's spawn up some carts (Unless they shouldn't randomly show up, like detomaxes)
// its already bulbs by default
// Most of these aren't in use anymore, but there's enough of them that they may as well get their own file.
// Comes with upgraded health scanner.
// Medkit filled with old crud for shady QM merchants (Convair880).
/* switch (pickweight(list("small" = 10, "mask" = 10, "tank" = 5, "both" = 20, "nothing" = 1)))
if ("small")
new /obj/item/tank/emergency_oxygen(src)
new /obj/item/tank/emergency_oxygen(src)
if ("mask")
new /obj/item/clothing/mask/breath(src)
if ("tank")
new /obj/item/tank/air(src)
if ("both")
new /obj/item/tank/emergency_oxygen(src)
new /obj/item/clothing/mask/breath(src)
if ("nothing")
return
*/
// SECURE STORAGE
// sets things to already have a randomized code on spawning
//Waluigi hates this
// set this to play proper beeps later
// SECURE BRIEFCASE
// ******* Check
// for things that should spawn with specific other things, ie guns & ammo
// if there's enough room for two things
// one less thing since we spawned two
// if there's not enough room
// try again
// if there's no matching thing to spawn
// if what we selected wasn't a valid path
// try again
// we're stealin all ur stuff >:D
// a thing to confuse people
// haine wuz here and tore this file to bits!!! f u we can have things in their own files and we SHOULD
// rather than EVERYTHING BEING IN HALLOWEEN.DM AND KEELINSSTUFF.DM OKAY THINGS CAN BE IN OTHER FILES
//Don't print a visible message on use.
//cogwerks - burn vars
// use this rather than overriding the container's New()
//Instead of duplicate entries in the list, let's make them associative
// no infinite loops for you
// nope
//Hi hello this used to gib the user and create an actual 5x5 explosion on their tile
//Turns out this condition can be met and reliably reproduced by players!
//Lets not give players the ability to fucking explode at will eh
// this check is probably dumb. BUT YOU NEVER KNOW
// the one you get in your backpack
// put these together
// Don't use up more slots, certain job datums put items in the briefcase the player spawns with.
// And nobody needs six sheets of paper right away, realistically speaking.
//Ugly. Who cares.
//cogwerks - burn vars
// The extra items (scanner and soldering iron) take up precious space in the backpack.
// It will devour people! It's an evil thing!
//Neatly sort everything they have into handy little boxes.
//Release trapped dudes...
//Remove the plague...
// just going to have to set it up manually i guess
/* Phased out with the forensic scanner overhaul. Was useless anyway (Convair880).
/obj/item/storage/box/fcard_kit
name = "fingerprint card box"
icon_state = "id"
spawn_contents = list(/obj/item/f_card = 7)
*/
// For sec officers and the HoS. Really love spawning with a full backpack (Convair880).
// cogwerks - i think the ammo boxes are dumb, giving the starting box more ammo
// Reduced the amount of ammo. The detective had four lethal and five stun speedloaders total in his closet, perhaps a bit too much (Convair880).
// cogwerks, terrorism update
// this might be a terrible idea giving them so much ammo, but whatevs
// this might be a terrible idea giving them so much ammo, but whatevs
// 2 TC for 1 speedloader was very poor value compared to other guns and traitor items in general (Convair880).
// For surplus crates (Convair880).
// cogwerks - tactical as heck
// For QM crate "Security Equipment" (Convair880).
// For QM crate "Experimental Weapons" (Convair880).
// The bowling ball won't fit into the bowling bag!
// Starter kit used in the conspiracy/spy game mode.
// Contains:
// - Baton parent
// - Subtypes
////////////////////////////////////////// Stun baton parent //////////////////////////////////////////////////
// Completely refactored the ca. 2009-era code here. Powered batons also use power cells now (Convair880).
// Update sprite periodically if we're using a self-charging cell.
// Type of cell to spawn by default.
// Ignored for cyborgs and when used_electricity is false.
// Cost in PU. Doesn't apply to cyborgs.
// Battery charge to drain when user is a cyborg.
// Does it deduct charges when used? Distinct from...
// Does it use electricity? Certain interactions don't work with a wooden baton.
// Only used when next flag is set to 1.
// Legacy behaviour for harmbaton, that is an instant knockdown.
// Experimental. Centered around stamina instead of traditional stun.
// Amount of stamina drained.
// No self-charging cell? Will be removed after the first tick.
// Kick out batons with a plain cell.
// Keep self-charging cells in the loop, though.
// Doubles as reset fallback (var editing).
// Sound effects, log entries and text messages.
// Target setup. User might not be a mob (Beepsky), but the victim needs to be one.
// Stun the target mob.
// Necessary since the item/attack() parent wasn't called.
// Must be called manually here to apply the stun instantly.
// Some after attack stuff.
// Parent handles attack log entry and stamina drain.
/////////////////////////////////////////////// Subtypes //////////////////////////////////////////////////////
// Every bit of usability helps (Convair880).
//Attach butt to head
// Marq fix for undefined variable /datum/human_limbs/var/head
// grhg w/e I'm half asleep this is good enough
// aaa why did they hold SO MUCH BLOOD?? 500 IS THE SAME AS A PERSON WHY DID THEY HAVE A PERSON WORTH OF BLOOD IN THEM
/* switch (src.volume)
if (90 to INFINITY)
src.icon_state = "bloodbag-10"
if (80 to 89)
src.icon_state = "bloodbag-9"
if (70 to 79)
src.icon_state = "bloodbag-8"
if (60 to 69)
src.icon_state = "bloodbag-7"
if (50 to 59)
src.icon_state = "bloodbag-6"
if (40 to 49)
src.icon_state = "bloodbag-5"
if (30 to 39)
src.icon_state = "bloodbag-4"
if (20 to 29)
src.icon_state = "bloodbag-3"
if (10 to 19)
src.icon_state = "bloodbag-2"
if (1 to 9)
src.icon_state = "bloodbag-1"
if (-INFINITY to 0)
src.icon_state = "bloodbag-0"
*/
// TABLE PARTS
//SN src = null
// REINFORCED TABLE PARTS
// will have to come back to this later
// RACK PARTS
//liters
//Allow for reactions
//Wire: Fix for Cannot execute null.react().
//Handle exploding, leaking, and rupturing of the tank
// 50 atmospheres, or: 5066.25 kpa under current _setup.dm conditions
//boutput(world, "<span style=\"color:blue\">[x],[y] tank is exploding: [pressure] kPa</span>")
//Give the gas a chance to build up more pressure through reacting
// (pressure - 5066.25 kpa) divided by 1013.25 kpa
// was 8
//boutput(world, "<span style=\"color:blue\">Exploding Pressure: [pressure] kPa, intensity: [range]</span>")
//boutput(world, "<span style=\"color:blue\">[x],[y] tank is rupturing: [pressure] kPa, integrity [integrity]</span>")
//TODO: make pop sound
// consider it TO DID
//boutput(world, "<span style=\"color:blue\">[x],[y] tank is leaking: [pressure] kPa, integrity [integrity]</span>")
// setting these things to start at the minimum pressure needed to breath - Haine
// setting these things to start at the minimum pressure needed to breath - Haine
//G = null
// setting these things to start at the minimum pressure needed to breath - Haine
// setting these things to start at the minimum pressure needed to breath - Haine
// cogwerks: drastically reduced capacity of emerg tanks
// setting these things to start at the minimum pressure needed to breath - Haine
//S = null
//S = null
//S = null
/*/obj/item/tank/supersoaker
name = "Super Soaker"
icon_state = "jetpack0"
var/on = 0.0
w_class = 4.0
item_state = "jetpack"*/
//?src=\ref[src];temp=1'>Clear</A>"
//?src=\ref[src];freq=-10'>-</A>
//?src=\ref[src];freq=-2'>-</A> [format_frequency(src.frequency)]
//?src=\ref[src];freq=2'>+</A>
//?src=\ref[src];freq=10'>+</A><BR>
//?src=\ref[src];refresh=1'>Refresh</A><BR>"
/// HAND TELE
// Port of the telegun improvements (Convair880).
// So we'll always get a list.
// Default option that should always be available, regardless of number of teleporters (or lack thereof).
// Don't put them at the edge.
// Don't show teleporters in "somewhere", okay.
// It's busted, Jim.
// Shouldn't happen, but you never know.
// "None" is a random turf, whereas computer-assisted teleportation locks on to a beacon or tracking implant.
// TILES
//SN src = null
//SN src = null
//SN src = null
// boutput(world, "[M] is no longer buckled to [src]")
// CROWBAR
// WIRECUTTERS
// Damn message spam.
// WRENCH
// SCREWDRIVER
// WELDING TOOL
//flamethrower construction :shobon:
// helper functions for weldingtool fuel use
// return fuel amount
// remove fuel amount
//check eye protection
/* L:head:up broke for no reason so I had to rewrite it.
if (istype(L:head, /obj/item/clothing/head/helmet/welding))
if(!L:head:up)
safety = 8*/
// we wanna check for the thermals first so having a polarized eye doesn't protect you if you also have a thermal eye
//mat_changename = 0
// rarely give a different material
// VERY rarely give a super-fancy material
// silly basic "rare" varieties of things that should probably just be fancy paintjobs or plastics, but whoever made these things are idiots and just made them out of the actual stuff. I guess.
// basic versions that should always be picked between (ex: hos hat/hos beret)
// rare versions to be picked sometimes
//, "captain3")
//reusable = 0
//Products
/////////////////////////////////////////// Uplink parent ////////////////////////////////////////////
// Amount of telecrystals.
// See setup().
// Use the parent's HTML interface (less repeated code).
// Spawned uplinks for which setup() wasn't called manually only get the standard (generic) items.
// No meta by checking VR uplinks.
// Sort alphabetically by item name.
// Should never, ever happen, but better safe than sorry.
//?src=\ref[src];unlock=1'>Enter password</A>.<BR>"
//?src=\ref[src];back=1'>Back</A>"
//?src=\ref[src];temp=1'>Clear</A>"
//?src=\ref[src];spawn=\ref[src.items_general[G]]'>[I1.name]</A> ([I1.cost])</td><td><A href='byond://?src=\ref[src];about=\ref[src.items_general[G]]'>About</A></td>"
//?src=\ref[src];spawn=\ref[src.items_job[J]]'>[I2.name]</A> ([I2.cost])</td><td><A href='byond://?src=\ref[src];about=\ref[src.items_job[J]]'>About</A></td>"
//?src=\ref[src];spawn=\ref[src.items_objective[O]]'>[I3.name]</A> ([I3.cost])</td><td><A href='byond://?src=\ref[src];about=\ref[src.items_objective[O]]'>About</A></td>"
//?src=\ref[src];lock=1'>Lock</A><BR>"
//?src=\ref[src];lock=1'>Lock</A><BR>"
//?src=\ref[src];selfdestruct=1'>Self-Destruct</A>"
/////////////////////////////////////////////// Syndicate uplink ////////////////////////////////////////////
///////////////////////////////////////////////// Integrated uplinks (PDA & headset) //////////////////////////////////
//Restore original notes when locked.
//Are we currently active??
//Switch right to the notes program
//Communicate with traitor through the PDA's note function.
//Let's build a menu!
//?src=\ref[src];buy_item=\ref[src.items_general[G]]'>[I1.name]</A> ([I1.cost])</td><td><A href='byond://?src=\ref[src];abt_item=\ref[src.items_general[G]]'>About</A></td>"
//?src=\ref[src];buy_item=\ref[src.items_job[J]]'>[I2.name]</A> ([I2.cost])</td><td><A href='byond://?src=\ref[src];abt_item=\ref[src.items_job[J]]'>About</A></td>"
//?src=\ref[src];buy_item=\ref[src.items_objective[O]]'>[I3.name]</A> ([I3.cost])</td><td><A href='byond://?src=\ref[src];abt_item=\ref[src.items_objective[O]]'>About</A></td>"
//?src=\ref[src];back=1'>Back</A>")
/*else if (href_list["back"])
src.generate_menu()
src.print_to_host(src.menu_message)
return*/
///////////////////////////////////////// Wizard's spellbook ///////////////////////////////////////////////////
//src.spells += new /datum/SWFuplinkspell/shockwave(src)
// unknown error
// ran out of points
/*/datum/SWFuplinkspell/lightningbolt
name = "Lightning Bolt"
eqtype = "Offensive"
desc = "Fires a bolt of electricity in a cardinal direction. Causes decent damage, and can go through thin walls and solid objects. You need special HAZARDOUS robes to cast this!"
cooldown = 20
assoc_verb = */
//?src=\ref[src];temp=1'>Clear</A>"
//?src=\ref[src];buyspell=\ref[SP]'><b>[SP.name]</b></A> ([SP.eqtype]) <A href='byond://?src=\ref[src];aboutspell=\ref[SP]'>(?)</A><br>"
//?src=\ref[src];lock=1'>Lock</A><BR>"
//?src=\ref[src];selfdestruct=1'>Self-Destruct</A>"
// presto chango, a regular radio again! (reset the freq too...)
// R.layer = initial(R.layer)
//?src=\ref[src];selfdestruct2=1'>Self-Destruct</A>"
//if (istype(H.wear_suit, /obj/item/clothing/suit/wizrobe))
// H.wear_suit.check_abilities()
// for bleeding system things, options: DAMAGE_BLUNT, DAMAGE_CUT, DAMAGE_STAB in order of how much it affects the chances to increase bleeding
// burn faster
// this already exists but nothing uses it???
//cogwerks fire project - can object catch on fire - let's have all sorts of shit burn at hellish temps
//how hot should it burn
// 0 = ash, 1 = melt
//Can't remove from non-hand slots
//Can't be removed from non-hand slots by others
//Cant' be removed in general. I guess.
// if null, only current type. otherwise uses this
//If nonzero, bots consider this a thing people shouldn't be carrying without authorization
//set to an icon state in human.dmi minus _s/_l and l_arm_/r_arm_ to allow use as an arm
//draw over clothes when used as a limb
//when used as an arm, attack with item rather than using attack_hand
//when used as an arm, can it hold things?
//amount of stamina removed from target per hit.
//amount of stamina removed from USER per hit. This cant bring you below 10 points and you will not be able to attack if it would.
//Crit chance when attacking with this.
// can you eat the thing?
//If set to something other than -1 these will control
//how long it takes to remove or put the item onto a person. 1/10ths of a second.
//Should this item use a contained item (in contents) to attack with instead?
// this is dumb but it won't let me initialize vars to image() for some reason
// just in case
// same as above
// Necessary.
// Why not, I guess. Adds a bit of flavour (Convair880).
// Necessary.
// Ditto (Convair880).
// this is a helper for organs and limbs
// this is a helper for organs and limbs
// this is a helper for organs and limbs
//Is called together with attackby and afterattack on items the MOB is wearing. Only works for mob/living/carbon s.
//Can be treated as afterattack that is called on all equiped items, basically. This is not restricted by LOS or anything
//You'll have to check for that yourself if you need it.
// cogwerks- flammable items project
/*if (src.reagents && src.reagents.reagent_list && src.reagents.reagent_list.len)
//boutput(world, "<span style=\"color:red\"><b>[src] is releasing chemsmoke!</b></span>")
//cogwerks note for drsingh: this was causing infinite server-killing problems
//someone brought a couple pieces of cheese into chemistry
//chlorine trifluoride foam set the cheese on fire causing it to releasee cheese smoke
//creating a dozen more cheeses on the floor
//which would catch on fire, releasing more cheese smoke
//i'm sure you can see where that is going
//this will happen with any reagents that create more reagent-containing items on turf reactions
var/location = get_turf(src)
var/max_vol = reagents.maximum_volume
var/rname = reagents.get_master_reagent_name()
var/color = reagents.get_master_color(1)
var/icon/overlay = icon('icons/effects/96x96.dmi',"smoke")
if (color)
overlay.Blend(color,ICON_MULTIPLY)
var/image/I = image(overlay)
I.pixel_x = -32
I.pixel_y = -32
var/the_dir = NORTH
for(var/i=0, i<8, i++)
var/obj/chem_smoke/C = new/obj/chem_smoke(location, reagents, max_vol)
C.overlays += I
if (rname) C.name = "[rname] smoke"
spawn(0)
var/my_dir = the_dir
var/my_time = rand(80,110)
var/my_range = 3
spawn(my_time) qdel(C)
for(var/b=0, b<my_range, b++)
sleep(15)
if (!C) break
step(C,my_dir)
C.expose()
the_dir = turn(the_dir,45) */
// runtime error fix
// Marquesas: this will give paper an average lifetime of 6 seconds while burning.
// call your fucking parents
//src.pickup(user) //This is called by the later put_in_hand() call
// this is to fix some bugs with storage items
// ugh
// UNF
// not sure if this is the right thing...
//This message was previously sent to the attacking item. YEP.
//who knows
//qdel(src)
//Refactor of the item removal code. Fuck having that shit defined in human.dm >>>>>>:C
//Return something true (lol byond) to allow removal
//Return something false to disallow
//dispose()
//prisoners
//if (name == "mazewarp")
// mazewarp += src.loc
//not prisoners
//Blocks the creation of an asteroid on this tile, as you would expect
//Who fired this?
//radio signal
//Flags:
// 1 for pressure
// 2 for temperature
// 4 for oxygen concentration
// 8 for toxins concentration
// 16 for CO2 concentration
// 32 for N2 concentration
// 64 for other shit
//radio signal
//radio signal
//radio signal
//
// Alarm
//
//Experimenting
//Pressure sensor
//Oxygen Levels Sensor
//Oxygen Levels Sensor
//CO2 Levels Sensor
//Plasma Levels Sensor
// locked = !locked
// boutput(user, "You [ locked ? "lock" : "unlock"] the local air monitor.")
// <-- dumb workaround until atmos processing is better
// completely opaque to air
// stepping around in the field while you're already inside it is fine
// prevent them from running into the field multiple times
//node1, air1, network1 correspond to input
//node2, air2, network2 correspond to output
//
// 1=left 2=right
//Calculate necessary moles to transfer using PV = nRT
//Actually transfer the gas
//
//node2 is output port
//node1 is input port
//0 = siphoning, 1 = releasing
//1: Do not pass external_pressure_bound
//2: Do not pass input_pressure_min
//4: Do not pass output_pressure_max
//to make the little pipe section invisible, the icon changes.
//input -> external
//external -> output
//Radio remote control
//radio signal
//Tries to achieve target pressure at output (like a normal pump) except
// Uses no power but can not transfer gases from a low pressure area to a high pressure area
//
//No need to pump gas if target is already reached or input pressure is too low
//Need at least 10 KPa difference to overcome friction in the mechanism
//Calculate necessary moles to transfer using PV = nRT
//Can not have a pressure delta that would cause output_pressure > input_pressure
//Actually transfer the gas
//
//on = !on
//No need to pump gas if target is already reached!
//Calculate necessary moles to transfer using PV=nRT
//Actually transfer the gas
// cogwerks: adjust the multiplier if needed
//Radio remote control
//radio signal
//ir2, network2 correspond to output
//radio signal
//
// Housekeeping and pipe network stuff below
// Signal air disposing...
//
//No need to mix if target is already full!
//Calculate necessary moles to transfer using PV=nRT
//Actually transfer the gas
//if(filtered_out.temperature)
//removing plasma
//removing O2
//removing N2
//removing CO2
//removing trace gases
// Housekeeping and pipe network stuff below
//
// Signal air disposing...
// Report the status of this mixer over the radio.
//radio signal
//Report gas concentration of input1
//Report gas concentration of input2
//Report transferred concentrations
//Report gas concentration of output
//boutput(world, "[id_tag] posted a signal for [master_id]!")
//No need to mix if target is already full!
//Calculate necessary moles to transfer using PV=nRT
/*else
if(transfer_moles1 != 0)
transfer_moles2 = air_in2_moles
else if (transfer_moles2 != 0)
transfer_moles1 = air_in1_moles*/
//Actually transfer the gas
// Housekeeping and pipe network stuff below
// Problem: Pumps seem to reset the temperature or something??
// Had a pipe on one end of a pump with 240 C, the other end was 20 C.
//
//used when reconstructing a pipeline that broke
//Return 1 if parent should continue checking other pipes
//Return null if parent should stop checking other pipes. Recall: qdel(src) will by default return null
//currently only need red pipes (insulated) to rupture
//oh no it broke and is leaking everywhere
//what do i change back to when repaired???
//This should cut back on the overhead calling build_network thousands of times per cycle
//boutput(world, "Missing node from [src] at [src.x],[src.y],[src.z]")
//boutput(world, "Missing node from [src] at [src.x],[src.y],[src.z]")
// cogwerks - adding an override so pda bombs aren't quite so ruinous in the engine
// hide if turf is not intact
//update_icon()
//in liters, 0.9 meters by 0.9 meters by 2 meters
// Experiment for improving the usefulness of air hookups. They have twice the capacity of portable
// canisters and contain 4 times the volume of their default air mixture (Convair880).
//to make the little pipe section invisible, the icon changes.
// hide if turf is not intact
//update_icon()
//to make the little pipe section invisible, the icon changes.
// Housekeeping and pipe network stuff below
//Ye olde filter of yore (Pre-dev adjustable filter)
//TODO: Hacking.
//
//This is where filtered air comes out. It's this one.
//Percentage of passing gas to consider for transfer.
//Bitfield determining gases to filter.
//Let oxygen through
//Let nitrogen through
//Let CO2 through
//Let plasma through.
//Let trace gases (Like N2O) through.
// "Filter Release Rate:<BR><br><A href='?src=\ref[src];fp=-[num2text(src.maxrate, 9)]'>M</A> <A href='?src=\ref[src];fp=-100000'>-</A> <A href='?src=\ref[src];fp=-10000'>-</A> <A href='?src=\ref[src];fp=-1000'>-</A> <A href='?src=\ref[src];fp=-100'>-</A> <A href='?src=\ref[src];fp=-1'>-</A> [src.f_per] <A href='?src=\ref[src];fp=1'>+</A> <A href='?src=\ref[src];fp=100'>+</A> <A href='?src=\ref[src];fp=1000'>+</A> <A href='?src=\ref[src];fp=10000'>+</A> <A href='?src=\ref[src];fp=100000'>+</A> <A href='?src=\ref[src];fp=[num2text(src.maxrate, 9)]'>M</A><BR><br>"
//Draw the nice little blinky lights that give an at-a-glance indication of filter state.
//No need to mix if target is already full!
//Calculate necessary moles to transfer using PV=nRT
//Actually transfer the gas
//air_in.remove(transfer_moles)
//Unlike the regular filter, we can pick and choose the gas to remove!
//One might say that a little filter being this advanced is rather unrealistic
//However, who gives a fuck.
// Housekeeping and pipe network stuff below
//network_out2 = new_network
//network_in = new_network
// Todo shouldnt this remove the gas mixture? Not sure, this system is complex...
//
//totally random
//todo: have current temperature affected. require power to bring down current temperature again
//MOB_EFFECT_LAYER
// Rigging cryo is advertised in the 'Tip of the Day' list (Convair880).
// Ditto (Convair880).
// this is so ugly i'm sorry for doing it i'll fix it later i promise
//occupant.stat = 1
// Lets expel hot gas and see if that helps people not die as they are removed
// Medbay and kitchen freezers start at correct temperature to avoid pointless busywork.
//
//
//currently the same code as cold_sink but anticipating process() changes
//
//totally random
//todo: have current temperature affected. require power to bring up current temperature again
//
//radio signal
//to make the little pipe section invisible, the icon changes.
//
//
// Housekeeping and pipe network stuff below
//0 = siphoning, 1 = releasing
//1: Do not pass external_pressure_bound
//2: Do not pass internal_pressure_bound
//3: Do not pass either
//internal -> external
//Do not go above environment_pressure
//external -> internal
//Do not go below environment_pressure
//Radio remote control
//radio signal
//to make the little pipe section invisible, the icon changes.
//0 = siphoning, 1 = scrubbing
//
//Take a gas sample
//Filter it
//Remix the resulting gases
//Just siphoning all air
//to make the little pipe section invisible, the icon changes.
//Does this valve have enough grief potential that the admins should be messaged when this is opened?
// can be controlled by AI
//Radio remote control
//radio signal
//
// override default subscribes to be in a different process loop. that's why they don't call parent ( ..() )
// Called by a network associated with this machine when it is being disposed
// This must be implemented to unhook any references to the network
// Check to see if should be added to network. Add self if so and adjust variables appropriately.
// Note don't forget to have neighbors look as well!
// Called to build a network from this node
// Returns pipe_network associated with connection to reference
// Notes: should create network if necessary
// Should never return null
// Used when two pipe_networks are combining
// Return a list of gas_mixture(s) in the object
// associated with reference pipe_network for use in rebuilding the networks gases list
// Is permitted to return null
// screwdriver removed
//////////////////////////////
//The amazing bodyswappitron
////////////////////////////
//Set to one to have the thing regain usability on reboot
//src.overlays.Cut()
//lol cheats
//So it will shut itself down after a while
//We have what we need
//So it won't switch itself off on us
//We're not going to allow you to unbuckle during the process
//Don't die on us mid-process
//We're all here, still
//Just in case A is mindless, try from B's side
//Someone was being clever during the process
//Still standing, you fuck?
//Still standing, you fuck?
//Time to die
//We're now going to allow you to unbuckle
//Failure.
//Something is amiss oh no!
// AI (i.e. game AI, not the AI player) controlled bots
// ID card that the bot "holds".
// For the get_access() proc. Defaults to all-access.
// shut up omg shut up.
// dectalk!
// Generic default. Override for specific bots as needed.
// Navigation procs
// Used for A-star pathfinding
// Returns the surrounding cardinal turfs with open links
// Including through doors openable with the ID
// for(var/turf/simulated/t in oview(src,1))
//if(istype(T) && !T.density)
// Returns true if a link between A and B is blocked
// Movement through doors allowed if ID has access
// diagonal
// Returns true if direction is blocked from loc
// Checks doors against access with given ID
// whatever man
// Todo layer
//t/%/")
//Do not hit the buttbot with the emag tia
//TODO LAYER
// ACTION
// F U C K temporary measure
// fix for cannot read null.name (the food sometimes no longer exists after a sleep (because people eat it I assume)) - haine
// Nobody is in range anyway
// WIP bot improvements (Convair880).
////////////////////////////////////////////// Cleanbot assembly ///////////////////////////////////////
///////////////////////////////////////////////// Cleanbot ///////////////////////////////////////
// Current target.
// Path to current target.
// Targets we weren't able to reach.
// In relation to world time. Clear list periodically.
// How frequently?
// Simple counter. Bot selects new target if current one is too far away.
// In relation to world time. In case there aren't any valid targets nearby.
// For how long?
// Are we currently cleaning something?
// So we don't lube the same turf ad infinitum.
// Turf vs decal when emagged, so we gotta clear it.
// We're still idling.
//DEBUG("Sleeping. [log_loc(src)]")
// Invalid targets may not be unreachable anymore. Clear list periodically.
//DEBUG("[src.emagged ? "(E) " : ""]Cleared target_invalid. [log_loc(src)]")
//DEBUG("[src.emagged ? "(E) " : ""]Selecting new target (frustration). [log_loc(src)]")
// So nearby bots don't go after the same mess.
// Let's find us something to clean.
//DEBUG("[src.emagged ? "(E) " : ""]Acquiring target failed (target_invalid). [F] [log_loc(F)]")
//DEBUG("[src.emagged ? "(E) " : ""]Acquiring target failed (other bot target). [F] [log_loc(F)]")
//DEBUG("[src.emagged ? "(E) " : ""]Acquiring target failed (lubed). [F] [log_loc(F)]")
//DEBUG("[src.emagged ? "(E) " : ""]Acquiring target failed (density). [F] [log_loc(F)]")
//DEBUG("[src.emagged ? "(E) " : ""]Target acquired. [F] [log_loc(F)]")
//DEBUG("[src.emagged ? "(E) " : ""]Acquiring target failed (target_invalid). [D] [log_loc(D)]")
//DEBUG("[src.emagged ? "(E) " : ""]Acquiring target failed (other bot target). [D] [log_loc(D)]")
//DEBUG("[src.emagged ? "(E) " : ""]Target acquired. [D] [log_loc(D)]")
// Still couldn't find one? Abort and retry later.
//DEBUG("[src.emagged ? "(E) " : ""]Acquiring target failed (no valid targets). [log_loc(src)]")
// Let's find us a path to the target.
//DEBUG("[src.emagged ? "(E) " : ""]Acquiring target failed (target density). [T] [log_loc(T)]")
//DEBUG("[src.emagged ? "(E) " : ""]Acquiring target failed (space tile). [T] [log_loc(T)]")
//DEBUG("[src.emagged ? "(E) " : ""]Acquiring target failed (obstruction). [T] [log_loc(T)]")
// Woops, couldn't find a path.
//DEBUG("[src.emagged ? "(E) " : ""]Pathfinding failed. [T] [log_loc(T)]")
// Move towards the target.
//DEBUG("[src.emagged ? "(E) " : ""]Moving towards target. [src.target] [log_loc(src.target)]")
//DEBUG("[src.emagged ? "(E) " : ""]Cleaning target. [src.target] [log_loc(src.target)]")
// migrated from disaster game mode
// by request
//TODO LAYER
// ACTION
// MUSIC
// MUSIC
//Firebot
//Firebot assembly
//TODO LAYER
//It can be stunned by tasers. Delicate circuits.
//To-Do: Patrol the station for fires maybe??
//
//Is the extinguisher added?
// Firebots are used in multiple department, so I guess they get all-access instead of only engineering.
// if(radio_connection)
// radio_controller.add_object(src, "[beacon_freq]")
// dat += "<br>Behaviour controls are [src.locked ? "locked" : "unlocked"]<hr>"
// if(!src.locked)
//To-Do: Behavior control stuff to go with ~fire patrols~
//Swedenfact:
//"Fart" means "speed", so if a policeman pulls you over with the words "fartkontroll" you should not pull your pants down
//More fire resistant than other bots
//src.currently_healing = 0
//Check if this is a mob and we can stop spraying when they are no longer on fire.
// src.currently_healing = 0
//Oh no we're emagged!! Nobody better try to cross us!
//Empty the toolbox so we don't have infinite crowbars or whatever
//Floorbot assemblies
//Floorbot
//TODO LAYER
//weight = 1.0E7
//Regular ID
//checks to see if robot is on
//checks to see if already repairing
//checks if already targeting something
///Code for handling when out of tiles
/////////Search for target code
///Search for space turf
///Search for incomplete floor
///search for tiles
/////////////////////////////////////////////////
///Emagged "repair" ///////////////////////
/////////////////////////////////////////////////
/////////////////////////////////////////
//////Floorbot Construction/////////////
/////////////////////////////////////////
//TODO LAYER
//CONTENTS
//Movement control datum
//Guardbot
//Guardbot tools
//Task datums
//Guardbot parts
//Docking Station
//Old Robuddies (PR-4)
//Robot config constants
//movement datum
//var/compare_movepath = current_movepath
// Same distance cap as the MULE because I'm really tired of various pathfinding issues. Buddy time and docking stations are often way more than 150 steps away.
// It's 200 something steps alone to get from research to the bar on COG2 for instance, and that's pretty much in a straight line.
//Make sure to check it isn't null!!
//Only go UP to the target, not the same tile.
//dispose()
// boutput(world, "[compare_movepath] : [current_movepath]")
//if(compare_movepath != current_movepath)
// break
//dispose()
//The Robot.
//TODO LAYER
//Sleeping on the job??
//Are we stunned?
//Behavior Controls lock
//Are we currently ON THE MOVE?
//var/current_movepath = 0 //If we need to switch movement halfway
//How are you feeling, buddy?
//Our current task.
//All tasks. First one is the current.
//Scratchpad memory for tasks to pass messages.
//Not sure what this should do yet.
//Are we waiting to exit idle mode?
//Have we already done the full startup procedure?
//We have limited power! Immersion!!
//What weapon do we have?
//Call update_icon() in process
// bot control frequency
//World time of last transmission
//So we don't die like five times at once.
//Job access for doors.
//It's not like they can be pushed into airlocks anymore
//no halloween costumes for us!!
//Name doesn't need random number appended to it.
//Spawn a docking station where we are.
//Max charge of internal cell. 1500 ~25 minutes
//Percentage charge of internal cell
//Starting tool.
//Task to run on startup. Duh.
//setup_default_startup_task = /datum/computer/file/guardbot_task/security/patrol
//xmas -- See spacemas.dm
//Returns true if we need to halt process
//(ie we are now off or idle)
//Are we idling?
//Are we waiting to exit the idle state?
//Exit idle state.
//Return to dock for new instructions.
//if it's an energy shot but does no damage, ie. taser rather than laser
//Oh no! We have been hit by an EMP grenade!
//qdel(src.mover)
//This is why it is called "throwparts"
//Delete the overlay when finished with it.
//Get out of idle state and prepare anything that needs preparing I guess
//Also called after recovery from stunning.
//Already snoozing.
//src.target = null
//src.secondary_targets.len = 0
//ugh it's some dude just flicking the switch.
//src.target = null
//qdel(src.mover)
//boutput(world, "TEST: Navigate to [target]")
//current_movepath = world.time
// drsingh for cannot modify null.delay
//, GUARDBOT_RADIO_RANGE)
//Clear overlays so it will update on update_icon call
//TODO LAYER
//Robot tools. Flash boards, batons, etc
//Can it be non-lethal?
//Can it be lethal?
//Identification ID.
//1 Is ranged, 0 is melee.
//If we want a use delay.
//A syringe gun module. Mercy sakes.
//Can be both nonlethal and lethal
//Depends on reagent load.
// Updated for new projectile code (Convair880).
//Short-range smoke riot control module
// Fixed. Was completely non-functional (Convair880).
//Taser tool
// Updated for new projectile code (Convair880).
//Flash tool
// We're flashing somebody directly, hence the 100% chance to disrupt cloaking device at the end.
//Electrobolt tool. Basically, Keelin owns ok
//Can be both nonlethal and lethal
//Probably unsafe.
//xmas -- See spacemas.dm
//Task Datums
//Computer datum so it can be transmitted over radio
//Small allcaps id for task
//Can we handle beacon signals?
//Return true if there is a new target, false otherwise
//Recharge task
//If 0: return to recharge, if 1: return for new programming
//master.snooze() //Connect autosnoozes the bot.
//master.reply_wait = 0
//Buddytime task -- Even buddies need to relax sometimes!
//Location of bar beacon
//Emotion to express during buddytime.
//Tag of the bar beacon
//Seeking the bar.
//master.current_movepath = "HEH"
//Seeking a seat.
//IT IS RUMPUS TIME
//boutput(world, "patrol task received")
// if the recvd beacon location matches the set destination
// then we will navigate there
//Guardbots don't like beepsky. They think he's a jerk. They are right.
//Huh? We haven't lost him.
//Definitely beepsky in this case.
//Security/Patrol task -- Essentially secbot emulation.
// pending new destination (waiting for beacon response)
// destination description tag
// the next destination in the patrol route
// the nearest beacon's tag
// the nearest beacon's location
//Dudes we are preprogrammed to arrest.
//0: Patrol, 1: Arresting somebody
//These guys can use guns, ok!
//Do we use lethal force (if possible) ?
//Martial law! Arrest all kinds!!
//Don't patrol.
//Delay between movements when chasing a criminal, slightly faster than usual. (2.5 vs 3)
//Tenths of a second between cute actions
//Already chasing somebody
//Let's find us a criminal
//master.current_movepath = "HEH"
//qdel(master.mover)
//qdel(master.mover)
//Put in here instead of right after attack so gun robuddies don't get confused
//if(H.bioHolder.HasEffect("lost_left_arm") || H.bioHolder.HasEffect("lost_right_arm"))
//master.current_movepath = "HEH" //Stop any current movement.
//boutput(world, "patrol task received")
// if the recvd beacon location matches the set destination
// then we will navigate there
//So a patrol group doesn't bunch up on a single tile.
// if looking for nearest beacon
// note we ignore the beacon we are located at
//Already chasing somebody
//Let's find us a criminal
// else
// if(isalien(C))
// threat = 9
//hugs!!
// awaiting beacon response
// if(istype(perp.mutantrace, /datum/mutantrace/zombie))
// return 5 //Zombies are bad news!
// threatcount += 2
//Go trick or treating!
//Let's get some candy!
// else
// if(isalien(C))
// threat = 9
//master.current_movepath = "HEH"
//qdel(master.mover)
//Arrest anyone who isn't a DWAINE superuser.
//todo
//Bodyguard Task -- Guard some dude's personal space
//0: Following protectee, 1: Arresting threat
//Do we use lethal force (if possible) ?
//Has our buddy hit us? Buddy abuse is a serious problem.
//Our buddy kinda sucks :(
//Who are we seeking?
//Priority one: Arrest a jerk who hurt our buddy.
//Priority two: Assess status of buddy.
//Should ONLY return true when we pick up a new arrest target.
//So we don't have to wait for the next process. LIVES ARE ON THE LINE HERE!
//qdel(master.mover)
//qdel(master.mover)
// src.arrest_target = null
//Search for a mob in view with the name we are programmed to guard.
//We have someone to protect!
//We were too late!
//if (buddy_is_dork && prob(50))
//master.speak(pick("I am here to protect...Oh, it's <i>you</i>.", "I have been instructed to guard you. Welp.", "You are now under guard. I guess."))
//Out of sight, out of mind.
//Has our buddy been attacked??
//qdel(master.mover)
//Search for a mob in view with the name we are programmed to guard.
//We have someone to protect!
//We were too late!
//src.desired_emotion = GUARDING_EMOTION
//Byond, enums, lack thereof, etc
//Neat things we've seen on this trip
//Note: this is the last one the bitfield can fit. Thanks, byond!!
//Wait for people to be around before giving tour dialog?
//Bitfield to mark neat things seen on a tour.
//Method of operation:
//Locate starting beacon or last beacon
//Check name of beacon against list of visited beacons.
//Interrogate beacon for information string, if any
//Say information string once our tourgroup (or some random doofus, it doesn't really matter) has arrived.
//Locate next beacon OR finish if none defined.
//Maybe we shouldn't speak to no-one??
//I realize this doesn't check if they're dead. Buddies can't always tell, ok!! Maybe if people had helpful power lights too
//There are pauses present! So, um, pause.
//This will just serve as a delay so the buddy isn't zipping around at light speed between stops.
// if the recvd beacon location matches the set destination
// then we will navigate there
//We're going to make him sad until the end of this spawn, ok.
// || (H.ckey in Dorks))) //If this is too mean to clarks, remove that part I guess
//Notify other buddy
//As before, notify the other buddy
//Be kind, undefine...d
//Let's find us a criminal
// else
// if(isalien(C))
// threat = 9
//Default task path of result
//Name of resulting guardbot
//What type of guardbot does this belong to (Default is PR-6, but Murray and Marty are PR-4s)
//Still the name of resulting guardbot
//Default task path of result
//Initial model task of result.
//Tool module of result.
//Energy cell of result.
//What type of guardbot does this belong to (Default is PR-6, but Murray and Marty are PR-4s)
//Frame -> Add cell -> Add tool -> Add core -> Add arm -> Done
//The Docking Station. Recharge here!
//1: Eject fully charged robots automatically. 2: Eject robot when living carbon mob is in view.
//What is our network id???
//Who is linked to us?
//A reset button is useful for when the system gets all confused.
//Last world.time we were manually reset.
//Send a reply for those curious jerks
//Terminal interface stuff.
//Sign up with the driver (if a mainframe contacted us)
//Huh, who is this?
//Status of connected bot.
//status += "&botid=[current.net_id]"
//Eject current bot
//eject_robot alerts the host on its own
//Original one will be deleted with the signal.
//Clear other tasks?
//Replace model (default task)?
//Task inquiry.
//Clear tasks of current bot
//No new task, normal priority, wipe all others.
//So robots don't swarm one of the stations.
//if(!O:idle)
// O:snooze()
//Alert system host of this development!!
//This is why it is called "throwparts"
//Delete the overlay when finished with it.
//A tourguide for "the crunch"
//src.hat = new /obj/item/clothing/head/helmet/space/santahat(src)
//MEDBOT
//MEDBOT PATHFINDING
//MEDBOT ASSEMBLY
//TODO LAYER
//It can be stunned by tasers. Delicate circuits.
//Can be set to draw from this for reagents.
// options are brute1/2, burn1/2, toxin1/2, brain1/2, O21/2/3/4, berserk1/2/3, and psyche
//Don't spam the "HEY I'M COMING" messages
//How much reagent do we inject at a time?
//Start healing when they have this much damage in a category
//Use reagents in beaker instead of default treatment agents.
//Setting which reagents to use to treat what by default. By id.
// for making the medbots all super fucked up
// don't drag it into space goddamn jerks
// so we don't have to have two sets of the skin sprites, we're just gunna bump this up a bit
//To preserve the name if it's a unique medbot I guess
// same as the bots themselves: options are brute1/2, burn1/2, toxin1/2, brain1/2, O21/2/3/4, berserk1/2/3, and psyche
//if (istype(W, /obj/item/card/emag)) // this gets to stay here because it is a good story
//return
// I stole this from the chefbot <3 u marq ur a beter codr then me
//Time to find a patient!
//Don't spam these messages!
//Time to see if they need medical help!
//welp too late for them!
//Kevorkian school of robotic medical assistants.
//Everyone needs our medicine. (Our medicine is toxins)
//If they're injured, we're using a beaker, and don't have one of our WONDERCHEMS.
//They're injured enough for it!
//If they're already medicated don't bother!
//STOP DISEASE FOREVER
//Use whatever is inside the loaded beaker. If there is one.
//Emagged! Time to poison everybody.
// HEH
//If they don't need any of that they're probably cured!
//Inject from beaker instead.
// let's grustle a bit
// src.speak(reagent_id)
// copied from transposed scientists
// fart
// farto
/* all of this is kinda needlessly complicated imo
if (istype(src, /obj/item/storage/firstaid/fire))
A.skin = "ointment"
else if (istype(src, /obj/item/storage/firstaid/toxin))
A.skin = "tox"
else if (istype(src, /obj/item/storage/firstaid/oxygen))
A.skin = "o2"
else if (istype(src, /obj/item/storage/firstaid/brain))
A.skin = "red"
else if (istype(src, /obj/item/storage/firstaid/brute))
A.skin = "brute"
*/
// Mulebot - carries crates around for Quartermaster
// Navigates via floor navbeacons
// Remote Controlled from QM's PDA
// the loaded crate (usually)
// this is turf to navigate to (location of beacon)
// this the direction to unload onto/load from
// pending new destination (waiting for beacon response)
// destination description
// tag of home beacon
//0 = idle/ready
//1 = loading/unloading
//2 = moving to deliver
//3 = returning to home
//4 = blocked
//5 = computing navigation
//6 = waiting for nav computation
//7 = no destination beacon found (or no route)
//number of times retried a blocked path
//true if already reached the target
// true to refresh dialogue
// true if auto return to home beacon after unload
// true if auto-pickup at beacon
// true if maint hatch is open
// the installed power cell
// constants for internal wiring bitflags
// power connections
// mob avoidance
// load checking (non-crate)
// motor wires
//
// remote recv functions
// remote trans status
// beacon ping recv
// beacon ping trans
// all flags on
// list of wire colours
// order of wire indices
// count of bloodiness
// must wait for map loading to finish
// set up the wire colours in random order
// and the random wire display order
// needs 10 wire colours
// attack by item
// emag : lock/unlock,
// screwdriver: open/close hatch
// cell: insert it
// other: chance to knock rider off bot
// chance to knock off rider
//?src=\ref[src];op=unlock'><I>(unlock)</I></A>"
//?src=\ref[src];op=lock'><I>(lock)</I></A><BR><BR>"
//?src=\ref[src];op=power'>Toggle Power</A><BR>"
//?src=\ref[src];op=stop'>Stop</A><BR>"
//?src=\ref[src];op=go'>Proceed</A><BR>"
//?src=\ref[src];op=home'>Return to Home</A><BR>"
//?src=\ref[src];op=destination'>Set Destination</A><BR>"
//?src=\ref[src];op=setid'>Set Bot ID</A><BR>"
//?src=\ref[src];op=sethome'>Set Home</A><BR>"
//?src=\ref[src];op=autoret'>Toggle Auto Return Home</A> ([auto_return ? "On":"Off"])<BR>"
//?src=\ref[src];op=autopick'>Toggle Auto Pickup Crate</A> ([auto_pickup ? "On":"Off"])<BR>"
//?src=\ref[src];op=unload'>Unload Now</A><BR>"
//?src=\ref[src];op=cellremove'>Installed</A><BR>"
//?src=\ref[src];op=cellinsert'>Removed</A><BR>"
// returns the wire panel text
//?src=\ref[src];op=wirecut;wire=[index]'>(cut)</A> <A href='byond://?src=\ref[src];op=wirepulse;wire=[index]'>(pulse)</A><BR>"
//?src=\ref[src];op=wiremend;wire=[index]'>(mend)</A><BR>"
// returns true if the bot has power
// mousedrop a crate to load the bot
// called to load a crate
// if a create, close before loading
// called to unload the bot
// argument is optional direction to unload
// if zero, unload at bot's location
// in case non-load items end up in contents, dump every else too
// this seems to happen sometimes due to race conditions
// with items dropping as mobs are loaded
//boutput(world, "speed: [speed]")
// 0 is can't move, 1 is fastest, 3 is slowest (normal unhacked)
// do nothing
//if(mode) boutput(world, "Mode: [mode]")
// idle
// loading/unloading
// navigating to deliver,home, or blocked
// reached target
// valid path
//boutput(world, "at ([x],[y]) moving to ([next.x],[next.y])")
// attempt to move
// successful move
//boutput(world, "Successful move.")
// failed to move
//boutput(world, "Unable to move.")
// attempt 5 times before recomputing
// find new path excluding blocked turf
//boutput(world, "Bad turf.")
//boutput(world, "No path.")
// calculate new path
//boutput(world, "Calc new path.")
//if(6)
//boutput(world, "Pending path calc.")
//if(7)
//boutput(world, "No dest / no route.")
// calculates a path to the current destination
// given an optional turf to avoid
// sets the current destination
// signals all beacons matching the delivery code
// beacons will return a signal giving their locations
// starts bot moving to current destination
// starts bot moving to home
// sends a beacon query to find
// called when bot reaches current target
// if loaded, unload at target
// not loaded
// find a crate
// if emagged, load first unanchored thing we find
// otherwise, look for crates only
// whatever happened, check to see if we return home
// auto return set and not at home already
// otherwise go idle
// report status to anyone listening
// called when bot bumps into anything
//usually just bumps, but if avoidance disabled knock over mobs
// called from mob/living/carbon/human/HasEntered()
// when mulebot is in the same loc
// player on mulebot attempted to move
// receive a radio signal
// used for control and beacon reception
// process all-bot input
// process control input
// receive response from beacon
// if the recvd beacon location matches the set destination
// the we will navigate there
// this will be the load/unload dir
// send a radio signal with a single data key/value pair
// send a radio signal with multiple data key/values
//boutput(world, "sent [key],[keyval[key]] on [freq]")
// signals bot status etc. to controller
//TODO LAYER
// weight = 1.0E7
// Our baton.
//Behavior Controls lock
//Loc of target when arrested.
//There's a delay
//Emagged Secbots view everyone as a criminal
//If false, all station IDs are authorized for weapons.
//Does it check security records?
//If true, don't handcuff
//If true, report arrests over PDA messages.
//Job access for doors.
//Add an overlay from aibots.dmi with this state. hats.
// idle
// found target, hunting
// at target, preparing to arrest
// arresting target
// start patrol
// patrolling
// summoned by PDA
// set to make bot automatically patrol
// navigation beacon frequency
// bot control frequency
// this is turf to navigate to (location of beacon)
// pending new destination (waiting for beacon response)
// destination description tag
// the next destination in the patrol route
// list of path turfs
//Are we currently ON THE MOVE?
//number of times retried a blocked path
// count of pticks awaiting a beacon response
// the nearest beacon's tag
// the nearest beacon's location
//To preserve the name if it's a unique securitron I guess
//If it's running on another beacon circuit I guess
// drsingh for cannot modify null.delay
// drsingh again for the same thing further down in a moment.
// Because master_move can delete the mover
// idle
// see if any criminals are in range
// still idle, and set to patrol
// switch to patrol mode
// hunting for perp
// if can't reach perp for long enough, go idle
// for(var/mob/O in hearers(src, null))
// boutput(O, "<span class='game say'><span class='name'>[src]</span> beeps, \"Backup requested! Suspect has evaded arrest.\"")
//qdel(src.mover)
//walk_to(src,0)
// make sure target exists
// if right next to perp
// No need for unnecessary hassle, just make it ignore charges entirely for the time being.
//qdel(src.mover)
//current_movepath = "HEH" //Stop any current movement.
// not next to perp
//qdel(src.mover)
// preparing to arrest target
// see if he got away
//if(H.bioHolder.HasEffect("lost_left_arm") || H.bioHolder.HasEffect("lost_right_arm"))
// var/arrest_message = pick("Have a secure day!","I AM THE LAW.", "God made tomorrow for the crooks we don't catch today.","You can't outrun a radio.")
// src.speak(arrest_message)
//////PDA NOTIFY/////
// arresting
//qdel(src.mover)
//qdel(src.mover)
// start a patrol
// have a valid path, so just resume
// has patrol target already
// so just find a route to it
// no patrol target, so need a new one
//speak("Engaging patrol mode.")
// patrol mode
// summoned to PDA
// perform a single patrol step
// reached target
// valid path
// attempt to move
// successful move
// failed to move
// attempt 5 times before recomputing
// find new path excluding blocked turf
// not a valid turf
// no path, so calculate new one
// finds a new patrol target
// awaiting beacon response
// wait 5 secs for beacon response
// then go to nearest instead
// finds the nearest beacon to self
// signals all beacons matching the patrol code
//speak("Disengaging patrol mode.")
// sets the current destination
// signals all beacons matching the patrol code
// beacons will return a signal giving their locations
// receive a radio signal
// used for beacon reception
// process all-bot input
// check to see if we are the commanded bot
// process control input
// receive response from beacon
// if the recvd beacon location matches the set destination
// the we will navigate there
// if looking for nearest beacon
// note we ignore the beacon we are located at
// send a radio signal with a single data key/value pair
// send a radio signal with multiple data key/values
//boutput(world, "sent [key],[keyval[key]] on [freq]")
// signals bot status etc. to controller
// calculates a path to the current destination
// given an optional turf to avoid
// look for a criminal in view of the bot
//Let's find us a criminal
// ensure bot quickly responds to a perp
// sorry for making a mess here i will clean it up later i promise xoxoxo -drsingh
//If the security records say to arrest them, arrest them
//Or if they have weapons and aren't security, arrest them.
//Everyone is a criminal!
//Corrupt cops cannot exist, beep boop
//Agent cards lower threatlevel when normal idchecking is off.
//Generally we want to explode() instead of just deleting the securitron.
// Not charged when dropped (ran on Beepsky's internal battery or whatever).
//movement control datum. Why yes, this is copied from guardbot.dm
//dispose()
//Make sure to check it isn't null!!
//Only go UP to the target, not the same tile.
//if(master.task)
// master.task.task_input("path_error")
//dispose()
// boutput(world, "[compare_movepath] : [current_movepath]")
//dispose()
//Secbot Construction
//Eh, but we don't want people making secbots out of space helmets.
// fart
//TODO LAYER
//This camera is a node pointing to the other bunch of cameras nearby for AI movement purposes
//Here's a list of cameras pointing to this camera for reprocessing purposes
// why not.
// making life easy for mappers since 2013
//Safe addition
//Completely remove a node from this camera
//In case the GC does not have time to remove us from the referring cameras
//logTheThing("debug", null, null, "<B>SpyGuy/Camnet:</B> Camera destroyed. Camera network needs a rebuild! Number of dirty cameras: [dirty_cameras.len]")
//connect_camera_list(referrers)
//Not the best way but it will do. I think.
//Other silicon mobs shouldn't try to encroach on the AI's "view through all cameras" schtick. Mostly because it generates runtime errors.
//if (istype(user, /mob/living/silicon/ai/hologram))
// return
// v the fuck is this??? v
/*/obj/machinery/camera/attack_hand(mob/user as mob)
if(user.jew == 1)
src.status = !( src.status )
if (!( src.status ))
var/message = pick("OY VEY!","Bupkes!","Feh!","What a mishegas!","Schlocky putz!")
user.say(message)
src.icon_state = "camera1"
else
var/message = pick("OY VEY!","Bupkes!","Feh!","What a mishegas!","Schlocky putz!")
user.say(message)
src.icon_state = "camera"
// now disconnect anyone using the camera
disconnect_viewers()
else
return
return*/
//dumb easter egg incoming
// now disconnect anyone using the camera
//Return a working camera that can see a given mob
//or null if none
// check if camera disabled
// motion camera event loop
// start the clock
// call the parent to (de|re)activate
// now handle alarm on/off...
// ok we've just been reconnected... send an alarm!
// manually cancel, to not disturb internal state
/*------------------------------------
CAMERA NETWORK STUFF
------------------------------------*/
//This is one of those weird internal cameras, or it's been deleted and hasn't had the decency to go away yet
//The direction we're trying to fill
//The reciprocal of this direction
// && (!camera_network_reciprocity || !candidate.vars[rec_var]))
// power per tick
//boutput(world, "nl: [newlevel]")
//boutput(world, "ccpt [charging] [stat]")
// vOv
//For premature unlocking.
//The clone is released once its health reaches this level.
//So we remember the connected clone machine.
//Need to clean out it if it's full of exploded clone.
//One clone attempt at a time thanks
//Don't eject them as soon as they are created fuckkk
//Are we part of a port-a-clone?
//Are we currently cloning some duder?
//Are we analysing the genes while reassembling the duder? (read: Do we work faster or do we give a material bonus?)
//Normal generation speed
// goes up while someone is stuck in there and there's not enough meat to clone them, after so many ticks they'll get dumped out
//This will be used for genetics bonuses when cloning
//Bye bye
// no need here
//Start growing a human clone in the pod!
//One at a time!!
// make sure we start here
// This should already be a copy.
//Get the clone body ready
//Organs may not exist yet if we call this right away.
//Genetic degradation! Oh no!!
//Here let's calculate their health so the pod doesn't immediately eject them!!!
//No null names!!
//Move that mind over!!
//welp
// -- Mode/mind specific stuff goes here
//So the icon actually appears
// -- End mode specific stuff
//Don't leave ghosts everywhere!!
//Grow clones to maturity then kick them out. FREELOADERS
//Autoeject if power is lost
//Autoeject corpses and suiciding dudes.
// you been in there too long, get out
// halfway to ejection
//Slowly get that clone healed and finished.
//At this rate one clone takes about 95 seconds to produce.(with heal_level 90)
//Premature clones may have brain damage.
//So clones don't die of oxy damage in a running pod.
// cogwerks: changed from epinephrine
// lowering this but keeping it in a fully value range
// cogwerks: adding this because it'll be funny when someone gets scanned
// cogwerks: adding this because it'll be funny when someone gets scanned
//Also heal some oxy ourselves because epinephrine is so bad at preventing it!!
// cogwerks: speeding this up too
//This might need tweaking.
// go_out() updates icon too, so vOv
//Welp. Where did you go? Jerk.
//Let's unlock this early I guess.
//This is needed to suppress the SYNDI CAT HITS CLONING POD message *cry
// why was there a 2 here? it was injecting ice cold reagents that burn people
//Put messages in the connected computer's temp var for display.
//Welp
//Clean that mess and dump those gibs!
// we don't need to do if/else things just to say "put gibs on this thing's turf"
// cogwerks - let's spread that mess instead of having a pile! bahaha
// this seems to often not work right, changing 20 to 50
// STOP FUCKING SUFFOCATING GOD DAMN
// no more cloning with heart failure
//If it's still set somehow.
//Only operate nominally for non-shit cloners
//If the analysis feature is disabled, then generate the clone slightly faster
//SOME SCRAPS I GUESS
/* EMP grenade/spell effect
if(istype(A, /obj/machinery/clonepod))
A:malfunction()
*/
//WHAT DO YOU WANT FROM ME(AT)
//Meat that we want to reclaim.
//To be honest, I added the meat reclamation thing in part because I wanted a "max_meat" var.
// give an equal amount of reagents to each pod that happens to be around
//var/obj/machinery/clonepod/nearbyPod = locate(/obj/machinery/clonepod) in orange(1, src)
//if (istype(nearbyPod))
//src.reagents.trans_to(nearbyPod, 1000)
/////////////////////////////////////// General Announcement Computer
//Temporary message, for attack messages, etc
//Player health/attack points
//Enemy health/attack points
//Player cannot attack/heal while set
//?src=\ref[src];close=1'>Close</a>"
//?src=\ref[src];newgame=1'>New Game</a>"
//?src=\ref[src];attack=1'>Attack</a> | "
//?src=\ref[src];heal=1'>Heal</a> | "
//?src=\ref[src];charge=1'>Recharge Power</a>"
//Reset everything
/*CONTENTS
Gas Sensor
Siphon computer
Atmos alert computer
*/
//the atmos alerts computer
// weight = 1.0E8
//obj/item/circuitboard/med_data
// name = "Circuit board (Medical)"
// computertype = "/obj/machinery/computer/med_data"
//obj/item/circuitboard/shield
// name = "Circuit board (Shield Control)"
// computertype = "/obj/machinery/computer/stationshield"
//Wire: fix for Cannot read null.amount (&& P)
//my_cable = P:take(5, src) // Haine: fix for Cannot execute null.set loc()
//my_cable.set_loc(src.loc) // Haine: fix for Cannot execute null.set loc()
//my_cable = null
// accessing crew manifest
//When both IDs are inserted
//Jobs organised into sections
//make sure there isn't a line break in the middle of a job
//Change access to individual areas
//Organised into sections
/* Conor12: I removed some unused accesses as the page is large enough, add these if they ever get used:
3 (access_armory). Replaced by HoS-exclusive access_maxsec.
21 (access_all_personal_lockers). Current personal lockers don't have a master key.
36 (access_mail)
42 (access_engineering_eva)*/
//Click these to remove access
//Click these to add access
//Cloning revival method.
//The pod handles the actual cloning while the computer manages the clone profiles
//Only used for record deletion right now.
//Linked scanner. For scanning.
//Linked cloning pod.
//Which menu screen to display
//Mostly so the geneticist can steal somebody's identity while pretending to give them a handy backup profile.
// one free clone
//Can the dead be scanned in the cloner?
//override new() proc and proximity check, for port-a-clones
//?src=\ref[src];refresh=1'>Refresh</a></font>
//Scan someone
//?src=\ref[src];scan=1'>Scan - [src.scanner.occupant]</a>"
//?src=\ref[src];lock=1'>[src.scanner.locked ? "Locked" : "Unlocked"]</a><BR>"
//?src=\ref[src];menu=5'>Genetic Analysis Mode</a><br>
//?src=\ref[src];menu=2'>View Records</a><br>"}
//?src=\ref[src];disk=eject'>Eject Disk</a>"
//Viewing records
//?src=\ref[src];menu=1'>Back</a><br><br>"}
//?src=\ref[src];view_rec=\ref[R]'>[R.fields["id"]]-[R.fields["name"]]</a><br>"
//Viewing details of record
//?src=\ref[src];menu=2'>Back</a><br>"}
//?src=\ref[src];del_rec=1'>Delete Record</a></font><br>
//?src=\ref[src];disk=load'>Load from disk.</a>
//?src=\ref[src];save_disk=holder'>Complete</a>
//Keeping a line empty for appearances I guess.
//?src=\ref[src];clone=\ref[src.active_record]'>Clone</a><br>"}
//Deleting a record
//?src=\ref[src];del_rec=1'>Yes</a></b><br>
//?src=\ref[src];menu=3'>No</a></b>"}
//Advanced genetics analysis
//?src=\ref[src];menu=1'>Back</a><br>
//?src=\ref[src];set_analysis=0'>Disable</A><BR>"}
//?src=\ref[src];set_analysis=1'>Enable</A><BR>
//No locking an open scanner.
//If we are viewing a record, confirm deletion
//Load or eject.
//Save to disk!
//Save as Ui/Ui+Ue/Se
//Look for that player! They better be dead!
//Can't clone without someone to clone. Or a pod. Or if the pod is busy. Or full of gibs.
// most helpful error message in THE HISTORY OF THE WORLD
//Add an implant if needed
// imp.implanted = subject // this isn't how this works with new implants sheesh
//Update it if needed
//Save that mind so traitors can continue traitoring after cloning.
//Find a specific record by key.
//New loading/storing records is a todo while I determine how it should work.
//Find a dead mob with a brain and client.
//Dead people only thanks!
//They need a brain!
// The communications computer
// main interface
// Status display stuff
// AI interface
//deactivate firealarms
//open airlocks
// give the AI a different interact proc to limit its access
// dat += "<BR>\[ <A HREF='?src=\ref[src];operation=call-prison'>Send Prison Shutle</A> \]"
// dat += "<BR>\[ <A HREF='?src=\ref[src];operation=call-prison'>Send Prison Shutle</A> \]"
// hack to display shuttle timer
/*if(istype(ticker.mode, /datum/game_mode/sandbox))
boutput(usr, "Under directive 7-10, [station_name()] is quarantined until further notice.")
return*/
/*if(istype(ticker.mode, /datum/game_mode/sandbox))
boutput(user, "Under directive 7-10, [station_name()] is quarantined until further notice.")
return 1*/
//marker4
// var/authenticated = 0.0 if anyone wants to make it so you need to log in in future go ahead.
//radio signal
//radio signal
//radio signal
//radio signal
//radio signal
//radio signal
//radio signal
//radio signal
//radio signal
//radio
//Oh, someone is asking us for data instead of reporting a thing.
//boutput(world, "[id] actually can recieve a signal!")
//boutput(world, "[id] recieved a signal from [id_tag]!")
//radio
//
//src.projector.projection = null
//| <A HREF='?src=\ref[user];update=1'>Update</A>"
// if (href_list["update"])
// src.interact(usr)
//src.connected.drive() *****RM from 40.93.3S
//generate appropriate circuitboard. Accounts for /pod/old computer types
//it's not an old computer. Generate standard pod circuitboard.
//generate appropriate circuitboard. Accounts for /pod/old computer types
//it's not an old computer. Generate standard pod circuitboard.
//Foreach goto(172)
/*****RM from 40.93.3S
else
dat += text("<BR><br><A href = '?src=\ref[];door=1'>Toggle Outer Door</A><BR>", src)
//*****
dat += text("<BR><BR><A href='?action=mach_close&window=computer'>Close</A></TT></BODY></HTML>")
if(istype(src, /obj/machinery/computer/pod/old/swf))
dat = "<HTML><BODY><TT><B>Magix IV Shuttle and Teleport Control</B>"
if(!src.TPR)
dat += "<BR><BR><BR><A href='byond://?src=\ref[src];spell_teleport=1'>Teleport</A><BR>"
else
dat += "<BR><BR><BR>RECHARGING TELEPORT<BR><DD>Please stand by...</DD>"
dat += text("<BR><BR><A href = '?src=\ref[];door=1'>Toggle Outer Door</A><BR>", src)
dat += text("<BR><BR><A href='?action=mach_close&window=computer'>Close</A></TT></BODY></HTML>")
user << browse(dat, "window=computer;size=400x500")
onclose(user, "computer")
return
/obj/machinery/computer/pod/process()
..()
if (src.timing)
if (src.time > 0)
src.time = round(src.time) - 1
else
alarm()
src.time = 0
src.timing = 0
src.updateDialog()
return
/obj/machinery/computer/pod/Topic(href, href_list)
if(..())
return
if ((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon)))
usr.machine = src
if (href_list["spell_teleport"])
src.TPR = 1
spawn(600)
if(src)
src.TPR = 0
src.updateDialog()
usr.machine = null
usr << browse(null, "window=computer")
usr.teleportscroll(1, 2, src)
return
if (href_list["power"])
var/t = text2num(href_list["power"])
t = min(max(0.25, t), 16)
if (src.connected)
src.connected.power = t
else
if (href_list["alarm"])
src.alarm()
else
if (href_list["time"])
src.timing = text2num(href_list["time"])
else
if (href_list["tp"])
var/tp = text2num(href_list["tp"])
src.time += tp
src.time = min(max(round(src.time), 0), 120)
else
if (href_list["door"])
for(var/obj/machinery/door/poddoor/M)
if (M.id == src.id)
if (M.density)
spawn( 0 )
M.open()
return
else
spawn( 0 )
M.close()
return
//Foreach goto(298)
src.add_fingerprint(usr)
src.updateUsrDialog()
return
//<A href='?src=\ref[src];vieworders=1'>View Approved Orders</A><BR><BR> This right here never worked anyway.
//Well, let's not emag this.
//buy it with their money
// pda alert ////////
//////////////////
// pda alert ////////
//////////////////
////// PDA NOTIFY/////
//////////
//These will be used to not update the price list needlessly
//I guess you'll wanna put the emag away now instead of getting a massive popup
//If this is a supply order we came from the request approval form
//Comes from the orderform
//Okay, the market has updated and we need a new price list
// whoops, you've pissed them off and now they're going to fuck off
// yeah sure let's reduce the barter into negative numbers, herp derp
// whoops, you've pissed them off and now they're going to fuck off
// unless they've got negative patience in which case haggle all you like
// yeah sure let's reduce the barter into negative numbers, herp derp
//src.temp += "<A href='?src=\ref[src];trader_cart=\ref[T]'>Refresh</A><BR>"
//
// if(href_list["read"])
//if(!A.weapon_lock)
//dat += "<A href='?src=\ref[src];lock=1;ai=\ref[A]'>Emergency Lockout AI *Swipe ID*</A><BR>"
//else
//dat += "Time left:[A.weaponlock_time] | "
//dat += "<A href='?src=\ref[src];lock=2;ai=\ref[A]'>Cancel Lockout</A><BR>"
// more like 180 really but whatever
//Foreach goto(136)
//R = null
//Foreach goto(497)
//todo: sanitize these fucking inputs jesus christ
//src.active2 = null
//R = null
//src.active2 = null
//src.active1 = null
//Foreach continue //goto(2614)
//Foreach continue //goto(3414)
//Foreach continue //goto(3502)
//Foreach continue //goto(3708)
//Foreach continue //goto(3813)
// -------------------- VR --------------------
// --------------------------------------------
//var/list/D = list()
//D["Cancel"] = "Cancel"
//D[.] = C
//?src=\ref[src];camera=\ref[C]' style='display:block;'><div>[.]</div></a>", "camera_console.camlist")
// Must appear over cockpit shuttle wall thingy.
// Must appear over cockpit shuttle wall thingy.
// Must appear over cockpit shuttle wall thingy.
// Must appear over cockpit shuttle wall thingy.
// 0 for bottom, 1 for top
// 0 for bottom, 1 for top
//no access
//no access
//doesn't have this access
//src.authorized = null
//?src=\ref[src];close=1'>Close</a><BR><BR>"
//?src=\ref[src];send=1'>Move Shuttle</a><BR><BR>"
//?src=\ref[src];close=1'>Close</a><BR><BR>"
//?src=\ref[src];send=1'>Move Shuttle</a><BR><BR>"
//Prison -> Station -> Outpost -> Prison.
//Skip outpost if there's a lockdown there.
//drsingh took outpost out for cogmap prison shuttle
//if(researchshuttle_lockdown)
//else
//end_location = locate(/area/shuttle/brig/outpost)
//if(researchshuttle_lockdown)
//else
//brigshuttle_location = 2
//?src=\ref[src];close=1'>Close</a><BR><BR>"
//?src=\ref[src];send=1'>Move Shuttle</a><BR><BR>"
// ehh
//?src=\ref[src];close=1'>Close</a><BR><BR>"
//?src=\ref[src];send=1'>Move Elevator</a><BR><BR>"
// at bottom
// at top
// oh dear, stay behind the yellow line kids
//?src=\ref[src];close=1'>Close</a><BR><BR>"
//?src=\ref[src];send=1'>Move Elevator</a><BR><BR>"
// at bottom
// at top
// oh dear, stay behind the yellow line kids
// Called by the telegun etc (Convair880).
// Not linked to a working portal ring.
// No power.
// All good.
// Not locked in.
//if(!istype(src,/obj/machinery/computer/security/telescreen))
//src.icon_state = "c_unpowered"
//365 F is a good frying temp, right?
// Logging for the deep fryer (Convair880).
// For player monkeys (Convair880).
// I'd love to have some thermostat logic here to make it heat up / cool down slowly but aaaaAAAAAAAAAAAAA (exposing it to the frytemp is too slow)
//Welp!
//, src.fryitem.dir, 1)
//Things can get dropped somehow sometimes ok
// Ghosts probably shouldn't be able to take revenge on a traitor chef or whatever (Convair880).
//SN src = null
//SN src = null
//SN src = null
//SN src = null
// NOOOOOOO
//var/datum/ailment/disease/new_ailment = new D.disease_path
//src.active_vial.contained = new_ailment
//new_ailment.spread = D.spread
//new_ailment.cure = D.cure
//new_ailment.name = D.disease_name
//new_ailment.stage_prob = D.stage_prob
//new_ailment.curable = D.curable
//new_ailment.regress = D.regress
//new_ailment.vaccine = D.vaccine
//var/datum/reagent/disease/R = null
//for(var/A in typesof(/datum/reagent/disease) - /datum/reagent/disease)
// R = new A()
// if (R.id == new_ailment.associated_reagent)
// R.Rvaccine = D.vaccine
// R.Rcurable = D.curable
// R.Rregress = D.regress
// R.Rspread = D.spread
// R.Rcure = D.cure
// R.Rprob = D.stage_prob
// break
// qdel(R)
//if(R)
// src.active_vial.reagents.add_reagent_disease(R, 5)
// qdel(R)
//This generates the randomized airlock wire assignments for the game.
//to make this not randomize the wires, just set index to 1 and increment it in the flag for loop (after doing everything else).
/* Example:
Airlock wires color -> flag are { 64, 128, 256, 2, 16, 4, 8, 32, 1 }.
Airlock wires color -> index are { 7, 8, 9, 2, 5, 3, 4, 6, 1 }.
Airlock index -> flag are { 1, 2, 4, 8, 16, 32, 64, 128, 256 }.
Airlock index -> wire color are { 9, 4, 6, 7, 5, 8, 1, 2, 3 }.
*/
//This is the dumbest var.
//If 1, AI control is disabled until the AI hacks back in and disables the lock. If 2, the AI has bypassed the lock. If -1, the control is enabled but the AI had bypassed it earlier, so if it is disabled again the AI would have no trouble getting back in.
//The number of seconds until power is restored.
//The number of seconds until power is restored.
//How many seconds remain until the door is no longer electrified. -1 if it is permanently electrified until someone fixes it.
// fuck our players for making us (or at least me) need this
/* New()
..()
// a lazy pixel offset
if(src.dir == 1 || src.dir == 2)
src.pixel_y -= 3
return
*/
//var/wireFlag = airlockWireColorToFlag[wireColor] //not used in this function
//Sending a pulse through this flashes the red light on the door (if the door has power).
//Sending a pulse through either one causes a breaker to trip, disabling the door for 10 seconds if backup power is connected, or 1 minute if not (or until backup power comes back on, whichever is shorter).
//one wire for door bolts. Sending a pulse through this drops door bolts if they're not down (whether power's on or not),
//raises them if they are down (only if power's on)
//only can raise bolts if power's on
//two wires for backup power. Sending a pulse through either one causes a breaker to trip, but this does not disable it unless main power is down too (in which case it is disabled for 1 minute or however long it takes main power to come back, whichever is shorter).
//one wire for electrifying the door. Sending a pulse through this electrifies the door for 30 seconds.
//TODO: Move this into process() and make pulsing reset secondsElectrified to 30
//tries to open the door without ID
//will succeed only if the ID wire is cut or the door requires no access
//Cutting either one disables the main door power, but unless backup power is also cut, the backup power re-powers the door in 10 seconds. While unpowered, the door may be crowbarred open, but bolts-raising will not work. Cutting these wires may electocute the user.
//Cutting this wire also drops the door bolts, and mending it does not raise them. (This is what happens now, except there are a lot more wires going to door bolts at present)
//Cutting either one disables the backup door power (allowing it to be crowbarred open, but disabling bolts-raising), but may electocute the user.
//one wire for AI control. Cutting this prevents the AI from controlling the door unless it has hacked the door through the power connection (which takes about a minute). If both main and backup power are cut, as well as this wire, then the AI cannot operate or hack the door at all.
//aiControlDisabled: If 1, AI control is disabled until the AI hacks back in and disables the lock. If 2, the AI has bypassed the lock. If -1, the control is enabled but the AI had bypassed it earlier, so if it is disabled again the AI would have no trouble getting back in.
//Cutting this wire electrifies the door, so that the next person to touch the door without insulated gloves gets electrocuted.
//not used in this function
//one wire for AI control. Cutting this prevents the AI from controlling the door unless it has hacked the door through the power connection (which takes about a minute). If both main and backup power are cut, as well as this wire, then the AI cannot operate or hack the door at all.
//aiControlDisabled: If 1, AI control is disabled until the AI hacks back in and disables the lock. If 2, the AI has bypassed the lock. If -1, the control is enabled but the AI had bypassed it earlier, so if it is disabled again the AI would have no trouble getting back in.
//borrowed from the grille's get_connection
// shock user with probability prb (if all connections & power are working)
// returns 1 if shocked, 0 otherwise
// The preceding comment was borrowed from the grille's shock script
//you lucked out, no shock for you
// find the powernet of the connected cable
// cable is unpowered
//if (src.airlockelectrocute(user, net))
//return 1
/// cogwerks: unifying this with cabl electrocution
//var/atom/A = src
// cogwerks - this should be commented out or removed later but i am too tired right now
//You're probably getting shocked deal w/ it
// unconnected cable is unpowered
// elec insulted gloves protect completely
//ok you're getting shocked now
// find the powernet
//someone juiced up the grid enough, people going to die!
// message_admins("<span style=\"color:blue\"><B>ADMIN: </B>DEBUG: shock_damage = [shock_damage] PN.avail = [PN.avail] user = [user] netnum = [netnum]</span>")
// there's an issue with the panel overlay not being gone by the time the animation is nearly done but I can't make that stop, despite my best efforts
// if(ai_no_access && istype(user, /mob/living/silicon))
// boutput(user, "You are unable to access this door.")
// return
//Separate interface for the AI.
//Power
//Main power
//Backup power
//IDscan
//Electrify
//Bolt
//Open or close
//aiDisable - 1 idscan, 2 disrupt main power, 3 disrupt backup power, 4 drop door bolts, 5 un-electrify door, 7 close door
//aiEnable - 1 idscan, 4 raise door bolts, 5 electrify door for 30 seconds, 6 electrify door indefinitely, 7 open door
//TODO: Make this take a minute
//disable blocked control
//bring up airlock dialog
//t1 += text("[]: ", airlockFeatureNames[airlockWireColorToIndex[9]])
//AI
//aiDisable - 1 idscan, 2 disrupt main power, 3 disrupt backup power, 4 drop door bolts, 5 un-electrify door, 7 close door
//aiEnable - 1 idscan, 4 raise door bolts, 5 electrify door for 30 seconds, 6 electrify door indefinitely, 7 open door
//disable idscan
//disrupt main power
//disrupt backup power
//drop door bolts
//un-electrify door
//close door
//enable idscan
//raise door bolts
//electrify door for 30 seconds
//electrify door indefinitely
//open door
// close()
//boutput(world, text("airlock attackby src [] obj [] mob []", src, C, user))
// This code allows for airlocks to be controlled externally by setting an id_tag and comm frequency (disables ID access)
//radio signal
//For unique conditions like a rejection message instead of overall status
//radio signal
// Please keep synchronizied with these lists for easy map changes:
// /obj/machinery/r_door_control (door_control.dm)
// /obj/machinery/door/poddoor/pyro (poddoor.dm)
// /obj/machinery/door/poddoor/blast/pyro (poddoor.dm)
// /obj/warp_beacon (warp_travel.dm)
// Workaround for the stacked conveyor belt issue (Convair880).
////////////////////////////////////////////////////////
//////////////Mass Driver Button ///////////////////
///////////////////////////////////////////////////////
///////////Uses a radio signal to control the door
//////////////////////////////////////////////////////////////////////////
///////Remote Door Control //////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
//open or not?
// Please keep synchronizied with these lists for easy map changes:
// /obj/machinery/door_control (door_control.dm)
// /obj/machinery/door/poddoor/pyro (poddoor.dm)
// /obj/machinery/door/poddoor/blast/pyro (poddoor.dm)
// /obj/warp_beacon (warp_travel.dm)
// must wait for map loading to finish
//////Open Door
////////reset pass
//else
//qdel(signal)
//Weird, but need to make use of turf for entered proc
// Can't be hacked, RCD'd or controlled by silicon mobs.
//var/req_only_one_required = 0
// Can a mob stumble into this door if they have enough brain damage? Won't work if you override Bumped() or attackby() and don't check for it separately.
// In relation to world time.
// Simple proc to avoid some duplicate code (Convair880).
// No text spam, please. Bumped() is called more than once by some doors, though.
// If we just return 0, they will be able to bump-open the door and get past regardless
// because mob paralysis doesn't take effect until the next tick.
//if(air_group) return 0
//cannot be opened by bots.
// Don't override ID cards.
// It's broken now.
// stop the sound from spamming, if there is one
//grabsmash
//doors can still open when emag-disabled
//in case of emag
//emag again
//There are no false wall checks because that would be fucking retarded
/////////////////////////////////////////////////// Unpowered doors
// APRIL FOOLS
//don't care who they are or what they have, act as if they're NOTHING
// Please keep synchronizied with these lists for easy map changes:
// /obj/storage/secure/closet/brig/automatic (secure_closets.dm)
// /obj/machinery/floorflusher (floorflusher.dm)
// /obj/machinery/door/window/brigdoor (window.dm)
// /obj/machinery/flasher (flasher.dm)
// Why range 30? COG2 places linked fixtures much further away from the timer than originally envisioned.
// opens the inner gen pop door and not the outer so that the perp (and anyone who manages to stow away with him) can be processed for release
//close the cell door up when the timer starts.
//open the cell door if the timer is stopped.
// listen for fire alert from firealarm
//close it up again
//Rebuild/update nearby group geometry
//Did players (de)activate it?
//Actual current status.
//Did AI/Robots Overload it?
// Please keep synchronizied with these lists for easy map changes:
// /obj/machinery/door_control (door_control.dm)
// /obj/machinery/r_door_control (door_control.dm)
// /obj/machinery/door/poddoor/blast/pyro (poddoor.dm)
// /obj/warp_beacon (warp_travel.dm)
// Please keep synchronizied with these lists for easy map changes:
// /obj/machinery/door_control (door_control.dm)
// /obj/machinery/r_door_control (door_control.dm)
// /obj/machinery/door/poddoor/pyro (poddoor.dm)
// /obj/warp_beacon (warp_travel.dm)
//doors can still open when emag-disabled
//in case of emag
//emag again
//doors can still open when emag-disabled
//in case of emag
//emag again
// ugh, lets not use the autoclose built into the door type due to autoclose, for now, give doors proper functionality for this later
/*/obj/machinery/door/supernorn/medical
name = "Medical"
icon = 'door_medical.dmi'
req_access = list(access_medical)
/obj/machinery/door/supernorn/maintenance
name = "Maintenance Access"
icon = 'icons/Testing/newicons/obj/NEWdoors/door_maintenance.dmi'
req_access = list(access_maint_tunnels)*/
// let them through halfway through the anim
// kinda hacky, oh well
// something was in the way
// Contains:
// - Sliding door parent
// - Brig door
// - Opaque door
// - Generic door
////////////////////////////////////////////////////// Sliding door parent ////////////////////////////////////
// Check for appropriate border.
// Rebuild resp. update nearby group geometry.
// Since these things don't have a maintenance panel or any other place to put this, really (Convair880).
// Emagged.
////////////////////////////////////////////// Brig door //////////////////////////////////////////////
//brig doors close only when the cell timer starts
// Please keep synchronizied with these lists for easy map changes:
// /obj/storage/secure/closet/brig/automatic (secure_closets.dm)
// /obj/machinery/floorflusher (floorflusher.dm)
// /obj/machinery/door_timer (door_timer.dm)
// /obj/machinery/flasher (flasher.dm)
/////////////////////////////////////////////////////////// Opaque door //////////////////////////////////////
//////////////////////////////////////////////////////// Generic door //////////////////////////////////////////////
//5 minutes in ticks
//search nearby turfs for flusher
//src.flusher = locate(/obj/machinery/floorflusher) in range(1, src)
//start the round off with a drone
//power usage modifications here
//deal with the counter for creating new drones
//Make a brand new drone!
//Check output areas for a free spot
//No free chargers ohno
//error out visibly, with sound
//do some beep boops for a successful build
//2 seconds
//G.throw_at(T, 1, 1)
//For when closing
//fully charged yo
//Do opening thing
//Animation is 6 ticks, 1 extra for byond
//Do closing thing
//
// Firealarm
//
// added check of detector status here
// maybe we should trigger an alarm when there already is one, goddamn
// var/datum/radio_frequency/frequency = radio_controller.return_frequency(alarm_frequency)
// It is a gizmo that flashes a small area
//this is roughly the size of brig cell
//Don't want it getting spammed like regular flashes
//How weakened targets are when flashed.
// Please keep synchronizied with these lists for easy map changes:
// /obj/storage/secure/closet/brig/automatic (secure_closets.dm)
// /obj/machinery/floorflusher (floorflusher.dm)
// /obj/machinery/door_timer (door_timer.dm)
// /obj/machinery/door/window/brigdoor (window.dm)
//Portable version of the flasher. Only flashes when anchored
//Don't want to render prison breaks impossible
//Let the AI trigger them directly.
// Heavy-duty flashers should be capable of disrupting cloaks in a reliable fashion, hence the 100% at the end.
//Floor Flushing Mechanism.
//icon = 'icons/obj/disposal.dmi'
// new icon
//is it open
//ID used for brig stuff
// internal reservoir
// item mode 0=off 1=charging 2=charged
// true if triggered
// the attached pipe trunk, if none reject user
// true if flushing in progress
// Please keep synchronizied with these lists for easy map changes:
// /obj/storage/secure/closet/brig/automatic (secure_closets.dm)
// /obj/machinery/door_timer (door_timer.dm)
// /obj/machinery/door/window/brigdoor (window.dm)
// /obj/machinery/flasher (flasher.dm)
// create a new floor flusher
// find the attached trunk (if present) and init gas resvr.
// link the pipe trunk to self
//gas.volume = 1.05 * CELLSTANDARD
// attack by item places it in to disposal
// mouse drop another mob or self
//you can fall in if its open
// if drop self, then climbed in
// must be awake
// can breath normally in the disposal
// attempt to move while inside
// ai cannot interface.
// human interact with machine
//fall in hilariously
// eject the contents of the unit
// update the icon & overlays to reflect mode & status
// check for items in disposal - if there is a mob in there, flush.
// timed process
// charge the gas reservoir and perform flush if ready
// nothing can happen if broken
// flush can happen even without power, must be open first
// won't charge if no power
// base power usage
// if off or ready, no need to charge
// perform a flush
// virtual holder object which actually
// travels through the pipes.
// copy the contents of disposer to holder
// empty gas
// wait for animation to finish
// start the holder processing movement
// now reset disposal state
// if was ready,
// switch to charging
// called when area power changes
// do default setting/reset of stat NOPOWER bit
// update icon
//open up, called on trigger
// called when holder is expelled from a disposal
// should usually only occur if the pipe network is modified
// nothing can happen if broken
// flush can happen even without power, must be open first
// won't charge if no power
// base power usage
//Is it on?
// Does it need cleaning?
// Time from starting until meat appears
// Mob who has been put inside
// Spray gibs and meat in that direction.
// For forensics (Convair880).
// Ditto (Convair880).
//for suiciding with gibber
// For forensics (Convair880).
// For forensics (Convair880).
// should probably rewrite this since it's kinda shitty
//src.projector.projection = null
// Wall mounted remote-control igniter.
// so the sprites default to facing the same way as they always have
//this may need some adjusting still
//The direction things get sent into when the router does not have a destination for the given barcode or when there is none attached.
//List of tags and the associated directions.
//By default send things to disposals, for this example, if they dont have a code or we don't have a destination.
//You could leave one direction open and use that as default to send things with invalid destinations back to QM or something.
//Or if QM is already in the list of destinations , use that direction as default. I don't know.
// cogwerks notes: I'm starting with the first router from QM and moving sorta clockwise.
//airbridge loader
//eva loader
//cafeteria
//disposals
//crusher or QM?
// shortcut - bypasses the central hub
// engine dock
// to outer router -> out
// to outer router -> in
// outer router -> up
// outer router -> down
// catering outer router -> east-west
// catering outer router -> west-east
// log account information for QM sales
//These have to match the ones on the cargo routers for the routers to work.
// cogwerks - uncomment this stuff if/when custom locations are ready
/*else if (href_list["remove"])
if(destinations.Find(href_list["remove"]))
destinations.Remove(href_list["remove"])
else if (href_list["add"])
var/input = input(usr,"Enter new tag:","Tag","") as text
if(length(input) && !destinations.Find(input))
destinations.Add(input)*/
//has trader tags if there is one
// log account information for QM sales
//Backpack or something
// the light switch
// can have multiple per area
// can also operate on non-loc area through "otherarea" var
// luminosity = 1
// mats = 6 fuck you mport
//bit of a hack but hey.
// temporary measure, i want a better UI for this =(
// 0 is =>, 1 is ==
// unlikely as this is to happen we might as well make sure everything is purged
// swiped from guardbot.dm
//dat += "<A href='?src=\ref[src];shake=0'>(shake)</A>"
//if (href_list["shake"])
// src.flip_out()
//Anti-spam to prevent people lagging the server with autoclickers
//Anti-spam to prevent people lagging the server with autoclickers
/*if (href_list["delete"])
var/datum/manufacture/I = locate(href_list["disp"])
if (!istype(I,/datum/manufacture/mechanics/))
boutput(usr, "<span style=\"color:red\">Cannot delete this schematic.</span>")
return
src.download -= I*/
// reagents are going into beaker
// reagents are being drawn from beaker
//not used in this function
// Marq fix for various cannot read null. runtimes
// anything at all
// wildcard
// this was kind of thrown together in a panic when i felt shitty so if its horrible
// go ahead and clean it up a bit
// maux hardness = 15
// bohr hardness = 33
// specific material id
//Wire: Fix for href exploit creating arbitrary items
//for (var/obj/item/O in mats_used)
// del O
// pick a new item each loop
// get a random item from the list and produce it
// produce every item in the list once per loop
//Wire: Fix for list index out of bounds
// adapted from vending machine code
// adapted from vending machine code
//SpyGuy for RTE "pick() from empty list"
// Blueprints
// Fabricator Defines
// add more stuff to this as needed, but it should be for regular uniforms the HoP might hand out, not tons of gimmicks. -cogwerks
/// cogwerks - a gas extractor for the engine
// a blank manufacturer for mechanics
//this is mostly irrelevant since current mass drivers throw into space, but you could make a lower-range mass driver for interstation transport or something I guess.
//Current number of eggs inside
//Current amount of flour inside
//Current amount of water inside
// Is it on?
// Does it need cleaning?
// How broken is it???
// List of the recipes you can use
// The item being cooked
// One non food item that can be added
// *** After making the recipe in datums\recipes.dm, add it in here! ***
/*******************
* Item Adding
********************/
// If it's broken and they're using a screwdriver
// Fix it a bit
// If it's broken and they're doing the wrench
// Fix it!
// The microwave is all dirty so can't be used!
// If they're trying to clean it then let them
// It's cleaned!
//Otherwise bad luck!!
// If an egg is used, add it
// If flour is used, add it
// Band-aid fix. The microwave code could really use an overhaul (Convair880).
//Allow one non food item to be added!
//Let them know it failed for a reason though
/*******************
* Microwave Menu
********************/
// The microwave Menu
/***********************************
* Microwave Menu Handling/Cooking
************************************/
// The time to wait before spawning the item
// If cook was pressed
//Look through the recipe list we made above
// Check if it's an accepted recipe
// Just in case the recipe doesn't have an extra item in it
// If so remove all the eggs
// And the flour
//And the water
// And the extra item
// Store the item that will be created
//Oops that wasn't a recipe dummy!!!
//Make sure there's something inside though to dirty it
// Turn it on
//Clear all the values as this crap is what makes the mess inside!!
// Half way through
// Play a splat sound
// Make it look dirty!!
// Then at the end let it finish normally
// Make it dirty so it can't be used util cleaned
// Make it look dirty too
// Turn it off again aferwards
// Don't clear the extra item though so important stuff can't be deleted this way and
// it prolly wouldn't make a mess anyway
// However if there's a weird item inside we want to break it, not dirty it
// Turn it on
//Clear all the values as this crap is gone when it breaks!!
// Wait a while
// Make it look all busted up and shit
//Let them know they're stupid
// Make it broken so it can't be used util fixed
// Turn it off again aferwards
// Eject the extra item so important shit like the disk can't be destroyed in there
//Otherwise it was empty, so just turn it on then off again with nothing happening
// If dispose was pressed, empty the microwave
// Eject the extra item so important shit like the disk can't be destroyed in there
// Get the item that needs to be spanwed
// Turn it on so it can't be used again while it's cooking
//Make it look on too
//After the cooking time
// Create the new item
// We're done!
// Turn the microwave back off
// Navigation beacon for AI robots
// Functions as a transponder: looks for incoming signal matching
// underfloor
// TODO layer whatever
// true if cover is open
// true if controls are locked
// radio frequency
// location response text
// assoc. list of transponder codes
// codes as set on map: "tag1;tag2" or "tag1=value;tag2=value"
// must wait for map loading to finish
// set the transponder codes assoc list from codes_txt
// entries are separated by semicolons
// format is "key=value"
// called when turf state changes
// hide the object if turf is intact
// update the icon_state
// if invisible, set icon to faded version
// in case revealed by T-scanner
// look for a signal of the form "findbeacon=X"
// where X is any
// or the location
// or one of the set transponder keys
// if found, return a signal
// if(stat & NOPOWER)
// return
// return a signal giving location and transponder codes
// prevent intraction when T-scanner revealed
// prevent intraction when T-scanner revealed
// can't alter controls if not open, unless you're an AI
//?src=\ref[src];freq=-10'>-</A>
//?src=\ref[src];freq=-2'>-</A>
//?src=\ref[src];freq=2'>+</A>
//?src=\ref[src];freq=10'>+</A><BR>
//?src=\ref[src];locedit=1'>[location ? location : "(none)"]</A><BR>
//?src=\ref[src];edit=1;code=[key]'>(edit)</A>"
//?src=\ref[src];delete=1;code=[key]'>(delete)</A></small><BR>"
//?src=\ref[src];add=1;'>(add new)</A></small><BR>"
//Wired nav device
// underfloor
// Circular patrol pattern. I'm sure as hell not going to varedit all those things by hand.
// 20 should be sufficient for a full-sized map such as COG1 or 2 (Convair880).
// Same deal for MULE delivery beacons (Convair880).
// if(rep == 0)
// for (var/obj/X in orange(4,src))
// if(istype(X,/obj/machinery/the_singularity/))
// for(var/obj/machinery/noise_maker/M in machines)
// rep = 1
// M.containment_fail = 1
// M.sound = 3
// M.emittsound()
// for(var/obj/machinery/field_generator/T in machines)
// T.Varedit_start = 1
// playsound(src.loc, "sound/effects/Explosion1.ogg", 100, 1)
//Add when it gets emagged it perma shuts it off
// if(((src.last_shot + src.fire_delay) <= world.time))
// src.last_shot = world.time
//1"
// 8 min.
// +3 (crew member) or -3 (nuke ops) min.
// Nuke round development was abandoned for 4 whole months, so I went out of my way to implement some user feedback from that 11 pages long forum thread (Convair880).
//src.icon_state = "nuclearbomb2"
//else if (istype(W,/obj/item/wirecutters/))
// user.visible_message("<b>[user]</b> opens up [src]'s wiring panel and takes a look.")
// open_wire_panel(user)
// return
// Esword has 60 force.
/*switch(severity) // No more suicide-bombing the nuke.
if(1)
src.take_damage(80)
if(2)
src.take_damage(50)
if(3)
src.take_damage(20)*/
// cogwerks - making the end of nuke more exciting. oh no a nuke went off, let's all... stand around for thirty seconds
// until we can fix the lag related to deleting mobs we should probably just leave the end of the animation up and kill everyone instead of firegibbing everyone
//firegib()
//SN src = null
//SN src = null
// hack
//Owl version of the portable flasher
// I can't take it anymore I can't take the destiny owls reacting to the monkey it's driving me mad
// I stole this from the automaton because I am a dirty code frankenstein
//
// Party alarm
//
/*CONTENTS
Buildable pipes
Buildable meters
*/
//update the name and icon of the pipe item depending on the type
//update the icon of the item
// true if placed under floor
// fade the icon
// otherwise reset to inital icon
// called to hide or unhide a pipe
// i=true if hiding
// make hidden pipe items invisible
//called when a turf is attacked with a pipe item
// place the pipe on the turf, setting pipe level to 1 (underfloor) if the turf is not intact
// rotate the pipe item clockwise
// returns the p_dir from the pipe item type and dir
// return the h_dir (heat-exchange pipes) from the type and the dir
// var/flip = turn(dir, 180)
// var/cw = turn(dir, -90)
// all possible pipe dirs including h/e#
// only on same level
// matches at least one direction on either type of pipe
// no conflicts found
// 0 1 2 3 4 5 6 7 8 9 10
//"pipe", "bent pipe", "h/e pipe", "bent h/e pipe", "connector", "manifold", "junction", "vent", "valve", "pump", "filter inlet"
// straight or bent pipe
// straight or bent h/e pipe
// connector
//manifold
//junctions
// vent
//valve
//Pipe pump
//filter inlet
// for pipe objects, now do updating of pipelines if needed
// new regular or or h/e pipe
// number of pipes connected to P
// simplest case - no connection pipes (but may be machines)
// create a new pipeline
// set new pipe to use new pl
// set new pipe to use new pl
// and add it
// and new pipeline to the global list
// and ensure any connections to machines are made
// set the name
// single connected pipe
// the connected pipe
// find the connected pipe
// the pipeline we connected to
// set the pipeline and nodes of any adjoining pipes
// if the connected pipe is at start of line nodes list
// insert new pipe into start of node list
// otherwise, insert it at end
// connect to any machines
// connected pipe no longer terminal
//(pipecon==2)
// special case - completing a loop
// make sure to check if this works properly
// link pipeline to self
// separate pipelines
// remove the pipe item
//TODO: DEFERRED
// ensure that setterm() is called for a newly connected pipeline
// Currently only used to control /obj/machinery/inlet/filter
// todo: expand to vent control as well?
//wait for world
//ugly
//Who cares if we're dead or whatever let us close the fucking window
//someone modified the html so I added a check here
// toggle gas
// pipeline datum for storing inter-machine links
// create a pipeline
//number of pipelines
// find the pipeline that contains the /obj/machine (including pipe)
// sets the vnode1&2 terminators to the joining machines (or null)
//first make sure pipes are oriented correctly
// special case for 1st pipe
// flip if node1 is a pipe
//other cases, flip if node1 doesn't point to previous node
// (including if it is null)
// pipes are now ordered so that n1/n2 is in same order as pipeline list
// 1st node in list
// n1 points to 1st machine
// last node in list
// n2 points to last machine
//if(suffix == "d" && Debug) world.log << "PLF1 [gas.total_moles()] ~ [ngas.total_moles()]"
//if(suffix == "d" && Debug) world.log << "PLF2 [gas.total_moles()] ~ [ngas.total_moles()]"
// heat exchange for whole pipeline
//if(suffix=="dbgp")
// world.log << "PLP"
// Plasma()
// var/dbg = (suffix == "d") && Debug
//if(dbg) world.log << "PLP1 [gas.total_moles()] ~ [ngas.total_moles()]"
//dividing by zero is bad okay?
// cached temperature for heat exch calc
// fraction of gas in this node
//if(dbg) world.log << "PLHE: [gtemp] [tot_node]"
// no pipe contents, don't heat
// for each segment of pipe
//, dbg) // exchange heat with its turf
//Commenting this out because it spams on endlessly
//for (var/mob/M in viewers(P))
//M.show_message("<span style=\"color:red\">The pipe has ruptured!</span>", 3)
//so this is changed to pipe rupturing instead of explosions
//i.e. it ruptures if the pressure over 15000%
//and temperature over 8000K
//it also doesn't work on heat_exchange pipes
// now do standard gas flow proc
//if(dbg) world.log << "PLP2 [ngas.total_moles()]"
//, dbg)
//if(dbg) world.log << "PLT1 [delta_gt] >> [gas.total_moles()] ~ [ngas.total_moles()]"
//, dbg)
//if(dbg) world.log << "PLT2 [delta_gt] >> [gas.total_moles()] ~ [ngas.total_moles()]"
//TODO: FIX
// 1st node in list
// last node in list
//TODO: FIX
// build the pipelines (THIS HAPPENS ONCE!)
// look for a pipe
// if not already part of a line
// add it, and spread to all connected pipes
//world.log<<"Line #[linecount] started at [P] ([P.x],[P.y],[P.z])"
// for count of lines found
// make a pipeline virtual object
// and add it to the list
// look for pipes
// true if pipe is terminated (ends in blank or a machine)
// get the pipeline from the pipe's pl-number
// get a list of pipes from P until terminated
// pipeline is this list of nodes
// with this many nodes
// with this flow multiplier
// all pipes
// set the pipeline object for this pipe
//add debug tag to line containing debug pipe
//add debug tag to line containing debug pipe
//add debug tag to line containing debug pipe
// for all machines
// which are pipe-connected
// is not a pipe itself
// build the nodes, setting the links to the virtual pipelines
// also sets the vnodes for the pipelines
// for all lines
// orient the pipes and set the pipeline vnodes to the terminating machines
// return a list of pipes (not including terminating machine)
// new pipes system
// flip the nodes of a pipe
// return the next pipe in the node chain
// if from null, then return the next actual pipe
// else return null if no real pipe connected
// otherwise, return the node opposite the incoming one
// set the pipeline obj from the pl-number and global list of pipelines
// returns the pipeline that this line is in
// returns a list of dir1, dir2 & p_dir for a pipe
// returns a list of the directions of a pipe, matched to nodes (if present)
// no nodes - just return the standard dirs
// note extra p_dir on end of list is unimportant
// find the direction of node1
// if it matches
// then dirs list is correct
// otherwise return the list swapped
// node2 must be valid
// direction of node2
// matches
// dirs list is correct
// otherwise swap order
//its lazy right now but wait until after my exams and I'll redo it.
//redid it, oh shit
//lets say hypothetically it uses up 9/10 of its energy in bursting the pipe
//if ((src.gas.temperature > (450+T0C) && src.gas.plasma == 1600000.0))
//Foreach goto(342)
//Foreach goto(170)
//if ((src.gas.temperature > (300+T0C) && src.gas.plasma == 1600000.0))
//Foreach goto(598)
//Foreach goto(498)
//src.master = null
//SN src = null
//Foreach goto(732)
//var/m_range = 2
//Foreach goto(776)
//Foreach goto(1217)
//U.mark(zone)
//Foreach goto(961)
//src.master = null
//SN src = null
// return true since this is a pipe
// h/e pipe cannot be put underfloor
/* var/turf/T = src.loc // turf location of pipe
if(T.density) return
if(istype(src, /obj/machinery/pipes/flexipipe)) return
if( level != 1) // no heat exchange for under-floor pipes
if(istype(T,/turf/space)) // heat exchange less efficient in space (no conduction)
gas.temperature += ( T.temp - temp) / (3.0 * insulation * numnodes)
else
// if(dbg) world.log << "PHE: ([x],[y]) [T.temp]-> \..."
var/delta_T = (T.temp - temp) / (insulation) // normal turf
gas.temperature += delta_T / numnodes // heat the pipe due to turf temperature
/*
if(abs(delta_T*tot_node/T.total_moles()) > 1)
world.log << "Turf [T] at [T.x],[T.y]: gt=[temp] tt=[T.temp]"
world.log << "dT = [delta_T] tn=[tot_node] ttg=[T.total_moles()] tt-=[delta_T*tot_node/T.total_moles()]"
*/
// also heat the turf due to pipe temp
// clamp max temp change to prevent thermal runaway
// if low amount of gas in turf
// if(dbg) world.log << "[T.temp] [tot_turf] #[delta_T]"
// ensure turf tmp vars are updated
// if level 1 but in space, perform cooling anyway - exposed pipes
//TODO FIX
// finds the machine with compatible p_dir in 1 step in dir from S
// finds the machine with compatible h_dir in 1 step in dir from S
// ***** circulator
//gas.co2 = capacity
// 3 second delay for slow-off
// status ==2
//src.gas.transfer_from(t_gas, amount)
// if operating, pump from resv1 to resv2
// only do circulator step if powered; still do rest of gas flow at all times
// now do standard process
//TODO FIX
// do leak
//TODO: FIX
//TODO: FIX
//agas = new/obj/substance/gas()
// var/dbg = (suffix == "d") && Debug
//if(dbg) world.log << "CF0: ngas=[ngas.total_moles()]"
//ngas.transfer_from(agas, -1)
//if(dbg) world.log << "CF1: ngas=[gas.total_moles()]"
//if(dbg) world.log << "CF2: gas=[gas.total_moles()]"
//if(suffix=="dbgp")
// world.log << "CP"
// Plasma()
// var/dbg = (suffix == "d") && Debug
//if(dbg) world.log << "C[tag]P: [gas.total_moles()] ~ [ngas.total_moles()]"
//if(dbg && connected) world.log << "C[tag]PC: [connected.gas.total_moles()]"
//if(dbg) world.log << "C[tag]P0: [delta_gt]"
//var/obj/substance/gas/vgas = vnode.get_gas(src)
//if(dbg) world.log << "C[tag]P1: [gas.total_moles()], [ngas.total_moles()] -> [vgas.total_moles()]"
//, dbg)
//if(dbg) world.log << "C[tag]P2: [gas.total_moles()], [ngas.total_moles()] -> [vgas.total_moles()]"
// canister set to release
//if(dbg) world.log << "C[tag]PC1: [gas.total_moles()], [ngas.total_moles()] <- [connected.gas.total_moles()]"
// limit to space in connector
// limit to amount in canister, or 0
//if(dbg) world.log << "C[tag]PC2: a=[amount]"
//var/ng = ngas.total_moles()
//if(dbg) world.log <<"[ngas.total_moles()-ng] from siph to connector"
//if(dbg) world.log << "C[tag]PC3: [gas.total_moles()], [ngas.total_moles()] <- [connected.gas.total_moles()]"
// canister set to accept
//limit to space in canister
// limit to amount in connector, or 0
//flag = 1
//if(suffix=="dbgp")
// world.log << "CP"
// Plasma()
//TODO: FIX
//var/dbg = (tag == "dbg") && Debug
//if(dbg) world.log << "CLT1: [gas.tostring()] ~ [ngas.tostring()]<br>Tg = [T.tostring()]"
//if(dbg) world.log << "CLT2: [gas.tostring()] ~ [ngas.tostring()]<br>Tg = [T.tostring()]"
// the h/e pipe is in obj dir
// the reg pipe is in opposite dir
// the h/e pipe
// the regular pipe
//var/dbg
//if(tag == "dbg1")
// dbg = 1
//else if(tag == "dbg2")
// dbg = 2
//if(dbg) world.log << "J[dbg]F1: [gas.tostring()] ~ [ngas.tostring()]"
//if(dbg) world.log << "J[dbg]F2: [gas.tostring()] ~ [ngas.tostring()]"
//var/dbg
//if(tag == "dbg1")
// dbg = 1
//else if(tag == "dbg2")
// dbg = 2
//if(dbg) world.log << "J[dbg]P: [gas.tostring()] ~ [ngas.tostring()]"
//, dbg)
// if(dbg) world.log << "J[dbg]T1: [delta_gt] >> [gas.tostring()] ~ [ngas.tostring()]"
//, dbg)
// if(dbg) world.log << "J[dbg]T2: [delta_gt] >> [gas.tostring()] ~ [ngas.tostring()]"
//TODO: FIX
// var/dbg = (suffix=="d") && Debug
//if(dbg) world.log << "V[tag]F1: [gas.total_moles()] ~ [ngas.total_moles()]"
//if(dbg) world.log << "V[tag]F2: [gas.total_moles()] ~ [ngas.total_moles()]"
// var/dbg = (suffix=="d") && Debug
//if(dbg) world.log << "V[tag]T1: [gas.total_moles()] ~ [ngas.total_moles()]"
//if(suffix=="dbgp")
// world.log << "VP"
// Plasma()
//var/ng = ngas.total_moles()
//if(dbg) world.log << "[num2text(ng-ngas.total_moles(),10)] from vent to turf"
//if(dbg) world.log << "V[tag]T2: [gas.total_moles()] ~ [ngas.total_moles()]"
//if(dbg) world.log << "V[tag]N1: [gas.total_moles()] ~ [ngas.total_moles()]"
//, dbg)
//if(dbg) world.log << "V[tag]N2: [gas.total_moles()] ~ [ngas.total_moles()]"
//TODO: FIX
// note this is a leak from the node, not the vent itself
// thus acts as a link between the vent turf and the turf in step(dir)
// inlet - equilibrates between pipe contents and turf
// very similar to vent, except that a vent always dumps pipe gas into turf
//if(suffix=="dbgp")
// world.log << "VP"
// Plasma()
// this is the difference between vent and inlet
// act as gas leak
//if(dbg) world.log << "V[tag]N1: [gas.total_moles()] ~ [ngas.total_moles()]"
//, dbg)
//if(dbg) world.log << "V[tag]N2: [gas.total_moles()] ~ [ngas.total_moles()]"
//TODO: FIX
// note this is a leak from the node, not the inlet itself
// thus acts as a link between the inlet turf and the turf in step(dir)
// standard proc for all machines - passed gas/ngas as arguments
// equilibrate a pipe object and a turf's gas content
// partial pressure of turf gas at pipe, for the moment
// flow from pipe to turf
//world.log << "FTT<0"
// ndelta contains gas to transfer to turf
//world.log << "ND=[ndelta.tostring()]"
// update new gas to remove the amount transfered
//world.log << "SN=[sngas.tostring()]"
// add all of ndelta to turf
//world.log << "T=[T.tostring()]"
//world.log << "LTT: [num2text(-delta_gt,10)] from [sgas.loc] to turf"
// flow from turf to pipe
// grab gas from turf and direcly add it to the new gas
// update turf gas vars for both cases
//TODO: FIX
// on-off valve
// the h/e pipe
// the regular pipe
/* var/delta_gt
if(vnode1)
delta_gt = FLOWFRAC * ( vnode1.get_gas_val(src) - gas1.total_moles() / capmult)
calc_delta( src, gas1, ngas1, vnode1, delta_gt)
else
leak_to_turf(1)
if(vnode2)
delta_gt = FLOWFRAC * ( vnode2.get_gas_val(src) - gas2.total_moles() / capmult)
calc_delta( src, gas2, ngas2, vnode2, delta_gt)
else
leak_to_turf(2)
if(open) // valve operating, so transfer btwen resv1 & 2
delta_gt = FLOWFRAC * (gas1.total_moles() / capmult - gas2.total_moles() / capmult)
var/datum/gas_mixture//ndelta = new()
if(delta_gt < 0) // then flowing from R2 to R1
ndelta.set_frac(gas2, -delta_gt)
ngas2.sub_delta(ndelta)
ngas1.add_delta(ndelta)
else // flowing from R1 to R2
ndelta.set_frac(gas1, delta_gt)
ngas2.add_delta(ndelta)
ngas1.sub_delta(ndelta)*/
//TODO: FIX
// now opening
// now closing
// Digital Valve
// the h/e pipe
// the regular pipe
// valve operating, so transfer btwen resv1 & 2
// then flowing from R2 to R1
// flowing from R1 to R2
//TODO: FIX
// now opening
// now closing
// one way pipe
// then flowing from R2 to R1
//TODO: FIX
// pump if power
//TODO: FIX
// So they don't all turn off at the same time
// Filter inlet
// works with filter_control
/* var/turf/T = src.loc
if(!T || T.density) return
if(!vnode) return leak_to_turf()
var/obj/substance/gas/exterior = new()
exterior.oxygen = T.oxygen
exterior.n2 = T.n2
exterior.plasma = T.poison
exterior.co2 = T.co2
exterior.sl_gas = T.sl_gas
exterior.temperature = T.temp
var/obj/substance/gas/interior = gas
var/obj/substance/gas/flowing = new()
var/flow_rate = (exterior.total_moles()-interior.total_moles())*FLOWFRAC
if(flow_rate <= 0)
return
flowing.set_frac(exterior,flow_rate)
if(!(src.f_mask & GAS_O2)) flowing.oxygen = 0
if(!(src.f_mask & GAS_N2)) flowing.n2 = 0
if(!(src.f_mask & GAS_PL)) flowing.plasma = 0
if(!(src.f_mask & GAS_CO2)) flowing.co2 = 0
if(!(src.f_mask & GAS_N2O)) flowing.sl_gas = 0
use_power(5,ENVIRON)
exterior.sub_delta(flowing)
interior.add_delta(flowing)*/
//TODO: FIX
// note this is a leak from the node, not the inlet itself
// thus acts as a link between the inlet turf and the turf in step(dir)
//TODO FIX
// Filter vent
// doesn't do anything yet
//TODO FIX
//<A href='?src=\ref[src];make=10'>Filter Inlet<BR>
// 0=straight, 1=bent, 2=junction-j1, 3=junction-j2, 4=junction-y, 5=trunk
// *** pipefilter
// the main flow dir
// the ejector port
/* var/delta_gt
if(vnode1)
delta_gt = FLOWFRAC * ( vnode1.get_gas_val(src) - gas.total_moles() / capmult)
calc_delta( src, gas, ngas, vnode1, delta_gt)
else
leak_to_turf(1)
if(vnode2)
delta_gt = FLOWFRAC * ( vnode2.get_gas_val(src) - gas.total_moles() / capmult)
calc_delta( src, gas, ngas, vnode2, delta_gt)
else
leak_to_turf(2)
if(vnode3)
delta_gt = FLOWFRAC * ( vnode3.get_gas_val(src) - f_gas.total_moles() / capmult)
calc_delta( src, f_gas, f_ngas, vnode3, delta_gt)
else
leak_to_turf(3)
// transfer gas from ngas->f_ngas according to extraction rate, but only if we have power
if(! (stat & NOPOWER) )
use_power(min(src.f_per, 100),ENVIRON)
var/datum/gas_mixture/ndelta = src.get_extract()
ngas.sub_delta(ndelta)
f_ngas.add_delta(ndelta)
AutoUpdateAI(src)
src.updateUsrDialog()*/
//TODO: FIX
//TODO: FIX
// pipefilter interact/topic
/* if(stat & NOPOWER)
user << browse(null, "window=pipefilter")
user.machine = null
return
var/list/gases = list("O2", "N2", "Plasma", "CO2", "N2O")
user.machine = src
var/dat = "Filter Release Rate:<BR><br><A href='?src=\ref[src];fp=-[num2text(src.maxrate, 9)]'>M</A> <A href='?src=\ref[src];fp=-100000'>-</A> <A href='?src=\ref[src];fp=-10000'>-</A> <A href='?src=\ref[src];fp=-1000'>-</A> <A href='?src=\ref[src];fp=-100'>-</A> <A href='?src=\ref[src];fp=-1'>-</A> [src.f_per] <A href='?src=\ref[src];fp=1'>+</A> <A href='?src=\ref[src];fp=100'>+</A> <A href='?src=\ref[src];fp=1000'>+</A> <A href='?src=\ref[src];fp=10000'>+</A> <A href='?src=\ref[src];fp=100000'>+</A> <A href='?src=\ref[src];fp=[num2text(src.maxrate, 9)]'>M</A><BR><br>"
for (var/i = 1; i <= gases.len; i++)
dat += "[gases[i]]: <A HREF='?src=\ref[src];tg=[1 << (i - 1)]'>[(src.f_mask & 1 << (i - 1)) ? "Releasing" : "Passing"]</A><BR><br>"
if(gas.total_moles())
var/totalgas = gas.total_moles()
var/pressure = round(totalgas / gas.maximum * 100)
var/nitrogen = gas.n2 / totalgas * 100
var/oxygen = gas.oxygen / totalgas * 100
var/plasma = gas.plasma / totalgas * 100
var/co2 = gas.co2 / totalgas * 100
var/no2 = gas.sl_gas / totalgas * 100
dat += "<BR>Gas Levels: <BR><br>Pressure: [pressure]%<BR><br>Nitrogen: [nitrogen]%<BR><br>Oxygen: [oxygen]%<BR><br>Plasma: [plasma]%<BR><br>CO2: [co2]%<BR><br>N2O: [no2]%<BR><br>"
else
dat += "<BR>Gas Levels: <BR><br>Pressure: 0%<BR><br>Nitrogen: 0%<BR><br>Oxygen: 0%<BR><br>Plasma: 0%<BR><br>CO2: 0%<BR><br>N2O: 0%<BR><br>"
dat += "<BR><br><A href='?src=\ref[src];close=1'>Close</A><BR><br>"
user << browse(dat, "window=pipefilter;size=300x365")*/
//TODO: FIX
//onclose(user, "pipefilter")
// toggle gas
//so all the filters don't come on at once
//only show if powered because presumeably its the interface that has been fried
//should only be bypassed if unlocked
// This file is arguably the "main" file where all of the central hydroponics shit goes down.
// Most of the actual content itself is found in other files, but the plantpot does just about
// all of the actual work, so if you're looking to see how Hydro works at the very base level
// this is the file you want to be looking in.
//
// Other files you'll want if you're looking up on Hydroponics stuff:
// obj/item/plants_food_etc.dm: Most of the seed and produce items are in here.
// obj/item/hydroponics.dm: The tools players use to do hydro work are here.
// datums/plants.dm: The plant species, mutations and genetics are kept here.
// obj/submachine/seed.dm: The splicer and reagent extractor are in here.
// The central object for Hydroponics. All plant growing and most of everything goes on in
// this object - that said you don't want to have too many of them on the map because they
// get kind of resource intensive past a certain point.
// What is currently growing in the plant pot
// Set this up in New
// Automatic. Tracks how many ticks have elapsed, for CPU efficiency things.
// Automatic. If the plant is dead.
// Automatic. How developed the plant is.
// Set this when you plant a seed. Plant dies when this hits 0.
// Set this when you plant a seed. How many times you can harvest it before it dies. Plant dies when it hits 0.
// Automatic. A time delay between harvests.
// Automatic. Just a fun thing to track how many generations a plant has been bred.
// Does this tray block weeds from appearing in it? (Won't stop deliberately planted weeds)
// Who helped grow this plant? Mainly used for critters.
//Radio channel to report plant status/death/whatever.
// Used for efficiency in the update_icon proc with water level changing
// Same as the above except for current plant growth
// this is now a var on the pot itself so you can actually call it outside of process()
// We have this here as a check for whether or not the plant needs to update its sprite.
// Originally plantpots updated constantly but this was found to be rather expensive, so
// now it only does that if it needs to.
// The plantpot can store 400 reagents in total, we want a bit more than the max water
// level since we can put other additives in the pot for various effects.
// 200 is the exact maximum amount of water a plantpot can hold before it is considered
// to have too much water, which stunts plant growth speed.
// We skip every other tick. Another cpu-conserving measure.
// If the plantpot is empty or contains a dead plant, we don't need to do anything
// more in the process loop since that'd be pointless and silly.
// We obtain the current plant type in the plantpot, and the genes of the individual plant.
// We'll be referencing these a lot!
// REAGENT PROCESSING
// drink_rate is how much reagent is consumed per tick. This used to be 0.5, but got bumped
// up to 1 when the tick rate for plant pots was halved.
// Simplegrowth is used pretty much only for crystals. It essentially skips all
// simulation whatsoever and just adds one growth point per tick, ignoring all
// reagents and everything else going on.
// All of the above is pretty much to figure out whether or not the water level
// icon on the plant pot needs to change.
// max water limit!!
// If our plant has a slow metabolism, it will only gain growth 50% of
// the time compared to usual. It consumes reagents a lot slower though.
// This is essentially like putting the plant on slow-mo overall.
// If not, it grows 2 points per tick - the regular rate. Remember, the
// tick rate is halved so 1 point would mean plants take AGES to grow.
// The "growth rate on crack" mutation. Also causes it to take up
// reagents a lot faster - it's like hitting fast forward for plants.
// If there's no water in the plant pot, we slowly damage the plant and prevent
// it from gaining any growth if it's not a weed.
// Now we look through every reagent currently in the plantpot and call the reagent's
// on_plant_life proc. These are defined in the chemistry reagents file on each reagent
// for the sake of efficiency.
/* DEPRECATED, IN COMMENTS FOR THE MOMENT FOR TESTING
// Now we do a similar thing for gene strains, except with these we do a hard-coded
// thing right here since the gene strains themselves are just text strings.
for (var/X in DNA.commuts)
switch(X)
if("Unstable")
if (prob(18))
HYPmutateplant(1)
// Unstable causes the plant to mutate on its own every so often.
// Players might want this or might not, so it's neither good nor bad.
if("Accelerator")
if (prob(10))
DNA.growtime--
DNA.harvtime--
// This gene strain should be kept rare. It boosts the growth rate genes
// which makes the plant grow faster permanently. As of the time of writing
// I don't think anyone's discovered it so if it needs a downside, we can
// figure it out later.
if("Poor Health")
if(prob(24))
HYPdamageplant("frailty",1)
// Poor Health is a bad strain to have that causes the plant to slowly take
// damage for sod all reason. It's basically a weak wuss plant strain.
if("Rapid Growth")
src.growth += 2
// Basically like rapid metabolism with no downsides.
if("Stunted Growth")
if(src.growth > 1)
src.growth--
// Slow down growth. We don't want this to reduce src.growth to zero in
// any case, because that means the plant would die.
*/
// This is where drink_rate does its thing. It will remove a bit of all reagents to meet
// it's quota, except nectar because that's supposed to stay in the plant pot.
//We give off nectar and should check our nectar levels
// This keeps the nectar at the amount specified in the plant's datum.
// Special procs now live in the plant datums file! These are for plants that will
// occasionally do special stuff on occasion, such as radweeds, lashers, and the like.
// If we've got a mutation, we want to check if the mutation has its own special
// proc that overrides the regular one.
// There's no special proc for this mutation, so just use the regular one.
// The mutation overrides the base proc to use its own.
// Any other value means we use BOTH procs.
// If there's no mutation we just use the base special proc, obviously!
// This is entirely for updating the icon. Check how far the plant has grown and update
// if it's gone a level beyond what the tracking says it is.
// Have we lost all health or growth, or used up all available harvests? If so, this plant
// should now die. Sorry, that's just life! Didn't they teach you the curds and the peas?
// Inside this if block we'll handle reactions for specific kinds of plant.
// General reactions from the plantpot itself come after these.
// We want to be able to feed stuff to maneaters, such as meat, people, etc.
// It doesn't make much sense to feed a full man to a dinky little plant.
// Some logging would be nice (Convair880).
// Same as the gibber and reclaimer. Was 20 (Convair880).
// From here on out we handle item reacions of the plantpot itself rather than specific
// special kinds of plant.
// These allow you to unanchor the plantpots to move them around, or re-anchor them.
// These are for burning down plants with.
// It will fight back if possible, and halts the attack if it returns
// anything other than zero from the attack proc.
// Ashes in the plantpot I guess.
// Allows you to cut down plants. Never really saw the point in chainsaws considering
// I already had burn procs in, but whatever.
// Planting a seed in the tray. This one should be self-explanatory really.
// Logging for man-eaters, since they can't be harvested (Convair880).
// Not just watering cans - any kind of glass can be used to pour stuff in.
// Planting a crystal shard simply puts a crystal seed inside the plant pot for
// a moment, spawns a new plant from it, then deletes both the seed and the shard.
// Harvesting directly into a satchel.
// naughty AIs used to be able to harvest plants
// If the plant is ready for harvest, do that. Otherwise, check it's condition.
// If there's no plant, just check what reagents are in there.
// ghosts killing plants fix
// Plants that can fight back can halt your attempt to clear them, and will also
// run whatever is in their attacked proc. Same as harvesting really.
// The idea here is you gotta use weedkiller or something else to get rid of the
// weeds since you can't just clear them out by hand.
// ty to Razage for the initial code
// Checks to make sure it's a seed being dragged onto the tray.
// Activates the same command as would be used with a seed in hand on the tray.
// if it's not a seed...
// call our parents and ask what to do.
//Todo: Set this as something appropriate when complete.
//Send a reply for those curious jerks
//Just toss out the rest of the signal then I guess
// Procs specific to the plantpot start here.
// Pretty much figure out if we can harvest the plant yet or not. This is used for
// updating the sprite and obviously handling harvesting when a player clicks
// on the plant pot.
// This proc is where the harvesting actually happens. Again it shouldn't need tweaking
// with since i've tried to account for most special circumstances that might come up.
// it's okay if we don't have a satchel at all since it'll just harvest by hand instead
// Does this plant react to being harvested? If so, do it - it also functions as
// a check since harvesting will stop here if this returns anything other than 0.
// This is a modular thing suggested by Cogwerks that can affect the final quality
// of produce such as making fruit make you sick or herbs have less reagents.
// Reset the growth back to the beginning of maturation so we can wait out the
// harvest time again.
// Good health levels bump the harvest amount up a bit and increase jumbo chances.
// This is if the plant health is absolutely excellent.
// And this is if you've neglected the plant!
// And ones that mess with the quality of crops.
// Unstable isn't here because it'd be less random outside the loop.
// Figure out what crop we use - the base crop or a mutation crop.
// Gene strains that boost or penalize the cap.
// Max harvest amount for all plants is capped. If we've got higher output
// than the cap it's probably through gene manipulation, so reward the player
// with greater chances for an extra harvest if this is the case.
// The cap is defined in hydro_controls and can be edited by coders on the fly.
// We just don't bother if the output is below one.
// mostly a fix for a runtime error if getitem was null
// Just a bit of natural variance to make it interesting
// Marquesas: I thought of everything and couldn't find another way, but we need this for synthlimbs.
// Okay, I meanwhile realized there might be another way but this looks cleaner. IMHO.
// Start up the loop of grabbing all our produce. Remember, each iteration of
// this loop is for one item each.
// this will never happen. but why not!
// If we've got a piece of fruit or veg that contains seeds. More often than
// not this is fruit but some veg do this too.
// Copy the genes from the plant we're harvesting to the new piece of produce.
// We need to do special shit with the genes if the plant is a spliced
// hybrid since they run off instanced datums rather than referencing
// a specific already-existing one.
// Now we calculate the final quality of the item!
// The unstable gene can do weird shit to your produce.
// We also want to put any reagents the plant produces into the new item.
// If we've got a herb or some other thing like wheat or shit like that.
// Mushrooms mostly act the same as herbs, except you can eat them.
// If it's a critter we don't need to do reagents or shit like that but
// we do need to make sure they don't attack the botanist that grew it.
// If the crop is just straight up seeds. Don't need reagents, but we do
// need to pass genes and whatnot along like we did for fruit.
// Same shit again. This isn't so much the crop as it is giving you seeds
// incase you couldn't get them otherwise, though.
// Mostly for dangerous produce (explosive tomatoes etc) that should show up somewhere in the logs (Convair880).
// At this point all the harvested items are inside the plant pot, and this is the
// part where we decide where they're going and get them out.
// If we're putting stuff in a satchel, this is where we do it.
// if the satchel got filled up this will dump any unharvested items on the floor
// if we're harvesting by hand it'll just default to this anyway! truly magical~
// Now we determine the harvests remaining or grant extra ones.
// Immortal is a gene strain that means infinite harvests as long as the plant
// is kept alive, it's on melons usually.
// If we have excellent health, its a +20% chance for an extra harvest.
// We got the bonus so don't reduce harvests.
// No bonus, harvest is decremented as usual.
// Vegetable-style plants always die after one harvest irregardless of harvests
// remaining, though they do get bonuses for having a good harvests gene.
// This proc is for mutating the plant - gene strains, mutant variants and plain old
// genetic bonuses and penalties are handled here.
// Severity is basically a multiplier to odds and amounts.
// This proc is triggered on the plantpot when we want to grow a new plant. Usually by
// planting a seed - even weed growth briefly spawns a seed, uses it for this proc, then
// deletes the seed.
// Now we deal with various health bonuses and penalties for the plant.
// If we have a single-harvest vegetable plant, the harvests gene (which is otherwise
// useless) adds 2 health for every point. This works negatively also!
// If we have a total crop yield above the maximum harvest size, we add it to the
// plant's starting health.
// Add the plant's total endurance score to the health.
// If the seed was damaged by infusions, knock off 5 health points for each point
// of damage to the seed.
// And finally, if health has fallen below zero we put it back to 1 so the plant
// doesn't instantly die. It still will if conditions in the pot aren't good though.
// Copy over all genes, strains and mutations from the seed.
// Finally set the harvests, make sure we always have at least one harvest,
// then get rid of the seed, mutate the genes a little and update the pot sprite.
//Haw haw
// Simple proc to kill the plant without clearing the plantpot out altogether.
// This resets the plantpot back to it's base state, apart from reagents.
// The proc to use for causing health damage to plants. You can just directly alter
// the health var without much of an issue, but that would ignore resistances and
// other stuff like that.
// Various gene strains will eliminate or reduce damage from various sources.
// In some cases damage is increased, like a fast metabolism plant dying faster
// from lack of water.
// Hydroponics procs not specific to the plantpot start here.
// This is called during harvest to add reagents from the plant to a new piece of produce.
// First we decide how much reagents to begin with certain items should hold.
// Now we add the plant's potency to their max reagent capacity. If this causes it to fall
// below one, we allow them at least that much because otherwise what's the damn point!!!
// Build the list of all what reagents need to go into the new item.
// And finally put them in there. We figure out the max volume and add an even amount of
// all reagents into the item.
// This is a proc used to copy genes from PARENT to CHILD. It's used in a whole bunch
// of places, usually when seeds or fruit are created and need to get their genes from
// the thing that spawned them.
// This is the proc plant analyzers use to pop up their readout for the player.
// Should be mostly self-explanatory to read through.
//
// I made some tweaks here for calls in the global scan_plant() proc (Convair880).
// The check to see if a new mutation will be generated. The criteria check for whether
// or not the mutation will actually appear is HYPmutationcheck_full.
// This just checks to see if we have a paticular gene strain active.
// This is the proc for checking if a new random gene strain will appear in the plant.
// And this one is for forcibly adding specific strains.
// This proc jumbles up the variables in a plant's genes. It's fundamental to breeding.
// This proc iterates through all of the various boundaries and requirements a mutation must
// have to appear, and if all of them are matchedit gives the green light to go ahead and
// add it - though there's still a % chance involved after this check passes which is handled
// where this check is called, usually.
// Part of mutationcheck_full. Just a simple mathematical check to keep the prior proc
// more compact and efficient.
// Machines created specifically to interact with plantpots, kind of abandoned experimental
// shit for the time being for the most part.
// sprites by Clarks
// :I
// for canister explosions
//For preventing the DAMNABLE window taking focus when manually inputting pressure
//Can not have a pressure delta that would cause environment pressure > tank pressure
//Actually transfer the gas
// should the canister blow the hell up?
//Canister bomb grumpy sounds
//If it's counting down
//EXPLOSION IMMINENT
//Someone might have defused it or the bomb failed
// cogwerks- high pressure tank explosions
//Otherwise canister bombs detonate after rupture
// has anyone drained the tank?
// smash shit
// wreck shit
// cut down the number of things that get blown around
//Wire: canister bomb stuff
//var/df_code_text //WIRE TODO: finish det codes
//Wire: canister bomb stuff
//Detonator header
//Timer
//fuckin byond goes below zero sometimes due to lag/byond being byond
//Detonator/priming
/* WIRE TODO: finish det codes
df_code_text = "<b>Defusal Code: </b>"
if (src.det.dfcodeSet)
df_code_text += "<A href='?src=\ref[src];defuseCode=1'>Set Code</A>"
else
df_code_text += "<A href='?src=\ref[src];defuseCode=1'>Enter Code</A>"
*/
//Wire: canister bomb stuff start
/* WIRE TODO: finish det codes
if (href_list["defuseCode"])
if (src.det.dfcodeSet) //code already programmed in
var/code = copytext(input(usr, "[src.det.dfcodeTries] attempts left", "Enter defusal code (4 digits)") as num, 1, 4)
if (length(code) != 4) return ..()
if (code == src.det.dfcode) //defused!
playsound(src.loc, "sound/machines/ping.ogg", 50, 1)
src.visible_message("<B><font color=#32CD32>The detonator assembly emits a sighing, fading beep. The bomb has been disarmed.</font></B>")
src.det.defused = 1
else
if (src.det.dfcodeTries >= 1) //still more tries left
playsound(src.loc, "sound/machines/buzz-two.ogg", 50, 1)
src.visible_message("<B><font color=#B7410E>The detonator bloops an annoyed tone. Wrong code! \[[src.det.dfcodeTries] attempts remaining\]</font></B>")
src.det.dfcodeTries = src.det.dfcodeTries - 1
else //uh oh! kaboom!
playsound(src.loc, "sound/machines/whistlealert.ogg", 50, 1)
src.visible_message("<B><font color=red>The detonator rumbles menacingly. The timer changes to 3 seconds remaining. Oh dear.</font></B>")
src.det.part_fs.time = 3
else //still gotta set dat code yo
var/code = copytext(input(usr, "[src.det.dfcodeTries] attempts left", "Enter defusal code (4 digits)") as num, 1, 4)
boutput(world, "[length(code)]")
*/
//Wire: canister bomb stuff end
//0 = siphoning, 1 = releasing
//Can not have a pressure delta that would cause environment pressure > tank pressure
//Actually transfer the gas
//Can not have a pressure delta that would cause environment pressure > tank pressure
//Actually transfer the gas
//Take a gas sample
//Filter it
// drsingh attempted fix for Cannot read null.temperature
// if(istype(trace_gas, /datum/gas/oxygen_agent_b))
//Remix the resulting gases
//only react when pipe_network will ont it do it for you
//Allow for reactions
//Make sure not already connected to something else
//Make sure are close enough for a valid connection
//logTheThing("combat", usr, null, "attaches [src] to [new_port] at [showCoords(new_port.x, new_port.y, new_port.z)].")
//Perform the connection
//Prevent movement
//Actually enforce the air sharing
// Contains:
// - Portable machinery remote parent
// - Broken decal remote
// - Port-a-Brig & remote
// - Port-a-Medbay & remote
// - Port-a-NanoMed & remote
// - Port-a-Sci & remote
///////////////////////////// Remote parent ///////////////////////////////////
// Adapted from the PDA program in portable_machinery_control.dm (Convair880).
// For user prompt stuff.
// In relation to world time.
// As to avoid a separate lookup for every remote.
// Failure states:
// 0: Tele-blocked loc, src/dest.loc/remote is null or related errors.
// 1: Pass.
// 2: On cooldown.
// 3: There's an occupant and type of machinery requires lock to be engaged.
// 4: Obstacle at dest.loc.
// 5: Obstacle at home.loc.
// If we're in a pod etc and want to summon the device, or if the machinery is on the MULE.
// Both can have unexpected and bad results.
// It's not a Port-a-Sci, okay.
// It's not a Port-a-Sci, okay.
// We don't have to loop through the remote.loc checks as well if we send the device back to its home turf.
// Somebody will find a way to abuse it if I don't put this here.
// Somebody will find a way to abuse it if I don't put this here.
// I have sinned, though the BAD OPERATOR might be unproblematic here.
// Z-level check bypass for Port-a-Sci.
// We're at home, so let's summon the thing to our location.
// Send back to home location.
///////////////////////////////// Remotes //////////////////////////////////
// Don't show stuff in "somewhere", okay.
// Don't remove the #[number] part here.
// Don't show stuff in "somewhere", okay.
// Don't remove the #[number] part here.
// I suppose this device would be sorta useless with tele-block checks?
/*var/turf/M_loc = get_turf(M)
if (M && M_loc && isturf(M_loc) && isrestrictedz(M_loc.z)) // Don't show stuff in "somewhere", okay.
continue*/
// Don't remove the #[number] part here.
// Don't show stuff in "somewhere", okay.
// Don't remove the #[number] part here.
///////////////////////////////////// Port-a-Brig /////////////////////////////////////
// Could be useful (Convair880).
// The crusher, hell fires etc. This feature enables quite a bit of mischief.
//What if you drop something while inside? WHAT THEN HUH?
////////////////////////////////////////// Port-a-Medbay /////////////////////////////////////
// Could be useful (Convair880).
// The crusher, hell fires etc. This feature enables quite a bit of mischief.
//Sometimes people drop stuff OKAY
/////////////////////////////////////// Port-a-Sci ///////////////////////////////////////////
//mats = 30 // Nope! We don't need multiple personal teleporters without any z-level restrictions (Convair880).
//Hilarious accident mode, more like
//Debug vars that should never ever be used maliciously, no sir
// This thing isn't z-level-restricted except for the homeloc.
// Somebody WILL find an exploit otherwise (Convair880).
// The crusher, hell fires etc. This feature enables quite a bit of mischief.
//We want a logged-in and living mob otherwise fucklers could spam this without consequence.
//Body swapping
//Don't think you're gonna get lucky, ghosts!
//What the actual fuck is this motherfucking nonsense shit fuck I hate you byond what the hell.
//Step once more to prevent us from hitting the swapped mob
//Other fuckery
//This is totally safe.
//Travel sickness!
//A nice tan
//A very nice tan
//The nicest tan
//lol
//Mechanical failure aaaaaa
//Hitchhiker friend!
//Hilarious accident
//////////////////////////////////////// Port-a-NanoMed ///////////////////////////////////////////
//animate_bumble(src, -1, 10, 1, -1)
//Products
//Hidden
// Could be useful (Convair880).
// The crusher, hell fires etc. This feature enables quite a bit of mischief...well, if it wouldn't be the NanoMed.
//logTheThing("station", usr, null, "sets [src.name]'s home turf to [log_loc(src.homeloc)].")
// the Area Power Controller (APC), formerly Power Distribution Unit (PDU)
// one per area, needs wire conection to power network
// controls power to devices in that area
// may be opened to change power cell
// three different channels (lighting/equipment/environ) - may each be set to on, off, or auto
//NOTE: STUFF STOLEN FROM AIRLOCK.DM thx
// set so that APCs aren't found as powernet nodes
// Area.name
// initial cell charge %
// 0=no cell, 1=regular, 2=high-cap (x5) <- old, now it's just 0=no cell, otherwise dictate cellcapacity by changing this value. 1 used to be 1000, 2 was 2500
//0: Screwdriver - Disconnect Control Unit -> 1: 4 units of cable - repair autotransformer -> 2: Wrench - Tune autotransformer -> 3: Multitool - Reset control circuitry -> 4: Screwdriver - Reconnect circuitry.
//0: Local interface only, 1: Local interface and network interface, 2: network interface only.
//The time until we auto disconnect (if we don't get a refresh ping)
//Have we sent a timeout refresh alert?
// luminosity = 1
// wonder if this will help the cpu usage?
//to make this not randomize the wires, just set index to 1 and increment it in the flag for loop (after doing everything else).
// unbroken
// && M.machine == src is omitted because if we triggered this by using the dialog, it doesn't matter if our machine changed in between triggering it and this - the dialog is probably still supposed to refresh.
// unbroken
// offset 24 pixels in direction of dir
// this allows the APC to be embedded in a wall, yet still inside an area
// to fix Vars bug
// is starting with a power cell installed, create it and set its charge level
// cell_type is maximum charge (old default was 1000 or 2500 (values one and two respectively)
// (convert percentage to actual value)
// making life easy for mappers since 2013
// 2015 addendum: The fixed name checks are kept for backward compatibility, I'm not gonna manually replace every APC of each of the six maps we have right now.
// create a terminal object at the same position as original turf loc
// wires will attach to this
// COGWERKS NOTE: disabling calls to this proc for now, it is ruining the live servers
// update the APC icon to show the three base states
// also add overlays for indicator lights
// if no status overlays list, this is first call
// 0=blue 1=red
// 0=red, 1=yellow/black 2=green
// 0=red, 1=green, 2=blue
// if opened, show cell if it's inserted
// also delete all overlays
// if closed, update overlays for channel status
// trying to unlock with an emag card
//attack with an item - open/close cover, insert cell, or (un)lock interface
//APC REPAIR
//Can't use CURRENT dir because it is set to south on spawn.
//Clear broken flag
//Repair the transformer with a cable.
// crowbar means open or close the cover
// trying to put a cell inside
// haxing
// trying to unlock the interface with an ID card
// attack with hand - remove cell (if cover open) or interact with the APC
// do APC interaction
/*for (var/area/relatedArea in area)
relatedArea.power_light = (lighting > 1)
relatedArea.power_equip = (equipment > 1)
relatedArea.power_environ = (environ > 1)*/
/*for (var/area/relatedArea in area)
relatedArea.power_light = 0
relatedArea.power_equip = 0
relatedArea.power_environ = 0*/
//Note: the power_change() for areas ALREADY deals with relatedArea. Don't put it in the loops here!!
// find the powernet of the connected cable
// cable is unpowered
// unconnected cable is unpowered
// elec insulted gloves protect completely
//someone juiced up the grid enough, people going to die!
//this doesn't work for some reason, give me a while I'll figure it out
// if(APC_WIRE_IDSCAN) nothing happens when you cut this wire, add in something if you want whatever
// are you fuckin retarded
//this doesn't work for some reason, give me a while I'll figure it out
// basically pulse but with a really good chance of dying
//not used in this function
//one wire for AI control. Cutting this prevents the AI from controlling the door unless it has hacked the door through the power connection (which takes about a minute). If both main and backup power are cut, as well as this wire, then the AI cannot operate or hack the door at all.
//aidisabledDisabled: If 1, AI control is disabled until the AI hacks back in and disables the lock. If 2, the AI has bypassed the lock. If -1, the control is enabled but the AI had bypassed it earlier, so if it is disabled again the AI would have no trouble getting back in.
// if(APC_WIRE_IDSCAN) nothing happens when you cut this wire, add in something if you want whatever
//var/wireFlag = apcWireColorToFlag[wireColor] //not used in this function
//unlocks the APC for 30 seconds, if you have a better way to hack an APC I'm all ears
// Fix for exploit that allowed synthetics to perma-stun intruders by cycling the APC
// ad infinitum (activating power/turrets for one tick) despite missing power cell (Convair880).
// Same deal.
// Yep.
// off=0, off auto=1, on=2, on auto=3
// off=0, off auto=1, on=2, on auto=3
// off=0, off auto=1, on=2, on auto=3
//store states to update icon if any change
// draw power from cell as before
// clamp deduction to a max, amount left in cell
// if power excess, or enough anyway, recharge the cell
// by the same amount just used
// add the load used to recharge the cell
// no excess, and not enough per-apc
// can we draw enough from cell+grid to cover last usage?
//recharge with what we can
// so draw what we can from the grid
// not enough power available to run the last tick!
// This turns everything off in the case that there is still a charge left on the battery, just not enough to run the room.
// set channels depending on how much charge we have left
// zero charge, turn all off
// <15%, turn off lighting & equipment
// <30%, turn off equipment
// otherwise all can be on
// now trickle-charge the cell
// check to make sure we have enough to charge
// Max charge is perapc share, capped to cell capacity, or % per second constant (Whichever is smallest)
// Removes the power we're taking from the grid
// actually recharge the cell
// stop charging
// show cell as fully charged if so
// chargemode off
// no cell, switch everything off
// update icon & area power if anything changed
// val 0=off, 1=off(auto) 2=on 3=on(auto)
// on 0=off, 1=on, 2=autooff
// if on, return off
// if auto-on, return auto-off
// if auto-off, return auto-on
// if auto-on, return auto-off
// damage and destruction acts
// overload all the lights in this APC area
//We should only receive signals relayed from our terminal.
//src.updateUsrDialog()
//Huh, who is this?
//src.updateUsrDialog()
// unconnected cable is unpowered
// attach a wire to a power machine - leads from the turf you are standing on
// only for attaching to directwired machines
// the power cable object
// ensure d1 & d2 reflect the icon_state for entering and exiting cable
// hide if turf is not intact
// but show if in space
// called when a cable is deleted
// set if network will be rebuilt manually
// make sure cable & powernet data is valid
// updated the powernets
// then go ahead and delete the cable
// && istype(loc, /turf/simulated))
// returns the powernet this cable belongs to
// find the powernet
// 0-X cables are 1 unit, X-X cables are 2 units long
// to fix no-action bug
// not needed, but for clarity
//note do shock in cable_join
// find the powernet
// is it powered?
// shock the user with probability prb
// unconnected cable is unpowered
//var/shock_damage = 0
// cogwerks - simplifying this stack of ranges below into something that feels better
//shock_damage = (max(rand(10,20), round(PN.avail * 0.00004)))*prot // adjust the multiplier as needed
/* if(PN.avail > 700000) //someone juiced up the grid enough, people going to die!
shock_damage = min(rand(70,145),rand(70,145))*prot
else if(PN.avail > 200000)
shock_damage = min(rand(35,110),rand(35,110))*prot
playsound(src.loc, "sound/effects/elec_bzzz.ogg", 50, 1)
else if(PN.avail > 75000)
shock_damage = min(rand(30,100),rand(30,100))*prot
playsound(src.loc, "sound/effects/electric_shock.ogg", 50, 1)
else if(PN.avail > 50000)
shock_damage = min(rand(25,90),rand(25,90))*prot
playsound(src.loc, "sound/effects/electric_shock.ogg", 50, 1)
else if(PN.avail > 25000)
shock_damage = min(rand(20,80),rand(20,80))*prot
playsound(src.loc, "sound/effects/electric_shock.ogg", 50, 1)
else if(PN.avail > 10000)
shock_damage = min(rand(20,65),rand(20,65))*prot
playsound(src.loc, "sound/effects/electric_shock.ogg", 50, 1)
else
shock_damage = min(rand(20,45),rand(20,45))*prot
playsound(src.loc, "sound/effects/electric_shock.ogg", 50, 1)*/
// message_admins("<span style=\"color:blue\"><B>ADMIN: </B>DEBUG: shock_damage = [shock_damage] PN.avail = [PN.avail] user = [user] netnum = [netnum]</span>")
/*if (user.bioHolder)
. = user.bioHolder.HasEffect("resist_electric")
if (. == 2)
var/healing = 0
healing = shock_damage / 3
user.HealDamage("All", healing, healing)
user.take_toxin_damage(0 - healing)
boutput(user, "<span style=\"color:blue\">You absorb the electrical shock, healing your body!</span>")
return 0
else if (. == 1)
boutput(user, "<span style=\"color:blue\">You feel electricity course through you harmlessly!</span>")
return 0
//cogwerks - fun horrible things
switch(shock_damage)
if (0 to 25)
playsound(user.loc, "sound/effects/electric_shock.ogg", 50, 1)
if (26 to 59)
playsound(user.loc, "sound/effects/elec_bzzz.ogg", 50, 1)
if (60 to 99)
playsound(user.loc, "sound/effects/elec_bigzap.ogg", 50, 1) // begin the fun arcflash
boutput(user, "<span style=\"color:red\"><b>[src] discharges a violent arc of electricity!</b></span>")
flick("e_flash", user.flash)
user.stunned = 10
if (istype(user, /mob/living/carbon/human))
var/mob/living/carbon/human/H = user
H.cust_one_state = pick("xcom","bart","zapped")
H.set_face_icon_dirty()
if (100 to INFINITY) // cogwerks - here are the big fuckin murderflashes
playsound(user.loc, "sound/effects/elec_bigzap.ogg", 50, 1)
playsound(user.loc, "explosion", 50, 1)
flick("e_flash", user.flash)
if (istype(user, /mob/living/carbon/human))
var/mob/living/carbon/human/H = user
H.cust_one_state = pick("xcom","bart","zapped")
H.set_face_icon_dirty()
var/turf/T = get_turf(user) // not src goddamn
if(T)
T.hotspot_expose(5000,125)
explosion(src, T, -1,-1,1,2)
if (istype(user, /mob/living/carbon/human))
var/mob/living/carbon/human/M = user
if(prob(20))
boutput(M, "<span style=\"color:red\"><b>[src] vaporizes you with a lethal arc of electricity!</b></span>")
if(M.shoes)
M.drop_from_slot(M.shoes)
new /obj/decal/cleanable/ash(M.loc)
spawn(1)
M.elecgib()
else
boutput(M, "<span style=\"color:red\"><b>[src] blasts you with an arc flash!</b></span>")
if(M.shoes)
M.drop_from_slot(M.shoes)
var/atom/targetTurf = get_edge_target_turf(M, get_dir(src, get_step_away(M, src)))
M.throw_at(targetTurf, 200, 4)
// fuck all that deafen/flash mess
///////////// end arcflash mess
if(user)
user.TakeDamage(user.hand == 1 ? "l_arm" : "r_arm", 0, shock_damage)
user.updatehealth()
boutput(user, "<span style=\"color:red\"><B>You feel a powerful shock course through your body!</B></span>")
user.unlock_medal("HIGH VOLTAGE", 1)
if (istype(user,/mob/living/carbon/))
var/mob/living/carbon/C = user
C.Virus_ShockCure(user, 100)
C.shock_cyberheart(100)
spawn(1) // cogwerks - changed sleep to spawn
if(user.stunned < 12) user.stunned = min((shock_damage/5), 12) //cogwerks: limiter - 40 stun was waaaaay too high
if(user.weakened < 8) user.weakened = min((shock_damage/6), 8) // cogwerks: limiter
for(var/mob/M in AIviewers(src))
if(M == user) continue
M.show_message("<span style=\"color:red\">[user.name] was shocked by the [src.name]!</span>", 3, "<span style=\"color:red\">You hear a heavy electrical crack</span>", 2)
return 1
return 0*/
// called when a new cable is created
// can be 1 of 3 outcomes:
// 1. Isolated cable (or only connects to isolated machine) -> create new powernet
// 2. Joins to end or bridges loop of a single network (may also connect isolated machine) -> add to old network
// 3. Bridges gap between 2 networks -> merge the networks (must rebuild lists also) (currently just calls makepowernets. welp)
//locate() in (d1 ? get_step(src,d1) : orange(0, src) )
//locate() in (d2 ? get_step(src,d2) : orange(0, src) )
// Terminal connections aren't always restored when laying wires...and I can't be bothered
// to dive into the powernet code to avoid an additional makepowernets() call. Sorry.
//ugh :(
//powernets are really in need of a renovation. makepowernets() is called way too much and is really intensive on the server ok.
// Some non-traitors love to hotwire the engine (Convair880).
// note %age conveted to actual charge in New
// true if rigged to explode
// mob responsible for the explosion
// how much power the cell generates by itself per process tick
// used for autoprocess shit
//should be 0 to 20000
// I think this relic of a by-gone age is only used by APCs (in New()). Did result in absurd numbers for these
// pre-charged power cells, though. How did this go unnoticed for many years?
// 1) Power cell descs aren't dynamic. 2) Self-charging cells are in the item loop and capped.
// 3) The majority of charged power cells placed in the map editor were var-editied to use this formula (Convair880).
// charge = charge * maxcharge/100.0 // map obj has charge as percentage, convert to real value here
// return % charge of cell
// use power from a cell
// recharge the cell
// Negative charge isn't an uncommon occurrence, but it appeared too expensive to keep an additional
// ~270 power cells in the item loop just for this check (simple as it may be) (Convair880).
// Moved the stungloves stuff to gloves.dm (Convair880).
/* else if (istype(W, /obj/item/cable_coil))
var/obj/item/cable_coil/C = W
if (C.amount < 4)
user.show_text("You need at least 4 pieces of cable to attach it to [src].", "red")
else if (src.zap(user))
return
else
C.use(4)
user.show_text("You attach some of the cable to [src].[prob(20) ? " That seems safe." : null]", "blue")
new /obj/item/robodefibrilator/makeshift(get_turf(src), src)
user.u_equip(src)
*/
//Oh no!
// engine ungrump
//src.overlays = null
//if (src.active) src.overlays += image('icons/obj/power.dmi', "furn-burn")
//if (fuelperc >= 20) src.overlays += image('icons/obj/power.dmi', "furn-c1")
//if (fuelperc >= 40) src.overlays += image('icons/obj/power.dmi', "furn-c2")
//if (fuelperc >= 60) src.overlays += image('icons/obj/power.dmi', "furn-c3")
//if (fuelperc >= 80) src.overlays += image('icons/obj/power.dmi', "furn-c4")
//Keep it in cache for when it's toggled
//At max fuel, the state will be 4, aka all bars, then it will lower / increase as fuel is added
//The fuel state has changed and we need to do an update
//Add the overlay
//Clear the overlay
// four fuckin twenty all day
// generator output coefficient from Q
//65% of Carnot efficiency
// uncomment to debug
// logTheThing("debug", null, null, "POWER: [lastgen] W generated at [efficiency*100]% efficiency and sinks sizes [cold_air_heat_capacity], [hot_air_heat_capacity]")
// update icon overlays only if displayed level has changed
// generator output coefficient from Q
//65% of Carnot efficiency
// uncomment to debug
// logTheThing("debug", null, null, "POWER: [lastgen] W generated at [efficiency*100]% efficiency and sinks sizes [cold_air_heat_capacity], [hot_air_heat_capacity]")
// update icon overlays only if displayed level has changed
// Overhauled the generator to incorporate APC.cell charging.
// It used to in the past, but that feature was reverted for reasons unknown.
// However, it's not a C&P job of the old code (Convair880).
// 1 = charge APC, 2 = charge inserted power cell.
// If either of these values aren't competitive, nobody will bother with the generator.
// Remember, there's quite a bit of hassle involved when buying (i.e. QM) and using one of these.
// And you can't even fully recharge a 15000 cell with these parameters and stock plasma tank.
// Units per tick. Comparison: ~20 (APC), 250 (regular cell charger).
// Per tick. Stock (304 kPa) tank will last about 6 min when charging non-stop.
// Linked APC if mode == 1.
// In relation to world time. Ideally, we don't want to run this every tick.
// Generator doesn't need to shut down when in APC mode.
// It might have happened, I guess?
// Because we don't run the check every tick.
// Don't combust plasma if we don't have to.
// Call proc to trigger rigged cell and log entries.
// Call proc to trigger rigged cell and log entries.
// It might have happened, I guess?
// It's just gonna cause trouble otherwise.
// The lighting system
//
// consists of light fixtures (/obj/machinery/light) and light tube/bulb items (/obj/item/light)
// status values shared between lighting fixtures and items
// For metal sheets. Can't easily change an item's vars the way it's set up (Convair880).
// the standard tube light fixture
// base description and icon_state
// They were appearing under mobs which is a little weird - Ostaf
// 1 if on, 0 if off
// luminosity when on, also used in power calculation
// LIGHT_OK, _EMPTY, _BURNED or _BROKEN
// the type of the inserted light item
// the name of the inserted light item
// count of number of times switched on/off
// this is used to calc the probability the light burns out
// true if rigged to explode
// mob responsible for the explosion
// the desk lamp
// independent switching for lamps - not controlled by area lightswitch
// green-shaded desk lamp
// green-shaded desk lamp
// create a new lighting fixture
// update the icon_state and luminosity of the light depending on its state
// set icon_states
// if the state changed, inc the switching counter
// now check to see if the bulb is burned out
// attempt to set the light's on/off status
// will not switch on if broken/burned/empty
// examine verb
// attack with item - insert light (if right type), otherwise try to break the light
//Wire TODO: Magtractor handling here
// attempt to insert light
//rigged = 0
//user.put_in_hand_or_drop(OL)
// attempt to break the light
// attempt to stick weapon into light socket
// returns whether this light has power
// true if area has power and lightswitch is on
// ai attack - do nothing
// attack with hand - remove tube/bulb
// if hands aren't protected and the light is on, burn the player
// hey don't run around and steal all the emergency bolts you jerk
// make it burn hands if not wearing fire-insulated gloves
// *** TODO: better handling of glove heat protection
// if burned, don't remove the light
// create a light tube/bulb item and put it in the user's hand
// light item inherits the switchcount, then zero it
// break the light and make sparks if was on
// explosion effect
// destroy the whole light fixture or just shatter it
//blob effect
// timed process
// use power
// Used to be 20 with the old src.brightness values (reduced drastically for the new lighting system).
// called when area power state changes
//TODO fix the dispose proc for this so that when it is sent into the delete queue it doesn't try and exec this
// called when on fire
//0% at <400C, 100% at >500C
// explode the light
// break it first to give a warning
// special handling for emergency lights
// called when area power state changes
// override since emergency lights do not use area lightswitch
// special handling for desk lamps
// if attack with hand, only "grab" attacks are an attempt to remove bulb
// otherwise, switch the lamp on/off
// do standard hand attack
// called when area power state changes
// override since lamp does not use area lightswitch
// returns whether this lamp has power
// true if area has power and lamp switch is on
// the light item
// can be tube or bulb subtypes
// will fit into empty /obj/machinery/light of the corresponding type
// LIGHT_OK, LIGHT_BURNED or LIGHT_BROKEN
// number of times switched
// true if rigged to explode
// mob responsible
// this isn't working for some reason
// the smaller bulb light fixture
// update the icon state and description of the light
// attack bulb/tube with object
// if a syringe, can inject plasma to make it explode
// called after an attack with a light item
// shatter light, unless it was an attempt to put it in a light socket
// now only shatter if the intent was harm
// the power monitoring computer
// for the moment, just report the status of all APCs in the same powernet
// tweaked version to hook up to the engine->smes powernet and show SMES usage stats and power pro
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment