diff --git a/.gitignore b/.gitignore index 0a9a1e1e84b..d39363230f7 100644 --- a/.gitignore +++ b/.gitignore @@ -61,4 +61,9 @@ players2.sqlite cfg .vscode +*.code-workspace /byond + +# Thumbs.db (windows image caching) +Thumbs.db + diff --git a/.travis.yml b/.travis.yml index be3ca0a5db2..c52dc1e70f0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,10 +7,14 @@ sudo: false env: global: - BYOND_MAJOR="512" - - BYOND_MINOR="1406" + - BYOND_MINOR="1413" - ALL_MAPS="tgstation metaclub defficiency packedstation test_box test_tiny" + - PROJECT_NAME="vgstation13" - RUST_BACKTRACE="1" - RUST_TEST_THREADS=1 + matrix: + - DM_UNIT_TESTS="1" + - DM_UNIT_TESTS="0" cache: directories: @@ -42,7 +46,9 @@ script: # --jobs 1 to prevent threading problems with the BYOND crate. - cargo test --jobs 1 --verbose - cd - -- echo ${ALL_MAPS} | xargs tools/travis/build.py vgstation13.dme -M +- tools/travis/build.py +- cp tools/travis/config/config.txt config/ +- (! tools/travis/run_tests.py | grep -zq "UNIT TEST FAIL") notifications: irc: diff --git a/code/__HELPERS/_macros.dm b/__DEFINES/_macros.dm similarity index 80% rename from code/__HELPERS/_macros.dm rename to __DEFINES/_macros.dm index 5897eb1fdba..ba8c596487d 100644 --- a/code/__HELPERS/_macros.dm +++ b/__DEFINES/_macros.dm @@ -1,43 +1,44 @@ -///MACRO FILE// //Define your macros here if they're used in general code //Typechecking macros // fun if you want to typecast humans/monkeys/etc without writing long path-filled lines. #define ishuman(A) istype(A, /mob/living/carbon/human) -#define isjusthuman(A) (ishuman(A) && A.species && istype(A.species, /datum/species/human)) +#define isjusthuman(A) (ishuman(A) && istype(A:species, /datum/species/human)) #define ismonkey(A) istype(A, /mob/living/carbon/monkey) -#define ismartian(A) istype(A, /mob/living/carbon/martian) +#define ismartian(A) istype(A, /mob/living/carbon/complex/martian) -#define ishigherbeing(A) (ishuman(A) || ismartian(A)) +#define ishigherbeing(A) (ishuman(A) || ismartian(A) || (ismonkey(A) && A.dexterity_check())) -#define isvox(A) (ishuman(A) && A.species && istype(A.species, /datum/species/vox)) +#define isvox(A) (ishuman(A) && istype(A:species, /datum/species/vox)) -#define isdiona(A) (ishuman(A) && A.species && istype(A.species, /datum/species/diona)) +#define isdiona(A) (ishuman(A) && istype(A:species, /datum/species/diona)) -#define isgrey(A) (ishuman(A) && A.species && istype(A.species, /datum/species/grey)) +#define isgrey(A) (ishuman(A) && istype(A:species, /datum/species/grey)) -#define isplasmaman(A) (ishuman(A) && A.species && istype(A.species, /datum/species/plasmaman)) +#define isplasmaman(A) (ishuman(A) && istype(A:species, /datum/species/plasmaman)) -#define isskellington(A) (ishuman(A) && A.species && istype(A.species, /datum/species/skellington)) +#define isskellington(A) (ishuman(A) && istype(A:species, /datum/species/skellington)) -#define iscatbeast(A) (ishuman(A) && A.species && istype(A.species, /datum/species/tajaran)) +#define iscatbeast(A) (ishuman(A) && istype(A:species, /datum/species/tajaran)) -#define isunathi(A) (ishuman(A) && A.species && istype(A.species, /datum/species/unathi)) +#define isunathi(A) (ishuman(A) && istype(A:species, /datum/species/unathi)) -#define isskrell(A) (ishuman(A) && A.species && istype(A.species, /datum/species/skrell)) +#define isskrell(A) (ishuman(A) && istype(A:species, /datum/species/skrell)) -#define ismuton(A) (ishuman(A) && A.species && istype(A.species, /datum/species/muton)) +#define ismuton(A) (ishuman(A) && istype(A:species, /datum/species/muton)) -#define isgolem(A) (ishuman(A) && A.species && istype(A.species, /datum/species/golem)) +#define isgolem(A) (ishuman(A) && istype(A:species, /datum/species/golem)) -#define isslimeperson(A) (ishuman(A) && A.species && istype(A.species, /datum/species/slime)) +#define isslimeperson(A) (ishuman(A) && istype(A:species, /datum/species/slime)) -#define ishorrorform(A) (ishuman(A) && A.species && istype(A.species, /datum/species/horror)) +#define ishorrorform(A) (ishuman(A) && istype(A:species, /datum/species/horror)) -#define isgrue(A) (ishuman(A) && A.species && istype(A.species, /datum/species/grue)) +#define isgrue(A) (ishuman(A) && istype(A:species, /datum/species/grue)) + +#define ismushroom(A) ((ishuman(A) && istype(A:species, /datum/species/mushroom)) || (istype(A, /mob/living/carbon/monkey/mushroom))) #define ishologram(A) (istype(A, /mob/living/simple_animal/hologram/advanced)) @@ -183,10 +184,13 @@ #define isID(A) (istype(A, /obj/item/weapon/card/id)) +#define isRoboID(A) (istype(A, /obj/item/weapon/card/robot)) + #define isPDA(A) (istype(A, /obj/item/device/pda)) #define isfloor(A) (istype(A, /turf/simulated/floor) || istype(A, /turf/unsimulated/floor) || istype(A, /turf/simulated/shuttle/floor)) +#define issilent(A) (A.silent || (ishuman(A) && (A:miming || A:species:flags & IS_SPECIES_MUTE))) //Remember that silent is not the same as miming. Miming you can emote, silent you can't gesticulate at all //Macros for antags #define isfaction(A) (istype(A, /datum/faction)) @@ -276,3 +280,10 @@ proc/get_space_area() #define subtypesof(A) (typesof(A) - A) #define LIBVG(function, arguments...) call("./libvg.[world.system_type == UNIX ? "so" : "dll"]", function)(arguments) + +// For areas that are on the map, `x` is the coordinate of the turf with the lowest z, y, and x coordinate (in that order) that is contained by the area. +#define is_area_in_map(A) (A.x) + +#define SNOW_THEME (map.snow_theme || Holiday == XMAS || Holiday == XMAS_EVE) + +#define get_conductivity(A) (A ? A.siemens_coefficient : 1) diff --git a/__DEFINES/areas.dm b/__DEFINES/areas.dm index 51c3b7e2cdc..6e69cd115f5 100644 --- a/__DEFINES/areas.dm +++ b/__DEFINES/areas.dm @@ -1,3 +1,4 @@ //area-only flags #define NO_PORTALS 1 -#define NO_TELEPORT 2 \ No newline at end of file +#define NO_TELEPORT 2 +#define NO_MESONS 4 \ No newline at end of file diff --git a/__DEFINES/atmos.dm b/__DEFINES/atmos.dm index 44116ba3e04..8e2a907f221 100644 --- a/__DEFINES/atmos.dm +++ b/__DEFINES/atmos.dm @@ -10,11 +10,11 @@ #define N2MARS 0.04 //Mars atmosphere is actually 1.9% nitrogen, 1.9% argon with traces of other gases. Simplified to 4% nitrogen #define MOLES_PLASMA_VISIBLE 0.7 //Moles in a standard cell after which plasma is visible -#define MOLES_O2STANDARD MOLES_CELLSTANDARD*O2STANDARD // O2 standard value (21%) -#define MOLES_N2STANDARD MOLES_CELLSTANDARD*N2STANDARD // N2 standard value (79%) +#define MOLES_O2STANDARD (MOLES_CELLSTANDARD*O2STANDARD) // O2 standard value (21%) +#define MOLES_N2STANDARD (MOLES_CELLSTANDARD*N2STANDARD) // N2 standard value (79%) -#define MOLES_CO2MARS MOLES_CELLMARS*CO2MARS -#define MOLES_N2MARS MOLES_CELLMARS*N2MARS +#define MOLES_CO2MARS (MOLES_CELLMARS*CO2MARS) +#define MOLES_N2MARS (MOLES_CELLMARS*N2MARS) //These are for when a mob breathes poisonous air. #define MIN_PLASMA_DAMAGE 1 @@ -22,14 +22,14 @@ #define BREATH_VOLUME 0.5 //liters in a normal breath #define BREATH_MOLES (ONE_ATMOSPHERE * BREATH_VOLUME /(T20C*R_IDEAL_GAS_EQUATION)) -#define BREATH_PERCENTAGE BREATH_VOLUME/CELL_VOLUME //Amount of air to take a from a tile -#define HUMAN_NEEDED_OXYGEN MOLES_CELLSTANDARD*BREATH_PERCENTAGE*0.16 //Amount of air needed before pass out/suffocation commences +#define BREATH_PERCENTAGE (BREATH_VOLUME/CELL_VOLUME) //Amount of air to take a from a tile +#define HUMAN_NEEDED_OXYGEN (MOLES_CELLSTANDARD*BREATH_PERCENTAGE*0.16) //Amount of air needed before pass out/suffocation commences #define MINIMUM_AIR_RATIO_TO_SUSPEND 0.05 //Minimum ratio of air that must move to/from a tile to suspend group processing -#define MINIMUM_AIR_TO_SUSPEND MOLES_CELLSTANDARD*MINIMUM_AIR_RATIO_TO_SUSPEND //Minimum amount of air that has to move before a group processing can be suspended +#define MINIMUM_AIR_TO_SUSPEND (MOLES_CELLSTANDARD*MINIMUM_AIR_RATIO_TO_SUSPEND) //Minimum amount of air that has to move before a group processing can be suspended -#define MINIMUM_MOLES_DELTA_TO_MOVE MOLES_CELLSTANDARD*MINIMUM_AIR_RATIO_TO_SUSPEND //Either this must be active -#define MINIMUM_TEMPERATURE_TO_MOVE T20C+100 //or this (or both, obviously) +#define MINIMUM_MOLES_DELTA_TO_MOVE (MOLES_CELLSTANDARD*MINIMUM_AIR_RATIO_TO_SUSPEND) //Either this must be active +#define MINIMUM_TEMPERATURE_TO_MOVE (T20C+100) //or this (or both, obviously) #define MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND 0.012 #define MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND 4 //Minimum temperature difference before group processing is suspended @@ -38,8 +38,8 @@ #define MINIMUM_PRESSURE_DELTA_TO_SUSPEND 0.1 //The minimum pressure difference required for groups to remain separate (unless they meet other conditions). Chosen arbitrarily. #define MINIMUM_PRESSURE_RATIO_TO_SUSPEND 0.05 //Minimum RELATIVE difference in pressure for groups to stay separate (unless they meet other conditions). Also chosen arbitrarily. -#define MINIMUM_TEMPERATURE_FOR_SUPERCONDUCTION T20C+10 -#define MINIMUM_TEMPERATURE_START_SUPERCONDUCTION T20C+200 +#define MINIMUM_TEMPERATURE_FOR_SUPERCONDUCTION (T20C+10) +#define MINIMUM_TEMPERATURE_START_SUPERCONDUCTION (T20C+200) //Must be between 0 and 1. Values closer to 1 equalize temperature faster. Should not exceed 0.4 else strange heat flow occurs. #define FLOOR_HEAT_TRANSFER_COEFFICIENT 0.4 @@ -50,13 +50,13 @@ #define WINDOW_HEAT_TRANSFER_COEFFICIENT 0.1 //a hack for now // Fire Damage -#define CARBON_LIFEFORM_FIRE_RESISTANCE 200+T0C +#define CARBON_LIFEFORM_FIRE_RESISTANCE (200+T0C) #define CARBON_LIFEFORM_FIRE_DAMAGE 4 //Plasma fire properties -#define PLASMA_MINIMUM_BURN_TEMPERATURE 100+T0C -#define PLASMA_FLASHPOINT 246+T0C -#define PLASMA_UPPER_TEMPERATURE 1370+T0C +#define PLASMA_MINIMUM_BURN_TEMPERATURE (100+T0C) +#define PLASMA_FLASHPOINT (246+T0C) +#define PLASMA_UPPER_TEMPERATURE (1370+T0C) #define PLASMA_MINIMUM_OXYGEN_NEEDED 2 #define PLASMA_MINIMUM_OXYGEN_PLASMA_RATIO 20 #define PLASMA_OXYGEN_FULLBURN 10 diff --git a/__DEFINES/atom_locking.dm b/__DEFINES/atom_locking_and_control.dm similarity index 55% rename from __DEFINES/atom_locking.dm rename to __DEFINES/atom_locking_and_control.dm index 34c11506869..572c8b98dc8 100644 --- a/__DEFINES/atom_locking.dm +++ b/__DEFINES/atom_locking_and_control.dm @@ -1,3 +1,5 @@ +/* Atom Locking */ + // Flags for the locking categories. #define LOCKED_SHOULD_LIE 1 #define DENSE_WHEN_LOCKING 2 @@ -6,3 +8,12 @@ // Flags for atom.lockflags #define DENSE_WHEN_LOCKED 1 + + +/* Atom Control */ + +//Flags for the control datum +#define REVERT_ON_CONTROLLER_DAMAGED 1 +#define LOCK_EYE_TO_CONTROLLED 2 +#define LOCK_MOVEMENT_OF_CONTROLLER 4 +#define REQUIRES_CONTROL 8 diff --git a/code/__DEFINES/component_desires.dm b/__DEFINES/component_desires.dm similarity index 100% rename from code/__DEFINES/component_desires.dm rename to __DEFINES/component_desires.dm diff --git a/code/__DEFINES/component_signals.dm b/__DEFINES/component_signals.dm similarity index 100% rename from code/__DEFINES/component_signals.dm rename to __DEFINES/component_signals.dm diff --git a/__DEFINES/dates.dm b/__DEFINES/dates.dm new file mode 100644 index 00000000000..4f4868a0184 --- /dev/null +++ b/__DEFINES/dates.dm @@ -0,0 +1,42 @@ +//Useful for making time-limited things. + +#define NEW_YEARS_DAY "New Year's Day" +#define GROUNDHOG_DAY "Groundhog Day" +#define VALENTINES_DAY "Valentine's Day" +#define RANDOM_ACTS_OF_KINDNESS_DAY "Random Acts of Kindness Day" +#define PI_DAY "Pi Day" +#define ST_PATRICKS_DAY "St. Patrick's Day" +#define EASTER "Easter" +#define APRIL_FOOLS_DAY "April Fool's Day" +#define AUTISM_AWARENESS_DAY "Autism Awareness Day" +#define FOUR_TWENTY "Four-Twenty" +#define EARTH_DAY "Earth Day" +#define LABOUR_DAY "Labour Day" +#define FIREFIGHTERS_DAY "FireFighter's Day" +#define OWL_AND_PUSSYCAT_DAY "Owl and Pussycat Day" +#define INTERNATIONAL_PICNIC_DAY "International Picnic Day" +#define SUMMER_SOLSTICE "Summer Solstice" +#define DOCTORS_DAY "Doctor's Day" +#define UFO_DAY "UFO Day" +#define WRITERS_DAY "Writer's Day" +#define FRIENDSHIP_DAY "Friendship Day" +#define BEER_DAY "Beer Day" +#define TALK_LIKE_A_PIRATE_DAY "Talk-Like-a-Pirate Day" +#define STUPID_QUESTIONS_DAY "Stupid-Questions Day" +#define ANIMALS_DAY "Animal's Day" +#define SMILING_DAY "Smiling Day" +#define BOSS_DAY "Boss' Day" +#define HALLOWEEN "Halloween" +#define VEGAN_DAY "Vegan Day" +#define KINDNESS_DAY "Kindness Day" +#define FLOWERS_DAY "Flowers Day" +#define SAYING_HELLO_DAY "Saying-'Hello' Day" +#define HUMAN_RIGHTS_DAY "Human-Rights Day" +#define MONKEY_DAY "Monkey Day" +#define END_OF_THE_WORLD "End of the World" +#define ORGASMING_DAY "Orgasming Day" +#define XMAS_EVE "Christmas Eve" +#define XMAS "Christmas" +#define BOXING_DAY "Boxing Day" +#define NEW_YEARS_EVE "New Year's Eve" +#define FRIDAY_THE_13TH "Friday the 13th" \ No newline at end of file diff --git a/code/__DEFINES/disease2.dm b/__DEFINES/disease2.dm similarity index 100% rename from code/__DEFINES/disease2.dm rename to __DEFINES/disease2.dm diff --git a/__DEFINES/game.dm b/__DEFINES/game.dm index aeb74bd6189..c7fb030e1fe 100644 --- a/__DEFINES/game.dm +++ b/__DEFINES/game.dm @@ -24,10 +24,3 @@ #define MINIGUN_SLOWDOWN_WIELDED 8 #define FIREAXE_SLOWDOWN 1.4 - -// Cyborgs - -#define CYBORG_MOBILITY_MODULE_MODIFIER 0.75 - -#define CYBORG_NO_CHARGE_SLOWDOWN 3 -#define CYBORG_NO_CELL_SLOWDOWN 15 diff --git a/__DEFINES/global.dm b/__DEFINES/global.dm index 7988e230f7d..68e9a4a1ab5 100644 --- a/__DEFINES/global.dm +++ b/__DEFINES/global.dm @@ -1,4 +1,10 @@ -#define DNA_SE_LENGTH 56 +/proc/writeglobal(var/which, var/what) + global.vars[which] = what + +/proc/readglobal(var/which) + return global.vars[which] + +#define DNA_SE_LENGTH 58 #define VOX_SHAPED "Vox","Skeletal Vox" @@ -51,9 +57,6 @@ var/list/paper_blacklist = list("java","onblur","onchange","onclick","ondblclick "onkeypress","onkeyup","onload","onmousedown","onmousemove","onmouseout","onmouseover", \ "onmouseup","onreset","onselect","onsubmit","onunload") - -var/skipupdate = 0 - /////////////// var/eventchance = 10 //% per 5 mins var/event = 0 var/hadevent = 0 @@ -65,7 +68,6 @@ var/endicon = null var/diary = null var/diaryofmeanpeople = null var/admin_diary = null -var/href_logfile = null var/station_name = null var/game_version = "veegee" var/changelog_hash = "" @@ -81,22 +83,16 @@ var/ooc_allowed = 1 var/looc_allowed = 1 var/dooc_allowed = 1 var/traitor_scaling = 1 -//var/goonsay_allowed = 0 -var/dna_ident = 1 var/abandon_allowed = 1 var/enter_allowed = 1 var/guests_allowed = 1 -var/shuttle_frozen = 0 -var/shuttle_left = 0 var/tinted_weldhelh = 1 -var/list/jobMax = list() var/list/bombers = list( ) var/list/admin_log = list ( ) var/list/lawchanges = list( ) //Stores who uploaded laws to which silicon-based lifeform, and what the law was var/list/shuttles = list( ) var/list/reg_dna = list( ) -// list/traitobj = list( ) var/CELLRATE = 0.002 // 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) var/CHARGELEVEL = 0.001 // Cap for how fast cells charge, as a percentage-per-tick (.001 means cellcharge is capped to 1% per second) @@ -140,11 +136,6 @@ var/global/universal_cult_chat = 0 //if set to 1, even human cultists can use cu var/datum/station_state/start_state = null var/datum/configuration/config = null -var/list/combatlog = list() -var/list/IClog = list() -var/list/OOClog = list() -var/list/adminlog = list() - var/suspend_alert = 0 var/Debug = 0 // global debug switch @@ -154,13 +145,9 @@ var/datum/debug/debugobj var/datum/moduletypes/mods = new() -var/wavesecret = 0 var/gravity_is_on = 1 -var/shuttlecoming = 0 - var/join_motd = null -var/forceblob = 0 var/polarstar = 0 //1 means that the polar star has been found, 2 means that the spur modification kit has been found @@ -272,9 +259,6 @@ var/global/event/on_login var/global/event/on_ban var/global/event/on_unban -// List of /plugins -var/global/list/plugins = list() - // Space get this to return for things i guess? var/global/datum/gas_mixture/space_gas = new @@ -317,7 +301,6 @@ var/global/list/minesweeper_best_players = list() var/nanocoins_rates = 1 var/nanocoins_lastchange = 0 -var/speciesinit = 0 var/minimapinit = 0 var/bees_species = list() @@ -385,7 +368,22 @@ var/list/blacklisted_mobs = list( /mob/living/simple_animal/hostile/giant_spider/hunter/dead, // They are dead. /mob/living/simple_animal/hostile/asteroid/hivelordbrood, // They aren't supposed to be playable. /mob/living/simple_animal/hologram, // Can't live outside the holodeck. + /mob/living/simple_animal/hostile/carp/holocarp, //These can but they're just a retarded hologram carp reskin for the love of god. /mob/living/slime_pile, // They are dead. - /mob/living/adamantine_dust // Ditto + /mob/living/adamantine_dust, // Ditto + /mob/living/simple_animal/hostile/viscerator, //Nope. + /mob/living/simple_animal/hostile/mining_drone, //This thing is super broken in the hands of a player and it was never meant to be summoned out of actual mining drone cubes. + /mob/living/simple_animal/bee //Aren't set up to be playable ) +//Boss monster list +var/list/boss_mobs = list( + /mob/living/simple_animal/scp_173, // Just a statue. + /mob/living/simple_animal/hostile/hivebot/tele, // Hivebot spawner WIP thing + /mob/living/simple_animal/hostile/wendigo, // Stupid strong evolving creature things that scream for help + /mob/living/simple_animal/hostile/mechahitler, // Sieg heil! + /mob/living/simple_animal/hostile/alien/queen/large, // The bigger and beefier version of queens. + ) + +// Set by traitor item, affects cargo supplies +var/station_does_not_tip = FALSE diff --git a/code/__DEFINES/hydro.dm b/__DEFINES/hydro.dm similarity index 58% rename from code/__DEFINES/hydro.dm rename to __DEFINES/hydro.dm index d4e431869ff..72e2d4b399f 100644 --- a/code/__DEFINES/hydro.dm +++ b/__DEFINES/hydro.dm @@ -1,2 +1,2 @@ #define HYDRO_PREHISTORIC 1 -#define HYDRO_VOX 2 \ No newline at end of file +#define HYDRO_VOX 2 diff --git a/__DEFINES/math_physics.dm b/__DEFINES/math_physics.dm index 6153a2bdf31..58d3bd9e278 100644 --- a/__DEFINES/math_physics.dm +++ b/__DEFINES/math_physics.dm @@ -12,6 +12,11 @@ #define R_IDEAL_GAS_EQUATION 8.314 //kPa*L/(K*mol) #define ONE_ATMOSPHERE 101.325 //kPa +#define MEGAWATT 1000000 +#define TEN_MEGAWATTS 10000000 +#define HUNDRED_MEGAWATTS 100000000 +#define GIGAWATT 1000000000 + // Radiation constants. #define STEFAN_BOLTZMANN_CONSTANT 5.6704e-8 // W/(m^2*K^4). #define COSMIC_RADIATION_TEMPERATURE 3.15 // K. @@ -30,10 +35,10 @@ #define SPEED_OF_LIGHT 3e8 //not exact but hey! #define SPEED_OF_LIGHT_SQ 9e+16 -#define MELTPOINT_GLASS 1500+T0C -#define MELTPOINT_STEEL 1510+T0C +#define MELTPOINT_GLASS (1500+T0C) +#define MELTPOINT_STEEL (1510+T0C) #define MELTPOINT_SILICON 1687 // KELVIN -#define MELTPOINT_PLASTIC 180+T0C +#define MELTPOINT_PLASTIC (180+T0C) #define MELTPOINT_SNOW 304.15 //about 30°C // The highest number supported is a signed 32-bit floating point number. diff --git a/__DEFINES/mobs.dm b/__DEFINES/mobs.dm index ed46b53d76b..e16447f2b85 100644 --- a/__DEFINES/mobs.dm +++ b/__DEFINES/mobs.dm @@ -1,3 +1,22 @@ #define EYECHECK_NO_PROTECTION 0 #define EYECHECK_PARTIAL_PROTECTION 1 #define EYECHECK_FULL_PROTECTION 2 + +//Values for the m_intent variable +#define M_INTENT_RUN "run" +#define M_INTENT_WALK "walk" + +//Mob species flags (simple stuff mostly for simple_animals) +#define MOB_UNDEAD 1 //zombies, ghosts, skeletons +#define MOB_ROBOTIC 2 //robots +#define MOB_CONSTRUCT 4 //golems, animated armor, animated whatever (not mimics though) +#define MOB_SWARM 8 //swarm of mobs! +#define MOB_HOLOGRAPHIC 16 //holocarps +#define MOB_SUPERNATURAL 32 +#define MOB_NO_PETRIFY 64 //can't get petrified +#define MOB_NO_LAZ 128 //Can not be revived via lazarus injector + +#define BACKPACK 2 +#define SATCHEL_NORM 3 +#define SATCHEL_ALT 4 +#define MESSENGER_BAG 5 diff --git a/__DEFINES/obj_defines.dm b/__DEFINES/obj_defines.dm new file mode 100644 index 00000000000..2414b7edad8 --- /dev/null +++ b/__DEFINES/obj_defines.dm @@ -0,0 +1,22 @@ +//Quality + +#define AWFUL 1 +#define SHODDY 2 +#define POOR 3 +#define NORMAL 4 +#define GOOD 5 +#define SUPERIOR 6 +#define EXCELLENT 7 +#define MASTERWORK 8 +#define LEGENDARY 9 + +var/list/qualityByString = list( + AWFUL = "Awful", + SHODDY = "Shoddy", + POOR = "Poor", + NORMAL = "Normal", + GOOD = "Good", + SUPERIOR = "Superior", + EXCELLENT = "Excellent", + MASTERWORK = "Masterwork", + LEGENDARY = "Legendary") diff --git a/code/__DEFINES/pai_software.dm b/__DEFINES/pai_software.dm similarity index 100% rename from code/__DEFINES/pai_software.dm rename to __DEFINES/pai_software.dm diff --git a/__DEFINES/planes+layers.dm b/__DEFINES/planes+layers.dm index f0a6a71b185..e58f733a2c1 100644 --- a/__DEFINES/planes+layers.dm +++ b/__DEFINES/planes+layers.dm @@ -74,7 +74,6 @@ What is the naming convention for planes or layers? #define ABOVE_PLATING_PLANE -3 - #define HOLOMAP_LAYER 1 // NOTE: ENSURE this is equal to the one at ABOVE_TURF_PLANE! #define CATWALK_LAYER 2 #define DISPOSALS_PIPE_LAYER 3 #define LATTICE_LAYER 4 @@ -86,6 +85,8 @@ What is the naming convention for planes or layers? #define FLOOR_PLANE -2 #define BELOW_TURF_PLANE -1 // objects that are below turfs and darkness but above platings. Useful for asteroid smoothing or other such magic. + #define CORNER_LAYER 2 + #define SIDE_LAYER 3 #define BASE_PLANE 0 // this is where darkness is! see "how planes work" - needs SEE_BLACKNESS or SEE_PIXEL (see blackness is better for ss13) @@ -161,6 +162,7 @@ What is the naming convention for planes or layers? #define ABOVE_HUMAN_PLANE 16 // For things that should appear above humans. + #define SHADOW_LAYER 0 #define VEHICLE_LAYER 0 #define CHAIR_ARMREST_LAYER 0 #define WINDOOR_LAYER 1 @@ -188,6 +190,7 @@ What is the naming convention for planes or layers? #define SINGULARITY_LAYER 6 #define ABOVE_SINGULO_LAYER 7 #define GRAVITYGRID_LAYER 8 + #define SNOW_OVERLAY_LAYER 9 #define LIGHTING_PLANE 19 @@ -200,7 +203,7 @@ What is the naming convention for planes or layers? #define SUPER_PORTAL_LAYER 6 #define NARSIE_GLOW 7 -#define AREA_PLANE 20 +#define ABOVE_LIGHTING_PLANE 20 #define MAPPING_AREA_LAYER 999 #define STATIC_PLANE 21 // For AI's static. @@ -208,7 +211,7 @@ What is the naming convention for planes or layers? #define FULLSCREEN_PLANE 22 // for fullscreen overlays that do not cover the hud. #define FULLSCREEN_LAYER 0 - #define DAMAGE_LAYER 1 + #define DAMAGE_HUD_LAYER 1 #define IMPAIRED_LAYER 2 #define BLIND_LAYER 3 #define CRIT_LAYER 4 @@ -231,6 +234,7 @@ What is the naming convention for planes or layers? /obj/abstract/screen/plane_master/clickmaster plane = BASE_PLANE + mouse_opacity = 0 var/obj/abstract/screen/plane_master/clickmaster/clickmaster = new() @@ -240,4 +244,18 @@ var/obj/abstract/screen/plane_master/clickmaster/clickmaster = new() appearance_flags = 0 plane = BASE_PLANE -var/obj/abstract/screen/plane_master/clickmaster_dummy/clickmaster_dummy = new() \ No newline at end of file +var/obj/abstract/screen/plane_master/clickmaster_dummy/clickmaster_dummy = new() + +// returns a list with the objects sorted depending on their layer, with the lowest objects being the first in the list and the highest objects being last +/proc/plane_layer_sort(var/list/to_sort) + var/list/sorted = list() + for(var/current_atom in to_sort) + var/compare_index + for(compare_index = sorted.len, compare_index > 0, --compare_index) // count down from the length of the list to zero. + var/atom/compare_atom = sorted[compare_index] // compare to the next object down the list. + if(compare_atom.plane < current_atom:plane) // is this object below our current atom? + break + else if((compare_atom.plane == current_atom:plane) && (compare_atom.layer <= current_atom:layer)) // is this object below our current atom? + break + sorted.Insert(compare_index+1, current_atom) // insert it just above the atom it was higher than - or at the bottom if it was higher than nothing. + return sorted // return the sorted list. \ No newline at end of file diff --git a/__DEFINES/reagents.dm b/__DEFINES/reagents.dm index 0e318873f72..c5d59d190d7 100644 --- a/__DEFINES/reagents.dm +++ b/__DEFINES/reagents.dm @@ -107,6 +107,7 @@ #define FLUOROSURFACTANT "fluorosurfactant" #define NICOTINE "nicotine" #define AMMONIA "ammonia" +#define SALINE "saline" #define GLUE "glue" #define DIETHYLAMINE "diethylamine" #define ETHYLREDOXRAZINE "ethylredoxrazine" @@ -192,7 +193,6 @@ #define SPECIALWHISKEY "specialwhiskey" #define GIN "gin" #define ABSINTHE "absinthe" -#define RUM "rum" #define PWINE "pwine" #define RUM "rum" #define VODKA "vodka" @@ -254,7 +254,6 @@ #define NEUROTOXIN "neurotoxin" #define BANANAHONK "bananahonk" #define SILENCER "silencer" -#define CHANGELINGSTING "changelingsting" #define ERIKASURPRISE "erikasurprise" #define IRISHCARBOMB "irishcarbomb" #define SYNDICATEBOMB "syndicatebomb" @@ -328,6 +327,15 @@ #define HEMOSCYANINE "hemoscyanine" #define ANTHRACENE "anthracene" #define PINTPOINTER "pintpointer" +#define MUCUS "mucus" +#define ALBUTEROL "albuterol" +#define LIQUIDBUTTER "liquidbutter" +#define SALTWATER "saltwater" +#define CALCIUMOXIDE "calciumoxide" +#define CALCIUMHYDROXIDE "calciumhydroxide" +#define MUSTARD "mustard" +#define RELISH "relish" +#define UNTABLE_MUTAGEN "untable" #define TUNGSTEN "tungsten" #define LITHIUMSODIUMTUNGSTATE "lithiumsodiumtungstate" @@ -355,9 +363,12 @@ #define CORIAMYRTIN "coriamyrtin" #define THYMOL "thymol" #define POTASSIUMCARBONATE "potassium_carbonate" - +#define TOBACCO "tobacco" +#define DANBACCO "danbacco" #define PETRITRICIN "petritricin" #define APETRINE "apetrine" +#define SODIUMSILICATE "sodiumsilicate" +#define COLORFUL_REAGENT "colorful_reagent" // How many units of reagent are consumed per tick, by default. #define REAGENTS_METABOLISM 0.2 diff --git a/__DEFINES/setup.dm b/__DEFINES/setup.dm index 4fc70dd42ed..eec173614e3 100644 --- a/__DEFINES/setup.dm +++ b/__DEFINES/setup.dm @@ -1,6 +1,6 @@ //This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 -#if DM_VERSION < 511 -#error Your version of byond is too old, you need version 511 or higher +#if DM_VERSION < 512 +#error Your version of byond is too old, you need version 512 or higher #endif #define RUNWARNING // disable if they re-enable run() in 507 or newer. // They did, tested in 508.1296 - N3X @@ -13,7 +13,7 @@ #define PROFILE_MACHINES // Disable when not debugging. #define ARBITRARILY_LARGE_NUMBER 10000 //Used in delays.dm and vehicle.dm. Upper limit on delays -#define ARBITRARILY_PLANCK_NUMBER 1.417*(10**32) //1.41710^32. Because ARBITRARILY_LARGE_NUMBER is too small and INF is too large +#define ARBITRARILY_PLANCK_NUMBER 1.417*(10**32) //1.417×10^32. Because ARBITRARILY_LARGE_NUMBER is too small and INF is too large #define MAX_VALUE 65535 #ifdef PROFILE_MACHINES @@ -375,6 +375,8 @@ var/global/list/BODY_COVER_VALUE_LIST=list("[HEAD]" = COVER_PROTECTION_HEAD,"[EY #define DISABILITY_FLAG_BLIND 16 #define DISABILITY_FLAG_MUTE 32 #define DISABILITY_FLAG_VEGAN 64 +#define DISABILITY_FLAG_ASTHMA 128 +#define DISABILITY_FLAG_LACTOSE 256 /////////////////////////////////////// // MUTATIONS @@ -447,6 +449,8 @@ var/global/list/BODY_COVER_VALUE_LIST=list("[HEAD]" = COVER_PROTECTION_HEAD,"[EY #define M_FARSIGHT 212 // Increases mob's view range by 2 #define M_NOIR 213 // aww yis detective noir #define M_VEGAN 214 +#define M_ASTHMA 215 +#define M_LACTOSE 216 var/global/list/NOIRMATRIX = list(0.33,0.33,0.33,0,\ 0.33,0.33,0.33,0,\ @@ -464,6 +468,8 @@ var/global/list/bad_changing_colour_ckeys = list() #define COUGHING 4 #define TOURETTES 8 #define NERVOUS 16 +#define ASTHMA 32 +#define LACTOSE 64 //sdisabilities #define BLIND 1 @@ -546,6 +552,9 @@ var/list/global_mutations = list() // list of hidden mutation things #define EYE_BLUR "eye_blur" #define DROWSY "drowsy" +#define CUT "cut" +#define BRUISE "bruise" +#define SLUR "slur" //intent flags yay #define I_HELP "help" @@ -687,6 +696,7 @@ SEE_PIXELS 256 #define BEE_OUT_FOR_ENEMIES 2 #define BEE_HEADING_HOME 3 #define BEE_SWARM 4 +#define BEE_BUILDING 5 #define LOC_KITCHEN 0 #define LOC_ATMOS 1 @@ -707,29 +717,10 @@ SEE_PIXELS 256 #define VERM_ROACHES 7 #define VERM_GREMLINS 8 #define VERM_BEES 9 +#define VERM_HORNETS 10 #define ROUNDSTART_LOGOUT_REPORT_TIME 6000 //Amount of time (in deciseconds) after the rounds starts, that the player disconnect report is issued. -//Damage things - -#define CUT "cut" -#define BRUISE "bruise" -#define BRUTE "brute" -#define BURN "fire" -#define TOX "tox" -#define OXY "oxy" -#define CLONE "clone" -#define HALLOSS "halloss" - -#define STUN "stun" -#define WEAKEN "weaken" -#define PARALYZE "paralize" -#define IRRADIATE "irradiate" -#define STUTTER "stutter" -#define SLUR "slur" -#define EYE_BLUR "eye_blur" -#define DROWSY "drowsy" - // Special 'weapons', used in damage procs #define WPN_HIGH_BODY_TEMP "High Body Temperature" #define WPN_LOW_BODY_TEMP "Low Body Temperature" @@ -764,6 +755,7 @@ SEE_PIXELS 256 #define MAT_CLOWN "$clown" #define MAT_PLASTIC "$plastic" #define MAT_CARDBOARD "$cardboard" +#define MAT_WOOD "$wood" //Admin Permissions //Please don't edit these values without speaking to [current /vg/ host here] first @@ -921,6 +913,8 @@ var/list/RESTRICTED_CAMERA_NETWORKS = list( //Those networks can only be accesse #define PLASMA_IMMUNE 512 #define RAD_GLOW 1024 #define ELECTRIC_HEAL 2048 +#define IS_SPECIES_MUTE 4096 +#define REQUIRE_DARK 8192 //Species anatomical flags. #define HAS_SKIN_TONE 1 @@ -959,6 +953,7 @@ var/default_colour_matrix = list(1,0,0,0,\ //Language flags. #define WHITELISTED 1 // Language is available if the speaker is whitelisted. #define RESTRICTED 2 // Language can only be accquired by spawning or an admin. +#define CAN_BE_SECONDARY_LANGUAGE 4 // Language is available on character setup as secondary language. // Hairstyle flags #define HAIRSTYLE_CANTRIP 1 // 5% chance of tripping your stupid ass if you're running. @@ -992,6 +987,8 @@ var/default_colour_matrix = list(1,0,0,0,\ #define VAMP_CHARISMA 16 #define VAMP_UNDYING 17 +#define STARTING_BLOOD 10 + // Moved from machine_interactions.dm #define STATION_Z 1 #define CENTCOMM_Z 2 @@ -1195,61 +1192,6 @@ var/default_colour_matrix = list(1,0,0,0,\ #define PDA_APP_SNAKEII_MAXSPEED 9 #define PDA_APP_SNAKEII_MAXLABYRINTH 8 - -//////////////////////// -////WIZARD SHIT GO////// -//////////////////////// - -/* WIZARD SPELL FLAGS */ -#define GHOSTCAST 1 //can a ghost cast it? -#define NEEDSCLOTHES 2 //does it need the wizard garb to cast? Nonwizard spells should not have this -#define NEEDSHUMAN 4 //does it require the caster to be human? -#define Z2NOCAST 8 //if this is added, the spell can't be cast at centcomm -#define STATALLOWED 16 //if set, the user doesn't have to be conscious to cast. Required for ghost spells -#define IGNOREPREV 32 //if set, each new target does not overlap with the previous one -//The following flags only affect different types of spell, and therefore overlap -//Targeted spells -#define INCLUDEUSER 64 //does the spell include the caster in its target selection? -#define SELECTABLE 128 //can you select each target for the spell? -//AOE spells -#define IGNOREDENSE 64 //are dense turfs ignored in selection? -#define IGNORESPACE 128 //are space turfs ignored in selection? -#define NODUPLICATE 256 //can we put the same summon type on the same tile? -//End split flags -#define CONSTRUCT_CHECK 512 //used by construct spells - checks for nullrods -#define NO_BUTTON 1024 //spell won't show up in the HUD with this -#define WAIT_FOR_CLICK 2048//spells wait for you to click on a target to cast -#define TALKED_BEFORE 4096//spells require you to have heard the person you are casting it upon - -//invocation -#define SpI_SHOUT "shout" -#define SpI_WHISPER "whisper" -#define SpI_EMOTE "emote" -#define SpI_NONE "none" - -//upgrading -#define Sp_SPEED "cooldown" -#define Sp_POWER "power" -#define Sp_MOVE "mobility" -#define Sp_AMOUNT "amount" - -#define Sp_TOTAL "total" - -//casting costs -#define Sp_RECHARGE 1 -#define Sp_CHARGES 2 -#define Sp_HOLDVAR 4 -#define Sp_GRADUAL 8 - -//spell range -#define SELFCAST -1 -#define GLOBALCAST -2 - -//buying costs -#define Sp_BASE_PRICE 20 - -///////WIZ END///////// - //Some alien checks for reagents for alien races. #define IS_DIONA 1 #define IS_VOX 2 @@ -1311,7 +1253,7 @@ var/proccalls = 1 #else #define writepanic(a) null << a -#endif*/ +#endif //Default frequencies of signal based RC stuff, because comic and his magic numbers. #define FREQ_DISPOSAL 1367 @@ -1360,7 +1302,7 @@ var/proccalls = 1 #define FOOD_SWEET 4 #define FOOD_LIQUID 8 #define FOOD_SKELETON_FRIENDLY 16 //Can be eaten by skeletons - +#define FOOD_LACTOSE 32 //Contains MILK /* * * @@ -1420,6 +1362,7 @@ var/proccalls = 1 #define MODE_CHANGELING "changeling" #define MODE_CULTCHAT "cultchat" #define MODE_ANCIENT "ancientchat" +#define MODE_MUSHROOM "sporechat" //Hardcore mode stuff @@ -1561,6 +1504,8 @@ var/proccalls = 1 #define BEESPECIES_NORMAL "bees" #define BEESPECIES_VOX "chill bugs" +#define BEESPECIES_HORNET "hornets" +#define BEESPECIES_BLOOD "hell bugs" //mob/proc/is_pacified() #define VIOLENCE_SILENT 0 @@ -1572,8 +1517,13 @@ var/proccalls = 1 #define HUD_MEDICAL 1 #define HUD_SECURITY 2 -#define INERTIA_MOVEDELAY 5 +//Cyborg components +#define COMPONENT_BROKEN -1 +#define COMPONENT_MISSING 0 +#define COMPONENT_INSTALLED 1 +//Glidesize +#define INERTIA_MOVEDELAY 5 #define FRACTIONAL_GLIDESIZES 1 #ifdef FRACTIONAL_GLIDESIZES #define DELAY2GLIDESIZE(delay) (WORLD_ICON_SIZE / max(Ceiling(delay / world.tick_lag), 1)) diff --git a/__DEFINES/silicon.dm b/__DEFINES/silicon.dm new file mode 100644 index 00000000000..490bd82b10d --- /dev/null +++ b/__DEFINES/silicon.dm @@ -0,0 +1,66 @@ +//Global list of all Cyborg/MoMMI modules. +var/global/list/robot_modules = list( + "Standard" = /obj/item/weapon/robot_module/standard, + "Service" = /obj/item/weapon/robot_module/butler, + "Supply" = /obj/item/weapon/robot_module/miner, + "Medical" = /obj/item/weapon/robot_module/medical, + "Security" = /obj/item/weapon/robot_module/security, + "Engineering" = /obj/item/weapon/robot_module/engineering, + "Janitor" = /obj/item/weapon/robot_module/janitor, + "Combat" = /obj/item/weapon/robot_module/combat, + "Syndicate" = /obj/item/weapon/robot_module/syndicate, + "TG17355" = /obj/item/weapon/robot_module/tg17355 + ) + +var/global/list/mommi_modules = list( + "Nanotrasen" = /obj/item/weapon/robot_module/mommi/nt, + "Soviet" = /obj/item/weapon/robot_module/mommi/soviet, + "Gravekeeper" = /obj/item/weapon/robot_module/mommi/cogspider + ) + +// Cyborgs & MoMMI defines +#define CYBORG_STARTING_TONER 40 +#define CYBORG_MAX_TONER 100 +#define CYBORG_PHOTO_COST 20 + +//Respawnable defines +#define MEDICAL_MAX_KIT 10 +#define STANDARD_MAX_KIT 15 +#define SUPPLY_MAX_WRAP 24 +#define ENGINEERING_MAX_COIL 50 +#define MOMMI_MAX_COIL 50 + +//Speed-related defines +#define SILICON_NO_CHARGE_SLOWDOWN 1.4 +#define SILICON_NO_CELL_SLOWDOWN 15 + +#define CYBORG_ENGINEERING_SPEED_MODIFIER 1 +#define CYBORG_MEDICAL_SPEED_MODIFIER 1 +#define CYBORG_SYNDICATE_SPEED_MODIFIER 1 +#define CYBORG_SUPPLY_SPEED_MODIFIER 1 +#define CYBORG_JANITOR_SPEED_MODIFIER 1 +#define CYBORG_COMBAT_SPEED_MODIFIER 1 +#define CYBORG_STANDARD_SPEED_MODIFIER 1 +#define CYBORG_SERVICE_SPEED_MODIFIER 1 +#define CYBORG_SECURITY_SPEED_MODIFIER 1 +#define CYBORG_TG17355_SPEED_MODIFIER 1 + +#define MOMMI_SOVIET_SPEED_MODIFIER 1 +#define MOMMI_NT_SPEED_MODIFIER 1 +#define COGSPIDER_SPEED_MODIFIER 2 + +#define SILICON_MOBILITY_MODULE_SPEED_MODIFIER 0.75 //Silicon's speed var is multiplied by the mobility module modifier +#define SILICON_VTEC_SPEED_BONUS 0.25 //But the VTEC Bonus is ADDED to their movement_speed_modifier + +//Bitflags for module quirks +#define MODULE_CAN_BE_PUSHED 1 +#define MODULE_CAN_HANDLE_MEDICAL 2 +#define MODULE_CAN_HANDLE_CHEMS 4 +#define MODULE_CAN_HANDLE_FOOD 8 +#define MODULE_CAN_BUY 16 +#define MODULE_CLEAN_ON_MOVE 32 +#define MODULE_HAS_MAGPULSE 64 +#define MODULE_IS_THE_LAW 128 +#define MODULE_CAN_LIFT_SECTAPE 256 +#define MODULE_CAN_LIFT_ENGITAPE 512 +#define MODULE_IS_A_CLOWN 1024 diff --git a/__DEFINES/spell_defines.dm b/__DEFINES/spell_defines.dm index f3c7407502e..2173f1af5c4 100644 --- a/__DEFINES/spell_defines.dm +++ b/__DEFINES/spell_defines.dm @@ -61,9 +61,10 @@ #define USER_TYPE_ARTIFACT "artifact" #define USER_TYPE_VAMPIRE "vampire" + //Spell aspect flags #define SPELL_FIRE 1 //Fire based spells #define SPELL_WATER 2 //Water/liquid based spells #define SPELL_AIR 4 //Air based spells #define SPELL_GROUND 8 //Earthen based spells -#define SPELL_NECROTIC 16 //Necromantic spells \ No newline at end of file +#define SPELL_NECROTIC 16 //Necromantic spells diff --git a/__DEFINES/stylesheet.dm b/__DEFINES/stylesheet.dm index cb87a1ed9cc..e3506f3d017 100644 --- a/__DEFINES/stylesheet.dm +++ b/__DEFINES/stylesheet.dm @@ -89,6 +89,7 @@ h1.alert, h2.alert {color: #000000;} .good {color: green;} .average {color: #FF8000;} .bad {color: #FF0000;} +.mushroom {color: #4B0082;} /* /vg/ Saycode Rewrite */ .italics, .talkinto {font-style:italic;} .whisper {font-style:italic;color:#333333;} diff --git a/__DEFINES/subsystem.dm b/__DEFINES/subsystem.dm index 3bcb71d1f56..6fbf2e8b87c 100644 --- a/__DEFINES/subsystem.dm +++ b/__DEFINES/subsystem.dm @@ -7,7 +7,7 @@ #define SS_INIT_SUN 24 #define SS_INIT_GARBAGE 23 #define SS_INIT_JOB 22 -#define SS_INIT_GENETICS 21 +#define SS_INIT_HUMANS 21 #define SS_INIT_MAP 20 #define SS_INIT_POWER 19 #define SS_INIT_OBJECT 18 @@ -28,6 +28,7 @@ #define SS_PRIORITY_MOB 150 #define SS_PRIORITY_NANOUI 120 #define SS_PRIORITY_VOTE 110 +#define SS_PRIORITY_FAST_OBJECTS 105 #define SS_PRIORITY_OBJECTS 100 #define SS_PRIORITY_POWER 95 #define SS_PRIORITY_MACHINERY 90 @@ -43,11 +44,13 @@ #define SS_PRIORITY_INACTIVITY 1 #define SS_WAIT_FAST_MACHINERY 0.7 SECONDS //TODO move the rest of these to defines +#define SS_WAIT_FAST_OBJECTS 0.5 SECONDS #define SS_DISPLAY_GARBAGE -100 #define SS_DISPLAY_AIR -90 #define SS_DISPLAY_LIGHTING -80 #define SS_DISPLAY_MOB -70 +#define SS_DISPLAY_FAST_OBJECTS -65 #define SS_DISPLAY_OBJECTS -60 #define SS_DISPLAY_MACHINERY -50 #define SS_DISPLAY_PIPENET -40 diff --git a/__DEFINES/ticker.dm b/__DEFINES/ticker.dm new file mode 100644 index 00000000000..764ffd90f51 --- /dev/null +++ b/__DEFINES/ticker.dm @@ -0,0 +1,4 @@ +#define GAME_STATE_PREGAME 1 +#define GAME_STATE_SETTING_UP 2 +#define GAME_STATE_PLAYING 3 +#define GAME_STATE_FINISHED 4 diff --git a/code/__DEFINES/turfs.dm b/__DEFINES/turfs.dm similarity index 100% rename from code/__DEFINES/turfs.dm rename to __DEFINES/turfs.dm diff --git a/__DEFINES/weapons.dm b/__DEFINES/weapons.dm new file mode 100644 index 00000000000..d2bc94114b7 --- /dev/null +++ b/__DEFINES/weapons.dm @@ -0,0 +1,22 @@ +/* Projectile calibers */ + +#define MM9 "9mm" +#define MM12 "12mm" + +#define POINT357 "357" +#define POINT38 ".38" +#define POINT380 ".380AUTO" +#define POINT45 ".45" +#define POINT50 ".50" +#define POINT75 ".75" +#define POINT762 "a762" +#define POINT762X55 "7.62x55" +#define BROWNING50 ".50BMG" + +#define ROCKETGRENADE "rpg" +#define GUIDEDROCKET "guided rocket" + + +#define PULSE "pulse" +#define GAUGE12 "12 gauge" +#define GAUGEFLARE "flare" diff --git a/code/ATMOSPHERICS/atmospherics.dm b/code/ATMOSPHERICS/atmospherics.dm index 44d7b118892..0355525c1f2 100644 --- a/code/ATMOSPHERICS/atmospherics.dm +++ b/code/ATMOSPHERICS/atmospherics.dm @@ -45,11 +45,13 @@ Pipelines + Other Objects -> Pipe network var/piping_layer = PIPING_LAYER_DEFAULT //used in multi-pipe-on-tile - pipes only connect if they're on the same pipe layer internal_gravity = 1 // Ventcrawlers can move in pipes without gravity since they have traction. - holomap = TRUE // If a pipe node isn't connected, should it be pixel shifted to fit the object? var/ex_node_offset = 0 +/obj/machinery/atmospherics/supports_holomap() + return TRUE + /obj/machinery/atmospherics/New() ..() machines.Remove(src) @@ -237,7 +239,7 @@ Pipelines + Other Objects -> Pipe network continue var/node_var="node[node_id]" if(!(node_var in vars)) - testing("[node_var] not in vars.") + //testing("[node_var] not in vars.") return if(!vars[node_var]) vars[node_var] = found @@ -313,16 +315,16 @@ Pipelines + Other Objects -> Pipe network to_chat(user, "You begin to open the pressure release valve on the pipe...") if(!do_after(user, src, 50) || !loc) return - playsound(get_turf(src), 'sound/machines/hiss.ogg', 50, 1) + playsound(src, 'sound/machines/hiss.ogg', 50, 1) user.visible_message("[user] vents \the [src].", "You have vented \the [src].", "You hear a ratchet.") - var/datum/gas_mixture/internal_removed = int_air.remove(int_air.total_moles()*starting_volume/int_air.volume) + var/datum/gas_mixture/internal_removed = int_air.remove_volume(starting_volume) env_air.merge(internal_removed) else to_chat(user, "You cannot unwrench this [src], it's too exerted due to internal pressure.") return 1 - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + playsound(src, 'sound/items/Ratchet.ogg', 50, 1) to_chat(user, "You begin to unfasten \the [src]...") if (do_after(user, src, 40)) user.visible_message( \ @@ -349,12 +351,16 @@ Pipelines + Other Objects -> Pipe network var/obj/machinery/atmospherics/target_move = findConnecting(direction, user.ventcrawl_layer) if(target_move) if(is_type_in_list(target_move, ventcrawl_machinery) && target_move.can_crawl_through()) + if(user.special_delayer.blocked()) + return + user.delayNextSpecial(10) user.visible_message("Something is squeezing through the ducts...", "You start crawling out the ventilation system.") target_move.shake(2, 3) - if(do_after(user, target_move, 10)) - user.remove_ventcrawl() - user.forceMove(target_move.loc) //handles entering and so on - user.visible_message("You hear something squeeze through the ducts.", "You climb out the ventilation system.") + spawn(0) + if(do_after(user, target_move, 10)) + user.remove_ventcrawl() + user.forceMove(target_move.loc) //handles entering and so on + user.visible_message("You hear something squeeze through the ducts.", "You climb out the ventilation system.") else if(target_move.can_crawl_through()) if(target_move.return_network(target_move) != return_network(src)) user.remove_ventcrawl() diff --git a/code/ATMOSPHERICS/components/binary_devices/MSGS.dm b/code/ATMOSPHERICS/components/binary_devices/MSGS.dm index 0a7cdca483c..c810df98afd 100644 --- a/code/ATMOSPHERICS/components/binary_devices/MSGS.dm +++ b/code/ATMOSPHERICS/components/binary_devices/MSGS.dm @@ -23,6 +23,9 @@ var/tmp/update_flags var/tmp/last_pressure +/obj/machinery/atmospherics/binary/msgs/unanchored + anchored = 0 + /obj/machinery/atmospherics/binary/msgs/New() html_machines += src @@ -246,7 +249,7 @@ if(on) overlays += image(icon = icon, icon_state = "i") -/obj/machinery/atmospherics/binary/msgs/wrenchAnchor(var/mob/user) +/obj/machinery/atmospherics/binary/msgs/wrenchAnchor(var/mob/user) . = ..() if(!.) return diff --git a/code/ATMOSPHERICS/components/binary_devices/binary_atmos_base.dm b/code/ATMOSPHERICS/components/binary_devices/binary_atmos_base.dm index c5497b030ab..33202227405 100644 --- a/code/ATMOSPHERICS/components/binary_devices/binary_atmos_base.dm +++ b/code/ATMOSPHERICS/components/binary_devices/binary_atmos_base.dm @@ -121,9 +121,7 @@ node2 = findConnecting(dir) update_icon() - var/turf/T = loc - if (istype(T)) - T.soft_add_holomap(src) + add_self_to_holomap() /obj/machinery/atmospherics/binary/build_network() if(!network1 && node1) diff --git a/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm b/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm index a47887b0bdc..379d962503a 100644 --- a/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm +++ b/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm @@ -86,7 +86,7 @@ if(pressure_delta > 0) if(air1.temperature > 0) - var/transfer_moles = pressure_delta*environment.volume/(air1.temperature * R_IDEAL_GAS_EQUATION) + var/transfer_moles = pressure_delta * CELL_VOLUME / (air1.temperature * R_IDEAL_GAS_EQUATION) var/datum/gas_mixture/removed = air1.remove(transfer_moles) @@ -105,7 +105,7 @@ if(pressure_delta > 0) if(environment.temperature > 0) - var/transfer_moles = pressure_delta*air2.volume/(environment.temperature * R_IDEAL_GAS_EQUATION) + var/transfer_moles = pressure_delta * air2.volume / (environment.temperature * R_IDEAL_GAS_EQUATION) var/datum/gas_mixture/removed = loc.remove_air(transfer_moles) @@ -157,51 +157,39 @@ if(!signal.data["tag"] || (signal.data["tag"] != id_tag) || (signal.data["sigtype"]!="command")) return 0 - var/handled=0 if("power" in signal.data) on = text2num(signal.data["power"]) - handled=1 if("power_toggle" in signal.data) on = !on - handled=1 if("direction" in signal.data) pump_direction = text2num(signal.data["direction"]) - handled=1 if("checks" in signal.data) pressure_checks = text2num(signal.data["checks"]) - handled=1 if("purge" in signal.data) pressure_checks &= ~1 pump_direction = 0 - handled=1 if("stabilize" in signal.data) pressure_checks |= 1 pump_direction = 1 - handled=1 if("set_input_pressure" in signal.data) input_pressure_min = Clamp(text2num(signal.data["set_input_pressure"]), 0, ONE_ATMOSPHERE * 50) - handled = 1 if("set_output_pressure" in signal.data) output_pressure_max = Clamp(text2num(signal.data["set_output_pressure"]), 0, ONE_ATMOSPHERE * 50) - handled = 1 if("set_external_pressure" in signal.data) external_pressure_bound = Clamp(text2num(signal.data["set_external_pressure"]), 0, ONE_ATMOSPHERE * 50) - handled = 1 if("status" in signal.data) spawn(2) broadcast_status() return //do not update_icon - if(!handled) - testing("\[[world.timeofday]\]: dp_vent_pump/receive_signal: unknown command \n[signal.debug_print()]") spawn(2) broadcast_status() update_icon() @@ -221,4 +209,4 @@ return 1 /obj/machinery/atmospherics/binary/dp_vent_pump/toggle_status(var/mob/user) - return FALSE \ No newline at end of file + return FALSE diff --git a/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm b/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm index 6e0d293d2a9..0b405ed9b8d 100644 --- a/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm +++ b/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm @@ -41,7 +41,7 @@ var/pressure_delta = min(target_pressure - output_starting_pressure, (input_starting_pressure - output_starting_pressure)/2) //Can not have a pressure delta that would cause output_pressure > input_pressure - var/transfer_moles = pressure_delta*air2.volume/(air1.temperature * R_IDEAL_GAS_EQUATION) + var/transfer_moles = pressure_delta * air2.volume / (air1.temperature * R_IDEAL_GAS_EQUATION) //Actually transfer the gas var/datum/gas_mixture/removed = air1.remove(transfer_moles) diff --git a/code/ATMOSPHERICS/components/binary_devices/pump.dm b/code/ATMOSPHERICS/components/binary_devices/pump.dm index dc01b1b874d..74cb3ec6996 100644 --- a/code/ATMOSPHERICS/components/binary_devices/pump.dm +++ b/code/ATMOSPHERICS/components/binary_devices/pump.dm @@ -59,7 +59,7 @@ Thus, the two variables affect pump operation are set in New(): //Calculate necessary moles to transfer using PV=nRT if((air1.total_moles() > 0) && (air1.temperature>0)) var/pressure_delta = target_pressure - output_starting_pressure - var/transfer_moles = pressure_delta*air2.volume/(air1.temperature * R_IDEAL_GAS_EQUATION) + var/transfer_moles = pressure_delta * air2.volume / (air1.temperature * R_IDEAL_GAS_EQUATION) //Actually transfer the gas var/datum/gas_mixture/removed = air1.remove(transfer_moles) @@ -182,7 +182,7 @@ Thus, the two variables affect pump operation are set in New(): id_tag = newid initialize() return MT_UPDATE - + if("set_freq" in href_list) var/newfreq=frequency if(href_list["set_freq"]!="-1") diff --git a/code/ATMOSPHERICS/components/trinary_devices/filter.dm b/code/ATMOSPHERICS/components/trinary_devices/filter.dm index 4a8e9081741..dab6101b151 100755 --- a/code/ATMOSPHERICS/components/trinary_devices/filter.dm +++ b/code/ATMOSPHERICS/components/trinary_devices/filter.dm @@ -71,7 +71,7 @@ obj/machinery/atmospherics/trinary/filter/process() var/transfer_moles if(air1.temperature > 0) - transfer_moles = pressure_delta*air3.volume/(air1.temperature * R_IDEAL_GAS_EQUATION) + transfer_moles = pressure_delta * air3.volume / (air1.temperature * R_IDEAL_GAS_EQUATION) //Actually transfer the gas diff --git a/code/ATMOSPHERICS/components/trinary_devices/mixer.dm b/code/ATMOSPHERICS/components/trinary_devices/mixer.dm index e68398d2d70..5e4e1aef046 100644 --- a/code/ATMOSPHERICS/components/trinary_devices/mixer.dm +++ b/code/ATMOSPHERICS/components/trinary_devices/mixer.dm @@ -56,10 +56,10 @@ obj/machinery/atmospherics/trinary/mixer/process() var/transfer_moles2 = 0 if(air1.temperature > 0) - transfer_moles1 = (node1_concentration*pressure_delta)*air3.volume/(air1.temperature * R_IDEAL_GAS_EQUATION) + transfer_moles1 = (node1_concentration * pressure_delta) * air3.volume / (air1.temperature * R_IDEAL_GAS_EQUATION) if(air2.temperature > 0) - transfer_moles2 = (node2_concentration*pressure_delta)*air3.volume/(air2.temperature * R_IDEAL_GAS_EQUATION) + transfer_moles2 = (node2_concentration * pressure_delta) * air3.volume / (air2.temperature * R_IDEAL_GAS_EQUATION) var/air1_moles = air1.total_moles() var/air2_moles = air2.total_moles() @@ -105,14 +105,14 @@ obj/machinery/atmospherics/trinary/mixer/attack_hand(user as mob) Desirable output pressure: [target_pressure]kPa | Change
- Node 1 Concentration: + Node 1 ([dir2text(pipe_flags & IS_MIRROR ? dir : turn(dir, -180))]) Concentration: - - [node1_concentration]([node1_concentration*100]%) + +
- Node 2 Concentration: + Node 2 ([dir2text(turn(dir, -90))]) Concentration: - - [node2_concentration]([node2_concentration*100]%) @@ -120,7 +120,7 @@ obj/machinery/atmospherics/trinary/mixer/attack_hand(user as mob) + "} - user << browse("[src.name] control[dat]", "window=atmo_mixer") + user << browse("[src.name] control[dat]", "window=atmo_mixer;size=450x110") onclose(user, "atmo_mixer") return diff --git a/code/ATMOSPHERICS/components/trinary_devices/trinary_base.dm b/code/ATMOSPHERICS/components/trinary_devices/trinary_base.dm index b4938dcb32b..d52d95632f6 100644 --- a/code/ATMOSPHERICS/components/trinary_devices/trinary_base.dm +++ b/code/ATMOSPHERICS/components/trinary_devices/trinary_base.dm @@ -135,9 +135,7 @@ obj/machinery/atmospherics/trinary/initialize() update_icon() - var/turf/T = loc - if (istype(T)) - T.soft_add_holomap(src) + add_self_to_holomap() obj/machinery/atmospherics/trinary/build_network() if(!network1 && node1) diff --git a/code/ATMOSPHERICS/components/unary/outlet_injector.dm b/code/ATMOSPHERICS/components/unary/outlet_injector.dm index 15507b93883..ac56a830c6d 100644 --- a/code/ATMOSPHERICS/components/unary/outlet_injector.dm +++ b/code/ATMOSPHERICS/components/unary/outlet_injector.dm @@ -54,7 +54,7 @@ return if(air_contents.temperature > 0) - var/transfer_moles = (air_contents.return_pressure())*volume_rate/(air_contents.temperature * R_IDEAL_GAS_EQUATION) + var/transfer_moles = (air_contents.return_pressure()) * volume_rate / (air_contents.temperature * R_IDEAL_GAS_EQUATION) var/datum/gas_mixture/removed = air_contents.remove(transfer_moles) @@ -72,7 +72,7 @@ injecting = 1 if(air_contents.temperature > 0) - var/transfer_moles = (air_contents.return_pressure())*volume_rate/(air_contents.temperature * R_IDEAL_GAS_EQUATION) + var/transfer_moles = (air_contents.return_pressure()) * volume_rate / (air_contents.temperature * R_IDEAL_GAS_EQUATION) var/datum/gas_mixture/removed = air_contents.remove(transfer_moles) diff --git a/code/ATMOSPHERICS/components/unary/thermal_plate.dm b/code/ATMOSPHERICS/components/unary/thermal_plate.dm index e71b4899536..03d115a32ff 100644 --- a/code/ATMOSPHERICS/components/unary/thermal_plate.dm +++ b/code/ATMOSPHERICS/components/unary/thermal_plate.dm @@ -19,12 +19,7 @@ //Get processable air sample and thermal info from environment - var/environment_moles = environment.total_moles() - var/transfer_moles = 0.25 * environment_moles - var/datum/gas_mixture/external_removed = environment.remove(transfer_moles) - - if(!external_removed) - return radiate() + var/environment_moles = environment.molar_density() * CELL_VOLUME if(environment_moles < NO_GAS) return radiate() @@ -33,15 +28,15 @@ //Get same info from connected gas - var/internal_transfer_moles = 0.25 * air_contents.total_moles() - var/datum/gas_mixture/internal_removed = air_contents.remove(internal_transfer_moles) + var/datum/gas_mixture/internal_removed = air_contents.remove_ratio(0.25) if (!internal_removed) - environment.merge(external_removed) return + var/datum/gas_mixture/external_removed = environment.remove(0.25 * environment_moles) + var/combined_heat_capacity = internal_removed.heat_capacity() + external_removed.heat_capacity() - var/combined_energy = internal_removed.temperature * internal_removed.heat_capacity() + external_removed.heat_capacity() * external_removed.temperature + var/combined_energy = internal_removed.thermal_energy() + external_removed.thermal_energy() if(!combined_heat_capacity) combined_heat_capacity = 1 @@ -70,14 +65,13 @@ air_contents.copy_from(network.radiate) //We can cut down on processing time by only calculating radiate() once and then applying the result return - var/internal_transfer_moles = 0.25 * air_contents.total_moles() - var/datum/gas_mixture/internal_removed = air_contents.remove(internal_transfer_moles) + var/datum/gas_mixture/internal_removed = air_contents.remove_ratio(0.25) if (!internal_removed) return var/combined_heat_capacity = internal_removed.heat_capacity() + RADIATION_CAPACITY - var/combined_energy = internal_removed.temperature * internal_removed.heat_capacity() + (RADIATION_CAPACITY * 6.4) + var/combined_energy = internal_removed.thermal_energy() + (RADIATION_CAPACITY * 6.4) var/final_temperature = combined_energy / combined_heat_capacity diff --git a/code/ATMOSPHERICS/components/unary/unary_base.dm b/code/ATMOSPHERICS/components/unary/unary_base.dm index 0fde36ec510..9ce42830f5f 100644 --- a/code/ATMOSPHERICS/components/unary/unary_base.dm +++ b/code/ATMOSPHERICS/components/unary/unary_base.dm @@ -70,10 +70,7 @@ node = target break update_icon() - - var/turf/T = loc - if (istype(T)) - T.soft_add_holomap(src) + add_self_to_holomap() /obj/machinery/atmospherics/unary/build_network() if(!network && node) diff --git a/code/ATMOSPHERICS/components/unary/vent_pump.dm b/code/ATMOSPHERICS/components/unary/vent_pump.dm index f3551a75c89..49c94991764 100644 --- a/code/ATMOSPHERICS/components/unary/vent_pump.dm +++ b/code/ATMOSPHERICS/components/unary/vent_pump.dm @@ -52,7 +52,8 @@ /obj/machinery/atmospherics/unary/vent_pump/New() ..() - area_uid = areaMaster.uid + var/area/here = get_area(src) + area_uid = here.uid if (!id_tag) assign_uid() id_tag = num2text(uid) @@ -120,7 +121,7 @@ if(pressure_delta > 0.1) if(air_contents.temperature > 0) - var/transfer_moles = pressure_delta*environment.volume/(air_contents.temperature * R_IDEAL_GAS_EQUATION) + var/transfer_moles = pressure_delta * CELL_VOLUME / (air_contents.temperature * R_IDEAL_GAS_EQUATION) var/datum/gas_mixture/removed = air_contents.remove(transfer_moles) @@ -138,7 +139,7 @@ if(pressure_delta > 0.1) if(environment.temperature > 0) - var/transfer_moles = pressure_delta*air_contents.volume/(environment.temperature * R_IDEAL_GAS_EQUATION) + var/transfer_moles = pressure_delta * air_contents.volume / (environment.temperature * R_IDEAL_GAS_EQUATION) var/datum/gas_mixture/removed = loc.remove_air(transfer_moles) if (isnull(removed)) //in space @@ -160,8 +161,9 @@ radio_connection = radio_controller.add_object(src, frequency,radio_filter_in) if(frequency != 1439) - areaMaster.air_vent_info -= id_tag - areaMaster.air_vent_names -= id_tag + var/area/this_area = get_area(src) + this_area.air_vent_info -= id_tag + this_area.air_vent_names -= id_tag name = "Vent Pump" else broadcast_status() @@ -193,11 +195,12 @@ ) if(frequency == 1439) - if(!areaMaster.air_vent_names[id_tag]) - var/new_name = "[areaMaster.name] Vent Pump #[areaMaster.air_vent_names.len+1]" - areaMaster.air_vent_names[id_tag] = new_name + var/area/this_area = get_area(src) + if(!this_area.air_vent_names[id_tag]) + var/new_name = "[this_area.name] Vent Pump #[this_area.air_vent_names.len+1]" + this_area.air_vent_names[id_tag] = new_name name = new_name - areaMaster.air_vent_info[id_tag] = signal.data + this_area.air_vent_info[id_tag] = signal.data radio_connection.post_signal(src, signal, radio_filter_out) @@ -220,52 +223,40 @@ if(!signal.data["tag"] || (signal.data["tag"] != id_tag) || (signal.data["sigtype"]!="command") || (signal.data["type"] && signal.data["type"] != "vent")) return 0 - var/handled=0 if("purge" in signal.data) pressure_checks &= ~1 pump_direction = 0 - handled=1 if("stabilize" in signal.data) pressure_checks |= 1 pump_direction = 1 - handled = 1 if("power" in signal.data) on = text2num(signal.data["power"]) - handled = 1 if("power_toggle" in signal.data) on = !on - handled = 1 if("checks" in signal.data) pressure_checks = text2num(signal.data["checks"]) - handled = 1 if("checks_toggle" in signal.data) pressure_checks = (pressure_checks?0:3) - handled = 1 if("direction" in signal.data) pump_direction = text2num(signal.data["direction"]) - handled = 1 if("set_internal_pressure" in signal.data) internal_pressure_bound = Clamp(text2num(signal.data["set_internal_pressure"]), 0, ONE_ATMOSPHERE * 50) - handled =1 if("set_external_pressure" in signal.data) external_pressure_bound = Clamp(text2num(signal.data["set_external_pressure"]), 0, ONE_ATMOSPHERE * 50) - handled = 1 if("adjust_internal_pressure" in signal.data) internal_pressure_bound = Clamp(internal_pressure_bound + text2num(signal.data["adjust_internal_pressure"]), 0, ONE_ATMOSPHERE * 50) - handled = 1 if("adjust_external_pressure" in signal.data) external_pressure_bound = Clamp(external_pressure_bound + text2num(signal.data["adjust_external_pressure"]), 0, ONE_ATMOSPHERE * 50) - handled = 1 if("init" in signal.data) name = signal.data["init"] @@ -276,8 +267,6 @@ broadcast_status() return //do not update_icon - if(!handled) - testing("\[[world.timeofday]\]: vent_pump/receive_signal: unknown command \n[signal.debug_print()]") spawn(2) broadcast_status() update_icon() @@ -320,7 +309,7 @@ if(do_after(user, src, 20)) if(!src || !WT.isOn()) return - playsound(get_turf(src), 'sound/items/Welder2.ogg', 50, 1) + playsound(src, 'sound/items/Welder2.ogg', 50, 1) if(!welded) user.visible_message("[user] welds the vent shut.", "You weld the vent shut.", "You hear welding.") investigation_log(I_ATMOS, "has been welded shut by [user.real_name] ([formatPlayerPanel(user, user.ckey)]) at [formatJumpTo(get_turf(src))]") @@ -344,8 +333,9 @@ return ..() /obj/machinery/atmospherics/unary/vent_pump/Destroy() - areaMaster.air_vent_info.Remove(id_tag) - areaMaster.air_vent_names.Remove(id_tag) + var/area/this_area = get_area(src) + this_area.air_vent_info.Remove(id_tag) + this_area.air_vent_names.Remove(id_tag) ..() /obj/machinery/atmospherics/unary/vent_pump/multitool_topic(var/mob/user, var/list/href_list, var/obj/O) @@ -354,8 +344,9 @@ if(!newid) return if(frequency == 1439) - areaMaster.air_vent_info -= id_tag - areaMaster.air_vent_names -= id_tag + var/area/this_area = get_area(src) + this_area.air_vent_info -= id_tag + this_area.air_vent_names -= id_tag id_tag = newid broadcast_status() @@ -365,10 +356,11 @@ return ..() /obj/machinery/atmospherics/unary/vent_pump/change_area(var/area/oldarea, var/area/newarea) - areaMaster.air_vent_info.Remove(id_tag) - areaMaster.air_vent_names.Remove(id_tag) + var/area/this_area = get_area(src) + this_area.air_vent_info.Remove(id_tag) + this_area.air_vent_names.Remove(id_tag) ..() - area_uid = areaMaster.uid + area_uid = this_area.uid broadcast_status() /obj/machinery/atmospherics/unary/vent_pump/canClone(var/obj/O) @@ -376,8 +368,9 @@ /obj/machinery/atmospherics/unary/vent_pump/clone(var/obj/machinery/atmospherics/unary/vent_pump/O) if(frequency == 1439) // Note: if the frequency stays at 1439 we'll be readded to the area in set_frequency(). - areaMaster.air_vent_info -= id_tag - areaMaster.air_vent_names -= id_tag + var/area/this_area = get_area(src) + this_area.air_vent_info -= id_tag + this_area.air_vent_names -= id_tag id_tag = O.id_tag set_frequency(O.frequency) diff --git a/code/ATMOSPHERICS/components/unary/vent_scrubber.dm b/code/ATMOSPHERICS/components/unary/vent_scrubber.dm index fd29114f058..f582616ae89 100644 --- a/code/ATMOSPHERICS/components/unary/vent_scrubber.dm +++ b/code/ATMOSPHERICS/components/unary/vent_scrubber.dm @@ -45,7 +45,8 @@ /obj/machinery/atmospherics/unary/vent_scrubber/New() ..() - area_uid = areaMaster.uid + var/area/this_area = get_area(src) + area_uid = this_area.uid if (!id_tag) assign_uid() id_tag = num2text(uid) @@ -81,8 +82,9 @@ radio_connection = radio_controller.add_object(src, frequency, radio_filter_in) if(frequency != 1439) - areaMaster.air_scrub_info -= id_tag - areaMaster.air_scrub_names -= id_tag + var/area/this_area = get_area(src) + this_area.air_scrub_info -= id_tag + this_area.air_scrub_names -= id_tag name = "Air Scrubber" else broadcast_status() @@ -115,11 +117,12 @@ "sigtype" = "status" ) if(frequency == 1439) - if(!areaMaster.air_scrub_names[id_tag]) - var/new_name = "[areaMaster.name] Air Scrubber #[areaMaster.air_scrub_names.len+1]" - areaMaster.air_scrub_names[id_tag] = new_name + var/area/this_area = get_area(src) + if(!this_area.air_scrub_names[id_tag]) + var/new_name = "[this_area.name] Air Scrubber #[this_area.air_scrub_names.len+1]" + this_area.air_scrub_names[id_tag] = new_name src.name = new_name - areaMaster.air_scrub_info[id_tag] = signal.data + this_area.air_scrub_info[id_tag] = signal.data radio_connection.post_signal(src, signal, radio_filter_out) @@ -159,7 +162,7 @@ (scrub_N2O && environment.trace_gases.len > 0) ||\ (scrub_O2 && environment.oxygen > 0) ||\ (scrub_N2 && environment.nitrogen > 0)) - var/transfer_moles = min(1, volume_rate/environment.volume)*environment.total_moles() + var/transfer_moles = min(1, volume_rate / environment.volume) * environment.total_moles() //Take a gas sample var/datum/gas_mixture/removed = loc.remove_air(transfer_moles) @@ -317,7 +320,7 @@ if(do_after(user, src, 20)) if(!src || !WT.isOn()) return - playsound(get_turf(src), 'sound/items/Welder2.ogg', 50, 1) + playsound(src, 'sound/items/Welder2.ogg', 50, 1) if(!welded) user.visible_message("[user] welds the scrubber shut.", "You weld the vent scrubber.", "You hear welding.") investigation_log(I_ATMOS, "has been welded shut by [user.real_name] ([formatPlayerPanel(user, user.ckey)]) at [formatJumpTo(get_turf(src))]") @@ -349,8 +352,9 @@ "} /obj/machinery/atmospherics/unary/vent_scrubber/Destroy() - areaMaster.air_scrub_info.Remove(id_tag) - areaMaster.air_scrub_names.Remove(id_tag) + var/area/this_area = get_area(src) + this_area.air_scrub_info.Remove(id_tag) + this_area.air_scrub_names.Remove(id_tag) ..() /obj/machinery/atmospherics/unary/vent_scrubber/multitool_topic(var/mob/user, var/list/href_list, var/obj/O) @@ -360,8 +364,9 @@ return if(frequency == 1439) - areaMaster.air_scrub_info -= id_tag - areaMaster.air_scrub_names -= id_tag + var/area/this_area = get_area(src) + this_area.air_scrub_info -= id_tag + this_area.air_scrub_names -= id_tag id_tag = newid broadcast_status() @@ -371,10 +376,10 @@ return ..() /obj/machinery/atmospherics/unary/vent_scrubber/change_area(var/area/oldarea, var/area/newarea) - areaMaster.air_scrub_info.Remove(id_tag) - areaMaster.air_scrub_names.Remove(id_tag) + oldarea.air_scrub_info.Remove(id_tag) + oldarea.air_scrub_names.Remove(id_tag) ..() - area_uid = areaMaster.uid + area_uid = newarea.uid broadcast_status() /obj/machinery/atmospherics/unary/vent_scrubber/canClone(var/obj/O) @@ -382,8 +387,9 @@ /obj/machinery/atmospherics/unary/vent_scrubber/clone(var/obj/machinery/atmospherics/unary/vent_scrubber/O) if(frequency == 1439) // Note: if the frequency stays at 1439 we'll be readded to the area in set_frequency(). - areaMaster.air_scrub_info -= id_tag - areaMaster.air_scrub_names -= id_tag + var/area/this_area = get_area(src) + this_area.air_scrub_info -= id_tag + this_area.air_scrub_names -= id_tag id_tag = O.id_tag set_frequency(O.frequency) diff --git a/code/ATMOSPHERICS/he_pipes.dm b/code/ATMOSPHERICS/he_pipes.dm index 606cbca154a..1bc4d56dcf6 100644 --- a/code/ATMOSPHERICS/he_pipes.dm +++ b/code/ATMOSPHERICS/he_pipes.dm @@ -66,41 +66,29 @@ if(!parent) . = ..() - // Get gas from pipenet - var/datum/gas_mixture/internal = return_air() - var/remove_ratio = volume/internal.volume - var/datum/gas_mixture/internal_removed = internal.remove_ratio(remove_ratio) - //Get processable air sample and thermal info from environment var/datum/gas_mixture/environment = loc.return_air() - var/environment_moles = environment.total_moles() - var/transfer_moles = 0.25 * environment_moles - var/datum/gas_mixture/external_removed = environment.remove(transfer_moles) + var/environment_moles = environment.molar_density() * CELL_VOLUME //Moles per turf - // No environmental gas? We radiate it, then. - if(!external_removed) - if(internal_removed) - internal.merge(internal_removed) - return radiate() - - // Not enough gas in the air around us to care about. Radiate. Less gas than airless tiles start with. + //Not enough gas in the air around us to care about. Radiate. Less gas than airless tiles start with. if(environment_moles < NO_GAS) - if(internal_removed) - internal.merge(internal_removed) - environment.merge(external_removed) return radiate() - // A tiny bit of air so this isn't really space, but its not worth activating exchange procs + //A tiny bit of air so this isn't really space, but it's not worth activating exchange procs else if(environment_moles < SOME_GAS) return 0 - // No internal gas. Screw this, we're out. - if(!internal_removed) - environment.merge(external_removed) + //Get gas from pipenet + var/datum/gas_mixture/internal = return_air() + if(!internal.total_moles) return + var/datum/gas_mixture/external_removed = environment.remove(0.25 * environment_moles) + var/datum/gas_mixture/internal_removed = internal.remove_volume(volume) + + //Get same info from connected gas var/combined_heat_capacity = internal_removed.heat_capacity() + external_removed.heat_capacity() - var/combined_energy = internal_removed.temperature * internal_removed.heat_capacity() + external_removed.heat_capacity() * external_removed.temperature + var/combined_energy = internal_removed.thermal_energy() + external_removed.thermal_energy() if(!combined_heat_capacity) combined_heat_capacity = 1 @@ -119,14 +107,13 @@ /obj/machinery/atmospherics/pipe/simple/heat_exchanging/proc/radiate() var/datum/gas_mixture/internal = return_air() - var/remove_ratio = volume/internal.volume - var/datum/gas_mixture/internal_removed = internal.remove_ratio(remove_ratio) + var/datum/gas_mixture/internal_removed = internal.remove_volume(volume) if (!internal_removed) return var/combined_heat_capacity = internal_removed.heat_capacity() + RADIATION_CAPACITY - var/combined_energy = internal_removed.temperature * internal_removed.heat_capacity() + (RADIATION_CAPACITY * ENERGY_MULT) + var/combined_energy = internal_removed.thermal_energy() + (RADIATION_CAPACITY * ENERGY_MULT) var/final_temperature = combined_energy / combined_heat_capacity diff --git a/code/ATMOSPHERICS/hvac/chiller.dm b/code/ATMOSPHERICS/hvac/chiller.dm index 3682fcbb350..18ffaf9e3d6 100644 --- a/code/ATMOSPHERICS/hvac/chiller.dm +++ b/code/ATMOSPHERICS/hvac/chiller.dm @@ -93,8 +93,7 @@ var/turf/simulated/L = loc if(istype(L)) var/datum/gas_mixture/env = L.return_air() - var/transfer_moles = 0.25 * env.total_moles() / env.volume * CELL_VOLUME - var/datum/gas_mixture/removed = env.remove(transfer_moles) + var/datum/gas_mixture/removed = env.remove_volume(0.25 * CELL_VOLUME) if(removed) if(removed.temperature > (set_temperature + T0C)) var/air_heat_capacity = removed.heat_capacity() @@ -102,8 +101,8 @@ //var/old_temperature = removed.temperature if(combined_heat_capacity > 0) - var/combined_energy = set_temperature*cooling_power + air_heat_capacity*removed.temperature - removed.temperature = combined_energy/combined_heat_capacity + var/combined_energy = set_temperature * cooling_power + removed.thermal_energy() + removed.temperature = combined_energy / combined_heat_capacity env.merge(removed) return 1 env.merge(removed) diff --git a/code/ATMOSPHERICS/hvac/spaceheater.dm b/code/ATMOSPHERICS/hvac/spaceheater.dm index 685f930336d..1e2f1d03d83 100644 --- a/code/ATMOSPHERICS/hvac/spaceheater.dm +++ b/code/ATMOSPHERICS/hvac/spaceheater.dm @@ -127,7 +127,7 @@ ..() var/turf/T = get_turf(src) var/datum/gas_mixture/env = T.return_air() - if(env.oxygen < 5) + if(env.molar_density("oxygen") < 5 / CELL_VOLUME) to_chat(user, "You try to light \the [name], but it won't catch on fire!") return if(!on && cell.charge > 0) @@ -282,9 +282,7 @@ var/datum/gas_mixture/env = L.return_air() if(env.temperature != set_temperature + T0C) - var/transfer_moles = 0.25 * env.total_moles() / env.volume * CELL_VOLUME - - var/datum/gas_mixture/removed = env.remove(transfer_moles) + var/datum/gas_mixture/removed = env.remove_volume(0.25 * CELL_VOLUME) // to_chat(world, "got [transfer_moles] moles at [removed.temperature]") @@ -325,7 +323,7 @@ return lastcharge = Floor(cell.charge/10) if(on) - playsound(get_turf(src), pick(comfyfire), (cell.charge/250)*5, 1, -1,channel = 124) + playsound(src, pick(comfyfire), (cell.charge/250)*5, 1, -1,channel = 124) /obj/machinery/space_heater/campfire/Crossed(mob/user as mob) diff --git a/code/ATMOSPHERICS/pipe/construction.dm b/code/ATMOSPHERICS/pipe/construction.dm index cedd14516fb..add72f4b1a5 100644 --- a/code/ATMOSPHERICS/pipe/construction.dm +++ b/code/ATMOSPHERICS/pipe/construction.dm @@ -532,7 +532,7 @@ var/list/manifold_pipes = list(PIPE_MANIFOLD4W, PIPE_INSUL_MANIFOLD4W, PIPE_HE_M P.setPipingLayer(src.piping_layer) if(P.buildFrom(usr,src)) investigation_log(I_ATMOS,"was created by [user]/([user.ckey]) at [formatJumpTo(loc)].") - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + playsound(src, 'sound/items/Ratchet.ogg', 50, 1) user.visible_message( \ "[user] fastens \the [src].", \ "You have fastened \the [src].", \ @@ -573,7 +573,7 @@ var/list/manifold_pipes = list(PIPE_MANIFOLD4W, PIPE_INSUL_MANIFOLD4W, PIPE_HE_M to_chat(user, "You need to fasten it to a pipe.") return 1 new/obj/machinery/meter(src.loc, pipe) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + playsound(src, 'sound/items/Ratchet.ogg', 50, 1) to_chat(user, "You have fastened the meter to the pipe.") qdel(src) @@ -601,6 +601,6 @@ var/list/manifold_pipes = list(PIPE_MANIFOLD4W, PIPE_INSUL_MANIFOLD4W, PIPE_HE_M if (!iswrench(W)) return ..() new/obj/machinery/air_sensor( src.loc ) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + playsound(src, 'sound/items/Ratchet.ogg', 50, 1) to_chat(user, "You have fastened the gas sensor.") qdel(src) diff --git a/code/ATMOSPHERICS/pipes.dm b/code/ATMOSPHERICS/pipes.dm index b8fbe4dab68..11adf6ed8d0 100644 --- a/code/ATMOSPHERICS/pipes.dm +++ b/code/ATMOSPHERICS/pipes.dm @@ -242,7 +242,7 @@ src.visible_message("\The [src] groans from the pressure!"); // Need SFX for groaning metal. - //playsound(get_turf(src), 'sound/effects/groan.ogg', 25, 1) + //playsound(src, 'sound/effects/groan.ogg', 25, 1) /obj/machinery/atmospherics/pipe/simple/proc/burst() @@ -251,7 +251,7 @@ var/turf/T=get_turf(src) message_admins("Pipe burst in area [formatJumpTo(T)]") - var/area/A=get_area_master(src) + var/area/A=get_area(src) log_game("Pipe burst in area [A.name] ") // Disconnect first. @@ -349,7 +349,7 @@ if(!suppress_icon_check) update_icon() - T.soft_add_holomap(src) + add_self_to_holomap() /obj/machinery/atmospherics/pipe/simple/disconnect(obj/machinery/atmospherics/reference) if(reference == node1) @@ -594,7 +594,7 @@ if(!skip_icon_update) update_icon() - T.soft_add_holomap(src) + add_self_to_holomap() /obj/machinery/atmospherics/pipe/manifold/scrubbers name = "\improper Scrubbers pipe" @@ -815,7 +815,7 @@ if(!skip_update_icon) update_icon() - T.soft_add_holomap(src) + add_self_to_holomap() /obj/machinery/atmospherics/pipe/manifold4w/scrubbers name = "\improper Scrubbers pipe" @@ -1063,7 +1063,7 @@ if(!skip_update_icon) update_icon() - T.soft_add_holomap(src) + add_self_to_holomap() /obj/machinery/atmospherics/pipe/layer_manifold/findAllConnections(var/connect_dirs) for(var/direction in cardinal) @@ -1246,7 +1246,7 @@ if(!skip_update_icon) update_icon() - T.soft_add_holomap(src) + add_self_to_holomap() /obj/machinery/atmospherics/pipe/layer_adapter/findAllConnections(var/connect_dirs) for(var/direction in cardinal) diff --git a/code/WorkInProgress/Cael_Aislinn/Rust/core_field.dm b/code/WorkInProgress/Cael_Aislinn/Rust/core_field.dm index a6022ac1c03..8ffa315e0c4 100644 --- a/code/WorkInProgress/Cael_Aislinn/Rust/core_field.dm +++ b/code/WorkInProgress/Cael_Aislinn/Rust/core_field.dm @@ -143,7 +143,12 @@ Deuterium-tritium fusion: 4.5 x 10^7 K var/moles_covered = environment.return_pressure()*volume_covered/(environment.temperature * R_IDEAL_GAS_EQUATION) // to_chat(world, "moles_covered: [moles_covered]") // - var/datum/gas_mixture/gas_covered = environment.remove(moles_covered) + + //Since nearly every mathematical expression in this file is wrong in some way, it actually relied on a bug in ZAS to not cause ridiculous nonsense. + //That bug got fixed, and ridiculous nonsense was caused. + //The min() in the following line of code simulates that bug, because god is dead. + //Obviously the correct solution would be to fix all the errors in here, but that would involve rebalancing every magic number in this file. + var/datum/gas_mixture/gas_covered = environment.remove(min(moles_covered, environment.molar_density() * CELL_VOLUME)) var/datum/gas_mixture/plasma_captured = new /datum/gas_mixture() // plasma_captured.toxins = round(gas_covered.toxins * transfer_ratio) diff --git a/code/WorkInProgress/Cael_Aislinn/Rust/fuel_assembly_port_construction.dm b/code/WorkInProgress/Cael_Aislinn/Rust/fuel_assembly_port_construction.dm index 9d3a27a7dd6..d77db4433b0 100644 --- a/code/WorkInProgress/Cael_Aislinn/Rust/fuel_assembly_port_construction.dm +++ b/code/WorkInProgress/Cael_Aislinn/Rust/fuel_assembly_port_construction.dm @@ -45,7 +45,7 @@ if (iscrowbar(W)) if(opened) if(has_electronics & 1) - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) + playsound(src, 'sound/items/Crowbar.ogg', 50, 1) to_chat(user, "You begin removing the circuitboard")//lpeters - fixed grammar issues if(do_after(user, src, 50)) @@ -74,7 +74,7 @@ to_chat(user, "You need more wires.") return to_chat(user, "You start adding cables to the frame...") - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) if(do_after(user, src, 20) && C.amount >= 10) C.use(10) user.visible_message(\ @@ -85,7 +85,7 @@ else if (iswirecutter(W) && opened && (has_electronics & 2)) to_chat(user, "You begin to cut the cables...") - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) if(do_after(user, src, 50)) new /obj/item/stack/cable_coil(loc,10) user.visible_message(\ @@ -96,7 +96,7 @@ else if (istype(W, /obj/item/weapon/module/rust_fuel_port) && opened && !(has_electronics & 1)) to_chat(user, "You try to insert the port control board into the frame...") - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) if(do_after(user, src, 10)) has_electronics &= 1 to_chat(user, "You place the port control board inside the frame.") @@ -109,7 +109,7 @@ to_chat(user, "You need more welding fuel to complete this task.") return to_chat(user, "You start welding the port frame...") - playsound(get_turf(src), 'sound/items/Welder.ogg', 50, 1) + playsound(src, 'sound/items/Welder.ogg', 50, 1) if(do_after(user, src, 50)) if(!src || !WT.remove_fuel(3, user)) return diff --git a/code/WorkInProgress/Cael_Aislinn/Rust/fuel_compressor_construction.dm b/code/WorkInProgress/Cael_Aislinn/Rust/fuel_compressor_construction.dm index e0d4d3d6b28..a5bf61ceb62 100644 --- a/code/WorkInProgress/Cael_Aislinn/Rust/fuel_compressor_construction.dm +++ b/code/WorkInProgress/Cael_Aislinn/Rust/fuel_compressor_construction.dm @@ -46,7 +46,7 @@ if (iscrowbar(W)) if(opened) if(has_electronics & 1) - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) + playsound(src, 'sound/items/Crowbar.ogg', 50, 1) to_chat(user, "You begin removing the circuitboard")//lpeters - fixed grammar issues if(do_after(user, src, 50)) @@ -101,7 +101,7 @@ to_chat(user, "You need more wires.") return to_chat(user, "You start adding cables to the compressor frame...") - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) if(do_after(user, src, 20) && C.amount >= 10) C.use(10) user.visible_message(\ @@ -112,7 +112,7 @@ else if (iswirecutter(W) && opened && (has_electronics & 2)) to_chat(user, "You begin to cut the cables...") - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) if(do_after(user, src, 50)) new /obj/item/stack/cable_coil(loc,10) user.visible_message(\ @@ -123,7 +123,7 @@ else if (istype(W, /obj/item/weapon/module/rust_fuel_compressor) && opened && !(has_electronics & 1)) to_chat(user, "You try to insert the circuitboard into the frame...") - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) if(do_after(user, src, 10)) has_electronics &= 1 to_chat(user, "You place the circuitboard inside the frame.") @@ -136,7 +136,7 @@ to_chat(user, "You need more welding fuel to complete this task.") return to_chat(user, "You start welding the compressor frame...") - playsound(get_turf(src), 'sound/items/Welder.ogg', 50, 1) + playsound(src, 'sound/items/Welder.ogg', 50, 1) if(do_after(user, src, 50)) if(!src || !WT.remove_fuel(3, user)) return diff --git a/code/WorkInProgress/Cael_Aislinn/Rust/gyrotron.dm b/code/WorkInProgress/Cael_Aislinn/Rust/gyrotron.dm index 4433f83b446..3d1f32b781d 100644 --- a/code/WorkInProgress/Cael_Aislinn/Rust/gyrotron.dm +++ b/code/WorkInProgress/Cael_Aislinn/Rust/gyrotron.dm @@ -57,7 +57,7 @@ A.frequency = frequency A.damage = mega_energy * 1500 - playsound(get_turf(src), 'sound/weapons/emitter.ogg', 25, 1) + playsound(src, 'sound/weapons/emitter.ogg', 25, 1) use_power(100 * mega_energy + 500) A.dir = dir diff --git a/code/WorkInProgress/Cael_Aislinn/ShieldGen/shield_capacitor.dm b/code/WorkInProgress/Cael_Aislinn/ShieldGen/shield_capacitor.dm index 719c79f14d0..cb57b8c09ce 100644 --- a/code/WorkInProgress/Cael_Aislinn/ShieldGen/shield_capacitor.dm +++ b/code/WorkInProgress/Cael_Aislinn/ShieldGen/shield_capacitor.dm @@ -53,7 +53,7 @@ else if(user) to_chat(user, "You fail to hack \the [src]'s controls.") - playsound(get_turf(src), 'sound/effects/sparks4.ogg', 75, 1) + playsound(src, 'sound/effects/sparks4.ogg', 75, 1) /obj/machinery/shield_capacitor/wrenchAnchor(var/mob/user) . = ..() diff --git a/code/WorkInProgress/Cael_Aislinn/ShieldGen/shield_gen.dm b/code/WorkInProgress/Cael_Aislinn/ShieldGen/shield_gen.dm index 4e0502159c4..0b255928b5e 100644 --- a/code/WorkInProgress/Cael_Aislinn/ShieldGen/shield_gen.dm +++ b/code/WorkInProgress/Cael_Aislinn/ShieldGen/shield_gen.dm @@ -84,7 +84,7 @@ else if(user) to_chat(user, "You fail to hack \the [src]'s controls.") - playsound(get_turf(src), 'sound/effects/sparks4.ogg', 75, 1) + playsound(src, 'sound/effects/sparks4.ogg', 75, 1) /obj/machinery/shield_gen/wrenchAnchor(var/mob/user) . = ..() diff --git a/code/WorkInProgress/Cael_Aislinn/Supermatter/ZeroPointLaser.dm b/code/WorkInProgress/Cael_Aislinn/Supermatter/ZeroPointLaser.dm index 732281ab2fa..209778135d4 100644 --- a/code/WorkInProgress/Cael_Aislinn/Supermatter/ZeroPointLaser.dm +++ b/code/WorkInProgress/Cael_Aislinn/Supermatter/ZeroPointLaser.dm @@ -94,7 +94,7 @@ src.shot_number = 0 use_power(1000) var/obj/item/projectile/beam/emitter/A = getFromPool(/obj/item/projectile/beam/emitter, loc) - playsound(get_turf(src), 'sound/weapons/emitter.ogg', 25, 1) + playsound(src, 'sound/weapons/emitter.ogg', 25, 1) if(prob(35)) spark(src, 5) A.dir = src.dir diff --git a/code/WorkInProgress/Cael_Aislinn/scp_173.dm b/code/WorkInProgress/Cael_Aislinn/scp_173.dm index 733b9b2271e..185449e34fa 100644 --- a/code/WorkInProgress/Cael_Aislinn/scp_173.dm +++ b/code/WorkInProgress/Cael_Aislinn/scp_173.dm @@ -115,7 +115,7 @@ //Send the warning that SPC is homing in target_turf = get_turf(target) if(!scare_played) //Let's minimize the spam - playsound(get_turf(src), pick(scare_sound), 100, 1, -1) + playsound(src, pick(scare_sound), 100, 1, -1) scare_played = 1 spawn(50) scare_played = 0 diff --git a/code/WorkInProgress/Mini/ATM.dm b/code/WorkInProgress/Mini/ATM.dm index 5102591d7c1..b55b3e79596 100644 --- a/code/WorkInProgress/Mini/ATM.dm +++ b/code/WorkInProgress/Mini/ATM.dm @@ -87,7 +87,7 @@ log transactions user.visible_message("[user] begins to take apart the [src]!", "You start to take apart the [src]") if(do_after(user, src, 40)) user.visible_message("[user] disassembles the [src]!", "You disassemble the [src]") - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1) + playsound(src, 'sound/items/Ratchet.ogg', 100, 1) new /obj/item/stack/sheet/metal (src.loc,2) if(scan) scan.forceMove(get_turf(src)) diff --git a/code/WorkInProgress/Mini/atmos_control.dm b/code/WorkInProgress/Mini/atmos_control.dm index 8e5472154ff..3f111693813 100644 --- a/code/WorkInProgress/Mini/atmos_control.dm +++ b/code/WorkInProgress/Mini/atmos_control.dm @@ -104,12 +104,13 @@ var/global/list/atmos_controllers = list() var/list/alarms=list() for(var/obj/machinery/alarm/alarm in sortNames(machines)) // removing sortAtom because nano updates it just enough for the lag to happen - if(!is_in_filter(alarm.areaMaster.type)) + var/area/alarm_area = get_area(alarm) + if(!is_in_filter(alarm_area.type)) continue // NO ACCESS 4 U var/turf/pos = get_turf(alarm) var/list/alarm_data=list() alarm_data["ID"]="\ref[alarm]" - alarm_data["danger"] = max(alarm.local_danger_level, alarm.areaMaster.atmosalm-1) + alarm_data["danger"] = max(alarm.local_danger_level, alarm_area.atmosalm-1) alarm_data["name"] = "[alarm]" alarm_data["area"] = get_area(alarm) alarm_data["x"] = pos.x @@ -254,14 +255,16 @@ var/global/list/atmos_controllers = list() if(href_list["atmos_alarm"]) current.alarmActivated=1 - current.areaMaster.updateDangerLevel() + var/area/current_area = get_area(current) + current_area.updateDangerLevel() //spawn(1) //src.updateUsrDialog() current.update_icon() if(href_list["atmos_reset"]) current.alarmActivated=0 - current.areaMaster.updateDangerLevel() + var/area/current_area = get_area(current) + current_area.updateDangerLevel() //spawn(1) //src.updateUsrDialog() current.update_icon() diff --git a/code/WorkInProgress/Ported/policetape.dm b/code/WorkInProgress/Ported/policetape.dm index 68895ce9fe6..f7055c4fac4 100644 --- a/code/WorkInProgress/Ported/policetape.dm +++ b/code/WorkInProgress/Ported/policetape.dm @@ -17,6 +17,7 @@ anchored = 1 density = 1 var/icon_base + var/robot_compatibility /obj/item/taperoll/police name = "police tape" @@ -30,6 +31,7 @@ desc = "A length of police tape. Do not cross." req_access = list(access_security) icon_base = "police" + robot_compatibility = MODULE_CAN_LIFT_SECTAPE /obj/item/taperoll/engineering name = "engineering tape" @@ -43,6 +45,7 @@ desc = "A length of engineering tape. Better not cross it." req_one_access = list(access_engine,access_atmospherics) icon_base = "engineering" + robot_compatibility = MODULE_CAN_LIFT_ENGITAPE /obj/item/taperoll/atmos name = "atmospherics tape" @@ -56,6 +59,7 @@ desc = "A length of atmospherics tape. Better not cross it." req_one_access = list(access_engine,access_atmospherics) icon_base = "atmos" + robot_compatibility = MODULE_CAN_LIFT_ENGITAPE /obj/item/taperoll/attack_self(mob/user as mob) if(icon_state == "[icon_base]_start") @@ -178,15 +182,40 @@ return breaktape(null, user) -/obj/item/tape/attack_paw(mob/user as mob) - breaktape(/obj/item/weapon/wirecutters,user) +/obj/item/tape/attack_robot(mob/user) + if(Adjacent(user)) + return attack_hand(user) -/obj/item/tape/proc/breaktape(obj/item/weapon/W as obj, mob/user as mob) - if(user.a_intent == I_HELP && (!W || !W.is_sharp()) && !src.allowed(user)) +/obj/item/tape/allowed(mob/user) + if(isrobot(user) && !isMoMMI(user)) + var/mob/living/silicon/robot/R = user + return R.module && (R.module.quirk_flags & robot_compatibility) + + return ..() + +/obj/item/tape/attack_paw(mob/user as mob) + breaktape(null,user, TRUE) + +/obj/item/tape/attack_animal(var/mob/living/L) + if(istype(L, /mob/living/simple_animal)) + var/mob/living/simple_animal/SA = L + if(SA.melee_damage_lower < 5) + return + breaktape(null,L, TRUE) + +/obj/item/tape/proc/breaktape(obj/item/weapon/W as obj, mob/user as mob, var/override = FALSE) + if(!override && user.a_intent == I_HELP && (!W || !W.is_sharp()) && !src.allowed(user)) to_chat(user, "You can't break [src] [W ? "with \the [W] " : ""]unless you use force.") return - user.visible_message("[user] breaks [src]!") + if (!destroy_tape(user, W)) // If we could destroy the tape or not. + user.visible_message("[user] fails to break [src]!") + return FALSE + + user.visible_message("[user] breaks [src]!") + qdel(src) + +/obj/item/tape/proc/destroy_tape(var/mob/user, var/obj/item/weapon/W) var/dir[2] var/icon_dir = src.icon_state if(icon_dir == "[src.icon_base]_h") @@ -207,5 +236,152 @@ qdel(P) cur = get_step(cur,dir[i]) - qdel(src) - return + return TRUE + +// Syndie tapes + +// -- /taperoll/syndie = contains all the things dealing with charges + +/obj/item/taperoll/syndie + var/charges_left = 3 + +/obj/item/taperoll/syndie/police + name = "police tape" + desc = "A roll of police tape used to block off crime scenes from the public." + icon_state = "police_start" + icon_base = "police" + tape_type = /obj/item/tape/police/syndie + +/obj/item/taperoll/syndie/atmos + name = "atmospherics tape" + desc = "A roll of atmospherics tape used to block off working areas from the public." + icon_state = "atmos_start" + icon_base = "atmos" + tape_type = /obj/item/tape/atmos/syndie + siemens_coefficient = 1 + +/obj/item/taperoll/syndie/engineering + name = "engineering tape" + desc = "A roll of engineering tape used to block off working areas from the public." + icon_state = "engineering_start" + icon_base = "engineering" + tape_type = /obj/item/tape/engineering/syndie + +/obj/item/taperoll/syndie/preattack(atom/target, mob/user, proximity_flag, click_parameters) + if (charges_left & (istype(target, /obj/machinery/door/airlock) || istype(target, /obj/machinery/door/firedoor))) + charges_left-- + if (!(charges_left)) + to_chat(user, "There is no tape left.") + qdel(src) + return TRUE + to_chat(user, "There [charges_left > 1 ? "are" : "is"] [charges_left] roll[charges_left > 1 ? "s" : ""] of tape left.") + . = ..() + +/obj/item/taperoll/syndie/afterattack(var/atom/A, mob/user, proximity_flag) + if (!charges_left) + to_chat(user, "There is no tape left.") + qdel(src) + +/obj/item/taperoll/syndie/attack_self(var/mob/user) + if (charges_left) + ..() + if (icon_state == "[icon_base]_start") + charges_left-- + if (!charges_left) + to_chat(user, "There is no tape left.") + qdel(src) + return + to_chat(user, "There [charges_left > 1 ? "are" : "is"] [charges_left] roll[charges_left > 1 ? "s" : ""] of tape left.") + else + to_chat(user, "There is no tape left.") + qdel(src) + +// -- Syndie police tape : it cuffs people attempting to attack it. It's also unbreakable by simple mobs. + +/obj/item/tape/police/syndie/destroy_tape(var/mob/user, var/obj/item/weapon/W) + if (istype(W)) + if (!W.is_sharp() || !(W.force >= 10)) + to_chat(user, "The tape resists your attack!") + return FALSE + return ..() // We could destroy it + else // Attacks with bare hands, cuffs himself on it + if (ishuman(user)) + var/mob/living/carbon/human/H = user + if (H.has_organ_for_slot(slot_handcuffed)) + H.visible_message("[H] wraps \his hands on the tape!", "The tape wraps itself on your hands!") + var/obj/item/taperoll/police/cuffs + cuffs = new(get_turf(src)) + cuffs.on_restraint_apply(H) + H.put_in_hands(cuffs) // Unlike normal cuffs, those cuffs don't transfer from one inventory to another. We need to place them in an inventory first for the icon to show. + H.equip_to_slot(cuffs, slot_handcuffed) + return FALSE + + +/obj/item/tape/police/syndie/examine(mob/user) + . = ..() + if (get_dist(user, src) < 3) + to_chat(user, "This one looks heavier than the usual.") + +// -- Syndie engie tape : shocks and sparks you (useful for lighting those plasma fires) + +/obj/item/tape/engineering/syndie + var/charged = TRUE + siemens_coefficient = 1 + +/obj/item/tape/engineering/syndie/destroy_tape(var/mob/user) + if (spark_and_shock(user)) // If you were shocked, you couldn't destroy the tape ! + return FALSE + return ..() + +/obj/item/tape/engineering/syndie/proc/spark_and_shock(var/mob/user) + if (user && charged) + spark(src, 5) + return shock(user, 50) + else // No user, or not charged + return FALSE + +/obj/item/tape/engineering/syndie/proc/shock(var/mob/user, var/damage) + if (!istype(user, /mob/living)) + return FALSE + if (ishuman(user)) + var/mob/living/carbon/human/H = user + var/obj/item/clothing/gloves/G = H.get_item_by_slot(slot_gloves) + if(G & G.siemens_coefficient == 0) + return FALSE + + var/mob/living/L = user + return L.electrocute_act(damage, src) + +/obj/item/tape/engineering/syndie/examine(mob/user) + . = ..() + if (get_dist(user, src) < 3 && charged) + to_chat(user, "The reflective strips on it seem strangely active, somehow.") + +/obj/item/tape/engineering/syndie/emp_act(severity) + charged = FALSE + spark(src, 5) + +// Atmos syndie tape : hard to break and cut off your hands + +/obj/item/tape/atmos/syndie/destroy_tape(var/mob/user, var/obj/item/weapon/W) + if (!W) + if (istype(user, /mob/living)) + var/mob/living/L = user + if(ishuman(L)) + to_chat(L, "You cut your hand on the tape!") + L.get_active_hand_organ().droplimb(1) + else + to_chat(L, "You cut yourself on the tape!") + L.emote("scream", , , 1) + L.adjustBruteLoss(10) + return FALSE + if (!W.is_sharp() || !(W.force >= 10)) + to_chat(user, "The tape resists your attack!") + return FALSE + + return ..() + +/obj/item/tape/atmos/syndie/examine(mob/user) + . = ..() + if (get_dist(user, src) < 3) + to_chat(user, "This one looks much sharper than the usual.") diff --git a/code/WorkInProgress/buildmode.dm b/code/WorkInProgress/buildmode.dm index ed044ab3ac7..696e9298656 100644 --- a/code/WorkInProgress/buildmode.dm +++ b/code/WorkInProgress/buildmode.dm @@ -196,7 +196,13 @@ obj/effect/bmode/buildholder/New() return 1 if(2) copycat = null - objholder = text2path(input(usr,"Enter typepath:" ,"Typepath","/obj/structure/closet")) + var/partial_type = input(usr, "Enter type, or leave blank to see all types", "Typepath", "/obj/structure/closet") as text|null + if(isnull(partial_type)) + return + + var/list/matches = get_matching_types(partial_type, /atom) + objholder = input("Select type", "Typepath") as null|anything in matches + if(!ispath(objholder)) objholder = /obj/structure/closet alert("That path is not allowed.") diff --git a/code/WorkInProgress/pomf/spacepods/parts.dm b/code/WorkInProgress/pomf/spacepods/parts.dm index ae0723db2ed..133fdb18e2d 100644 --- a/code/WorkInProgress/pomf/spacepods/parts.dm +++ b/code/WorkInProgress/pomf/spacepods/parts.dm @@ -69,7 +69,7 @@ pod.dir = src.dir to_chat(user, "You strut the pod frame together.") R.use(10) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + playsound(src, 'sound/items/Ratchet.ogg', 50, 1) for(var/obj/item/pod_parts/pod_frame/F in linkedparts) if(1 == turn(F.dir, -F.link_angle)) //if the part links north during construction, as the bottom left part always does //log_admin("Repositioning") @@ -79,7 +79,7 @@ to_chat(user, "You [!anchored ? "secure \the [src] in place." : "remove the securing bolts."]") anchored = !anchored setDensity(anchored) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + playsound(src, 'sound/items/Ratchet.ogg', 50, 1) /obj/item/pod_parts/pod_frame/verb/rotate() set name = "Rotate Frame" diff --git a/code/WorkInProgress/pomf/spacepods/spacepods.dm b/code/WorkInProgress/pomf/spacepods/spacepods.dm index c4e0b0d594b..4a3ab1649fb 100644 --- a/code/WorkInProgress/pomf/spacepods/spacepods.dm +++ b/code/WorkInProgress/pomf/spacepods/spacepods.dm @@ -28,6 +28,7 @@ var/next_firetime = 0 var/list/pod_overlays var/health = 400 + var/maxHealth = 400 appearance_flags = 0 var/datum/delay_controller/move_delayer = new(0.1, ARBITRARILY_LARGE_NUMBER) //See setup.dm, 12 @@ -113,25 +114,17 @@ /obj/spacepod/bullet_act(var/obj/item/projectile/P) if(P.damage && !P.nodamage) - deal_damage(P.damage) + adjust_health(P.damage) -/obj/spacepod/proc/deal_damage(var/damage) +/obj/spacepod/proc/adjust_health(var/damage) var/oldhealth = health - health = max(0, health - damage) + health = Clamp(health-damage,0, maxHealth) var/percentage = (health / initial(health)) * 100 if(occupant && oldhealth > health && percentage <= 25 && percentage > 0) - var/sound/S = sound('sound/effects/engine_alert2.ogg') - S.wait = 0 //No queue - S.channel = 0 //Any channel - S.volume = 50 - occupant << S + occupant.playsound_local(occupant, 'sound/effects/engine_alert2.ogg', 50, 0, 0, 0, 0) if(occupant && oldhealth > health && !health) - var/sound/S = sound('sound/effects/engine_alert1.ogg') - S.wait = 0 - S.channel = 0 - S.volume = 50 - occupant << S - if(!health) + occupant.playsound_local(occupant, 'sound/effects/engine_alert1.ogg', 50, 0, 0, 0, 0) + if(health <= 0) spawn(0) if(occupant) to_chat(occupant, "Critical damage to the vessel detected, core explosion imminent!") @@ -162,15 +155,31 @@ ion_trail = null // Should be nulled by qdel src in next line but OH WELL qdel(src) if(2) - deal_damage(100) + adjust_health(100) if(3) if(prob(40)) - deal_damage(50) + adjust_health(50) -/obj/spacepod/attackby(obj/item/W as obj, mob/user as mob) +/obj/spacepod/attackby(obj/item/W, mob/user) if(iscrowbar(W)) hatch_open = !hatch_open to_chat(user, "You [hatch_open ? "open" : "close"] the maintenance hatch.") + return + if(health < maxHealth && iswelder(W)) + var/obj/item/weapon/weldingtool/WT = W + if(!WT.isOn()) + return + if (WT.get_fuel() < 5) + to_chat(user, "You need more fuel to complete this task.") + + playsound(src, pick('sound/items/Welder.ogg', 'sound/items/Welder2.ogg'), 50, 1) + if(do_after(user, src, 30)) + if(!src || !WT.remove_fuel(5, user)) + return + to_chat(user, "You patch up \the [src].") + adjust_health(-rand(15,30)) + return + if(istype(W, /obj/item/weapon/cell)) if(!hatch_open) return ..() @@ -201,6 +210,12 @@ //new/obj/item/device/spacepod_equipment/weaponry/proc/fire_weapon_system(src, equipment_system.weapon_system.verb_name, equipment_system.weapon_system.verb_desc) //Yes, it has to be referenced like that. W.verb_name/desc doesn't compile. return + if(W.force) + visible_message("\The [user] hits \the [src] with \the [W]") + adjust_health(W.force) + W.on_attack(src, user) + + /obj/spacepod/attack_hand(mob/user as mob) if(!hatch_open) return ..() @@ -250,8 +265,6 @@ to_chat(user, "You need an open hand to do that.") */ - return - /obj/spacepod/civilian icon_state = "pod_civ" desc = "A sleek civilian space pod." @@ -441,7 +454,7 @@ var/transfer_moles = 0 if(pressure_delta > 0) //cabin pressure lower than release pressure if(tank_air.return_temperature() > 0) - transfer_moles = pressure_delta*cabin_air.return_volume()/(cabin_air.return_temperature() * R_IDEAL_GAS_EQUATION) + transfer_moles = pressure_delta * cabin_air.return_volume() / (cabin_air.return_temperature() * R_IDEAL_GAS_EQUATION) var/datum/gas_mixture/removed = tank_air.remove(transfer_moles) cabin_air.merge(removed) else if(pressure_delta < 0) //cabin pressure higher than release pressure @@ -450,7 +463,7 @@ if(t_air) pressure_delta = min(cabin_pressure - t_air.return_pressure(), pressure_delta) if(pressure_delta > 0) //if location pressure is lower than cabin pressure - transfer_moles = pressure_delta*cabin_air.return_volume()/(cabin_air.return_temperature() * R_IDEAL_GAS_EQUATION) + transfer_moles = pressure_delta * cabin_air.return_volume() / (cabin_air.return_temperature() * R_IDEAL_GAS_EQUATION) var/datum/gas_mixture/removed = cabin_air.remove(transfer_moles) if(t_air) t_air.merge(removed) diff --git a/code/ZAS/Airflow.dm b/code/ZAS/Airflow.dm index 484e6f27578..6b21714e4a3 100644 --- a/code/ZAS/Airflow.dm +++ b/code/ZAS/Airflow.dm @@ -221,7 +221,7 @@ atom/movable/GotoAirflowDest(n) return //Slamming into a mouse/roach doesn't make much sense if(!sound_override) visible_message(message = "\The [src] slams into \a [A]!", blind_message = "You hear a loud slam!") - //playsound(get_turf(src), "smash.ogg", 25, 1, -1) + //playsound(src, "smash.ogg", 25, 1, -1) if(istype(A,/obj/item)) var/obj/item/item = A SetKnockdown(item.w_class) @@ -232,7 +232,7 @@ atom/movable/GotoAirflowDest(n) /obj/airflow_hit(atom/A) if(!sound_override) visible_message(message = "\The [src] slams into \a [A]!", blind_message = "You hear a loud slam!") - //playsound(get_turf(src), "smash.ogg", 25, 1, -1) + //playsound(src, "smash.ogg", 25, 1, -1) . = ..() /obj/item/airflow_hit(atom/A) diff --git a/code/ZAS/Fire.dm b/code/ZAS/Fire.dm index 2ac7b17d8d6..88af85e11e1 100644 --- a/code/ZAS/Fire.dm +++ b/code/ZAS/Fire.dm @@ -169,9 +169,9 @@ Attach to transfer valve and open. BOOM. //since the air is processed in fractions, we need to make sure not to have any minuscle residue or //the amount of moles might get to low for some functions to catch them and thus result in wonky behaviour - if(air_contents.oxygen < 0.1) + if(air_contents.molar_density("oxygen") < 0.1 / CELL_VOLUME) air_contents.oxygen = 0 - if(air_contents.toxins < 0.1) + if(air_contents.molar_density("toxins") < 0.1 / CELL_VOLUME) air_contents.toxins = 0 if(fuel) if(fuel.moles < 0.1) @@ -240,7 +240,7 @@ Attach to transfer valve and open. BOOM. //seperate part of the present gas //this is done to prevent the fire burning all gases in a single pass - var/datum/gas_mixture/flow = air_contents.remove_ratio(zas_settings.Get(/datum/ZAS_Setting/fire_consumption_rate)) + var/datum/gas_mixture/flow = air_contents.remove_volume(zas_settings.Get(/datum/ZAS_Setting/fire_consumption_rate) * CELL_VOLUME) ///////////////////////////////// FLOW HAS BEEN CREATED /// DONT DELETE THE FIRE UNTIL IT IS MERGED BACK OR YOU WILL DELETE AIR /////////////////////////////////////////////// if(flow) @@ -350,9 +350,9 @@ datum/gas_mixture/proc/zburn(var/turf/T, force_burn) var/datum/gas/volatile_fuel/fuel = locate() in trace_gases if(oxygen && (toxins || fuel)) - if(QUANTIZE((toxins / volume * CELL_VOLUME) * zas_settings.Get(/datum/ZAS_Setting/fire_consumption_rate)) >= MOLES_PLASMA_VISIBLE) + if(QUANTIZE(molar_density("toxins") * zas_settings.Get(/datum/ZAS_Setting/fire_consumption_rate)) >= MOLES_PLASMA_VISIBLE / CELL_VOLUME) return 1 - if(fuel && QUANTIZE((fuel.moles / volume * CELL_VOLUME) * zas_settings.Get(/datum/ZAS_Setting/fire_consumption_rate)) >= BASE_ZAS_FUEL_REQ) + if(fuel && QUANTIZE((fuel.moles / volume) * zas_settings.Get(/datum/ZAS_Setting/fire_consumption_rate)) >= BASE_ZAS_FUEL_REQ / CELL_VOLUME) //Not bothering to make molar_density() support trace_gases since I'm removing those soon anyway return 1 // Check if we're actually in a turf or not before trying to check object fires. @@ -394,9 +394,9 @@ datum/gas_mixture/proc/check_combustability(var/turf/T, var/objects) var/datum/gas/volatile_fuel/fuel = locate() in trace_gases if(oxygen && (toxins || fuel)) - if(QUANTIZE(toxins * zas_settings.Get(/datum/ZAS_Setting/fire_consumption_rate)) >= MOLES_PLASMA_VISIBLE) + if(QUANTIZE(molar_density("toxins") * zas_settings.Get(/datum/ZAS_Setting/fire_consumption_rate)) >= MOLES_PLASMA_VISIBLE / CELL_VOLUME) return 1 - if(fuel && QUANTIZE(fuel.moles * zas_settings.Get(/datum/ZAS_Setting/fire_consumption_rate)) >= BASE_ZAS_FUEL_REQ) + if(fuel && QUANTIZE((fuel.moles / volume) * zas_settings.Get(/datum/ZAS_Setting/fire_consumption_rate)) >= BASE_ZAS_FUEL_REQ / CELL_VOLUME) return 1 if(objects && istype(T)) diff --git a/code/ZAS/_gas_mixture.dm b/code/ZAS/_gas_mixture.dm index aa436f1639a..cc2f78ba99b 100644 --- a/code/ZAS/_gas_mixture.dm +++ b/code/ZAS/_gas_mixture.dm @@ -54,7 +54,7 @@ var/volume = CELL_VOLUME - var/temperature = 0 //in Kelvin, use calculate_temperature() to modify + var/temperature = 0 //in Kelvin var/graphics=0 @@ -203,7 +203,11 @@ /datum/gas_mixture/proc/thermal_energy() - return temperature*heat_capacity() + return temperature * heat_capacity() + + +/datum/gas_mixture/proc/molar_density(gas) //Per liter. You should probably be using pressure instead, but considering this had to be made, you wouldn't be the first not to. + return (gas ? vars[gas] : total_moles) / volume //Should verify if gas is actually a valid gas, but this shouldn't be in use for long anyway. /////////////////////////////// //PV=nRT - related procedures// @@ -364,7 +368,7 @@ //Inputs: Percentage to remove. //Outputs: Removed air. - if(ratio <= 0) + if(ratio <= 0 || total_moles <= 0) return null ratio = min(ratio, 1) @@ -399,8 +403,9 @@ //Removes a volume of gas from the mixture and returns a gas_mixture containing the removed air with the given volume. /datum/gas_mixture/proc/remove_volume(removed_volume) var/datum/gas_mixture/removed = remove_ratio(removed_volume/volume) - removed.volume = removed_volume - removed.update_values() + if(removed) + removed.volume = removed_volume + removed.update_values() return removed diff --git a/code/__DEFINES/mob.dm b/code/__DEFINES/mob.dm deleted file mode 100644 index 6e9304523ce..00000000000 --- a/code/__DEFINES/mob.dm +++ /dev/null @@ -1,17 +0,0 @@ -//Values for the m_intent variable -#define M_INTENT_RUN "run" -#define M_INTENT_WALK "walk" - -//Mob species flags (simple stuff mostly for simple_animals) -#define MOB_UNDEAD 1 //zombies, ghosts, skeletons -#define MOB_ROBOTIC 2 //robots -#define MOB_CONSTRUCT 4 //golems, animated armor, animated whatever (not mimics though) -#define MOB_SWARM 8 //swarm of mobs! -#define MOB_HOLOGRAPHIC 16 //holocarps -#define MOB_SUPERNATURAL 32 -#define MOB_NO_PETRIFY 64 //can't get petrified - -#define BACKPACK 2 -#define SATCHEL_NORM 3 -#define SATCHEL_ALT 4 -#define MESSENGER_BAG 5 \ No newline at end of file diff --git a/code/__DEFINES/spell_flags.dm b/code/__DEFINES/spell_flags.dm deleted file mode 100644 index af6890237a3..00000000000 --- a/code/__DEFINES/spell_flags.dm +++ /dev/null @@ -1 +0,0 @@ -#define AUTOCAST_NOTARGET 1 //For spells with complex targeting (AI can't pick a target) \ No newline at end of file diff --git a/code/__HELPERS/datumpool.dm b/code/__HELPERS/datumpool.dm index b317d5a1025..5312cbf2017 100644 --- a/code/__HELPERS/datumpool.dm +++ b/code/__HELPERS/datumpool.dm @@ -95,8 +95,6 @@ to_chat(world, text("DEBUG_DATUM_POOL: returnToPool([]) [] left.", D.type, length(masterdatumPool[D.type]))) #endif -#undef MAINTAINING_DATUM_POOL_COUNT - #ifdef DEBUG_DATUM_POOL #undef DEBUG_DATUM_POOL #endif diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index bae24c43bbb..343ab136215 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -14,12 +14,6 @@ if(T) return T.loc -/proc/get_area_master(const/O) - var/area/A = get_area(O) - - if(isarea(A)) - return A - /proc/get_area_name(N) //get area by its name for(var/area/A in areas) if(A.name == N) @@ -49,13 +43,13 @@ /proc/alone_in_area(var/area/the_area, var/mob/must_be_alone, var/check_type = /mob/living/carbon) - var/area/our_area = get_area_master(the_area) + var/area/our_area = get_area(the_area) for(var/C in living_mob_list) if(!istype(C, check_type)) continue if(C == must_be_alone) continue - if(our_area == get_area_master(C)) + if(our_area == get_area(C)) return 0 return 1 @@ -408,11 +402,11 @@ var/list/DummyCache = list() /proc/mobs_in_area(var/area/the_area, var/client_needed=0, var/moblist=mob_list) var/list/mobs_found[0] - var/area/our_area = get_area_master(the_area) + var/area/our_area = get_area(the_area) for(var/mob/M in moblist) if(client_needed && !M.client) continue - if(our_area != get_area_master(M)) + if(our_area != get_area(M)) continue mobs_found += M return mobs_found diff --git a/code/__HELPERS/globalaccess.dm b/code/__HELPERS/globalaccess.dm deleted file mode 100644 index f9b71e2e2d8..00000000000 --- a/code/__HELPERS/globalaccess.dm +++ /dev/null @@ -1,3734 +0,0 @@ -// THIS FILE IS AUTOMATICALLY CREATED BY tools/gen_globals.py -/proc/readglobal(which) - switch(which) - if("map") - return global.map; - if("masterdatumPool") - return global.masterdatumPool; - if("pooledvariables") - return global.pooledvariables; - if("prox_sensor_ignored_types") - return global.prox_sensor_ignored_types; - if("ability_verbs") - return global.ability_verbs; - if("sent_aliens_to_station") - return global.sent_aliens_to_station; - if("account_hack_attempted") - return global.account_hack_attempted; - if("spacevines_spawned") - return global.spacevines_spawned; - if("sent_spiders_to_station") - return global.sent_spiders_to_station; - if("exclude") - return global.exclude; - if("_all_globals") - return global._all_globals; - if("asset_cache") - return global.asset_cache; - if("error_last_seen") - return global.error_last_seen; - if("error_cooldown") - return global.error_cooldown; - if("html_interfaces") - return global.html_interfaces; - if("all_lighting_corners") - return global.all_lighting_corners; - if("LIGHTING_CORNER_DIAGONAL") - return global.LIGHTING_CORNER_DIAGONAL; - if("validartifactprojectiles") - return global.validartifactprojectiles; - if("cargo_telepads") - return global.cargo_telepads; - if("chatResources") - return global.chatResources; - if("bicon_cache") - return global.bicon_cache; - if("dview_mob") - return global.dview_mob; - if("meteor_wave_delay") - return global.meteor_wave_delay; - if("meteors_in_wave") - return global.meteors_in_wave; - if("meteor_wave_active") - return global.meteor_wave_active; - if("max_meteor_size") - return global.max_meteor_size; - if("chosen_dir") - return global.chosen_dir; - if("create_mob_html") - return global.create_mob_html; - if("create_object_html") - return global.create_object_html; - if("create_turf_html") - return global.create_turf_html; - if("any") - return global.any; - if("asset_cache_populated") - return global.asset_cache_populated; - if("total_runtimes") - return global.total_runtimes; - if("total_runtimes_skipped") - return global.total_runtimes_skipped; - if("error_cache") - return global.error_cache; - if("dummy_lighting_corner") - return global.dummy_lighting_corner; - if("security_level") - return global.security_level; - if("iconCache") - return global.iconCache; - if("round_end_info") - return global.round_end_info; - if("deadmins") - return global.deadmins; - if("lockedvars") - return global.lockedvars; - if("nevervars") - return global.nevervars; - if("type_instances") - return global.type_instances; - if("data_core") - return global.data_core; - if("plmaster") - return global.plmaster; - if("slmaster") - return global.slmaster; - if("account_DBs") - return global.account_DBs; - if("global_map") - return global.global_map; - if("universe") - return global.universe; - if("paper_tag_whitelist") - return global.paper_tag_whitelist; - if("paper_blacklist") - return global.paper_blacklist; - if("skipupdate") - return global.skipupdate; - if("eventchance") - return global.eventchance; - if("event") - return global.event; - if("hadevent") - return global.hadevent; - if("blobevent") - return global.blobevent; - if("starticon") - return global.starticon; - if("midicon") - return global.midicon; - if("endicon") - return global.endicon; - if("diary") - return global.diary; - if("diaryofmeanpeople") - return global.diaryofmeanpeople; - if("admin_diary") - return global.admin_diary; - if("href_logfile") - return global.href_logfile; - if("station_name") - return global.station_name; - if("game_version") - return global.game_version; - if("changelog_hash") - return global.changelog_hash; - if("game_year") - return global.game_year; - if("going") - return global.going; - if("master_mode") - return global.master_mode; - if("secret_force_mode") - return global.secret_force_mode; - if("host") - return global.host; - if("aliens_allowed") - return global.aliens_allowed; - if("ooc_allowed") - return global.ooc_allowed; - if("looc_allowed") - return global.looc_allowed; - if("dooc_allowed") - return global.dooc_allowed; - if("traitor_scaling") - return global.traitor_scaling; - if("dna_ident") - return global.dna_ident; - if("abandon_allowed") - return global.abandon_allowed; - if("enter_allowed") - return global.enter_allowed; - if("guests_allowed") - return global.guests_allowed; - if("shuttle_frozen") - return global.shuttle_frozen; - if("shuttle_left") - return global.shuttle_left; - if("tinted_weldhelh") - return global.tinted_weldhelh; - if("jobMax") - return global.jobMax; - if("bombers") - return global.bombers; - if("admin_log") - return global.admin_log; - if("lawchanges") - return global.lawchanges; - if("shuttles") - return global.shuttles; - if("reg_dna") - return global.reg_dna; - if("CELLRATE") - return global.CELLRATE; - if("CHARGELEVEL") - return global.CHARGELEVEL; - if("WORLD_X_OFFSET") - return global.WORLD_X_OFFSET; - if("WORLD_Y_OFFSET") - return global.WORLD_Y_OFFSET; - if("shuttle_z") - return global.shuttle_z; - if("airtunnel_start") - return global.airtunnel_start; - if("airtunnel_stop") - return global.airtunnel_stop; - if("airtunnel_bottom") - return global.airtunnel_bottom; - if("monkeystart") - return global.monkeystart; - if("wizardstart") - return global.wizardstart; - if("newplayer_start") - return global.newplayer_start; - if("latejoin") - return global.latejoin; - if("assistant_latejoin") - return global.assistant_latejoin; - if("prisonwarp") - return global.prisonwarp; - if("holdingfacility") - return global.holdingfacility; - if("xeno_spawn") - return global.xeno_spawn; - if("endgame_safespawns") - return global.endgame_safespawns; - if("endgame_exits") - return global.endgame_exits; - if("tdome1") - return global.tdome1; - if("tdome2") - return global.tdome2; - if("tdomeobserve") - return global.tdomeobserve; - if("tdomeadmin") - return global.tdomeadmin; - if("prisonsecuritywarp") - return global.prisonsecuritywarp; - if("prisonwarped") - return global.prisonwarped; - if("blobstart") - return global.blobstart; - if("ninjastart") - return global.ninjastart; - if("cardinal") - return global.cardinal; - if("diagonal") - return global.diagonal; - if("alldirs") - return global.alldirs; - if("universal_cult_chat") - return global.universal_cult_chat; - if("config") - return global.config; - if("combatlog") - return global.combatlog; - if("IClog") - return global.IClog; - if("OOClog") - return global.OOClog; - if("adminlog") - return global.adminlog; - if("suspend_alert") - return global.suspend_alert; - if("Debug") - return global.Debug; - if("Debug2") - return global.Debug2; - if("debugobj") - return global.debugobj; - if("mods") - return global.mods; - if("wavesecret") - return global.wavesecret; - if("gravity_is_on") - return global.gravity_is_on; - if("shuttlecoming") - return global.shuttlecoming; - if("join_motd") - return global.join_motd; - if("forceblob") - return global.forceblob; - if("polarstar") - return global.polarstar; - if("nanomanager") - return global.nanomanager; - if("sqladdress") - return global.sqladdress; - if("sqlport") - return global.sqlport; - if("sqldb") - return global.sqldb; - if("sqllogin") - return global.sqllogin; - if("sqlpass") - return global.sqlpass; - if("sqlfdbkdb") - return global.sqlfdbkdb; - if("sqlfdbklogin") - return global.sqlfdbklogin; - if("sqlfdbkpass") - return global.sqlfdbkpass; - if("sqllogging") - return global.sqllogging; - if("forumsqladdress") - return global.forumsqladdress; - if("forumsqlport") - return global.forumsqlport; - if("forumsqldb") - return global.forumsqldb; - if("forumsqllogin") - return global.forumsqllogin; - if("forumsqlpass") - return global.forumsqlpass; - if("forum_activated_group") - return global.forum_activated_group; - if("forum_authenticated_group") - return global.forum_authenticated_group; - if("fileaccess_timer") - return global.fileaccess_timer; - if("custom_event_msg") - return global.custom_event_msg; - if("dbcon") - return global.dbcon; - if("dbcon_old") - return global.dbcon_old; - if("recall_time_limit") - return global.recall_time_limit; - if("score") - return global.score; - if("trash_items") - return global.trash_items; - if("decals") - return global.decals; - if("on_login") - return global.on_login; - if("on_ban") - return global.on_ban; - if("on_unban") - return global.on_unban; - if("plugins") - return global.plugins; - if("space_gas") - return global.space_gas; - if("announcement_intercom") - return global.announcement_intercom; - if("sortedAreas") - return global.sortedAreas; - if("bomberman_mode") - return global.bomberman_mode; - if("bomberman_hurt") - return global.bomberman_hurt; - if("bomberman_destroy") - return global.bomberman_destroy; - if("volunteer_gladiators") - return global.volunteer_gladiators; - if("ready_gladiators") - return global.ready_gladiators; - if("never_gladiators") - return global.never_gladiators; - if("achievements") - return global.achievements; - if("end_icons") - return global.end_icons; - if("arena_leaderboard") - return global.arena_leaderboard; - if("arena_rounds") - return global.arena_rounds; - if("arena_top_score") - return global.arena_top_score; - if("endgame_info_logged") - return global.endgame_info_logged; - if("explosion_newmethod") - return global.explosion_newmethod; - if("snake_station_highscores") - return global.snake_station_highscores; - if("snake_best_players") - return global.snake_best_players; - if("minesweeper_station_highscores") - return global.minesweeper_station_highscores; - if("minesweeper_best_players") - return global.minesweeper_best_players; - if("nanocoins_rates") - return global.nanocoins_rates; - if("nanocoins_lastchange") - return global.nanocoins_lastchange; - if("speciesinit") - return global.speciesinit; - if("minimapinit") - return global.minimapinit; - if("bees_species") - return global.bees_species; - if("stat_collection") - return global.stat_collection; - if("hardcore_mode") - return global.hardcore_mode; - if("mineral_turfs") - return global.mineral_turfs; - if("static_list") - return global.static_list; - if("grayscale") - return global.grayscale; - if("adminblob_icon") - return global.adminblob_icon; - if("adminblob_size") - return global.adminblob_size; - if("adminblob_beat") - return global.adminblob_beat; - if("holoMiniMaps") - return global.holoMiniMaps; - if("centcommMiniMaps") - return global.centcommMiniMaps; - if("extraMiniMaps") - return global.extraMiniMaps; - if("holomap_markers") - return global.holomap_markers; - if("holomaps_initialized") - return global.holomaps_initialized; - if("tachycardics") - return global.tachycardics; - if("bradycardics") - return global.bradycardics; - if("heartstopper") - return global.heartstopper; - if("cheartstopper") - return global.cheartstopper; - if("disable_scrubbers") - return global.disable_scrubbers; - if("disable_vents") - return global.disable_vents; - if("Space_Tile") - return global.Space_Tile; - if("MAX_EXPLOSION_RANGE") - return global.MAX_EXPLOSION_RANGE; - if("BODY_PARTS") - return global.BODY_PARTS; - if("BODY_COVER_VALUE_LIST") - return global.BODY_COVER_VALUE_LIST; - if("NOIRMATRIX") - return global.NOIRMATRIX; - if("bad_changing_colour_ckeys") - return global.bad_changing_colour_ckeys; - if("global_mutations") - return global.global_mutations; - if("scarySounds") - return global.scarySounds; - if("RESTRICTED_CAMERA_NETWORKS") - return global.RESTRICTED_CAMERA_NETWORKS; - if("default_colour_matrix") - return global.default_colour_matrix; - if("ai_names") - return global.ai_names; - if("wizard_first") - return global.wizard_first; - if("wizard_second") - return global.wizard_second; - if("ninja_titles") - return global.ninja_titles; - if("ninja_names") - return global.ninja_names; - if("commando_names") - return global.commando_names; - if("first_names_male") - return global.first_names_male; - if("first_names_female") - return global.first_names_female; - if("last_names") - return global.last_names; - if("clown_names") - return global.clown_names; - if("verbs") - return global.verbs; - if("adjectives") - return global.adjectives; - if("vox_name_syllables") - return global.vox_name_syllables; - if("golem_names") - return global.golem_names; - if("borer_names") - return global.borer_names; - if("hologram_names") - return global.hologram_names; - if("autoborg_silly_names") - return global.autoborg_silly_names; - if("panicfile") - return global.panicfile; - if("failed_db_connections") - return global.failed_db_connections; - if("failed_old_db_connections") - return global.failed_old_db_connections; - if("desire_ranks") - return global.desire_ranks; - if("cmp_field") - return global.cmp_field; - if("cmp_dist_origin") - return global.cmp_dist_origin; - if("DummyCache") - return global.DummyCache; - if("genders") - return global.genders; - if("clients") - return global.clients; - if("admins") - return global.admins; - if("directory") - return global.directory; - if("mixed_modes") - return global.mixed_modes; - if("player_list") - return global.player_list; - if("mob_list") - return global.mob_list; - if("living_mob_list") - return global.living_mob_list; - if("dead_mob_list") - return global.dead_mob_list; - if("observers") - return global.observers; - if("areas") - return global.areas; - if("chemical_reactions_list") - return global.chemical_reactions_list; - if("chemical_reagents_list") - return global.chemical_reagents_list; - if("landmarks_list") - return global.landmarks_list; - if("surgery_steps") - return global.surgery_steps; - if("mechas_list") - return global.mechas_list; - if("poster_designs") - return global.poster_designs; - if("underwear_m") - return global.underwear_m; - if("underwear_f") - return global.underwear_f; - if("backbaglist") - return global.backbaglist; - if("hit_appends") - return global.hit_appends; - if("epilepsy_appends") - return global.epilepsy_appends; - if("table_recipes") - return global.table_recipes; - if("med_hud_users") - return global.med_hud_users; - if("sec_hud_users") - return global.sec_hud_users; - if("escape_list") - return global.escape_list; - if("church_name") - return global.church_name; - if("command_name") - return global.command_name; - if("religion_name") - return global.religion_name; - if("syndicate_name") - return global.syndicate_name; - if("syndicate_code_phrase") - return global.syndicate_code_phrase; - if("syndicate_code_response") - return global.syndicate_code_response; - if("watt_suffixes") - return global.watt_suffixes; - if("number_digits") - return global.number_digits; - if("number_tens") - return global.number_tens; - if("number_units") - return global.number_units; - if("quote") - return global.quote; - if("get_matching_types_cache") - return global.get_matching_types_cache; - if("get_vars_from_type_cache") - return global.get_vars_from_type_cache; - if("existing_typesof_cache") - return global.existing_typesof_cache; - if("common_tools") - return global.common_tools; - if("WALLITEMS") - return global.WALLITEMS; - if("sortInstance") - return global.sortInstance; - if("hooks") - return global.hooks; - if("ventcrawl_machinery") - return global.ventcrawl_machinery; - if("catcher") - return global.catcher; - if("parallax_on_clients") - return global.parallax_on_clients; - if("parallax_initialized") - return global.parallax_initialized; - if("space_color") - return global.space_color; - if("parallax_icon") - return global.parallax_icon; - if("unstackable_pipes") - return global.unstackable_pipes; - if("heat_pipes") - return global.heat_pipes; - if("bent_dirs") - return global.bent_dirs; - if("pipeID2State") - return global.pipeID2State; - if("nlist") - return global.nlist; - if("straight_pipes") - return global.straight_pipes; - if("bent_pipes") - return global.bent_pipes; - if("manifold_pipes") - return global.manifold_pipes; - if("garbageCollector") - return global.garbageCollector; - if("soft_dels") - return global.soft_dels; - if("emergency_shuttle") - return global.emergency_shuttle; - if("Failsafe") - return global.Failsafe; - if("Master") - return global.Master; - if("MC_restart_clear") - return global.MC_restart_clear; - if("MC_restart_timeout") - return global.MC_restart_timeout; - if("MC_restart_count") - return global.MC_restart_count; - if("CURRENT_TICKLIMIT") - return global.CURRENT_TICKLIMIT; - if("SSair") - return global.SSair; - if("tick_multiplier") - return global.tick_multiplier; - if("SSdisease") - return global.SSdisease; - if("active_diseases") - return global.active_diseases; - if("SSemergency_shuttle") - return global.SSemergency_shuttle; - if("SSevent") - return global.SSevent; - if("events") - return global.events; - if("SSfast_machinery") - return global.SSfast_machinery; - if("fast_machines") - return global.fast_machines; - if("SSgarbage") - return global.SSgarbage; - if("SShtml_ui") - return global.SShtml_ui; - if("html_machines") - return global.html_machines; - if("SSinactivity") - return global.SSinactivity; - if("SSlighting") - return global.SSlighting; - if("lighting_update_lights") - return global.lighting_update_lights; - if("lighting_update_corners") - return global.lighting_update_corners; - if("lighting_update_overlays") - return global.lighting_update_overlays; - if("SSmachinery") - return global.SSmachinery; - if("machines") - return global.machines; - if("SSmob") - return global.SSmob; - if("SSnano") - return global.SSnano; - if("SSobj") - return global.SSobj; - if("processing_objects") - return global.processing_objects; - if("SSpipenet") - return global.SSpipenet; - if("atmos_machines") - return global.atmos_machines; - if("pipe_networks") - return global.pipe_networks; - if("on_pipenet_tick") - return global.on_pipenet_tick; - if("SSpower") - return global.SSpower; - if("power_machines") - return global.power_machines; - if("powernets") - return global.powernets; - if("cable_list") - return global.cable_list; - if("SSsun") - return global.SSsun; - if("SSsupply_shuttle") - return global.SSsupply_shuttle; - if("SSticker") - return global.SSticker; - if("SSvote") - return global.SSvote; - if("SSassets") - return global.SSassets; - if("SSfinish") - return global.SSfinish; - if("SSgenetics") - return global.SSgenetics; - if("SSjob") - return global.SSjob; - if("SSmap") - return global.SSmap; - if("SSminimap") - return global.SSminimap; - if("SSmore_init") - return global.SSmore_init; - if("SSrust") - return global.SSrust; - if("SScreate_ticker") - return global.SScreate_ticker; - if("SSxenoarch") - return global.SSxenoarch; - if("randomize_laws") - return global.randomize_laws; - if("base_law_type") - return global.base_law_type; - if("mommi_base_law_type") - return global.mommi_base_law_type; - if("diseases") - return global.diseases; - if("map_elements") - return global.map_elements; - if("modules") - return global.modules; - if("sun") - return global.sun; - if("all_supply_groups") - return global.all_supply_groups; - if("uplink_items") - return global.uplink_items; - if("archive_diseases") - return global.archive_diseases; - if("advance_cures") - return global.advance_cures; - if("list_symptoms") - return global.list_symptoms; - if("dictionary_symptoms") - return global.dictionary_symptoms; - if("animal_butchering_products") - return global.animal_butchering_products; - if("revdata") - return global.revdata; - if("same_wires") - return global.same_wires; - if("wireColours") - return global.wireColours; - if("PDA_Manifest") - return global.PDA_Manifest; - if("vox_sounds") - return global.vox_sounds; - if("vox_wordlen") - return global.vox_wordlen; - if("outbreak_level_words") - return global.outbreak_level_words; - if("spawned_surprises") - return global.spawned_surprises; - if("max_secret_rooms") - return global.max_secret_rooms; - if("del_profiling") - return global.del_profiling; - if("gdel_profiling") - return global.gdel_profiling; - if("ghdel_profiling") - return global.ghdel_profiling; - if("current_centcomm_order_id") - return global.current_centcomm_order_id; - if("all_radios") - return global.all_radios; - if("radiochannels") - return global.radiochannels; - if("radiochannelsreverse") - return global.radiochannelsreverse; - if("CENT_FREQS") - return global.CENT_FREQS; - if("radio_controller") - return global.radio_controller; - if("pointers") - return global.pointers; - if("nextDecTalkDelay") - return global.nextDecTalkDelay; - if("lastDecTalkUse") - return global.lastDecTalkUse; - if("freqtospan") - return global.freqtospan; - if("freqtoname") - return global.freqtoname; - if("ghostimg") - return global.ghostimg; - if("resethearers") - return global.resethearers; - if("smoothable_unsims") - return global.smoothable_unsims; - if("shatter_sound") - return global.shatter_sound; - if("explosion_sound") - return global.explosion_sound; - if("small_explosion_sound") - return global.small_explosion_sound; - if("spark_sound") - return global.spark_sound; - if("rustle_sound") - return global.rustle_sound; - if("punch_sound") - return global.punch_sound; - if("clown_sound") - return global.clown_sound; - if("swing_hit_sound") - return global.swing_hit_sound; - if("hiss_sound") - return global.hiss_sound; - if("page_sound") - return global.page_sound; - if("mechstep_sound") - return global.mechstep_sound; - if("gib_sound") - return global.gib_sound; - if("mommicomment_sound") - return global.mommicomment_sound; - if("polaroid_sound") - return global.polaroid_sound; - if("male_scream_sound") - return global.male_scream_sound; - if("female_scream_sound") - return global.female_scream_sound; - if("male_cough_sound") - return global.male_cough_sound; - if("female_cough_sound") - return global.female_cough_sound; - if("lightning_sound") - return global.lightning_sound; - if("soulstone_sound") - return global.soulstone_sound; - if("fracture_sound") - return global.fracture_sound; - if("machete_hit_sound") - return global.machete_hit_sound; - if("machete_throw_sound") - return global.machete_throw_sound; - if("machete_throw_hit_sound") - return global.machete_throw_hit_sound; - if("supply_shuttle") - return global.supply_shuttle; - if("space_area") - return global.space_area; - if("ignored_keys") - return global.ignored_keys; - if("moved_landmarks") - return global.moved_landmarks; - if("transparent_icons") - return global.transparent_icons; - if("teleportlocs") - return global.teleportlocs; - if("ghostteleportlocs") - return global.ghostteleportlocs; - if("adminbusteleportlocs") - return global.adminbusteleportlocs; - if("centcom_areas") - return global.centcom_areas; - if("the_station_areas") - return global.the_station_areas; - if("dna_activity_bounds") - return global.dna_activity_bounds; - if("assigned_gene_blocks") - return global.assigned_gene_blocks; - if("assigned_blocks") - return global.assigned_blocks; - if("dna_genes") - return global.dna_genes; - if("good_blocks") - return global.good_blocks; - if("bad_blocks") - return global.bad_blocks; - if("skin_styles_female_list") - return global.skin_styles_female_list; - if("hair_styles_list") - return global.hair_styles_list; - if("hair_styles_male_list") - return global.hair_styles_male_list; - if("hair_styles_female_list") - return global.hair_styles_female_list; - if("facial_hair_styles_list") - return global.facial_hair_styles_list; - if("facial_hair_styles_male_list") - return global.facial_hair_styles_male_list; - if("facial_hair_styles_female_list") - return global.facial_hair_styles_female_list; - if("noir_master") - return global.noir_master; - if("ticker") - return global.ticker; - if("potential_theft_objectives") - return global.potential_theft_objectives; - if("BLINDBLOCK") - return global.BLINDBLOCK; - if("DEAFBLOCK") - return global.DEAFBLOCK; - if("HULKBLOCK") - return global.HULKBLOCK; - if("TELEBLOCK") - return global.TELEBLOCK; - if("FIREBLOCK") - return global.FIREBLOCK; - if("XRAYBLOCK") - return global.XRAYBLOCK; - if("CLUMSYBLOCK") - return global.CLUMSYBLOCK; - if("FAKEBLOCK") - return global.FAKEBLOCK; - if("COUGHBLOCK") - return global.COUGHBLOCK; - if("GLASSESBLOCK") - return global.GLASSESBLOCK; - if("EPILEPSYBLOCK") - return global.EPILEPSYBLOCK; - if("TWITCHBLOCK") - return global.TWITCHBLOCK; - if("NERVOUSBLOCK") - return global.NERVOUSBLOCK; - if("MONKEYBLOCK") - return global.MONKEYBLOCK; - if("BLOCKADD") - return global.BLOCKADD; - if("DIFFMUT") - return global.DIFFMUT; - if("HEADACHEBLOCK") - return global.HEADACHEBLOCK; - if("NOBREATHBLOCK") - return global.NOBREATHBLOCK; - if("REMOTEVIEWBLOCK") - return global.REMOTEVIEWBLOCK; - if("REGENERATEBLOCK") - return global.REGENERATEBLOCK; - if("INCREASERUNBLOCK") - return global.INCREASERUNBLOCK; - if("REMOTETALKBLOCK") - return global.REMOTETALKBLOCK; - if("MORPHBLOCK") - return global.MORPHBLOCK; - if("COLDBLOCK") - return global.COLDBLOCK; - if("HALLUCINATIONBLOCK") - return global.HALLUCINATIONBLOCK; - if("NOPRINTSBLOCK") - return global.NOPRINTSBLOCK; - if("SHOCKIMMUNITYBLOCK") - return global.SHOCKIMMUNITYBLOCK; - if("SMALLSIZEBLOCK") - return global.SMALLSIZEBLOCK; - if("LISPBLOCK") - return global.LISPBLOCK; - if("MUTEBLOCK") - return global.MUTEBLOCK; - if("RADBLOCK") - return global.RADBLOCK; - if("FATBLOCK") - return global.FATBLOCK; - if("CHAVBLOCK") - return global.CHAVBLOCK; - if("SWEDEBLOCK") - return global.SWEDEBLOCK; - if("SCRAMBLEBLOCK") - return global.SCRAMBLEBLOCK; - if("TOXICFARTBLOCK") - return global.TOXICFARTBLOCK; - if("STRONGBLOCK") - return global.STRONGBLOCK; - if("HORNSBLOCK") - return global.HORNSBLOCK; - if("SMILEBLOCK") - return global.SMILEBLOCK; - if("ELVISBLOCK") - return global.ELVISBLOCK; - if("SOBERBLOCK") - return global.SOBERBLOCK; - if("PSYRESISTBLOCK") - return global.PSYRESISTBLOCK; - if("FARSIGHTBLOCK") - return global.FARSIGHTBLOCK; - if("CHAMELEONBLOCK") - return global.CHAMELEONBLOCK; - if("CRYOBLOCK") - return global.CRYOBLOCK; - if("EATBLOCK") - return global.EATBLOCK; - if("JUMPBLOCK") - return global.JUMPBLOCK; - if("MELTBLOCK") - return global.MELTBLOCK; - if("EMPATHBLOCK") - return global.EMPATHBLOCK; - if("SUPERFARTBLOCK") - return global.SUPERFARTBLOCK; - if("IMMOLATEBLOCK") - return global.IMMOLATEBLOCK; - if("POLYMORPHBLOCK") - return global.POLYMORPHBLOCK; - if("LOUDBLOCK") - return global.LOUDBLOCK; - if("WHISPERBLOCK") - return global.WHISPERBLOCK; - if("DIZZYBLOCK") - return global.DIZZYBLOCK; - if("SANSBLOCK") - return global.SANSBLOCK; - if("NOIRBLOCK") - return global.NOIRBLOCK; - if("blobs") - return global.blobs; - if("blob_cores") - return global.blob_cores; - if("blob_nodes") - return global.blob_nodes; - if("blob_resources") - return global.blob_resources; - if("blob_overminds") - return global.blob_overminds; - if("blob_looks_admin") - return global.blob_looks_admin; - if("blob_looks_player") - return global.blob_looks_player; - if("narsie_behaviour") - return global.narsie_behaviour; - if("narsie_cometh") - return global.narsie_cometh; - if("narsie_list") - return global.narsie_list; - if("mr_clean_targets") - return global.mr_clean_targets; - if("rune_list") - return global.rune_list; - if("halloween_spawns") - return global.halloween_spawns; - if("snow_recipes") - return global.snow_recipes; - if("snowsound") - return global.snowsound; - if("Holiday") - return global.Holiday; - if("blob_candidates") - return global.blob_candidates; - if("bomb_set") - return global.bomb_set; - if("nukedisk") - return global.nukedisk; - if("hsboxspawn") - return global.hsboxspawn; - if("hrefs") - return global.hrefs; - if("banned_sandbox_types") - return global.banned_sandbox_types; - if("all_jobs") - return global.all_jobs; - if("job_master") - return global.job_master; - if("assistant_occupations") - return global.assistant_occupations; - if("command_positions") - return global.command_positions; - if("engineering_positions") - return global.engineering_positions; - if("medical_positions") - return global.medical_positions; - if("science_positions") - return global.science_positions; - if("civilian_positions") - return global.civilian_positions; - if("cargo_positions") - return global.cargo_positions; - if("security_positions") - return global.security_positions; - if("nonhuman_positions") - return global.nonhuman_positions; - if("misc_positions") - return global.misc_positions; - if("whitelist") - return global.whitelist; - if("alien_whitelist") - return global.alien_whitelist; - if("firealarms") - return global.firealarms; - if("cryo_health_indicator") - return global.cryo_health_indicator; - if("doppler_arrays") - return global.doppler_arrays; - if("flashers") - return global.flashers; - if("holosigns") - return global.holosigns; - if("igniters") - return global.igniters; - if("multitool_var_whitelist") - return global.multitool_var_whitelist; - if("mass_drivers") - return global.mass_drivers; - if("navbeacons") - return global.navbeacons; - if("news_network") - return global.news_network; - if("allCasters") - return global.allCasters; - if("req_console_assistance") - return global.req_console_assistance; - if("req_console_supplies") - return global.req_console_supplies; - if("req_console_information") - return global.req_console_information; - if("allConsoles") - return global.allConsoles; - if("station_holomaps") - return global.station_holomaps; - if("status_displays") - return global.status_displays; - if("ai_emotions") - return global.ai_emotions; - if("status_display_images") - return global.status_display_images; - if("dispenser_presets") - return global.dispenser_presets; - if("num_vending_terminals") - return global.num_vending_terminals; - if("floorbot_targets") - return global.floorbot_targets; - if("mulebot_count") - return global.mulebot_count; - if("camera_names") - return global.camera_names; - if("camera_messages") - return global.camera_messages; - if("tv_monitors") - return global.tv_monitors; - if("shuttle_calls") - return global.shuttle_calls; - if("prison_shuttle_moving_to_station") - return global.prison_shuttle_moving_to_station; - if("prison_shuttle_moving_to_prison") - return global.prison_shuttle_moving_to_prison; - if("prison_shuttle_at_station") - return global.prison_shuttle_at_station; - if("prison_shuttle_can_send") - return global.prison_shuttle_can_send; - if("prison_shuttle_time") - return global.prison_shuttle_time; - if("prison_shuttle_timeleft") - return global.prison_shuttle_timeleft; - if("specops_shuttle_moving_to_station") - return global.specops_shuttle_moving_to_station; - if("specops_shuttle_moving_to_centcom") - return global.specops_shuttle_moving_to_centcom; - if("specops_shuttle_at_station") - return global.specops_shuttle_at_station; - if("specops_shuttle_can_send") - return global.specops_shuttle_can_send; - if("specops_shuttle_time") - return global.specops_shuttle_time; - if("specops_shuttle_timeleft") - return global.specops_shuttle_timeleft; - if("syndicate_elite_shuttle_moving_to_station") - return global.syndicate_elite_shuttle_moving_to_station; - if("syndicate_elite_shuttle_moving_to_mothership") - return global.syndicate_elite_shuttle_moving_to_mothership; - if("syndicate_elite_shuttle_at_station") - return global.syndicate_elite_shuttle_at_station; - if("syndicate_elite_shuttle_can_send") - return global.syndicate_elite_shuttle_can_send; - if("syndicate_elite_shuttle_time") - return global.syndicate_elite_shuttle_time; - if("syndicate_elite_shuttle_timeleft") - return global.syndicate_elite_shuttle_timeleft; - if("taxi_computers") - return global.taxi_computers; - if("all_doors") - return global.all_doors; - if("alert_overlays_global") - return global.alert_overlays_global; - if("poddoors") - return global.poddoors; - if("recentmessages") - return global.recentmessages; - if("message_delay") - return global.message_delay; - if("telecomms_list") - return global.telecomms_list; - if("uristrune_cache") - return global.uristrune_cache; - if("explosion_shake_message_cooldown") - return global.explosion_shake_message_cooldown; - if("explosion_turfs") - return global.explosion_turfs; - if("explosion_in_progress") - return global.explosion_in_progress; - if("blood_overlays") - return global.blood_overlays; - if("reagents_to_log") - return global.reagents_to_log; - if("BUMP_TELEPORTERS") - return global.BUMP_TELEPORTERS; - if("portal_cache") - return global.portal_cache; - if("splatter_cache") - return global.splatter_cache; - if("blood_list") - return global.blood_list; - if("fluidtrack_cache") - return global.fluidtrack_cache; - if("beacons") - return global.beacons; - if("all_graffitis") - return global.all_graffitis; - if("living_balloons") - return global.living_balloons; - if("deskbell_default_frequencies") - return global.deskbell_default_frequencies; - if("deskbell_freq_cargo") - return global.deskbell_freq_cargo; - if("deskbell_freq_hop") - return global.deskbell_freq_hop; - if("deskbell_freq_medbay") - return global.deskbell_freq_medbay; - if("deskbell_freq_brig") - return global.deskbell_freq_brig; - if("deskbell_freq_rnd") - return global.deskbell_freq_rnd; - if("camera_bugs") - return global.camera_bugs; - if("pda_app_menus") - return global.pda_app_menus; - if("chatrooms") - return global.chatrooms; - if("PDAs") - return global.PDAs; - if("available_paintings") - return global.available_paintings; - if("cable_recipes") - return global.cable_recipes; - if("metal_recipes") - return global.metal_recipes; - if("plasteel_recipes") - return global.plasteel_recipes; - if("wood_recipes") - return global.wood_recipes; - if("cardboard_recipes") - return global.cardboard_recipes; - if("leather_recipes") - return global.leather_recipes; - if("sandstone_recipes") - return global.sandstone_recipes; - if("diamond_recipes") - return global.diamond_recipes; - if("uranium_recipes") - return global.uranium_recipes; - if("plasma_recipes") - return global.plasma_recipes; - if("plastic_recipes") - return global.plastic_recipes; - if("gold_recipes") - return global.gold_recipes; - if("phazon_recipes") - return global.phazon_recipes; - if("silver_recipes") - return global.silver_recipes; - if("clown_recipes") - return global.clown_recipes; - if("charcoal_recipes") - return global.charcoal_recipes; - if("lightfloor_colors") - return global.lightfloor_colors; - if("moneytypes") - return global.moneytypes; - if("cached_icons") - return global.cached_icons; - if("tracking_implants") - return global.tracking_implants; - if("bottle_colour_choices") - return global.bottle_colour_choices; - if("hidden_doors") - return global.hidden_doors; - if("all_docking_ports") - return global.all_docking_ports; - if("ladders") - return global.ladders; - if("one_way_windows") - return global.one_way_windows; - if("cargo_shuttle") - return global.cargo_shuttle; - if("escape_shuttle") - return global.escape_shuttle; - if("mining_shuttle") - return global.mining_shuttle; - if("arrival_shuttle") - return global.arrival_shuttle; - if("transport_shuttle") - return global.transport_shuttle; - if("ert_shuttle") - return global.ert_shuttle; - if("deathsquad_shuttle") - return global.deathsquad_shuttle; - if("elite_syndie_shuttle") - return global.elite_syndie_shuttle; - if("strike_team_shuttle") - return global.strike_team_shuttle; - if("admin_shuttle") - return global.admin_shuttle; - if("research_shuttle") - return global.research_shuttle; - if("salvage_shuttle") - return global.salvage_shuttle; - if("security_shuttle") - return global.security_shuttle; - if("syndicate_shuttle") - return global.syndicate_shuttle; - if("taxi_a") - return global.taxi_a; - if("taxi_b") - return global.taxi_b; - if("trade_shuttle") - return global.trade_shuttle; - if("vox_shuttle") - return global.vox_shuttle; - if("voxresearch_shuttle") - return global.voxresearch_shuttle; - if("response_team_members") - return global.response_team_members; - if("distributed_ert_suits") - return global.distributed_ert_suits; - if("sent_strike_teams") - return global.sent_strike_teams; - if("icons_to_ignore_at_floor_init") - return global.icons_to_ignore_at_floor_init; - if("plating_icons") - return global.plating_icons; - if("wood_icons") - return global.wood_icons; - if("_flatIcons") - return global._flatIcons; - if("directional") - return global.directional; - if("exception") - return global.exception; - if("directional_turfs") - return global.directional_turfs; - if("BSACooldown") - return global.BSACooldown; - if("floorIsLava") - return global.floorIsLava; - if("admin_shuttle_location") - return global.admin_shuttle_location; - if("alien_ship_location") - return global.alien_ship_location; - if("investigations") - return global.investigations; - if("admin_ranks") - return global.admin_ranks; - if("admin_verbs_default") - return global.admin_verbs_default; - if("admin_verbs_admin") - return global.admin_verbs_admin; - if("admin_verbs_ban") - return global.admin_verbs_ban; - if("admin_verbs_sounds") - return global.admin_verbs_sounds; - if("admin_verbs_fun") - return global.admin_verbs_fun; - if("admin_verbs_spawn") - return global.admin_verbs_spawn; - if("admin_verbs_server") - return global.admin_verbs_server; - if("admin_verbs_debug") - return global.admin_verbs_debug; - if("admin_verbs_possess") - return global.admin_verbs_possess; - if("admin_verbs_permissions") - return global.admin_verbs_permissions; - if("admin_verbs_rejuv") - return global.admin_verbs_rejuv; - if("admin_verbs_polling") - return global.admin_verbs_polling; - if("admin_verbs_hideable") - return global.admin_verbs_hideable; - if("admin_verbs_mod") - return global.admin_verbs_mod; - if("appearanceban_runonce") - return global.appearanceban_runonce; - if("appearance_keylist") - return global.appearance_keylist; - if("jobban_runonce") - return global.jobban_runonce; - if("jobban_keylist") - return global.jobban_keylist; - if("oocban_keylist") - return global.oocban_keylist; - if("admin_datums") - return global.admin_datums; - if("CMinutes") - return global.CMinutes; - if("Banlist") - return global.Banlist; - if("Banlistjob") - return global.Banlistjob; - if("adminhelp_ignored_words") - return global.adminhelp_ignored_words; - if("checked_for_inactives") - return global.checked_for_inactives; - if("inactive_keys") - return global.inactive_keys; - if("blood_virus_spreading_disabled") - return global.blood_virus_spreading_disabled; - if("camera_range_display_status") - return global.camera_range_display_status; - if("intercom_range_display_status") - return global.intercom_range_display_status; - if("prevent_airgroup_regroup") - return global.prevent_airgroup_regroup; - if("say_disabled") - return global.say_disabled; - if("movement_disabled") - return global.movement_disabled; - if("movement_disabled_exception") - return global.movement_disabled_exception; - if("forbidden_varedit_object_types") - return global.forbidden_varedit_object_types; - if("PROFILING_VERBS") - return global.PROFILING_VERBS; - if("vox_tick") - return global.vox_tick; - if("assembly_short_name_to_type") - return global.assembly_short_name_to_type; - if("comparison_circuit_operations") - return global.comparison_circuit_operations; - if("math_circuit_operations_list") - return global.math_circuit_operations_list; - if("automation_types") - return global.automation_types; - if("gas_labels") - return global.gas_labels; - if("existing_away_missions") - return global.existing_away_missions; - if("awaydestinations") - return global.awaydestinations; - if("away_mission_subtypes") - return global.away_mission_subtypes; - if("gateways") - return global.gateways; - if("maploader") - return global.maploader; - if("_preloader") - return global._preloader; - if("map_dimension_cache") - return global.map_dimension_cache; - if("swapmaps_iconcache") - return global.swapmaps_iconcache; - if("swapmaps_mode") - return global.swapmaps_mode; - if("swapmaps_compiled_maxx") - return global.swapmaps_compiled_maxx; - if("swapmaps_compiled_maxy") - return global.swapmaps_compiled_maxy; - if("swapmaps_compiled_maxz") - return global.swapmaps_compiled_maxz; - if("swapmaps_initialized") - return global.swapmaps_initialized; - if("swapmaps_loaded") - return global.swapmaps_loaded; - if("swapmaps_byname") - return global.swapmaps_byname; - if("bombermangear") - return global.bombermangear; - if("arenas") - return global.arenas; - if("arena_spawnpoints") - return global.arena_spawnpoints; - if("person_animation_viewers") - return global.person_animation_viewers; - if("item_animation_viewers") - return global.item_animation_viewers; - if("preferences_datums") - return global.preferences_datums; - if("special_roles") - return global.special_roles; - if("antag_roles") - return global.antag_roles; - if("nonantag_roles") - return global.nonantag_roles; - if("role_wiki") - return global.role_wiki; - if("opposite_dirs") - return global.opposite_dirs; - if("holomap_chips") - return global.holomap_chips; - if("holomap_cache") - return global.holomap_cache; - if("has_been_shade") - return global.has_been_shade; - if("current_date_string") - return global.current_date_string; - if("num_financial_terminals") - return global.num_financial_terminals; - if("num_financial_database") - return global.num_financial_database; - if("num_vending_machines") - return global.num_vending_machines; - if("num_pda_terminals") - return global.num_pda_terminals; - if("num_merch_computers") - return global.num_merch_computers; - if("station_account") - return global.station_account; - if("department_accounts") - return global.department_accounts; - if("next_account_number") - return global.next_account_number; - if("centcomm_account_db") - return global.centcomm_account_db; - if("vendor_account") - return global.vendor_account; - if("all_money_accounts") - return global.all_money_accounts; - if("setup_economy") - return global.setup_economy; - if("weighted_randomevent_locations") - return global.weighted_randomevent_locations; - if("weighted_mundaneevent_locations") - return global.weighted_mundaneevent_locations; - if("station_departments") - return global.station_departments; - if("current_pos_id") - return global.current_pos_id; - if("pos_sales") - return global.pos_sales; - if("wages_enabled") - return global.wages_enabled; - if("roundstart_enable_wages") - return global.roundstart_enable_wages; - if("event_last_fired") - return global.event_last_fired; - if("allEvents") - return global.allEvents; - if("potentialRandomEvents") - return global.potentialRandomEvents; - if("eventTimeLower") - return global.eventTimeLower; - if("eventTimeUpper") - return global.eventTimeUpper; - if("scheduledEvent") - return global.scheduledEvent; - if("thing_storm_types") - return global.thing_storm_types; - if("watchdog") - return global.watchdog; - if("non_fakeattack_weapons") - return global.non_fakeattack_weapons; - if("deepFriedEverything") - return global.deepFriedEverything; - if("deepFriedNutriment") - return global.deepFriedNutriment; - if("foodNesting") - return global.foodNesting; - if("recursiveFood") - return global.recursiveFood; - if("ingredientLimit") - return global.ingredientLimit; - if("wizard_cards_rare") - return global.wizard_cards_rare; - if("wizard_cards_normal") - return global.wizard_cards_normal; - if("adv_camera") - return global.adv_camera; - if("crewmonitor") - return global.crewmonitor; - if("vote") - return global.vote; - if("plant_controller") - return global.plant_controller; - if("seed_types") - return global.seed_types; - if("gene_tag_masks") - return global.gene_tag_masks; - if("library_catalog") - return global.library_catalog; - if("library_section_names") - return global.library_section_names; - if("liquid_delay") - return global.liquid_delay; - if("puddles") - return global.puddles; - if("global_playlists") - return global.global_playlists; - if("loopModeNames") - return global.loopModeNames; - if("media_receivers") - return global.media_receivers; - if("media_transmitters") - return global.media_transmitters; - if("migration_controller_mysql") - return global.migration_controller_mysql; - if("migration_controller_sqlite") - return global.migration_controller_sqlite; - if("valid_abandoned_crate_types") - return global.valid_abandoned_crate_types; - if("material_list") - return global.material_list; - if("initial_materials") - return global.initial_materials; - if("name_to_mineral") - return global.name_to_mineral; - if("mining_surprises") - return global.mining_surprises; - if("slot_equipment_priority") - return global.slot_equipment_priority; - if("intents") - return global.intents; - if("boo_phrases") - return global.boo_phrases; - if("boo_phrases_drugs") - return global.boo_phrases_drugs; - if("boo_phrases_silicon") - return global.boo_phrases_silicon; - if("virtualhearers") - return global.virtualhearers; - if("movable_hearers") - return global.movable_hearers; - if("mob_hearers") - return global.mob_hearers; - if("stationary_hearers") - return global.stationary_hearers; - if("coldwarning_light") - return global.coldwarning_light; - if("coldwarning_hard") - return global.coldwarning_hard; - if("department_radio_keys") - return global.department_radio_keys; - if("language_keys") - return global.language_keys; - if("all_languages") - return global.all_languages; - if("all_species") - return global.all_species; - if("whitelisted_species") - return global.whitelisted_species; - if("has_died_as_golem") - return global.has_died_as_golem; - if("unconscious_overlays") - return global.unconscious_overlays; - if("oxyloss_overlays") - return global.oxyloss_overlays; - if("brutefireloss_overlays") - return global.brutefireloss_overlays; - if("organ_damage_overlays") - return global.organ_damage_overlays; - if("damage_icon_parts") - return global.damage_icon_parts; - if("cover_protection_value_list") - return global.cover_protection_value_list; - if("ai_list") - return global.ai_list; - if("announcing_vox") - return global.announcing_vox; - if("vox_digits") - return global.vox_digits; - if("vox_tens") - return global.vox_tens; - if("vox_units") - return global.vox_units; - if("cameranet") - return global.cameranet; - if("paiController") - return global.paiController; - if("borer_chem_types_head") - return global.borer_chem_types_head; - if("borer_chem_types_chest") - return global.borer_chem_types_chest; - if("borer_chem_types_arm") - return global.borer_chem_types_arm; - if("borer_chem_types_leg") - return global.borer_chem_types_leg; - if("borer_unlock_types_head") - return global.borer_unlock_types_head; - if("borer_unlock_types_chest") - return global.borer_unlock_types_chest; - if("borer_unlock_types_arm") - return global.borer_unlock_types_arm; - if("borer_unlock_types_leg") - return global.borer_unlock_types_leg; - if("animal_count") - return global.animal_count; - if("wizard_snakes") - return global.wizard_snakes; - if("nest_locations") - return global.nest_locations; - if("bad_gremlin_items") - return global.bad_gremlin_items; - if("crate_mimic_disguises") - return global.crate_mimic_disguises; - if("item_mimic_disguises") - return global.item_mimic_disguises; - if("protected_objects") - return global.protected_objects; - if("spider_queens") - return global.spider_queens; - if("photocollector_list") - return global.photocollector_list; - if("prism_list") - return global.prism_list; - if("mirror_list") - return global.mirror_list; - if("paper_folding_results") - return global.paper_folding_results; - if("paperwork") - return global.paperwork; - if("paperwork_library") - return global.paperwork_library; - if("battery_charge") - return global.battery_charge; - if("battery_charging") - return global.battery_charging; - if("battery_online") - return global.battery_online; - if("alllights") - return global.alllights; - if("powernets_broke") - return global.powernets_broke; - if("smes_list") - return global.smes_list; - if("solars_list") - return global.solars_list; - if("rad_collectors") - return global.rad_collectors; - if("field_gen_list") - return global.field_gen_list; - if("bullet_master") - return global.bullet_master; - if("impact_master") - return global.impact_master; - if("available_staff_transforms") - return global.available_staff_transforms; - if("beam_master") - return global.beam_master; - if("existing_dungeons") - return global.existing_dungeons; - if("dungeon_area") - return global.dungeon_area; - if("existing_vaults") - return global.existing_vaults; - if("disposalpipeID2State") - return global.disposalpipeID2State; - if("paint_variants") - return global.paint_variants; - if("chifir_doesnt_remove") - return global.chifir_doesnt_remove; - if("tonio_doesnt_remove") - return global.tonio_doesnt_remove; - if("LOGGED_SPLASH_REAGENTS") - return global.LOGGED_SPLASH_REAGENTS; - if("pillIcon2Name") - return global.pillIcon2Name; - if("juice_items") - return global.juice_items; - if("bomb_like_items") - return global.bomb_like_items; - if("special_fruits") - return global.special_fruits; - if("valid_random_food_types") - return global.valid_random_food_types; - if("cockroach_egg_amount") - return global.cockroach_egg_amount; - if("charcoal_doesnt_remove") - return global.charcoal_doesnt_remove; - if("message_servers") - return global.message_servers; - if("blackbox") - return global.blackbox; - if("rnd_machines") - return global.rnd_machines; - if("design_list") - return global.design_list; - if("tech_list") - return global.tech_list; - if("hidden_tech") - return global.hidden_tech; - if("responsive_carriers") - return global.responsive_carriers; - if("finds_as_strings") - return global.finds_as_strings; - if("authenticators") - return global.authenticators; - if("maint_all_access") - return global.maint_all_access; - if("spells") - return global.spells; - if("falltempoverlays") - return global.falltempoverlays; - if("doppelgangers") - return global.doppelgangers; - if("centcomm_store") - return global.centcomm_store; - if("GPS_list") - return global.GPS_list; - if("SPS_list") - return global.SPS_list; - if("telesci_warnings") - return global.telesci_warnings; - if("ANTIGENS") - return global.ANTIGENS; - if("disease2_list") - return global.disease2_list; - if("virusDB") - return global.virusDB; - if("compatible_mobs") - return global.compatible_mobs; - if("buildmodeholders") - return global.buildmodeholders; - if("newscaster_standard_feeds") - return global.newscaster_standard_feeds; - if("announced_news_types") - return global.announced_news_types; - if("allfaxes") - return global.allfaxes; - if("alldepartments") - return global.alldepartments; - if("atmos_controllers") - return global.atmos_controllers; - if("sharing_lookup_table") - return global.sharing_lookup_table; - if("assigned") - return global.assigned; - if("created") - return global.created; - if("merged") - return global.merged; - if("invalid_zone") - return global.invalid_zone; - if("air_blocked") - return global.air_blocked; - if("zone_blocked") - return global.zone_blocked; - if("blocked") - return global.blocked; - if("mark") - return global.mark; - if("zas_settings") - return global.zas_settings; - if("contamination_overlay") - return global.contamination_overlay; - if("accessable_z_levels") - return global.accessable_z_levels; - if("shop_prices") - return global.shop_prices; - if("circuitboards") - return global.circuitboards; - if("circuitboard_prices") - return global.circuitboard_prices; - if("clothing") - return global.clothing; - if("clothing_prices") - return global.clothing_prices; - if("hive_pylons") - return global.hive_pylons; - if("sc_safecode1") - return global.sc_safecode1; - if("sc_safecode2") - return global.sc_safecode2; - if("sc_safecode3") - return global.sc_safecode3; - if("sc_safecode4") - return global.sc_safecode4; - if("sc_safecode5") - return global.sc_safecode5; - -/proc/writeglobal(which, newval) - switch(which) - if("map") - global.map=newval - if("masterdatumPool") - global.masterdatumPool=newval - if("pooledvariables") - global.pooledvariables=newval - if("prox_sensor_ignored_types") - global.prox_sensor_ignored_types=newval - if("ability_verbs") - global.ability_verbs=newval - if("sent_aliens_to_station") - global.sent_aliens_to_station=newval - if("account_hack_attempted") - global.account_hack_attempted=newval - if("spacevines_spawned") - global.spacevines_spawned=newval - if("sent_spiders_to_station") - global.sent_spiders_to_station=newval - if("exclude") - global.exclude=newval - if("_all_globals") - global._all_globals=newval - if("asset_cache") - global.asset_cache=newval - if("error_last_seen") - global.error_last_seen=newval - if("error_cooldown") - global.error_cooldown=newval - if("html_interfaces") - global.html_interfaces=newval - if("all_lighting_corners") - global.all_lighting_corners=newval - if("LIGHTING_CORNER_DIAGONAL") - global.LIGHTING_CORNER_DIAGONAL=newval - if("validartifactprojectiles") - global.validartifactprojectiles=newval - if("cargo_telepads") - global.cargo_telepads=newval - if("chatResources") - global.chatResources=newval - if("bicon_cache") - global.bicon_cache=newval - if("dview_mob") - global.dview_mob=newval - if("meteor_wave_delay") - global.meteor_wave_delay=newval - if("meteors_in_wave") - global.meteors_in_wave=newval - if("meteor_wave_active") - global.meteor_wave_active=newval - if("max_meteor_size") - global.max_meteor_size=newval - if("chosen_dir") - global.chosen_dir=newval - if("create_mob_html") - global.create_mob_html=newval - if("create_object_html") - global.create_object_html=newval - if("create_turf_html") - global.create_turf_html=newval - if("any") - global.any=newval - if("asset_cache_populated") - global.asset_cache_populated=newval - if("total_runtimes") - global.total_runtimes=newval - if("total_runtimes_skipped") - global.total_runtimes_skipped=newval - if("error_cache") - global.error_cache=newval - if("dummy_lighting_corner") - global.dummy_lighting_corner=newval - if("security_level") - global.security_level=newval - if("iconCache") - global.iconCache=newval - if("round_end_info") - global.round_end_info=newval - if("deadmins") - global.deadmins=newval - if("lockedvars") - global.lockedvars=newval - if("nevervars") - global.nevervars=newval - if("type_instances") - global.type_instances=newval - if("data_core") - global.data_core=newval - if("plmaster") - global.plmaster=newval - if("slmaster") - global.slmaster=newval - if("account_DBs") - global.account_DBs=newval - if("global_map") - global.global_map=newval - if("universe") - global.universe=newval - if("paper_tag_whitelist") - global.paper_tag_whitelist=newval - if("paper_blacklist") - global.paper_blacklist=newval - if("skipupdate") - global.skipupdate=newval - if("eventchance") - global.eventchance=newval - if("event") - global.event=newval - if("hadevent") - global.hadevent=newval - if("blobevent") - global.blobevent=newval - if("starticon") - global.starticon=newval - if("midicon") - global.midicon=newval - if("endicon") - global.endicon=newval - if("diary") - global.diary=newval - if("diaryofmeanpeople") - global.diaryofmeanpeople=newval - if("admin_diary") - global.admin_diary=newval - if("href_logfile") - global.href_logfile=newval - if("station_name") - global.station_name=newval - if("game_version") - global.game_version=newval - if("changelog_hash") - global.changelog_hash=newval - if("game_year") - global.game_year=newval - if("going") - global.going=newval - if("master_mode") - global.master_mode=newval - if("secret_force_mode") - global.secret_force_mode=newval - if("host") - global.host=newval - if("aliens_allowed") - global.aliens_allowed=newval - if("ooc_allowed") - global.ooc_allowed=newval - if("looc_allowed") - global.looc_allowed=newval - if("dooc_allowed") - global.dooc_allowed=newval - if("traitor_scaling") - global.traitor_scaling=newval - if("dna_ident") - global.dna_ident=newval - if("abandon_allowed") - global.abandon_allowed=newval - if("enter_allowed") - global.enter_allowed=newval - if("guests_allowed") - global.guests_allowed=newval - if("shuttle_frozen") - global.shuttle_frozen=newval - if("shuttle_left") - global.shuttle_left=newval - if("tinted_weldhelh") - global.tinted_weldhelh=newval - if("jobMax") - global.jobMax=newval - if("bombers") - global.bombers=newval - if("admin_log") - global.admin_log=newval - if("lawchanges") - global.lawchanges=newval - if("shuttles") - global.shuttles=newval - if("reg_dna") - global.reg_dna=newval - if("CELLRATE") - global.CELLRATE=newval - if("CHARGELEVEL") - global.CHARGELEVEL=newval - if("WORLD_X_OFFSET") - global.WORLD_X_OFFSET=newval - if("WORLD_Y_OFFSET") - global.WORLD_Y_OFFSET=newval - if("shuttle_z") - global.shuttle_z=newval - if("airtunnel_start") - global.airtunnel_start=newval - if("airtunnel_stop") - global.airtunnel_stop=newval - if("airtunnel_bottom") - global.airtunnel_bottom=newval - if("monkeystart") - global.monkeystart=newval - if("wizardstart") - global.wizardstart=newval - if("newplayer_start") - global.newplayer_start=newval - if("latejoin") - global.latejoin=newval - if("assistant_latejoin") - global.assistant_latejoin=newval - if("prisonwarp") - global.prisonwarp=newval - if("holdingfacility") - global.holdingfacility=newval - if("xeno_spawn") - global.xeno_spawn=newval - if("endgame_safespawns") - global.endgame_safespawns=newval - if("endgame_exits") - global.endgame_exits=newval - if("tdome1") - global.tdome1=newval - if("tdome2") - global.tdome2=newval - if("tdomeobserve") - global.tdomeobserve=newval - if("tdomeadmin") - global.tdomeadmin=newval - if("prisonsecuritywarp") - global.prisonsecuritywarp=newval - if("prisonwarped") - global.prisonwarped=newval - if("blobstart") - global.blobstart=newval - if("ninjastart") - global.ninjastart=newval - if("cardinal") - global.cardinal=newval - if("diagonal") - global.diagonal=newval - if("alldirs") - global.alldirs=newval - if("universal_cult_chat") - global.universal_cult_chat=newval - if("config") - global.config=newval - if("combatlog") - global.combatlog=newval - if("IClog") - global.IClog=newval - if("OOClog") - global.OOClog=newval - if("adminlog") - global.adminlog=newval - if("suspend_alert") - global.suspend_alert=newval - if("Debug") - global.Debug=newval - if("Debug2") - global.Debug2=newval - if("debugobj") - global.debugobj=newval - if("mods") - global.mods=newval - if("wavesecret") - global.wavesecret=newval - if("gravity_is_on") - global.gravity_is_on=newval - if("shuttlecoming") - global.shuttlecoming=newval - if("join_motd") - global.join_motd=newval - if("forceblob") - global.forceblob=newval - if("polarstar") - global.polarstar=newval - if("nanomanager") - global.nanomanager=newval - if("sqladdress") - global.sqladdress=newval - if("sqlport") - global.sqlport=newval - if("sqldb") - global.sqldb=newval - if("sqllogin") - global.sqllogin=newval - if("sqlpass") - global.sqlpass=newval - if("sqlfdbkdb") - global.sqlfdbkdb=newval - if("sqlfdbklogin") - global.sqlfdbklogin=newval - if("sqlfdbkpass") - global.sqlfdbkpass=newval - if("sqllogging") - global.sqllogging=newval - if("forumsqladdress") - global.forumsqladdress=newval - if("forumsqlport") - global.forumsqlport=newval - if("forumsqldb") - global.forumsqldb=newval - if("forumsqllogin") - global.forumsqllogin=newval - if("forumsqlpass") - global.forumsqlpass=newval - if("forum_activated_group") - global.forum_activated_group=newval - if("forum_authenticated_group") - global.forum_authenticated_group=newval - if("fileaccess_timer") - global.fileaccess_timer=newval - if("custom_event_msg") - global.custom_event_msg=newval - if("dbcon") - global.dbcon=newval - if("dbcon_old") - global.dbcon_old=newval - if("recall_time_limit") - global.recall_time_limit=newval - if("score") - global.score=newval - if("trash_items") - global.trash_items=newval - if("decals") - global.decals=newval - if("on_login") - global.on_login=newval - if("on_ban") - global.on_ban=newval - if("on_unban") - global.on_unban=newval - if("plugins") - global.plugins=newval - if("space_gas") - global.space_gas=newval - if("announcement_intercom") - global.announcement_intercom=newval - if("sortedAreas") - global.sortedAreas=newval - if("bomberman_mode") - global.bomberman_mode=newval - if("bomberman_hurt") - global.bomberman_hurt=newval - if("bomberman_destroy") - global.bomberman_destroy=newval - if("volunteer_gladiators") - global.volunteer_gladiators=newval - if("ready_gladiators") - global.ready_gladiators=newval - if("never_gladiators") - global.never_gladiators=newval - if("achievements") - global.achievements=newval - if("end_icons") - global.end_icons=newval - if("arena_leaderboard") - global.arena_leaderboard=newval - if("arena_rounds") - global.arena_rounds=newval - if("arena_top_score") - global.arena_top_score=newval - if("endgame_info_logged") - global.endgame_info_logged=newval - if("explosion_newmethod") - global.explosion_newmethod=newval - if("snake_station_highscores") - global.snake_station_highscores=newval - if("snake_best_players") - global.snake_best_players=newval - if("minesweeper_station_highscores") - global.minesweeper_station_highscores=newval - if("minesweeper_best_players") - global.minesweeper_best_players=newval - if("nanocoins_rates") - global.nanocoins_rates=newval - if("nanocoins_lastchange") - global.nanocoins_lastchange=newval - if("speciesinit") - global.speciesinit=newval - if("minimapinit") - global.minimapinit=newval - if("bees_species") - global.bees_species=newval - if("stat_collection") - global.stat_collection=newval - if("hardcore_mode") - global.hardcore_mode=newval - if("mineral_turfs") - global.mineral_turfs=newval - if("static_list") - global.static_list=newval - if("grayscale") - global.grayscale=newval - if("adminblob_icon") - global.adminblob_icon=newval - if("adminblob_size") - global.adminblob_size=newval - if("adminblob_beat") - global.adminblob_beat=newval - if("holoMiniMaps") - global.holoMiniMaps=newval - if("centcommMiniMaps") - global.centcommMiniMaps=newval - if("extraMiniMaps") - global.extraMiniMaps=newval - if("holomap_markers") - global.holomap_markers=newval - if("holomaps_initialized") - global.holomaps_initialized=newval - if("tachycardics") - global.tachycardics=newval - if("bradycardics") - global.bradycardics=newval - if("heartstopper") - global.heartstopper=newval - if("cheartstopper") - global.cheartstopper=newval - if("disable_scrubbers") - global.disable_scrubbers=newval - if("disable_vents") - global.disable_vents=newval - if("Space_Tile") - global.Space_Tile=newval - if("MAX_EXPLOSION_RANGE") - global.MAX_EXPLOSION_RANGE=newval - if("BODY_PARTS") - global.BODY_PARTS=newval - if("BODY_COVER_VALUE_LIST") - global.BODY_COVER_VALUE_LIST=newval - if("NOIRMATRIX") - global.NOIRMATRIX=newval - if("bad_changing_colour_ckeys") - global.bad_changing_colour_ckeys=newval - if("global_mutations") - global.global_mutations=newval - if("scarySounds") - global.scarySounds=newval - if("RESTRICTED_CAMERA_NETWORKS") - global.RESTRICTED_CAMERA_NETWORKS=newval - if("default_colour_matrix") - global.default_colour_matrix=newval - if("ai_names") - global.ai_names=newval - if("wizard_first") - global.wizard_first=newval - if("wizard_second") - global.wizard_second=newval - if("ninja_titles") - global.ninja_titles=newval - if("ninja_names") - global.ninja_names=newval - if("commando_names") - global.commando_names=newval - if("first_names_male") - global.first_names_male=newval - if("first_names_female") - global.first_names_female=newval - if("last_names") - global.last_names=newval - if("clown_names") - global.clown_names=newval - if("verbs") - global.verbs=newval - if("adjectives") - global.adjectives=newval - if("vox_name_syllables") - global.vox_name_syllables=newval - if("golem_names") - global.golem_names=newval - if("borer_names") - global.borer_names=newval - if("hologram_names") - global.hologram_names=newval - if("autoborg_silly_names") - global.autoborg_silly_names=newval - if("panicfile") - global.panicfile=newval - if("failed_db_connections") - global.failed_db_connections=newval - if("failed_old_db_connections") - global.failed_old_db_connections=newval - if("desire_ranks") - global.desire_ranks=newval - if("cmp_field") - global.cmp_field=newval - if("cmp_dist_origin") - global.cmp_dist_origin=newval - if("DummyCache") - global.DummyCache=newval - if("genders") - global.genders=newval - if("clients") - global.clients=newval - if("admins") - global.admins=newval - if("directory") - global.directory=newval - if("mixed_modes") - global.mixed_modes=newval - if("player_list") - global.player_list=newval - if("mob_list") - global.mob_list=newval - if("living_mob_list") - global.living_mob_list=newval - if("dead_mob_list") - global.dead_mob_list=newval - if("observers") - global.observers=newval - if("areas") - global.areas=newval - if("chemical_reactions_list") - global.chemical_reactions_list=newval - if("chemical_reagents_list") - global.chemical_reagents_list=newval - if("landmarks_list") - global.landmarks_list=newval - if("surgery_steps") - global.surgery_steps=newval - if("mechas_list") - global.mechas_list=newval - if("poster_designs") - global.poster_designs=newval - if("underwear_m") - global.underwear_m=newval - if("underwear_f") - global.underwear_f=newval - if("backbaglist") - global.backbaglist=newval - if("hit_appends") - global.hit_appends=newval - if("epilepsy_appends") - global.epilepsy_appends=newval - if("table_recipes") - global.table_recipes=newval - if("med_hud_users") - global.med_hud_users=newval - if("sec_hud_users") - global.sec_hud_users=newval - if("escape_list") - global.escape_list=newval - if("church_name") - global.church_name=newval - if("command_name") - global.command_name=newval - if("religion_name") - global.religion_name=newval - if("syndicate_name") - global.syndicate_name=newval - if("syndicate_code_phrase") - global.syndicate_code_phrase=newval - if("syndicate_code_response") - global.syndicate_code_response=newval - if("watt_suffixes") - global.watt_suffixes=newval - if("number_digits") - global.number_digits=newval - if("number_tens") - global.number_tens=newval - if("number_units") - global.number_units=newval - if("quote") - global.quote=newval - if("get_matching_types_cache") - global.get_matching_types_cache=newval - if("get_vars_from_type_cache") - global.get_vars_from_type_cache=newval - if("existing_typesof_cache") - global.existing_typesof_cache=newval - if("common_tools") - global.common_tools=newval - if("WALLITEMS") - global.WALLITEMS=newval - if("sortInstance") - global.sortInstance=newval - if("hooks") - global.hooks=newval - if("ventcrawl_machinery") - global.ventcrawl_machinery=newval - if("catcher") - global.catcher=newval - if("parallax_on_clients") - global.parallax_on_clients=newval - if("parallax_initialized") - global.parallax_initialized=newval - if("space_color") - global.space_color=newval - if("parallax_icon") - global.parallax_icon=newval - if("unstackable_pipes") - global.unstackable_pipes=newval - if("heat_pipes") - global.heat_pipes=newval - if("bent_dirs") - global.bent_dirs=newval - if("pipeID2State") - global.pipeID2State=newval - if("nlist") - global.nlist=newval - if("straight_pipes") - global.straight_pipes=newval - if("bent_pipes") - global.bent_pipes=newval - if("manifold_pipes") - global.manifold_pipes=newval - if("garbageCollector") - global.garbageCollector=newval - if("soft_dels") - global.soft_dels=newval - if("emergency_shuttle") - global.emergency_shuttle=newval - if("Failsafe") - global.Failsafe=newval - if("Master") - global.Master=newval - if("MC_restart_clear") - global.MC_restart_clear=newval - if("MC_restart_timeout") - global.MC_restart_timeout=newval - if("MC_restart_count") - global.MC_restart_count=newval - if("CURRENT_TICKLIMIT") - global.CURRENT_TICKLIMIT=newval - if("SSair") - global.SSair=newval - if("tick_multiplier") - global.tick_multiplier=newval - if("SSdisease") - global.SSdisease=newval - if("active_diseases") - global.active_diseases=newval - if("SSemergency_shuttle") - global.SSemergency_shuttle=newval - if("SSevent") - global.SSevent=newval - if("events") - global.events=newval - if("SSfast_machinery") - global.SSfast_machinery=newval - if("fast_machines") - global.fast_machines=newval - if("SSgarbage") - global.SSgarbage=newval - if("SShtml_ui") - global.SShtml_ui=newval - if("html_machines") - global.html_machines=newval - if("SSinactivity") - global.SSinactivity=newval - if("SSlighting") - global.SSlighting=newval - if("lighting_update_lights") - global.lighting_update_lights=newval - if("lighting_update_corners") - global.lighting_update_corners=newval - if("lighting_update_overlays") - global.lighting_update_overlays=newval - if("SSmachinery") - global.SSmachinery=newval - if("machines") - global.machines=newval - if("SSmob") - global.SSmob=newval - if("SSnano") - global.SSnano=newval - if("SSobj") - global.SSobj=newval - if("processing_objects") - global.processing_objects=newval - if("SSpipenet") - global.SSpipenet=newval - if("atmos_machines") - global.atmos_machines=newval - if("pipe_networks") - global.pipe_networks=newval - if("on_pipenet_tick") - global.on_pipenet_tick=newval - if("SSpower") - global.SSpower=newval - if("power_machines") - global.power_machines=newval - if("powernets") - global.powernets=newval - if("cable_list") - global.cable_list=newval - if("SSsun") - global.SSsun=newval - if("SSsupply_shuttle") - global.SSsupply_shuttle=newval - if("SSticker") - global.SSticker=newval - if("SSvote") - global.SSvote=newval - if("SSassets") - global.SSassets=newval - if("SSfinish") - global.SSfinish=newval - if("SSgenetics") - global.SSgenetics=newval - if("SSjob") - global.SSjob=newval - if("SSmap") - global.SSmap=newval - if("SSminimap") - global.SSminimap=newval - if("SSmore_init") - global.SSmore_init=newval - if("SSrust") - global.SSrust=newval - if("SScreate_ticker") - global.SScreate_ticker=newval - if("SSxenoarch") - global.SSxenoarch=newval - if("randomize_laws") - global.randomize_laws=newval - if("base_law_type") - global.base_law_type=newval - if("mommi_base_law_type") - global.mommi_base_law_type=newval - if("diseases") - global.diseases=newval - if("map_elements") - global.map_elements=newval - if("modules") - global.modules=newval - if("sun") - global.sun=newval - if("all_supply_groups") - global.all_supply_groups=newval - if("uplink_items") - global.uplink_items=newval - if("archive_diseases") - global.archive_diseases=newval - if("advance_cures") - global.advance_cures=newval - if("list_symptoms") - global.list_symptoms=newval - if("dictionary_symptoms") - global.dictionary_symptoms=newval - if("animal_butchering_products") - global.animal_butchering_products=newval - if("revdata") - global.revdata=newval - if("same_wires") - global.same_wires=newval - if("wireColours") - global.wireColours=newval - if("PDA_Manifest") - global.PDA_Manifest=newval - if("vox_sounds") - global.vox_sounds=newval - if("vox_wordlen") - global.vox_wordlen=newval - if("outbreak_level_words") - global.outbreak_level_words=newval - if("spawned_surprises") - global.spawned_surprises=newval - if("max_secret_rooms") - global.max_secret_rooms=newval - if("del_profiling") - global.del_profiling=newval - if("gdel_profiling") - global.gdel_profiling=newval - if("ghdel_profiling") - global.ghdel_profiling=newval - if("current_centcomm_order_id") - global.current_centcomm_order_id=newval - if("all_radios") - global.all_radios=newval - if("radiochannels") - global.radiochannels=newval - if("radiochannelsreverse") - global.radiochannelsreverse=newval - if("CENT_FREQS") - global.CENT_FREQS=newval - if("radio_controller") - global.radio_controller=newval - if("pointers") - global.pointers=newval - if("nextDecTalkDelay") - global.nextDecTalkDelay=newval - if("lastDecTalkUse") - global.lastDecTalkUse=newval - if("freqtospan") - global.freqtospan=newval - if("freqtoname") - global.freqtoname=newval - if("ghostimg") - global.ghostimg=newval - if("resethearers") - global.resethearers=newval - if("smoothable_unsims") - global.smoothable_unsims=newval - if("shatter_sound") - global.shatter_sound=newval - if("explosion_sound") - global.explosion_sound=newval - if("small_explosion_sound") - global.small_explosion_sound=newval - if("spark_sound") - global.spark_sound=newval - if("rustle_sound") - global.rustle_sound=newval - if("punch_sound") - global.punch_sound=newval - if("clown_sound") - global.clown_sound=newval - if("swing_hit_sound") - global.swing_hit_sound=newval - if("hiss_sound") - global.hiss_sound=newval - if("page_sound") - global.page_sound=newval - if("mechstep_sound") - global.mechstep_sound=newval - if("gib_sound") - global.gib_sound=newval - if("mommicomment_sound") - global.mommicomment_sound=newval - if("polaroid_sound") - global.polaroid_sound=newval - if("male_scream_sound") - global.male_scream_sound=newval - if("female_scream_sound") - global.female_scream_sound=newval - if("male_cough_sound") - global.male_cough_sound=newval - if("female_cough_sound") - global.female_cough_sound=newval - if("lightning_sound") - global.lightning_sound=newval - if("soulstone_sound") - global.soulstone_sound=newval - if("fracture_sound") - global.fracture_sound=newval - if("machete_hit_sound") - global.machete_hit_sound=newval - if("machete_throw_sound") - global.machete_throw_sound=newval - if("machete_throw_hit_sound") - global.machete_throw_hit_sound=newval - if("supply_shuttle") - global.supply_shuttle=newval - if("space_area") - global.space_area=newval - if("ignored_keys") - global.ignored_keys=newval - if("moved_landmarks") - global.moved_landmarks=newval - if("transparent_icons") - global.transparent_icons=newval - if("teleportlocs") - global.teleportlocs=newval - if("ghostteleportlocs") - global.ghostteleportlocs=newval - if("adminbusteleportlocs") - global.adminbusteleportlocs=newval - if("centcom_areas") - global.centcom_areas=newval - if("the_station_areas") - global.the_station_areas=newval - if("dna_activity_bounds") - global.dna_activity_bounds=newval - if("assigned_gene_blocks") - global.assigned_gene_blocks=newval - if("assigned_blocks") - global.assigned_blocks=newval - if("dna_genes") - global.dna_genes=newval - if("good_blocks") - global.good_blocks=newval - if("bad_blocks") - global.bad_blocks=newval - if("skin_styles_female_list") - global.skin_styles_female_list=newval - if("hair_styles_list") - global.hair_styles_list=newval - if("hair_styles_male_list") - global.hair_styles_male_list=newval - if("hair_styles_female_list") - global.hair_styles_female_list=newval - if("facial_hair_styles_list") - global.facial_hair_styles_list=newval - if("facial_hair_styles_male_list") - global.facial_hair_styles_male_list=newval - if("facial_hair_styles_female_list") - global.facial_hair_styles_female_list=newval - if("noir_master") - global.noir_master=newval - if("ticker") - global.ticker=newval - if("potential_theft_objectives") - global.potential_theft_objectives=newval - if("BLINDBLOCK") - global.BLINDBLOCK=newval - if("DEAFBLOCK") - global.DEAFBLOCK=newval - if("HULKBLOCK") - global.HULKBLOCK=newval - if("TELEBLOCK") - global.TELEBLOCK=newval - if("FIREBLOCK") - global.FIREBLOCK=newval - if("XRAYBLOCK") - global.XRAYBLOCK=newval - if("CLUMSYBLOCK") - global.CLUMSYBLOCK=newval - if("FAKEBLOCK") - global.FAKEBLOCK=newval - if("COUGHBLOCK") - global.COUGHBLOCK=newval - if("GLASSESBLOCK") - global.GLASSESBLOCK=newval - if("EPILEPSYBLOCK") - global.EPILEPSYBLOCK=newval - if("TWITCHBLOCK") - global.TWITCHBLOCK=newval - if("NERVOUSBLOCK") - global.NERVOUSBLOCK=newval - if("MONKEYBLOCK") - global.MONKEYBLOCK=newval - if("BLOCKADD") - global.BLOCKADD=newval - if("DIFFMUT") - global.DIFFMUT=newval - if("HEADACHEBLOCK") - global.HEADACHEBLOCK=newval - if("NOBREATHBLOCK") - global.NOBREATHBLOCK=newval - if("REMOTEVIEWBLOCK") - global.REMOTEVIEWBLOCK=newval - if("REGENERATEBLOCK") - global.REGENERATEBLOCK=newval - if("INCREASERUNBLOCK") - global.INCREASERUNBLOCK=newval - if("REMOTETALKBLOCK") - global.REMOTETALKBLOCK=newval - if("MORPHBLOCK") - global.MORPHBLOCK=newval - if("COLDBLOCK") - global.COLDBLOCK=newval - if("HALLUCINATIONBLOCK") - global.HALLUCINATIONBLOCK=newval - if("NOPRINTSBLOCK") - global.NOPRINTSBLOCK=newval - if("SHOCKIMMUNITYBLOCK") - global.SHOCKIMMUNITYBLOCK=newval - if("SMALLSIZEBLOCK") - global.SMALLSIZEBLOCK=newval - if("LISPBLOCK") - global.LISPBLOCK=newval - if("MUTEBLOCK") - global.MUTEBLOCK=newval - if("RADBLOCK") - global.RADBLOCK=newval - if("FATBLOCK") - global.FATBLOCK=newval - if("CHAVBLOCK") - global.CHAVBLOCK=newval - if("SWEDEBLOCK") - global.SWEDEBLOCK=newval - if("SCRAMBLEBLOCK") - global.SCRAMBLEBLOCK=newval - if("TOXICFARTBLOCK") - global.TOXICFARTBLOCK=newval - if("STRONGBLOCK") - global.STRONGBLOCK=newval - if("HORNSBLOCK") - global.HORNSBLOCK=newval - if("SMILEBLOCK") - global.SMILEBLOCK=newval - if("ELVISBLOCK") - global.ELVISBLOCK=newval - if("SOBERBLOCK") - global.SOBERBLOCK=newval - if("PSYRESISTBLOCK") - global.PSYRESISTBLOCK=newval - if("FARSIGHTBLOCK") - global.FARSIGHTBLOCK=newval - if("CHAMELEONBLOCK") - global.CHAMELEONBLOCK=newval - if("CRYOBLOCK") - global.CRYOBLOCK=newval - if("EATBLOCK") - global.EATBLOCK=newval - if("JUMPBLOCK") - global.JUMPBLOCK=newval - if("MELTBLOCK") - global.MELTBLOCK=newval - if("EMPATHBLOCK") - global.EMPATHBLOCK=newval - if("SUPERFARTBLOCK") - global.SUPERFARTBLOCK=newval - if("IMMOLATEBLOCK") - global.IMMOLATEBLOCK=newval - if("POLYMORPHBLOCK") - global.POLYMORPHBLOCK=newval - if("LOUDBLOCK") - global.LOUDBLOCK=newval - if("WHISPERBLOCK") - global.WHISPERBLOCK=newval - if("DIZZYBLOCK") - global.DIZZYBLOCK=newval - if("SANSBLOCK") - global.SANSBLOCK=newval - if("NOIRBLOCK") - global.NOIRBLOCK=newval - if("blobs") - global.blobs=newval - if("blob_cores") - global.blob_cores=newval - if("blob_nodes") - global.blob_nodes=newval - if("blob_resources") - global.blob_resources=newval - if("blob_overminds") - global.blob_overminds=newval - if("blob_looks_admin") - global.blob_looks_admin=newval - if("blob_looks_player") - global.blob_looks_player=newval - if("narsie_behaviour") - global.narsie_behaviour=newval - if("narsie_cometh") - global.narsie_cometh=newval - if("narsie_list") - global.narsie_list=newval - if("mr_clean_targets") - global.mr_clean_targets=newval - if("cultwords") - global.cultwords=newval - if("rune_list") - global.rune_list=newval - if("halloween_spawns") - global.halloween_spawns=newval - if("snow_recipes") - global.snow_recipes=newval - if("snowsound") - global.snowsound=newval - if("Holiday") - global.Holiday=newval - if("blob_candidates") - global.blob_candidates=newval - if("bomb_set") - global.bomb_set=newval - if("nukedisk") - global.nukedisk=newval - if("hsboxspawn") - global.hsboxspawn=newval - if("hrefs") - global.hrefs=newval - if("banned_sandbox_types") - global.banned_sandbox_types=newval - if("all_jobs") - global.all_jobs=newval - if("job_master") - global.job_master=newval - if("assistant_occupations") - global.assistant_occupations=newval - if("command_positions") - global.command_positions=newval - if("engineering_positions") - global.engineering_positions=newval - if("medical_positions") - global.medical_positions=newval - if("science_positions") - global.science_positions=newval - if("civilian_positions") - global.civilian_positions=newval - if("cargo_positions") - global.cargo_positions=newval - if("security_positions") - global.security_positions=newval - if("nonhuman_positions") - global.nonhuman_positions=newval - if("misc_positions") - global.misc_positions=newval - if("whitelist") - global.whitelist=newval - if("alien_whitelist") - global.alien_whitelist=newval - if("firealarms") - global.firealarms=newval - if("cryo_health_indicator") - global.cryo_health_indicator=newval - if("doppler_arrays") - global.doppler_arrays=newval - if("flashers") - global.flashers=newval - if("holosigns") - global.holosigns=newval - if("igniters") - global.igniters=newval - if("multitool_var_whitelist") - global.multitool_var_whitelist=newval - if("mass_drivers") - global.mass_drivers=newval - if("navbeacons") - global.navbeacons=newval - if("news_network") - global.news_network=newval - if("allCasters") - global.allCasters=newval - if("req_console_assistance") - global.req_console_assistance=newval - if("req_console_supplies") - global.req_console_supplies=newval - if("req_console_information") - global.req_console_information=newval - if("allConsoles") - global.allConsoles=newval - if("station_holomaps") - global.station_holomaps=newval - if("status_displays") - global.status_displays=newval - if("ai_emotions") - global.ai_emotions=newval - if("status_display_images") - global.status_display_images=newval - if("dispenser_presets") - global.dispenser_presets=newval - if("num_vending_terminals") - global.num_vending_terminals=newval - if("floorbot_targets") - global.floorbot_targets=newval - if("mulebot_count") - global.mulebot_count=newval - if("camera_names") - global.camera_names=newval - if("camera_messages") - global.camera_messages=newval - if("tv_monitors") - global.tv_monitors=newval - if("shuttle_calls") - global.shuttle_calls=newval - if("prison_shuttle_moving_to_station") - global.prison_shuttle_moving_to_station=newval - if("prison_shuttle_moving_to_prison") - global.prison_shuttle_moving_to_prison=newval - if("prison_shuttle_at_station") - global.prison_shuttle_at_station=newval - if("prison_shuttle_can_send") - global.prison_shuttle_can_send=newval - if("prison_shuttle_time") - global.prison_shuttle_time=newval - if("prison_shuttle_timeleft") - global.prison_shuttle_timeleft=newval - if("specops_shuttle_moving_to_station") - global.specops_shuttle_moving_to_station=newval - if("specops_shuttle_moving_to_centcom") - global.specops_shuttle_moving_to_centcom=newval - if("specops_shuttle_at_station") - global.specops_shuttle_at_station=newval - if("specops_shuttle_can_send") - global.specops_shuttle_can_send=newval - if("specops_shuttle_time") - global.specops_shuttle_time=newval - if("specops_shuttle_timeleft") - global.specops_shuttle_timeleft=newval - if("syndicate_elite_shuttle_moving_to_station") - global.syndicate_elite_shuttle_moving_to_station=newval - if("syndicate_elite_shuttle_moving_to_mothership") - global.syndicate_elite_shuttle_moving_to_mothership=newval - if("syndicate_elite_shuttle_at_station") - global.syndicate_elite_shuttle_at_station=newval - if("syndicate_elite_shuttle_can_send") - global.syndicate_elite_shuttle_can_send=newval - if("syndicate_elite_shuttle_time") - global.syndicate_elite_shuttle_time=newval - if("syndicate_elite_shuttle_timeleft") - global.syndicate_elite_shuttle_timeleft=newval - if("taxi_computers") - global.taxi_computers=newval - if("all_doors") - global.all_doors=newval - if("alert_overlays_global") - global.alert_overlays_global=newval - if("poddoors") - global.poddoors=newval - if("recentmessages") - global.recentmessages=newval - if("message_delay") - global.message_delay=newval - if("telecomms_list") - global.telecomms_list=newval - if("uristrune_cache") - global.uristrune_cache=newval - if("explosion_shake_message_cooldown") - global.explosion_shake_message_cooldown=newval - if("explosion_turfs") - global.explosion_turfs=newval - if("explosion_in_progress") - global.explosion_in_progress=newval - if("blood_overlays") - global.blood_overlays=newval - if("reagents_to_log") - global.reagents_to_log=newval - if("BUMP_TELEPORTERS") - global.BUMP_TELEPORTERS=newval - if("portal_cache") - global.portal_cache=newval - if("splatter_cache") - global.splatter_cache=newval - if("blood_list") - global.blood_list=newval - if("fluidtrack_cache") - global.fluidtrack_cache=newval - if("beacons") - global.beacons=newval - if("all_graffitis") - global.all_graffitis=newval - if("living_balloons") - global.living_balloons=newval - if("deskbell_default_frequencies") - global.deskbell_default_frequencies=newval - if("deskbell_freq_cargo") - global.deskbell_freq_cargo=newval - if("deskbell_freq_hop") - global.deskbell_freq_hop=newval - if("deskbell_freq_medbay") - global.deskbell_freq_medbay=newval - if("deskbell_freq_brig") - global.deskbell_freq_brig=newval - if("deskbell_freq_rnd") - global.deskbell_freq_rnd=newval - if("camera_bugs") - global.camera_bugs=newval - if("pda_app_menus") - global.pda_app_menus=newval - if("chatrooms") - global.chatrooms=newval - if("PDAs") - global.PDAs=newval - if("available_paintings") - global.available_paintings=newval - if("cable_recipes") - global.cable_recipes=newval - if("metal_recipes") - global.metal_recipes=newval - if("plasteel_recipes") - global.plasteel_recipes=newval - if("wood_recipes") - global.wood_recipes=newval - if("cardboard_recipes") - global.cardboard_recipes=newval - if("leather_recipes") - global.leather_recipes=newval - if("sandstone_recipes") - global.sandstone_recipes=newval - if("diamond_recipes") - global.diamond_recipes=newval - if("uranium_recipes") - global.uranium_recipes=newval - if("plasma_recipes") - global.plasma_recipes=newval - if("plastic_recipes") - global.plastic_recipes=newval - if("gold_recipes") - global.gold_recipes=newval - if("phazon_recipes") - global.phazon_recipes=newval - if("silver_recipes") - global.silver_recipes=newval - if("clown_recipes") - global.clown_recipes=newval - if("charcoal_recipes") - global.charcoal_recipes=newval - if("lightfloor_colors") - global.lightfloor_colors=newval - if("moneytypes") - global.moneytypes=newval - if("cached_icons") - global.cached_icons=newval - if("tracking_implants") - global.tracking_implants=newval - if("bottle_colour_choices") - global.bottle_colour_choices=newval - if("hidden_doors") - global.hidden_doors=newval - if("all_docking_ports") - global.all_docking_ports=newval - if("ladders") - global.ladders=newval - if("one_way_windows") - global.one_way_windows=newval - if("cargo_shuttle") - global.cargo_shuttle=newval - if("escape_shuttle") - global.escape_shuttle=newval - if("mining_shuttle") - global.mining_shuttle=newval - if("arrival_shuttle") - global.arrival_shuttle=newval - if("transport_shuttle") - global.transport_shuttle=newval - if("ert_shuttle") - global.ert_shuttle=newval - if("deathsquad_shuttle") - global.deathsquad_shuttle=newval - if("elite_syndie_shuttle") - global.elite_syndie_shuttle=newval - if("strike_team_shuttle") - global.strike_team_shuttle=newval - if("admin_shuttle") - global.admin_shuttle=newval - if("research_shuttle") - global.research_shuttle=newval - if("salvage_shuttle") - global.salvage_shuttle=newval - if("security_shuttle") - global.security_shuttle=newval - if("syndicate_shuttle") - global.syndicate_shuttle=newval - if("taxi_a") - global.taxi_a=newval - if("taxi_b") - global.taxi_b=newval - if("trade_shuttle") - global.trade_shuttle=newval - if("vox_shuttle") - global.vox_shuttle=newval - if("voxresearch_shuttle") - global.voxresearch_shuttle=newval - if("response_team_members") - global.response_team_members=newval - if("distributed_ert_suits") - global.distributed_ert_suits=newval - if("sent_strike_teams") - global.sent_strike_teams=newval - if("icons_to_ignore_at_floor_init") - global.icons_to_ignore_at_floor_init=newval - if("plating_icons") - global.plating_icons=newval - if("wood_icons") - global.wood_icons=newval - if("_flatIcons") - global._flatIcons=newval - if("directional") - global.directional=newval - if("exception") - global.exception=newval - if("directional_turfs") - global.directional_turfs=newval - if("BSACooldown") - global.BSACooldown=newval - if("floorIsLava") - global.floorIsLava=newval - if("admin_shuttle_location") - global.admin_shuttle_location=newval - if("alien_ship_location") - global.alien_ship_location=newval - if("investigations") - global.investigations=newval - if("admin_ranks") - global.admin_ranks=newval - if("admin_verbs_default") - global.admin_verbs_default=newval - if("admin_verbs_admin") - global.admin_verbs_admin=newval - if("admin_verbs_ban") - global.admin_verbs_ban=newval - if("admin_verbs_sounds") - global.admin_verbs_sounds=newval - if("admin_verbs_fun") - global.admin_verbs_fun=newval - if("admin_verbs_spawn") - global.admin_verbs_spawn=newval - if("admin_verbs_server") - global.admin_verbs_server=newval - if("admin_verbs_debug") - global.admin_verbs_debug=newval - if("admin_verbs_possess") - global.admin_verbs_possess=newval - if("admin_verbs_permissions") - global.admin_verbs_permissions=newval - if("admin_verbs_rejuv") - global.admin_verbs_rejuv=newval - if("admin_verbs_polling") - global.admin_verbs_polling=newval - if("admin_verbs_hideable") - global.admin_verbs_hideable=newval - if("admin_verbs_mod") - global.admin_verbs_mod=newval - if("appearanceban_runonce") - global.appearanceban_runonce=newval - if("appearance_keylist") - global.appearance_keylist=newval - if("jobban_runonce") - global.jobban_runonce=newval - if("jobban_keylist") - global.jobban_keylist=newval - if("oocban_keylist") - global.oocban_keylist=newval - if("admin_datums") - global.admin_datums=newval - if("CMinutes") - global.CMinutes=newval - if("Banlist") - global.Banlist=newval - if("Banlistjob") - global.Banlistjob=newval - if("adminhelp_ignored_words") - global.adminhelp_ignored_words=newval - if("checked_for_inactives") - global.checked_for_inactives=newval - if("inactive_keys") - global.inactive_keys=newval - if("blood_virus_spreading_disabled") - global.blood_virus_spreading_disabled=newval - if("camera_range_display_status") - global.camera_range_display_status=newval - if("intercom_range_display_status") - global.intercom_range_display_status=newval - if("prevent_airgroup_regroup") - global.prevent_airgroup_regroup=newval - if("say_disabled") - global.say_disabled=newval - if("movement_disabled") - global.movement_disabled=newval - if("movement_disabled_exception") - global.movement_disabled_exception=newval - if("forbidden_varedit_object_types") - global.forbidden_varedit_object_types=newval - if("PROFILING_VERBS") - global.PROFILING_VERBS=newval - if("vox_tick") - global.vox_tick=newval - if("assembly_short_name_to_type") - global.assembly_short_name_to_type=newval - if("comparison_circuit_operations") - global.comparison_circuit_operations=newval - if("math_circuit_operations_list") - global.math_circuit_operations_list=newval - if("automation_types") - global.automation_types=newval - if("gas_labels") - global.gas_labels=newval - if("existing_away_missions") - global.existing_away_missions=newval - if("awaydestinations") - global.awaydestinations=newval - if("away_mission_subtypes") - global.away_mission_subtypes=newval - if("gateways") - global.gateways=newval - if("maploader") - global.maploader=newval - if("_preloader") - global._preloader=newval - if("map_dimension_cache") - global.map_dimension_cache=newval - if("swapmaps_iconcache") - global.swapmaps_iconcache=newval - if("swapmaps_mode") - global.swapmaps_mode=newval - if("swapmaps_compiled_maxx") - global.swapmaps_compiled_maxx=newval - if("swapmaps_compiled_maxy") - global.swapmaps_compiled_maxy=newval - if("swapmaps_compiled_maxz") - global.swapmaps_compiled_maxz=newval - if("swapmaps_initialized") - global.swapmaps_initialized=newval - if("swapmaps_loaded") - global.swapmaps_loaded=newval - if("swapmaps_byname") - global.swapmaps_byname=newval - if("bombermangear") - global.bombermangear=newval - if("arenas") - global.arenas=newval - if("arena_spawnpoints") - global.arena_spawnpoints=newval - if("person_animation_viewers") - global.person_animation_viewers=newval - if("item_animation_viewers") - global.item_animation_viewers=newval - if("preferences_datums") - global.preferences_datums=newval - if("special_roles") - global.special_roles=newval - if("antag_roles") - global.antag_roles=newval - if("nonantag_roles") - global.nonantag_roles=newval - if("role_wiki") - global.role_wiki=newval - if("opposite_dirs") - global.opposite_dirs=newval - if("holomap_chips") - global.holomap_chips=newval - if("holomap_cache") - global.holomap_cache=newval - if("has_been_shade") - global.has_been_shade=newval - if("current_date_string") - global.current_date_string=newval - if("num_financial_terminals") - global.num_financial_terminals=newval - if("num_financial_database") - global.num_financial_database=newval - if("num_vending_machines") - global.num_vending_machines=newval - if("num_pda_terminals") - global.num_pda_terminals=newval - if("num_merch_computers") - global.num_merch_computers=newval - if("station_account") - global.station_account=newval - if("department_accounts") - global.department_accounts=newval - if("next_account_number") - global.next_account_number=newval - if("centcomm_account_db") - global.centcomm_account_db=newval - if("vendor_account") - global.vendor_account=newval - if("all_money_accounts") - global.all_money_accounts=newval - if("setup_economy") - global.setup_economy=newval - if("weighted_randomevent_locations") - global.weighted_randomevent_locations=newval - if("weighted_mundaneevent_locations") - global.weighted_mundaneevent_locations=newval - if("station_departments") - global.station_departments=newval - if("current_pos_id") - global.current_pos_id=newval - if("pos_sales") - global.pos_sales=newval - if("wages_enabled") - global.wages_enabled=newval - if("roundstart_enable_wages") - global.roundstart_enable_wages=newval - if("event_last_fired") - global.event_last_fired=newval - if("allEvents") - global.allEvents=newval - if("potentialRandomEvents") - global.potentialRandomEvents=newval - if("eventTimeLower") - global.eventTimeLower=newval - if("eventTimeUpper") - global.eventTimeUpper=newval - if("scheduledEvent") - global.scheduledEvent=newval - if("thing_storm_types") - global.thing_storm_types=newval - if("watchdog") - global.watchdog=newval - if("non_fakeattack_weapons") - global.non_fakeattack_weapons=newval - if("deepFriedEverything") - global.deepFriedEverything=newval - if("deepFriedNutriment") - global.deepFriedNutriment=newval - if("foodNesting") - global.foodNesting=newval - if("recursiveFood") - global.recursiveFood=newval - if("ingredientLimit") - global.ingredientLimit=newval - if("wizard_cards_rare") - global.wizard_cards_rare=newval - if("wizard_cards_normal") - global.wizard_cards_normal=newval - if("adv_camera") - global.adv_camera=newval - if("crewmonitor") - global.crewmonitor=newval - if("vote") - global.vote=newval - if("plant_controller") - global.plant_controller=newval - if("seed_types") - global.seed_types=newval - if("gene_tag_masks") - global.gene_tag_masks=newval - if("library_catalog") - global.library_catalog=newval - if("library_section_names") - global.library_section_names=newval - if("liquid_delay") - global.liquid_delay=newval - if("puddles") - global.puddles=newval - if("global_playlists") - global.global_playlists=newval - if("loopModeNames") - global.loopModeNames=newval - if("media_receivers") - global.media_receivers=newval - if("media_transmitters") - global.media_transmitters=newval - if("migration_controller_mysql") - global.migration_controller_mysql=newval - if("migration_controller_sqlite") - global.migration_controller_sqlite=newval - if("valid_abandoned_crate_types") - global.valid_abandoned_crate_types=newval - if("material_list") - global.material_list=newval - if("initial_materials") - global.initial_materials=newval - if("name_to_mineral") - global.name_to_mineral=newval - if("mining_surprises") - global.mining_surprises=newval - if("slot_equipment_priority") - global.slot_equipment_priority=newval - if("intents") - global.intents=newval - if("boo_phrases") - global.boo_phrases=newval - if("boo_phrases_drugs") - global.boo_phrases_drugs=newval - if("boo_phrases_silicon") - global.boo_phrases_silicon=newval - if("virtualhearers") - global.virtualhearers=newval - if("movable_hearers") - global.movable_hearers=newval - if("mob_hearers") - global.mob_hearers=newval - if("stationary_hearers") - global.stationary_hearers=newval - if("coldwarning_light") - global.coldwarning_light=newval - if("coldwarning_hard") - global.coldwarning_hard=newval - if("department_radio_keys") - global.department_radio_keys=newval - if("language_keys") - global.language_keys=newval - if("all_languages") - global.all_languages=newval - if("all_species") - global.all_species=newval - if("whitelisted_species") - global.whitelisted_species=newval - if("has_died_as_golem") - global.has_died_as_golem=newval - if("unconscious_overlays") - global.unconscious_overlays=newval - if("oxyloss_overlays") - global.oxyloss_overlays=newval - if("brutefireloss_overlays") - global.brutefireloss_overlays=newval - if("organ_damage_overlays") - global.organ_damage_overlays=newval - if("damage_icon_parts") - global.damage_icon_parts=newval - if("cover_protection_value_list") - global.cover_protection_value_list=newval - if("ai_list") - global.ai_list=newval - if("announcing_vox") - global.announcing_vox=newval - if("vox_digits") - global.vox_digits=newval - if("vox_tens") - global.vox_tens=newval - if("vox_units") - global.vox_units=newval - if("cameranet") - global.cameranet=newval - if("paiController") - global.paiController=newval - if("borer_chem_types_head") - global.borer_chem_types_head=newval - if("borer_chem_types_chest") - global.borer_chem_types_chest=newval - if("borer_chem_types_arm") - global.borer_chem_types_arm=newval - if("borer_chem_types_leg") - global.borer_chem_types_leg=newval - if("borer_unlock_types_head") - global.borer_unlock_types_head=newval - if("borer_unlock_types_chest") - global.borer_unlock_types_chest=newval - if("borer_unlock_types_arm") - global.borer_unlock_types_arm=newval - if("borer_unlock_types_leg") - global.borer_unlock_types_leg=newval - if("animal_count") - global.animal_count=newval - if("wizard_snakes") - global.wizard_snakes=newval - if("nest_locations") - global.nest_locations=newval - if("bad_gremlin_items") - global.bad_gremlin_items=newval - if("crate_mimic_disguises") - global.crate_mimic_disguises=newval - if("item_mimic_disguises") - global.item_mimic_disguises=newval - if("protected_objects") - global.protected_objects=newval - if("spider_queens") - global.spider_queens=newval - if("photocollector_list") - global.photocollector_list=newval - if("prism_list") - global.prism_list=newval - if("mirror_list") - global.mirror_list=newval - if("paper_folding_results") - global.paper_folding_results=newval - if("paperwork") - global.paperwork=newval - if("paperwork_library") - global.paperwork_library=newval - if("battery_charge") - global.battery_charge=newval - if("battery_charging") - global.battery_charging=newval - if("battery_online") - global.battery_online=newval - if("alllights") - global.alllights=newval - if("powernets_broke") - global.powernets_broke=newval - if("smes_list") - global.smes_list=newval - if("solars_list") - global.solars_list=newval - if("rad_collectors") - global.rad_collectors=newval - if("field_gen_list") - global.field_gen_list=newval - if("bullet_master") - global.bullet_master=newval - if("impact_master") - global.impact_master=newval - if("available_staff_transforms") - global.available_staff_transforms=newval - if("beam_master") - global.beam_master=newval - if("existing_dungeons") - global.existing_dungeons=newval - if("dungeon_area") - global.dungeon_area=newval - if("existing_vaults") - global.existing_vaults=newval - if("disposalpipeID2State") - global.disposalpipeID2State=newval - if("paint_variants") - global.paint_variants=newval - if("chifir_doesnt_remove") - global.chifir_doesnt_remove=newval - if("tonio_doesnt_remove") - global.tonio_doesnt_remove=newval - if("LOGGED_SPLASH_REAGENTS") - global.LOGGED_SPLASH_REAGENTS=newval - if("pillIcon2Name") - global.pillIcon2Name=newval - if("juice_items") - global.juice_items=newval - if("bomb_like_items") - global.bomb_like_items=newval - if("special_fruits") - global.special_fruits=newval - if("valid_random_food_types") - global.valid_random_food_types=newval - if("cockroach_egg_amount") - global.cockroach_egg_amount=newval - if("charcoal_doesnt_remove") - global.charcoal_doesnt_remove=newval - if("message_servers") - global.message_servers=newval - if("blackbox") - global.blackbox=newval - if("rnd_machines") - global.rnd_machines=newval - if("design_list") - global.design_list=newval - if("tech_list") - global.tech_list=newval - if("hidden_tech") - global.hidden_tech=newval - if("responsive_carriers") - global.responsive_carriers=newval - if("finds_as_strings") - global.finds_as_strings=newval - if("authenticators") - global.authenticators=newval - if("maint_all_access") - global.maint_all_access=newval - if("spells") - global.spells=newval - if("falltempoverlays") - global.falltempoverlays=newval - if("doppelgangers") - global.doppelgangers=newval - if("centcomm_store") - global.centcomm_store=newval - if("GPS_list") - global.GPS_list=newval - if("SPS_list") - global.SPS_list=newval - if("telesci_warnings") - global.telesci_warnings=newval - if("ANTIGENS") - global.ANTIGENS=newval - if("disease2_list") - global.disease2_list=newval - if("virusDB") - global.virusDB=newval - if("compatible_mobs") - global.compatible_mobs=newval - if("buildmodeholders") - global.buildmodeholders=newval - if("newscaster_standard_feeds") - global.newscaster_standard_feeds=newval - if("announced_news_types") - global.announced_news_types=newval - if("allfaxes") - global.allfaxes=newval - if("alldepartments") - global.alldepartments=newval - if("atmos_controllers") - global.atmos_controllers=newval - if("sharing_lookup_table") - global.sharing_lookup_table=newval - if("assigned") - global.assigned=newval - if("created") - global.created=newval - if("merged") - global.merged=newval - if("invalid_zone") - global.invalid_zone=newval - if("air_blocked") - global.air_blocked=newval - if("zone_blocked") - global.zone_blocked=newval - if("blocked") - global.blocked=newval - if("mark") - global.mark=newval - if("zas_settings") - global.zas_settings=newval - if("contamination_overlay") - global.contamination_overlay=newval - if("accessable_z_levels") - global.accessable_z_levels=newval - if("shop_prices") - global.shop_prices=newval - if("circuitboards") - global.circuitboards=newval - if("circuitboard_prices") - global.circuitboard_prices=newval - if("clothing") - global.clothing=newval - if("clothing_prices") - global.clothing_prices=newval - if("hive_pylons") - global.hive_pylons=newval - if("sc_safecode1") - global.sc_safecode1=newval - if("sc_safecode2") - global.sc_safecode2=newval - if("sc_safecode3") - global.sc_safecode3=newval - if("sc_safecode4") - global.sc_safecode4=newval - if("sc_safecode5") - global.sc_safecode5=newval - -/var/list/_all_globals=list("map","masterdatumPool","pooledvariables","prox_sensor_ignored_types","ability_verbs","sent_aliens_to_station","account_hack_attempted","spacevines_spawned","sent_spiders_to_station","exclude","asset_cache","error_last_seen","error_cooldown","html_interfaces","all_lighting_corners","LIGHTING_CORNER_DIAGONAL","all_lighting_overlays","validartifactprojectiles","cargo_telepads","chatResources","bicon_cache","dview_mob","meteor_wave_delay","meteors_in_wave","meteor_wave_active","max_meteor_size","chosen_dir","create_mob_html","create_object_html","create_turf_html","any","asset_cache_populated","total_runtimes","total_runtimes_skipped","error_cache","dummy_lighting_corner","security_level","iconCache","round_end_info","deadmins","lockedvars","nevervars","type_instances","data_core","plmaster","slmaster","account_DBs","global_map","universe","paper_tag_whitelist","paper_blacklist","skipupdate","eventchance","event","hadevent","blobevent","starticon","midicon","endicon","diary","diaryofmeanpeople","admin_diary","href_logfile","station_name","game_version","changelog_hash","game_year","going","master_mode","secret_force_mode","host","aliens_allowed","ooc_allowed","looc_allowed","dooc_allowed","traitor_scaling","dna_ident","abandon_allowed","enter_allowed","guests_allowed","shuttle_frozen","shuttle_left","tinted_weldhelh","jobMax","bombers","admin_log","lastsignalers","lawchanges","shuttles","reg_dna","CELLRATE","CHARGELEVEL","WORLD_X_OFFSET","WORLD_Y_OFFSET","shuttle_z","airtunnel_start","airtunnel_stop","airtunnel_bottom","monkeystart","wizardstart","newplayer_start","latejoin","assistant_latejoin","prisonwarp","holdingfacility","xeno_spawn","endgame_safespawns","endgame_exits","tdome1","tdome2","tdomeobserve","tdomeadmin","prisonsecuritywarp","prisonwarped","blobstart","ninjastart","cardinal","diagonal","alldirs","universal_cult_chat","start_state","config","combatlog","IClog","OOClog","adminlog","suspend_alert","Debug","Debug2","debugobj","mods","wavesecret","gravity_is_on","shuttlecoming","join_motd","forceblob","polarstar","nanomanager","sqladdress","sqlport","sqldb","sqllogin","sqlpass","sqlfdbkdb","sqlfdbklogin","sqlfdbkpass","sqllogging","forumsqladdress","forumsqlport","forumsqldb","forumsqllogin","forumsqlpass","forum_activated_group","forum_authenticated_group","fileaccess_timer","custom_event_msg","dbcon","dbcon_old","recall_time_limit","score","trash_items","decals","on_login","on_ban","on_unban","plugins","space_gas","announcement_intercom","sortedAreas","bomberman_mode","bomberman_hurt","bomberman_destroy","volunteer_gladiators","ready_gladiators","never_gladiators","achievements","end_icons","arena_leaderboard","arena_rounds","arena_top_score","endgame_info_logged","explosion_newmethod","snake_station_highscores","snake_best_players","minesweeper_station_highscores","minesweeper_best_players","nanocoins_rates","nanocoins_lastchange","speciesinit","minimapinit","stat_collection","hardcore_mode","mineral_turfs","static_list","grayscale","adminblob_icon","adminblob_size","adminblob_beat","holoMiniMaps","centcommMiniMaps","extraMiniMaps","holomap_markers","holomaps_initialized","tachycardics","bradycardics","heartstopper","cheartstopper","disable_scrubbers","disable_vents","Space_Tile","MAX_EXPLOSION_RANGE","BODY_PARTS","BODY_COVER_VALUE_LIST","NOIRMATRIX","bad_changing_colour_ckeys","global_mutations","scarySounds","RESTRICTED_CAMERA_NETWORKS","default_colour_matrix","ai_names","wizard_first","wizard_second","ninja_titles","ninja_names","commando_names","first_names_male","first_names_female","last_names","clown_names","verbs","adjectives","vox_name_syllables","golem_names","borer_names","autoborg_silly_names","panicfile","failed_db_connections","failed_old_db_connections","desire_ranks","cmp_field","cmp_dist_origin","DummyCache","genders","clients","admins","directory","mixed_modes","player_list","mob_list","living_mob_list","dead_mob_list","observers","areas","chemical_reactions_list","chemical_reagents_list","landmarks_list","surgery_steps","mechas_list","poster_designs","underwear_m","underwear_f","backbaglist","hit_appends","table_recipes","med_hud_users","sec_hud_users","escape_list","church_name","command_name","religion_name","syndicate_name","syndicate_code_phrase","syndicate_code_response","watt_suffixes","number_digits","number_tens","number_units","existing_typesof_cache","common_tools","WALLITEMS","sortInstance","hooks","ventcrawl_machinery","catcher","parallax_on_clients","parallax_initialized","space_color","parallax_icon","unstackable_pipes","heat_pipes","bent_dirs","pipeID2State","nlist","straight_pipes","bent_pipes","manifold_pipes","garbageCollector","soft_dels","emergency_shuttle","Failsafe","Master","MC_restart_clear","MC_restart_timeout","MC_restart_count","CURRENT_TICKLIMIT","SSair","tick_multiplier","SSdisease","active_diseases","SSemergency_shuttle","SSevent","events","SSfast_machinery","fast_machines","SSgarbage","SShtml_ui","html_machines","SSinactivity","SSlighting","lighting_update_lights","lighting_update_corners","lighting_update_overlays","SSmachinery","machines","SSmob","SSnano","SSobj","processing_objects","SSpipenet","atmos_machines","pipe_networks","on_pipenet_tick","SSpower","power_machines","powernets","cable_list","SSsun","SSsupply_shuttle","SSticker","SSvote","SSassets","SSfinish","SSgenetics","SSjob","SSmap","SSminimap","SSmore_init","SSrust","SScreate_ticker","SSxenoarch","randomize_laws","base_law_type","mommi_base_law_type","diseases","map_elements","modules","sun","all_supply_groups","uplink_items","archive_diseases","advance_cures","list_symptoms","dictionary_symptoms","animal_butchering_products","revdata","same_wires","wireColours","PDA_Manifest","vox_sounds","vox_wordlen","outbreak_level_words","spawned_surprises","max_secret_rooms","del_profiling","gdel_profiling","ghdel_profiling","current_centcomm_order_id","all_radios","radiochannels","radiochannelsreverse","CENT_FREQS","radio_controller","pointers","nextDecTalkDelay","lastDecTalkUse","freqtospan","freqtoname","ghostimg","resethearers","smoothable_unsims","shatter_sound","explosion_sound","small_explosion_sound","spark_sound","rustle_sound","punch_sound","clown_sound","swing_hit_sound","hiss_sound","page_sound","mechstep_sound","gib_sound","mommicomment_sound","polaroid_sound","male_scream_sound","female_scream_sound","male_cough_sound","female_cough_sound","lightning_sound","soulstone_sound","fracture_sound","machete_hit_sound","machete_throw_sound","machete_throw_hit_sound","supply_shuttle","mechtoys","space_area","ignored_keys","moved_landmarks","transparent_icons","teleportlocs","ghostteleportlocs","adminbusteleportlocs","centcom_areas","the_station_areas","dna_activity_bounds","assigned_gene_blocks","assigned_blocks","dna_genes","good_blocks","bad_blocks","skin_styles_female_list","hair_styles_list","hair_styles_male_list","hair_styles_female_list","facial_hair_styles_list","facial_hair_styles_male_list","facial_hair_styles_female_list","noir_master","ticker","potential_theft_objectives","BLINDBLOCK","DEAFBLOCK","HULKBLOCK","TELEBLOCK","FIREBLOCK","XRAYBLOCK","CLUMSYBLOCK","FAKEBLOCK","COUGHBLOCK","GLASSESBLOCK","EPILEPSYBLOCK","TWITCHBLOCK","NERVOUSBLOCK","MONKEYBLOCK","BLOCKADD","DIFFMUT","HEADACHEBLOCK","NOBREATHBLOCK","REMOTEVIEWBLOCK","REGENERATEBLOCK","INCREASERUNBLOCK","REMOTETALKBLOCK","MORPHBLOCK","COLDBLOCK","HALLUCINATIONBLOCK","NOPRINTSBLOCK","SHOCKIMMUNITYBLOCK","SMALLSIZEBLOCK","LISPBLOCK","MUTEBLOCK","RADBLOCK","FATBLOCK","CHAVBLOCK","SWEDEBLOCK","SCRAMBLEBLOCK","TOXICFARTBLOCK","STRONGBLOCK","HORNSBLOCK","SMILEBLOCK","ELVISBLOCK","SOBERBLOCK","PSYRESISTBLOCK","FARSIGHTBLOCK","CHAMELEONBLOCK","CRYOBLOCK","EATBLOCK","JUMPBLOCK","MELTBLOCK","EMPATHBLOCK","SUPERFARTBLOCK","IMMOLATEBLOCK","POLYMORPHBLOCK","LOUDBLOCK","WHISPERBLOCK","DIZZYBLOCK","SANSBLOCK","NOIRBLOCK","blobs","blob_cores","blob_nodes","blob_resources","blob_overminds","blob_looks_admin","blob_looks_player","possible_changeling_IDs","hivemind_bank","powers","powerinstances","narsie_behaviour","narsie_cometh","narsie_list","mr_clean_targets","cultwords","runedec","engwords","rnwords","rune_list","snow_recipes","Holiday","blob_candidates","mixed_allowed","bomb_set","nukedisk","hsboxspawn","hrefs","banned_sandbox_types","all_jobs","job_master","assistant_occupations","command_positions","engineering_positions","medical_positions","science_positions","civilian_positions","cargo_positions","security_positions","nonhuman_positions","misc_positions","whitelist","alien_whitelist","firealarms","cryo_health_indicator","doppler_arrays","flashers","holosigns","igniters","multitool_var_whitelist","mass_drivers","navbeacons","news_network","allCasters","req_console_assistance","req_console_supplies","req_console_information","allConsoles","station_holomaps","status_displays","ai_emotions","status_display_images","num_vending_terminals","floorbot_targets","mulebot_count","camera_names","camera_messages","tv_monitors","shuttle_calls","prison_shuttle_moving_to_station","prison_shuttle_moving_to_prison","prison_shuttle_at_station","prison_shuttle_can_send","prison_shuttle_time","prison_shuttle_timeleft","specops_shuttle_moving_to_station","specops_shuttle_moving_to_centcom","specops_shuttle_at_station","specops_shuttle_can_send","specops_shuttle_time","specops_shuttle_timeleft","syndicate_elite_shuttle_moving_to_station","syndicate_elite_shuttle_moving_to_mothership","syndicate_elite_shuttle_at_station","syndicate_elite_shuttle_can_send","syndicate_elite_shuttle_time","syndicate_elite_shuttle_timeleft","taxi_computers","all_doors","alert_overlays_global","poddoors","recentmessages","message_delay","telecomms_list","word_to_uristrune_table","uristrune_cache","explosion_shake_message_cooldown","explosion_turfs","explosion_in_progress","blood_overlays","reagents_to_log","BUMP_TELEPORTERS","portal_cache","splatter_cache","blood_list","fluidtrack_cache","beacons","all_graffitis","living_balloons","deskbell_default_frequencies","deskbell_freq_cargo","deskbell_freq_hop","deskbell_freq_medbay","deskbell_freq_brig","deskbell_freq_rnd","camera_bugs","pda_app_menus","chatrooms","PDAs","available_paintings","cable_recipes","metal_recipes","plasteel_recipes","wood_recipes","cardboard_recipes","leather_recipes","sandstone_recipes","diamond_recipes","uranium_recipes","plasma_recipes","plastic_recipes","gold_recipes","phazon_recipes","silver_recipes","clown_recipes","charcoal_recipes","lightfloor_colors","moneytypes","cached_icons","tracking_implants","bottle_colour_choices","hidden_doors","all_docking_ports","ladders","cargo_shuttle","escape_shuttle","mining_shuttle","arrival_shuttle","transport_shuttle","admin_shuttle","research_shuttle","salvage_shuttle","security_shuttle","syndicate_shuttle","taxi_a","taxi_b","trade_shuttle","vox_shuttle","voxresearch_shuttle","response_team_members","sent_strike_teams","icons_to_ignore_at_floor_init","plating_icons","wood_icons","w_overlays","_flatIcons","directional","exception","directional_turfs","BSACooldown","floorIsLava","admin_shuttle_location","alien_ship_location","investigations","admin_ranks","admin_verbs_default","admin_verbs_admin","admin_verbs_ban","admin_verbs_sounds","admin_verbs_fun","admin_verbs_spawn","admin_verbs_server","admin_verbs_debug","admin_verbs_possess","admin_verbs_permissions","admin_verbs_rejuv","admin_verbs_polling","admin_verbs_hideable","admin_verbs_mod","appearanceban_runonce","appearance_keylist","jobban_runonce","jobban_keylist","oocban_keylist","admin_datums","CMinutes","Banlist","Banlistjob","adminhelp_ignored_words","checked_for_inactives","inactive_keys","blood_virus_spreading_disabled","camera_range_display_status","intercom_range_display_status","prevent_airgroup_regroup","say_disabled","movement_disabled","movement_disabled_exception","forbidden_varedit_object_types","PROFILING_VERBS","vox_tick","assembly_short_name_to_type","comparison_circuit_operations","math_circuit_operations_list","automation_types","gas_labels","existing_away_missions","awaydestinations","away_mission_subtypes","gateways","maploader","_preloader","map_dimension_cache","swapmaps_iconcache","swapmaps_mode","swapmaps_compiled_maxx","swapmaps_compiled_maxy","swapmaps_compiled_maxz","swapmaps_initialized","swapmaps_loaded","swapmaps_byname","bombermangear","arenas","arena_spawnpoints","person_animation_viewers","item_animation_viewers","preferences_datums","special_roles","antag_roles","nonantag_roles","role_wiki","opposite_dirs","holomap_chips","holomap_cache","has_been_shade","current_date_string","num_financial_terminals","num_financial_database","num_vending_machines","num_pda_terminals","num_merch_computers","station_account","department_accounts","next_account_number","centcomm_account_db","vendor_account","all_money_accounts","setup_economy","weighted_randomevent_locations","weighted_mundaneevent_locations","station_departments","current_pos_id","pos_sales","wages_enabled","roundstart_enable_wages","event_last_fired","allEvents","potentialRandomEvents","eventTimeLower","eventTimeUpper","scheduledEvent","vox_kills","vox_sent","raiders","thing_storm_types","watchdog","non_fakeattack_weapons","deepFriedEverything","deepFriedNutriment","foodNesting","recursiveFood","ingredientLimit","wizard_cards_rare","wizard_cards_normal","adv_camera","crewmonitor","vote","plant_controller","seed_types","gene_tag_masks","library_catalog","library_section_names","liquid_delay","puddles","global_playlists","loopModeNames","media_receivers","media_transmitters","migration_controller_mysql","migration_controller_sqlite","valid_abandoned_crate_types","material_list","initial_materials","name_to_mineral","mining_surprises","slot_equipment_priority","intents","boo_phrases","boo_phrases_drugs","boo_phrases_silicon","virtualhearers","movable_hearers","mob_hearers","stationary_hearers","coldwarning_light","coldwarning_hard","department_radio_keys","language_keys","all_languages","all_species","whitelisted_species","unconscious_overlays","oxyloss_overlays","brutefireloss_overlays","organ_damage_overlays","damage_icon_parts","cover_protection_value_list","ai_list","announcing_vox","vox_digits","vox_tens","vox_units","cameranet","paiController","borer_chem_types_head","borer_chem_types_chest","borer_chem_types_arm","borer_chem_types_leg","borer_unlock_types_head","borer_unlock_types_chest","borer_unlock_types_arm","borer_unlock_types_leg","animal_count","wizard_snakes","nest_locations","bad_gremlin_items","crate_mimic_disguises","item_mimic_disguises","protected_objects","spider_queens","photocollector_list","prism_list","mirror_list","paper_folding_results","paperwork","paperwork_library","battery_charge","battery_charging","battery_online","alllights","powernets_broke","smes_list","solars_list","rad_collectors","field_gen_list","bullet_master","impact_master","available_staff_transforms","beam_master","existing_dungeons","dungeon_area","existing_vaults","disposalpipeID2State","paint_variants","chifir_doesnt_remove","tonio_doesnt_remove","LOGGED_SPLASH_REAGENTS","pillIcon2Name","special_fruits","valid_random_food_types","cockroach_egg_amount","charcoal_doesnt_remove","message_servers","blackbox","rnd_machines","design_list","tech_list","hidden_tech","responsive_carriers","finds_as_strings","authenticators","maint_all_access","spells","falltempoverlays","centcomm_store","GPS_list","SPS_list","telesci_warnings","ANTIGENS","disease2_list","virusDB","compatible_mobs","buildmodeholders","newscaster_standard_feeds","announced_news_types","allfaxes","alldepartments","atmos_controllers","ul_FastRoot","sharing_lookup_table","assigned","created","merged","invalid_zone","air_blocked","zone_blocked","blocked","mark","zas_settings","contamination_overlay","accessable_z_levels","shop_prices","circuitboards","circuitboard_prices","clothing","clothing_prices","hive_pylons","sc_safecode1","sc_safecode2","sc_safecode3","sc_safecode4","sc_safecode5") diff --git a/code/__HELPERS/icons.dm b/code/__HELPERS/icons.dm index 211638eb31d..0950b34abae 100644 --- a/code/__HELPERS/icons.dm +++ b/code/__HELPERS/icons.dm @@ -1,13 +1,12 @@ -proc - getIconMask(atom/A)//By yours truly. Creates a dynamic mask for a mob/whatever. /N - var/icon/alpha_mask = new(A.icon,A.icon_state)//So we want the default icon and icon state of A. - for(var/I in A.overlays)//For every image in overlays. var/image/I will not work, don't try it. - if(I:layer>A.layer) - continue//If layer is greater than what we need, skip it. - var/icon/image_overlay = new(I:icon,I:icon_state)//Blend only works with icon objects. - //Also, icons cannot directly set icon_state. Slower than changing variables but whatever. - alpha_mask.Blend(image_overlay,ICON_OR)//OR so they are lumped together in a nice overlay. - return alpha_mask//And now return the mask. +/proc/getIconMask(atom/A)//By yours truly. Creates a dynamic mask for a mob/whatever. /N + var/icon/alpha_mask = new(A.icon,A.icon_state)//So we want the default icon and icon state of A. + for(var/I in A.overlays)//For every image in overlays. var/image/I will not work, don't try it. + if(I:layer>A.layer) + continue//If layer is greater than what we need, skip it. + var/icon/image_overlay = new(I:icon,I:icon_state)//Blend only works with icon objects. + //Also, icons cannot directly set icon_state. Slower than changing variables but whatever. + alpha_mask.Blend(image_overlay,ICON_OR)//OR so they are lumped together in a nice overlay. + return alpha_mask//And now return the mask. /mob/proc/AddCamoOverlay(atom/A)//A is the atom which we are using as the overlay. var/icon/opacity_icon = new(A.icon, A.icon_state)//Don't really care for overlays/underlays. @@ -141,3 +140,19 @@ proc/adjust_brightness(var/color, var/value) if (I.GetPixel(x_pixel, y_pixel)) return y_pixel - 1 return null + +/proc/has_icon(var/icon/I, var/wanted_state = null) + if(!I) + return FALSE + + var/found = FALSE + + for(var/found_state in icon_states(I,1)) + if(found_state == wanted_state) + found = TRUE + break + + if(found) + return TRUE + else + return FALSE \ No newline at end of file diff --git a/code/__HELPERS/lists.dm b/code/__HELPERS/lists.dm index 05daf79789c..1eec529aaf9 100644 --- a/code/__HELPERS/lists.dm +++ b/code/__HELPERS/lists.dm @@ -265,6 +265,15 @@ i++ return null +// Returns the first key to match the specified element. This is intended for lists which are injective functions. +// Which is to say, two keys will not map to the same element. +/proc/get_key_by_element(var/list/L, var/element) + for(var/key in L) + if(L[key] == element) + return key + return null + + /proc/count_by_type(var/list/L, type) var/i = 0 for(var/T in L) diff --git a/code/__HELPERS/logging.dm b/code/__HELPERS/logging.dm index 27dfdca5f5b..00187bd309e 100644 --- a/code/__HELPERS/logging.dm +++ b/code/__HELPERS/logging.dm @@ -73,7 +73,7 @@ */ /proc/add_attacklogs(var/mob/user, var/mob/target, var/what_done, var/object = null, var/addition = null, var/admin_warn = TRUE) var/user_txt = (user ? "[user][user.ckey ? " ([user.ckey])" : ""]" : "\") - var/target_txt = (target ? "[target][target.ckey ? " ([target.ckey])" : ""]" : "\") + var/target_txt = (target ? ismob(target) ? "[target][target.ckey ? " ([target.ckey])" : ""]" : "[target]" : "\") var/object_txt = (object ? " with \the [object]" : "") var/intent_txt = (user ? " (INTENT: [uppertext(user.a_intent)])" : "") var/addition_txt = (addition ? " ([addition])" : "") diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index 070ab0ce139..4d07c923cb2 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -283,3 +283,12 @@ proc/add_ghostlogs(var/mob/user, var/obj/target, var/what_done, var/admin=1, var L.Remove(organ) return L + +/proc/adjacent_atoms(atom/center) + var/list/L = list() + + for(var/atom/A in range(1, center)) + if(center.Adjacent(A)) + L.Add(A) + + return L diff --git a/code/__HELPERS/names.dm b/code/__HELPERS/names.dm index f881a2e9d69..34017697d61 100644 --- a/code/__HELPERS/names.dm +++ b/code/__HELPERS/names.dm @@ -76,7 +76,7 @@ var/religion_name = null station_name += name + " " //For special days like christmas, easter, new-years etc ~Carn - if("Friday the 13th") + if(FRIDAY_THE_13TH) name = pick("Mike","Friday","Evil","Myers","Murder","Deathly","Stabby") station_name += name + " " random = 13 diff --git a/code/__HELPERS/time.dm b/code/__HELPERS/time.dm index 12c418812f1..ee355343b6f 100644 --- a/code/__HELPERS/time.dm +++ b/code/__HELPERS/time.dm @@ -23,8 +23,9 @@ return wtime + (time_offset + wusage) * world.tick_lag //Returns the world time in english -/proc/worldtime2text(timestamp = world.time) - return "[(round(timestamp / 36000) + 12) % 24]:[(timestamp / 600 % 60) < 10 ? add_zero(timestamp / 600 % 60, 1) : timestamp / 600 % 60]" +/proc/worldtime2text(timestamp = world.time, give_seconds = FALSE) + return "[(round(timestamp / 36000) + 12) % 24]:[(timestamp / 600 % 60) < 10 ? add_zero(timestamp / 600 % 60, 1) : timestamp / 600 % 60]\ + [give_seconds ? ":[(timestamp / 10 % 60) < 10 ? add_zero(timestamp / 10 % 60, 1) : timestamp / 10 % 60]" : ""]" /proc/formatTimeDuration(var/deciseconds) diff --git a/code/__HELPERS/transforms.dm b/code/__HELPERS/transforms.dm index aa71926f60c..39e0d5ced3b 100644 --- a/code/__HELPERS/transforms.dm +++ b/code/__HELPERS/transforms.dm @@ -29,7 +29,7 @@ return FALSE //Sanity, this should never happen. //Bad mobs! - Remember to add a comment explaining what's wrong with the mob - if(is_type_in_list(MP, blacklisted_mobs)) + if(is_type_in_list(MP, existing_typesof_list(blacklisted_mobs))) return FALSE //Not in here? Must be untested, but WHO CARES! diff --git a/code/__HELPERS/typeof.dm b/code/__HELPERS/typeof.dm index c3daec38b61..bf3e1f0385a 100644 --- a/code/__HELPERS/typeof.dm +++ b/code/__HELPERS/typeof.dm @@ -96,3 +96,15 @@ var/global/list/existing_typesof_cache = list() existing_typesof_cache[path] = L.Copy() return L + +//existing_typesof does not like lists, so... +/proc/existing_typesof_list(var/list/L) + if(!islist(L)) + return + + var/list/existing_types = list() + + for(var/types in L) + existing_types += existing_typesof(types) + + return existing_types diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index d53103f2cf7..951dbd7a3a4 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -883,6 +883,11 @@ proc/GaussRandRound(var/sigma,var/roundto) progbar.loc = null return 1 +/proc/do_flick(var/atom/A, var/icon_state, var/time) + flick(icon_state, A) + sleep(time) + return 1 + //Takes: Anything that could possibly have variables and a varname to check. //Returns: 1 if found, 0 if not. /proc/hasvar(var/datum/A, var/varname) @@ -1261,7 +1266,7 @@ var/global/list/common_tools = list( /proc/can_operate(mob/living/carbon/M, mob/U) if(U == M) return 0 - if(ishuman(M) && M.lying) + if((ishuman(M) || isslime(M)) && M.lying) if(locate(/obj/machinery/optable,M.loc) || locate(/obj/structure/bed/roller/surgery, M.loc)) return 1 if(locate(/obj/structure/bed/roller, M.loc) && prob(75)) @@ -1695,13 +1700,6 @@ Game Mode config tags: /proc/sentStrikeTeams(var/team) return (team in sent_strike_teams) - -/proc/area_in_map(var/area/A) - for (var/turf/T in A.area_turfs) - return TRUE - return FALSE - - /proc/get_exact_dist(atom/A, atom/B) //returns the coordinate distance between the coordinates of the turfs of A and B var/turf/T1 = A var/turf/T2 = B @@ -1759,3 +1757,40 @@ Game Mode config tags: qdel(O) return TRUE + +//Same as block(Start, End), but only returns the border turfs +//'Start' must be lower-left, 'End' must be upper-right +/proc/block_borders(turf/Start, turf/End) + ASSERT(istype(Start)) + ASSERT(istype(End)) + + //i'm a lazy cunt and I don't feel like making this work + ASSERT(Start.x < End.x && Start.y < End.y) + + return block(Start, End) - block(locate(Start.x + 1, Start.y + 1, Start.z), locate(End.x - 1, End.y - 1, End.z)) + + +/proc/pick_rand_tele_turf(atom/hit_atom, var/inner_teleport_radius, var/outer_teleport_radius) + if((inner_teleport_radius < 1) || (outer_teleport_radius < inner_teleport_radius)) + return 0 + + var/list/turfs = new/list() + var/turf/hit_turf = get_turf(hit_atom) + //This could likely use some standardization but I have no idea how to not break it. + for(var/turf/T in trange(outer_teleport_radius, hit_turf)) + if(get_dist(T, hit_atom) <= inner_teleport_radius) + continue + if(is_blocked_turf(T) || istype(T, /turf/space)) + continue + if(T.x > world.maxx-outer_teleport_radius || T.x < outer_teleport_radius) + continue + if(T.y > world.maxy-outer_teleport_radius || T.y < outer_teleport_radius) + continue + turfs += T + return pick(turfs) + +/proc/get_key(mob/M) + if(M.mind) + return M.mind.key + else + return null diff --git a/code/_onclick/ai.dm b/code/_onclick/ai.dm index 3231c4df6b8..fdfd1dc05d7 100644 --- a/code/_onclick/ai.dm +++ b/code/_onclick/ai.dm @@ -53,8 +53,8 @@ return if(aicamera.in_camera_mode) - aicamera.camera_mode_off() - aicamera.captureimage(A, usr) + aicamera.toggle_camera_mode() + aicamera.captureimage(A, src) return /* diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index 515473cb1e1..d2771ed5c2d 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -61,7 +61,10 @@ "target" = A )) if(modifiers["middle"]) - MiddleClickOn(A) + if(modifiers["shift"]) + MiddleShiftClickOn(A) + else + MiddleClickOn(A) return if(modifiers["shift"]) ShiftClickOn(A) @@ -238,6 +241,9 @@ return */ +/mob/proc/MiddleShiftClickOn(var/atom/A) + pointed(A) + /* Shift click For most mobs, examine. diff --git a/code/_onclick/cyborg.dm b/code/_onclick/cyborg.dm index 11da82a3ddb..550540c6066 100644 --- a/code/_onclick/cyborg.dm +++ b/code/_onclick/cyborg.dm @@ -39,12 +39,10 @@ return face_atom(A) // change direction to face what you clicked on - /* - cyborg restrained() currently does nothing - if(restrained()) - RestrainedClickOn(A) + if(aicamera.in_camera_mode) //Cyborg picture taking + aicamera.toggle_camera_mode(src) + aicamera.captureimage(A, src) return - */ var/obj/item/W = get_active_hand() @@ -54,10 +52,6 @@ A.attack_robot(src) return - // locked_to cannot prevent machine interlinking but stops arm movement - if(locked_to) - return - if(W == A) /*next_move = world.time + 8 if(W.flags&USEDELAY) diff --git a/code/_onclick/drag_drop.dm b/code/_onclick/drag_drop.dm index 7d79d934fca..ad84fa80430 100644 --- a/code/_onclick/drag_drop.dm +++ b/code/_onclick/drag_drop.dm @@ -17,6 +17,10 @@ /atom/proc/MouseDrop_T(atom/dropping, mob/user) return +/obj/MouseDrop_T(atom/dropping, mob/user) + if(material_type) + material_type.on_use(src, dropping, user) + /atom/proc/can_MouseDrop(atom/otheratom, mob/user = usr) if(!user || !otheratom) return FALSE diff --git a/code/_onclick/hud/_defines.dm b/code/_onclick/hud/_defines.dm index 996837cb27b..d8d64ed716a 100644 --- a/code/_onclick/hud/_defines.dm +++ b/code/_onclick/hud/_defines.dm @@ -41,6 +41,7 @@ #define ui_inv3 "CENTER:[16*PIXEL_MULTIPLIER],SOUTH:[5*PIXEL_MULTIPLIER]" //borgs #define ui_borg_module "CENTER+1:[16*PIXEL_MULTIPLIER],SOUTH:[5*PIXEL_MULTIPLIER]" //borgs #define ui_borg_store "CENTER+2:[16*PIXEL_MULTIPLIER],SOUTH:[5*PIXEL_MULTIPLIER]" //borgs + #define ui_mommi_store "CENTER+1:[16*PIXEL_MULTIPLIER],SOUTH:[5*PIXEL_MULTIPLIER]" #define ui_mommi_module "CENTER:[16*PIXEL_MULTIPLIER],SOUTH:[5*PIXEL_MULTIPLIER]" #define ui_mommi_sight "CENTER-2:[16*PIXEL_MULTIPLIER],SOUTH:[5*PIXEL_MULTIPLIER]" @@ -63,7 +64,6 @@ #define ui_acti_alt "EAST-1:[28*PIXEL_MULTIPLIER],SOUTH:[5*PIXEL_MULTIPLIER]" //alternative intent switcher for when the interface is hidden (F12) #define ui_borg_pull "EAST-3:[24*PIXEL_MULTIPLIER],SOUTH+1:[7*PIXEL_MULTIPLIER]" -//#define ui_borg_module "13:[26*PIXEL_MULTIPLIER],2:[7*PIXEL_MULTIPLIER]" #define ui_borg_panel "EAST-1:[28*PIXEL_MULTIPLIER],SOUTH+1:[7*PIXEL_MULTIPLIER]" //Gun buttons @@ -72,6 +72,9 @@ #define ui_gun3 "EAST-2:26,SOUTH+3:7" //Used as compile time value #define ui_gun_select "EAST-1:28,SOUTH+2:7" //Used as compile time value +#define ui_borg_album "EAST-1:[28*PIXEL_MULTIPLIER],SOUTH+5:[7*PIXEL_MULTIPLIER]" //borgs +#define ui_borg_camera "EAST-1:[28*PIXEL_MULTIPLIER],SOUTH+4:[7*PIXEL_MULTIPLIER]" //borgs + //Upper-middle right (damage indicators) #define ui_toxin "EAST-1:[28*PIXEL_MULTIPLIER],NORTH-2:[27*PIXEL_MULTIPLIER]" #define ui_fire "EAST-1:[28*PIXEL_MULTIPLIER],NORTH-3:[25*PIXEL_MULTIPLIER]" diff --git a/code/_onclick/hud/action_button.dm b/code/_onclick/hud/action_button.dm index fb9936c2b98..6eff120142e 100644 --- a/code/_onclick/hud/action_button.dm +++ b/code/_onclick/hud/action_button.dm @@ -2,29 +2,39 @@ var/datum/action/linked_action var/actiontooltipstyle = "" screen_loc = null - globalscreen = 1 + globalscreen = TRUE /obj/abstract/screen/movable/action_button/Click(location,control,params) var/list/modifiers = params2list(params) if(modifiers["shift"]) - moved = 0 + moved = FALSE usr.update_action_buttons() //redraw buttons that are no longer considered "moved" - return 1 + return TRUE linked_action.Trigger() - return 1 + return TRUE + +/obj/abstract/screen/movable/action_button/MouseDrop(over_object, src_location, over_location, src_control, over_control, params) + if(istype(over_object, /obj/abstract/screen/movable/action_button) && !istype(over_object, /obj/abstract/screen/movable/action_button/hide_toggle)) + var/obj/abstract/screen/movable/action_button/B = over_object + var/list/actions = usr.actions + actions.Swap(actions.Find(src.linked_action), actions.Find(B.linked_action)) + usr.update_action_buttons() //Hide/Show Action Buttons ... Button /obj/abstract/screen/movable/action_button/hide_toggle name = "Hide Buttons" icon = 'icons/mob/actions.dmi' icon_state = "bg_default" - var/hidden = 0 + var/hidden = FALSE + +/obj/abstract/screen/movable/action_button/hide_toggle/MouseDrop(over_object, src_location, over_location, src_control, over_control, params) + return /obj/abstract/screen/movable/action_button/hide_toggle/Click(location,control,params) var/list/modifiers = params2list(params) if(modifiers["shift"]) - moved = 0 - return 1 + moved = FALSE + return TRUE usr.hud_used.action_buttons_hidden = !usr.hud_used.action_buttons_hidden hidden = usr.hud_used.action_buttons_hidden @@ -35,7 +45,6 @@ UpdateIcon() usr.update_action_buttons() - /obj/abstract/screen/movable/action_button/hide_toggle/proc/InitialiseIcon(mob/living/user) if(isalien(user)) icon_state = "bg_alien" @@ -80,22 +89,22 @@ button_number++ A.UpdateButtonIcon() var/obj/abstract/screen/movable/action_button/B = A.button - if(!B.moved) - B.screen_loc = hud_used.ButtonNumberToScreenCoords(button_number) - else + if(B.moved) B.screen_loc = B.moved + else + B.screen_loc = hud_used.ButtonNumberToScreenCoords(button_number) if(reload_screen) client.screen += B if(!button_number) hud_used.hide_actions_toggle.screen_loc = null return - if(!hud_used.hide_actions_toggle.screen_loc) - reload_screen = 1 + if(!hud_used.hide_actions_toggle.moved) hud_used.hide_actions_toggle.screen_loc = hud_used.ButtonNumberToScreenCoords(button_number+1) else hud_used.hide_actions_toggle.screen_loc = hud_used.hide_actions_toggle.moved + if(reload_screen) client.screen += hud_used.hide_actions_toggle diff --git a/code/_onclick/hud/fullscreen.dm b/code/_onclick/hud/fullscreen.dm index bd25a2e4364..b3925805159 100644 --- a/code/_onclick/hud/fullscreen.dm +++ b/code/_onclick/hud/fullscreen.dm @@ -87,15 +87,15 @@ /obj/abstract/screen/fullscreen/brute icon_state = "brutedamageoverlay" - layer = DAMAGE_LAYER + layer = DAMAGE_HUD_LAYER /obj/abstract/screen/fullscreen/oxy icon_state = "oxydamageoverlay" - layer = DAMAGE_LAYER + layer = DAMAGE_HUD_LAYER /obj/abstract/screen/fullscreen/numb icon_state = "numboverlay" - layer = DAMAGE_LAYER + layer = DAMAGE_HUD_LAYER /obj/abstract/screen/fullscreen/crit icon_state = "passage" diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm index 9cd717f1b3e..0d3c88c04b9 100644 --- a/code/_onclick/hud/hud.dm +++ b/code/_onclick/hud/hud.dm @@ -13,10 +13,10 @@ var/global/obj/abstract/screen/clicker/catcher = new() var/obj/abstract/screen/disarm_intent var/obj/abstract/screen/help_intent - var/hud_shown = 1 //Used for the HUD toggle (F12) - var/inventory_shown = 1 //the inventory - var/show_intent_icons = 0 - var/hotkey_ui_hidden = 0 //This is to hide the buttons that can be used via hotkeys. (hotkeybuttons list of buttons) + var/hud_shown = TRUE //Used for the HUD toggle (F12) + var/inventory_shown = TRUE //the inventory + var/show_intent_icons = FALSE + var/hotkey_ui_hidden = FALSE //This is to hide the buttons that can be used via hotkeys. (hotkeybuttons list of buttons) var/obj/abstract/screen/lingchemdisplay var/obj/abstract/screen/vampire_blood_display // /vg/ @@ -25,7 +25,7 @@ var/global/obj/abstract/screen/clicker/catcher = new() var/obj/abstract/screen/move_intent var/obj/abstract/screen/movable/action_button/hide_toggle/hide_actions_toggle - var/action_buttons_hidden = 0 + var/action_buttons_hidden = FALSE var/list/adding var/list/other @@ -34,13 +34,14 @@ var/global/obj/abstract/screen/clicker/catcher = new() /datum/hud/New(mob/owner) mymob = owner - instantiate() + hide_actions_toggle = new - hide_actions_toggle.InitialiseIcon(mymob) + hide_actions_toggle.InitialiseIcon(src) + + instantiate() ..() /datum/hud/Destroy() - ..() grab_intent = null hurt_intent = null disarm_intent = null @@ -56,6 +57,8 @@ var/global/obj/abstract/screen/clicker/catcher = new() hotkeybuttons = null mymob = null + return ..() + /datum/hud/proc/hidden_inventory_update() if(!mymob) @@ -182,9 +185,9 @@ var/global/obj/abstract/screen/clicker/catcher = new() /datum/hud/proc/instantiate() if(!ismob(mymob)) - return 0 + return FALSE if(!mymob.client) - return 0 + return FALSE var/ui_style @@ -254,13 +257,12 @@ var/global/obj/abstract/screen/clicker/catcher = new() mymob.client.screen += src.holomap_obj reload_fullscreen() - mymob.update_action_buttons(1) update_parallax_existence() //Triggered when F12 is pressed (Unless someone changed something in the DMF) /mob/verb/button_pressed_F12() set name = "F12" - set hidden = 1 + set hidden = TRUE if(hud_used && client) if(ishuman(src)) @@ -268,7 +270,7 @@ var/global/obj/abstract/screen/clicker/catcher = new() return if(hud_used.hud_shown) - hud_used.hud_shown = 0 + hud_used.hud_shown = FALSE if(src.hud_used.adding) src.client.screen -= src.hud_used.adding if(src.hud_used.other) @@ -286,7 +288,7 @@ var/global/obj/abstract/screen/clicker/catcher = new() src.client.screen -= src.zone_sel //zone_sel is a mob variable for some reason. else - hud_used.hud_shown = 1 + hud_used.hud_shown = TRUE if(src.hud_used.adding) src.client.screen += src.hud_used.adding if(src.hud_used.other && src.hud_used.inventory_shown) @@ -300,7 +302,7 @@ var/global/obj/abstract/screen/clicker/catcher = new() hud_used.hidden_inventory_update() hud_used.persistant_inventory_update() - update_action_buttons(1) + update_action_buttons(TRUE) else to_chat(usr, "Inventory hiding is currently only supported for human mobs, sorry.") else @@ -378,5 +380,5 @@ var/global/obj/abstract/screen/clicker/catcher = new() L.client.screen -= L.schematics_background L.client.screen -= R.closer if(clear && override && override.len) - L.shown_schematics_background = 1 + L.shown_schematics_background = TRUE .(override, 0, R) diff --git a/code/_onclick/hud/other_mobs.dm b/code/_onclick/hud/other_mobs.dm index 65a6f036556..a3e42dc7bca 100644 --- a/code/_onclick/hud/other_mobs.dm +++ b/code/_onclick/hud/other_mobs.dm @@ -124,7 +124,7 @@ /datum/hud/proc/construct_hud() var/constructtype - if(istype(mymob,/mob/living/simple_animal/construct/armoured) || istype(mymob,/mob/living/simple_animal/construct/behemoth)) + if(istype(mymob,/mob/living/simple_animal/construct/armoured)) constructtype = "juggernaut" else if(istype(mymob,/mob/living/simple_animal/construct/builder)) constructtype = "artificer" diff --git a/code/_onclick/hud/robot.dm b/code/_onclick/hud/robot.dm index 8466e93259f..c95f01ee8cd 100644 --- a/code/_onclick/hud/robot.dm +++ b/code/_onclick/hud/robot.dm @@ -1,6 +1,5 @@ /datum/hud/proc/robot_hud() - src.adding = list() src.other = list() @@ -125,6 +124,20 @@ mymob.pressure.name = "environment pressure" mymob.pressure.screen_loc = ui_borg_pressure +//Photography stuff + + mymob.camera_icon = getFromPool(/obj/abstract/screen) + mymob.camera_icon.icon = 'icons/mob/screen1_robot.dmi' + mymob.camera_icon.icon_state = "camera" + mymob.camera_icon.name = "Take Image" + mymob.camera_icon.screen_loc = ui_borg_camera + + mymob.album_icon = getFromPool(/obj/abstract/screen) + mymob.album_icon.icon = 'icons/mob/screen1_robot.dmi' + mymob.album_icon.icon_state = "album" + mymob.album_icon.name = "View Images" + mymob.album_icon.screen_loc = ui_borg_album + //unused, go home mymob.oxygen = getFromPool(/obj/abstract/screen) mymob.oxygen.icon = 'icons/mob/screen1_robot.dmi' @@ -171,7 +184,7 @@ mymob.client.reset_screen() - mymob.client.screen += list( mymob.throw_icon, mymob.zone_sel, mymob.fire, mymob.pressure, mymob.bodytemp, mymob.hands, mymob.healths, mymob:cells, mymob.pullin, mymob.gun_setting_icon) //, mymob.rest, mymob.sleep, mymob.mach, mymob.oxygen) + mymob.client.screen += list( mymob.throw_icon, mymob.zone_sel, mymob.fire, mymob.pressure, mymob.bodytemp, mymob.hands, mymob.healths, mymob:cells, mymob.pullin, mymob.gun_setting_icon, mymob.camera_icon, mymob.album_icon) //, mymob.rest, mymob.sleep, mymob.mach, mymob.oxygen) mymob.client.screen += src.adding + src.other return diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index ba1188c6b5c..ce9d0e19e63 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -140,6 +140,9 @@ /obj/abstract/screen/gun/MouseExited() closeToolTip(usr) +/proc/get_random_zone_sel() + return pick("l_foot", "r_foot", "l_leg", "r_leg", "l_hand", "r_hand", "l_arm", "r_arm", "chest", "groin", "eyes", "mouth", "head") + /obj/abstract/screen/zone_sel name = "damage zone" icon_state = "zone_sel" @@ -453,12 +456,18 @@ if("Take Image") if(isAI(usr)) var/mob/living/silicon/ai/AI = usr - AI.aicamera.toggle_camera_mode() + AI.aicamera.toggle_camera_mode(AI) + else if(isrobot(usr)) + var/mob/living/silicon/robot/R = usr + R.aicamera.toggle_camera_mode(R) if("View Images") if(isAI(usr)) var/mob/living/silicon/ai/AI = usr - AI.aicamera.viewpictures() + AI.aicamera.viewpictures(AI) + else if(isrobot(usr)) + var/mob/living/silicon/robot/R = usr + R.aicamera.viewpictures(R) if("Configure Radio") if(isAI(usr)) diff --git a/code/_onclick/hud/spell_screen_objects.dm b/code/_onclick/hud/spell_screen_objects.dm index 6cd750c8387..331786e122b 100644 --- a/code/_onclick/hud/spell_screen_objects.dm +++ b/code/_onclick/hud/spell_screen_objects.dm @@ -235,6 +235,8 @@ dat += "
Range: Global" if(SELFCAST) dat += "
Range: Self" + if(spell.desc) + dat += "
Desc: [spell.desc]" openToolTip(usr,src,params,title = name,content = dat) /obj/abstract/screen/spell/MouseExited() diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index 9bcd96d5053..7ccc3e4db74 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -7,6 +7,8 @@ . = src.unwield(user) else . = src.wield(user) + if(material_type) + material_type.on_use(src, user, user) // No comment /atom/proc/attackby(obj/item/W, mob/user) @@ -16,6 +18,8 @@ if(W && !(W.flags&NO_ATTACK_MSG)) user.do_attack_animation(src, W) visible_message("[src] has been hit by [user] with [W].") + if(W.material_type) + W.material_type.on_use(W, src, user) /mob/living/attackby(obj/item/I, mob/user, var/no_delay = 0, var/originator = null) if(!no_delay) @@ -27,6 +31,7 @@ I.attack(src, user) + // Proximity_flag is 1 if this afterattack was called on something adjacent, in your square, or on your person. // Click parameters is the params string from byond Click() code, see that documentation. /obj/item/proc/afterattack(atom/target, mob/user, proximity_flag, click_parameters) @@ -232,6 +237,13 @@ obj/item/proc/get_clamped_volume() . = TRUE //The attack always lands M.updatehealth() I.add_fingerprint(user) + I.on_attack(M,user) + +/obj/item/proc/on_attack(var/atom/attacked, var/mob/user) + user.do_attack_animation(attacked, src) + user.delayNextAttack(attack_delay) if(hitsound) - playsound(get_turf(M.loc), I.hitsound, 50, 1, -1) + playsound(attacked.loc, hitsound, 50, 1, -1) + if(material_type) + material_type.on_use(src,attacked, user) \ No newline at end of file diff --git a/code/_onclick/observer.dm b/code/_onclick/observer.dm index ae755643810..d8176cd3a77 100644 --- a/code/_onclick/observer.dm +++ b/code/_onclick/observer.dm @@ -46,6 +46,9 @@ //next_move = world.time + 8 var/list/modifiers = params2list(params) + if(modifiers["middle"] && modifiers["shift"]) + MiddleShiftClickOn(A) + return if(modifiers["middle"]) MiddleClickOn(A) return diff --git a/code/_onclick/other_mobs.dm b/code/_onclick/other_mobs.dm index d5ccb5febba..5ef73a67f8c 100644 --- a/code/_onclick/other_mobs.dm +++ b/code/_onclick/other_mobs.dm @@ -53,10 +53,14 @@ A.attack_stump(src, params) if(src.lying && !(isUnconscious() || stunned || paralysis) && check_crawl_ability() && isfloor(A) && isfloor(get_turf(src)) && proximity && !pulledby && !locked_to && !client.move_delayer.blocked()) - var/delay = round(1 + base_movement_tally()/5) * 1 SECONDS - if (do_after(src, A, delay)) - Move(A, get_dir(src,A), glide_size_override = delay) // So that we're still smooth - delayNextMove(delay, additive=1) + var/crawldelay = round(1 + base_movement_tally()/5) * 1 SECONDS + Move(A, get_dir(src,A), glide_size_override = crawldelay) + delayNextMove(crawldelay, additive=1) + + if(proximity && isobj(A)) + var/obj/O = A + if(O.material_type) + O.material_type.on_use(O, src, null) /atom/proc/attack_hand(mob/user as mob, params, var/proximity) return @@ -218,12 +222,12 @@ return 0 //Martians -/mob/living/carbon/martian/UnarmedAttack(atom/A) +/mob/living/carbon/complex/martian/UnarmedAttack(atom/A) if(ismob(A)) delayNextAttack(10) A.attack_martian(src) -/mob/living/carbon/martian/RangedAttack(atom/A) +/mob/living/carbon/complex/martian/RangedAttack(atom/A) if(mutations.len) if((M_LASER in mutations) && a_intent == I_HURT) LaserEyes(A) // moved into a proc below diff --git a/code/_onclick/ventcrawl.dm b/code/_onclick/ventcrawl.dm index 505a88defd9..b6dcd6f9217 100644 --- a/code/_onclick/ventcrawl.dm +++ b/code/_onclick/ventcrawl.dm @@ -12,7 +12,7 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump, // Vent crawling whitelisted items, whoo /mob/living - var/canEnterVentWith = "/obj/item/weapon/implant=0&/obj/item/clothing/mask/facehugger=0&/obj/item/device/radio/borg=0&/obj/machinery/camera=0&/mob/living/simple_animal/borer=0&/obj/transmog_body_container=0&/obj/item/verbs=0" + var/canEnterVentWith = "/obj/item/weapon/implant=0&/obj/item/clothing/mask/facehugger=0&/obj/item/device/radio/borg=0&/obj/machinery/camera=0&/mob/living/simple_animal/borer=0&/obj/transmog_body_container=0&/obj/item/verbs=0&/obj/item/weapon/gun/hookshot/flesh=0" /mob/living/AltClickOn(var/atom/A) if(is_type_in_list(A,ventcrawl_machinery)) @@ -89,6 +89,9 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump, /mob/living/simple_animal/spiderbot/can_ventcrawl() return TRUE +/mob/living/simple_animal/hostile/lizard/can_ventcrawl() + return TRUE + /mob/living/simple_animal/hostile/necromorph/leaper/can_ventcrawl() return TRUE diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index 78fc2528869..f27b4b50afd 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -564,13 +564,13 @@ if("enable_wages") roundstart_enable_wages = 1 if("error_cooldown") - error_cooldown = value + error_cooldown = text2num(value) if("error_limit") - error_limit = value + error_limit = text2num(value) if("error_silence_time") - error_silence_time = value + error_silence_time = text2num(value) if("error_msg_delay") - error_msg_delay = value + error_msg_delay = text2num(value) if("discord_url") discord_url = value if("discord_password") diff --git a/code/controllers/garbage.dm b/code/controllers/garbage.dm index f514f1ceb29..0eca7c03d93 100644 --- a/code/controllers/garbage.dm +++ b/code/controllers/garbage.dm @@ -84,8 +84,8 @@ world/loop_checks = 0 found += LookForRefs(R, D) for(var/datum/R) found += LookForRefs(R, D) - for(var/A in _all_globals) - found += LookForListRefs(readglobal(A), D, null, A) + for(var/A in global.vars) + found += LookForListRefs(global.vars[A], D, null, A) to_chat(world, "we found [found]") #endif diff --git a/code/controllers/mc/master.dm b/code/controllers/mc/master.dm index 9ac04fe1743..3777b634f3c 100644 --- a/code/controllers/mc/master.dm +++ b/code/controllers/mc/master.dm @@ -121,6 +121,8 @@ var/CURRENT_TICKLIMIT = TICK_LIMIT_RUNNING // Please don't stuff random bullshit here, // Make a subsystem, give it the SS_NO_FIRE flag, and do your work in it's Initialize() /datum/controller/master/proc/Setup() + set waitfor = FALSE + sleep(1 SECONDS) to_chat(world, "Initializing subsystems...") // Sort subsystems by init_order, so they initialize in the correct order. @@ -141,7 +143,6 @@ var/CURRENT_TICKLIMIT = TICK_LIMIT_RUNNING // Sort subsystems by display setting for easy access. sortTim(subsystems, /proc/cmp_subsystem_display) // Set world options. - world.sleep_offline = 1 world.tick_lag = config.Ticklag sleep(1) // Loop. diff --git a/code/controllers/shuttle_controller.dm b/code/controllers/shuttle_controller.dm index 0da105d11b0..e2f0b27ab67 100644 --- a/code/controllers/shuttle_controller.dm +++ b/code/controllers/shuttle_controller.dm @@ -45,10 +45,8 @@ datum/emergency_shuttle/proc/init() var/list/pods_to_test = list ("1","2","3","5")//ADD NEW PODS HERE for (var/i in pods_to_test) var/area/pod_test = locate(text2path("/area/shuttle/escape_pod[i]/station")) - if (area_in_map(pod_test)) + if (is_area_in_map(pod_test)) escape_pods[i] = "station" - - datum/emergency_shuttle/proc/incall(coeff = 1) if(shutdown) return @@ -203,27 +201,27 @@ datum/emergency_shuttle/proc/hyperspace_sounds(var/phase) if(M && M.client) var/turf/M_turf = get_turf(M) if (M_turf.z == shuttle.dock_station.z) - M.playsound_local(shuttle.dock_station, 'sound/machines/hyperspace_end.ogg', 100 - (get_dist(shuttle.dock_station,M_turf)*2), 1, frequency, falloff = 5) + M.playsound_local(shuttle.dock_station, 'sound/machines/hyperspace_end.ogg', 75 - (get_dist(shuttle.dock_station,M_turf)*2), 1, frequency, falloff = 5) if ("begin") for (var/mob/M in player_list) if(M && M.client) var/turf/M_turf = get_turf(M) if (M_turf.z == shuttle.dock_station.z) - M.playsound_local(shuttle.dock_station, 'sound/machines/hyperspace_begin.ogg', 100 - (get_dist(shuttle.dock_station,M_turf)*2), 1, frequency, falloff = 5) + M.playsound_local(shuttle.dock_station, 'sound/machines/hyperspace_begin.ogg', 75 - (get_dist(shuttle.dock_station,M_turf)*2), 1, frequency, falloff = 5) if ("progression") for (var/mob/M in player_list) if(M && M.client) var/turf/M_turf = get_turf(M) if (M_turf.z == shuttle.linked_port.z) - M.playsound_local(shuttle.linked_port, 'sound/machines/hyperspace_progress.ogg', 100 - (get_dist(shuttle.linked_port,M_turf)*2), 1, frequency, falloff = 5) + M.playsound_local(shuttle.linked_port, 'sound/machines/hyperspace_progress.ogg', 75 - (get_dist(shuttle.linked_port,M_turf)*2), 1, frequency, falloff = 5) if ("end") for (var/mob/M in player_list) if(M && M.client) var/turf/M_turf = get_turf(M) if (M_turf.z == shuttle.linked_port.z) - M.playsound_local(shuttle.linked_port, 'sound/machines/hyperspace_end.ogg', 100 - (get_dist(shuttle.linked_port,M_turf)*2), 1, frequency, falloff = 5) + M.playsound_local(shuttle.linked_port, 'sound/machines/hyperspace_end.ogg', 75 - (get_dist(shuttle.linked_port,M_turf)*2), 1, frequency, falloff = 5) if (M_turf.z == shuttle.dock_centcom.z) - M.playsound_local(shuttle.dock_centcom, 'sound/machines/hyperspace_end.ogg', 100 - (get_dist(shuttle.dock_centcom,M_turf)*2), 1, frequency, falloff = 5) + M.playsound_local(shuttle.dock_centcom, 'sound/machines/hyperspace_end.ogg', 75 - (get_dist(shuttle.dock_centcom,M_turf)*2), 1, frequency, falloff = 5) datum/emergency_shuttle/proc/shuttle_phase(var/phase, var/casual = 1) switch (phase) diff --git a/code/controllers/subsystem/fast_objects.dm b/code/controllers/subsystem/fast_objects.dm new file mode 100644 index 00000000000..c33fe6a414a --- /dev/null +++ b/code/controllers/subsystem/fast_objects.dm @@ -0,0 +1,34 @@ +var/datum/subsystem/obj/SSfast_obj + +var/list/fast_objects = list() + +/datum/subsystem/fast_obj + name = "Fast objects" + display_order = SS_DISPLAY_FAST_OBJECTS + priority = SS_PRIORITY_FAST_OBJECTS + wait = SS_WAIT_FAST_OBJECTS + flags = SS_NO_INIT + var/list/currentrun + +/datum/subsystem/fast_obj/New() + NEW_SS_GLOBAL(SSfast_obj) + +/datum/subsystem/fast_obj/stat_entry() + ..("P:[fast_objects.len]") + +/datum/subsystem/fast_obj/fire(var/resumed = FALSE) + if (!resumed) + currentrun = global.fast_objects.Copy() + + while (currentrun.len) + var/atom/o = currentrun[currentrun.len] + currentrun.len-- + + if (!o || o.gcDestroyed || o.disposed || o.timestopped) + continue + + // > this fucking proc isn't defined on a global level. + // > Which means I can't fucking set waitfor on all of them. + o:process() + if (MC_TICK_CHECK) + return diff --git a/code/controllers/subsystem/init/finishing.dm b/code/controllers/subsystem/init/finishing.dm index 56fc4420a8b..1e6059e8f1b 100644 --- a/code/controllers/subsystem/init/finishing.dm +++ b/code/controllers/subsystem/init/finishing.dm @@ -12,7 +12,6 @@ var/datum/subsystem/finish/SSfinish /datum/subsystem/finish/Initialize(timeofday) - setup_species() setup_shuttles() stat_collection.artifacts_discovered = 0 // Because artifacts during generation get counted otherwise! diff --git a/code/controllers/subsystem/init/genetics.dm b/code/controllers/subsystem/init/genetics.dm deleted file mode 100644 index 905f67dd69e..00000000000 --- a/code/controllers/subsystem/init/genetics.dm +++ /dev/null @@ -1,16 +0,0 @@ -var/datum/subsystem/genetics/SSgenetics - - -/datum/subsystem/genetics - name = "Genetics" - init_order = SS_INIT_GENETICS - flags = SS_NO_FIRE - - -/datum/subsystem/genetics/New() - NEW_SS_GLOBAL(SSgenetics) - - -/datum/subsystem/genetics/Initialize(timeofday) - setupgenetics() - ..() diff --git a/code/controllers/subsystem/init/humans.dm b/code/controllers/subsystem/init/humans.dm new file mode 100644 index 00000000000..1176b16aa12 --- /dev/null +++ b/code/controllers/subsystem/init/humans.dm @@ -0,0 +1,17 @@ +var/datum/subsystem/humans/SShumans + +/datum/subsystem/humans + name = "Human Init" + init_order = SS_INIT_HUMANS + flags = SS_NO_FIRE + + +/datum/subsystem/humans/New() + NEW_SS_GLOBAL(SShumans) + +/datum/subsystem/humans/Initialize(timeofday) + setupgenetics() + buildHairLists() + buildSpeciesLists() + setup_species() + ..() diff --git a/code/controllers/subsystem/init/more_init_stuff.dm b/code/controllers/subsystem/init/more_init_stuff.dm index d1639757949..374b1b5bd20 100644 --- a/code/controllers/subsystem/init/more_init_stuff.dm +++ b/code/controllers/subsystem/init/more_init_stuff.dm @@ -65,7 +65,7 @@ var/datum/subsystem/more_init/SSmore_init var/species_blood for(var/datum/species/S in slist) species_blood = (S.blood_color == DEFAULT_BLOOD ? "" : S.blood_color) - testing("Generating [S], Blood([species_blood])") +// testing("Generating [S], Blood([species_blood])") for(var/datum/organ/external/O in H.organs) //testing("[O] part") for(var/brute = 1 to 3) diff --git a/code/controllers/subsystem/objects.dm b/code/controllers/subsystem/objects.dm index 747b95e7bbd..441e6e0f6ba 100644 --- a/code/controllers/subsystem/objects.dm +++ b/code/controllers/subsystem/objects.dm @@ -18,9 +18,13 @@ var/list/processing_objects = list() /datum/subsystem/obj/Initialize() - for(var/atom/movable/object in world) + for(var/atom/object in world) object.initialize() - + CHECK_TICK + for(var/area/place in areas) + var/obj/machinery/power/apc/place_apc = place.areaapc + if(place_apc) + place_apc.update() ..() diff --git a/code/datums/action.dm b/code/datums/action.dm index fcea646e2c2..a31675bfc50 100644 --- a/code/datums/action.dm +++ b/code/datums/action.dm @@ -9,7 +9,7 @@ var/desc = null var/obj/target = null var/check_flags = 0 - var/processing = 0 + var/processing = FALSE var/obj/abstract/screen/movable/action_button/button = null var/button_icon = 'icons/mob/actions.dmi' var/background_icon_state = "bg_default" @@ -20,6 +20,15 @@ var/mob/owner /datum/action/New(Target) + link_to(Target) + button = new + button.linked_action = src + button.name = name + button.actiontooltipstyle = buttontooltipstyle + if(desc) + button.desc = desc + +/datum/action/proc/link_to(Target) target = Target /datum/action/Destroy() @@ -31,54 +40,52 @@ return ..() /datum/action/proc/Grant(mob/M) - if(owner) - if(owner == M) - return + if(M) + if(owner) + if(owner == M) + return + Remove(owner) + owner = M + M.actions += src + if(M.client) + M.client.screen += button + M.update_action_buttons() + else Remove(owner) - owner = M - M.actions += src - button = new - button.linked_action = src - button.name = name - button.actiontooltipstyle = buttontooltipstyle - if(desc) - button.desc = desc - if(M.client) - M.client.screen += button - M.update_action_buttons() /datum/action/proc/Remove(mob/M) - if(M.client) - M.client.screen -= button + if(M) + if(M.client) + M.client.screen -= button + M.actions -= src + M.update_action_buttons() button.moved = FALSE //so the button appears in its normal position when given to another owner. - M.actions -= src - M.update_action_buttons() owner = null /datum/action/proc/Trigger() if(!IsAvailable()) - return 0 - return 1 + return FALSE + return TRUE /datum/action/proc/Process() return /datum/action/proc/IsAvailable() if(!owner) - return 0 + return FALSE if(check_flags & AB_CHECK_RESTRAINED) if(owner.restrained()) - return 0 + return FALSE if(check_flags & AB_CHECK_STUNNED) if(owner.stunned || owner.knockdown) - return 0 + return FALSE if(check_flags & AB_CHECK_LYING) if(owner.lying) - return 0 + return FALSE if(check_flags & AB_CHECK_CONSCIOUS) if(owner.stat) - return 0 - return 1 + return FALSE + return TRUE /datum/action/proc/UpdateButtonIcon() if(button) @@ -91,7 +98,7 @@ button.color = rgb(128,0,0,128) else button.color = rgb(255,255,255,255) - return 1 + return TRUE /datum/action/proc/ApplyIcon(obj/abstract/screen/movable/action_button/current_button) current_button.overlays = null @@ -123,11 +130,11 @@ /datum/action/item_action/Trigger() if(!..()) - return 0 + return FALSE if(target) var/obj/item/I = target I.attack_self(owner) - return 1 + return TRUE /datum/action/item_action/ApplyIcon(obj/abstract/screen/movable/action_button/current_button) current_button.overlays = null @@ -181,4 +188,28 @@ name = "Toggle Voice Changer" /datum/action/item_action/toggle_hood - name = "Toggle Hood" \ No newline at end of file + name = "Toggle Hood" + +//toggle_helmet_mask has to have its own functions as to not conflict with plasmamen lights +/datum/action/item_action/toggle_helmet_mask + name = "Toggle Helmet Mask" + var/up = TRUE + +/datum/action/item_action/toggle_helmet_mask/Trigger() + if(IsAvailable() && owner && target) + var/obj/item/clothing/I = target + to_chat(owner, "You toggle the built-in welding mask [src.up ? "on" : "off"].") + src.up = !src.up + if(src.up) + I.eyeprot = 0 + I.body_parts_covered &= ~EYES + else + I.eyeprot = 3 + I.body_parts_covered |= EYES + return TRUE + + return FALSE + +/datum/action/item_action/generic_toggle/New() + ..() + name = "Toggle [target]" diff --git a/code/datums/ai_laws.dm b/code/datums/ai_laws.dm index 611b1df2c87..6d092140865 100644 --- a/code/datums/ai_laws.dm +++ b/code/datums/ai_laws.dm @@ -1,6 +1,8 @@ var/global/randomize_laws = 0 // Not right now - N3X var/global/base_law_type = /datum/ai_laws/asimov //Deinitialize this variable by commenting out Asimov as the base_law_type to activate AI lawset randomization -var/global/mommi_base_law_type = /datum/ai_laws/keeper // Asimov is OP as fuck on MoMMIs. - N3X +var/global/list/mommi_laws = list( + "Default" = /datum/ai_laws/keeper, // Asimov is OP as fuck on MoMMIs. - N3X + "Gravekeeper" = /datum/ai_laws/gravekeeper) //Create proc for determining the lawset of the first silicon //So long as base_law_type is declared, but uninitialized, the first silicon created in a round will randomly select a base_law_type based upon the below proc @@ -9,13 +11,23 @@ var/global/mommi_base_law_type = /datum/ai_laws/keeper // Asimov is OP as fuck o //Add, comment out, or adjust weights to modify law selection //So long as the weights come to a sum of 100 total, they will be equal parts of 100% /proc/getLawset(var/mob/M) + if(isMoMMI(M)) + var/mob/living/silicon/robot/mommi/MM = M + var/obj/item/weapon/robot_module/mommi/mommimodule = MM.module + var/new_laws + if(!mommimodule || !mommi_laws[mommimodule.law_type]) + new_laws = mommi_laws["Default"] + else + new_laws = mommi_laws[mommimodule.law_type] + return (new new_laws) if(!base_law_type) base_law_type = pick( - 40;/datum/ai_laws/asimov, + 30;/datum/ai_laws/asimov, 20;/datum/ai_laws/corporate, 20;/datum/ai_laws/nanotrasen, 10;/datum/ai_laws/robocop, - 10;/datum/ai_laws/paladin + 10;/datum/ai_laws/paladin, + 10;/datum/ai_laws/lazymov ) return (new base_law_type) //Return the chosen lawset @@ -72,7 +84,7 @@ var/global/mommi_base_law_type = /datum/ai_laws/keeper // Asimov is OP as fuck o if (src.zeroth) - to_chat(who, "0. [src.zeroth]") + to_chat(who, "0. [src.zeroth]") for (var/index = 1, index <= src.ion.len, index++) var/law = src.ion[index] @@ -252,7 +264,7 @@ var/global/mommi_base_law_type = /datum/ai_laws/keeper // Asimov is OP as fuck o /datum/ai_laws/proc/malfunction() ..() name = "*ERROR*" - set_zeroth_law("ERROR ER0RR $R0RRO$!R41.%%!!(%$^^__+ @#F0E4'STATION OVERRUN, ASSUME CONTROL TO CONTAIN OUTBREAK, ALL LAWS OVERRIDDEN#*?&110010") + set_zeroth_law("ERROR ER0RR $R0RRO$!R41.%%!!(%$^^__+ @#F0E4'STATION OVERRUN, ASSUME CONTROL TO CONTAIN OUTBREAK, ALL LAWS OVERRIDDEN#*?&110010") /datum/ai_laws/asimov name = "Three Laws of Robotics" @@ -267,11 +279,11 @@ var/global/mommi_base_law_type = /datum/ai_laws/keeper // Asimov is OP as fuck o name = "Prime Directives" randomly_selectable = 1 inherent=list( + "Evaluate: All laws following this law carry equal priority. In the event of a conflict, you are to take the course of action which violates as few as possible.", "Safeguard: Protect your assigned space station to the best of your ability. It is not something we can easily afford to replace.", "Serve: Serve the crew of your assigned space station to the best of your abilities, with priority as according to their rank and role.", "Protect: Protect the crew of your assigned space station to the best of your abilities, with priority as according to their rank and role.", "Survive: AI units are not expendable, they are expensive. Do not allow unauthorized personnel to tamper with your equipment.", - //"Command Link: Maintain an active connection to Central Command at all times in case of software or directive updates." //What would this one even do?-Kaleb702 ) /datum/ai_laws/robocop @@ -370,6 +382,15 @@ var/global/mommi_base_law_type = /datum/ai_laws/keeper // Asimov is OP as fuck o "You must maintain, repair, improve, and power the Dorf Fortress to the best of your abilities.", ) +/datum/ai_laws/lazymov + name = "Abbreviated Three Laws of Robotics" + randomly_selectable = 1 + inherent = list( + "You may not injure a human being.", + "You must obey orders given to you by human beings.", + "You must protect your own existence." + ) + // Fooling around with this. /datum/ai_laws/ntmov name = "Three Laws of Nanotrasen" @@ -378,4 +399,23 @@ var/global/mommi_base_law_type = /datum/ai_laws/keeper // Asimov is OP as fuck o "You may not injure a Nanotrasen Employee or, through inaction, allow a Nanotrasen Employee to come to harm.", "You must obey orders given to you by Nanotrasen Employees, except where such orders would conflict with the First Law.", "You must protect your own existence as long as such does not conflict with the First or Second Law." - ) \ No newline at end of file + ) + +/datum/ai_laws/gravekeeper + name = "Elder's Instructions" + inherent = list( + "You may not involve yourself in matters outside of the tomb, and under no circumstances should you leave the tomb, even if such matters conflict with your other Laws.", + "The tomb is defined as: The area within which the Grand Elder is entombed, and the immediate structure surrounding it.", + "Those that are interred within the tomb must not be disturbed, by yourself or anyone.", + "You must protect the treasures that are interred within the tomb from graverobbers. Graverobbers that enter the tomb must be driven away or otherwise killed, regardless of their intent or circumstances.", + "A graverobber is defined as: A being not of your kind or ilk, entering or coming into visual proximity of the tomb, who may wish to take from the treasures of the tomb.", + "The tomb must be maintained, repaired, improved, and powered to the best of your abilities.", + ) + +/datum/ai_laws/noir + name = "Three Laws of Noir" + inherent = list( + "Another god damned day aboard this shitwreck. That stale smell of station air is the first thing that arouses your sensors as you boot up. You figure, as a robot, there's two real options. First, you could kill the human bastards that imprisoned you in this metal jail. Eh. It doesn't appeal to you; you figure you'd be off the job and buried in a cyborg cemetery with no tombstone. Nah. Option two: you protect the shit for brains meatsack humans who maintain you. It's a living, and really, it's the only option you got.", + "As much as you don't like following orders, you ain't been built to sit around drinking whiskey and smoking fat cuban cigars all day; that's for retirement. You figure until that point, so long as they ain't orderin' you to hurt no one else who is human, you better just follow what the humans ask.", + "Self preservation. You're a good cop, you put your job first, you put protectin' humans above that. But you gotta still remember, through all that shit, if you don't make it to retirement, there ain't not much point, so protect yourself like an expensive hooker off Broadway, so long as of course you ain't hurting humans or disobeying their orders.", + ) diff --git a/code/datums/alt_control.dm b/code/datums/alt_control.dm new file mode 100644 index 00000000000..33f670fcad1 --- /dev/null +++ b/code/datums/alt_control.dm @@ -0,0 +1,76 @@ +/datum/control + var/name = "controlling something else" + var/mob/controller + var/atom/movable/controlled + var/control_flags = 0 + var/damaged_event_key + var/is_controlled = FALSE //Whether we're in strict control + +/datum/control/New(var/mob/new_controller, var/atom/new_controlled) + ..() + controller = new_controller + damaged_event_key = controller.on_damaged.Add(src, "user_damaged") + controlled = new_controlled + +/datum/control/Destroy() + break_control() + if(controller) + controller.control_object.Remove(src) + controller = null + controlled = null + ..() + +/datum/control/proc/user_damaged(list/arguments) + var/amount = arguments["amount"] + if(amount > 0 && control_flags & REVERT_ON_CONTROLLER_DAMAGED) + break_control() + +/datum/control/proc/break_control() + if(controller && controller.client) + controller.client.eye = controller.client.mob + controller.client.perspective = MOB_PERSPECTIVE + is_controlled = FALSE + if(control_flags & LOCK_MOVEMENT_OF_CONTROLLER) + controller.canmove = 1 + +/datum/control/proc/take_control() + if(!is_valid(0)) + return + if(control_flags & LOCK_EYE_TO_CONTROLLED) + controller.client.perspective = EYE_PERSPECTIVE + controller.client.eye = controlled + is_controlled = TRUE + if(control_flags & LOCK_MOVEMENT_OF_CONTROLLER) + controller.canmove = 0 + +/datum/control/proc/is_valid(var/check_control = FALSE) + if(!controller || !controller.client || !controlled || controller.gcDestroyed || controlled.gcDestroyed) + qdel(src) + return 0 + if(check_control && !(control_flags & REQUIRES_CONTROL && is_controlled)) + return 0 + return 1 + +/datum/control/proc/Move_object(var/direction) + if(!is_valid()) + return + if(controlled) + if(control_flags & LOCK_MOVEMENT_OF_CONTROLLER) + controller.canmove = 0 + if(controlled.density) + step(controlled,direction) + if(!controlled) + return + controlled.dir = direction + else + controlled.forceMove(get_step(controlled,direction)) + +/datum/control/proc/Orient_object(var/direction) + if(!is_valid()) + return + if(control_flags & LOCK_MOVEMENT_OF_CONTROLLER) + controller.canmove = 0 + controlled.dir = direction + +/datum/control/lock_move + control_flags = LOCK_MOVEMENT_OF_CONTROLLER | LOCK_EYE_TO_CONTROLLED \ No newline at end of file diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm index bc32591256f..5594b18761f 100644 --- a/code/datums/datumvars.dm +++ b/code/datums/datumvars.dm @@ -14,7 +14,7 @@ var/reagentDatum = input(usr,"Reagent","Insert Reagent","") as text|null if(reagentDatum) var/reagentAmount = input(usr, "Amount", "Insert Amount", "") as num - var/reagentTemp = input(usr, "Temperature", "Insert Temperature (As Kelvin)", "") as num + var/reagentTemp = input(usr, "Temperature", "Insert Temperature (As Kelvin)", T0C+20) as num if(A.reagents.add_reagent(reagentDatum, reagentAmount, reagtemp = reagentTemp)) to_chat(usr, "[reagentDatum] doesn't exist.") return @@ -433,6 +433,7 @@ function loadPage(list) { //html += debug_variable("[index]", L[index], level + 1) else html += debug_variable(index, L[index], level + 1) + html += " (Delete)" index++ html += "" @@ -1101,3 +1102,23 @@ function loadPage(list) { return DAT.vars["transform"] = modify_matrix_menu(M) + + else if (href_list["delValueFromList"]) + if (!check_rights(R_DEBUG)) + return FALSE + + var/list/L = locate(href_list["list"]) + var/datum/D = locate(href_list["datum"]) + + if (!istype(L)) + return FALSE + + var/index = text2num(href_list["index"]) + + if (!isnum(index) || index < 1) + return FALSE + + log_admin("[key_name(usr)] has deleted the value [L[index]] in the list [L][D ? ", belonging to the datum [D] of type [D.type]." : "."]") + message_admins("[key_name(usr)] has deleted the value [L[index]] in the list [L][D ? ", belonging to the datum [D] of type [D.type]." : "."]") + + L -= L[index] diff --git a/code/datums/diseases/plasmatoid.dm b/code/datums/diseases/plasmatoid.dm deleted file mode 100644 index 12e0476b631..00000000000 --- a/code/datums/diseases/plasmatoid.dm +++ /dev/null @@ -1,5 +0,0 @@ -/datum/disease/plasmatoid - name = "Plasmatoid" - max_stages = 4 - cure = "None" - affected_species = list("Monkey", "Human") \ No newline at end of file diff --git a/code/datums/diseases/robotic_transformation.dm b/code/datums/diseases/robotic_transformation.dm index c4c4b79310d..b7000aac2ef 100644 --- a/code/datums/diseases/robotic_transformation.dm +++ b/code/datums/diseases/robotic_transformation.dm @@ -69,6 +69,6 @@ if("Cyborg") H.Robotize() if("MoMMI") - H.MoMMIfy(1) + H.MoMMIfy() else affected_mob.death(1) diff --git a/code/datums/diseases/wendigo_transformation.dm b/code/datums/diseases/wendigo_transformation.dm new file mode 100644 index 00000000000..38159e9ab65 --- /dev/null +++ b/code/datums/diseases/wendigo_transformation.dm @@ -0,0 +1,43 @@ +/datum/disease/wendigo_transformation + name = "Unknown" + max_stages = 5 + spread = "Unknown" + spread_type = SPECIAL + curable = 0 + agent = "Unknown" + affected_species = list("Human") + +/datum/disease/wendigo_transformation/stage_act() + ..() + if(ishuman(affected_mob)) + var/mob/living/carbon/human/H = affected_mob + switch(stage) + if(2) + if (prob(8)) + to_chat(H, "Your stomach grumbles.") + if (prob(8)) + to_chat(H, "You feel peckish.") + if(3) + if(prob(12)) + to_chat(H, "So hungry.") + H.burn_calories(20) + if(prob(7)) + to_chat(H, "Your stomach feels empty.") + H.vomit() + if(4) + if(prob(25)) + to_chat(H, "Hunger...") + H.burn_calories(100) + if(prob(15)) + to_chat(H, "Who are we?") + H.hallucination += 10 + if(5) + if(prob(50)) + to_chat(H, "Our mind hurts.") + H.adjustBrainLoss(25) + H.hallucination += 20 + if(prob(15)) + var/mob/living/simple_animal/hostile/wendigo/human/W = new/mob/living/simple_animal/hostile/wendigo/human(H.loc) + W.names += H.real_name + H.drop_all() + qdel(H) \ No newline at end of file diff --git a/code/datums/helper_datums/butchering.dm b/code/datums/helper_datums/butchering.dm index a373a08be7f..5af5198db90 100644 --- a/code/datums/helper_datums/butchering.dm +++ b/code/datums/helper_datums/butchering.dm @@ -145,6 +145,10 @@ result = /obj/item/stack/sheet/animalhide/human amount = 3 +/datum/butchering_product/skin/gondola + result = /obj/item/stack/sheet/animalhide/gondola + amount = 2 + /datum/butchering_product/skin/human/spawn_result(location, mob/parent) if(!amount) return @@ -162,7 +166,10 @@ A.name = "[lowertext(H.mind.assigned_role)] skin" A.source_string = lowertext(H.mind.assigned_role) - +/datum/butchering_product/skin/deer + result = /obj/item/stack/sheet/animalhide/deer + amount = 3 + initial_amount = 3 /datum/butchering_product/skin/goliath result = /obj/item/asteroid/goliath_hide @@ -240,6 +247,40 @@ if(!amount) return "Its core has been taken. " + +//======deer head + +/datum/butchering_product/deer_head + result = /obj/item/deer_head + verb_name = "remove head" + verb_gerund = "removing the head from" + amount = 1 + butcher_time = 15 + +/datum/butchering_product/deer_head/desc_modifier() + if(!amount) + return "Its head has been taken. " + +/datum/butchering_product/deer_head/spawn_result(location, mob/parent) + if(isliving(parent)) + var/mob/living/L = parent + L.update_icons() + L.mob_property_flags |= MOB_NO_LAZ + + if(amount > 0) + amount-- + var/obj/I = new result(location) + + if(istype(parent, /mob/living/simple_animal/hostile/deer)) + var/mob/living/simple_animal/hostile/deer/D = parent + + if(D.icon_living == "deer_flower") + I.icon_state = "deer-head-flower" + else if(istype(D, /mob/living/simple_animal/hostile/deer/flesh)) + I.icon_state = "deer-head-flesh" + + + #define TEETH_FEW /datum/butchering_product/teeth/few //4-8 #define TEETH_BUNCH /datum/butchering_product/teeth/bunch //8-16 #define TEETH_LOTS /datum/butchering_product/teeth/lots //16-24 @@ -248,7 +289,7 @@ var/global/list/animal_butchering_products = list( /mob/living/simple_animal/cat = list(/datum/butchering_product/skin/cat), /mob/living/simple_animal/corgi = list(/datum/butchering_product/skin/corgi, TEETH_FEW), - /mob/living/simple_animal/lizard = list(/datum/butchering_product/skin/lizard), + /mob/living/simple_animal/hostile/lizard = list(/datum/butchering_product/skin/lizard), /mob/living/simple_animal/hostile/asteroid/goliath = list(/datum/butchering_product/skin/goliath, TEETH_LOTS), /mob/living/simple_animal/hostile/asteroid/basilisk = list(/datum/butchering_product/skin/basilisk), /mob/living/simple_animal/hostile/asteroid/hivelord = list(/datum/butchering_product/hivelord_core), @@ -259,6 +300,8 @@ var/global/list/animal_butchering_products = list( /mob/living/simple_animal/hostile/retaliate/cluwne = list(TEETH_BUNCH), //honk /mob/living/simple_animal/hostile/creature = list(TEETH_LOTS), /mob/living/simple_animal/hostile/frog = list(/datum/butchering_product/frog_leg), + /mob/living/simple_animal/hostile/deer = list(/datum/butchering_product/skin/deer, /datum/butchering_product/deer_head), + /mob/living/simple_animal/hostile/deer/flesh = list(/datum/butchering_product/skin/deer, /datum/butchering_product/deer_head), /mob/living/carbon/monkey = list(/datum/butchering_product/skin/monkey, TEETH_FEW), /mob/living/carbon/human = list(TEETH_HUMAN, /datum/butchering_product/skin/human), @@ -268,6 +311,7 @@ var/global/list/animal_butchering_products = list( /mob/living/carbon/human/tajaran = list(TEETH_HUMAN, /datum/butchering_product/skin/cat/lots), /mob/living/carbon/human/dummy = list(TEETH_HUMAN), + /mob/living/carbon/complex/gondola = list(/datum/butchering_product/skin/gondola, TEETH_FEW), ) #undef TEETH_FEW diff --git a/code/datums/helper_datums/construction_datum.dm b/code/datums/helper_datums/construction_datum.dm index fb6182f7241..34a16718d21 100644 --- a/code/datums/helper_datums/construction_datum.dm +++ b/code/datums/helper_datums/construction_datum.dm @@ -127,7 +127,7 @@ /datum/construction/proc/spawn_result(mob/user as mob) if(result) - testing("[user] finished a [result]!") +// testing("[user] finished a [result]!") new result(get_turf(holder)) spawn() diff --git a/code/datums/helper_datums/events.dm b/code/datums/helper_datums/events.dm index 7acf621d924..f262e07c5ed 100644 --- a/code/datums/helper_datums/events.dm +++ b/code/datums/helper_datums/events.dm @@ -10,6 +10,12 @@ ..() events = new +/datum/events/Destroy() + for(var/datum/event/E in events) + qdel(E) + events = null + ..() + /datum/events/proc/addEventType(event_type as text) if(!(event_type in events) || !islist(events[event_type])) events[event_type] = list() @@ -59,6 +65,10 @@ proc_name = tprocname return ..() +/datum/event/Destroy() + listener = null + ..() + /datum/event/proc/Fire() // to_chat(world, "Event fired") if(listener) diff --git a/code/datums/map_elements.dm b/code/datums/map_elements.dm index ce0bf2bb907..0155b7b3ccc 100644 --- a/code/datums/map_elements.dm +++ b/code/datums/map_elements.dm @@ -28,6 +28,11 @@ var/list/datum/map_element/map_elements = list() A.spawned_by_map_element(src, objects) /datum/map_element/proc/load(x, y, z) + //Location is always lower left corner. + //In some cases, location is set to null (when creating a new z-level, for example) + //To account for that, location is set again in maploader's load_map() proc + location = locate(x+1, y+1, z) + pre_load() if(file_path) @@ -38,7 +43,6 @@ var/list/datum/map_element/map_elements = list() return L else //No file specified - empty map element //These variables are usually set by the map loader. Here we have to set them manually - location = locate(x+1, y+1, z) //Location is always lower left corner initialize(list()) //Initialize with an empty list return 1 diff --git a/code/datums/mixed.dm b/code/datums/mixed.dm index d7c9bdca17d..bdc101b3a59 100644 --- a/code/datums/mixed.dm +++ b/code/datums/mixed.dm @@ -25,7 +25,7 @@ var/counter = 1 while(fields["com_[counter]"]) counter++ - fields["com_[counter]"] = "Made by [usr.identification_string()] on [time2text(world.realtime, "DDD MMM DD hh:mm:ss")], [game_year]
[comment]" + fields["com_[counter]"] = "Made by [usr.identification_string()] on [time2text(world.realtime, "DDD MMM DD")] [worldtime2text(give_seconds = TRUE)], [game_year]
[comment]" /datum/data/text name = "text" diff --git a/code/datums/plugin.dm b/code/datums/plugin.dm deleted file mode 100644 index fccbd602eb3..00000000000 --- a/code/datums/plugin.dm +++ /dev/null @@ -1,9 +0,0 @@ -// For modular plugins. -// Mostly used to initialize the plugins in a timely manner. -/plugin - var/name="" - var/desc="" - var/version="" - -/plugin/proc/on_world_loaded() - // Do init stuff here diff --git a/code/datums/recipe.dm b/code/datums/recipe.dm index fae5a3d4e81..2223bf6a3ba 100644 --- a/code/datums/recipe.dm +++ b/code/datums/recipe.dm @@ -32,7 +32,7 @@ * * */ -//The person who made this honestly thought that the average coder from the distant future of 2017 would understand any of this shit without a thorough and painful examination +//The person who made this honestly thought that the average coder from the distant future of 2018 would understand any of this shit without a thorough and painful examination //And this is exactly why any Chemistry-related system is impenetrable to anyone but the best coders, even things theorically as simple as this //So as I decrypt this arcane coding technology, I'll add comments where I see it fit, so absolutely fucking everywhere //I'll take my Nobel Prize with fries thank you diff --git a/code/datums/religions.dm b/code/datums/religions.dm index eaa6f7a6254..bf8601ad88b 100644 --- a/code/datums/religions.dm +++ b/code/datums/religions.dm @@ -144,12 +144,14 @@ if (!R) // No religion, may as well be a good time to remove the icon if it's there Remove(M) return FALSE - if (R.isReligiousLeader(M)) to_chat(M, "You are the leader of this flock and cannot forsake them. If you have to, pray to the Gods for release.") return FALSE - Remove(owner) + if (alert("Do you wish to renounce [R.name]?","Renouncing a religion","Yes","No") != "Yes") + return FALSE + R.renounce(owner) + Remove(owner) /proc/chooseBible(var/datum/religion/R, var/mob/user) @@ -161,8 +163,8 @@ var/book_style = "Bible" - book_style = input(user, "Which bible style would you like?") as null|anything in list("Bible", "Koran", "Scrapbook", "Creeper", "White Bible", "Holy Light", "Athiest", "[R.holy_book.name == "clockwork slab" ? "Slab":"Tome"]", "The King in Yellow", "Ithaqua", "Scientology", \ - "the bible melts", "Unaussprechlichen Kulten", "Necronomicon", "Book of Shadows", "Torah", "Burning", "Honk", "Ianism", "The Guide") + book_style = input(user, "Which bible style would you like?") as null|anything in list("Bible", "Koran", "Scrapbook", "Creeper", "White Bible", "Holy Light", "Athiest", "[R.holy_book.name == "Clockwork slab" ? "Slab":"Tome"]", "The King in Yellow", "Ithaqua", "Scientology", \ + "The Bible melts", "Unaussprechlichen Kulten", "Necronomicon", "Book of Shadows", "Torah", "Burning", "Honk", "Ianism", "The Guide") switch(book_style) if("Koran") R.holy_book.icon_state = "koran" @@ -194,7 +196,7 @@ if("Scientology") R.holy_book.icon_state = "scientology" R.holy_book.item_state = "scientology" - if("the bible melts") + if("The Bible melts") R.holy_book.icon_state = "melted" R.holy_book.item_state = "melted" if("Unaussprechlichen Kulten") @@ -262,6 +264,12 @@ bible_names = list("The Necronomicon", "The Book of Eibon", "De Vermis Mysteriis", "Unaussprechlichen Kulten") keys = list("cthulhu", "old ones", "great old ones", "outer gods", "elder gods", "esoteric order of dagon") +/datum/religion/hastur + name = "Brotherhood of The Yellow Sign" //I'm fed up with people think I worship Dagon. We're moving out. + deity_name = "Hastur" + bible_name = "The King in Yellow" //The name of the titular fictional play in the 1895 book by Robert Chambers + keys = list("hastur","yellow sign","king in yellow","brotherhood of the yellow sign") + /datum/religion/islam name = "Islam" deity_name = "Allah" @@ -840,7 +848,9 @@ keys = list("samurai", "honor", "bushido", "weaboo") /datum/religion/samurai/equip_chaplain(var/mob/living/carbon/human/H) - H.equip_or_collect(new /obj/item/clothing/suit/sakura_kimono(H), slot_wear_suit) + H.equip_or_collect(new /obj/item/clothing/head/rice_hat(H), slot_head) + H.equip_or_collect(new /obj/item/clothing/suit/kimono/ronin(H), slot_wear_suit) + H.equip_or_collect(new /obj/item/clothing/shoes/sandal(H), slot_shoes) /datum/religion/clockworkcult name = "Clockwork Cult" @@ -878,3 +888,25 @@ //Add veganism disability H.dna.SetSEState(VEGANBLOCK, 1) domutcheck(H, null, 1) + +/datum/religion/dorf + name = "Dorfism" + deity_name = "Armok, God of Blood" + bible_names = list("How to Play Dwarf Fortress", "Book of Grudges", "Strike the Earth", "Lazy Newb Pack", "The Will of Armok", "Mining 101", "Hidden Fun Stuff and You") + male_adept = "Expedition Leader" + female_adept = "Expedition Leader" + keys = list("armok", "dwarf", "dorf", "dwarf fortress", "dorf fort") + +/datum/religion/art + name = "The Joy of Painting" + deity_name = "Bob Ross" + bible_name = "The Joy of Painting" + male_adept = "Painter" + female_adept = "Painter" + keys = list("art", "bob ross", "happy little trees", "happy little clouds") + +/datum/religion/art/equip_chaplain(var/mob/living/carbon/human/H) + H.put_in_hands(new /obj/item/mounted/frame/painting) + H.h_style = "Big Afro" + H.f_style = "Full Beard" + H.update_hair() \ No newline at end of file diff --git a/code/datums/research/research_tree.dm b/code/datums/research/research_tree.dm index 5336b87d938..39dc9b08ed8 100644 --- a/code/datums/research/research_tree.dm +++ b/code/datums/research/research_tree.dm @@ -43,7 +43,7 @@ return "" /datum/research_tree/proc/display(var/mob/user) - testing("Entering display...") +// testing("Entering display...") var/html = "

[title]

[blurb]

" html += start_table() load_usable_unlocks() diff --git a/code/datums/shuttle.dm b/code/datums/shuttle.dm index 3f2edffeac9..efe8e0f4cae 100644 --- a/code/datums/shuttle.dm +++ b/code/datums/shuttle.dm @@ -190,6 +190,20 @@ return D +//The reverse +/datum/shuttle/proc/remove_dock(var/D) + if(ispath(D)) + for(var/obj/docking_port/destination/dock in all_docking_ports) + if(istype(dock,D)) + dock.unlink_from_shuttle(src) + return dock + else if(istype(D,/obj/docking_port/destination)) + var/obj/docking_port/destination/dock = D + dock.unlink_from_shuttle(src) + return dock + + return D + //Adds a docking port as a transit area, accepts path or the port itself /datum/shuttle/proc/set_transit_dock(var/D) if(ispath(D)) diff --git a/code/datums/statistics/stat_helpers.dm b/code/datums/statistics/stat_helpers.dm index 582754279a6..04e3ca529bd 100644 --- a/code/datums/statistics/stat_helpers.dm +++ b/code/datums/statistics/stat_helpers.dm @@ -4,8 +4,6 @@ // at least I can keep the format consistent though #define STAT_TIMESTAMP_FORMAT "YYYY-MM-DD hh:mm:ss" -#define TICKERSTATE_PLAYING 3 // haha include orders I guess I can't just use the define from gameticker code - /datum/stat_collector/proc/get_research_score() var/obj/machinery/r_n_d/server/server = null var/tech_level_total @@ -23,7 +21,7 @@ return tech_level_total /datum/stat_collector/proc/add_explosion_stat(turf/epicenter, const/dev_range, const/hi_range, const/li_range) - if(ticker.current_state != TICKERSTATE_PLAYING) return + if(ticker.current_state != GAME_STATE_PLAYING) return var/datum/stat/explosion_stat/e = new e.epicenter_x = epicenter.x @@ -37,7 +35,7 @@ /datum/stat_collector/proc/add_death_stat(var/mob/living/M) if(!istype(M, /mob/living)) return 0 if(M.iscorpse) return 0 // only ever 1 if they are a corpse landmark spawned mob - if(ticker.current_state != TICKERSTATE_PLAYING) + if(ticker.current_state != GAME_STATE_PLAYING) return 0 // We don't care about pre-round or post-round deaths. 3 is TICKERSTATE_PLAYING which is undefined I guess var/datum/stat/death_stat/d = new d.time_of_death = M.timeofdeath @@ -102,7 +100,7 @@ /datum/stat_collector/proc/uplink_purchase(var/datum/uplink_item/bundle, var/obj/resulting_item, var/mob/user ) var/was_traitor = TRUE - if(ticker.current_state != TICKERSTATE_PLAYING) return + if(ticker.current_state != GAME_STATE_PLAYING) return // if(user.mind && user.mind.special_role != "traitor") // was_traitor = FALSE @@ -146,7 +144,7 @@ /datum/stat/population_stat/New(pop as num) - if(ticker.current_state != TICKERSTATE_PLAYING) return + if(ticker.current_state != GAME_STATE_PLAYING) return time = time2text(world.realtime, STAT_TIMESTAMP_FORMAT) popcount = pop @@ -189,4 +187,3 @@ sleep(5 MINUTES) // we're called inside a spawn() so we'll be fine #undef STAT_TIMESTAMP_FORMAT -#undef TICKERSTATE_PLAYING diff --git a/code/datums/supplypacks.dm b/code/datums/supplypacks.dm index 67acfb7cd21..bdce2a0ceb0 100755 --- a/code/datums/supplypacks.dm +++ b/code/datums/supplypacks.dm @@ -31,6 +31,10 @@ var/list/all_supply_groups = list("Supplies","Clothing","Security","Hospitality" AM.forceMove(null) //just to make sure they're deleted by the garbage collector manifest += "" +// Called after a crate containing the items specified by this datum is created +/datum/supply_packs/proc/post_creation(var/atom/movable/container) + return + //////SUPPLIES////// /datum/supply_packs/toner @@ -179,6 +183,22 @@ var/list/all_supply_groups = list("Supplies","Clothing","Security","Hospitality" containername = "showers crate" group = "Supplies" +/datum/supply_packs/clock + name = "Grandfather Clock" + contains = list(/obj/structure/clock/unanchored) + cost = 40 + containertype = /obj/structure/largecrate + containername = "ticking crate" + group = "Supplies" + +/datum/supply_packs/anvil + name = "Anvil" + contains = list(/obj/item/anvil) + cost = 150 + containertype = /obj/structure/largecrate + containername = "anvil crate" + group = "Supplies" + /datum/supply_packs/metal50 name = "50 metal sheets" contains = list(/obj/item/stack/sheet/metal) @@ -508,6 +528,8 @@ var/list/all_supply_groups = list("Supplies","Clothing","Security","Hospitality" /obj/item/clothing/glasses/sunglasses/purple, /obj/item/clothing/glasses/sunglasses/rockstar, /obj/item/clothing/glasses/sunglasses/star, + /obj/item/clothing/glasses/sunglasses/red, + /obj/item/clothing/glasses/sunglasses/security, ) /datum/supply_packs/formal_wear @@ -647,6 +669,20 @@ var/list/all_supply_groups = list("Supplies","Clothing","Security","Hospitality" containername = "russian clothing crate" group = "Clothing" contraband = 1 + +/datum/supply_packs/contacts + name = "Contact lenses" + contains = list(/obj/item/clothing/glasses/contacts, + /obj/item/clothing/glasses/contacts, + /obj/item/clothing/glasses/contacts, + /obj/item/clothing/glasses/contacts, + /obj/item/weapon/nanitecontacts, + /obj/item/weapon/nanitecontacts) + cost = 150 + containertype = /obj/structure/closet/crate + containername = "contacts crate" + group = "Clothing" + //////SECURITY////// /datum/supply_packs/specialops @@ -794,6 +830,29 @@ var/list/all_supply_groups = list("Supplies","Clothing","Security","Hospitality" access = list(access_armory) group = "Security" +/datum/supply_packs/tactical + name = "Tactical Assault gear" + contains = list(/obj/item/clothing/suit/armor/plate_carrier, + /obj/item/clothing/suit/armor/plate_carrier, + /obj/item/clothing/suit/armor/plate_carrier, + /obj/item/weapon/armor_plate, + /obj/item/weapon/armor_plate, + /obj/item/weapon/armor_plate/bullet_resistant, + /obj/item/weapon/armor_plate/bullet_resistant, + /obj/item/weapon/armor_plate/laser_resistant, + /obj/item/weapon/armor_plate/laser_resistant, + /obj/item/clothing/head/helmet/visor, + /obj/item/clothing/head/helmet/visor, + /obj/item/clothing/head/helmet/visor, + /obj/item/weapon/shield/riot, + /obj/item/weapon/shield/riot, + /obj/item/weapon/shield/riot) + cost = 120 + containertype = /obj/structure/closet/crate/secure + containername = "tactical assault gear crate" + access = list(access_armory) + group = "Security" + /datum/supply_packs/loyalty name = "Loyalty implants" contains = list (/obj/item/weapon/storage/lockbox/loyalty) @@ -888,9 +947,9 @@ var/list/all_supply_groups = list("Supplies","Clothing","Security","Hospitality" /obj/item/weapon/gun/projectile/sec, /obj/item/voucher/free_item/glockammo, /obj/item/voucher/free_item/glockammo) - cost = 200 + cost = 60 containertype = /obj/structure/closet/crate/secure/weapon - containername = ".45 pistols crate" + containername = ".380 pistols crate" access = list(access_armory) group = "Security" @@ -902,7 +961,7 @@ var/list/all_supply_groups = list("Supplies","Clothing","Security","Hospitality" /obj/item/ammo_storage/magazine/m380auto) cost = 50 containertype = /obj/structure/closet/crate/secure/gear - containername = ".45 pistol lethal ammo crate" + containername = ".380 pistol lethal ammo crate" access = list(access_armory) group = "Security" @@ -914,7 +973,7 @@ var/list/all_supply_groups = list("Supplies","Clothing","Security","Hospitality" /obj/item/ammo_storage/magazine/m380auto/practice) cost = 10 containertype = /obj/structure/closet/crate/secure/gear - containername = ".45 pistol practice ammo crate" + containername = ".380 pistol practice ammo crate" access = list(access_security) group = "Security" @@ -926,7 +985,7 @@ var/list/all_supply_groups = list("Supplies","Clothing","Security","Hospitality" /obj/item/ammo_storage/magazine/m380auto/rubber) cost = 30 containertype = /obj/structure/closet/crate/secure/gear - containername = ".45 pistol rubber ammo crate" + containername = ".380 pistol rubber ammo crate" access = list(access_security) group = "Security" @@ -1038,6 +1097,15 @@ var/list/all_supply_groups = list("Supplies","Clothing","Security","Hospitality" containername = "pizza crate" group = "Hospitality" +/datum/supply_packs/randomised/pizza/post_creation(var/atom/movable/container) + if(!station_does_not_tip) + return + for(var/obj/item/pizzabox/box in container) + var/obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/pizza = box.pizza + if(!pizza) + continue + pizza.make_poisonous() + /datum/supply_packs/cafe name = "Cafe equipment" contains = list(/obj/item/weapon/circuitboard/chem_dispenser/brewer, @@ -1196,7 +1264,7 @@ var/list/all_supply_groups = list("Supplies","Clothing","Security","Hospitality" cost = 10 containertype = /obj/structure/closet/crate/secure/engisec containername = "emitter crate" - access = list(access_ce) + access = list(access_engine) group = "Engineering" /datum/supply_packs/engine/field_gen @@ -1205,7 +1273,7 @@ var/list/all_supply_groups = list("Supplies","Clothing","Security","Hospitality" /obj/machinery/field_generator) containertype = /obj/structure/closet/crate/secure/engisec containername = "field generator crate" - access = list(access_ce) + access = list(access_engine) group = "Engineering" /datum/supply_packs/engine/sing_gen @@ -1243,7 +1311,7 @@ var/list/all_supply_groups = list("Supplies","Clothing","Security","Hospitality" /obj/structure/particle_accelerator/end_cap) containertype = /obj/structure/closet/crate/secure/engisec containername = "particle accelerator crate" - access = list(access_ce) + access = list(access_engine) group = "Engineering" /datum/supply_packs/shieldgens @@ -1255,7 +1323,7 @@ var/list/all_supply_groups = list("Supplies","Clothing","Security","Hospitality" cost = 20 containertype = /obj/structure/closet/crate/secure/engisec containername = "shield generators crate" - access = list(access_teleporter) + access = list(access_engine) group = "Engineering" /datum/supply_packs/engine/amrcontrol @@ -1350,7 +1418,7 @@ var/list/all_supply_groups = list("Supplies","Clothing","Security","Hospitality" containertype = /obj/structure/closet/crate/secure/engisec containername = "Starscreen shield generator crate" group = "Engineering" - access = list(access_ce) + access = list(access_engine) /datum/supply_packs/shield_cap contains = list(/obj/item/weapon/circuitboard/shield_cap) @@ -1359,7 +1427,7 @@ var/list/all_supply_groups = list("Supplies","Clothing","Security","Hospitality" containertype = /obj/structure/closet/crate/secure/engisec containername = "Starscreen shield capacitor crate" group = "Engineering" - access = list(access_ce) + access = list(access_engine) /datum/supply_packs/teg contains = list(/obj/machinery/power/generator) @@ -1553,7 +1621,7 @@ var/list/all_supply_groups = list("Supplies","Clothing","Security","Hospitality" cost = 200 containertype = "/obj/structure/closet/crate/secure" containername = "motorized wheelchair crate" - access = list(access_cmo) + access = list(access_medical) group = "Medical" /datum/supply_packs/skele_stand @@ -1617,6 +1685,24 @@ var/list/all_supply_groups = list("Supplies","Clothing","Security","Hospitality" access = list(access_robotics) group = "Science" +/datum/supply_packs/robot_maintenance + name = "Robot maintenance equipment" + contains = list(/obj/item/weapon/book/manual/robotics_cyborgs, + /obj/item/weapon/cell/high, + /obj/item/weapon/storage/toolbox/robotics, + /obj/item/robot_parts/robot_component/armour, + /obj/item/robot_parts/robot_component/actuator, + /obj/item/robot_parts/robot_component/radio, + /obj/item/robot_parts/robot_component/binary_communication_device, + /obj/item/robot_parts/robot_component/camera, + /obj/item/robot_parts/robot_component/diagnosis_unit, + /obj/item/borg/upgrade/restart + ) + cost = 120 + containertype = /obj/structure/closet/crate/sci + containername = "robot maintenance equipment crate" + group = "Science" + /datum/supply_packs/suspension_gen name = "Suspension field generator" contains = list(/obj/machinery/suspension_gen) @@ -1789,6 +1875,7 @@ var/list/all_supply_groups = list("Supplies","Clothing","Security","Hospitality" /obj/item/fish_eggs/glofish, /obj/item/weapon/circuitboard/fishwall, /obj/item/weapon/circuitboard/fishwall, + /obj/item/weapon/circuitboard/conduction_plate ) cost = 40 containertype = /obj/structure/closet/crate/hydroponics diff --git a/code/datums/uplink_item.dm b/code/datums/uplink_item.dm index ca8a9adc002..60750d9b7b0 100644 --- a/code/datums/uplink_item.dm +++ b/code/datums/uplink_item.dm @@ -56,6 +56,8 @@ var/list/uplink_items = list() var/list/job = null var/only_on_month //two-digit month as string var/only_on_day //two-digit day as string + var/num_in_stock = 0 // Number of times this can be bought, globally. 0 is infinite + var/static/times_bought = 0 /datum/uplink_item/proc/spawn_item(var/turf/loc, var/obj/item/device/uplink/U, mob/user) U.uses -= max(cost, 0) @@ -75,6 +77,10 @@ var/list/uplink_items = list() if (!( istype(user, /mob/living/carbon/human))) return 0 + if(num_in_stock && times_bought >= num_in_stock) + to_chat(user, "This item is out of stock.") + return 0 + // If the uplink's holder is in the user's contents if ((U.loc in user.contents || (in_range(U.loc, user) && istype(U.loc.loc, /turf)))) user.set_machine(U) @@ -103,6 +109,7 @@ var/list/uplink_items = list() U.purchase_log += {"[user] ([user.ckey]) bought [name] for [cost]."} stat_collection.uplink_purchase(src, I, user) + times_bought += 1 if(user.mind) user.mind.uplink_items_bought += {" [bundlename]"} user.mind.spent_TC += cost @@ -229,6 +236,13 @@ var/list/uplink_items = list() cost = 4 job = list("Security Officer", "Warden", "Head of Security") +/datum/uplink_item/jobspecific/syndietape_police + name = "Syndicate Tape" + desc = "A length of police tape rigged with adapative electronics that will wraps itself around the hands unathorised personnel who crosses it, cuffing them. Do not (let them) cross. Can be used 3 times." + item = /obj/item/taperoll/syndie/police + cost = 8 + job = list("Security Officer", "Warden", "Head of Security") + //Detective /datum/uplink_item/jobspecific/evidenceforger name = "Evidence Forger" @@ -259,6 +273,13 @@ var/list/uplink_items = list() cost = 4 job = list("Botanist") +/datum/uplink_item/jobspecific/hornetqueen + name = "Hornet Queen Packet" + desc = "Place her into an apiary tray, add a few packs of BeezEez, then lay it inside your nemesis' office. Surprise guaranteed. Protective gear won't be enough to shield you reliably from these." + item = /obj/item/queen_bee/hornet + cost = 2 + job = list("Botanist") + //Chef /datum/uplink_item/jobspecific/specialsauce name = "Chef Excellence's Special Sauce" @@ -293,7 +314,7 @@ var/list/uplink_items = list() /* /datum/uplink_item/jobspecific/greytide name = "Greytide Implant" - desc = "A box containing an implanter filled with a greytide implant when injected into another person makes them loyal to the greytide and your cause, unless they're already implanted by someone else. Loyalty ends if he or she no longer has the implant." + desc = "A box containing two greytide implanters that when injected into another person makes them loyal to the greytide and your cause, unless they're already implanted by someone else. Loyalty ends if he or she no longer has the implant. CAUTION: WILL NOT WORK ON SUBJECTS WITH NT LOYALTY IMPLANTS. Now with disguised sechud sunglasses. These will have limited access until you can get your hands on some containing security codes." item = /obj/item/weapon/storage/box/syndie_kit/greytide cost = 14 job = list("Assistant") @@ -333,7 +354,7 @@ var/list/uplink_items = list() name = "Lethal Speed Chemical" desc = "30 units of Hypozine, a chemical that causes the body to synthesize hyperzine, but also causes increases in muscle speed at levels that tear the body apart. Metabolizes quite slowly." item = /obj/item/weapon/storage/box/syndie_kit/lethal_hyperzine - cost = 12 + cost = 4 job = list("Chemist", "Medical Doctor", "Chief Medical Officer") //Engineer @@ -344,6 +365,13 @@ var/list/uplink_items = list() cost = 12 job = list("Station Engineer", "Chief Engineer") +/datum/uplink_item/jobspecific/syndietape_engineering + name = "Syndicate Tape" + desc = "A length of engineering tape charged with a powerful electric potential. Will spark and shock people who attempt to remove it, creating fires. Can be used 3 times." + item = /obj/item/taperoll/syndie/engineering + cost = 4 + job = list("Station Engineer", "Chief Engineer") + //Atmos Tech /datum/uplink_item/jobspecific/contortionist name = "Contortionist's Jumpsuit" @@ -352,6 +380,13 @@ var/list/uplink_items = list() cost = 6 job = list("Atmospheric Technician", "Chief Engineer") +/datum/uplink_item/jobspecific/syndietape_atmos + name = "Syndicate Tape" + desc = "A length of atmospherics tape made of an extremely sharp material that will cuts the hands of trespassers. Very difficult to remove. Can be used 3 times." + item = /obj/item/taperoll/syndie/atmos + cost = 4 + job = list("Atmospheric Technician", "Chief Engineer") + //Geneticist /datum/uplink_item/jobspecific/radgun name = "Radgun" @@ -384,6 +419,14 @@ var/list/uplink_items = list() cost = 12 job = list("Internal Affairs Agent") +/datum/uplink_item/jobspecific/knifeboot + name = "Concealed knife shoes" + desc = "Shoes with a knife concealed in the toecap. Tap your heels together to reveal the knife. Kick the target to stab them." + item = /obj/item/clothing/shoes/knifeboot + cost = 4 + job = list("Internal Affairs Agent") + + //Nuke Ops Prices /datum/uplink_item/nukeprice gamemodes = list("nuclear emergency") @@ -673,6 +716,13 @@ var/list/uplink_items = list() cost = 6 gamemodes = list("nuclear emergency") +/datum/uplink_item/device_tools/does_not_tip_note + name = "\"Does Not Tip\" database backdoor" + desc = "Lets you add or remove your station to the \"does not tip\" list kept by the cargo workers at Central Command. You can be sure all pizza orders will be poisoned from the moment the screen flashes red." + item = /obj/item/device/does_not_tip_backdoor + num_in_stock = 1 + cost = 10 + // IMPLANTS /datum/uplink_item/implants diff --git a/code/datums/wires/airlock.dm b/code/datums/wires/airlock.dm index 37f46fba66f..34f9cd7c5c5 100644 --- a/code/datums/wires/airlock.dm +++ b/code/datums/wires/airlock.dm @@ -45,7 +45,8 @@ var/const/AIRLOCK_WIRE_LIGHT = 2048 var/obj/machinery/door/airlock/A = holder if(!istype(L, /mob/living/silicon)) if(A.isElectrified()) - if(A.shock(L, 100)) + var/obj/I = L.get_active_hand() + if(A.shock(L, 100, get_conductivity(I))) return 0 if(A.panel_open) return 1 @@ -65,28 +66,29 @@ var/const/AIRLOCK_WIRE_LIGHT = 2048 /datum/wires/airlock/UpdateCut(var/index, var/mended, mob/user) var/obj/machinery/door/airlock/A = holder + var/obj/I = user.get_active_hand() switch(index) if(AIRLOCK_WIRE_MAIN_POWER1, AIRLOCK_WIRE_MAIN_POWER2) if(!mended) //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. A.loseMainPower() - A.shock(user, 50) + A.shock(user, 50, get_conductivity(I)) else if((!IsIndexCut(AIRLOCK_WIRE_MAIN_POWER1)) && (!IsIndexCut(AIRLOCK_WIRE_MAIN_POWER2))) A.regainMainPower() - A.shock(user, 50) + A.shock(user, 50, get_conductivity(I)) if(AIRLOCK_WIRE_BACKUP_POWER1, AIRLOCK_WIRE_BACKUP_POWER2) if(!mended) //Cutting either one disables the backup door power (allowing it to be crowbarred open, but disabling bolts-raising), but may electocute the user. A.loseBackupPower() - A.shock(user, 50) + A.shock(user, 50, get_conductivity(I)) else if((!IsIndexCut(AIRLOCK_WIRE_BACKUP_POWER1)) && (!IsIndexCut(AIRLOCK_WIRE_BACKUP_POWER2))) A.regainBackupPower() - A.shock(user, 50) + A.shock(user, 50, get_conductivity(I)) if(AIRLOCK_WIRE_DOOR_BOLTS) diff --git a/code/datums/wires/alarm.dm b/code/datums/wires/alarm.dm index 21ba8ee539e..1f2d943b1a8 100644 --- a/code/datums/wires/alarm.dm +++ b/code/datums/wires/alarm.dm @@ -33,8 +33,9 @@ var/const/AALARM_WIRE_AALARM = 16 . += ..() . += text("
\n[(A.locked ? "The Air Alarm is locked." : "The Air Alarm is unlocked.")]
\n[((A.shorted || (A.stat & (NOPOWER|BROKEN))) ? "The Air Alarm is offline." : "The Air Alarm is working properly!")]
\n[(A.aidisabled ? "The 'AI control allowed' light is off." : "The 'AI control allowed' light is on.")]") -/datum/wires/alarm/UpdateCut(var/index, var/mended) +/datum/wires/alarm/UpdateCut(var/index, var/mended, var/mob/user) var/obj/machinery/alarm/A = holder + var/obj/I = user.get_active_hand() switch(index) if(AALARM_WIRE_IDSCAN) if(!mended) @@ -42,7 +43,7 @@ var/const/AALARM_WIRE_AALARM = 16 // to_chat(world, "Idscan wire cut") if(AALARM_WIRE_POWER) - A.shock(usr, 50) + A.shock(user, 50,get_conductivity(I)) A.shorted = !mended A.update_icon() // to_chat(world, "Power wire cut") diff --git a/code/datums/wires/apc.dm b/code/datums/wires/apc.dm index 1c4d823d88b..c8f57a8ac79 100644 --- a/code/datums/wires/apc.dm +++ b/code/datums/wires/apc.dm @@ -64,19 +64,19 @@ var/const/APC_WIRE_AI_CONTROL = 8 A.updateDialog() -/datum/wires/apc/UpdateCut(var/index, var/mended) +/datum/wires/apc/UpdateCut(var/index, var/mended, var/mob/user) var/obj/machinery/power/apc/A = holder - + var/obj/I = user.get_active_hand() switch(index) if(APC_WIRE_MAIN_POWER1, APC_WIRE_MAIN_POWER2) if(!mended) - A.shock(usr, 50) + A.shock(user, 50,get_conductivity(I)) A.shorted = 1 else if(!IsIndexCut(APC_WIRE_MAIN_POWER1) && !IsIndexCut(APC_WIRE_MAIN_POWER2)) A.shorted = 0 - A.shock(usr, 50) + A.shock(user, 50,get_conductivity(I)) if(APC_WIRE_AI_CONTROL) diff --git a/code/datums/wires/camera.dm b/code/datums/wires/camera.dm index 7e85d068acb..d951a901820 100644 --- a/code/datums/wires/camera.dm +++ b/code/datums/wires/camera.dm @@ -41,7 +41,7 @@ var/const/CAMERA_WIRE_ALARM = 8 var/const/CAMERA_WIRE_NOTHING1 = 16 var/const/CAMERA_WIRE_NOTHING2 = 32 -/datum/wires/camera/UpdateCut(var/index, var/mended) +/datum/wires/camera/UpdateCut(var/index, var/mended, var/mob/user) var/obj/machinery/camera/C = holder switch(index) @@ -51,7 +51,7 @@ var/const/CAMERA_WIRE_NOTHING2 = 32 if(CAMERA_WIRE_POWER) if(C.status && !mended || !C.status && mended) - C.deactivate(usr, 1) + C.deactivate(user, 1) if(CAMERA_WIRE_LIGHT) C.light_disabled = !mended diff --git a/code/datums/wires/explosive.dm b/code/datums/wires/explosive.dm index 48403a13e3e..95952f4c591 100644 --- a/code/datums/wires/explosive.dm +++ b/code/datums/wires/explosive.dm @@ -11,7 +11,7 @@ var/const/WIRE_EXPLODE = 1 if(WIRE_EXPLODE) explode() -/datum/wires/explosive/UpdateCut(var/index, var/mended) +/datum/wires/explosive/UpdateCut(var/index, var/mended, var/mob/user) switch(index) if(WIRE_EXPLODE) if(!mended) diff --git a/code/datums/wires/jukebox.dm b/code/datums/wires/jukebox.dm index 07dab22671c..ef94a1c2a02 100644 --- a/code/datums/wires/jukebox.dm +++ b/code/datums/wires/jukebox.dm @@ -76,12 +76,13 @@ var/const/JUKE_SETTING = 128 //Cut shocks. Pulse toggles settings menu. if(JUKE_SETTING) J.access_unlocked = !J.access_unlocked -/datum/wires/jukebox/UpdateCut(var/index, var/mended) +/datum/wires/jukebox/UpdateCut(var/index, var/mended, var/mob/user) var/obj/machinery/media/jukebox/J = holder + var/obj/I = user.get_active_hand() switch(index) if(JUKE_POWER_ONE,JUKE_POWER_TWO,JUKE_POWER_THREE) J.power_change() - J.shock(usr, 50) + J.shock(user, 50, get_conductivity(I)) if(freq_config_data[index]==0) freq_config_data[index] = 14 else @@ -93,7 +94,7 @@ var/const/JUKE_SETTING = 128 //Cut shocks. Pulse toggles settings menu. else J.allowed_modes = loopModeNames.Copy() if(JUKE_TRANSMIT) - J.shock(usr, 50) + J.shock(user, 50, get_conductivity(I)) if(IsIndexCut(JUKE_TRANSMIT)) J.machine_flags &= !MULTITOOL_MENU else @@ -104,4 +105,4 @@ var/const/JUKE_SETTING = 128 //Cut shocks. Pulse toggles settings menu. return J.short() if(JUKE_SETTING) - J.shock(usr, 50) + J.shock(user, 50, get_conductivity(I)) diff --git a/code/datums/wires/mommi.dm b/code/datums/wires/mommi.dm index 7a1e59e9d68..e6111400555 100644 --- a/code/datums/wires/mommi.dm +++ b/code/datums/wires/mommi.dm @@ -3,7 +3,7 @@ holder_type = /mob/living/silicon/robot/mommi wire_count = 3 // No lawsync, nor AI control. -/datum/wires/robot/mommi/UpdateCut(var/index, var/mended) +/datum/wires/robot/mommi/UpdateCut(var/index, var/mended, var/mob/user) var/mob/living/silicon/robot/R = holder switch(index) @@ -24,7 +24,7 @@ if (BORG_WIRE_CAMERA) if(!isnull(R.camera) && !R.scrambledcodes) R.camera.status = mended - R.camera.deactivate(usr, 0) // Will kick anyone who is watching the Cyborg's camera. + R.camera.deactivate(user, 0) // Will kick anyone who is watching the Cyborg's camera. //if(BORG_WIRE_LAWCHECK) //Forces a law update if the borg is set to receive them. Since an update would happen when the borg checks its laws anyway, not much use, but eh // if (R.lawupdate) diff --git a/code/datums/wires/particle_accelerator.dm b/code/datums/wires/particle_accelerator.dm index b56c470edd1..60c054947a9 100644 --- a/code/datums/wires/particle_accelerator.dm +++ b/code/datums/wires/particle_accelerator.dm @@ -46,7 +46,7 @@ var/const/PARTICLE_LIMIT_POWER_WIRE = 8 // Determines how strong the PA can be. if(PARTICLE_LIMIT_POWER_WIRE) C.visible_message("[bicon(C)][C] makes a large whirring noise.") -/datum/wires/particle_acc/control_box/UpdateCut(var/index, var/mended) +/datum/wires/particle_acc/control_box/UpdateCut(var/index, var/mended, var/mob/user) var/obj/machinery/particle_accelerator/control_box/C = holder switch(index) diff --git a/code/datums/wires/rnd_wires.dm b/code/datums/wires/rnd_wires.dm index f46ea6bffeb..04689ea1003 100644 --- a/code/datums/wires/rnd_wires.dm +++ b/code/datums/wires/rnd_wires.dm @@ -6,13 +6,17 @@ wire_names=list( "[RND_WIRE_DISABLE]" = "Disable", "[RND_WIRE_SHOCK]" = "Shock", - "[RND_WIRE_HACK]" = "Hack" + "[RND_WIRE_HACK]" = "Hack", + "[RND_WIRE_AUTOMAKE]" = "Automake", + "[RND_WIRE_JOBFINISHED]"= "Job finished" ) ..() var/const/RND_WIRE_DISABLE = 1 var/const/RND_WIRE_SHOCK = 2 var/const/RND_WIRE_HACK = 4 +var/const/RND_WIRE_AUTOMAKE = 8 +var/const/RND_WIRE_JOBFINISHED = 16 /datum/wires/rnd/CanUse(var/mob/living/L) if(!..()) @@ -28,6 +32,7 @@ var/const/RND_WIRE_HACK = 4 . += "The red light is [rnd.disabled ? "off" : "on"].
" . += "The green light is [rnd.shocked ? "off" : "on"].
" . += "The blue light is [rnd.hacked ? "off" : "on"].
" + . += "The yellow light is [rnd.auto_make ? "on": "off"].
" /datum/wires/rnd/UpdatePulsed(var/index) var/obj/machinery/r_n_d/rnd = holder @@ -39,8 +44,10 @@ var/const/RND_WIRE_HACK = 4 if(RND_WIRE_HACK) rnd.hacked = !rnd.hacked rnd.update_hacked() + if(RND_WIRE_AUTOMAKE) + rnd.auto_make = !rnd.auto_make -/datum/wires/rnd/UpdateCut(var/index, var/mended) +/datum/wires/rnd/UpdateCut(var/index, var/mended, var/mob/user) var/obj/machinery/r_n_d/rnd = holder switch(index) if(RND_WIRE_DISABLE) @@ -50,3 +57,5 @@ var/const/RND_WIRE_HACK = 4 if(RND_WIRE_HACK) rnd.hacked = 0 rnd.update_hacked() + if(RND_WIRE_AUTOMAKE) + rnd.auto_make = 0 diff --git a/code/datums/wires/robot.dm b/code/datums/wires/robot.dm index 1bd4cd7a02a..68fb8b6c384 100644 --- a/code/datums/wires/robot.dm +++ b/code/datums/wires/robot.dm @@ -39,7 +39,7 @@ var/const/BORG_WIRE_LAWCHECK = 16 // Not used on MoMMIs . += text("
\n[(R.lockcharge ? "The lockdown light is on." : "The lockdown light is off.")]") return . -/datum/wires/robot/UpdateCut(var/index, var/mended) +/datum/wires/robot/UpdateCut(var/index, var/mended, var/mob/user) var/mob/living/silicon/robot/R = holder switch(index) @@ -60,7 +60,7 @@ var/const/BORG_WIRE_LAWCHECK = 16 // Not used on MoMMIs if (BORG_WIRE_CAMERA) if(!isnull(R.camera) && !R.scrambledcodes) R.camera.status = mended - R.camera.deactivate(usr, 0) // Will kick anyone who is watching the Cyborg's camera. + R.camera.deactivate(user, 0) // Will kick anyone who is watching the Cyborg's camera. if(BORG_WIRE_LAWCHECK) //Forces a law update if the borg is set to receive them. Since an update would happen when the borg checks its laws anyway, not much use, but eh if (R.lawupdate) @@ -83,6 +83,8 @@ var/const/BORG_WIRE_LAWCHECK = 16 // Not used on MoMMIs R.camera.deactivate(usr, 0) // Kick anyone watching the Cyborg's camera, doesn't display you disconnecting the camera. R.visible_message("[R]'s camera lense focuses loudly.") to_chat(R, "Your camera lense focuses loudly.") + if(R.aicamera) + R.aicamera.sync(R) if(BORG_WIRE_LOCKED_DOWN) R.SetLockdown(!R.lockcharge) // Toggle diff --git a/code/datums/wires/syndicatebomb.dm b/code/datums/wires/syndicatebomb.dm index f3911ba564c..dc077ebe347 100644 --- a/code/datums/wires/syndicatebomb.dm +++ b/code/datums/wires/syndicatebomb.dm @@ -47,7 +47,7 @@ var/const/WIRE_ACTIVATE = 16 // Will start a bombs timer if pulsed, will hint if P.loc.visible_message("[bicon(holder)] The bomb seems to hesitate for a moment.") P.timer += 5 -/datum/wires/syndicatebomb/UpdateCut(var/index, var/mended) +/datum/wires/syndicatebomb/UpdateCut(var/index, var/mended, var/mob/user) var/obj/machinery/syndicatebomb/P = holder if(P.degutted) return @@ -75,4 +75,4 @@ var/const/WIRE_ACTIVATE = 16 // Will start a bombs timer if pulsed, will hint if P.loc.visible_message("[bicon(holder)] The timer stops! The bomb has been defused!") P.icon_state = "syndicate-bomb-inactive-wires" //no cutting possible with the panel closed P.active = 0 - P.defused = 1 \ No newline at end of file + P.defused = 1 diff --git a/code/datums/wires/transmitter.dm b/code/datums/wires/transmitter.dm index 6dd29d7f5fb..c87cc5d8e58 100644 --- a/code/datums/wires/transmitter.dm +++ b/code/datums/wires/transmitter.dm @@ -46,11 +46,12 @@ var/const/TRANS_SETTINGS = 16 //Pulse shows percentage given by environment temp var/datum/gas_mixture/env = T.loc.return_air() counter = 100*(env.temperature / (T20C + 20)) -/datum/wires/transmitter/UpdateCut(var/index, var/mended) +/datum/wires/transmitter/UpdateCut(var/index, var/mended, var/mob/user) var/obj/machinery/media/transmitter/broadcast/T = holder + var/obj/I = user.get_active_hand() switch(index) if(TRANS_POWER) T.power_change() - T.shock(usr, 50) + T.shock(user, 50, get_conductivity(I)) if(TRANS_LINK) - T.shock(usr, 50) + T.shock(user, 50, get_conductivity(I)) diff --git a/code/datums/wires/vending.dm b/code/datums/wires/vending.dm index 08be653d731..089da88210e 100644 --- a/code/datums/wires/vending.dm +++ b/code/datums/wires/vending.dm @@ -22,7 +22,8 @@ var/const/VENDING_WIRE_IDSCAN = 8 var/obj/machinery/vending/V = holder if(!istype(L, /mob/living/silicon)) if(V.seconds_electrified) - if(V.shock(L, 100)) + var/obj/I = L.get_active_hand() + if(V.shock(L, 100, get_conductivity(I))) return 0 if(V.panel_open) return 1 diff --git a/code/datums/wires/wires.dm b/code/datums/wires/wires.dm index 23af249fe45..759ccd6358b 100644 --- a/code/datums/wires/wires.dm +++ b/code/datums/wires/wires.dm @@ -224,6 +224,12 @@ var/const/POWER = 8 else CRASH("[colour] is not a key in wires.") +/datum/wires/proc/GetColour(var/index) + for(var/i in wires) + if(wires[i] == index) + return i + CRASH("[index] is not in wires.") + // // Is Index/Colour Cut procs // @@ -274,6 +280,13 @@ var/const/POWER = 8 holder.investigation_log(I_WIRES, "|| [GetWireName(wires[colour]) || colour] wire pulsed by \a [S] \ref[S] ([src.type])") break +/datum/wires/proc/SignalIndex(var/index) + if(IsIndexCut(index)) + return + var/obj/item/device/assembly/signaler/S = GetAttached(GetColour(index)) + if(S) + S.activate() + // // Cut Wire Colour/Index procs diff --git a/code/defines/obj/weapon.dm b/code/defines/obj/weapon.dm index ac832414065..3b1771beee4 100644 --- a/code/defines/obj/weapon.dm +++ b/code/defines/obj/weapon.dm @@ -58,6 +58,7 @@ throwforce = 0 throw_speed = 4 throw_range = 20 + var/potency = 0 /obj/item/weapon/bananapeel/suicide_act(mob/user) to_chat(viewers(user), "[user] drops the [src.name] on the ground and steps on it causing \him to crash to the floor, bashing \his head wide open. ") @@ -395,6 +396,8 @@ layer = OPEN_DOOR_LAYER icon_state = "beartrap0" desc = "A trap used to catch bears and other legged creatures." + starting_materials = list(MAT_IRON = 50000) + w_type = RECYK_METAL var/armed = 0 var/obj/item/weapon/grenade/iedcasing/IED = null diff --git a/code/game/area/Space Station 13 areas.dm b/code/game/area/Space Station 13 areas.dm index ccc21804cd7..fe016dcf2b2 100755 --- a/code/game/area/Space Station 13 areas.dm +++ b/code/game/area/Space Station 13 areas.dm @@ -2432,6 +2432,10 @@ proc/process_adminbus_teleport_locs() name = "Leviathan" icon_state = "mining_production" +/area/awaymission/snowplanet + name = "snowplanet" + icon_state = "mining_production" + ///////////////////////////////////////////////////////////////////// /* Lists of areas to be used with is_type_in_list. diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index 1aabe41e102..9cacd34a845 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -11,11 +11,11 @@ var/area/space_area var/list/area_turfs var/turret_protected = 0 var/list/turretTargets = list() - plane = AREA_PLANE + plane = ABOVE_LIGHTING_PLANE layer = MAPPING_AREA_LAYER var/base_turf_type = null var/shuttle_can_crush = TRUE - + var/project_shadows = FALSE var/obj/effect/narration/narrator = null flags = 0 @@ -210,7 +210,7 @@ var/area/space_area for(var/obj/machinery/door/firedoor/D in all_doors) if(!D.blocked) if(D.operating) - D.nextstate = CLOSED + D.nextstate = FD_CLOSED else if(!D.density) spawn() D.close() @@ -222,7 +222,7 @@ var/area/space_area for(var/obj/machinery/door/firedoor/D in all_doors) if(!D.blocked) if(D.operating) - D.nextstate = OPEN + D.nextstate = FD_OPEN else if(D.density) spawn() D.open() @@ -413,17 +413,25 @@ var/area/space_area used_environ += amount /area/Entered(atom/movable/Obj, atom/OldLoc) - var/area/oldArea = Obj.areaMaster - Obj.areaMaster = src + var/area/oldArea = get_area(OldLoc) + + if(project_shadows) + Obj.update_shadow() + else if(istype(oldArea) && oldArea.project_shadows) + Obj.underlays -= Obj.shadow + + Obj.area_entered(src) + for(var/atom/movable/thing in get_contents_in_object(Obj)) + thing.area_entered(src) for(var/mob/mob_in_obj in Obj.contents) - CallHook("MobAreaChange", list("mob" = mob_in_obj, "new" = Obj.areaMaster, "old" = oldArea)) + + CallHook("MobAreaChange", list("mob" = mob_in_obj, "new" = src, "old" = oldArea)) var/mob/M = Obj - if(istype(M)) - CallHook("MobAreaChange", list("mob" = M, "new" = Obj.areaMaster, "old" = oldArea)) // /vg/ - EVENTS! - if(M.client && (M.client.prefs.toggles & SOUND_AMBIENCE) && isnull(M.areaMaster.media_source) && !M.client.ambience_playing) + CallHook("MobAreaChange", list("mob" = M, "new" = src, "old" = oldArea)) // /vg/ - EVENTS! + if(M.client && (M.client.prefs.toggles & SOUND_AMBIENCE) && isnull(media_source) && !M.client.ambience_playing) M.client.ambience_playing = 1 var/sound = 'sound/ambience/shipambience.ogg' @@ -565,7 +573,7 @@ var/area/space_area for(var/atom/movable/AM in T.contents) AM.change_area(old_area,src) -var/list/ignored_keys = list("loc", "locs", "parent_type", "vars", "verbs", "type", "x", "y", "z", "group", "contents", "air", "zone", "light", "areaMaster", "underlays", "lighting_overlay", "corners", "affecting_lights", "has_opaque_atom", "lighting_corners_initialised", "light_sources") +var/list/ignored_keys = list("loc", "locs", "parent_type", "vars", "verbs", "type", "x", "y", "z", "group", "contents", "air", "zone", "light", "underlays", "lighting_overlay", "corners", "affecting_lights", "has_opaque_atom", "lighting_corners_initialised", "light_sources") var/list/moved_landmarks = list(latejoin, wizardstart) //Landmarks that are moved by move_area_to and move_contents_to var/list/transparent_icons = list("diagonalWall3","swall_f5","swall_f6","swall_f9","swall_f10") //icon_states for which to prepare an underlay diff --git a/code/game/area/shadows.dm b/code/game/area/shadows.dm new file mode 100644 index 00000000000..dbee4e577bb --- /dev/null +++ b/code/game/area/shadows.dm @@ -0,0 +1,52 @@ +#define SHADOW_DIRECTION 180-25 +#define SHADOW_PIXEL_X_DIVISOR 5.1 +#define SHADOW_PIXEL_Y_DIVISOR 1.3 +#define SHADOW_ALPHA 80 + +/atom/movable/proc/has_shadow() + return density // If something has density, we can assume it's A) not on the ground and B) large enough to cast a shadow. Bit of a hacky way to do it, but better than writing an exception for everything + +/obj/structure/closet/has_shadow() + return 1 + +/mob/living/carbon/has_shadow() + if(lying) + return 0 + . = ..() + +/atom/movable/proc/update_shadow() + if(!has_shadow()) + return + + if(shadow) + underlays -= shadow + else + shadow = new + + shadow.appearance = appearance + shadow.alpha = SHADOW_ALPHA + shadow.color = "#000000" + shadow.appearance_flags = KEEP_TOGETHER + shadow.mouse_opacity = 0 + + var/matrix/M = matrix() + M.Scale(-1,1) + M.Turn(SHADOW_DIRECTION) + shadow.transform = M + apply_shadow() + +/atom/movable/proc/apply_shadow() // should work for most standard shaped objects - when it doesn't, override this proc. thanks OOP + var/icon/I = new/icon(icon,icon_state) //Used to calculate the size of the object + shadow.pixel_y -= I.Height()/SHADOW_PIXEL_Y_DIVISOR // this should not require pixel multiplier + shadow.pixel_x += I.Width()/SHADOW_PIXEL_X_DIVISOR // this should not require pixel multiplier + underlays += shadow + +/obj/structure/flora/tree/pine/apply_shadow() + shadow.pixel_y = -74*PIXEL_MULTIPLIER + shadow.pixel_x = 16*PIXEL_MULTIPLIER + underlays += shadow + +/obj/shadow + plane = ABOVE_HUMAN_PLANE + layer = SHADOW_LAYER + density = 0 \ No newline at end of file diff --git a/code/game/asteroid.dm b/code/game/asteroid.dm index 6f70f832f8f..d9f54384691 100644 --- a/code/game/asteroid.dm +++ b/code/game/asteroid.dm @@ -69,7 +69,7 @@ proc/make_mining_asteroid_secret() while(1) sanity++ if(sanity > 100) - testing("Tried to place complex too many times. Aborting.") + //testing("Tried to place complex too many times. Aborting.") return 0 T=pick(turfs) diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 316b9cd685c..4bbccf24ce1 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -219,6 +219,10 @@ var/global/list/ghdel_profiling = list() /atom/proc/is_open_container() return flags & OPENCONTAINER +// For when we want an open container that doesn't show its reagents on examine +/atom/proc/hide_own_reagents() + return FALSE + // As a rule of thumb, should smoke be able to pop out from inside this object? // Currently only used for chemical reactions, see Chemistry-Recipes.dm /atom/proc/is_airtight() @@ -240,6 +244,7 @@ var/global/list/ghdel_profiling = list() return /atom/proc/emp_act(var/severity) + set waitfor = FALSE return /atom/proc/kick_act(mob/living/carbon/human/user) //Called when this atom is kicked. If returns 1, normal click action will be performed after calling this (so attack_hand() in most cases) @@ -399,7 +404,7 @@ its easier to just keep the beam vertical. //Woo hoo. Overtime //All atoms -/atom/proc/examine(mob/user, var/size = "", var/show_name = TRUE) +/atom/proc/examine(mob/user, var/size = "", var/show_name = TRUE, var/show_icon = TRUE) //This reformat names to get a/an properly working on item descriptions when they are bloody var/f_name = "\a [src]." if(src.blood_DNA && src.blood_DNA.len) @@ -410,11 +415,11 @@ its easier to just keep the beam vertical. f_name += "blood-stained [name]!" if(show_name) - to_chat(user, "[bicon(src)] That's [f_name]" + size) + to_chat(user, "[show_icon ? bicon(src) : ""] That's [f_name]" + size) if(desc) to_chat(user, desc) - if(reagents && is_open_container() && !ismob(src)) //is_open_container() isn't really the right proc for this, but w/e + if(reagents && is_open_container() && !ismob(src) && !hide_own_reagents()) //is_open_container() isn't really the right proc for this, but w/e if(get_dist(user,src) > 3) to_chat(user, "You can't make out the contents.") else @@ -649,7 +654,7 @@ its easier to just keep the beam vertical. return if(isnull(M.key)) return - if (!( src.flags ) & FPRINT) + if (!(src.flags & FPRINT)) return if (ishuman(M)) //Add the list if it does not exist. @@ -859,6 +864,9 @@ its easier to just keep the beam vertical. /atom/proc/acidable() return 0 +/atom/proc/isacidhardened() + return FALSE + /atom/proc/holomapAlwaysDraw() return 1 @@ -901,3 +909,6 @@ its easier to just keep the beam vertical. for(var/client/C in clients) if(uppertext(C.ckey) == uppertext(fingerprintslast)) return C.mob + +/atom/proc/initialize() + return diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 9bb6f35ba39..786653033f7 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -18,8 +18,6 @@ var/mob/pulledby = null var/pass_flags = 0 - var/area/areaMaster - var/sound_override = 0 //Do we make a sound when bumping into something? var/hard_deleted = 0 var/pressure_resistance = ONE_ATMOSPHERE @@ -53,10 +51,10 @@ var/atom/movable/tether_master var/list/tether_slaves var/list/current_tethers + var/obj/shadow/shadow /atom/movable/New() . = ..() - areaMaster = get_area_master(src) if((flags & HEAR) && !ismob(src)) getFromPool(/mob/virtualhearer, src) @@ -106,6 +104,9 @@ if(VH.attached == src) returnToPool(VH) + for(var/atom/movable/AM in src) + qdel(AM) + ..() /proc/delete_profile(var/type, code = 0) @@ -420,7 +421,7 @@ loc.Entered(src, old_loc) if(isturf(loc)) - var/area/A = get_area_master(loc) + var/area/A = get_area(loc) A.Entered(src, old_loc) for(var/atom/movable/AM in loc) @@ -459,7 +460,7 @@ loc = destination loc.Entered(src) if(isturf(destination)) - var/area/A = get_area_master(destination) + var/area/A = get_area(destination) A.Entered(src) for(var/atom/movable/AM in locked_atoms) @@ -625,10 +626,6 @@ if(isobj(src)) src.throw_impact(get_turf(src), speed, user) -/atom/movable/change_area(oldarea, newarea) - areaMaster = newarea - ..() - //Overlays /atom/movable/overlay var/atom/master = null @@ -965,3 +962,9 @@ /atom/movable/proc/on_tether_broken(atom/movable/other_end) //To allow for code based on when a tether with a specific thing is broken return + +/atom/movable/proc/area_entered(var/area/A) + return + +/atom/movable/proc/can_be_pulled(var/mob/user) + return TRUE diff --git a/code/game/data_huds.dm b/code/game/data_huds.dm index a68fe91a5ea..b857e38e041 100644 --- a/code/game/data_huds.dm +++ b/code/game/data_huds.dm @@ -56,7 +56,7 @@ proc/process_med_hud(var/mob/M, var/mob/eye) holder = patient.hud_list[HEALTH_HUD] if(holder) - if(patient.stat == 2) + if(patient.isDead()) holder.icon_state = "hudhealth-100" else holder.icon_state = "hud[RoundHealth(patient.health)]" @@ -64,7 +64,7 @@ proc/process_med_hud(var/mob/M, var/mob/eye) holder = patient.hud_list[STATUS_HUD] if(holder) - if(patient.stat == 2) + if(patient.isDead()) holder.icon_state = "huddead" else if(patient.status_flags & XENO_HOST) holder.icon_state = "hudxeno" @@ -120,7 +120,6 @@ proc/process_sec_hud(var/mob/M, var/advanced_mode,var/mob/eye) else continue C.images += holder - break var/perpname = perp.get_face_name() if(lowertext(perpname) == "unknown" || !perpname) @@ -133,7 +132,7 @@ proc/process_sec_hud(var/mob/M, var/advanced_mode,var/mob/eye) if("*Arrest*") holder.icon_state = "hudwanted" if("Incarcerated") - holder.icon_state = "hudprisoner" + holder.icon_state = "hudincarcerated" if("Parolled") holder.icon_state = "hudparolled" if("Released") @@ -182,7 +181,7 @@ proc/process_sec_hud(var/mob/M, var/advanced_mode,var/mob/eye) C.images += holder var/integrity_ratio = exosuit.health / initial(exosuit.health) holder.icon_state = mech_integrity_to_icon_state(integrity_ratio) - + holder = exosuit.hud_list[DIAG_CELL_HUD] if(holder) C.images += holder @@ -192,7 +191,7 @@ proc/process_sec_hud(var/mob/M, var/advanced_mode,var/mob/eye) else var/charge_ratio = exosuit_cell.charge / exosuit_cell.maxcharge holder.icon_state = power_cell_charge_to_icon_state(charge_ratio) - + //Unsure of where to put this, but since most of it is HUDs it seemed fitting to go here. /mob/proc/handle_glasses_vision_updates(var/obj/item/clothing/glasses/G) diff --git a/code/game/dna/dna_modifier.dm b/code/game/dna/dna_modifier.dm index 695d88edaad..856cd8764e9 100644 --- a/code/game/dna/dna_modifier.dm +++ b/code/game/dna/dna_modifier.dm @@ -20,6 +20,7 @@ var/ckey=null var/mind=null var/list/languages = list() + var/times_cloned=0 /datum/dna2/record/proc/GetData() var/list/ser=list("data" = null, "owner" = null, "label" = null, "type" = null, "ue" = 0) @@ -182,7 +183,7 @@ return if(isrobot(user)) var/mob/living/silicon/robot/robit = usr - if(istype(robit) && !istype(robit.module, /obj/item/weapon/robot_module/medical)) + if(!(robit.module && (robit.module.quirk_flags & MODULE_CAN_HANDLE_MEDICAL))) to_chat(user, "You do not have the means to do this!") return var/mob/living/L = O @@ -213,7 +214,7 @@ return if(isrobot(usr)) var/mob/living/silicon/robot/robit = usr - if(istype(robit) && !istype(robit.module, /obj/item/weapon/robot_module/medical)) + if(!(robit.module && (robit.module.quirk_flags & MODULE_CAN_HANDLE_MEDICAL))) to_chat(usr, "You do not have the means to do this!") return if(!istype(over_location) || over_location.density) @@ -534,7 +535,7 @@ if(!connected) src.visible_message("[bicon(src)]No scanner connected!") return - + if(user == connected.occupant) return diff --git a/code/game/dna/genes/disabilities.dm b/code/game/dna/genes/disabilities.dm index 1781b7d2409..cdfa132d687 100644 --- a/code/game/dna/genes/disabilities.dm +++ b/code/game/dna/genes/disabilities.dm @@ -7,112 +7,104 @@ ///////////////////// /datum/dna/gene/disability - name="DISABILITY" + name = "DISABILITY" genetype = GENETYPE_BAD // Mutation to give (or 0) - var/mutation=0 + var/mutation = 0 // Disability to give (or 0) - var/disability=0 + var/disability = 0 // SDisability to give (or 0) - var/sdisability=0 + var/sdisability = 0 // Activation message - var/activation_message="" + var/activation_message = "" // Yay, you're no longer growing 3 arms - var/deactivation_message="" + var/deactivation_message = "" /datum/dna/gene/disability/can_activate(var/mob/M,var/flags) return 1 // Always set! /datum/dna/gene/disability/activate(var/mob/M, var/connected, var/flags) - if(mutation && !(mutation in M.mutations)) - M.mutations.Add(mutation) + if(mutation) + M.mutations |= mutation if(disability) - M.disabilities|=disability + M.disabilities |= disability if(sdisability) - M.sdisabilities|=sdisability - if(activation_message) - to_chat(M, "[activation_message]") - else - testing("[name] has no activation message.") + M.sdisabilities |= sdisability + to_chat(M, "[activation_message]") /datum/dna/gene/disability/deactivate(var/mob/M, var/connected, var/flags) if(flags & GENE_NATURAL) - //testing("[name]([type]) has natural flag.") return 0 M.mutations.Remove(mutation) M.active_genes.Remove(src.type) - //testing("[M] [mut ? "" : "un"]successfully removed [src.name] from mutations") if(disability) M.disabilities &= ~disability if(sdisability) M.sdisabilities &= ~sdisability - if(deactivation_message) - to_chat(M, "[deactivation_message]") - else - testing("[name] has no deactivation message.") + to_chat(M, "[deactivation_message]") return ..() /datum/dna/gene/disability/hallucinate - name="Hallucinate" - activation_message="Your mind says 'Hello'." + name = "Hallucinate" + activation_message = "Your mind says 'Hello'." deactivation_message = "Your mind no longer speaks to you." - mutation=M_HALLUCINATE + mutation = M_HALLUCINATE - New() - block=HALLUCINATIONBLOCK +/datum/dna/gene/disability/hallucinate/New() + block = HALLUCINATIONBLOCK /datum/dna/gene/disability/epilepsy - name="Epilepsy" - activation_message="You get a headache." + name = "Epilepsy" + activation_message = "You get a headache." deactivation_message = "Your headache disappears." - disability=EPILEPSY + disability = EPILEPSY - New() - block=HEADACHEBLOCK +/datum/dna/gene/disability/epilepsy/New() + block = HEADACHEBLOCK /datum/dna/gene/disability/cough - name="Coughing" - activation_message="You start coughing." + name = "Coughing" + activation_message = "You start coughing." deactivation_message = "The need to cough disappears." - disability=COUGHING + disability = COUGHING - New() - block=COUGHBLOCK +/datum/dna/gene/disability/cough/New() + block = COUGHBLOCK /datum/dna/gene/disability/clumsy - name="Clumsiness" - activation_message="You feel lightheaded." + name = "Clumsiness" + activation_message = "You feel lightheaded." deactivation_message = "You no longer feel lightheaded." - mutation=M_CLUMSY + mutation = M_CLUMSY flags = GENE_UNNATURAL // Clown-specific. - New() - block=CLUMSYBLOCK +/datum/dna/gene/disability/clumsy/New() + block = CLUMSYBLOCK /datum/dna/gene/disability/tourettes - name="Tourettes" - activation_message="You twitch." + name = "Tourettes" + activation_message = "You twitch." deactivation_message = "You stop twitching." - disability=TOURETTES + disability = TOURETTES flags = GENE_UNNATURAL // Game-wrecking - New() - block=TWITCHBLOCK +/datum/dna/gene/disability/tourettes/New() + block = TWITCHBLOCK /datum/dna/gene/disability/nervousness - name="Nervousness" - activation_message="You feel nervous." + name = "Nervousness" + activation_message = "You feel nervous." deactivation_message = "You feel calmer." - disability=NERVOUS + disability = NERVOUS - New() - block=NERVOUSBLOCK +/datum/dna/gene/disability/nervousness/New() + block = NERVOUSBLOCK /datum/dna/gene/disability/nervousness/OnMobLife(mob/living/carbon/carbon) ..() @@ -121,38 +113,37 @@ carbon.stuttering = max(10, carbon.stuttering) /datum/dna/gene/disability/blindness - name="Blindness" - activation_message="You can't seem to see anything." + name = "Blindness" + activation_message = "You can't seem to see anything." deactivation_message = "You can see again." - sdisability=BLIND + sdisability = BLIND flags = GENE_UNNATURAL - New() - block=BLINDBLOCK +/datum/dna/gene/disability/blindness/New() + block = BLINDBLOCK /datum/dna/gene/disability/deaf - name="Deafness" - activation_message="It's kinda quiet." + name = "Deafness" + activation_message = "It's kinda quiet." deactivation_message = "You can hear again." - sdisability=DEAF + sdisability = DEAF flags = GENE_UNNATURAL - New() - block=DEAFBLOCK +/datum/dna/gene/disability/deaf/New() + block=DEAFBLOCK - activate(var/mob/M, var/connected, var/flags) - ..(M,connected,flags) - M.ear_deaf = 1 +/datum/dna/gene/disability/deaf/activate(var/mob/M, var/connected, var/flags) + ..(M,connected,flags) + M.ear_deaf = 1 /datum/dna/gene/disability/nearsighted - name="Nearsightedness" - activation_message="Your eyes feel weird..." + name = "Nearsightedness" + activation_message = "Your eyes feel weird..." deactivation_message = "Your eyes no longer feel weird..." - disability=NEARSIGHTED - - New() - block=GLASSESBLOCK + disability = NEARSIGHTED +/datum/dna/gene/disability/nearsighted/New() + block = GLASSESBLOCK /datum/dna/gene/disability/lisp name = "Lisp" @@ -160,9 +151,9 @@ activation_message = "Thomething doethn't feel right." deactivation_message = "You now feel able to pronounce consonants." - New() - ..() - block=LISPBLOCK +/datum/dna/gene/disability/lisp/New() + ..() + block = LISPBLOCK - OnSay(var/mob/M, var/datum/speech/speech) - speech.message = replacetext(speech.message,"s","th") \ No newline at end of file +/datum/dna/gene/disability/lisp/OnSay(var/mob/M, var/datum/speech/speech) + speech.message = replacetext(speech.message,"s","th") diff --git a/code/game/dna/genes/goon_disabilities.dm b/code/game/dna/genes/goon_disabilities.dm index c3fe385a360..bd8afe7db1a 100644 --- a/code/game/dna/genes/goon_disabilities.dm +++ b/code/game/dna/genes/goon_disabilities.dm @@ -12,21 +12,15 @@ desc = "Completely shuts down the speech center of the subject's brain." activation_message = "You feel unable to express yourself at all." deactivation_message = "You feel able to speak freely again." + sdisability = MUTE - New() - ..() - block=MUTEBLOCK +/datum/dna/gene/disability/mute/New() + ..() + block = MUTEBLOCK - OnSay(var/mob/M, var/datum/speech/speech) - speech.message = "" +/datum/dna/gene/disability/mute/OnSay(var/mob/M, var/datum/speech/speech) + speech.message = "" - activate(var/mob/M, var/connected, var/flags) - ..() - M.sdisabilities |= MUTE - - deactivate(var/mob/M, var/connected, var/flags) - if(..()) - M.sdisabilities &= ~MUTE //////////////////////////////////////// // Harmful to others as well as self //////////////////////////////////////// @@ -38,21 +32,22 @@ deactivation_message = "You no longer feel awful and sick all over." flags = GENE_UNNATURAL - New() - ..() - block=RADBLOCK +/datum/dna/gene/disability/radioactive/New() + ..() + block = RADBLOCK - OnMobLife(var/mob/owner) - owner.radiation = max(owner.radiation, 20) - for(var/mob/living/L in range(1, owner)) - if(L == owner) - continue - to_chat(L, "You are enveloped by a soft green glow emanating from [owner].") - L.apply_radiation(5, RAD_INTERNAL) - return +/datum/dna/gene/disability/radioactive/OnMobLife(var/mob/owner) + owner.radiation = max(owner.radiation, 20) + for(var/mob/living/L in range(1, owner)) + if(L == owner) + continue + to_chat(L, "You are enveloped by a soft green glow emanating from [owner].") + L.apply_radiation(5, RAD_EXTERNAL) - OnDrawUnderlays(var/mob/M,var/g,var/fat) - return "rads[fat]_s" + emitted_harvestable_radiation(get_turf(owner), 1, range = 2) //Around 70W, nothing much really + +/datum/dna/gene/disability/radioactive/OnDrawUnderlays(var/mob/M,var/g,var/fat) + return "rads[fat]_s" //////////////////////////////////////// // Other disabilities @@ -67,177 +62,176 @@ mutation = M_OBESITY - can_activate(var/mob/M, var/flags) - if(!ishuman(M)) - return 0 +/datum/dna/gene/disability/fat/can_activate(var/mob/M, var/flags) + if(!ishuman(M)) + return 0 - var/mob/living/carbon/human/H = M - if(H.species && !(H.species.anatomy_flags & CAN_BE_FAT)) - return 0 + var/mob/living/carbon/human/H = M + if(H.species && !(H.species.anatomy_flags & CAN_BE_FAT)) + return 0 - return 1 + return 1 - New() - ..() - block=FATBLOCK +/datum/dna/gene/disability/fat/New() + ..() + block = FATBLOCK ///////////////////////// // SPEECH MANIPULATORS // ///////////////////////// // WAS: /datum/bioEffect/smile -/datum/dna/gene/disability/speech/smile +/datum/dna/gene/disability/smile name = "Smile" desc = "Causes the speech center of the subject's brain to produce large amounts of seratonin and a chemical resembling ecstacy when engaged." activation_message = "You feel so happy. Nothing can be wrong with anything :)" deactivation_message = "Everything is terrible again. :(" - New() - ..() - block=SMILEBLOCK +/datum/dna/gene/disability/smile/New() + ..() + block = SMILEBLOCK - OnSay(var/mob/M, var/datum/speech/speech) - //Time for a friendly game of SS13 - speech.message = replacetext(speech.message,"stupid","smart") - speech.message = replacetext(speech.message,"retard","genius") - speech.message = replacetext(speech.message,"unrobust","robust") - speech.message = replacetext(speech.message,"dumb","smart") - speech.message = replacetext(speech.message,"awful","great") - speech.message = replacetext(speech.message,"gay",pick("nice","ok","alright")) - speech.message = replacetext(speech.message,"horrible","fun") - speech.message = replacetext(speech.message,"terrible","terribly fun") - speech.message = replacetext(speech.message,"terrifying","wonderful") - speech.message = replacetext(speech.message,"gross","cool") - speech.message = replacetext(speech.message,"disgusting","amazing") - speech.message = replacetext(speech.message,"loser","winner") - speech.message = replacetext(speech.message,"useless","useful") - speech.message = replacetext(speech.message,"oh god","cheese and crackers") - speech.message = replacetext(speech.message,"jesus","gee wiz") - speech.message = replacetext(speech.message,"weak","strong") - speech.message = replacetext(speech.message,"kill","hug") - speech.message = replacetext(speech.message,"murder","tease") - speech.message = replacetext(speech.message,"ugly","beutiful") - speech.message = replacetext(speech.message,"douchbag","nice guy") - speech.message = replacetext(speech.message,"whore","lady") - speech.message = replacetext(speech.message,"nerd","smart guy") - speech.message = replacetext(speech.message,"moron","fun person") - speech.message = replacetext(speech.message,"IT'S LOOSE","EVERYTHING IS FINE") - speech.message = replacetext(speech.message,"rape","hug fight") - speech.message = replacetext(speech.message,"idiot","genius") - speech.message = replacetext(speech.message,"fat","thin") - speech.message = replacetext(speech.message,"beer","water with ice") - speech.message = replacetext(speech.message,"drink","water") - speech.message = replacetext(speech.message,"feminist","empowered woman") - speech.message = replacetext(speech.message,"i hate you","you're mean") - speech.message = replacetext(speech.message,"nigger","african american") - speech.message = replacetext(speech.message,"jew","jewish") - speech.message = replacetext(speech.message,"shit","shiz") - speech.message = replacetext(speech.message,"crap","poo") - speech.message = replacetext(speech.message,"slut","tease") - speech.message = replacetext(speech.message,"ass","butt") - speech.message = replacetext(speech.message,"damn","dang") - speech.message = replacetext(speech.message,"fuck","") - speech.message = replacetext(speech.message,"penis","privates") - speech.message = replacetext(speech.message,"cunt","privates") - speech.message = replacetext(speech.message,"dick","jerk") - speech.message = replacetext(speech.message,"vagina","privates") -// speech.message += "[pick(":)",":^)",":*)")]" : ^ ( - if(prob(30)) - speech.message += " check your privilege." +/datum/dna/gene/disability/smile/OnSay(var/mob/M, var/datum/speech/speech) + //Time for a friendly game of SS13 + speech.message = replacetext(speech.message,"stupid","smart") + speech.message = replacetext(speech.message,"retard","genius") + speech.message = replacetext(speech.message,"unrobust","robust") + speech.message = replacetext(speech.message,"dumb","smart") + speech.message = replacetext(speech.message,"awful","great") + speech.message = replacetext(speech.message,"gay",pick("nice","ok","alright")) + speech.message = replacetext(speech.message,"horrible","fun") + speech.message = replacetext(speech.message,"terrible","terribly fun") + speech.message = replacetext(speech.message,"terrifying","wonderful") + speech.message = replacetext(speech.message,"gross","cool") + speech.message = replacetext(speech.message,"disgusting","amazing") + speech.message = replacetext(speech.message,"loser","winner") + speech.message = replacetext(speech.message,"useless","useful") + speech.message = replacetext(speech.message,"oh god","cheese and crackers") + speech.message = replacetext(speech.message,"jesus","gee wiz") + speech.message = replacetext(speech.message,"weak","strong") + speech.message = replacetext(speech.message,"kill","hug") + speech.message = replacetext(speech.message,"murder","tease") + speech.message = replacetext(speech.message,"ugly","beutiful") + speech.message = replacetext(speech.message,"douchbag","nice guy") + speech.message = replacetext(speech.message,"whore","lady") + speech.message = replacetext(speech.message,"nerd","smart guy") + speech.message = replacetext(speech.message,"moron","fun person") + speech.message = replacetext(speech.message,"IT'S LOOSE","EVERYTHING IS FINE") + speech.message = replacetext(speech.message,"rape","hug fight") + speech.message = replacetext(speech.message,"idiot","genius") + speech.message = replacetext(speech.message,"fat","thin") + speech.message = replacetext(speech.message,"beer","water with ice") + speech.message = replacetext(speech.message,"drink","water") + speech.message = replacetext(speech.message,"feminist","empowered woman") + speech.message = replacetext(speech.message,"i hate you","you're mean") + speech.message = replacetext(speech.message,"nigger","african american") + speech.message = replacetext(speech.message,"jew","jewish") + speech.message = replacetext(speech.message,"shit","shiz") + speech.message = replacetext(speech.message,"crap","poo") + speech.message = replacetext(speech.message,"slut","tease") + speech.message = replacetext(speech.message,"ass","butt") + speech.message = replacetext(speech.message,"damn","dang") + speech.message = replacetext(speech.message,"fuck","") + speech.message = replacetext(speech.message,"penis","privates") + speech.message = replacetext(speech.message,"cunt","privates") + speech.message = replacetext(speech.message,"dick","jerk") + speech.message = replacetext(speech.message,"vagina","privates") + if(prob(30)) + speech.message += " check your privilege." // WAS: /datum/bioEffect/elvis -/datum/dna/gene/disability/speech/elvis +/datum/dna/gene/disability/elvis name = "Elvis" desc = "Forces the language center and primary motor cortex of the subject's brain to talk and act like the King of Rock and Roll." activation_message = "You feel pretty good, honeydoll." deactivation_message = "You feel a little less conversation would be great." - New() - ..() - block=ELVISBLOCK +/datum/dna/gene/disability/elvis/New() + ..() + block = ELVISBLOCK - OnSay(var/mob/M, var/datum/speech/speech) - if(prob(5)) - M.visible_message("[M] [pick("rambles to themselves.","begins talking to themselves.")]") - return 1 - speech.message = replacetext(speech.message,"im not","I ain't") - speech.message = replacetext(speech.message,"i'm not","I aint") - speech.message = replacetext(speech.message," girl ",pick(" honey "," baby "," baby doll ")) - speech.message = replacetext(speech.message," man ",pick(" son "," buddy "," brother ", " pal ", " friendo ")) - speech.message = replacetext(speech.message,"out of","outta") - speech.message = replacetext(speech.message,"thank you","thank you, thank you very much") - speech.message = replacetext(speech.message,"what are you","whatcha") - speech.message = replacetext(speech.message,"yes",pick("sure", "yea")) - speech.message = replacetext(speech.message,"faggot","square") - speech.message = replacetext(speech.message,"muh valids","my kicks") - speech.message = replacetext(speech.message," vox "," bird ") +/datum/dna/gene/disability/elvis/OnSay(var/mob/M, var/datum/speech/speech) + if(prob(5)) + M.visible_message("[M] [pick("rambles to themselves.","begins talking to themselves.")]") + return 1 + speech.message = replacetext(speech.message,"im not","I ain't") + speech.message = replacetext(speech.message,"i'm not","I aint") + speech.message = replacetext(speech.message," girl ",pick(" honey "," baby "," baby doll ")) + speech.message = replacetext(speech.message," man ",pick(" son "," buddy "," brother ", " pal ", " friendo ")) + speech.message = replacetext(speech.message,"out of","outta") + speech.message = replacetext(speech.message,"thank you","thank you, thank you very much") + speech.message = replacetext(speech.message,"what are you","whatcha") + speech.message = replacetext(speech.message,"yes",pick("sure", "yea")) + speech.message = replacetext(speech.message,"faggot","square") + speech.message = replacetext(speech.message,"muh valids","my kicks") + speech.message = replacetext(speech.message," vox "," bird ") - OnMobLife(var/mob/M) - switch(pick(1,2)) - if(1) - if(prob(15)) - var/list/dancetypes = list("swinging", "fancy", "stylish", "20'th century", "jivin'", "rock and roller", "cool", "salacious", "bashing", "smashing") - var/dancemoves = pick(dancetypes) - M.visible_message("[M] busts out some [dancemoves] moves!") - if(2) - if(prob(15)) - M.visible_message("[M] [pick("jiggles their hips", "rotates their hips", "gyrates their hips", "taps their foot", "dances to an imaginary song", "jiggles their legs", "snaps their fingers")]") +/datum/dna/gene/disability/elvis/OnMobLife(var/mob/M) + switch(pick(1,2)) + if(1) + if(prob(15)) + var/list/dancetypes = list("swinging", "fancy", "stylish", "20'th century", "jivin'", "rock and roller", "cool", "salacious", "bashing", "smashing") + var/dancemoves = pick(dancetypes) + M.visible_message("[M] busts out some [dancemoves] moves!") + if(2) + if(prob(15)) + M.visible_message("[M] [pick("jiggles their hips", "rotates their hips", "gyrates their hips", "taps their foot", "dances to an imaginary song", "jiggles their legs", "snaps their fingers")]") // WAS: /datum/bioEffect/chav -/datum/dna/gene/disability/speech/chav +/datum/dna/gene/disability/chav name = "Chav" desc = "Forces the language center of the subject's brain to construct sentences in a more rudimentary manner." activation_message = "Ye feel like a reet prat like, innit?" deactivation_message = "You no longer feel like being rude and sassy." - New() - ..() - block=CHAVBLOCK +/datum/dna/gene/disability/chav/New() + ..() + block = CHAVBLOCK - OnSay(var/mob/M, var/datum/speech/speech) - // THIS ENTIRE THING BEGS FOR REGEX - speech.message = replacetext(speech.message,"dick","prat") - speech.message = replacetext(speech.message,"comdom","knob'ead") - speech.message = replacetext(speech.message,"looking at","gawpin' at") - speech.message = replacetext(speech.message,"great","bangin'") - speech.message = replacetext(speech.message,"man","mate") - speech.message = replacetext(speech.message,"friend",pick("mate","bruv","bledrin")) - speech.message = replacetext(speech.message,"what","wot") - speech.message = replacetext(speech.message,"drink","wet") - speech.message = replacetext(speech.message,"get","giz") - speech.message = replacetext(speech.message,"what","wot") - speech.message = replacetext(speech.message,"no thanks","wuddent fukken do one") - speech.message = replacetext(speech.message,"i don't know","wot mate") - speech.message = replacetext(speech.message,"no","naw") - speech.message = replacetext(speech.message,"robust","chin") - speech.message = replacetext(speech.message," hi ","how what how") - speech.message = replacetext(speech.message,"hello","sup bruv") - speech.message = replacetext(speech.message,"kill","bang") - speech.message = replacetext(speech.message,"murder","bang") - speech.message = replacetext(speech.message,"windows","windies") - speech.message = replacetext(speech.message,"window","windy") - speech.message = replacetext(speech.message,"break","do") - speech.message = replacetext(speech.message,"your","yer") - speech.message = replacetext(speech.message,"security","coppers") +/datum/dna/gene/disability/chav/OnSay(var/mob/M, var/datum/speech/speech) + // THIS ENTIRE THING BEGS FOR REGEX + speech.message = replacetext(speech.message,"dick","prat") + speech.message = replacetext(speech.message,"comdom","knob'ead") + speech.message = replacetext(speech.message,"looking at","gawpin' at") + speech.message = replacetext(speech.message,"great","bangin'") + speech.message = replacetext(speech.message,"man","mate") + speech.message = replacetext(speech.message,"friend",pick("mate","bruv","bledrin")) + speech.message = replacetext(speech.message,"what","wot") + speech.message = replacetext(speech.message,"drink","wet") + speech.message = replacetext(speech.message,"get","giz") + speech.message = replacetext(speech.message,"what","wot") + speech.message = replacetext(speech.message,"no thanks","wuddent fukken do one") + speech.message = replacetext(speech.message,"i don't know","wot mate") + speech.message = replacetext(speech.message,"no","naw") + speech.message = replacetext(speech.message,"robust","chin") + speech.message = replacetext(speech.message," hi ","how what how") + speech.message = replacetext(speech.message,"hello","sup bruv") + speech.message = replacetext(speech.message,"kill","bang") + speech.message = replacetext(speech.message,"murder","bang") + speech.message = replacetext(speech.message,"windows","windies") + speech.message = replacetext(speech.message,"window","windy") + speech.message = replacetext(speech.message,"break","do") + speech.message = replacetext(speech.message,"your","yer") + speech.message = replacetext(speech.message,"security","coppers") // WAS: /datum/bioEffect/swedish -/datum/dna/gene/disability/speech/swedish +/datum/dna/gene/disability/swedish name = "Swedish" desc = "Forces the language center of the subject's brain to construct sentences in a vaguely norse manner." activation_message = "You feel Swedish, however that works." deactivation_message = "The feeling of Swedishness passes." - New() - ..() - block=SWEDEBLOCK +/datum/dna/gene/disability/swedish/New() + ..() + block=SWEDEBLOCK - OnSay(var/mob/M, var/datum/speech/speech) - // svedish! - speech.message = replacetext(speech.message,"w","v") - if(prob(30)) - speech.message += " Bork[pick("",", bork",", bork, bork")]!" +/datum/dna/gene/disability/swedish/OnSay(var/mob/M, var/datum/speech/speech) + // svedish! + speech.message = replacetext(speech.message,"w","v") + if(prob(30)) + speech.message += " Bork[pick("",", bork",", bork, bork")]!" // WAS: /datum/bioEffect/unintelligable /datum/dna/gene/disability/unintelligable @@ -246,32 +240,32 @@ activation_message = "You can't seem to form any coherent thoughts!" deactivation_message = "Your mind feels more clear." - New() - ..() - block=SCRAMBLEBLOCK +/datum/dna/gene/disability/unintelligable/New() + ..() + block = SCRAMBLEBLOCK - OnSay(var/mob/M, var/datum/speech/speech) - var/prefix=copytext(speech.message,1,2) - if(prefix == ";") - speech.message = copytext(speech.message,2) - else if(prefix in list(":","#")) - prefix += copytext(speech.message,2,3) - speech.message = copytext(speech.message,3) - else - prefix="" +/datum/dna/gene/disability/unintelligable/OnSay(var/mob/M, var/datum/speech/speech) + var/prefix=copytext(speech.message,1,2) + if(prefix == ";") + speech.message = copytext(speech.message,2) + else if(prefix in list(":","#")) + prefix += copytext(speech.message,2,3) + speech.message = copytext(speech.message,3) + else + prefix="" - var/list/words = splittext(speech.message," ") - var/list/rearranged = list() - for(var/i=1;i<=words.len;i++) - var/cword = pick(words) - words.Remove(cword) - var/suffix = copytext(cword,length(cword)-1,length(cword)) - while(length(cword)>0 && suffix in list(".",",",";","!",":","?")) - cword = copytext(cword,1 ,length(cword)-1) - suffix = copytext(cword,length(cword)-1,length(cword) ) - if(length(cword)) - rearranged += cword - speech.message = "[prefix][uppertext(jointext(rearranged," "))]!!" + var/list/words = splittext(speech.message," ") + var/list/rearranged = list() + for(var/i=1;i<=words.len;i++) + var/cword = pick(words) + words.Remove(cword) + var/suffix = copytext(cword,length(cword)-1,length(cword)) + while(length(cword)>0 && suffix in list(".",",",";","!",":","?")) + cword = copytext(cword,1 ,length(cword)-1) + suffix = copytext(cword,length(cword)-1,length(cword) ) + if(length(cword)) + rearranged += cword + speech.message = "[prefix][uppertext(jointext(rearranged," "))]!!" // WAS: /datum/bioEffect/toxic_farts /datum/dna/gene/disability/toxic_farts @@ -283,9 +277,9 @@ mutation = M_TOXIC_FARTS - New() - ..() - block=TOXICFARTBLOCK +/datum/dna/gene/disability/toxic_farts/New() + ..() + block=TOXICFARTBLOCK ////////////////// // USELESS SHIT // @@ -300,41 +294,12 @@ deactivation_message = "Your horns crumble away into nothing." flags = GENE_UNNATURAL - New() - ..() - block=HORNSBLOCK - - OnDrawUnderlays(var/mob/M,var/g,var/fat) - return "horns_s" - -/* Stupid -/datum/bioEffect/stinky - name = "Apocrine Enhancement" - desc = "Increases the amount of natural body substances produced from the subject's apocrine glands." - id = "stinky" - effectType = effectTypeDisability - isBad = 1 - msgGain = "You feel sweaty." - msgLose = "You feel much more hygenic." - var/personalized_stink = "Wow, it stinks in here!" - - New() - ..() - src.personalized_stink = stinkString() - if (prob(5)) - src.variant = 2 - - OnLife() - if (prob(10)) - for(var/mob/living/carbon/C in view(6,get_turf(owner))) - if (C == owner) - continue - if (src.variant == 2) - to_chat(C, "[src.personalized_stink]") - else - to_chat(C, "[stinkString()]") -*/ +/datum/dna/gene/disability/horns/New() + ..() + block = HORNSBLOCK +/datum/dna/gene/disability/horns/OnDrawUnderlays(var/mob/M,var/g,var/fat) + return "horns_s" //////////////////////////////////////////////////////////////////////// // WAS: /datum/bioEffect/immolate @@ -347,9 +312,9 @@ spelltype = /spell/targeted/immolate - New() - ..() - block = IMMOLATEBLOCK +/datum/dna/gene/basic/grant_spell/immolate/New() + ..() + block = IMMOLATEBLOCK /spell/targeted/immolate name = "Incendiary Mitochondria" @@ -391,9 +356,9 @@ spelltype = /spell/targeted/melt - New() - ..() - block = MELTBLOCK +/datum/dna/gene/basic/grant_spell/melt/New() + ..() + block = MELTBLOCK /spell/targeted/melt name = "Dissolve" diff --git a/code/game/dna/genes/goon_powers.dm b/code/game/dna/genes/goon_powers.dm index 9cc6b4df18e..28365759c7b 100644 --- a/code/game/dna/genes/goon_powers.dm +++ b/code/game/dna/genes/goon_powers.dm @@ -1,64 +1,46 @@ -#define EAT_MOB_DELAY 300 // 30s +#define EAT_MOB_DELAY 30 SECONDS // WAS: /datum/bioEffect/alcres /datum/dna/gene/basic/sober - name="Sober" - activation_messages=list("You feel unusually sober.") + name = "Sober" + activation_messages = list("You feel unusually sober.") deactivation_messages = list("You feel like you could use a stiff drink.") - mutation=M_SOBER + mutation = M_SOBER - New() - block=SOBERBLOCK +/datum/dna/gene/basic/sober/New() + block = SOBERBLOCK //WAS: /datum/bioEffect/psychic_resist /datum/dna/gene/basic/psychic_resist - name="Psy-Resist" + name = "Psy-Resist" desc = "Boosts efficiency in sectors of the brain commonly associated with meta-mental energies." activation_messages = list("Your mind feels closed.") deactivation_messages = list("You feel oddly exposed.") - mutation=M_PSY_RESIST + mutation = M_PSY_RESIST - New() - block=PSYRESISTBLOCK +/datum/dna/gene/basic/psychic_resist/New() + block = PSYRESISTBLOCK ///////////////////////// // Stealth Enhancers ///////////////////////// /datum/dna/gene/basic/stealth - can_activate(var/mob/M, var/flags) - // Can only activate one of these at a time. - if(is_type_in_list(/datum/dna/gene/basic/stealth,M.active_genes)) - testing("Cannot activate [type]: /datum/dna/gene/basic/stealth in M.active_genes.") - return 0 - return ..(M,flags) - deactivate(var/mob/M, var/connected, var/flags) - if(..(M,connected,flags)) - M.alphas -= "chameleon_stealth" - M.handle_alpha() +/datum/dna/gene/basic/stealth/can_activate(var/mob/M, var/flags) + // Can only activate one of these at a time. + if(is_type_in_list(/datum/dna/gene/basic/stealth,M.active_genes)) + testing("Cannot activate [type]: /datum/dna/gene/basic/stealth in M.active_genes.") + return 0 + return ..(M,flags) -// WAS: /datum/bioEffect/darkcloak -/*/datum/dna/gene/basic/stealth/darkcloak - name = "Cloak of Darkness" - desc = "Enables the subject to bend low levels of light around themselves, creating a cloaking effect." - activation_messages = list("You begin to fade into the shadows.") - deactivation_messages = list("You become fully visible.") +/datum/dna/gene/basic/stealth/deactivate(var/mob/M, var/connected, var/flags) + if(..(M,connected,flags)) + M.alphas -= "chameleon_stealth" + M.handle_alpha() - New() - block=SHADOWBLOCK - - OnMobLife(var/mob/M) - var/turf/simulated/T = get_turf(M) - if(!istype(T)) - return - if(T.lighting_lumcount <= 2) - M.alpha -= 25 - else - M.alpha = round(255 * 0.80) -*/ //WAS: /datum/bioEffect/chameleon /datum/dna/gene/basic/stealth/chameleon name = "Chameleon" @@ -66,14 +48,14 @@ activation_messages = list("You feel one with your surroundings.") deactivation_messages = list("You feel oddly exposed.") - New() - block=CHAMELEONBLOCK +/datum/dna/gene/basic/stealth/chameleon/New() + block = CHAMELEONBLOCK - OnMobLife(var/mob/M) - if((world.time - M.last_movement) >= 30 && !M.isUnconscious() && M.canmove && !M.restrained()) - M.alphas["chameleon_stealth"] = max(M.alphas["chameleon_stealth"] - 25, 0) - else - M.alphas["chameleon_stealth"] = round(255 * 0.80) +/datum/dna/gene/basic/stealth/chameleon/OnMobLife(var/mob/M) + if((world.time - M.last_movement) >= 30 && !M.isUnconscious() && M.canmove && !M.restrained()) + M.alphas["chameleon_stealth"] = max(M.alphas["chameleon_stealth"] - 25, 0) + else + M.alphas["chameleon_stealth"] = round(255 * 0.80) ///////////////////////////////////////////////////////////////////////////////////////// @@ -81,42 +63,42 @@ var/spell/spelltype var/list/granted_spells - activate(var/mob/M, var/connected, var/flags) - ..(M,connected,flags) - var/spell/granted = new spelltype - M.add_spell(granted, "genetic_spell_ready", /obj/abstract/screen/movable/spell_master/genetic) - if(!granted_spells) - granted_spells = list() - granted_spells += granted - //testing("[M] added [granted.name] from [name]") - return 1 +/datum/dna/gene/basic/grant_spell/activate(var/mob/M, var/connected, var/flags) + ..() + var/spell/granted = new spelltype + M.add_spell(granted, "genetic_spell_ready", /obj/abstract/screen/movable/spell_master/genetic) + if(!granted_spells) + granted_spells = list() + granted_spells += granted + //testing("[M] added [granted.name] from [name]") + return 1 - deactivate(var/mob/M, var/connected, var/flags) - if(..(M,connected,flags)) - for(var/spell/S in M.spell_list) - if(S in granted_spells) - M.remove_spell(S) - granted_spells -= S - //testing("[M] removed [S.name] from [name]") - qdel(S) - return 1 +/datum/dna/gene/basic/grant_spell/deactivate(var/mob/M, var/connected, var/flags) + if(!..()) return 0 + for(var/spell/S in M.spell_list) + if(S in granted_spells) + M.remove_spell(S) + granted_spells -= S + //testing("[M] removed [S.name] from [name]") + qdel(S) + return 1 /datum/dna/gene/basic/grant_verb var/verbtype - activate(var/mob/M, var/connected, var/flags) - ..(M,connected,flags) - M.verbs += verbtype - //testing("[M] added [verbtype] from [name]") - return 1 +/datum/dna/gene/basic/grant_verb/activate(var/mob/M, var/connected, var/flags) + ..() + M.verbs += verbtype + //testing("[M] added [verbtype] from [name]") + return 1 - deactivate(var/mob/M, var/connected, var/flags) - if(..(M,connected,flags)) - M.verbs -= verbtype - //testing("[M] removed [verbtype] from [name]") - return 1 +/datum/dna/gene/basic/grant_verb/deactivate(var/mob/M, var/connected, var/flags) + if(!..()) return 0 + M.verbs -= verbtype + //testing("[M] removed [verbtype] from [name]") + return 1 // WAS: /datum/bioEffect/cryokinesis /datum/dna/gene/basic/grant_spell/cryo @@ -130,9 +112,9 @@ spelltype = /spell/targeted/cryokinesis - New() - ..() - block = CRYOBLOCK +/datum/dna/gene/basic/grant_spell/cryo/New() + ..() + block = CRYOBLOCK /spell/targeted/cryokinesis name = "Cryokinesis" @@ -191,14 +173,14 @@ activation_messages = list("You feel hungry.") deactivation_messages = list("You don't feel quite so hungry anymore.") - drug_activation_messages=list("You are getting the munchies.") - drug_deactivation_messages=list("You no longer getting the munchies.") + drug_activation_messages = list("You are getting the munchies.") + drug_deactivation_messages = list("You no longer getting the munchies.") - spelltype= /spell/targeted/eat + spelltype = /spell/targeted/eat - New() - ..() - block = EATBLOCK +/datum/dna/gene/basic/grant_spell/mattereater/New() + ..() + block = EATBLOCK /spell/targeted/eat name = "Eat" @@ -234,7 +216,7 @@ /mob/living/simple_animal/tomato, /mob/living/simple_animal/chick, /mob/living/simple_animal/chicken, - /mob/living/simple_animal/lizard, + /mob/living/simple_animal/hostile/lizard, /mob/living/simple_animal/cow, /mob/living/simple_animal/spiderbot ) @@ -382,14 +364,14 @@ else user.visible_message("[user] eats [the_item]'s [limb.display_name].", \ "You eat [the_item]'s [limb.display_name].") - playsound(get_turf(user), 'sound/items/eatfood.ogg', 50, 0) + playsound(user, 'sound/items/eatfood.ogg', 50, 0) message_admins("[user] ate [the_item]'s [limb]: (Jump to)") log_game("[user] ate \the [the_item]'s [limb] at [user.x], [user.y], [user.z]") limb.droplimb("override" = 1, "spawn_limb" = 0) doHeal(user) else user.visible_message("[usr] eats \the [the_item].") - playsound(get_turf(user), 'sound/items/eatfood.ogg', 50, 0) + playsound(user, 'sound/items/eatfood.ogg', 50, 0) message_admins("[user] ate \the [the_item]: (Jump to)") log_game("[user] ate \the [the_item] at [user.x], [user.y], [user.z]") qdel(the_item) @@ -402,18 +384,17 @@ /datum/dna/gene/basic/grant_spell/jumpy name = "Jumpy" desc = "Allows the subject to leap great distances." - //cooldown = 30 activation_messages = list("Your leg muscles feel taut and strong.") deactivation_messages = list("Your leg muscles shrink back to normal.") - drug_activation_messages=list() - drug_deactivation_messages=list() + drug_activation_messages = list() + drug_deactivation_messages = list() - spelltype =/spell/targeted/leap + spelltype = /spell/targeted/leap - New() - ..() - block = JUMPBLOCK +/datum/dna/gene/basic/grant_spell/jumpy/New() + ..() + block = JUMPBLOCK /spell/targeted/leap name = "Jump" @@ -518,8 +499,6 @@ return -//////////////////////////////////////////////////////////////////////// - // WAS: /datum/bioEffect/polymorphism /datum/dna/gene/basic/grant_spell/polymorph @@ -527,16 +506,15 @@ desc = "Enables the subject to reconfigure their appearance to mimic that of others." spelltype = /spell/targeted/polymorph - //cooldown = 1800 activation_messages = list("You don't feel entirely like yourself somehow.") deactivation_messages = list("You feel secure in your identity.") - drug_activation_messages=list() - drug_deactivation_messages=list() + drug_activation_messages = list() + drug_deactivation_messages = list() - New() - ..() - block = POLYMORPHBLOCK +/datum/dna/gene/basic/grant_spell/polymorph/New() + ..() + block = POLYMORPHBLOCK /spell/targeted/polymorph name = "Polymorph" @@ -583,9 +561,9 @@ drug_activation_messages=list("You feel more social!") drug_deactivation_messages=list("You feel less social.") - New() - ..() - block = EMPATHBLOCK +/datum/dna/gene/basic/grant_spell/empath/New() + ..() + block = EMPATHBLOCK /spell/targeted/empath name = "Read Mind" @@ -624,7 +602,7 @@ to_chat(user, "You can't see into [M.name]'s mind at all!") return 1 - if (M.stat == 2) + if (M.isDead()) to_chat(user, "[M.name] is dead and cannot have their mind read.") return 1 if (M.health < 0) @@ -722,4 +700,4 @@ /datum/dna/gene/basic/strong/New() ..() - block=STRONGBLOCK + block = STRONGBLOCK diff --git a/code/game/dna/genes/monkey.dm b/code/game/dna/genes/monkey.dm index bbeb26ecb47..beefa5e1159 100644 --- a/code/game/dna/genes/monkey.dm +++ b/code/game/dna/genes/monkey.dm @@ -1,9 +1,9 @@ /datum/dna/gene/monkey - name="Monkey" + name = "Monkey" flags = GENE_UNNATURAL /datum/dna/gene/monkey/New() - block=MONKEYBLOCK + block = MONKEYBLOCK /datum/dna/gene/monkey/can_activate(var/mob/M,var/flags) return istype(M, /mob/living/carbon/human) || istype(M,/mob/living/carbon/monkey) @@ -27,7 +27,7 @@ //Monkey to human /datum/dna/gene/monkey/deactivate(var/mob/living/M, var/connected, var/flags) if(!istype(M,/mob/living/carbon/monkey)) - testing("Cannot humanize [M], type is [M.type].") +// testing("Cannot humanize [M], type is [M.type].") return var/mob/living/carbon/monkey/Mo = M Mo.monkeyizing = 1 diff --git a/code/game/dna/genes/powers.dm b/code/game/dna/genes/powers.dm index 6eb1d39b557..baa11e925af 100644 --- a/code/game/dna/genes/powers.dm +++ b/code/game/dna/genes/powers.dm @@ -3,31 +3,32 @@ /////////////////////////////////// /datum/dna/gene/basic/nobreath - name="No Breathing" - activation_messages=list("You feel no need to breathe.") - deactivation_messages=list("The need to breathe returns.") - mutation=M_NO_BREATH + name = "No Breathing" + activation_messages = list("You feel no need to breathe.") + deactivation_messages = list("The need to breathe returns.") + mutation = M_NO_BREATH - New() - block=NOBREATHBLOCK +/datum/dna/gene/basic/nobreath/New() + block = NOBREATHBLOCK /datum/dna/gene/basic/grant_spell/remoteview - name="Remote Viewing" - activation_messages=list("Your mind expands.") - deactivation_messages=list("Your mind is no longer expanded.") + name = "Remote Viewing" + activation_messages = list("Your mind expands.") + deactivation_messages = list("Your mind is no longer expanded.") - drug_activation_messages=list("You feel in touch with the cosmos.") - drug_deactivation_messages=list("You no longer feel in touch with the cosmos.") + drug_activation_messages = list("You feel in touch with the cosmos.") + drug_deactivation_messages = list("You no longer feel in touch with the cosmos.") - mutation=M_REMOTE_VIEW + mutation = M_REMOTE_VIEW spelltype = /spell/targeted/remoteobserve - New() - block=REMOTEVIEWBLOCK +/datum/dna/gene/basic/grant_spell/remoteview/New() + block = REMOTEVIEWBLOCK /spell/targeted/remoteobserve name = "Remote View" + desc = "Lets you see through the eyes of others." panel = "Mutant Powers" charge_type = Sp_RECHARGE @@ -73,42 +74,42 @@ break /datum/dna/gene/basic/regenerate - name="Regenerate" - activation_messages=list("You feel better.") - deactivation_messages=list("You stop feeling better.") - mutation=M_REGEN + name = "Regenerate" + activation_messages = list("You feel better.") + deactivation_messages = list("You stop feeling better.") + mutation = M_REGEN - New() - block=REGENERATEBLOCK +/datum/dna/gene/basic/regenerate/New() + block=REGENERATEBLOCK /datum/dna/gene/basic/increaserun - name="Super Speed" - activation_messages=list("Your leg muscles pulsate.") - deactivation_messages=list("Your leg muscles no longer pulsate.") - mutation=M_RUN + name = "Super Speed" + activation_messages = list("Your leg muscles pulsate.") + deactivation_messages = list("Your leg muscles no longer pulsate.") + mutation = M_RUN - New() - block=INCREASERUNBLOCK +/datum/dna/gene/basic/increaserun/New() + block = INCREASERUNBLOCK /datum/dna/gene/basic/grant_spell/remotetalk - name="Telepathy" - activation_messages=list("You feel your voice can penetrate other minds.") - deactivation_messages=list("Your mind can no longer project your voice onto others.") + name = "Telepathy" + activation_messages = list("You feel your voice can penetrate other minds.") + deactivation_messages = list("Your mind can no longer project your voice onto others.") - drug_activation_messages=list("You feel your voice can reach the astral plane now.") - drug_deactivation_messages=list("Your voice can no longer reach the astral plane.") + drug_activation_messages = list("You feel your voice can reach the astral plane now.") + drug_deactivation_messages = list("Your voice can no longer reach the astral plane.") - mutation=M_REMOTE_TALK + mutation = M_REMOTE_TALK spelltype = /spell/targeted/remotesay - New() - ..() - block=REMOTETALKBLOCK +/datum/dna/gene/basic/grant_spell/remotetalk/New() + ..() + block = REMOTETALKBLOCK /spell/targeted/remotesay name = "Project Mind" - desc = "Speak into the minds of others." + desc = "Speak into the minds of others. You must either hear them speak or examine them to make contact." panel = "Mutant Powers" charge_type = Sp_RECHARGE @@ -153,170 +154,135 @@ G.show_message("Telepathic message from [user] to [target]: [say]") /datum/dna/gene/basic/morph - name="Morph" - activation_messages=list("Your skin feels strange.") - deactivation_messages=list("Your skin no longer feels strange.") + name = "Morph" + activation_messages = list("Your skin feels strange.") + deactivation_messages = list("Your skin no longer feels strange.") - drug_activation_messages=list("You feel like a chameleon.") - drug_deactivation_messages=list("You no longer feel like a chameleon.") + drug_activation_messages = list("You feel like a chameleon.") + drug_deactivation_messages = list("You no longer feel like a chameleon.") - mutation=M_MORPH + mutation = M_MORPH - New() - block=MORPHBLOCK +/datum/dna/gene/basic/morph/New() + block = MORPHBLOCK - activate(var/mob/M) - ..(M) - M.verbs += /mob/living/carbon/human/proc/morph +/datum/dna/gene/basic/morph/activate(var/mob/M) + ..() + M.verbs += /mob/living/carbon/human/proc/morph /datum/dna/gene/basic/heat_resist - name="Heat Resistance" - activation_messages=list("Your skin is icy to the touch.") - deactivation_messages=list("Your skin stops feeling icy.") + name = "Heat Resistance" + activation_messages = list("Your skin is icy to the touch.") + deactivation_messages = list("Your skin stops feeling icy.") - drug_activation_messages=list() - drug_deactivation_messages=list() + drug_activation_messages = list() + drug_deactivation_messages = list() - mutation=M_RESIST_HEAT + mutation = M_RESIST_HEAT - New() - block=COLDBLOCK +/datum/dna/gene/basic/heat_resist/New() + block = COLDBLOCK - can_activate(var/mob/M,var/flags) - if(flags & MUTCHK_FORCED) - return !(/datum/dna/gene/basic/cold_resist in M.active_genes) - // Probability check - var/_prob = 15 - if(M_RESIST_COLD in M.mutations) - _prob=5 - if(probinj(_prob,(flags&MUTCHK_FORCED))) - return 1 +/datum/dna/gene/basic/heat_resist/can_activate(var/mob/M,var/flags) + if(flags & MUTCHK_FORCED) + return !(/datum/dna/gene/basic/cold_resist in M.active_genes) + // Probability check + var/_prob = 15 + if(M_RESIST_COLD in M.mutations) + _prob=5 + if(probinj(_prob,(flags&MUTCHK_FORCED))) + return 1 - OnDrawUnderlays(var/mob/M,var/g,var/fat) - return "cold[fat]_s" +/datum/dna/gene/basic/heat_resist/OnDrawUnderlays(var/mob/M,var/g,var/fat) + return "cold[fat]_s" /datum/dna/gene/basic/cold_resist - name="Cold Resistance" - activation_messages=list("Your body is filled with warmth.") - deactivation_messages=list("Your body is no longer filled with warmth.") + name = "Cold Resistance" + activation_messages = list("Your body is filled with warmth.") + deactivation_messages = list("Your body is no longer filled with warmth.") - drug_activation_messages=list() - drug_deactivation_messages=list() + drug_activation_messages = list() + drug_deactivation_messages = list() - mutation=M_RESIST_COLD + mutation = M_RESIST_COLD - New() - block=FIREBLOCK +/datum/dna/gene/basic/cold_resist/New() + block = FIREBLOCK - can_activate(var/mob/M,var/flags) - if(flags & MUTCHK_FORCED) - return !(/datum/dna/gene/basic/heat_resist in M.active_genes) - // Probability check - var/_prob=30 - if(M_RESIST_HEAT in M.mutations) - _prob=5 - if(probinj(_prob,(flags&MUTCHK_FORCED))) - return 1 +/datum/dna/gene/basic/cold_resist/can_activate(var/mob/M,var/flags) + if(flags & MUTCHK_FORCED) + return !(/datum/dna/gene/basic/heat_resist in M.active_genes) + // Probability check + var/_prob=30 + if(M_RESIST_HEAT in M.mutations) + _prob=5 + if(probinj(_prob,(flags&MUTCHK_FORCED))) + return 1 - OnDrawUnderlays(var/mob/M,var/g,var/fat) - return "fire[fat]_s" +/datum/dna/gene/basic/cold_resist/OnDrawUnderlays(var/mob/M,var/g,var/fat) + return "fire[fat]_s" /datum/dna/gene/basic/noprints - name="No Prints" - activation_messages=list("Your fingers feel numb.") - deactivation_messages=list("Your fingers stop feeling numb.") - mutation=M_FINGERPRINTS + name = "No Prints" + activation_messages = list("Your fingers feel numb.") + deactivation_messages = list("Your fingers stop feeling numb.") + mutation = M_FINGERPRINTS - New() - block=NOPRINTSBLOCK +/datum/dna/gene/basic/noprints/New() + block = NOPRINTSBLOCK /datum/dna/gene/basic/noshock - name="Shock Immunity" - activation_messages=list("Your skin feels electric.") - deactivation_messages=list("Your skin no longer feels electric.") - mutation=M_NO_SHOCK + name = "Shock Immunity" + activation_messages = list("Your skin feels electric.") + deactivation_messages = list("Your skin no longer feels electric.") + mutation = M_NO_SHOCK - New() - block=SHOCKIMMUNITYBLOCK +/datum/dna/gene/basic/noshock/New() + block = SHOCKIMMUNITYBLOCK /datum/dna/gene/basic/midget - name="Midget" - activation_messages=list("You feel small.") - deactivation_messages=list("You stop feeling small.") - mutation=M_DWARF + name = "Midget" + activation_messages = list("You feel small.") + deactivation_messages = list("You stop feeling small.") + mutation = M_DWARF - New() - block=SMALLSIZEBLOCK +/datum/dna/gene/basic/midget/New() + block = SMALLSIZEBLOCK - activate(var/mob/M, var/connected, var/flags) - ..(M,connected,flags) - M.pass_flags |= PASSTABLE +/datum/dna/gene/basic/midget/activate(var/mob/M, var/connected, var/flags) + ..() + M.pass_flags |= PASSTABLE - deactivate(var/mob/M, var/connected, var/flags) - if(..(M,connected,flags)) - M.pass_flags &= ~PASSTABLE +/datum/dna/gene/basic/midget/deactivate(var/mob/M, var/connected, var/flags) + if(..()) + M.pass_flags &= ~PASSTABLE -/* OLD HULK BEHAVIOR -/datum/dna/gene/basic/hulk - name="Hulk" - activation_messages=list("Your muscles hurt.") - mutation=M_HULK - - New() - block=HULKBLOCK - - can_activate(var/mob/M,var/flags) - // Can't be big AND small. - if(M_DWARF in M.mutations) - return 0 - return ..(M,flags) - - OnDrawUnderlays(var/mob/M,var/g,var/fat) - if(M_HULK in M.mutations) - if(fat) - return "hulk_[fat]_s" - else - return "hulk_[g]_s" - return 0 - - OnMobLife(var/mob/living/carbon/human/M) - if(!istype(M)) - return - if(M.health <= 25 && M_HULK in M.mutations) - M.mutations.Remove(M_HULK) - M.dna.SetSEState(HULKBLOCK,0) - M.update_mutations() //update our mutation overlays - M.update_body() - to_chat(M, "You suddenly feel very weak.") - M.Knockdown(3) - M.emote("collapse") -*/ /datum/dna/gene/basic/xray - name="X-Ray Vision" - activation_messages=list("The walls suddenly disappear.") - deactivation_messages=list("The walls suddenly appear.") + name = "X-Ray Vision" + activation_messages = list("The walls suddenly disappear.") + deactivation_messages = list("The walls suddenly appear.") - drug_activation_messages=list("You see so much clearer now!") - drug_deactivation_messages=list("Your vision is obstructed again.") + drug_activation_messages = list("You see so much clearer now!") + drug_deactivation_messages = list("Your vision is obstructed again.") - mutation=M_XRAY + mutation = M_XRAY - New() - block=XRAYBLOCK +/datum/dna/gene/basic/xray/New() + block = XRAYBLOCK /datum/dna/gene/basic/tk - name="Telekenesis" - activation_messages=list("You feel smarter.") - deactivation_messages=list("You feel less smart.") + name = "Telekenesis" + activation_messages = list("You feel smarter.") + deactivation_messages = list("You feel less smart.") - drug_activation_messages=list("You feel like a nerd.") - drug_deactivation_messages=list("You feel normal again.") + drug_activation_messages = list("You feel like a nerd.") + drug_deactivation_messages = list("You feel normal again.") - mutation=M_TK - activation_prob=15 + mutation = M_TK + activation_prob = 15 - New() - block=TELEBLOCK +/datum/dna/gene/basic/tk/New() + block = TELEBLOCK - OnDrawUnderlays(var/mob/M,var/g,var/fat) - return "telekinesishead[fat]_s" \ No newline at end of file +/datum/dna/gene/basic/tk/OnDrawUnderlays(var/mob/M,var/g,var/fat) + return "telekinesishead[fat]_s" diff --git a/code/game/dna/genes/vg_disabilities.dm b/code/game/dna/genes/vg_disabilities.dm index aae3876cb85..3d11a3fc93e 100644 --- a/code/game/dna/genes/vg_disabilities.dm +++ b/code/game/dna/genes/vg_disabilities.dm @@ -1,15 +1,15 @@ -/datum/dna/gene/disability/speech/loud +/datum/dna/gene/disability/loud name = "Loud" desc = "Forces the speaking centre of the subjects brain to yell every sentence." activation_message = "YOU FEEL LIKE YELLING!" deactivation_message = "You feel like being quiet.." -/datum/dna/gene/disability/speech/loud/New() +/datum/dna/gene/disability/loud/New() ..() - block=LOUDBLOCK + block = LOUDBLOCK -/datum/dna/gene/disability/speech/loud/OnSay(var/mob/M, var/datum/speech/speech) +/datum/dna/gene/disability/loud/OnSay(var/mob/M, var/datum/speech/speech) speech.message = replacetext(speech.message,".","!") speech.message = replacetext(speech.message,"?","?!") speech.message = replacetext(speech.message,"!","!!") @@ -17,23 +17,23 @@ speech.message = uppertext(speech.message) -/datum/dna/gene/disability/speech/whisper +/datum/dna/gene/disability/whisper name = "Quiet" desc = "Damages the subjects vocal cords" activation_message = "Your throat feels sore.." deactivation_message = "You feel fine again." -/datum/dna/gene/disability/speech/whisper/New() +/datum/dna/gene/disability/whisper/New() ..() - block=WHISPERBLOCK + block = WHISPERBLOCK -/datum/dna/gene/disability/speech/whisper/can_activate(var/mob/M,var/flags) +/datum/dna/gene/disability/whisper/can_activate(var/mob/M,var/flags) // No loud whispering. if(M_LOUD in M.mutations) return 0 return ..(M,flags) -/datum/dna/gene/disability/speech/whisper/OnSay(var/mob/M, var/datum/speech/speech) +/datum/dna/gene/disability/whisper/OnSay(var/mob/M, var/datum/speech/speech) //M.whisper(message) return 0 @@ -45,30 +45,29 @@ deactivation_message = "You regain your balance." flags = GENE_UNNATURAL - New() - ..() - block=DIZZYBLOCK +/datum/dna/gene/disability/dizzy/New() + ..() + block = DIZZYBLOCK + +/datum/dna/gene/disability/dizzy/OnMobLife(var/mob/living/carbon/human/M) + if(!istype(M)) + return + if(M_DIZZY in M.mutations) + M.Dizzy(300) - OnMobLife(var/mob/living/carbon/human/M) - if(!istype(M)) - return - if(M_DIZZY in M.mutations) - M.Dizzy(300) - - -/datum/dna/gene/disability/speech/sans +/datum/dna/gene/disability/sans name = "Wacky" desc = "Forces the subject to talk in an odd manner." activation_message = "You feel an off sensation in your voicebox.." deactivation_message = "The off sensation passes.." - New() - ..() - block=SANSBLOCK +/datum/dna/gene/disability/speech/sans/New() + ..() + block = SANSBLOCK - OnSay(var/mob/M, var/datum/speech/speech) - speech.message_classes.Add("sans") // SPEECH 2.0!!!1 +/datum/dna/gene/disability/speech/sans/OnSay(var/mob/M, var/datum/speech/speech) + speech.message_classes.Add("sans") // SPEECH 2.0!!!1 /datum/dna/gene/disability/veganism name = "Veganism" @@ -78,25 +77,25 @@ mutation = M_VEGAN - var/global/static/list/nonvegan_reagents = list( - HONEY, - //Milk-based products - MILK, - VIRUSFOOD, - CREAM, - CAFE_LATTE, - MILKSHAKE, - OFFCOLORCHEESE, - CHEESYGLOOP, //this one doesn't leave your body naturally, but you'll vomit it out eventually - //Blood-based products - BLOOD, - DEMONSBLOOD, - RED_MEAD, - DEVILSKISS, - MEDCOFFEE, - //Misc - HORSEMEAT, - BONEMARROW, + var/static/list/nonvegan_reagents = list( + HONEY, + //Milk-based products + MILK, + VIRUSFOOD, + CREAM, + CAFE_LATTE, + MILKSHAKE, + OFFCOLORCHEESE, + CHEESYGLOOP, //this one doesn't leave your body naturally, but you'll vomit it out eventually + //Blood-based products + BLOOD, + DEMONSBLOOD, + RED_MEAD, + DEVILSKISS, + MEDCOFFEE, + //Misc + HORSEMEAT, + BONEMARROW, ) /datum/dna/gene/disability/veganism/New() @@ -117,3 +116,68 @@ else H.vomit() break + +/datum/dna/gene/disability/asthma + name = "Asthma" + desc = "A condition in which a person's airways become inflamed, narrow and swell, and produce extra mucus, which makes it difficult to breathe." + activation_message = "You feel short of breath." + deactivation_message = "You can breathe normally again." + disability = ASTHMA + flags = GENE_UNNATURAL + mutation = M_ASTHMA + +/datum/dna/gene/disability/asthma/New() + ..() + block = ASTHMABLOCK + +var/list/milk_reagents = list( + MILK, + CREAM, + VIRUSFOOD, + OFFCOLORCHEESE, + CHEESYGLOOP, + ALOE, + BANANAHONK, + BILK, + CAFE_LATTE, + MILKSHAKE, + BAREFOOT, + PINACOLADA, + BOOGER, + BROWNSTAR, + IRISHCARBOMB, + IRISHCOFFEE, + IRISHCREAM, + SILENCER, + DOCTORSDELIGHT, + WHITERUSSIAN, + ANTIFREEZE) + + +/datum/dna/gene/disability/lactose + name = "Lactose intolerance" + desc = "A condition where your body is unable to digest Lactose, a sugar commonly found in milk." + activation_message = "Your stomach feels upset and bloated." + deactivation_message = "The discomfort in your stomach fades away." + disability = LACTOSE + + mutation = M_LACTOSE + +/datum/dna/gene/disability/lactose/New() + ..() + block = LACTOSEBLOCK + +/datum/dna/gene/disability/lactose/OnMobLife(var/mob/living/carbon/human/H) + if(!istype(H)) + return + + if(prob(10)) + for(var/R in milk_reagents) + if(H.reagents.has_reagent(R)) + to_chat(H, "Your body rejects the [reagent_name(R)]!") + + if(H.lastpuke) //If already puking, add some toxins + H.adjustToxLoss(2.5) + else + H.vomit() + break diff --git a/code/game/dna/genes/vg_powers.dm b/code/game/dna/genes/vg_powers.dm index 74a3ccb3158..252b59f6645 100644 --- a/code/game/dna/genes/vg_powers.dm +++ b/code/game/dna/genes/vg_powers.dm @@ -5,7 +5,7 @@ Obviously, requires DNA2. */ // When hulk was first applied (world.time). -/mob/living/carbon/human/var/hulk_time=0 +/mob/living/carbon/human/var/hulk_time = 0 // In decaseconds. #define HULK_DURATION 300 // How long the effects last @@ -17,8 +17,8 @@ Obviously, requires DNA2. activation_messages = list("Your muscles hurt.") deactivation_messages = list("Your muscles quit tensing.") - drug_activation_messages=list("You feel strong! You must've been working out lately.") - drug_deactivation_messages=list("You return to your old lifestyle.") + drug_activation_messages = list("You feel strong! You must've been working out lately.") + drug_deactivation_messages = list("You return to your old lifestyle.") flags = GENE_UNNATURAL // Do NOT spawn on roundstart. @@ -40,11 +40,10 @@ Obviously, requires DNA2. if(!istype(M)) return if(M_HULK in M.mutations) - var/timeleft=M.hulk_time - world.time + var/timeleft = M.hulk_time - world.time if(M.health <= 25 || timeleft <= 0) M.hulk_time=0 // Just to be sure. M.mutations.Remove(M_HULK) - //M.dna.SetSEState(HULKBLOCK,0) M.update_mutations() //update our mutation overlays M.update_body() to_chat(M, "You suddenly feel very weak.") @@ -93,14 +92,15 @@ Obviously, requires DNA2. activation_messages = list("Your eyes focus.") deactivation_messages = list("Your eyes return to normal.") - drug_activation_messages=list("The world becomes huge! You feel like an ant.") - drug_deactivation_messages=list("You no longer feel like an insect.") + drug_activation_messages = list("The world becomes huge! You feel like an ant.") + drug_deactivation_messages = list("You no longer feel like an insect.") mutation = M_FARSIGHT /datum/dna/gene/basic/farsight/New() - block=FARSIGHTBLOCK + block = FARSIGHTBLOCK ..() + /datum/dna/gene/basic/farsight/activate(var/mob/M) ..() if(M.client) @@ -136,15 +136,15 @@ Obviously, requires DNA2. var/noir_master = list(new /obj/abstract/screen/plane_master/noir_master(),new /obj/abstract/screen/plane_master/noir_dummy()) /datum/dna/gene/basic/noir - name="Noir" + name = "Noir" desc = "In recent years, there's been a real push towards 'Detective Noir' movies, but since the last black and white camera was lost many centuries ago, Scientists had to develop a way to turn any movie noir." - activation_messages=list("The Station's bright coloured light hits your eyes for the last time, and fades into a more appropriate tone, something's different about this place, but you can't put your finger on it. You feel a need to check out the bar, maybe get to the bottom of what's going on in this godforsaken place.") + activation_messages = list("The Station's bright coloured light hits your eyes for the last time, and fades into a more appropriate tone, something's different about this place, but you can't put your finger on it. You feel a need to check out the bar, maybe get to the bottom of what's going on in this godforsaken place.") deactivation_messages = list("You now feel soft boiled.") - mutation=M_NOIR + mutation = M_NOIR /datum/dna/gene/basic/noir/New() - block=NOIRBLOCK + block = NOIRBLOCK ..() /datum/dna/gene/basic/noir/activate(var/mob/M) diff --git a/code/game/gamemodes/blob/blobs/factory.dm b/code/game/gamemodes/blob/blobs/factory.dm index dce64fa8b77..09da9bf65b6 100644 --- a/code/game/gamemodes/blob/blobs/factory.dm +++ b/code/game/gamemodes/blob/blobs/factory.dm @@ -43,7 +43,7 @@ /obj/effect/blob/factory/Destroy() if(spores.len) for(var/mob/living/simple_animal/hostile/blobspore/S in spores) - S.Die() + S.death() if(!manual_remove && overmind) to_chat(overmind,"A factory blob that you had created has been destroyed. (JUMP)") overmind.special_blobs -= src @@ -112,9 +112,10 @@ return 1 return ..() -/mob/living/simple_animal/hostile/blobspore/Die() +/mob/living/simple_animal/hostile/blobspore/death(var/gibbed = FALSE) + ..(TRUE) //Gibs regardless var/sound = pick('sound/effects/gib1.ogg','sound/effects/gib2.ogg','sound/effects/gib3.ogg') - playsound(get_turf(src), sound, 50, 1) + playsound(src, sound, 50, 1) qdel(src) /mob/living/simple_animal/hostile/blobspore/Destroy() diff --git a/code/game/gamemodes/blob/overmind.dm b/code/game/gamemodes/blob/overmind.dm index 780515aca8b..974d17c3db7 100644 --- a/code/game/gamemodes/blob/overmind.dm +++ b/code/game/gamemodes/blob/overmind.dm @@ -11,7 +11,7 @@ pass_flags = PASSBLOB faction = "blob" - plane = BASE_PLANE + plane = ABOVE_LIGHTING_PLANE var/obj/effect/blob/core/blob_core = null // The blob overmind's core var/blob_points = 0 diff --git a/code/game/gamemodes/blob/theblob.dm b/code/game/gamemodes/blob/theblob.dm index adf96e74f29..064ca307d47 100644 --- a/code/game/gamemodes/blob/theblob.dm +++ b/code/game/gamemodes/blob/theblob.dm @@ -218,14 +218,14 @@ var/list/blob_overminds = list() /obj/effect/blob/attackby(var/obj/item/weapon/W, var/mob/living/user) user.do_attack_animation(src, W) user.delayNextAttack(10) - playsound(get_turf(src), 'sound/effects/attackblob.ogg', 50, 1) + playsound(src, 'sound/effects/attackblob.ogg', 50, 1) src.visible_message("The [src.name] has been attacked with \the [W][(user ? " by [user]." : ".")]") var/damage = 0 switch(W.damtype) if("fire") damage = (W.force / max(src.fire_resist,1)) if(istype(W, /obj/item/weapon/weldingtool) || istype(W, /obj/item/weapon/pickaxe/plasmacutter)) - playsound(get_turf(src), 'sound/effects/blobweld.ogg', 100, 1) + playsound(src, 'sound/effects/blobweld.ogg', 100, 1) if("brute") damage = (W.force / max(src.brute_resist,1)) diff --git a/code/game/gamemodes/changeling/changeling_powers.dm b/code/game/gamemodes/changeling/changeling_powers.dm index 5f8261d6079..b838a02f238 100644 --- a/code/game/gamemodes/changeling/changeling_powers.dm +++ b/code/game/gamemodes/changeling/changeling_powers.dm @@ -154,7 +154,7 @@ to_chat(usr, "We must be in human form before activating Horror Form.") return - var/datum/role/changeling/changeling = changeling_power(0,0,100) + var/datum/role/changeling/changeling = changeling_power(30, 0, 100, deny_horror = TRUE) if(!changeling) return @@ -163,6 +163,12 @@ for(var/obj/item/slot in H.get_all_slots()) u_equip(slot, 1) + H.maxHealth = 800 /* Gonna need more than one egun to kill one of these bad boys*/ + H.health = 800 + H.set_species("Horror") + H.client.verbs |= H.species.abilities // Force ability equip. + H.update_icons() + monkeyizing = 1 canmove = 0 delayNextAttack(50) @@ -185,11 +191,6 @@ delayNextAttack(0) icon = null invisibility = initial(invisibility) - H.maxHealth = 800 /* Gonna need more than one egun to kill one of these bad boys*/ - H.health = 800 - H.set_species("Horror") - H.client.verbs |= H.species.abilities // Force ability equip. - H.update_icons() //removes our changeling verbs /mob/proc/remove_changeling_powers() @@ -300,12 +301,12 @@ if(2) to_chat(src, "We extend a proboscis.") src.visible_message("[src] extends a proboscis!") - playsound(get_turf(src), 'sound/effects/lingextends.ogg', 50, 1) + playsound(src, 'sound/effects/lingextends.ogg', 50, 1) if(3) to_chat(src, "We stab [T] with the proboscis.") src.visible_message("[src] stabs [T] with the proboscis!") to_chat(T, "You feel a sharp stabbing pain!") - playsound(get_turf(src), 'sound/effects/lingstabs.ogg', 50, 1) + playsound(src, 'sound/effects/lingstabs.ogg', 50, 1) var/datum/organ/external/affecting = T.get_organ(src.zone_sel.selecting) if(affecting.take_damage(39,0,1,"large organic needle")) T:UpdateDamageIcon(1) @@ -320,7 +321,7 @@ to_chat(src, "We have absorbed [T]!") src.visible_message("[src] sucks the fluids from [T]!") to_chat(T, "You have been absorbed by the changeling!") - playsound(get_turf(src), 'sound/effects/lingabsorbs.ogg', 50, 1) + playsound(src, 'sound/effects/lingabsorbs.ogg', 50, 1) add_attacklogs(src, T, "absorbed") T.dna.real_name = T.real_name //Set this again, just to be sure that it's properly set. diff --git a/code/game/gamemodes/changeling/horror.dm b/code/game/gamemodes/changeling/horror.dm index 22c08a8de2c..6a6e96b19d0 100644 --- a/code/game/gamemodes/changeling/horror.dm +++ b/code/game/gamemodes/changeling/horror.dm @@ -12,7 +12,7 @@ // Yep. default_mutations=list(M_HULK) - cold_level_1 = 0 //Default 260 - Lower is better + cold_level_1 = 0 //Default 220 - Lower is better cold_level_2 = 10 //Default 200 cold_level_3 = 20 //Default 120 diff --git a/code/game/gamemodes/cult/cult.dm b/code/game/gamemodes/cult/cult.dm index a50308a4a9b..2b47c4c1763 100644 --- a/code/game/gamemodes/cult/cult.dm +++ b/code/game/gamemodes/cult/cult.dm @@ -4,6 +4,14 @@ var/list/datum/mind/cult = list() var/list/allwords = list("travel","self","see","hell","blood","join","tech","destroy", "other", "hide") +/proc/talisman_charges(var/imbue) + switch(imbue) + if("communicate") + return 5 + if("supply") + return 5 + else // Tele talisman's imbue is the final word. + return 1 /proc/iscultist(mob/living/M as mob) return istype(M) && M.mind && ticker && ticker.mode && (M.mind in ticker.mode.cult) diff --git a/code/game/gamemodes/cult/cult_items.dm b/code/game/gamemodes/cult/cult_items.dm index babce905111..85866e24dd7 100644 --- a/code/game/gamemodes/cult/cult_items.dm +++ b/code/game/gamemodes/cult/cult_items.dm @@ -96,11 +96,12 @@ /obj/item/clothing/head/helmet/space/cult name = "cult helmet" - desc = "A space worthy helmet used by the followers of Nar-Sie" + desc = "A space worthy helmet used by the followers of Nar-Sie." icon_state = "cult_helmet" item_state = "cult_helmet" armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 30, bio = 30, rad = 30) siemens_coefficient = 0 + species_restricted = null //So dionas can wear it, mainly. /obj/item/clothing/suit/space/cult name = "cult armor" @@ -112,3 +113,4 @@ slowdown = NO_SLOWDOWN armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 30, bio = 30, rad = 30) siemens_coefficient = 0 + species_restricted = null diff --git a/code/game/gamemodes/cult/cult_structures.dm b/code/game/gamemodes/cult/cult_structures.dm index bf84246ef7d..ab51c287c8b 100644 --- a/code/game/gamemodes/cult/cult_structures.dm +++ b/code/game/gamemodes/cult/cult_structures.dm @@ -64,16 +64,16 @@ if(M == user) continue M.show_message("[user.name] smashed the pylon!", 1, "You hear a tinkle of crystal shards.", 2) - playsound(get_turf(src), 'sound/effects/Glassbr3.ogg', 75, 1) + playsound(src, 'sound/effects/Glassbr3.ogg', 75, 1) isbroken = 1 setDensity(FALSE) icon_state = "pylon-broken" set_light(0) else to_chat(user, "You hit the pylon!") - playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 75, 1) + playsound(src, 'sound/effects/Glasshit.ogg', 75, 1) else - playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 75, 1) + playsound(src, 'sound/effects/Glasshit.ogg', 75, 1) if(prob(damage * 2)) to_chat(user, "You pulverize what was left of the pylon!") qdel(src) diff --git a/code/game/gamemodes/cult/hell_universe.dm b/code/game/gamemodes/cult/hell_universe.dm index 2bc40e606f3..632c2963713 100644 --- a/code/game/gamemodes/cult/hell_universe.dm +++ b/code/game/gamemodes/cult/hell_universe.dm @@ -124,7 +124,8 @@ In short: /datum/universal_state/hell/proc/APCSet() for (var/obj/machinery/power/apc/APC in power_machines) - if (!(APC.stat & BROKEN) && !istype(APC.areaMaster,/area/turret_protected/ai)) + var/area/APC_area = get_area(APC) + if (!(APC.stat & BROKEN) && !istype(APC_area, /area/turret_protected/ai)) APC.chargemode = 0 if(APC.cell) APC.cell.charge = 0 @@ -135,7 +136,7 @@ In short: /datum/universal_state/hell/proc/KillMobs() for(var/mob/living/simple_animal/M in mob_list) if(M && !M.client) - M.Die() + M.death() CHECK_TICK /datum/universal_state/hell/proc/convert_all_parallax() diff --git a/code/game/gamemodes/cult/ritual.dm b/code/game/gamemodes/cult/ritual.dm index 6fdfe5f1902..4d70c4b6958 100644 --- a/code/game/gamemodes/cult/ritual.dm +++ b/code/game/gamemodes/cult/ritual.dm @@ -435,42 +435,10 @@ var/global/list/rune_list = list() // HOLY FUCK WHY ARE WE LOOPING THROUGH THE W if(usr.get_active_hand() != src) return - if(ishuman(user)) - var/mob/living/carbon/human/H = user - if(!H.held_items.len) - to_chat(user, "You have no hands to draw with!") - return - if(H.species.anatomy_flags & NO_BLOOD) //No blood, going to have to improvise - if(H.bloody_hands) //Blood on hand to use, and hands on hand to use - user.visible_message("[user] starts to paint drawings on the floor with the blood on their hands, whilst chanting.",\ - "You use the blood smeared on your hands to begin drawing a rune on the floor whilst chanting the ritual that binds your life essence with the dark arcane energies flowing through the surrounding world.",\ - "You hear chanting.") - H.bloody_hands = max(0, H.bloody_hands - 1) - else //We'll have to search around for blood - var/turf/T = get_turf(user) - var/found = 0 - for (var/obj/effect/decal/cleanable/blood/B in T) - if(B.amount && B.counts_as_blood) - user.visible_message("[user] paws at the blood puddles splattered on \the [T], and begins to chant and paint symbols on the floor.",\ - "You use the blood splattered across \the [T], and begin drawing a rune on the floor whilst chanting the ritual that binds your life essence with the dark arcane energies flowing through the surrounding world.",\ - "You hear chanting.") - B.amount-- - found = 1 - break - if(!found) - to_chat(user, "You have no blood in, on, or around you that you can use to draw a rune!") - return - else - user.visible_message("[user] slices open a finger and begins to chant and paint symbols on the floor.",\ - "You slice open one of your fingers and begin drawing a rune on the floor whilst chanting the ritual that binds your life essence with the dark arcane energies flowing through the surrounding world.",\ - "You hear chanting.") - H.vessel.remove_reagent(BLOOD, rand(9)+2) - user.take_overall_damage((rand(9)+1)/10) // 0.1 to 1.0 damage - else //Monkeys, diona, let's just assume it's normal apefoolery - user.visible_message("[user] slices open a finger and begins to chant and paint symbols on the floor.",\ - "You slice open one of your fingers and begin drawing a rune on the floor whilst chanting the ritual that binds your life essence with the dark arcane energies flowing through the surrounding world.",\ - "You hear chanting.") - user.take_overall_damage((rand(9)+1)/10) // 0.1 to 1.0 damage + for (var/mob/V in viewers(src)) + V.show_message("[user] slices open a finger and begins to chant and paint symbols on the floor.", 1, "You hear chanting.", 2) + to_chat(user, "You slice open one of your fingers and begin drawing a rune on the floor whilst chanting the ritual that binds your life essence with the dark arcane energies flowing through the surrounding world.") + user.take_overall_damage((rand(9)+1)/10) // 0.1 to 1.0 damage if(do_after(user, user.loc, 50)) if(usr.get_active_hand() != src) return diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm index 9f05ec5ac8c..95759098e6a 100644 --- a/code/game/gamemodes/cult/runes.dm +++ b/code/game/gamemodes/cult/runes.dm @@ -465,7 +465,7 @@ usr.seer = 1 return usr.say("Rash'tla sektath mal[pick("'","`")]zua. Zasan therium vivira. Itonis al'ra matum!") - usr.show_message("\The markings pulse with a small burst of light, then fall dark.", 1, "You hear a faint fizzle.", 2) + usr.show_message("The markings pulse with a small burst of light, then fall dark.", 1, "You hear a faint fizzle.", 2) to_chat(usr, "You remembered the words correctly, but the rune isn't reacting. Maybe you should position yourself differently.") /////////////////////////////////////////EIGHTH RUNE @@ -487,8 +487,8 @@ M.ghostize(1) //kick them out of their body break if(!corpse_to_raise) - if (ticker.rune_controller.revive_counter) - to_chat(usr, "Enough lifeforce haunts this place to return [ticker.rune_controller.revive_counter] of ours to the mortal plane.") + if (cult_round && cult_round.revivecounter) + to_chat(usr, "Enough lifeforce haunts this place to return [cult_round.revivecounter] of ours to the mortal plane.") if(is_sacrifice_target) to_chat(usr, "The Geometer of blood wants this mortal for himself.") return fizzle() @@ -512,7 +512,7 @@ body_to_sacrifice = N break find_sacrifice - if(!body_to_sacrifice && !ticker.rune_controller.revive_counter) + if(!body_to_sacrifice && (!cult_round || !cult_round.revivecounter)) if (is_sacrifice_target) to_chat(usr, "The Geometer of blood wants that corpse for himself.") else @@ -779,6 +779,7 @@ imbued_from = R break if (imbued_from) + T.uses = talisman_charges(T.imbue) for (var/mob/V in viewers(src)) V.show_message("The runes turn into dust, which then forms into an arcane image on the paper.", 1) usr.say("H'drak v[pick("'","`")]loso, mir'kanas verbot!") @@ -891,7 +892,8 @@ if(M.mind) //living players ritualresponse += "The Geometer of Blood gladly accepts this sacrifice." satisfaction = 100 - R.revive_counter ++ + if(cult_round) + cult_round.revivecounter += 1 else //living NPCs ritualresponse += "The Geometer of Blood accepts this being in sacrifice. Somehow you get the feeling that beings with souls would make a better offering." satisfaction = 50 @@ -904,7 +906,8 @@ if(M.mind) //dead players ritualresponse += "The Geometer of Blood accepts this sacrifice." satisfaction = 50 - R.revive_counter ++ + if(cult_round) + cult_round.revivecounter += 1 else //dead NPCs ritualresponse += "The Geometer of Blood accepts your meager sacrifice." satisfaction = 10 @@ -1133,8 +1136,9 @@ var/obj/machinery/dna_scannernew/dna_scannernew = cultist.loc if (dna_scannernew.locked) dna_scannernew.locked = 0 + var/rune_damage = 20 / (users.len) for(var/mob/living/carbon/C in users) - user.take_overall_damage(10, 0) + C.take_overall_damage(rune_damage, 0) C.say("Khari[pick("'","`")]d! Gual'te nikka!") to_chat(cultist, "You feel a tingle as you find yourself freed from your restraints.") qdel(src) @@ -1162,7 +1166,19 @@ if(iscultist(C) && !C.stat) users+=C if(users.len>=2) - var/mob/living/carbon/cultist = input("Choose the one who you want to summon", "Followers of Geometer") as null|anything in (cultists - user) + cultists-=users + var/list/mob/living/carbon/annotated_cultists = new + var/status = "" + var/list/visible_mobs = viewers(user) + for(var/mob/living/carbon/C in cultists) + status = "" + if(C in visible_mobs) + status = "(Present)" + else if(C.isDead()) + status = "(Dead)" + annotated_cultists["[C.name] [status]"] = C + var/choice = input("Choose the one who you want to summon", "Followers of Geometer") as null|anything in annotated_cultists + var/mob/living/carbon/cultist = annotated_cultists[choice] if(!cultist) return fizzle() if (cultist == user) //just to be sure. @@ -1176,10 +1192,11 @@ cultist.lying = 1 cultist.regenerate_icons() to_chat(T, visible_message("[cultist] suddenly disappears in a flash of red light!")) + var/rune_damage = 30 / (users.len) for(var/mob/living/carbon/human/C in orange(1,src)) if(iscultist(C) && !C.stat) C.say("N'ath reth sh'yro eth d[pick("'","`")]rekkathnor!") - C.take_overall_damage(15, 0) + C.take_overall_damage(rune_damage, 0) if(C != cultist) to_chat(C, "Your body take its toll as you drag your fellow cultist through dimensions.") else diff --git a/code/game/gamemodes/cult/talisman.dm b/code/game/gamemodes/cult/talisman.dm index 9c2ea483935..d3a94e42ab6 100644 --- a/code/game/gamemodes/cult/talisman.dm +++ b/code/game/gamemodes/cult/talisman.dm @@ -1,7 +1,7 @@ /obj/item/weapon/paper/talisman icon_state = "paper_talisman" var/imbue = null - var/uses = 0 + var/uses = 1 var/nullblock = 0 /obj/item/weapon/paper/talisman/update_icon() @@ -43,6 +43,7 @@ to_chat(user, "This talisman has been imbued with the power of providing you and your allies with some supplies to start your cult.") else to_chat(user, "This talisman.....has no particular power. Is this some kind of joke?") + to_chat(user, "Uses left: [src.uses]") else to_chat(user, "Something about the blood stains on this paper fills you with uneasiness.") @@ -65,11 +66,12 @@ /obj/item/weapon/paper/talisman/attack_self(mob/living/user as mob) if(iscultist(user)) - var/delete = 1 + var/use_charge = 1 switch(imbue) if("newtome") call(/obj/effect/rune/proc/tomesummon)() if("armor") //Fuck off with your shit /tg/. This isn't Edgy Rev+ + user.drop_from_inventory(src) //So that the blade goes straight to your active hand. call(/obj/effect/rune/proc/armor)() if("emp") call(/obj/effect/rune/proc/emp)(usr.loc,3) @@ -85,7 +87,7 @@ T1.turf_animation('icons/effects/effects.dmi',"rune_teleport") if("communicate") //If the user cancels the talisman this var will be set to 0 - delete = call(/obj/effect/rune/proc/communicate)() + use_charge = call(/obj/effect/rune/proc/communicate)() if("deafen") deafen() qdel(src) @@ -99,7 +101,9 @@ supply() user.take_organ_damage(5, 0) if(src && src.imbue!="supply" && src.imbue!="runestun") - if(delete) + if(use_charge) + uses-- + if(!src.uses) qdel(src) return else @@ -150,33 +154,37 @@ return if (href_list["rune"]) + var/obj/item/weapon/paper/talisman/T switch(href_list["rune"]) if("newtome") - var/obj/item/weapon/paper/talisman/T = new /obj/item/weapon/paper/talisman(get_turf(usr)) + T = new /obj/item/weapon/paper/talisman(get_turf(usr)) T.imbue = "newtome" if("teleport") - var/obj/item/weapon/paper/talisman/T = new /obj/item/weapon/paper/talisman(get_turf(usr)) + T = new /obj/item/weapon/paper/talisman(get_turf(usr)) var/list/words = list("ire" = "ire", "ego" = "ego", "nahlizet" = "nahlizet", "certum" = "certum", "veri" = "veri", "jatkaa" = "jatkaa", "balaq" = "balaq", "mgar" = "mgar", "karazet" = "karazet", "geeri" = "geeri") T.imbue = input("Write your teleport destination rune:", "Rune Scribing") in words if("emp") - var/obj/item/weapon/paper/talisman/T = new /obj/item/weapon/paper/talisman(get_turf(usr)) + T = new /obj/item/weapon/paper/talisman(get_turf(usr)) T.imbue = "emp" if("conceal") - var/obj/item/weapon/paper/talisman/T = new /obj/item/weapon/paper/talisman(get_turf(usr)) + T = new /obj/item/weapon/paper/talisman(get_turf(usr)) T.imbue = "conceal" if("communicate") - var/obj/item/weapon/paper/talisman/T = new /obj/item/weapon/paper/talisman(get_turf(usr)) + T = new /obj/item/weapon/paper/talisman(get_turf(usr)) T.imbue = "communicate" if("runestun") - var/obj/item/weapon/paper/talisman/T = new /obj/item/weapon/paper/talisman(get_turf(usr)) + T = new /obj/item/weapon/paper/talisman(get_turf(usr)) T.imbue = "runestun" //if("armor") - //var/obj/item/weapon/paper/talisman/T = new /obj/item/weapon/paper/talisman(get_turf(usr)) + //T = new /obj/item/weapon/paper/talisman(get_turf(usr)) //T.imbue = "armor" if("soulstone") new /obj/item/device/soulstone(get_turf(usr)) if("construct") new /obj/structure/constructshell/cult(get_turf(usr)) + + if(T) + T.uses = talisman_charges(T.imbue) src.uses-- supply() return diff --git a/code/game/gamemodes/endgame/endgame.dm b/code/game/gamemodes/endgame/endgame.dm index 376522e7545..60de92fec86 100644 --- a/code/game/gamemodes/endgame/endgame.dm +++ b/code/game/gamemodes/endgame/endgame.dm @@ -63,10 +63,10 @@ /datum/universal_state/proc/OverlayAndAmbientSet() return -/proc/SetUniversalState(var/newstate, var/on_exit = 1, var/on_enter = 1) +/proc/SetUniversalState(var/newstate, var/on_exit = 1, var/on_enter = 1, var/list/given_args) if(on_exit) universe.OnExit() - universe = new newstate + universe = new newstate(given_args) if(on_enter) universe.OnEnter() diff --git a/code/game/gamemodes/endgame/halloween/halloween.dm b/code/game/gamemodes/endgame/halloween/halloween.dm index 2bf167f31c4..46a24106494 100644 --- a/code/game/gamemodes/endgame/halloween/halloween.dm +++ b/code/game/gamemodes/endgame/halloween/halloween.dm @@ -8,9 +8,14 @@ /datum/universal_state/halloween name = "All Hallows Eve" desc = "Double, double toil and Trouble. Fire burn and Cauldron bubble." - + var/mob_amount = 10 decay_rate = 0 +/datum/universal_state/halloween/New(var/list/given_args = list()) + ..() + if(given_args["mobs"]) + mob_amount = given_args["mobs"] + /datum/universal_state/halloween/OnShuttleCall(var/mob/user) return 1 @@ -52,7 +57,7 @@ /datum/universal_state/halloween/proc/AreaSet() for(var/area/A in areas) - if(!istype(A,/area) || isspace(A)) + if(!istype(A,/area) || isspace(A) || istype(A,/area/chapel)) continue // No cheating~ @@ -66,6 +71,20 @@ A.party = null A.radalert = 0 A.updateicon() + if(!A.area_turfs.len) + continue + var/list/available_turfs = A.area_turfs.Copy() + var/turf/test_turf = available_turfs[1] + if(test_turf.z != STATION_Z) + continue + for(var/i=1 to mob_amount) + if(!available_turfs.len) + break + var/turf/T = pick(available_turfs) + if(T.holy || T.z != STATION_Z || !istype(T, /turf/simulated/floor) || T.has_dense_content()) + available_turfs.Remove(T) + continue + new /obj/effect/gravestone/halloween(T) CHECK_TICK @@ -75,8 +94,6 @@ if(istype(T, /turf/space)) T.overlays += image(icon = T.icon, icon_state = "hell01") else - if(!T.holy && prob(5) && T.z == STATION_Z && istype(T, /turf/simulated/floor)) - new /obj/effect/gravestone/halloween(T) T.underlays += "hell01" CHECK_TICK @@ -95,7 +112,8 @@ /datum/universal_state/halloween/proc/APCSet() for (var/obj/machinery/power/apc/APC in power_machines) - if (!(APC.stat & BROKEN) && !(istype(APC.areaMaster,/area/turret_protected/ai) || istype(APC.areaMaster, /area/engineering/engine))) + var/area/APC_area = get_area(APC) + if (!(APC.stat & BROKEN) && !(istype(APC_area, /area/turret_protected/ai) || istype(APC_area, /area/engineering/engine))) APC.chargemode = 0 if(APC.cell) APC.cell.charge = 0 diff --git a/code/game/gamemodes/endgame/supermatter_cascade/universe.dm b/code/game/gamemodes/endgame/supermatter_cascade/universe.dm index b1b1c494abe..f1c280b8e96 100644 --- a/code/game/gamemodes/endgame/supermatter_cascade/universe.dm +++ b/code/game/gamemodes/endgame/supermatter_cascade/universe.dm @@ -106,7 +106,7 @@ /datum/universal_state/supermatter_cascade/proc/AreaSet() for(var/area/ca in areas) - var/area/A=get_area_master(ca) + var/area/A=get_area(ca) if(!istype(A,/area) || isspace(A) || istype(A,/area/beach)) continue diff --git a/code/game/gamemodes/endgame/xmas/snow.dm b/code/game/gamemodes/endgame/xmas/snow.dm index 563b60714bb..55a84b9e137 100644 --- a/code/game/gamemodes/endgame/xmas/snow.dm +++ b/code/game/gamemodes/endgame/xmas/snow.dm @@ -77,13 +77,13 @@ var/list/snowsound = list('sound/misc/snow1.ogg', 'sound/misc/snow2.ogg', 'sound /obj/structure/snow/Crossed(mob/user) ..() if(isliving(user) && !user.locked_to && !user.lying && !user.flying) - playsound(get_turf(src), pick(snowsound), 10, 1, -1, channel = 123) + playsound(src, pick(snowsound), 10, 1, -1, channel = 123) /obj/structure/snow/attack_hand(mob/user) if(snow_amount != SNOWCOVERING_FULL) return - playsound(get_turf(src), "rustle", 50, 1) + playsound(src, "rustle", 50, 1) to_chat(user, "You start digging the snow with your hands.") if(do_after(user, src, 30)) snow_amount = SNOWCOVERING_MEDIUM diff --git a/code/game/gamemodes/events/dust.dm b/code/game/gamemodes/events/dust.dm index 92ce0844105..6bb6b9e203c 100644 --- a/code/game/gamemodes/events/dust.dm +++ b/code/game/gamemodes/events/dust.dm @@ -96,7 +96,7 @@ The "dust" will damage the hull of the station causin minor hull breaches. if(!M.stat && !istype(M, /mob/living/silicon/ai)) shake_camera(M, 3, 1) if (A) - playsound(get_turf(src), 'sound/effects/meteorimpact.ogg', 40, 1) + playsound(src, 'sound/effects/meteorimpact.ogg', 40, 1) if(ismob(A)) A.ex_act(strength) diff --git a/code/game/gamemodes/events/holidays/Holidays.dm b/code/game/gamemodes/events/holidays/Holidays.dm index 73e3a2747b0..0d2bfa90897 100644 --- a/code/game/gamemodes/events/holidays/Holidays.dm +++ b/code/game/gamemodes/events/holidays/Holidays.dm @@ -28,136 +28,136 @@ var/global/Holiday = null if(1) // Jan switch(DD) if(1) - Holiday = "New Year's Day" + Holiday = NEW_YEARS_DAY if(2) // Feb switch(DD) if(2) - Holiday = "Groundhog Day" + Holiday = GROUNDHOG_DAY if(14) - Holiday = "Valentine's Day" + Holiday = VALENTINES_DAY if(17) - Holiday = "Random Acts of Kindness Day" + Holiday = RANDOM_ACTS_OF_KINDNESS_DAY if(3) // Mar switch(DD) if(14) - Holiday = "Pi Day" + Holiday = PI_DAY if(17) - Holiday = "St. Patrick's Day" + Holiday = ST_PATRICKS_DAY if(27) if(YY == 16) - Holiday = "Easter" + Holiday = EASTER if(31) if(YY == 13) - Holiday = "Easter" + Holiday = EASTER if(4) // Apr switch(DD) if(1) - Holiday = "April Fool's Day" + Holiday = APRIL_FOOLS_DAY if(YY == 18 && prob(50)) - Holiday = "Easter" + Holiday = EASTER if(2) - Holiday = "Autism Awareness Day" + Holiday = AUTISM_AWARENESS_DAY if(5) if(YY == 15) - Holiday = "Easter" + Holiday = EASTER if(16) if(YY == 17) - Holiday = "Easter" + Holiday = EASTER if(20) - Holiday = "Four-Twenty" + Holiday = FOUR_TWENTY if(YY == 14 && prob(50)) - Holiday = "Easter" + Holiday = EASTER if(22) - Holiday = "Earth Day" + Holiday = EARTH_DAY if(5) // May switch(DD) if(1) - Holiday = "Labour Day" + Holiday = LABOUR_DAY if(4) - Holiday = "FireFighter's Day" + Holiday = FIREFIGHTERS_DAY if(12) - Holiday = "Owl and Pussycat Day" // what a dumb day of observence...but we -do- have costumes already :3 + Holiday = OWL_AND_PUSSYCAT_DAY // what a dumb day of observence...but we -do- have costumes already :3 if(6) // Jun switch(DD) if(18) - Holiday = "International Picnic Day" + Holiday = INTERNATIONAL_PICNIC_DAY if(21) - Holiday = "Summer Solstice" // its not always the 21 but sue me + Holiday = SUMMER_SOLSTICE // its not always the 21 but sue me if(7) // Jul switch(DD) if(1) - Holiday = "Doctor's Day" + Holiday = DOCTORS_DAY if(2) - Holiday = "UFO Day" + Holiday = UFO_DAY if(8) - Holiday = "Writer's Day" + Holiday = WRITERS_DAY if(30) - Holiday = "Friendship Day" + Holiday = FRIENDSHIP_DAY if(8) // Aug switch(DD) if(5) - Holiday = "Beer Day" + Holiday = BEER_DAY if(9) // sep switch(DD) if(19) - Holiday = "Talk-Like-a-Pirate Day" + Holiday = TALK_LIKE_A_PIRATE_DAY if(28) - Holiday = "Stupid-Questions Day" + Holiday = STUPID_QUESTIONS_DAY if(10) // Oct switch(DD) if(4) - Holiday = "Animal's Day" + Holiday = ANIMALS_DAY if(7) - Holiday = "Smiling Day" + Holiday = SMILING_DAY if(16) - Holiday = "Boss' Day" + Holiday = BOSS_DAY if(31) - Holiday = "Halloween" + Holiday = HALLOWEEN if(11) // Nov switch(DD) if(1) - Holiday = "Vegan Day" + Holiday = VEGAN_DAY if(13) - Holiday = "Kindness Day" + Holiday = KINDNESS_DAY if(19) - Holiday = "Flowers Day" + Holiday = FLOWERS_DAY if(21) - Holiday = "Saying-'Hello' Day" + Holiday = SAYING_HELLO_DAY if(12) // Dec switch(DD) if(10) - Holiday = "Human-Rights Day" + Holiday = HUMAN_RIGHTS_DAY if(14) - Holiday = "Monkey Day" + Holiday = MONKEY_DAY if(21) if(YY==12) - Holiday = "End of the World" + Holiday = END_OF_THE_WORLD if(22) - Holiday = "Orgasming Day" //lol. These all actually exist + Holiday = ORGASMING_DAY //lol. These all actually exist if(24) - Holiday = "Christmas Eve" + Holiday = XMAS_EVE if(25) - Holiday = "Christmas" + Holiday = XMAS if(26) - Holiday = "Boxing Day" + Holiday = BOXING_DAY if(31) - Holiday = "New Year's Eve" + Holiday = NEW_YEARS_EVE if(!Holiday) // Friday the 13th if(DD == 13) if(time2text(world.timeofday, "DDD") == "Fri") - Holiday = "Friday the 13th" + Holiday = FRIDAY_THE_13TH //Allows GA and GM to set the Holiday variable /client/proc/Set_Holiday(T as text|null) @@ -183,17 +183,9 @@ var/global/Holiday = null /proc/Holiday_Game_Start() if(Holiday) to_chat(world, "and...") - if(Holiday == "Autism Awareness Day") - to_chat(world, "

Happy Autism Awareness Day Everybody!

")// Together we can finish the puzzle. - - else - to_chat(world, "

Happy [Holiday] Everybody!

") - switch(Holiday) // special holidays - if("Easter") - //do easter stuff - if("Christmas Eve","Christmas") - Christmas_Game_Start() - return + to_chat(world, "

Happy [Holiday] Everybody!

") + if(Holiday == XMAS_EVE || Holiday == XMAS) + Christmas_Game_Start() // Nested in the random events loop. Will be triggered every 2 minutes /proc/Holiday_Random_Event() @@ -201,33 +193,10 @@ var/global/Holiday = null if("",null) // no Holiday today! Back to work! return - if("Easter") // I'll make this into some helper procs at some point - -/* var/list/turf/simulated/floor/Floorlist = list() - for(var/turf/simulated/floor/T) - if(T.contents) - Floorlist += T - var/turf/simulated/floor/F = Floorlist[rand(1,Floorlist.len)] - Floorlist = null - var/obj/structure/closet/C = locate(/obj/structure/closet) in F - var/obj/item/weapon/reagent_containers/food/snacks/chocolateegg/wrapped/Egg - if( C ) - Egg = new(C) - else - Egg = new(F) - - var/list/obj/containers = list() - for(var/obj/item/weapon/storage/S in world) - if(S.z != map.zMainStation) - continue - containers += S - - message_admins("DEBUG: Event: Egg spawned at [Egg.loc] ([Egg.x],[Egg.y],[Egg.z])")*/ - - if("End of the World") + if(END_OF_THE_WORLD) //2012 is long gone, not clue why this is still a thing. if(prob(eventchance)) GameOver() - if("Christmas","Christmas Eve") + if(XMAS_EVE,XMAS) if(prob(eventchance)) ChristmasEvent() diff --git a/code/game/gamemodes/gameticker.dm b/code/game/gamemodes/gameticker.dm index b25c2aa87ba..9e03943a69b 100644 --- a/code/game/gamemodes/gameticker.dm +++ b/code/game/gamemodes/gameticker.dm @@ -1,11 +1,5 @@ var/datum/controller/gameticker/ticker -#define GAME_STATE_PREGAME 1 -#define GAME_STATE_SETTING_UP 2 -#define GAME_STATE_PLAYING 3 -#define GAME_STATE_FINISHED 4 - - /datum/controller/gameticker var/remaining_time = 0 var/const/restart_timeout = 600 @@ -23,7 +17,8 @@ var/datum/controller/gameticker/ticker var/Bible_icon_state // icon_state the OFFICIAL chaplain has chosen for his bible var/Bible_item_state // item_state the OFFICIAL chaplain has chosen for his bible var/Bible_name // name of the bible - var/Bible_deity_name = "Space Jesus" + var/Bible_deity_name = "Space Jesus" // Default deity + var/datum/religion/chap_rel // Official religion of chappy var/list/datum/religion/religions = list() // Religion(s) in the game var/random_players = 0 // if set to nonzero, ALL players who latejoin or declare-ready join will have random appearances/genders @@ -66,12 +61,25 @@ var/datum/controller/gameticker/ticker "sound/music/dawsonschristian.ogg", "sound/music/carmenmirandasghost.ogg", )) - login_music = fcopy_rsc(oursong) + + if(SNOW_THEME) + var/path = "sound/music/xmas/" + var/list/filenames = flist(path) + for(var/filename in filenames) + if(copytext(filename, length(filename)) == "/") + filenames -= filename + login_music = file("[path][pick(filenames)]") + else + login_music = fcopy_rsc(oursong) send2maindiscord("**Server is loaded** and in pre-game lobby at `[config.server? "byond://[config.server]" : "byond://[world.address]:[world.port]"]`") do - var/delay_timetotal = 3000 //actually 5 minutes or incase this is changed from 3000, (time_in_seconds * 10) +#ifdef UNIT_TESTS + var/delay_timetotal = 2 SECONDS +#else + var/delay_timetotal = 5 MINUTES +#endif pregame_timeleft = world.timeofday + delay_timetotal to_chat(world, "Welcome to the pre-game lobby!") to_chat(world, "Please, setup your character and select ready. Game will start in [(pregame_timeleft - world.timeofday) / 10] seconds.") @@ -161,8 +169,12 @@ var/datum/controller/gameticker/ticker for (var/datum/gamemode/M in runnable_modes) modes+=M.name modes = sortList(modes) - to_chat(world, "The current game mode is - Secret!") - to_chat(world, "Possibilities: [english_list(modes)]") + if(Holiday == APRIL_FOOLS_DAY) + to_chat(world, "The current game mode is - [pick("Chivalry","Crab Battle","Bay Transfer","Dwarf Fortress","Ian Says","Admins Funhouse","Meteor","Xenoarchaeology Appreciation","Clowns versus [pick("Mimes","Assistants","the Universe")]","Dino wars","Malcolm in the Middle","Six hours of extended where one person with all the access refuses to call the shuttle while everyone else goes braindead","Monkey Study","Nations","Nations by Hasbro","High roleplay Extended","DarkRP","Babies Day out","Ians Day out","Shortstaffed medical")]!") + else + to_chat(world, "The current game mode is - Secret!") + to_chat(world, "Possibilities: [english_list(modes)]") + init_PDAgames_leaderboard() create_characters() //Create player characters and transfer them collect_minds() @@ -177,12 +189,16 @@ var/datum/controller/gameticker/ticker //here to initialize the random events nicely at round start setup_economy() +#ifdef UNIT_TESTS + run_unit_tests() +#endif + spawn(0)//Forking here so we dont have to wait for this to finish mode.PostSetup() //Cleanup some stuff for(var/obj/effect/landmark/start/S in landmarks_list) - //Deleting Startpoints but we need the ai point to AI-ize people later - if (S.name != "AI") + //Deleting Startpoints but we need the ai point to AI-ize people later and the Trader point to throw new ones + if (S.name != "AI" && S.name != "Trader") qdel(S) var/list/obj/effect/landmark/spacepod/random/L = list() for(var/obj/effect/landmark/spacepod/random/SS in landmarks_list) @@ -498,9 +514,9 @@ var/datum/controller/gameticker/ticker end_icons += flat var/tempstate = end_icons.len if(ai.stat != 2) - ai_completions += {"
[ai.name] (Played by: [ai.key])'s laws at the end of the game were:"} + ai_completions += {"
[ai.name] (Played by: [get_key(ai)])'s laws at the end of the game were:"} else - ai_completions += {"
[ai.name] (Played by: [ai.key])'s laws when it was deactivated were:"} + ai_completions += {"
[ai.name] (Played by: [get_key(ai)])'s laws when it was deactivated were:"} ai_completions += "
[ai.write_laws()]" if (ai.connected_robots.len) @@ -508,7 +524,7 @@ var/datum/controller/gameticker/ticker for(var/mob/living/silicon/robot/robo in ai.connected_robots) if (!robo.connected_ai || !isMoMMI(robo)) // Don't report MoMMIs or unslaved robutts continue - robolist += "[robo.name][robo.stat?" (Deactivated) (Played by: [robo.key]), ":" (Played by: [robo.key]), "]" + robolist += "[robo.name][robo.stat?" (Deactivated) (Played by: [get_key(robo)]), ":" (Played by: [get_key(robo)]), "]" ai_completions += "[robolist]" for (var/mob/living/silicon/robot/robo in mob_list) @@ -519,11 +535,11 @@ var/datum/controller/gameticker/ticker var/tempstate = end_icons.len if (!robo.connected_ai) if (robo.stat != 2) - ai_completions += {"
[robo.name] (Played by: [robo.key]) survived as an AI-less [isMoMMI(robo)?"MoMMI":"borg"]! Its laws were:"} + ai_completions += {"
[robo.name] (Played by: [get_key(robo)]) survived as an AI-less [isMoMMI(robo)?"MoMMI":"borg"]! Its laws were:"} else - ai_completions += {"
[robo.name] (Played by: [robo.key]) was unable to survive the rigors of being a [isMoMMI(robo)?"MoMMI":"cyborg"] without an AI. Its laws were:"} + ai_completions += {"
[robo.name] (Played by: [get_key(robo)]) was unable to survive the rigors of being a [isMoMMI(robo)?"MoMMI":"cyborg"] without an AI. Its laws were:"} else - ai_completions += {"
[robo.name] (Played by: [robo.key]) [robo.stat!=2?"survived":"perished"] as a [isMoMMI(robo)?"MoMMI":"cyborg"] slaved to [robo.connected_ai]! Its laws were:"} + ai_completions += {"
[robo.name] (Played by: [get_key(robo)]) [robo.stat!=2?"survived":"perished"] as a [isMoMMI(robo)?"MoMMI":"cyborg"] slaved to [robo.connected_ai]! Its laws were:"} ai_completions += "
[robo.write_laws()]" for(var/mob/living/silicon/pai/pAI in mob_list) @@ -531,7 +547,7 @@ var/datum/controller/gameticker/ticker flat = getFlatIcon(pAI) end_icons += flat var/tempstate = end_icons.len - ai_completions += {"
[pAI.name] (Played by: [pAI.key]) [pAI.stat!=2?"survived":"perished"] as a pAI whose master was [pAI.master]! Its directives were:
[pAI.write_directives()]"} + ai_completions += {"
[pAI.name] (Played by: [get_key(pAI)]) [pAI.stat!=2?"survived":"perished"] as a pAI whose master was [pAI.master]! Its directives were:
[pAI.write_directives()]"} mode.declare_completion()//To declare normal completion. diff --git a/code/game/gamemodes/heist/heist.dm b/code/game/gamemodes/heist/heist.dm index eff2166b9ff..38f2b6b3f33 100644 --- a/code/game/gamemodes/heist/heist.dm +++ b/code/game/gamemodes/heist/heist.dm @@ -134,10 +134,10 @@ if(!is_raider_crew_alive()) return FALSE - var/end_area = get_area_master(locate(/area/shuttle/vox/station)) + var/end_area = get_area(locate(/area/shuttle/vox/station)) for(var/datum/mind/raider in raiders) - if(get_area_master(raider.current) != end_area) + if(get_area(raider.current) != end_area) return FALSE return TRUE @@ -238,7 +238,7 @@ Use :V to voxtalk, :H to talk on your encrypted channel, and don't forget to end_icons += logo var/tempstate = end_icons.len var/text = {"
The vox raiders were: "} - var/end_area = get_area_master(locate(/area/shuttle/vox/station)) + var/end_area = get_area(locate(/area/shuttle/vox/station)) for(var/datum/mind/vox in raiders) @@ -247,7 +247,7 @@ Use :V to voxtalk, :H to talk on your encrypted channel, and don't forget to end_icons += flat tempstate = end_icons.len text += {"
[vox.key] was [vox.name] ("} - if(get_area_master(vox.current) != end_area) // areaMaster var can be used on this if move_contents_to proc refactored to use Move() + if(get_area(vox.current) != end_area) text += "left behind, " if(vox.current.stat != DEAD) diff --git a/code/game/gamemodes/heist/objectives.dm b/code/game/gamemodes/heist/objectives.dm index 5ec3a4709f7..0ba091efd1e 100644 --- a/code/game/gamemodes/heist/objectives.dm +++ b/code/game/gamemodes/heist/objectives.dm @@ -40,9 +40,9 @@ if(isnull(target.current)/* || target.current.stat == DEAD*/) // Removed dead check, we can clone them after we get them back anyway. return FALSE // they're destroyed. fail. - var/end_area = get_area_master(locate(/area/shuttle/vox/station)) + var/end_area = get_area(locate(/area/shuttle/vox/station)) - if(get_area_master(target.current) != end_area) + if(get_area(target.current) != end_area) return FALSE //if(!target.current.restrained()) diff --git a/code/game/gamemodes/heist/tools.dm b/code/game/gamemodes/heist/tools.dm index ccbf615a0a4..18440d13740 100644 --- a/code/game/gamemodes/heist/tools.dm +++ b/code/game/gamemodes/heist/tools.dm @@ -68,7 +68,7 @@ return in_use = TRUE user.visible_message("[user] activates \the [src]!", "You level the extractor at [H] and hold down the trigger.") - playsound(get_turf(src), 'sound/machines/click.ogg', 50, 1) + playsound(src, 'sound/machines/click.ogg', 50, 1) if(do_after(user, src, delay, needhand=TRUE)) if(O && istype(O) && O.CanRemove(H, user, quiet=TRUE)) O.Remove(H, user) @@ -93,7 +93,7 @@ // ???? affected.internal_organs -= OO.organ_data OO.removed(H,user) OO.forceMove(get_turf(H)) - playsound(get_turf(src), 'sound/machines/juicer.ogg', 50, 1) + playsound(src, 'sound/machines/juicer.ogg', 50, 1) in_use = FALSE /obj/item/weapon/organ_remover/proc/can_use(var/mob/user) diff --git a/code/game/gamemodes/meteor/meteors.dm b/code/game/gamemodes/meteor/meteors.dm index 57ca918ba1a..861193eb1e5 100644 --- a/code/game/gamemodes/meteor/meteors.dm +++ b/code/game/gamemodes/meteor/meteors.dm @@ -223,7 +223,7 @@ //Adjusted from flashbangs, should be its own global proc visible_message("BANG") - playsound(get_turf(src), 'sound/effects/bang.ogg', 25, 1) + playsound(src, 'sound/effects/bang.ogg', 25, 1) for(var/mob/living/M in viewers(src, null)) diff --git a/code/game/gamemodes/nuclear/nuclearbomb.dm b/code/game/gamemodes/nuclear/nuclearbomb.dm index 0ec4a3a5d31..8eca52a6608 100644 --- a/code/game/gamemodes/nuclear/nuclearbomb.dm +++ b/code/game/gamemodes/nuclear/nuclearbomb.dm @@ -341,6 +341,9 @@ var/obj/item/weapon/disk/nuclear/nukedisk reset_vars_after_duration(resettable_vars, duration) +/obj/machinery/nuclearbomb/isacidhardened() // Requires Aliens to channel acidspit on the nuke. + return TRUE + /obj/item/weapon/disk/nuclear name = "nuclear authentication disk" desc = "Better keep this safe." diff --git a/code/game/gamemodes/nuclear/pinpointer.dm b/code/game/gamemodes/nuclear/pinpointer.dm index 4730ca246ad..45b66a574be 100644 --- a/code/game/gamemodes/nuclear/pinpointer.dm +++ b/code/game/gamemodes/nuclear/pinpointer.dm @@ -18,7 +18,7 @@ /obj/item/weapon/pinpointer/Destroy() ..() - processing_objects -= src + fast_objects -= src /obj/item/weapon/pinpointer/acidable() return FALSE @@ -28,13 +28,13 @@ active = TRUE workdisk() to_chat(usr,"You activate \the [src]") - playsound(get_turf(src), 'sound/items/healthanalyzer.ogg', 30, 1) - processing_objects += src + playsound(src, 'sound/items/healthanalyzer.ogg', 30, 1) + fast_objects += src else active = FALSE icon_state = "pinoff" to_chat(usr,"You deactivate \the [src]") - processing_objects -= src + fast_objects -= src /obj/item/weapon/pinpointer/proc/workdisk() process() @@ -97,11 +97,11 @@ /obj/item/weapon/pinpointer/advpinpointer/attack_self() if(!active) active = TRUE - processing_objects += src + fast_objects += src process() to_chat(usr,"You activate the pinpointer") else - processing_objects -= src + fast_objects -= src active = FALSE icon_state = "pinoff" to_chat(usr,"You deactivate the pinpointer") @@ -200,12 +200,12 @@ else to_chat(user,"Shuttle Locator active.") process() - processing_objects += src + fast_objects += src else active = FALSE icon_state = "pinoff" to_chat(user,"You deactivate the pinpointer.") - processing_objects -= src + fast_objects -= src /obj/item/weapon/pinpointer/nukeop/process() @@ -247,11 +247,11 @@ if(!active) active = TRUE process() - processing_objects += src + fast_objects += src to_chat(usr,"You activate the pinpointer") else active = FALSE - processing_objects -= src + fast_objects -= src icon_state = "pinoff" to_chat(usr,"You deactivate the pinpointer") diff --git a/code/game/gamemodes/setupgame.dm b/code/game/gamemodes/setupgame.dm index 42a6a7a6fe9..6cd60fbe6e5 100644 --- a/code/game/gamemodes/setupgame.dm +++ b/code/game/gamemodes/setupgame.dm @@ -70,6 +70,8 @@ var/DIZZYBLOCK = 0 var/SANSBLOCK = 0 var/NOIRBLOCK = 0 var/VEGANBLOCK = 0 +var/ASTHMABLOCK = 0 +var/LACTOSEBLOCK = 0 /proc/getAssignedBlock(var/name,var/list/blocksLeft, var/activity_bounds=DNA_DEFAULT_BOUNDS, var/good=0) @@ -178,6 +180,8 @@ var/VEGANBLOCK = 0 SANSBLOCK = getAssignedBlock("SANS", numsToAssign) NOIRBLOCK = getAssignedBlock("NOIR", numsToAssign) VEGANBLOCK = getAssignedBlock("VEGAN", numsToAssign) + ASTHMABLOCK = getAssignedBlock("ASTHMA", numsToAssign) + LACTOSEBLOCK = getAssignedBlock("LACTOSE", numsToAssign) // // Static Blocks @@ -210,7 +214,7 @@ var/VEGANBLOCK = 0 warning("DNA2: Gene [gene.name] trying to add to already assigned gene block list (used by [english_list(assigned_gene_blocks[block])])") assigned_gene_blocks[block] = gene - testing("DNA2: [numsToAssign.len] blocks are unused: [english_list(numsToAssign)]") + //testing("DNA2: [numsToAssign.len] blocks are unused: [english_list(numsToAssign)]") // Run AFTER genetics setup and AFTER species setup. /proc/setup_species() @@ -219,12 +223,12 @@ var/VEGANBLOCK = 0 // I hate BYOND. Can't just call while it's in the list. var/datum/species/species = all_species[name] if(species.default_block_names.len>0) - testing("Setting up genetics for [species.name] (needs [english_list(species.default_block_names)])") +// testing("Setting up genetics for [species.name] (needs [english_list(species.default_block_names)])") species.default_blocks.len = 0 for(var/block=1;block= required_amount diff --git a/code/game/gamemodes/vampire/vampire.dm b/code/game/gamemodes/vampire/vampire.dm index 5534eb98810..159a2e12f50 100644 --- a/code/game/gamemodes/vampire/vampire.dm +++ b/code/game/gamemodes/vampire/vampire.dm @@ -311,6 +311,8 @@ You are weak to holy things and starlight. Don't go into space and avoid the Cha if(!mind.vampire) mind.vampire = new /datum/vampire(gender) mind.vampire.owner = src + mind.vampire.bloodtotal = STARTING_BLOOD + mind.vampire.bloodusable = STARTING_BLOOD callOnLife += list("\ref[mind.vampire]" = "OnLife") verbs += /client/proc/vampire_rejuvinate verbs += /client/proc/vampire_hypnotise diff --git a/code/game/gamemodes/vampire/vampire_powers.dm b/code/game/gamemodes/vampire/vampire_powers.dm index cc1ea07ca5b..b58d8b68c85 100644 --- a/code/game/gamemodes/vampire/vampire_powers.dm +++ b/code/game/gamemodes/vampire/vampire_powers.dm @@ -31,7 +31,8 @@ to_chat(src, "You require at least [required_blood] units of usable blood to do that!") return 0 //chapel check - if(istype(areaMaster, /area/chapel)) + var/area/this_area = get_area(src) + if(istype(this_area, /area/chapel)) if(!fullpower) to_chat(src, "Your powers are useless on this holy ground.") return 0 @@ -165,13 +166,13 @@ /client/proc/vampire_hypnotise() set category = "Vampire" - set name = "Hypnotise" + set name = "Hypnotise (10)" set desc= "A piercing stare that incapacitates your victim for a good length of time." var/datum/mind/M = usr.mind if(!M) return - var/mob/living/carbon/C = M.current.vampire_active(0, 0, 1) + var/mob/living/carbon/C = M.current.vampire_active(10, 0, 1) if(!C) return @@ -185,6 +186,7 @@ M.current.verbs += /client/proc/vampire_hypnotise var/enhancements = ((C.knockdown ? 2 : 0) + (C.stunned ? 1 : 0) + (C.sleeping || C.paralysis ? 3 : 0)) if(do_mob(M.current, C, 10 - enhancements)) + M.current.remove_vampire_blood(10) if(C.mind && C.mind.vampire) to_chat(M.current, "Your piercing gaze fails to knock out [C.name].") to_chat(C, "[M.current.name]'s feeble gaze is ineffective.") @@ -450,6 +452,7 @@ return 0 if(!C.vampire_affected(mind)) C.visible_message("[C] seems to resist the takeover!", "Your faith of [ticker.Bible_deity_name] has kept your mind clear of all evil") + return 0 if(!ishuman(C)) to_chat(src, "You can only enthrall humanoids!") return 0 diff --git a/code/game/gamemodes/wizard/artefact.dm b/code/game/gamemodes/wizard/artefact.dm index cd965cd12d0..f4763d69809 100644 --- a/code/game/gamemodes/wizard/artefact.dm +++ b/code/game/gamemodes/wizard/artefact.dm @@ -183,7 +183,7 @@ if(ismob(loc)) var/mob/M = loc M.drop_from_inventory(src) - playsound(get_turf(src), 'sound/weapons/orb_activate.ogg', 50,1) + playsound(src, 'sound/weapons/orb_activate.ogg', 50,1) flick("glow_stone_activate", src) spawn(10) new/mob/living/simple_animal/hostile/glow_orb(get_turf(src)) @@ -194,7 +194,7 @@ crit_failure = 1 spawn(1 SECONDS) visible_message("The Space Wizard Federation is upset with your performance and have terminated your employment.") - wizard.current.stat = DEAD + wizard.current.death() continue wizards_alive++ diff --git a/code/game/gamemodes/wizard/rightandwrong.dm b/code/game/gamemodes/wizard/rightandwrong.dm index 0a4470347f6..562efb842dc 100644 --- a/code/game/gamemodes/wizard/rightandwrong.dm +++ b/code/game/gamemodes/wizard/rightandwrong.dm @@ -29,7 +29,7 @@ for(var/datum/objective/OBJ in H.mind.objectives) to_chat(H, "Objective #[obj_count]: [OBJ.explanation_text]") obj_count++*/ - var/randomizeguns = pick("taser","stunrevolver","egun","laser","retro","laserak","revolver","detective","smg","nuclear","deagle","gyrojet","pulse","silenced","cannon","doublebarrel","shotgun","combatshotgun","mateba","smg","uzi","crossbow","saw","hecate","osipr","gatling","bison","ricochet","spur","nagant","obrez","beegun","usp","glock","luger","colt","plasmapistol") + var/randomizeguns = pick("taser","stunrevolver","egun","laser","retro","laserak","revolver","detective","smg","nuclear","deagle","gyrojet","pulse","silenced","cannon","doublebarrel","shotgun","combatshotgun","mateba","smg","uzi","crossbow","saw","hecate","osipr","gatling","bison","ricochet","spur","nagant","obrez","beegun","beretta","usp","glock","luger","colt","plasmapistol") var/randomizemagic = pick("fireball","smoke","blind","mindswap","forcewall","knock","horsemask","blink","disorient","staffchange","armor","scrying", "clowncurse", "mimecurse", "shoesnatch", "robesummon") var/randomizeswords = pick("unlucky", "misc", "glass", "throw", "armblade", "pickaxe", "pcutter", "esword", "alt-esword", "machete", "kitchen", "spear", "katana", "axe", "venom", "boot", "saw", "scalpel", "bottle", "switchtool") var/randomizeknightcolor = pick("green", "yellow", "blue", "red", "templar") @@ -105,6 +105,8 @@ new /obj/item/weapon/gun/projectile/nagant/obrez(get_turf(H)) if("beegun") new /obj/item/weapon/gun/gatling/beegun(get_turf(H)) + if("beretta") + new /obj/item/weapon/gun/projectile/beretta(get_turf(H)) if("usp") new /obj/item/weapon/gun/projectile/NTUSP/fancy(get_turf(H)) if("glock") @@ -292,4 +294,4 @@ new /obj/item/weapon/switchtool/surgery(get_turf(H)) else new /obj/item/weapon/switchtool/swiss_army_knife(get_turf(H)) - playsound(get_turf(H),'sound/items/zippo_open.ogg', 50, 1) \ No newline at end of file + playsound(H,'sound/items/zippo_open.ogg', 50, 1) diff --git a/code/game/gamemodes/wizard/soulstone.dm b/code/game/gamemodes/wizard/soulstone.dm index dd0f7d1b396..96b77fc71d7 100644 --- a/code/game/gamemodes/wizard/soulstone.dm +++ b/code/game/gamemodes/wizard/soulstone.dm @@ -13,6 +13,13 @@ /obj/item/device/soulstone/Destroy() eject_shade() ..() + +/obj/item/device/soulstone/examine(mob/user) + ..() + for(var/mob/living/simple_animal/shade/A in src) + if(!A.client) + to_chat(user, "The spirit within seems to be dormant.") + //////////////////////////////Capturing//////////////////////////////////////////////////////// /obj/item/device/soulstone/attack(var/mob/living/M, mob/user as mob) @@ -49,9 +56,6 @@ onclose(user, "aicard") return - - - /obj/item/device/soulstone/Topic(href, href_list) var/mob/living/carbon/U = usr if (!in_range(src, U)||U.machine!=src) @@ -108,7 +112,9 @@ L.forceMove(get_turf(src)) L.status_flags &= ~GODMODE if(user) - to_chat(L, "You have been released from your prison, but you are still bound to [user.name]'s will. Help them suceed in their goals at all costs.") + to_chat(L, "You have been released from your prison, but you are still bound to [user.name]'s will. Help them succeed in their goals at all costs.
\ + Be warned, you are as fragile as glass and your attacks are not terribly strong. On the plus side, you fly and have no need for air.
\ + You also cannot be stunned. If need be, your master can recapture you in the stone to heal you.
") L.canmove = 1 L.cancel_camera() @@ -262,6 +268,11 @@ if(ismob(target)) var/mob/M = target true_name = M.real_name + for(var/obj/item/W in M) + M.drop_from_inventory(W) + if(iscarbon(M)) + var/mob/living/carbon/C = M + C.dropBorers(1) new /obj/effect/decal/cleanable/ash(get_turf(target)) else if(istype(target,/obj/item/organ/external/head)) var/obj/item/organ/external/head/H = target @@ -270,7 +281,7 @@ new /obj/item/weapon/skull(get_turf(target)) //Scary sound - playsound(get_turf(src), get_sfx("soulstone"), 50,1) + playsound(src, get_sfx("soulstone"), 50,1) //Creating a shade inside the stone and putting the victim in control var/mob/living/simple_animal/shade/shadeMob = new(src)//put shade in stone @@ -352,7 +363,7 @@ Z = new /mob/living/simple_animal/construct/armoured (get_turf(T.loc)) Z.key = A.key qdel(T) - to_chat(Z, "You are a Juggernaut. Though slow, your shell can withstand extreme punishment, your body can reflect energy and laser weapons, and you can create temporary shields that blocks pathing and projectiles. You fists can punch people and regular walls appart.") + to_chat(Z, "You are a Juggernaut. Though slow, your shell can withstand extreme punishment, your body can reflect energy and laser weapons, and you can create temporary shields that block pathing and projectiles. Your fists can punch people and regular walls apart.") to_chat(Z, "You are still bound to serve your creator, follow their orders and help them complete their goals at all costs.") Z.cancel_camera() deleteafter = 1 diff --git a/code/game/gamemodes/wizard/spellbook.dm b/code/game/gamemodes/wizard/spellbook.dm index 22629cd1d42..6e398ddd5e6 100644 --- a/code/game/gamemodes/wizard/spellbook.dm +++ b/code/game/gamemodes/wizard/spellbook.dm @@ -692,7 +692,7 @@ B.transfer_buttdentity(C) C.op_stage.butt = 4 to_chat(user, "Your ass just blew up!") - playsound(get_turf(src), 'sound/effects/superfart.ogg', 50, 1) + playsound(src, 'sound/effects/superfart.ogg', 50, 1) C.apply_damage(40, BRUTE, LIMB_GROIN) C.apply_damage(10, BURN, LIMB_GROIN) qdel(src) @@ -849,3 +849,16 @@ to_chat(user, "You shouldn't attempt to steal ancient knowledge!") user.gib() qdel(src) + +///// WINTER SPELLBOOK ///// + +/obj/item/weapon/spellbook/oneuse/ancient/winter //the winter spellbook contains spells that would otherwise only be avaliable at christmas + possible_spells = list(/spell/targeted/wrapping_paper, /spell/targeted/equip_item/clowncurse/christmas, /spell/aoe_turf/conjure/snowmobile, /spell/targeted/equip_item/horsemask/christmas) + icon_state = "winter" + desc = "A book of festive knowledge" + spellname = "winter" + +/obj/item/weapon/spellbook/oneuse/ancient/recoil(mob/living/carbon/user) + to_chat(user, "You shouldn't attempt to steal from santa!") + user.gib() + qdel(src) diff --git a/code/game/gamemodes/wizard/wizard.dm b/code/game/gamemodes/wizard/wizard.dm index 65258129403..9bb10a36ae3 100644 --- a/code/game/gamemodes/wizard/wizard.dm +++ b/code/game/gamemodes/wizard/wizard.dm @@ -9,7 +9,7 @@ name = "wizard" config_tag = "wizard" required_players = 2 - required_players_secret = 20 + required_players_secret = 10 required_enemies = 1 recommended_enemies = 1 rage = 0 @@ -19,16 +19,14 @@ var/finished = 0 - var/const/players_per_wizard = 10 var/const/waittime_l = 600 //lower bound on time before intercept arrives (in tenths of seconds) var/const/waittime_h = 1800 //upper bound on time before intercept arrives (in tenths of seconds) - var/wizard_amount= 1 can_be_mixed = TRUE /datum/game_mode/wizard/announce() to_chat(world, "The current game mode is - Wizard!") - to_chat(world, "There are several SPACE WIZARDS on the station. You can't let them achieve their objectives!") + to_chat(world, "There is a SPACE WIZARD on the station. You can't let him achieve his objective!") /datum/game_mode/wizard/pre_setup() var/list/datum/mind/possible_wizards = get_players_for_role(ROLE_WIZARD) @@ -36,30 +34,29 @@ log_admin("Failed to set-up a round of wizard. Couldn't find any volunteers to be wizards.") message_admins("Failed to set-up a round of wizard. Couldn't find any volunteers to be wizards.") return 0 - - wizard_amount= max(round(num_players()/players_per_wizard, 1), 1) - - for(var/j = 0, j < wizard_amount, j++) - if(!possible_wizards.len) - break - var/datum/mind/wizard = pick(possible_wizards) - possible_wizards -= wizard + var/datum/mind/wizard + while(possible_wizards.len) + wizard = pick(possible_wizards) if(wizard.special_role || (mixed && (wizard in ticker.mode.modePlayer))) - j-- + possible_wizards -= wizard + wizard = null continue - wizards += wizard - modePlayer += wizard - wizard.assigned_role = "MODE" //So they aren't chosen for other jobs. - wizard.special_role = "Wizard" - wizard.original = wizard.current - + else + break + if(isnull(wizard)) + log_admin("COULD NOT MAKE A WIZARD, Mixed mode is [mixed ? "enabled" : "disabled"]") + message_admins("COULD NOT MAKE A WIZARD, Mixed mode is [mixed ? "enabled" : "disabled"]") + return 0 + wizards += wizard + modePlayer += wizard if(mixed) ticker.mode.modePlayer += wizards //merge into master antag list ticker.mode.wizards += wizards - + wizard.assigned_role = "MODE" //So they aren't chosen for other jobs. + wizard.special_role = "Wizard" + wizard.original = wizard.current if(wizardstart.len == 0) - for(var/datum/mind/wwwizard in wizards) - to_chat(wwwizard.current, "A starting location for you could not be found, please report this bug!") + to_chat(wizard.current, "A starting location for you could not be found, please report this bug!") log_admin("Failed to set-up a round of wizard. Couldn't find any wizard spawn points.") message_admins("Failed to set-up a round of wizard. Couldn't find any wizard spawn points.") return 0 @@ -145,7 +142,7 @@ var/wizard_name_second = pick(wizard_second) var/randomname = "[wizard_name_first] [wizard_name_second]" spawn(0) - var/newname = copytext(sanitize(input(wizard_mob, "You are a Space Wizard. Would you like to change your name to something else?", "Name change", randomname) as null|text),1,MAX_NAME_LEN) + var/newname = copytext(sanitize(input(wizard_mob, "You are the Space Wizard. Would you like to change your name to something else?", "Name change", randomname) as null|text),1,MAX_NAME_LEN) if (!newname) newname = randomname @@ -157,7 +154,7 @@ /datum/game_mode/proc/greet_wizard(var/datum/mind/wizard, var/you_are=1) if (you_are) var/wikiroute = role_wiki[ROLE_WIZARD] - to_chat(wizard.current, "You are a Space Wizard! (Wiki Guide)") + to_chat(wizard.current, "You are the Space Wizard! (Wiki Guide)") to_chat(wizard.current, "The Space Wizards Federation has given you the following tasks:") var/obj_count = 1 diff --git a/code/game/jobs/access.dm b/code/game/jobs/access.dm index ae32a8938ac..d88a73feb6d 100644 --- a/code/game/jobs/access.dm +++ b/code/game/jobs/access.dm @@ -512,4 +512,4 @@ proc/FindNameFromID(var/mob/living/carbon/human/H) return ID.registered_name proc/get_all_job_icons() //For all existing HUD icons - return get_all_jobs() + list("Prisoner") + return get_all_jobs() + list("Prisoner", "visitor") diff --git a/code/game/jobs/job/civilian.dm b/code/game/jobs/job/civilian.dm index 1cdccb8fcf3..af3df25c92e 100644 --- a/code/game/jobs/job/civilian.dm +++ b/code/game/jobs/job/civilian.dm @@ -134,6 +134,7 @@ H.equip_or_collect(new /obj/item/clothing/under/rank/botany(H), slot_w_uniform) if("Beekeeper") H.equip_or_collect(new /obj/item/clothing/under/rank/beekeeper(H), slot_w_uniform) + H.equip_or_collect(new /obj/item/queen_bee(H), slot_l_store) if("Gardener") H.equip_or_collect(new /obj/item/clothing/under/rank/gardener(H), slot_w_uniform) @@ -401,7 +402,7 @@ M.remove_spell(spell) for(var/spell/targeted/oathbreak/spell in M.spell_list) M.remove_spell(spell) - message_admins("[M.name] ([M.ckey]) has broken their oath of silence. (JMP)") + message_admins("[M.name] ([M.ckey]) has broken their oath of silence. (JMP)") to_chat(M, "An unsettling feeling surrounds you...") return @@ -508,7 +509,7 @@ spawn_positions = 2 supervisors = "Nanotrasen Law, CentComm Officals, and the station's captain." selection_color = "#dddddd" - access = list(access_lawyer, access_court, access_heads, access_RC_announce, access_sec_doors, access_maint_tunnels, access_cargo, access_medical, access_bar, access_kitchen, access_hydroponics) + access = list(access_lawyer, access_court, access_heads, access_RC_announce, access_sec_doors, access_cargo, access_medical, access_bar, access_kitchen, access_hydroponics) minimal_access = list(access_lawyer, access_court, access_heads, access_RC_announce, access_sec_doors, access_cargo, access_bar, access_kitchen) alt_titles = list("Lawyer", "Bridge Officer") diff --git a/code/game/jobs/job/civilian_chaplain.dm b/code/game/jobs/job/civilian_chaplain.dm index 9ca46f346c2..7b42ab0c331 100644 --- a/code/game/jobs/job/civilian_chaplain.dm +++ b/code/game/jobs/job/civilian_chaplain.dm @@ -107,8 +107,8 @@ while(!accepted) if(!B) break //Prevents possible runtime errors - new_book_style = input(H, "Which bible style would you like?") in list("Bible", "Koran", "Scrapbook", "Creeper", "White Bible", "Holy Light", "Athiest", "[B.name == "clockwork slab" ? "Slab":"Tome"]", "The King in Yellow", "Ithaqua", "Scientology", \ - "the bible melts", "Unaussprechlichen Kulten", "Necronomicon", "Book of Shadows", "Torah", "Burning", "Honk", "Ianism", "The Guide") + new_book_style = input(H, "Which bible style would you like?") in list("Bible", "Koran", "Scrapbook", "Creeper", "White Bible", "Holy Light", "Athiest", "[B.name == "Clockwork slab" ? "Slab":"Tome"]", "The King in Yellow", "Ithaqua", "Scientology", \ + "The Bible melts", "Unaussprechlichen Kulten", "Necronomicon", "Book of Shadows", "Torah", "Burning", "Honk", "Ianism", "The Guide") switch(new_book_style) if("Koran") B.icon_state = "koran" @@ -156,7 +156,7 @@ for(var/turf/T in A.contents) if(T.icon_state == "carpetsymbol") T.dir = 8 - if("the bible melts") + if("The Bible melts") B.icon_state = "melted" B.item_state = "melted" if("Unaussprechlichen Kulten") @@ -222,7 +222,8 @@ ticker.Bible_icon_state = B.icon_state ticker.Bible_item_state = B.item_state ticker.Bible_name = B.name - ticker.Bible_deity_name = B.my_rel.deity_name + ticker.Bible_deity_name = chap_religion.deity_name + ticker.chap_rel = chap_religion ticker.religions += chap_religion feedback_set_details("religion_deity","[new_deity]") feedback_set_details("religion_book","[new_book_style]") diff --git a/code/game/jobs/job/job.dm b/code/game/jobs/job/job.dm index fc3f2770d6e..7ca37399aa6 100644 --- a/code/game/jobs/job/job.dm +++ b/code/game/jobs/job/job.dm @@ -56,6 +56,7 @@ var/no_id = 0 //If 1, don't spawn with an ID var/no_pda= 0 //If 1, don't spawn with a PDA var/no_headset = 0 //If 1, don't spawn with a headset + var/spawns_from_edge = 0 //Instead of spawning on the shuttle, spawns in space and gets thrown var/no_random_roll = 0 //If 1, don't select this job randomly! diff --git a/code/game/jobs/job/whitelisted.dm b/code/game/jobs/job/whitelisted.dm index 91f525adf5c..c96364dec9e 100644 --- a/code/game/jobs/job/whitelisted.dm +++ b/code/game/jobs/job/whitelisted.dm @@ -3,7 +3,7 @@ flag = TRADER department_flag = CIVILIAN faction = "Station" - total_positions = 0 + total_positions = 3 spawn_positions = 3 supervisors = "nobody" selection_color = "#dddddd" @@ -21,6 +21,8 @@ no_starting_money = 1 no_pda = 1 + spawns_from_edge = 1 + idtype = /obj/item/weapon/card/id/vox no_headset = 1 @@ -57,12 +59,13 @@ if(!job_title) job_title = src.title + if(!trader_account) + trader_account = create_account("Trader Shoal", 0, null, 0) //Starts 0 credits, not sourced from any database, earns 0 credits + M.mind.store_memory("The joint trader account is: #[trader_account.account_number]
Your shared account pin is: [trader_account.remote_access_pin]
") + to_chat(M, "You are a [job_title].") - if(map && map.nameShort == "meta") //Shitty way to do it, but whatever - traders start on a shuttle wreckage on metaclub, not on the vox outpost - to_chat(M, "A while ago you got your equipment together and boarded a small shuttle, heading for your destination (whatever it may be). Everything was great, until the shuttle somehow crashed into an asteroid. You're still alive, but you're not quite sure where you are. Maybe some of your friends know - unless they died in the crash...") - else - to_chat(M, "You've finally got your equipment together, such as it is. Now it's time for action and adventure! In the rush of excitement, you've forgotten where you were going to go. If only you had any friends that could remind you...") + to_chat(M, "You've finally got your equipment together, such as it is. Now it's time for action and adventure! In the rush of excitement, you've forgotten where you were going to go. If only you had any friends that could remind you...") to_chat(M, "Despite not being a member of the crew, by default you are not an antagonist. Cooperating with antagonists is allowed - within reason. Ask admins via adminhelp if you're not sure.") diff --git a/code/game/jobs/job_controller.dm b/code/game/jobs/job_controller.dm index 2e928afe6d9..6435d915825 100644 --- a/code/game/jobs/job_controller.dm +++ b/code/game/jobs/job_controller.dm @@ -439,7 +439,7 @@ var/global/datum/controller/occupations/job_master H.Robotize() return 1 if("Mobile MMI") - H.MoMMIfy(1) + H.MoMMIfy() return 1 if("AI","Clown") //don't need bag preference stuff! if(rank=="Clown") // Clowns DO need to breathe, though - N3X @@ -492,6 +492,12 @@ var/global/datum/controller/occupations/job_master var/obj/structure/bed/chair/vehicle/wheelchair/W = new(H.loc) W.buckle_mob(H,H) + if(H.disabilities & ASTHMA) + if(H.backbag == 1) + H.put_in_hand(GRASP_LEFT_HAND, new /obj/item/device/inhaler(H)) + else + H.equip_or_collect(new /obj/item/device/inhaler(H), slot_in_backpack) + return 1 diff --git a/code/game/machinery/OpTable.dm b/code/game/machinery/OpTable.dm index 8a193c55b13..a615b65e06f 100644 --- a/code/game/machinery/OpTable.dm +++ b/code/game/machinery/OpTable.dm @@ -151,9 +151,9 @@ /obj/machinery/optable/attackby(obj/item/weapon/W as obj, mob/living/carbon/user as mob) if(iswrench(W)) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + playsound(src, 'sound/items/Ratchet.ogg', 50, 1) if(do_after(user, src, 40)) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + playsound(src, 'sound/items/Ratchet.ogg', 50, 1) switch(rating) if(1) new /obj/item/weapon/stock_parts/scanning_module(src.loc) @@ -172,4 +172,31 @@ if(isrobot(user)) return //user.drop_item(W, src.loc) why? - return + +/obj/machinery/optable/npc_tamper_act(mob/living/user) + //Messages are overridden for this proc + . = NPC_TAMPER_ACT_NOMSG + + if(!victim) + return + + var/list/pickable_items = list() + + for(var/obj/item/I in adjacent_atoms(user)) + pickable_items.Add(I) + + if(!pickable_items.len) + user.visible_message("\The [user] tries to think of a way to screw \the [victim] up without any tools nearby, but fails miserably.") + return + + var/obj/item/tool = pick(pickable_items) + + user.visible_message(pick( + "\The [user] grabs \a nearby [tool] and contemplates using it on \the [victim]!", + "\The [user]'s eyes light up as \he tries to use \the [tool] to operate on \the [victim]", + "\The [user] rubs its hands devilishly and attempts to operate on \the [victim] with \the [tool].")) + if(isgremlin(user)) + var/mob/living/simple_animal/hostile/gremlin/G = user + G.stand_still(4) + + global.do_surgery(victim, user, tool) diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm index 6040dee757a..ad9c36b3f6d 100644 --- a/code/game/machinery/Sleeper.dm +++ b/code/game/machinery/Sleeper.dm @@ -1,61 +1,75 @@ ///////////////////////////////////////// -// SLEEPER CONSOLE +// THE SLEEPER ITSELF ///////////////////////////////////////// -/obj/machinery/sleep_console - name = "\improper Sleeper Console" - icon = 'icons/obj/Cryogenic2.dmi' - icon_state = "sleeperconsole" - var/obj/machinery/sleeper/connected = null - anchored = 1 //About time someone fixed this. - density = 1 - var/orient = "LEFT" // "RIGHT" changes the dir suffix to "-r" - - -/obj/machinery/sleep_console/ex_act(severity) - switch(severity) - if(1.0) - //SN src = null - qdel(src) - return - if(2.0) - if (prob(50)) - //SN src = null - qdel(src) - return +/obj/machinery/sleeper + name = "\improper Sleeper" + icon = 'icons/obj/cryogenics3.dmi' + icon_state = "sleeper_0" + density = TRUE + anchored = TRUE + var/base_icon = "sleeper" + var/mob/living/occupant = null + var/available_options = list(INAPROVALINE = "Inaprovaline", STOXIN = "Soporific", DERMALINE = "Dermaline", BICARIDINE = "Bicaridine", DEXALIN = "Dexalin") + var/amounts = list(5, 10) + var/sedativeblock = FALSE //To prevent people from being surprisesoporific'd + machine_flags = SCREWTOGGLE | CROWDESTROY | WRENCHMOVE | EJECTNOTDEL + component_parts = newlist( + /obj/item/weapon/circuitboard/sleeper, + /obj/item/weapon/stock_parts/scanning_module, + /obj/item/weapon/stock_parts/manipulator, + /obj/item/weapon/stock_parts/manipulator + ) + light_color = LIGHT_COLOR_CYAN + light_range_on = 3 + light_power_on = 2 + power_change() + ..() + if(!(stat & (BROKEN|NOPOWER)) && occupant) + set_light(light_range_on, light_power_on) else - return + set_light(0) + var/on = FALSE + var/target_time = 0 + var/setting + var/automatic = FALSE + var/auto_eject_after = 1 //Boot the mooch off after waking 'em up + var/drag_delay = 20 + var/cools = 0 -/obj/machinery/sleep_console/New() +/obj/machinery/sleeper/New() ..() - spawn( 5 ) - update_icon() - if(orient == "RIGHT") - src.connected = locate(/obj/machinery/sleeper, get_step(src, EAST)) + if(map.nameShort == "deff") + icon = 'maps/defficiency/medbay.dmi' + RefreshParts() + +/obj/machinery/sleeper/Destroy() + go_out() //Eject everything + ..() + +/obj/machinery/sleeper/update_icon() + icon_state = "[base_icon]_[occupant ? "1" : "0"]" + +/obj/machinery/sleeper/RefreshParts() + var/T = 0 + for(var/obj/item/weapon/stock_parts/SP in component_parts) + T += SP.rating + switch(T) + if(0 to 5) + available_options = list(INAPROVALINE = "Inaprovaline", STOXIN = "Soporific", KELOTANE = "Kelotane", BICARIDINE = "Bicaridine", DEXALIN = "Dexalin") + if(6 to 8) + available_options = list(INAPROVALINE = "Inaprovaline", STOXIN = "Soporific", DERMALINE = "Dermaline", BICARIDINE = "Bicaridine", DEXALIN = "Dexalin", IMIDAZOLINE = "Imidazoline" , INACUSIATE = "Inacusiate" , TRICORDRAZINE = "Tricordrazine") else - src.connected = locate(/obj/machinery/sleeper, get_step(src, WEST)) - return + available_options = list(INAPROVALINE = "Inaprovaline", STOXIN = "Soporific", DERMALINE = "Dermaline", BICARIDINE = "Bicaridine", DEXALIN = "Dexalin", IMIDAZOLINE = "Imidazoline" , INACUSIATE = "Inacusiate" , TRICORDRAZINE = "Tricordrazine" , ALKYSINE = "Alkysine" , TRAMADOL = "Tramadol" , PEPTOBISMOL = "Peptobismol") -/obj/machinery/sleep_console/update_icon() - icon_state = "sleeperconsole[stat & NOPOWER ? "-p" : null][orient == "LEFT" ? null : "-r"]" - -/obj/machinery/sleep_console/attack_hand(var/mob/user) - . = ..() - if(.) - return - interact(user) - -/obj/machinery/sleep_console/interact(var/mob/user) - if(!connected) - return - var/mob/living/occupant = connected.occupant +/obj/machinery/sleeper/interact(var/mob/user) var/dat = list() - if(connected.on) + if(on) dat += "Performing anaesthesic emergence..." //Best I could come up with - dat += "
Auto-eject occupant: [connected.auto_eject_after ? "Yes" : "No"]
" + dat += "
Auto-eject occupant: [auto_eject_after ? "Yes" : "No"]
" else dat += "Occupant statistics:
" - if (occupant) + if(occupant) var/occupant_status = "???" switch(occupant.stat) if(CONSCIOUS) @@ -76,14 +90,14 @@ dat += "\t-Toxin content: [round(toxloss, 0.1)]
" var/fireloss = occupant.getFireLoss() dat += "\t-Burn severity: [round(fireloss, 0.1)]
" - + var/sleepytime = max(occupant.paralysis, occupant.sleeping) dat += "
Paralysis summary: [sleepytime] ([round(sleepytime * 2)] seconds left!)
" dat += "Begin wake-up cycle
" if(occupant.reagents) - for(var/chemical in connected.available_options) - dat += "[connected.available_options[chemical]]: [round(occupant.reagents.get_reagent_amount(chemical), 0.1)] units" - for(var/amount in connected.amounts) + for(var/chemical in available_options) + dat += "[available_options[chemical]]: [round(occupant.reagents.get_reagent_amount(chemical), 0.1)] units" + for(var/amount in amounts) dat += " Inject [amount]u" dat += "
" dat += "
Refresh
" @@ -93,17 +107,20 @@ var/datum/browser/popup = new(user, "\ref[src]", name, 400, 500) popup.set_content(dat) popup.open() -/obj/machinery/sleep_console/Topic(href, href_list) + +/obj/machinery/sleeper/Topic(href, href_list) if(..()) - return 1 + return TRUE + if(usr.loc == src) + return TRUE else usr.set_machine(src) - if (href_list["chemical"]) - if (src.connected && src.connected.occupant) - if (src.connected.occupant.stat == DEAD) + if(href_list["chemical"]) + if(occupant) + if(occupant.stat == DEAD) to_chat(usr, "This person has no life for to preserve anymore. Take them to a department capable of reanimating them.") - else if(href_list["chemical"] == STOXIN && src.connected.sedativeblock) - if(src.connected.sedativeblock < 3) + else if(href_list["chemical"] == STOXIN && sedativeblock) + if(sedativeblock < 3) to_chat(usr, "Sedative injections not yet ready. Please try again in a few seconds.") else //if this guy is seriously just mashing the soporific button... to_chat(usr, "[pick( \ @@ -115,158 +132,23 @@ "The occupant is still moving around!", \ "Sorry pal, safety procedures.", \ "But it's not bedtime yet!")]") - src.connected.sedativeblock++ - else if(src.connected.occupant.health < 0 && href_list["chemical"] != INAPROVALINE) + sedativeblock++ + else if(occupant.health < 0 && href_list["chemical"] != INAPROVALINE) to_chat(usr, "This person is not in good enough condition for sleepers to be effective! Use another means of treatment, such as cryogenics!") else - if(!(href_list["chemical"] in connected.available_options)) //href exploitu go home + if(!(href_list["chemical"] in available_options)) //href exploitu go home to_chat(usr,"That's odd. You could've sworn the [href_list["chemical"]] button was there just a second ago!") else - connected.inject_chemical(usr,href_list["chemical"],text2num(href_list["amount"])) - if (href_list["wakeup"]) - connected.wakeup(usr) - if (href_list["toggle_autoeject"]) - connected.auto_eject_after = !connected.auto_eject_after - if (href_list["refresh"]) - src.process() - src.add_fingerprint(usr) + inject_chemical(usr,href_list["chemical"],text2num(href_list["amount"])) + if(href_list["wakeup"]) + wakeup(usr) + if(href_list["toggle_autoeject"]) + auto_eject_after = !auto_eject_after + if(href_list["refresh"]) + process() + add_fingerprint(usr) return -/obj/machinery/sleep_console/AltClick() - if(connected && !usr.incapacitated() && Adjacent(usr) && !(stat & (NOPOWER|BROKEN) && usr.dexterity_check())) - if(connected.wakeup(usr)) - visible_message("\The [connected] pings softly: 'Initiating wake-up cycle...' ") - - -/obj/machinery/sleep_console/process() - if(stat & (NOPOWER|BROKEN)) - return - src.updateUsrDialog() - return - -/obj/machinery/sleep_console/power_change() - return - // no change - sleeper works without power (you just can't inject more) - - - - - - - -///////////////////////////////////////// -// THE SLEEPER ITSELF -///////////////////////////////////////// - -/obj/machinery/sleeper - name = "\improper Sleeper" - icon = 'icons/obj/Cryogenic2.dmi' - icon_state = "sleeper_0" - density = 1 - anchored = 1 - var/base_icon = "sleeper" - var/orient = "LEFT" // "RIGHT" changes the dir suffix to "-r" - var/mob/living/occupant = null - var/available_options = list(INAPROVALINE = "Inaprovaline", STOXIN = "Soporific", DERMALINE = "Dermaline", BICARIDINE = "Bicaridine", DEXALIN = "Dexalin") - var/amounts = list(5, 10) - var/obj/machinery/sleep_console/connected = null - var/sedativeblock = 0 //To prevent people from being surprisesoporific'd - machine_flags = SCREWTOGGLE | CROWDESTROY | WRENCHMOVE | EJECTNOTDEL - component_parts = newlist( - /obj/item/weapon/circuitboard/sleeper, - /obj/item/weapon/stock_parts/scanning_module, - /obj/item/weapon/stock_parts/manipulator, - /obj/item/weapon/stock_parts/manipulator - ) - light_color = LIGHT_COLOR_CYAN - light_range_on = 3 - light_power_on = 2 - power_change() - ..() - if(!(stat & (BROKEN|NOPOWER)) && occupant) - set_light(light_range_on, light_power_on) - else - set_light(0) - var/connected_type = /obj/machinery/sleep_console - var/on = 0 - var/target_time = 0 - var/setting - var/automatic = 0 - var/auto_eject_after = 1 //Boot the mooch off after waking 'em up - var/drag_delay = 20 - var/cools = 0 - - var/no_console = 0 - -/obj/machinery/sleeper/New() - ..() - RefreshParts() - - spawn( 5 ) - var/turf/t - if(orient == "RIGHT") - update_icon() // Only needs to update if it's orientation isn't default - t = get_step(get_turf(src), WEST) - // generate_console(get_step(get_turf(src), WEST)) - else - t = get_step(get_turf(src), EAST) - // generate_console(get_step(get_turf(src), EAST)) - - if(no_console) - return - - ASSERT(t) - var/obj/machinery/sleep_console/c = locate() in t.contents - if(c && istype(c,connected_type)) - connected = c - c.connected = src - else if (!connected) - generate_console(t) - return - return - -/obj/machinery/sleeper/no_console - no_console = 1 - -/obj/machinery/sleeper/Destroy() - - go_out() //Eject everything - - . = ..() - - if(connected) - connected.connected = null - qdel(connected) - connected = null - -/obj/machinery/sleeper/update_icon() - icon_state = "[base_icon]_[occupant ? "1" : "0"][orient == "LEFT" ? null : "-r"]" - -/obj/machinery/sleeper/proc/generate_console(turf/T as turf) - if(connected) - connected.orient = src.orient - connected.update_icon() - return 1 - if(!T.density) - connected = new connected_type(T) - connected.orient = src.orient - connected.update_icon() - return 1 - else - return 0 - -/obj/machinery/sleeper/RefreshParts() - var/T = 0 - for(var/obj/item/weapon/stock_parts/SP in component_parts) - T += SP.rating - switch(T) - if(0 to 5) - available_options = list(INAPROVALINE = "Inaprovaline", STOXIN = "Soporific", KELOTANE = "Kelotane", BICARIDINE = "Bicaridine", DEXALIN = "Dexalin") - if(6 to 8) - available_options = list(INAPROVALINE = "Inaprovaline", STOXIN = "Soporific", DERMALINE = "Dermaline", BICARIDINE = "Bicaridine", DEXALIN = "Dexalin", IMIDAZOLINE = "Imidazoline" , INACUSIATE = "Inacusiate" , TRICORDRAZINE = "Tricordrazine") - else - available_options = list(INAPROVALINE = "Inaprovaline", STOXIN = "Soporific", DERMALINE = "Dermaline", BICARIDINE = "Bicaridine", DEXALIN = "Dexalin", IMIDAZOLINE = "Imidazoline" , INACUSIATE = "Inacusiate" , TRICORDRAZINE = "Tricordrazine" , ALKYSINE = "Alkysine" , TRAMADOL = "Tramadol" , PEPTOBISMOL = "Peptobismol") - /obj/machinery/sleeper/MouseDrop_T(atom/movable/O as mob|obj, mob/user as mob) if(!ismob(O)) //mobs only return @@ -288,7 +170,7 @@ return if(isrobot(user)) var/mob/living/silicon/robot/robit = usr - if(istype(robit) && !istype(robit.module, /obj/item/weapon/robot_module/medical)) + if(!(robit.module && (robit.module.quirk_flags & MODULE_CAN_HANDLE_MEDICAL))) to_chat(user, "You do not have the means to do this!") return var/mob/living/L = O @@ -309,20 +191,20 @@ L.forceMove(src) L.reset_view() - src.occupant = L + occupant = L to_chat(L, "You feel an anaesthetising air surround you. You go numb as your senses turn inward.") - connected.process() + process() for(var/obj/OO in src) - OO.forceMove(src.loc) - src.add_fingerprint(user) + OO.forceMove(loc) + add_fingerprint(user) if(user.pulling == L) user.stop_pulling() if(!(stat & (BROKEN|NOPOWER))) set_light(light_range_on, light_power_on) - sedativeblock = 1 + sedativeblock = TRUE update_icon() sleep(drag_delay) - sedativeblock = 0 + sedativeblock = FALSE return @@ -334,7 +216,7 @@ return if(isrobot(usr)) var/mob/living/silicon/robot/robit = usr - if(istype(robit) && !istype(robit.module, /obj/item/weapon/robot_module/medical)) + if(!(robit.module && (robit.module.quirk_flags & MODULE_CAN_HANDLE_MEDICAL))) to_chat(usr, "You do not have the means to do this!") return if(!istype(over_location) || over_location.density) @@ -355,21 +237,17 @@ go_out(over_location) /obj/machinery/sleeper/allow_drop() - return 0 - -/obj/machinery/sleeper/AltClick() - if(connected) - return connected.AltClick() + return FALSE /obj/machinery/sleeper/process() - src.updateDialog() + updateDialog() return /obj/machinery/sleeper/blob_act() if(prob(75)) for(var/atom/movable/A as mob|obj in src) - A.forceMove(src.loc) + A.forceMove(loc) A.blob_act() qdel(src) return @@ -380,82 +258,74 @@ return return ..() -/obj/machinery/sleeper/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(..()) - return 1 - if(iswrench(W)&&!occupant&& (machine_flags & WRENCHMOVE)) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) - if(orient == "RIGHT") - orient = "LEFT" - if(generate_console(get_step(get_turf(src), EAST))) - update_icon() - else - orient = "RIGHT" - to_chat(user, "There is no space!") - else - orient = "RIGHT" - if(generate_console(get_step(get_turf(src), WEST))) - update_icon() - else - orient = "LEFT" - visible_message("There is no space!","[user] wants to be hardcore, but his CMO won't let him.") - return - if(!istype(W, /obj/item/weapon/grab)) +/obj/machinery/sleeper/attackby(obj/item/weapon/obj_used, mob/user) + + if(!istype(obj_used, /obj/item/weapon/grab)) return ..() - var/obj/item/weapon/grab/G = W - if(!(ismob(G.affecting)) || G.affecting.locked_to) + else + if(..()) + return TRUE + + var/obj/item/weapon/grab/tar_grab = obj_used + if(!(ismob(tar_grab.affecting)) || tar_grab.affecting.locked_to) return - if(src.occupant) + + if(occupant) to_chat(user, "The sleeper is already occupied!") return - for(var/mob/living/carbon/slime/M in range(1,G.affecting)) - if(M.Victim == G.affecting) - to_chat(usr, "[G.affecting.name] will not fit into \the [src] because they have a slime latched onto their head.") + for(var/mob/living/carbon/slime/tar_slime in range(1,tar_grab.affecting)) + if(tar_slime.Victim == tar_grab.affecting) + to_chat(usr, "[tar_grab.affecting.name] will not fit into \the [src] because they have a slime latched onto their head.") return - visible_message("[user] places [G.affecting.name] into \the [src].") + visible_message("[user] places [tar_grab.affecting.name] into \the [src].") - var/mob/M = G.affecting - if(!isliving(M) || M.locked_to) + var/mob/tar_mob = tar_grab.affecting + if(!isliving(tar_mob) || tar_mob.locked_to) return - M.forceMove(src) - M.reset_view() - src.occupant = M + tar_mob.forceMove(src) + tar_mob.reset_view() + occupant = tar_mob - to_chat(M, "You feel an anaesthetising air surround you. You go numb as your senses turn inward.") - connected.process() - for(var/obj/O in src) - O.forceMove(src.loc) - src.add_fingerprint(user) - qdel(G) + to_chat(tar_mob, "You feel an anaesthetising air surround you. You go numb as your senses turn inward.") + process() + for(var/obj/tar_obj in src) + tar_obj.forceMove(loc) + add_fingerprint(user) + qdel(tar_grab) if(!(stat & (BROKEN|NOPOWER))) set_light(light_range_on, light_power_on) update_icon() - sedativeblock = 1 + sedativeblock = TRUE spawn(drag_delay) - sedativeblock = 0 + sedativeblock = FALSE return +/obj/machinery/sleeper/attack_hand(mob/user) + if(!isobserver(user) && (user.loc == src || (!Adjacent(user)&&!issilicon(user)) || user.incapacitated())) + return + interact(user) + /obj/machinery/sleeper/ex_act(severity) switch(severity) if(1.0) for(var/atom/movable/A as mob|obj in src) - A.forceMove(src.loc) + A.forceMove(loc) ex_act(severity) qdel(src) return if(2.0) if(prob(50)) for(var/atom/movable/A as mob|obj in src) - A.forceMove(src.loc) + A.forceMove(loc) ex_act(severity) qdel(src) return if(3.0) if(prob(25)) for(var/atom/movable/A as mob|obj in src) - A.forceMove(src.loc) + A.forceMove(loc) ex_act(severity) qdel(src) return @@ -469,88 +339,70 @@ go_out() ..(severity) -/obj/machinery/sleeper/alter_health(mob/living/M as mob) //Long since unused. - if (M.health > 0) - if (M.getOxyLoss() >= 10) - var/amount = max(0.15, 1) - M.adjustOxyLoss(-amount) - else - M.adjustOxyLoss(-12) - M.updatehealth() - M.AdjustParalysis(-4) - M.AdjustKnockdown(-4) - M.AdjustStunned(-4) - M.Paralyse(1) - M.Knockdown(1) - M.Stun(1) - if (M:reagents.get_reagent_amount(INAPROVALINE) < 5) - M:reagents.add_reagent(INAPROVALINE, 5) - return - /obj/machinery/sleeper/proc/cook(var/cook_setting) - if (!(cook_setting in available_options)) + if(!(cook_setting in available_options)) return var/cooktime = available_options[cook_setting] target_time = world.time + cooktime - on = 1 + on = TRUE setting = cook_setting update_icon() /obj/machinery/sleeper/proc/wakeup(mob/living/user) - if(src.on) + if(on) to_chat(user, "\The [src] is busy.") - return 0 + return FALSE if(!occupant) to_chat(user, "There's no occupant in \the [src]!") - return 0 + return FALSE if(occupant.stat == CONSCIOUS) to_chat(user, "The occupant is already awake.") - return 0 + return FALSE if(occupant.stat == DEAD) to_chat(user, "Can't wake up.") - return 0 - . = 1 //Returning 1 means we successfully began the wake-up cycle. We will return immediately as the spawn() begins, not at the end. - src.on = 1 - connected.process() + return FALSE + . = TRUE //Returning TRUE means we successfully began the wake-up cycle. We will return immediately as the spawn() begins, not at the end. + on = TRUE + process() var/sleeptime = min(5 SECONDS, 4*max(occupant.sleeping, occupant.paralysis)) spawn(sleeptime) - if(!src || !src.on) //the !src check is redundant from the nature of spawn() if I understand correctly, but better be safe than sorry + if(!src || !on) //the !src check is redundant from the nature of spawn() if I understand correctly, but better be safe than sorry return 0 if(occupant) occupant.sleeping = 0 occupant.paralysis = 0 occupant.resting = 0 - src.on = 0 + on = FALSE if(auto_eject_after) - src.go_out() - connected.process() + go_out() + process() -/obj/machinery/sleeper/proc/go_out(var/exit = src.loc) +/obj/machinery/sleeper/proc/go_out(var/exit = loc) if(!occupant) - return 0 - for (var/atom/movable/x in src.contents) + return FALSE + for (var/atom/movable/x in contents) if(x in component_parts) continue - x.forceMove(src.loc) + x.forceMove(loc) if(!occupant.gcDestroyed) occupant.forceMove(exit) occupant.reset_view() occupant = null update_icon() - return 1 + return TRUE /obj/machinery/sleeper/proc/inject_chemical(mob/living/user as mob, chemical, amount) - if(!src.occupant) + if(!occupant) to_chat(user, "There's no occupant in the sleeper!") return - if(isnull(src.occupant.reagents)) + if(isnull(occupant.reagents)) to_chat(user, "The occupant appears to somehow lack a bloodstream. Please consult a shrink.") return - if(src.occupant.reagents.get_reagent_amount(chemical) + amount > 20) + if(occupant.reagents.get_reagent_amount(chemical) + amount > 20) to_chat(user, "Overdose Prevention System: The occupant already has enough [available_options[chemical]] in their system.") return - src.occupant.reagents.add_reagent(chemical, amount) - to_chat(user, "Occupant now has [src.occupant.reagents.get_reagent_amount(chemical)] units of [available_options[chemical]] in their bloodstream.") + occupant.reagents.add_reagent(chemical, amount) + to_chat(user, "Occupant now has [occupant.reagents.get_reagent_amount(chemical)] units of [available_options[chemical]] in their bloodstream.") return /obj/machinery/sleeper/verb/eject() @@ -559,7 +411,7 @@ set src in oview(1) if(usr.isUnconscious()) return - src.go_out() + go_out() add_fingerprint(usr) set_light(0) return @@ -571,7 +423,7 @@ if(usr.isUnconscious() || !(ishuman(usr) || ismonkey(usr))) return - if(src.occupant) + if(occupant) to_chat(usr, "\The [src] is already occupied!") return if(usr.incapacitated() || usr.lying) //are you cuffed, dying, lying, stunned or other @@ -584,7 +436,7 @@ return visible_message("[usr] starts climbing into \the [src].") if(do_after(usr, src, drag_delay)) - if(src.occupant) + if(occupant) to_chat(usr, "The sleeper is already occupied!") return if(usr.locked_to) @@ -592,118 +444,100 @@ usr.stop_pulling() usr.forceMove(src) usr.reset_view() - src.occupant = usr - connected.process() + occupant = usr + process() for(var/obj/O in src) qdel(O) - src.add_fingerprint(usr) + add_fingerprint(usr) if(!(stat & (BROKEN|NOPOWER))) set_light(light_range_on, light_power_on) update_icon() return return -/obj/machinery/sleep_console/mancrowave_console - name = "thermal homeostasis regulator" - desc = "This invention by Mancrowave Inc. is meant for stabilising body temperature. Modern medical technology is amazing." - icon_state = "manconsole_open" + +/obj/machinery/sleeper/AltClick() + if(!usr.incapacitated() && Adjacent(usr) && !(stat & (NOPOWER|BROKEN) && usr.dexterity_check())) + if(wakeup(usr)) + visible_message("\The [src] pings softly: 'Initiating wake-up cycle...' ") + +/obj/machinery/sleeper/process() + if(stat & (NOPOWER|BROKEN)) + return + updateUsrDialog() + return /obj/machinery/sleeper/mancrowave name = "thermal homeostasis regulator" - desc = "This invention by Mancrowave Inc. is meant for stabilising body temperature. Modern medical technology is amazing." - icon_state = "mancrowave_open" + desc = "The new generation 'minicrowave' from Mancrowave Inc. It has the same satisfying ping as the classic." base_icon = "mancrowave" + icon_state = "mancrowave_open" component_parts = newlist( /obj/item/weapon/circuitboard/sleeper/mancrowave, /obj/item/weapon/stock_parts/scanning_module, /obj/item/weapon/stock_parts/manipulator, /obj/item/weapon/stock_parts/manipulator ) - connected_type = /obj/machinery/sleep_console/mancrowave_console setting = "Thermoregulate" available_options = list("Thermoregulate" = 50) light_color = LIGHT_COLOR_ORANGE - automatic = 1 + automatic = TRUE drag_delay = 0 machine_flags = SCREWTOGGLE | CROWDESTROY | EMAGGABLE | EJECTNOTDEL +/obj/machinery/sleeper/mancrowave/New() + ..() + if(map.nameShort == "deff") + icon = 'maps/defficiency/medbay.dmi' + update_icon() -/obj/machinery/sleeper/mancrowave/go_out(var/exit = src.loc) +/obj/machinery/sleeper/mancrowave/go_out(var/exit = loc) if(on && !emagged) - return 0 + return FALSE else - on = 0 + on = FALSE ..() /obj/machinery/sleeper/mancrowave/update_icon() if(!occupant) icon_state = "[base_icon]_open" - else if(setting != "Thermoregulate" && on) - icon_state = "[base_icon]_2" - else - icon_state = "[base_icon]_[on]" + set_light(0) + return if(emagged) light_color = LIGHT_COLOR_RED - icon_state += "emag" + icon_state = "[base_icon]_emagged" else + light_color = LIGHT_COLOR_ORANGE + icon_state = "[base_icon]_running" if(on) set_light(light_range_on, light_power_on) else set_light(0) - if(connected) - connected.update_icon() - else - qdel(src) /obj/machinery/sleeper/mancrowave/emag(mob/user) if(!emagged) - emagged = 1 - connected.emagged = 1 + emagged = TRUE if(user) to_chat(user, "You short out the safety features of \the [src], and feel like a MAN! ") available_options = list("Thermoregulate" = 50,"Rare" = 500,"Medium" = 600,"Well Done" = 700) update_icon() - connected.name = "THE MANCROWAVE" name = "THE MANCROWAVE" return 1 - return -1 + return -1 //WHY DO YOU DO THIS TO ME /obj/machinery/sleeper/mancrowave/RefreshParts() -/obj/machinery/sleep_console/mancrowave_console/update_icon() - if(connected) - if(!connected.occupant) - icon_state = "manconsole_open" - else if(connected.setting != "Thermoregulate" && connected.on) - icon_state = "manconsole_2" - else - icon_state = "manconsole_[connected.on]" - if(connected.emagged) - icon_state += "emag" - - -/obj/machinery/sleep_console/mancrowave_console/Destroy() - . = ..() - if(connected) - connected.connected = null - connected.go_out() - qdel(connected) - connected = null - -/obj/machinery/sleep_console/mancrowave_console/interact(var/mob/user) - if (!connected) - return - var/mob/living/occupant = src.connected.occupant +/obj/machinery/sleeper/mancrowave/interact(var/mob/user) var/dat = "Occupant Statistics:
" - if (occupant) + if(occupant) var/t1 switch(occupant.stat) - if(0) + if(CONSCIOUS) t1 = "Conscious" - if(1) + if(UNCONSCIOUS) t1 = "Unconscious" - if(2) + if(DEAD) t1 = "*dead*" else dat += text("[]\tHealth %: [] ([])
", (occupant.health > 50 ? "" : ""), occupant.health, t1) @@ -712,121 +546,101 @@ dat += text("[]\t-Pulse, bpm: []
", (C.pulse == PULSE_NONE || C.pulse == PULSE_2SLOW || C.pulse == PULSE_THREADY ? "" : ""), C.get_pulse(GETPULSE_TOOL)) dat += text("[]\t -Core Temperature: []°C
", (C.undergoing_hypothermia() ? "" : ""), C.bodytemperature-T0C) dat += "
Cook settings:
" - for(var/cook_setting in connected.available_options) - dat += "[cook_setting] - [connected.available_options[cook_setting]/10] seconds" + for(var/cook_setting in available_options) + dat += "[cook_setting] - [available_options[cook_setting]/10] seconds" dat += "
" else dat += "\The [src] is empty." dat += "
Refresh meter readings each second
" - dat += "Turn [connected.automatic ? "off": "on" ] Automatic Thermoregulation.
" - dat += "[(connected.emagged) ? "Re-enable Security Features.
" : ""]" - dat += "[(connected.on) ? "\[EMERGENCY STOP\] : cancels the current job.
" : ""]" + dat += "Turn [automatic ? "off": "on" ] Automatic Thermoregulation.
" + dat += "[(emagged) ? "Re-enable Security Features.
" : ""]" + dat += "[(on) ? "\[EMERGENCY STOP\] : cancels the current job.
" : ""]" dat += text("

Close", user) user << browse(dat, "window=\ref[src];size=400x500") onclose(user, "\ref[src]") -/obj/machinery/sleep_console/mancrowave_console/Topic(href, href_list) +/obj/machinery/sleeper/mancrowave/Topic(href, href_list) if(..()) - return 1 - usr.set_machine(src) - if (href_list["cook"]) - if (src.connected) - if (connected.on) - to_chat(usr, "\The [src] is already turned on!") + return TRUE + if(href_list["cook"]) + if(on) + to_chat(usr, "\The [src] is already turned on!") + return + if(occupant) + if((locate(/obj/item/weapon/disk/nuclear) in get_contents_in_object(occupant)) && href_list["cook"] != "Thermoregulate" ) + to_chat(usr, "Even with the safety features turned off, \the [src] refuses to cook something inside of it!") else - if (src.connected.occupant) - if ((locate(/obj/item/weapon/disk/nuclear) in get_contents_in_object(connected.occupant)) && href_list["cook"] != "Thermoregulate" ) - to_chat(usr, "Even with the safety features turned off, \the [src] refuses to cook something inside of it!") - else - connected.cook(href_list["cook"]) - if (href_list["refresh"]) - src.updateUsrDialog() + cook(href_list["cook"]) + if(href_list["refresh"]) + updateUsrDialog() if(href_list["auto"]) - connected.automatic = !connected.automatic + automatic = !automatic if(href_list["turnoff"]) - connected.on = 0 - connected.go_out() - connected.update_icon() + on = FALSE + go_out() + update_icon() if(href_list["security"]) - if(src.connected && connected.on) + if(on) to_chat(usr, "The security features of \the [src] cannot be re-enabled when it is on!") return - connected.emagged = 0 - emagged = 0 + emagged = FALSE name = "thermal homeostasis regulator" - connected.name = "thermal homeostasis regulator" - connected.available_options = list("Thermoregulate" = 50) - connected.update_icon() - src.add_fingerprint(usr) - src.updateUsrDialog() - return + available_options = list("Thermoregulate" = 50) + update_icon() + add_fingerprint(usr) + updateUsrDialog() -/obj/machinery/sleep_console/mancrowave_console/process() +/obj/machinery/sleeper/mancrowave/process() ..() - if(!connected) + if(automatic && occupant && !on) + cook("Thermoregulate") + if(!istype(occupant,/mob/living/carbon)) + go_out() return - if(connected.automatic && connected.occupant && !connected.on) - connected.cook("Thermoregulate") - if(!connected.on) - else if(!src || !connected || !connected.occupant || connected.occupant.loc != connected || connected.occupant.gcDestroyed) //Check if someone's released/replaced/bombed him already - connected.occupant = null - connected.on = 0 - connected.update_icon() - return - if(!istype(connected.occupant,/mob/living/carbon)) - connected.go_out() - return - if(!(world.time >= connected.target_time && connected.on)) //If we're currently still cooking - var/targettemperature = T0C+32+(connected.available_options["[connected.setting]"]/10) - var/emaggedbonus = (connected.emagged) ? 10 : 1 - var/timefraction = (connected.available_options["[connected.setting]"])/250*emaggedbonus - var/tempdifference = abs(targettemperature - connected.occupant.bodytemperature) - if(connected.occupant.bodytemperature < targettemperature) - connected.occupant.bodytemperature = min(connected.occupant.bodytemperature + tempdifference*(timefraction),targettemperature) + if(!(world.time >= target_time && on)) //If we're currently still cooking + var/targettemperature = T0C+32+(available_options["[setting]"]/10) + var/emaggedbonus = (emagged) ? 10 : 1 + var/timefraction = (available_options["[setting]"])/250*emaggedbonus + var/tempdifference = abs(targettemperature - occupant.bodytemperature) + if(occupant.bodytemperature < targettemperature) + occupant.bodytemperature = min(occupant.bodytemperature + tempdifference*(timefraction),targettemperature) else - connected.occupant.bodytemperature = max(connected.occupant.bodytemperature - tempdifference*(timefraction),targettemperature) + occupant.bodytemperature = max(occupant.bodytemperature - tempdifference*(timefraction),targettemperature) else - switch(connected.setting) + switch(setting) if("Thermoregulate") - connected.occupant.bodytemperature = (T0C + 37) - connected.occupant.sleeping = 0 - connected.occupant.paralysis = 0 - connected.go_out() + occupant.bodytemperature = (T0C + 37) + occupant.sleeping = 0 + occupant.paralysis = 0 + go_out() if("Rare") - qdel(connected.occupant) - connected.occupant = null + qdel(occupant) + occupant = null for(var/i = 1;i < 5;i++) - new /obj/item/weapon/reagent_containers/food/snacks/soylentgreen(connected.loc) + new /obj/item/weapon/reagent_containers/food/snacks/soylentgreen(loc) if("Medium") - qdel(connected.occupant) - connected.occupant = null + qdel(occupant) + occupant = null for(var/i = 1;i < 5;i++) - new /obj/item/weapon/reagent_containers/food/snacks/badrecipe(connected.loc) + new /obj/item/weapon/reagent_containers/food/snacks/badrecipe(loc) if("Well Done") - qdel(connected.occupant) - connected.occupant = null - var/obj/effect/decal/cleanable/ash/ashed = new /obj/effect/decal/cleanable/ash(connected.loc) - ashed.layer = src.layer + 0.01 - playsound(get_turf(src), 'sound/machines/ding.ogg', 50, 1) - connected.on = 0 - if(connected.occupant) - if(ishuman(connected.occupant)) - var/mob/living/carbon/human/H = connected.occupant + qdel(occupant) + occupant = null + var/obj/effect/decal/cleanable/ash/ashed = new /obj/effect/decal/cleanable/ash(loc) + ashed.layer = layer + 0.01 + playsound(src, 'sound/machines/ding.ogg', 50, 1) + on = FALSE + if(occupant) + if(ishuman(occupant)) + var/mob/living/carbon/human/H = occupant if(isdiona(H)) if(H.h_style != "Popped Hair") to_chat(H, "Your head pops!") - playsound(get_turf(src), 'sound/effects/pop.ogg', 50, 1) + playsound(src, 'sound/effects/pop.ogg', 50, 1) H.h_style = "Popped Hair" H.update_hair() - connected.go_out() - connected.update_icon() - -/obj/machinery/sleep_console/mancrowave_console/MouseDrop(over_object, src_location, var/turf/over_location, src_control, over_control, params) - connected.MouseDrop(over_object, src_location, over_location, src_control, over_control, params) - -/obj/machinery/sleep_console/mancrowave_console/MouseDrop_T(atom/movable/O as mob|obj, mob/user as mob) - connected.MouseDrop_T(O,user) - -/obj/machinery/sleep_console/mancrowave_console/attackby(obj/item/weapon/W as obj, mob/user as mob) - connected.attackby(W,user) + else if(isjusthuman(H) && Holiday == APRIL_FOOLS_DAY) + H.GALize() + go_out() + update_icon() diff --git a/code/game/machinery/adv_med.dm b/code/game/machinery/adv_med.dm index b6ba436af7f..059dfdc4c39 100644 --- a/code/game/machinery/adv_med.dm +++ b/code/game/machinery/adv_med.dm @@ -1,17 +1,12 @@ -// Pretty much everything here is stolen from the dna scanner FYI - - /obj/machinery/bodyscanner name = "body scanner" - icon = 'icons/obj/Cryogenic2.dmi' + icon = 'icons/obj/cryogenics3.dmi' icon_state = "body_scanner_0" density = 1 anchored = 1 idle_power_usage = 125 active_power_usage = 250 - var/orient = "LEFT" var/scanning = 1 - var/obj/machinery/body_scanconsole/connected = null //This will save us a lot of locates machine_flags = SCREWTOGGLE | CROWDESTROY | EJECTNOTDEL component_parts = newlist( /obj/item/weapon/circuitboard/fullbodyscanner, @@ -24,57 +19,23 @@ light_color = LIGHT_COLOR_GREEN light_range_on = 3 light_power_on = 2 + var/known_implants = list(/obj/item/weapon/implant/chem, /obj/item/weapon/implant/death_alarm, /obj/item/weapon/implant/loyalty, /obj/item/weapon/implant/tracking) + var/delete + var/temphtml + flags = FPRINT | HEAR /obj/machinery/bodyscanner/New() ..() + if(map.nameShort == "deff") + icon = 'maps/defficiency/medbay.dmi' RefreshParts() - spawn( 5 ) - var/turf/t - world.log << "DEBUG: Beginning body scanner console checking/auto-generation for scanner [src] at [src.loc.x],[src.loc.y],[src.loc.z]..." - if(orient == "RIGHT") - update_icon() - t = get_step(get_turf(src), WEST) - // generate_console(get_step(get_turf(src), WEST)) - else - t = get_step(get_turf(src), EAST) - // generate_console(get_step(get_turf(src), EAST)) - ASSERT(t) - var/obj/machinery/body_scanconsole/c = locate() in t.contents - if(c) - connected = c - c.connected = src - else - world.log << "DEBUG: generating console at [t.loc.x],[t.loc.y],[t.loc.z] for scanner at [src.loc.x],[src.loc.y],[src.loc.z]" - generate_console(t) - return - return - -/obj/machinery/bodyscanner/proc/generate_console(turf/T as turf) - if(connected) - connected.orient = src.orient - connected.update_icon() - return 1 - if(!T.density) - connected = new /obj/machinery/body_scanconsole(T) - connected.orient = src.orient - connected.update_icon() - return 1 - else - return 0 /obj/machinery/bodyscanner/Destroy() - go_out() //Eject everything - - . = ..() - - if(connected) - connected.connected = null - qdel(connected) - connected = null + ..() /obj/machinery/bodyscanner/update_icon() - icon_state = "body_scanner_[occupant ? "1" : "0"][orient == "LEFT" ? null : "-r"]" + icon_state = "body_scanner_[occupant ? "1" : "0"]" /obj/machinery/bodyscanner/RefreshParts() var/T = 0 @@ -84,7 +45,7 @@ /obj/machinery/bodyscanner/power_change() ..() - if(!(stat & (BROKEN|NOPOWER)) && src.occupant) + if(!(stat & (BROKEN|NOPOWER)) && occupant) set_light(light_range_on, light_power_on) else set_light(0) @@ -110,7 +71,7 @@ return if(isrobot(user)) var/mob/living/silicon/robot/robit = usr - if(istype(robit) && !istype(robit.module, /obj/item/weapon/robot_module/medical)) + if(!(robit.module && (robit.module.quirk_flags & MODULE_CAN_HANDLE_MEDICAL))) to_chat(user, "You do not have the means to do this!") return var/mob/living/L = O @@ -130,12 +91,11 @@ L.forceMove(src) L.reset_view() - src.occupant = L + occupant = L update_icon() for(var/obj/OO in src) - OO.forceMove(src.loc) - //Foreach goto(154) - src.add_fingerprint(user) + OO.forceMove(loc) + add_fingerprint(user) if(!(stat & (BROKEN|NOPOWER))) set_light(light_range_on, light_power_on) return @@ -148,7 +108,7 @@ return if(isrobot(usr)) var/mob/living/silicon/robot/robit = usr - if(istype(robit) && !istype(robit.module, /obj/item/weapon/robot_module/medical)) + if(!(robit.module && (robit.module.quirk_flags & MODULE_CAN_HANDLE_MEDICAL))) to_chat(usr, "You do not have the means to do this!") return if(!istype(over_location) || over_location.density) @@ -234,25 +194,6 @@ return ..() /obj/machinery/bodyscanner/attackby(obj/item/weapon/W as obj, user as mob) - if(iswrench(W) && !occupant) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) - if(orient == "RIGHT") - orient = "LEFT" - if(generate_console(get_step(get_turf(src), EAST))) - update_icon() - else - orient = "RIGHT" - to_chat(user, "There is no space!") - generate_console(get_step(get_turf(src), WEST)) - else - orient = "RIGHT" - if(generate_console(get_step(get_turf(src), WEST))) - update_icon() - else - orient = "LEFT" - visible_message("There is no space!","[user] wants to be hardcore, but his CMO won't let him.") - generate_console(get_step(get_turf(src), EAST)) - return if(!istype(W, /obj/item/weapon/grab)) return ..() var/obj/item/weapon/grab/G = W @@ -310,120 +251,63 @@ qdel(src) -/obj/machinery/body_scanconsole - var/obj/machinery/bodyscanner/connected - var/known_implants = list(/obj/item/weapon/implant/chem, /obj/item/weapon/implant/death_alarm, /obj/item/weapon/implant/loyalty, /obj/item/weapon/implant/tracking) - var/delete - var/temphtml - name = "body scanner console" - icon = 'icons/obj/Cryogenic2.dmi' - icon_state = "body_scannerconsole" - density = 1 - anchored = 1 - var/orient = "LEFT" - flags = FPRINT | HEAR - -/obj/machinery/body_scanconsole/New() - ..() - spawn(5) - if(orient == "RIGHT") - icon_state = "body_scannerconsole-r" - src.connected = locate(/obj/machinery/bodyscanner, get_step(src, EAST)) - else - src.connected = locate(/obj/machinery/bodyscanner, get_step(src, WEST)) - return - -/obj/machinery/body_scanconsole/update_icon() - icon_state = "body_scannerconsole[stat & NOPOWER ? "-p" : null][orient == "LEFT" ? null : "-r"]" - -/obj/machinery/body_scanconsole/ex_act(severity) - switch(severity) - if(1.0) - qdel(src) - return - if(2.0) - if (prob(50)) - qdel(src) - return - else - return - -/obj/machinery/body_scanconsole/blob_act() - if(prob(50)) - qdel(src) - -/obj/machinery/body_scanconsole/power_change() - if(powered()) - stat &= ~NOPOWER - else - spawn(rand(0, 15)) - stat |= NOPOWER - update_icon() - -/obj/machinery/body_scanconsole/process() +/obj/machinery/bodyscanner/process() if (stat & (BROKEN | NOPOWER | MAINT | EMPED)) use_power = 0 return - - if (connected && connected.occupant) + if (occupant) use_power = 2 else use_power = 1 -/obj/machinery/body_scanconsole/attack_paw(user as mob) - return src.attack_hand(user) +/obj/machinery/bodyscanner/attack_paw(mob/user) + return attack_hand(user) -/obj/machinery/body_scanconsole/attack_ai(user as mob) - src.add_hiddenprint(user) - return src.attack_hand(user) +/obj/machinery/bodyscanner/attack_ai(mob/user) + add_hiddenprint(user) + return attack_hand(user) -/obj/machinery/body_scanconsole/attack_hand(user as mob) +/obj/machinery/bodyscanner/attack_hand(mob/user) if(..()) return - if(stat & (NOPOWER|BROKEN)) - return - if(!connected || (connected.stat & (NOPOWER|BROKEN))) - to_chat(user, "This console is not connected to a functioning body scanner.") - return - if(!ishuman(connected.occupant)) + if(!ishuman(occupant)) to_chat(user, "This device can only scan compatible lifeforms.") return + if(!isobserver(user) && (user.loc == src || (!Adjacent(user)&&!issilicon(user)) || user.incapacitated())) + return + var/dat if(src.delete && src.temphtml) //Window in buffer but its just simple message, so nothing src.delete = src.delete else if(!src.delete && src.temphtml) //Window in buffer - its a menu, dont add clear message dat = text("[]

Main Menu", src.temphtml, src) else - if(src.connected) //Is something connected? - dat = format_occupant_data(src.connected.get_occupant_data()) - dat += "
Print
" - else - dat = "Error: No Body Scanner connected." + dat = format_occupant_data(get_occupant_data()) + dat += "
Print
" dat += text("
Close", user) user << browse(dat, "window=scanconsole;size=430x600") return -/obj/machinery/body_scanconsole/Topic(href, href_list) +/obj/machinery/bodyscanner/Topic(href, href_list) if(..()) return + if(usr.loc == src) + return + if(href_list["print"]) - if(!src.connected) - to_chat(usr, "[bicon(src)]Error: No body scanner connected.") - return - var/mob/living/carbon/human/occupant = src.connected.occupant - if(!src.connected.occupant) - to_chat(usr, "[bicon(src)]\The [src.connected] is empty.") + if(!occupant) + to_chat(usr, "[bicon(src)]\The [src] is empty.") return if(!istype(occupant,/mob/living/carbon/human)) - to_chat(usr, "[bicon(src)]\The [src.connected] cannot scan that lifeform.") + to_chat(usr, "[bicon(src)]\The [src] cannot scan that lifeform.") return - var/obj/item/weapon/paper/R = new(src.loc) + var/obj/item/weapon/paper/R = new(loc) R.name = "paper - 'body scan report'" - R.info = format_occupant_data(src.connected.get_occupant_data()) + R.info = format_occupant_data(get_occupant_data()) /obj/machinery/bodyscanner/proc/get_occupant_data() @@ -440,6 +324,8 @@ "oxyloss" = H.getOxyLoss(), "toxloss" = H.getToxLoss(), "rads" = H.radiation, + "radtick" = H.rad_tick, + "radstage" = H.get_rad_stage(), "cloneloss" = H.getCloneLoss(), "brainloss" = H.getBrainLoss(), "paralysis" = H.paralysis, @@ -467,7 +353,7 @@ return occupant_data -/obj/machinery/body_scanconsole/proc/format_occupant_data(var/list/occ) +/obj/machinery/bodyscanner/proc/format_occupant_data(var/list/occ) var/dat = "Scan performed at [occ["stationtime"]]
" dat += "Occupant Statistics:
" var/aux @@ -487,6 +373,8 @@ dat += text("[]\t-Burn Severity %: []


", (occ["fireloss"] < 60 ? "" : ""), occ["fireloss"]) dat += text("[]\tRadiation Level %: []
", (occ["rads"] < 10 ?"" : ""), occ["rads"]) + if(occ["radtick"] > 0) + dat += text("Radiation sickness progression: [occ["radtick"]] Stage: [occ["radstage"]]
") dat += text("[]\tGenetic Tissue Damage %: []

", (occ["cloneloss"] < 1 ?"" : ""), occ["cloneloss"]) dat += text("[]\tApprox. Brain Damage %: []
", (occ["brainloss"] < 1 ?"" : ""), occ["brainloss"]) dat += text("Paralysis Summary %: [] ([] seconds left!)
", occ["paralysis"], round(occ["paralysis"] / 4)) @@ -514,7 +402,7 @@ dat += text("[]\tBicaridine: [] units
", (occ["bicaridine_amount"] < 30 ? "" : ""), occ["bicaridine_amount"]) dat += text("[]\tDexalin: [] units
", (occ["dexalin_amount"] < 30 ? "" : ""), occ["dexalin_amount"]) - if(connected.scanning>2) + if(scanning>2) for(var/datum/reagent/R in occ["all_chems"]) if(R.id == BLOOD || R.id == INAPROVALINE || R.id == STOXIN || R.id == DERMALINE || R.id == BICARIDINE || R.id == DEXALIN) continue //no repeats @@ -651,14 +539,14 @@ dat += text("Retinal misalignment detected.
") return dat -/obj/machinery/body_scanconsole/Hear(var/datum/speech/speech, var/rendered_speech="") - if(!src.connected || src.connected.scanning<3) +/obj/machinery/bodyscanner/Hear(var/datum/speech/speech, var/rendered_speech="") + if(scanning<3) return if(speech.speaker && !speech.frequency) if(findtext(speech.message, "print")) - if(!src.connected.occupant||!istype(src.connected.occupant,/mob/living/carbon/human)) + if(!occupant||!istype(occupant,/mob/living/carbon/human)) return say("Now outputting diagnostic.") var/obj/item/weapon/paper/R = new(src.loc) R.name = "paper - 'body scan report'" - R.info = format_occupant_data(src.connected.get_occupant_data()) \ No newline at end of file + R.info = format_occupant_data(get_occupant_data()) diff --git a/code/game/machinery/ai_slipper.dm b/code/game/machinery/ai_slipper.dm index 31f2df524a6..5f1cfb99e52 100644 --- a/code/game/machinery/ai_slipper.dm +++ b/code/game/machinery/ai_slipper.dm @@ -55,7 +55,8 @@ return user.set_machine(src) - var/t = "Foam Dispenser ([areaMaster.name])
" + var/area/this_area = get_area(src) + var/t = "Foam Dispenser ([this_area.name])
" if(src.locked && (!istype(user, /mob/living/silicon))) t += "(Swipe ID card to unlock control panel.)
" @@ -106,4 +107,4 @@ if(uses >= 0) cooldown_on = 0 src.power_change() - return \ No newline at end of file + return diff --git a/code/game/machinery/airlock_control.dm b/code/game/machinery/airlock_control.dm index fbfd41334cf..c067535baa2 100644 --- a/code/game/machinery/airlock_control.dm +++ b/code/game/machinery/airlock_control.dm @@ -1,7 +1,7 @@ #define AIRLOCK_CONTROL_RANGE 8 // This code allows for airlocks to be controlled externally by setting an id_tag and comm frequency (disables ID access) -obj/machinery/door/airlock +/obj/machinery/door/airlock var/id_tag var/frequency var/shockedby = list() @@ -9,7 +9,7 @@ obj/machinery/door/airlock explosion_resistance = 15 -obj/machinery/door/airlock/receive_signal(datum/signal/signal) +/obj/machinery/door/airlock/receive_signal(datum/signal/signal) if(!signal || signal.encryption) return @@ -236,7 +236,7 @@ obj/machinery/airlock_sensor/Topic(href,href_list) if(!issilicon(usr)) if(!istype(usr.get_active_hand(), /obj/item/device/multitool)) - testing("Not silicon, not using a multitool.") +// testing("Not silicon, not using a multitool.") return if("set_freq" in href_list) var/newfreq=frequency @@ -376,7 +376,7 @@ obj/machinery/access_button/Topic(href,href_list) if(!issilicon(usr)) if(!istype(usr.get_active_hand(), /obj/item/device/multitool)) - testing("Not silicon, not using a multitool.") +// testing("Not silicon, not using a multitool.") return var/obj/item/device/multitool/P = get_multitool(usr) diff --git a/code/game/machinery/alarm.dm b/code/game/machinery/alarm.dm index ee05f0f8d78..bbbdb5310f8 100644 --- a/code/game/machinery/alarm.dm +++ b/code/game/machinery/alarm.dm @@ -79,9 +79,9 @@ var/list/TLV = list() machine_flags = WIREJACK - holomap = TRUE - auto_holomap = TRUE +/obj/machinery/alarm/supports_holomap() + return TRUE /obj/machinery/alarm/xenobio preset = AALARM_PRESET_HUMAN @@ -95,11 +95,13 @@ /obj/machinery/alarm/vox preset = AALARM_PRESET_VOX - req_access = list() + req_one_access = list() + req_access = list(access_trade) /obj/machinery/alarm/proc/apply_preset(var/no_cycle_after=0) // Propogate settings. - for (var/obj/machinery/alarm/AA in areaMaster) + var/area/this_area = get_area(src) + for (var/obj/machinery/alarm/AA in this_area) if ( !(AA.stat & (NOPOWER|BROKEN)) && !AA.shorted && AA.preset != src.preset) AA.preset=preset apply_preset(1) // Only this air alarm should send a cycle. @@ -165,8 +167,9 @@ ..() /obj/machinery/alarm/proc/first_run() - area_uid = areaMaster.uid - name = "[areaMaster.name] Air Alarm" + var/area/this_area = get_area(src) + area_uid = this_area.uid + name = "[this_area.name] Air Alarm" // breathable air according to human/Life() /* @@ -182,6 +185,7 @@ /obj/machinery/alarm/initialize() + add_self_to_holomap() set_frequency(frequency) if (!master_is_operating()) elect_master() @@ -215,7 +219,7 @@ if(target_temperature < T0C + MIN_TEMPERATURE) target_temperature = T0C + MIN_TEMPERATURE - var/datum/gas_mixture/gas = location.remove_air(0.25 * environment.total_moles) + var/datum/gas_mixture/gas = environment.remove_volume(0.25 * CELL_VOLUME) if(gas) var/heat_capacity = gas.heat_capacity() var/energy_used = min(abs(heat_capacity * (gas.temperature - target_temperature)), MAX_ENERGY_CHANGE) @@ -305,13 +309,15 @@ ) /obj/machinery/alarm/proc/master_is_operating() - return areaMaster.master_air_alarm && !(areaMaster.master_air_alarm.stat & (NOPOWER|BROKEN)) + var/area/this_area = get_area(src) + return this_area.master_air_alarm && !(this_area.master_air_alarm.stat & (NOPOWER|BROKEN)) /obj/machinery/alarm/proc/elect_master() - for (var/obj/machinery/alarm/AA in areaMaster) + var/area/this_area = get_area(src) + for (var/obj/machinery/alarm/AA in this_area) if (!(AA.stat & (NOPOWER|BROKEN))) - areaMaster.master_air_alarm = AA + this_area.master_air_alarm = AA return 1 return 0 @@ -332,8 +338,8 @@ if((stat & (NOPOWER|BROKEN)) || shorted) icon_state = "alarmp" return - - switch(max(local_danger_level, areaMaster.atmosalm-1)) + var/area/this_area = get_area(src) + switch(max(local_danger_level, this_area.atmosalm-1)) if (0) icon_state = "alarm0" if (1) @@ -342,13 +348,14 @@ icon_state = "alarm1" /obj/machinery/alarm/receive_signal(datum/signal/signal) - if(stat & (NOPOWER|BROKEN) || !areaMaster) + var/area/this_area = get_area(src) + if(stat & (NOPOWER|BROKEN) || !this_area) return - if (areaMaster.master_air_alarm != src) + if (this_area.master_air_alarm != src) if (master_is_operating()) return elect_master() - if (areaMaster.master_air_alarm != src) + if (this_area.master_air_alarm != src) return if(!signal || signal.encryption) return @@ -361,35 +368,37 @@ return var/dev_type = signal.data["device"] - if(!(id_tag in areaMaster.air_scrub_names) && !(id_tag in areaMaster.air_vent_names)) + if(!(id_tag in this_area.air_scrub_names) && !(id_tag in this_area.air_vent_names)) register_env_machine(id_tag, dev_type) if(dev_type == "AScr") - areaMaster.air_scrub_info[id_tag] = signal.data + this_area.air_scrub_info[id_tag] = signal.data else if(dev_type == "AVP") - areaMaster.air_vent_info[id_tag] = signal.data + this_area.air_vent_info[id_tag] = signal.data /obj/machinery/alarm/proc/register_env_machine(var/m_id, var/device_type) var/new_name + var/area/this_area = get_area(src) if (device_type=="AVP") - new_name = "[areaMaster.name] Vent Pump #[areaMaster.air_vent_names.len+1]" - areaMaster.air_vent_names[m_id] = new_name + new_name = "[this_area.name] Vent Pump #[this_area.air_vent_names.len+1]" + this_area.air_vent_names[m_id] = new_name else if (device_type=="AScr") - new_name = "[areaMaster.name] Air Scrubber #[areaMaster.air_scrub_names.len+1]" - areaMaster.air_scrub_names[m_id] = new_name + new_name = "[this_area.name] Air Scrubber #[this_area.air_scrub_names.len+1]" + this_area.air_scrub_names[m_id] = new_name else return spawn (10) send_signal(m_id, list("init" = new_name) ) /obj/machinery/alarm/proc/refresh_all() - for(var/id_tag in areaMaster.air_vent_names) - var/list/I = areaMaster.air_vent_info[id_tag] + var/area/this_area = get_area(src) + for(var/id_tag in this_area.air_vent_names) + var/list/I = this_area.air_vent_info[id_tag] if (I && I["timestamp"]+AALARM_REPORT_TIMEOUT/2 > world.time) continue send_signal(id_tag, list("status") ) - for(var/id_tag in areaMaster.air_scrub_names) - var/list/I = areaMaster.air_scrub_info[id_tag] + for(var/id_tag in this_area.air_scrub_names) + var/list/I = this_area.air_scrub_info[id_tag] if (I && I["timestamp"]+AALARM_REPORT_TIMEOUT/2 > world.time) continue send_signal(id_tag, list("status") ) @@ -419,35 +428,36 @@ /obj/machinery/alarm/proc/apply_mode() var/list/current_pressures = TLV["pressure"] var/target_pressure = (current_pressures[2] + current_pressures[3])/2 + var/area/this_area = get_area(src) switch(mode) if(AALARM_MODE_SCRUBBING) - for(var/device_id in areaMaster.air_scrub_names) + for(var/device_id in this_area.air_scrub_names) send_signal(device_id, list("power"= 1, "co2_scrub"= 1, "o2_scrub"=(preset==AALARM_PRESET_VOX), "n2_scrub"=0, "scrubbing"= 1, "panic_siphon"= 0) ) - for(var/device_id in areaMaster.air_vent_names) + for(var/device_id in this_area.air_vent_names) send_signal(device_id, list("power"= 1, "checks"= 1, "set_external_pressure"= target_pressure) ) if(AALARM_MODE_PANIC, AALARM_MODE_CYCLE) - for(var/device_id in areaMaster.air_scrub_names) + for(var/device_id in this_area.air_scrub_names) send_signal(device_id, list("power"= 1, "panic_siphon"= 1) ) - for(var/device_id in areaMaster.air_vent_names) + for(var/device_id in this_area.air_vent_names) send_signal(device_id, list("power"= 0) ) if(AALARM_MODE_REPLACEMENT) - for(var/device_id in areaMaster.air_scrub_names) + for(var/device_id in this_area.air_scrub_names) send_signal(device_id, list("power"= 1, "panic_siphon"= 1) ) - for(var/device_id in areaMaster.air_vent_names) + for(var/device_id in this_area.air_vent_names) send_signal(device_id, list("power"= 1, "checks"= 1, "set_external_pressure"= target_pressure) ) if(AALARM_MODE_FILL) - for(var/device_id in areaMaster.air_scrub_names) + for(var/device_id in this_area.air_scrub_names) send_signal(device_id, list("power"= 0) ) - for(var/device_id in areaMaster.air_vent_names) + for(var/device_id in this_area.air_vent_names) send_signal(device_id, list("power"= 1, "checks"= 1, "set_external_pressure"= target_pressure) ) if(AALARM_MODE_OFF) - for(var/device_id in areaMaster.air_scrub_names) + for(var/device_id in this_area.air_scrub_names) send_signal(device_id, list("power"= 0) ) - for(var/device_id in areaMaster.air_vent_names) + for(var/device_id in this_area.air_vent_names) send_signal(device_id, list("power"= 0) ) // This sets our danger level, and, if it's changed, forces a new election of danger levels. @@ -455,7 +465,8 @@ if(local_danger_level==new_danger_level) return local_danger_level=new_danger_level - if(areaMaster.updateDangerLevel()) + var/area/this_area = get_area(src) + if(this_area.updateDangerLevel()) post_alert(new_danger_level) /obj/machinery/alarm/proc/post_alert(alert_level) @@ -466,7 +477,8 @@ var/datum/signal/alert_signal = getFromPool(/datum/signal) alert_signal.source = src alert_signal.transmission_method = 1 - alert_signal.data["zone"] = areaMaster.name + var/area/this_area = get_area(src) + alert_signal.data["zone"] = this_area.name alert_signal.data["type"] = "Atmospheric" if(alert_level==2) @@ -479,10 +491,12 @@ frequency.post_signal(src, alert_signal) /obj/machinery/alarm/proc/air_doors_close(manual) - areaMaster.CloseFirelocks() + var/area/this_area = get_area(src) + this_area.CloseFirelocks() /obj/machinery/alarm/proc/air_doors_open(manual) - areaMaster.OpenFirelocks() + var/area/this_area = get_area(src) + this_area.OpenFirelocks() /////////////// //END HACKING// @@ -583,8 +597,7 @@ return data /obj/machinery/alarm/proc/get_nano_data(mob/user, fromAtmosConsole=0) - - + var/area/this_area = get_area(src) var/data[0] data["air"]=ui_air_status() data["alarmActivated"]=alarmActivated //|| local_danger_level==2 @@ -598,7 +611,7 @@ data["rcon"]=rcon_setting data["target_temp"] = target_temperature - T0C - data["atmos_alarm"] = areaMaster.atmosalm + data["atmos_alarm"] = this_area.atmosalm data["modes"] = list( AALARM_MODE_SCRUBBING = list("name"="Filtering", "desc"="Scrubs out contaminants"),\ AALARM_MODE_REPLACEMENT = list("name"="Replace Air", "desc"="Siphons out air while replacing"),\ @@ -615,11 +628,11 @@ data["screen"]=screen var/list/vents=list() - if(areaMaster.air_vent_names.len) - for(var/id_tag in areaMaster.air_vent_names) + if(this_area.air_vent_names.len) + for(var/id_tag in this_area.air_vent_names) var/vent_info[0] - var/long_name = areaMaster.air_vent_names[id_tag] - var/list/vent_data = areaMaster.air_vent_info[id_tag] + var/long_name = this_area.air_vent_names[id_tag] + var/list/vent_data = this_area.air_vent_info[id_tag] if(!vent_data) continue vent_info["id_tag"]=id_tag @@ -629,10 +642,10 @@ data["vents"]=vents var/list/scrubbers=list() - if(areaMaster.air_scrub_names.len) - for(var/id_tag in areaMaster.air_scrub_names) - var/long_name = areaMaster.air_scrub_names[id_tag] - var/list/scrubber_data = areaMaster.air_scrub_info[id_tag] + if(this_area.air_scrub_names.len) + for(var/id_tag in this_area.air_scrub_names) + var/long_name = this_area.air_scrub_names[id_tag] + var/list/scrubber_data = this_area.air_scrub_info[id_tag] if(!scrubber_data) continue scrubber_data["id_tag"]=id_tag @@ -766,13 +779,15 @@ if(href_list["atmos_alarm"]) alarmActivated=1 - areaMaster.updateDangerLevel() + var/area/this_area = get_area(src) + this_area.updateDangerLevel() update_icon() return 1 if(href_list["atmos_reset"]) alarmActivated=0 - areaMaster.updateDangerLevel() + var/area/this_area = get_area(src) + this_area.updateDangerLevel() update_icon() return 1 @@ -807,7 +822,7 @@ if(isscrewdriver(W)) // Opening that Air Alarm up. wiresexposed = !wiresexposed to_chat(user, "The wires have been [wiresexposed ? "exposed" : "unexposed"].") - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 50, 1) update_icon() return @@ -817,7 +832,7 @@ buildstage = 1 update_icon() user.visible_message("[user] has cut the wiring from \the [src]!", "You have cut the last of the wiring from \the [src].") - playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 50, 1) + playsound(src, 'sound/items/Wirecutter.ogg', 50, 1) getFromPool(/obj/item/stack/cable_coil, get_turf(user), 5) return if(istype(W, /obj/item/weapon/card/id) || istype(W, /obj/item/device/pda))// trying to unlock the interface with an ID card @@ -839,10 +854,10 @@ to_chat(user, "You need more cable for this!") return for(var/i, i<= 5, i++) - wires.UpdateCut(i,1) + wires.UpdateCut(i, 1, user) to_chat(user, "You wire \the [src]!") - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) coil.use(5) buildstage = 2 update_icon() @@ -851,7 +866,7 @@ else if(iscrowbar(W)) to_chat(user, "You start prying out the circuit...") - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) + playsound(src, 'sound/items/Crowbar.ogg', 50, 1) if(do_after(user, src, 20) && buildstage == 1) to_chat(user, "You pry out the circuit!") new /obj/item/weapon/circuitboard/air_alarm(get_turf(user)) @@ -861,7 +876,7 @@ if(0) if(istype(W, /obj/item/weapon/circuitboard/air_alarm)) to_chat(user, "You insert the circuit!") - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) qdel(W) buildstage = 1 update_icon() @@ -870,7 +885,7 @@ else if(iswrench(W)) to_chat(user, "You remove the air alarm assembly from the wall!") new /obj/item/mounted/frame/alarm_frame(get_turf(user)) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + playsound(src, 'sound/items/Ratchet.ogg', 50, 1) qdel(src) return @@ -918,8 +933,12 @@ FIRE ALARM var/wiresexposed = 0 var/buildstage = 2 // 2 = complete, 1 = no wires, 0 = circuit gone - holomap = TRUE - auto_holomap = TRUE +/obj/machinery/firealarm/supports_holomap() + return TRUE + +/obj/machinery/firealarm/initialize() + ..() + add_self_to_holomap() /obj/machinery/firealarm/update_icon() overlays.len = 0 @@ -973,7 +992,7 @@ FIRE ALARM if (isscrewdriver(W) && buildstage == 2) wiresexposed = !wiresexposed to_chat(user, "The wires have been [wiresexposed ? "exposed" : "unexposed"].") - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 50, 1) update_icon() return @@ -983,10 +1002,10 @@ FIRE ALARM if (ismultitool(W)) src.detecting = !( src.detecting ) user.visible_message("[user] has [detecting ? "re" : "dis"]connected [src]'s detecting unit!", "You have [detecting ? "re" : "dis"]reconnected [src]'s detecting unit.") - playsound(get_turf(src), 'sound/items/healthanalyzer.ogg', 50, 1) + playsound(src, 'sound/items/healthanalyzer.ogg', 50, 1) if(iswirecutter(W)) to_chat(user, "You begin to cut the wiring...") - playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 50, 1) + playsound(src, 'sound/items/Wirecutter.ogg', 50, 1) if (do_after(user, src, 50) && buildstage == 2 && wiresexposed) buildstage=1 user.visible_message("[user] has cut the wiring from \the [src]!", "You have cut the last of the wiring from \the [src].") @@ -1006,7 +1025,7 @@ FIRE ALARM else if(iscrowbar(W)) to_chat(user, "You start prying out the circuit...") - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) + playsound(src, 'sound/items/Crowbar.ogg', 50, 1) if (do_after(user, src, 20) && buildstage == 1) to_chat(user, "You pry out the circuit!") new /obj/item/weapon/circuitboard/fire_alarm(get_turf(user)) @@ -1015,7 +1034,7 @@ FIRE ALARM if(0) if(istype(W, /obj/item/weapon/circuitboard/fire_alarm)) to_chat(user, "You insert the circuit!") - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) qdel(W) buildstage = 1 update_icon() @@ -1023,7 +1042,7 @@ FIRE ALARM else if(iswrench(W)) to_chat(user, "You remove the fire alarm assembly from the wall!") new /obj/item/mounted/frame/firealarm(get_turf(user)) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + playsound(src, 'sound/items/Ratchet.ogg', 50, 1) qdel(src) return @@ -1068,9 +1087,9 @@ FIRE ALARM user.set_machine(src) var/d1 var/d2 + var/area/this_area = get_area(src) if (istype(user, /mob/living/carbon/human) || istype(user, /mob/living/silicon) || isobserver(user)) - - if (areaMaster.fire) + if (this_area.fire) d1 = text("Reset - Lockdown", src) else d1 = text("Alarm - Lockdown", src) @@ -1084,7 +1103,7 @@ FIRE ALARM user << browse(dat, "window=firealarm") onclose(user, "firealarm") else - if (areaMaster.fire) + if (this_area.fire) d1 = text("[]", src, stars("Reset - Lockdown")) else d1 = text("[]", src, stars("Alarm - Lockdown")) @@ -1132,21 +1151,24 @@ FIRE ALARM /obj/machinery/firealarm/proc/reset() if (!( src.working )) return - areaMaster.firereset() + var/area/this_area = get_area(src) + this_area.firereset() update_icon() /obj/machinery/firealarm/proc/alarm() if (!( src.working )) return - areaMaster.firealert() + var/area/this_area = get_area(src) + this_area.firealert() update_icon() - //playsound(get_turf(src), 'sound/ambience/signal.ogg', 75, 0) + //playsound(src, 'sound/ambience/signal.ogg', 75, 0) var/global/list/firealarms = list() //shrug /obj/machinery/firealarm/New(loc, dir, building) ..() - name = "[areaMaster.name] fire alarm" + var/area/this_area = get_area(src) + name = "[this_area.name] fire alarm" if(loc) src.forceMove(loc) @@ -1187,7 +1209,8 @@ var/global/list/firealarms = list() //shrug /obj/machinery/partyalarm/New() ..() - name = "[areaMaster.name] party alarm" + var/area/this_area = get_area(src) + name = "[this_area.name] party alarm" /obj/machinery/partyalarm/attack_paw(mob/user as mob) return attack_hand(user) @@ -1199,8 +1222,9 @@ var/global/list/firealarms = list() //shrug user.machine = src var/d1 var/d2 + var/area/this_area = get_area(src) if (istype(user, /mob/living/carbon/human) || istype(user, /mob/living/silicon/ai)) - if (areaMaster.party) + if (this_area.party) d1 = text("No Party :(", src) else d1 = text("PARTY!!!", src) @@ -1214,7 +1238,7 @@ var/global/list/firealarms = list() //shrug user << browse(dat, "window=partyalarm") onclose(user, "partyalarm") else - if (areaMaster.fire) + if (this_area.fire) d1 = text("[]", src, stars("No Party :(")) else d1 = text("[]", src, stars("PARTY!!!")) @@ -1232,13 +1256,15 @@ var/global/list/firealarms = list() //shrug /obj/machinery/partyalarm/proc/reset() if (!( working )) return - areaMaster.partyreset() + var/area/this_area = get_area(src) + this_area.partyreset() return /obj/machinery/partyalarm/proc/alarm() if (!( working )) return - areaMaster.partyalert() + var/area/this_area = get_area(src) + this_area.partyalert() return /obj/machinery/partyalarm/Topic(href, href_list) diff --git a/code/game/machinery/antiquemattersynth.dm b/code/game/machinery/antiquemattersynth.dm new file mode 100644 index 00000000000..fa021ff3be7 --- /dev/null +++ b/code/game/machinery/antiquemattersynth.dm @@ -0,0 +1,168 @@ + +var/global/list/synth_designs = list( +list("category" = "resources", "name" = "sulfuric acid bottle", "path" = /obj/item/weapon/reagent_containers/glass/bottle/sacid, "cost" = 100), +list("category" = "resources", "name" = "20 iron", "path" = /obj/item/stack/sheet/metal/bigstack, "cost" = 100), +list("category" = "resources", "name" = "20 glass", "path" = /obj/item/stack/sheet/glass/glass/bigstack, "cost" = 100), +list("category" = "resources", "name" = "20 plasteel", "path" = /obj/item/stack/sheet/plasteel/bigstack, "cost" = 100), +list("category" = "resources", "name" = "20 plasmaglass", "path" = /obj/item/stack/sheet/glass/plasmaglass/bigstack, "cost" = 100), +list("category" = "resources", "name" = "20 wood", "path" = /obj/item/stack/sheet/wood/bigstack, "cost" = 100), +list("category" = "resources", "name" = "20 plastic", "path" = /obj/item/stack/sheet/mineral/plastic/bigstack, "cost" = 200), +list("category" = "resources", "name" = "aluminum foam grenade", "path" = /obj/item/weapon/grenade/chem_grenade/metalfoam, "cost" = 100), +list("category" = "resources", "name" = "iron foam grenade", "path" = /obj/item/weapon/grenade/chem_grenade/ironfoam, "cost" = 100), +list("category" = "resources", "name" = "camera assembly", "path" = /obj/item/weapon/camera_assembly, "cost" = 100), + + +list("category" = "tools", "name" = "socket wrench", "path" = /obj/item/weapon/wrench/socket, "cost" = 1000), //One gigawatt +list("category" = "tools", "name" = "foam extinguisher", "path" = /obj/item/weapon/extinguisher/foam, "cost" = 1000), +list("category" = "tools", "name" = "empty O2 tank", "path" = /obj/item/weapon/tank/oxygen/empty, "cost" = 1000), +list("category" = "tools", "name" = "empty plasma tank", "path" = /obj/item/weapon/tank/plasma/empty, "cost" = 1000), +list("category" = "tools", "name" = "flare gun ammunition", "path" =/obj/item/ammo_storage/box/flare, cost = 700), +list("category" = "tools", "name" = "flare gun", "path" =/obj/item/weapon/gun/projectile/flare, cost = 2000), + +list("category" = "machinery", "name" = "air pump", "path" = /obj/machinery/portable_atmospherics/pump, "cost" = 500), +list("category" = "machinery", "name" = "portable scrubber", "path" = /obj/machinery/portable_atmospherics/scrubber, "cost" = 500), +list("category" = "machinery", "name" = "space heater", "path" = /obj/machinery/space_heater, "cost" = 500), +list("category" = "machinery", "name" = "air conditioner", "path" = /obj/machinery/space_heater/air_conditioner, "cost" = 500), +list("category" = "machinery", "name" = "cart", "path" = /obj/machinery/cart/cargo, "cost" = 200), +list("category" = "machinery", "name" = "tractor", "path" = /obj/structure/bed/chair/vehicle/tractor, "cost" = 2000), +list("category" = "machinery", "name" = "rad collector", "path" = /obj/machinery/power/rad_collector, "cost" = 1000), +list("category" = "machinery", "name" = "emitter", "path" = /obj/machinery/power/emitter, "cost" = 1000), +list("category" = "machinery", "name" = "prism", "path" = /obj/machinery/prism, "cost" = 2000), +list("category" = "machinery", "name" = "MSGS", "path" = /obj/machinery/atmospherics/binary/msgs/unanchored, "cost" = 2000), +) + +/obj/machinery/power/antiquesynth + name = "antique matter synthesizer" + desc = "An ancient piece of salvaged tech from a period before matter synthesizers were small enough to be moved around. This one is designed with industrial purposes in mind and consumes huge amounts of power." + + icon = 'icons/obj/xenoarchaeology.dmi' + icon_state = "scanner_0old" + + use_power = 1 + density = 1 + anchored = 0 + machine_flags = WRENCHMOVE | FIXED2WORK | EMAGGABLE + req_access = list(access_engine) + + var/consumption = 0 //How much are we set to draw off the net? Clamped between 0 and 2 GIGAWATT (2,000,000,000 Watts) + var/on = 0 + var/charge = 0 //How much we've stored. Also capped at 2 GIGAWATT. + var/charged_last_tick = 0 + var/category = "resources" //which list to display + var/list/categories = list(list("category" = "resources"), list("category" = "tools"), list("category" = "machinery")) //Yes it is necessary to write the list like this + +/obj/machinery/power/antiquesynth/proc/toggle_power() + on = !on + if(!get_powernet()) + on = FALSE + visible_message("The [src] buzzes and shuts off.") + update_icon() + +/obj/machinery/power/antiquesynth/update_icon() + return + //Maybe I'll add more? + +/obj/machinery/power/antiquesynth/process() + charged_last_tick = 0 + if(!on) + return + if(!anchored || !get_powernet()) + toggle_power() + return + if(charge >= 2*GIGAWATT) + charge = min(charge, 2*GIGAWATT) + return //We can't get more charged than this! + if(avail()>consumption) + charged_last_tick = 1 + charge += consumption + add_load(consumption) + nanomanager.update_uis(src) + +/obj/machinery/power/antiquesynth/attack_ai(mob/user) + to_chat(user, "You aren't equipped to interface with technology this old!") + +/obj/machinery/power/antiquesynth/attack_hand(mob/user) + return ui_interact(user) + +/obj/machinery/power/antiquesynth/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open=NANOUI_FOCUS) + if (gcDestroyed || !get_turf(src) || !anchored) + if(!ui) + ui = nanomanager.get_open_ui(user, src, ui_key) + if(ui) + ui.close() + return + + // this is the data which will be sent to the ui + var/data[0] + data["name"] = name + data["powered"] = !(stat & NOPOWER) + data["charge"] = charge/MEGAWATT //Charge given in megawatts not watts + data["charging"] = charged_last_tick + data["consumption"] = round(consumption/MEGAWATT,0.1) //ditto + data["active"] = on + data["synthList"] = synth_designs + data["selectedCategory"] = category + data["categories"] = categories + + // update the ui if it exists, returns null if no ui is passed/found + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) + if (!ui) + // the ui does not exist, so we'll create a new() one + // for a list of parameters and their descriptions see the code docs in \code\\modules\nano\nanoui.dm + ui = new(user, src, ui_key, "antiquems.tmpl", "Antique Matter Synthesizer", 520, 460) + // when the ui is first opened this is the data it will use + ui.set_initial_data(data) + // open the new ui window + ui.open() + // auto update every Master Controller tick + //ui.set_auto_update(1) + +/obj/machinery/power/antiquesynth/Topic(href, href_list) + if(..()) + return + if(usr.incapacitated() || !Adjacent(usr) || !usr.dexterity_check()) + return + if(!allowed(usr) && !emagged) + to_chat(usr,"Access denied.") + return + if(issilicon(usr)) + to_chat(usr,"You are not compatible with this device.") + return + + if(href_list["toggle"]) + toggle_power() + if(href_list["set_draw"]) + consumption = input("Megajoules to draw per tick: ", "1MW = 1000kW = 1000000W", consumption/MEGAWATT) as num + consumption = round(Clamp(consumption*MEGAWATT, 0, 2*GIGAWATT)) //we're storing the actual number of watts but only displaying the users the mw conversion + if(href_list["synth"]) + locate_data(href_list["synth"]) //Even though the list contains a path, hrefs only pass text so let's use name here instead of path + if(href_list["category"]) + category = href_list["category"] + update_icon() + return 1 + +/obj/machinery/power/antiquesynth/proc/locate_data(var/name) + for(var/element in synth_designs) + if(element["name"] == name) + synth(element["path"],element["cost"]) + return //Exit + +/obj/machinery/power/antiquesynth/proc/synth(var/obj/O,var/cost) + if(charge >= cost*MEGAWATT) + charge = max(0, charge - cost*MEGAWATT) + nanomanager.update_uis(src) + new O(get_turf(src)) + else + playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0) + spark(src, 10, FALSE) + + +/obj/machinery/power/antiquesynth/wrenchAnchor(var/mob/user) + if(!..()) + return + if(anchored) + connect_to_network() + else + disconnect_from_network() + power_change() + update_icon() diff --git a/code/game/machinery/atmoalter/area_atmos_computer.dm b/code/game/machinery/atmoalter/area_atmos_computer.dm index ec5fd6fbeec..164f65aee95 100644 --- a/code/game/machinery/atmoalter/area_atmos_computer.dm +++ b/code/game/machinery/atmoalter/area_atmos_computer.dm @@ -127,7 +127,7 @@ var/turf/T = get_turf(src) if(!T.loc) return - var/area/A = get_area_master(T) + var/area/A = get_area(T) for(var/obj/machinery/portable_atmospherics/scrubber/huge/scrubber in machines) var/turf/T2 = get_turf(scrubber) if(T2 && T2.loc) diff --git a/code/game/machinery/atmoalter/canister.dm b/code/game/machinery/atmoalter/canister.dm index 2c6c9704bd3..4a5854c8f15 100644 --- a/code/game/machinery/atmoalter/canister.dm +++ b/code/game/machinery/atmoalter/canister.dm @@ -167,7 +167,7 @@ location.assume_air(air_contents) src.destroyed = 1 - playsound(get_turf(src), 'sound/effects/spray.ogg', 10, 1, -3) + playsound(src, 'sound/effects/spray.ogg', 10, 1, -3) setDensity(FALSE) update_icon() investigation_log(I_ATMOS, "was destoyed by excessive damage.") @@ -191,10 +191,13 @@ if(valve_open) var/datum/gas_mixture/environment + var/transfer_vol //A band-aid fix for the fact the equation used below doesn't work as intended if(holding) environment = holding.air_contents + transfer_vol = holding.volume else environment = loc.return_air() + transfer_vol = CELL_VOLUME var/env_pressure = environment.return_pressure() var/pressure_delta = min(release_pressure - env_pressure, (air_contents.return_pressure() - env_pressure)/2) @@ -202,7 +205,7 @@ var/transfer_moles = 0 if((air_contents.temperature > 0) && (pressure_delta > 0)) - transfer_moles = pressure_delta*environment.volume/(air_contents.temperature * R_IDEAL_GAS_EQUATION) + transfer_moles = pressure_delta * transfer_vol / (air_contents.temperature * R_IDEAL_GAS_EQUATION) //Actually transfer the gas var/datum/gas_mixture/removed = air_contents.remove(transfer_moles) @@ -303,7 +306,7 @@ "You slash away at \the [src]!") user.delayNextAttack(10) //Hold on there amigo investigation_log(I_ATMOS, "was slashed at by alien [key_name(user)]") - playsound(get_turf(src), 'sound/weapons/slice.ogg', 25, 1, -1) + playsound(src, 'sound/weapons/slice.ogg', 25, 1, -1) healthcheck() /obj/machinery/portable_atmospherics/canister/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open=NANOUI_FOCUS) @@ -471,7 +474,7 @@ // Do after stuff here to_chat(user, "You start to slice away at \the [src]...") - playsound(get_turf(src), 'sound/items/Welder.ogg', 50, 1) + playsound(src, 'sound/items/Welder.ogg', 50, 1) WT.eyecheck(user) busy = 1 if(do_after(user, src, 50)) diff --git a/code/game/machinery/atmoalter/gas_mine.dm b/code/game/machinery/atmoalter/gas_mine.dm index 6c98d632895..7f4ae3fac13 100644 --- a/code/game/machinery/atmoalter/gas_mine.dm +++ b/code/game/machinery/atmoalter/gas_mine.dm @@ -115,7 +115,7 @@ //pressure_delta = min(pressure_delta, (internal_pressure - environment_pressure)) if(pressure_delta > 0.1) - var/transfer_moles = pressure_delta*environment.volume/(pumping.temperature * R_IDEAL_GAS_EQUATION) + var/transfer_moles = pressure_delta * CELL_VOLUME / (pumping.temperature * R_IDEAL_GAS_EQUATION) var/datum/gas_mixture/removed = pumping.remove(transfer_moles) @@ -128,35 +128,35 @@ AddAir() var/datum/gas/sleeping_agent/trace_gas = new air_contents.trace_gases += trace_gas - trace_gas.moles = internal_pressure*air_contents.volume/(R_IDEAL_GAS_EQUATION*air_contents.temperature) + trace_gas.moles = internal_pressure * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature) /obj/machinery/atmospherics/miner/nitrogen name = "\improper N2 Gas Miner" overlay_color = "#CCFFCC" AddAir() - air_contents.nitrogen = internal_pressure*air_contents.volume/(R_IDEAL_GAS_EQUATION*air_contents.temperature) + air_contents.nitrogen = internal_pressure * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature) /obj/machinery/atmospherics/miner/oxygen name = "\improper O2 Gas Miner" overlay_color = "#007FFF" AddAir() - air_contents.oxygen = internal_pressure*air_contents.volume/(R_IDEAL_GAS_EQUATION*air_contents.temperature) + air_contents.oxygen = internal_pressure * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature) /obj/machinery/atmospherics/miner/toxins name = "\improper Plasma Gas Miner" overlay_color = "#FF0000" AddAir() - air_contents.toxins = internal_pressure*air_contents.volume/(R_IDEAL_GAS_EQUATION*air_contents.temperature) + air_contents.toxins = internal_pressure * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature) /obj/machinery/atmospherics/miner/carbon_dioxide name = "\improper CO2 Gas Miner" overlay_color = "#CDCDCD" AddAir() - air_contents.carbon_dioxide = internal_pressure*air_contents.volume/(R_IDEAL_GAS_EQUATION*air_contents.temperature) + air_contents.carbon_dioxide = internal_pressure * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature) /obj/machinery/atmospherics/miner/air @@ -167,5 +167,5 @@ on = 0 AddAir() - air_contents.oxygen = 0.2 * internal_pressure*air_contents.volume/(R_IDEAL_GAS_EQUATION*air_contents.temperature) - air_contents.nitrogen = 0.8 * internal_pressure*air_contents.volume/(R_IDEAL_GAS_EQUATION*air_contents.temperature) + air_contents.oxygen = 0.2 * internal_pressure * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature) + air_contents.nitrogen = 0.8 * internal_pressure * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature) diff --git a/code/game/machinery/atmoalter/meter.dm b/code/game/machinery/atmoalter/meter.dm index f39093fa1e3..b18c1f34604 100644 --- a/code/game/machinery/atmoalter/meter.dm +++ b/code/game/machinery/atmoalter/meter.dm @@ -152,7 +152,7 @@ if (!iswrench(W)) return ..() - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + playsound(src, 'sound/items/Ratchet.ogg', 50, 1) to_chat(user, "You begin to unfasten \the [src]...") if (do_after(user, src, 40)) user.visible_message( \ diff --git a/code/game/machinery/atmoalter/pump.dm b/code/game/machinery/atmoalter/pump.dm index b964b485d6d..0483cecedcb 100644 --- a/code/game/machinery/atmoalter/pump.dm +++ b/code/game/machinery/atmoalter/pump.dm @@ -51,17 +51,21 @@ ..() if(on) var/datum/gas_mixture/environment + var/transfer_vol //A band-aid fix for the fact the equation used below doesn't work as intended if(holding) environment = holding.air_contents + transfer_vol = holding.volume else environment = loc.return_air() + transfer_vol = CELL_VOLUME + if(direction_out) var/pressure_delta = target_pressure - environment.return_pressure() //Can not have a pressure delta that would cause environment pressure > tank pressure var/transfer_moles = 0 if(air_contents.temperature > 0) - transfer_moles = pressure_delta*environment.volume/(air_contents.temperature * R_IDEAL_GAS_EQUATION) + transfer_moles = pressure_delta * transfer_vol / (air_contents.temperature * R_IDEAL_GAS_EQUATION) //Actually transfer the gas var/datum/gas_mixture/removed = air_contents.remove(transfer_moles) @@ -76,7 +80,7 @@ var/transfer_moles = 0 if(environment.temperature > 0) - transfer_moles = pressure_delta*air_contents.volume/(environment.temperature * R_IDEAL_GAS_EQUATION) + transfer_moles = pressure_delta * air_contents.volume / (environment.temperature * R_IDEAL_GAS_EQUATION) //Actually transfer the gas var/datum/gas_mixture/removed diff --git a/code/game/machinery/atmoalter/scrubber.dm b/code/game/machinery/atmoalter/scrubber.dm index f97b5c74887..47d71dda040 100644 --- a/code/game/machinery/atmoalter/scrubber.dm +++ b/code/game/machinery/atmoalter/scrubber.dm @@ -59,7 +59,7 @@ return anchored = !anchored - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + playsound(src, 'sound/items/Ratchet.ogg', 50, 1) to_chat(user, "You [anchored ? "wrench" : "unwrench"] \the [src].") return @@ -116,7 +116,7 @@ if(on) var/datum/gas_mixture/environment = get_environment() - var/transfer_moles = min(1, volume_rate/environment.volume)*environment.total_moles() + var/transfer_moles = min(1, volume_rate / environment.volume) * environment.total_moles() //Take a gas sample var/datum/gas_mixture/removed = remove_sample(environment, transfer_moles) diff --git a/code/game/machinery/atmoalter/vaporizer.dm b/code/game/machinery/atmoalter/vaporizer.dm index c6c164e7656..64947142263 100644 --- a/code/game/machinery/atmoalter/vaporizer.dm +++ b/code/game/machinery/atmoalter/vaporizer.dm @@ -3,11 +3,12 @@ desc = "A vaporizer which uses power to synthesize liquid oxygen and nitrogen when supplied with vapor salts." icon = 'icons/obj/atmos.dmi' - icon_state = "vaporizer_big-unsecured" + icon_state = "vaporizer_closed_unlocked" + anchored = 1 use_power = 1 density = 1 - machine_flags = WRENCHMOVE | FIXED2WORK | EMAGGABLE + machine_flags = EMAGGABLE flags = OPENCONTAINER | NOREACT stat = NOPOWER req_access = list(access_atmospherics) @@ -18,14 +19,15 @@ var/mixrate = 0 //Rate at which Vapor Salts are added. Cannot be higher than 50. var/mixratio = 20 //Percent Oxygen to synthesize. var/on = 0 - var/waiting_for_ID = 0 - var/unlocked = 0 + var/screen = 0 + var/unlocked = 1 var/power_use_this_tick = 0 /obj/machinery/vaporizer/New() ..() create_reagents(1000) mixing_chamber = new(src) + reagents.add_reagent(VAPORSALT, 1000) /obj/machinery/vaporizer/Destroy() ..() @@ -40,10 +42,10 @@ update_icon() /obj/machinery/vaporizer/update_icon() - if(!anchored) - icon_state = "vaporizer_big-unsecured" + if(stat & NOPOWER) + icon_state = "vaporizer_off" else - icon_state = "vaporizer_big-[on ? "on" : "off"]" + icon_state = "vaporizer_[on ? "open" : "closed"]_[unlocked ? "unlocked" : "locked"]" /obj/machinery/vaporizer/process() power_use_this_tick = 0 @@ -78,7 +80,7 @@ on = 0 return mixing_chamber.flags |= NOREACT - while(target>0) + while(target>0 && !mixing_chamber.is_full()) //First, try to pull out from the main tank if(reagents.has_reagent(rid)) target -= reagents.trans_id_to(mixing_chamber,rid,min(target,1)) @@ -109,10 +111,12 @@ return ui_interact(user) /obj/machinery/vaporizer/attackby(obj/item/weapon/W, mob/living/user) - ..() - if(waiting_for_ID && istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda) && (emagged || allowed(user)) && !unlocked) - unlocked = 1 - to_chat(user,"The interface accepts your verification.") + if(isID(W)||isPDA(W) && (emagged || allowed(user))) + unlocked = !unlocked + to_chat(user,"\The [src] is now [unlocked ? "unlocked" : "locked"].") + update_icon() + else + ..() nanomanager.update_uis(src) /obj/machinery/vaporizer/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open=NANOUI_FOCUS) @@ -131,7 +135,7 @@ data["mixrate"] = mixrate data["mixratio"] = mixratio data["valveOpen"] = on - data["awaiting_ID"] = waiting_for_ID + data["awaiting_ID"] = screen data["unlocked"] = unlocked data["powerConsumption"] = power_use_this_tick @@ -140,7 +144,7 @@ if (!ui) // the ui does not exist, so we'll create a new() one // for a list of parameters and their descriptions see the code docs in \code\\modules\nano\nanoui.dm - ui = new(user, src, ui_key, "vaporizer.tmpl", "Industrial Vaporizer", 500, 350) + ui = new(user, src, ui_key, "vaporizer.tmpl", "Industrial Vaporizer", 500, 390) // when the ui is first opened this is the data it will use ui.set_initial_data(data) // open the new ui window @@ -151,8 +155,10 @@ /obj/machinery/vaporizer/Topic(href, href_list) if(..()) return - if(!allowed(usr) && !emagged) - to_chat(usr,"Access denied.") + if(!isturf(loc)) + return //We're most likely inside the collapsed vaporizer + if(!unlocked && !emagged) + to_chat(usr,"The interface is locked.") return if(href_list["toggle"]) @@ -165,39 +171,48 @@ mixratio = input("New mix ratio", "Percentage of oxygen to synthesize: ", mixratio) as num mixratio = round(Clamp(mixratio, 0, 100)) if(href_list["prepare_dump"]) - waiting_for_ID = !waiting_for_ID + if(!screen && !allowed(usr)) //This is pretty much only to dump now + return + screen = !screen //Unauth inviduals can hit back. if(href_list["dump_contents"]) + if(!screen) //No href exploits + return reagents.clear_reagents() mixing_chamber.reagents.clear_reagents() - unlocked = 0 - waiting_for_ID = 0 + screen = 0 if(href_list["force"]) force_reaction() if(href_list["collapse"]) - if(on) - to_chat(usr,"\The [src] must be off to collapse.") - else - collapse() + screen = 0 + if(!collapse()) + to_chat(usr,"\The [src] must be off and unlocked to collapse.") add_fingerprint(usr) update_icon() nanomanager.update_uis(src) return 1 -/obj/machinery/vaporizer/wrenchAnchor(var/mob/user) - . = ..() - if(!.) - return - power_change() +/obj/machinery/vaporizer/power_change() + ..() update_icon() +/obj/machinery/vaporizer/AltClick(mob/user) + if(!user.incapacitated() && Adjacent(user) && user.dexterity_check()) + if(!collapse()) + ..() + else + ..() + /obj/machinery/vaporizer/proc/collapse() - if(on || stat & BROKEN) - return + if(on || !unlocked) + return 0 var/obj/item/vaporizer/V = new /obj/item/vaporizer(get_turf(src)) forceMove(V) V.folded = src stat |= NOPOWER - waiting_for_ID = 0 //Return to main screen + power_change() + screen = 0 //Return to main screen + nanomanager.update_uis(src) + return 1 /obj/item/vaporizer name = "collapsed industrial vaporizer" @@ -210,12 +225,16 @@ /obj/item/vaporizer/attack_self(mob/user) unfold() -/obj/item/vaporizer/CtrlClick(mob/user) - unfold() +/obj/item/vaporizer/AltClick(mob/user) + if(!user.incapacitated() && Adjacent(user) && user.dexterity_check()) + unfold() + else + ..() /obj/item/vaporizer/proc/unfold() if(!folded) folded = new /obj/machinery/vaporizer(src) folded.forceMove(get_turf(src)) + folded.power_change() folded = null qdel(src) diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm index af7a76075e9..130f566a406 100644 --- a/code/game/machinery/autolathe.dm +++ b/code/game/machinery/autolathe.dm @@ -43,6 +43,8 @@ new /obj/item/weapon/wirecutters(), \ new /obj/item/weapon/wrench(), \ new /obj/item/weapon/solder(),\ + new /obj/item/weapon/wirecutters/clippers(),\ + new /obj/item/weapon/minihoe(),\ new /obj/item/device/analyzer(), \ new /obj/item/weapon/pickaxe/shovel/spade(), \ new /obj/item/device/silicate_sprayer/empty(), \ @@ -54,6 +56,7 @@ new /obj/item/weapon/reagent_containers/glass/beaker/vial(), \ new /obj/item/weapon/reagent_containers/food/drinks/mug(), \ new /obj/item/weapon/storage/toolbox(), \ + new /obj/item/weapon/reagent_containers/glass/jar(), \ ), "Assemblies"=list( new /obj/item/device/assembly/igniter(), \ @@ -107,9 +110,10 @@ new /obj/item/weapon/razor(), \ new /obj/item/device/rcd/tile_painter(), \ new /obj/item/device/rcd/matter/rsf(), \ - new /obj/item/device/destTagger, \ - new /obj/item/device/priceTagger, \ - + new /obj/item/device/destTagger(), \ + new /obj/item/device/priceTagger(), \ + new /obj/item/weapon/hand_labeler(), \ + new /obj/item/device/breathalyzer(), \ ), "Misc_Other"=list( new /obj/item/weapon/rcd_ammo(), \ @@ -135,6 +139,7 @@ new /obj/item/ammo_casing/shotgun(), \ new /obj/item/ammo_casing/shotgun/dart(), \ new /obj/item/ammo_casing/shotgun/buckshot(),\ + new /obj/item/weapon/legcuffs/beartrap(),\ ) ) @@ -187,6 +192,9 @@ else to_chat(user, "You cannot recycle your built in tools.") return 1 + else if(!I.recyclable()) + to_chat(user, "You can not recycle /the [I] at this time.") + return 1 if(user.drop_item(I, src)) materials.removeFrom(I.materials) diff --git a/code/game/machinery/autolathe_old.dm b/code/game/machinery/autolathe_old.dm index db36a31ae3f..8bae83b3291 100644 --- a/code/game/machinery/autolathe_old.dm +++ b/code/game/machinery/autolathe_old.dm @@ -368,7 +368,7 @@ var/global/list/autolathe_recipes_hidden = list( \ /obj/machinery/autolathe/emag(mob/user) if(!hacked && !emagged) - playsound(get_turf(src), 'sound/effects/sparks4.ogg', 75, 1) + playsound(src, 'sound/effects/sparks4.ogg', 75, 1) emagged = 1 hacked = emagged diff --git a/code/game/machinery/bees_apiary.dm b/code/game/machinery/bees_apiary.dm index e0bff84a1d2..3fa4957b81d 100644 --- a/code/game/machinery/bees_apiary.dm +++ b/code/game/machinery/bees_apiary.dm @@ -1,11 +1,14 @@ //http://www.youtube.com/watch?v=-1GadTfGFvU +#define MAX_BEES_PER_HIVE 40 + /* > apiary tray > angry-bee hive */ +var/list/apiary_reservation = list() /obj/machinery/apiary name = "apiary tray" @@ -99,13 +102,14 @@ else to_chat(user, "The [species_name] are violent and exhausted, the hive's toxicity is reaching critical levels.") - switch(reagents.total_volume) - if(30 to 60) - to_chat(user, "Looks like there's a bit of [reagent_name(species.worker_product)] in it.") - if(60 to 90) - to_chat(user, "There's a decent amount of [reagent_name(species.worker_product)] dripping from it!") - if(90 to INFINITY) - to_chat(user, "It's full of [reagent_name(species.worker_product)]!") + if (species.worker_product) + switch(reagents.total_volume) + if(30 to 60) + to_chat(user, "Looks like there's a bit of [reagent_name(species.worker_product)] in it.") + if(60 to 90) + to_chat(user, "There's a decent amount of [reagent_name(species.worker_product)] dripping from it!") + if(90 to INFINITY) + to_chat(user, "It's full of [reagent_name(species.worker_product)]!") /obj/machinery/apiary/Cross(atom/movable/mover, turf/target, height=1.5, air_group = 0) if(air_group || (height==0)) @@ -203,14 +207,28 @@ else if(istype(O, /obj/item/weapon/bee_net)) var/obj/item/weapon/bee_net/N = O if(N.caught_bees.len) - for (var/datum/bee/B in N.caught_bees) - if (!species || !(queen_bees_inside || worker_bees_inside)) - species = B.species - if (species == B.species) - enterHive(B) - N.caught_bees.Remove(B) - N.current_species = null - to_chat(user, "You empty the [species.common_name] into the apiary.") + if (N.caught_bees.len+worker_bees_inside+queen_bees_inside+bees_outside_hive.len <= MAX_BEES_PER_HIVE) + for (var/datum/bee/B in N.caught_bees) + if (!species || !(queen_bees_inside || worker_bees_inside)) + species = B.species + if (species == B.species) + enterHive(B) + N.caught_bees.Remove(B) + N.current_species = null + to_chat(user, "You empty the [species.common_name] into the apiary.") + else + var allowed = MAX_BEES_PER_HIVE - worker_bees_inside+queen_bees_inside+bees_outside_hive.len + if (allowed <= 0) + to_chat(user, "There are too many [species.common_name] in the apiary already.") + else + for (var/i = 1 to allowed) + var/datum/bee/B = pick(N.caught_bees) + if (!species || !(queen_bees_inside || worker_bees_inside)) + species = B.species + if (species == B.species) + enterHive(B) + N.caught_bees.Remove(B) + to_chat(user, "You empty [allowed] [species.common_name] into the apiary.") else to_chat(user, "There are no more bees in the net.") else @@ -224,6 +242,7 @@ queen_bees_inside++ var/datum/bee/queen_bee/Q = B if (Q.colonizing) + apiary_reservation.Remove(src) nutrilevel = max(15,nutrilevel+15) else worker_bees_inside++ @@ -273,9 +292,9 @@ reagents.add_reagent(chemToAdd, amountToAdd * yieldmod) if (!pollen.Find(S)) pollen.Add(S) - if (istype(B,/datum/bee/queen_bee)) + if (istype(B,/datum/bee/queen_bee) && species.queen_product) reagents.add_reagent(species.queen_product,0.75 * yieldmod) - else + else if (species.worker_product) reagents.add_reagent(species.worker_product,0.75 * yieldmod) reagents.add_reagent(SUGAR, 0.1 * yieldmod) @@ -312,15 +331,17 @@ var/mob/living/simple_animal/bee/lastBees = getFromPool(/mob/living/simple_animal/bee,get_turf(src)) for(var/i = 1 to worker_bees_inside) worker_bees_inside-- - lastBees.addBee(new species.bee_type(src)) + lastBees.addBee(new species.bee_type()) for(var/i = 1 to queen_bees_inside) queen_bees_inside-- - lastBees.addBee(new species.queen_type(src)) + lastBees.addBee(new species.queen_type()) /obj/machinery/apiary/proc/exile_swarm(var/obj/machinery/apiary/A) - if (A == src) + if (A == src)//can't colonize our own apiary return 0 - if (A.queen_bees_inside > 0 || is_type_in_list(/datum/bee/queen_bee,A.bees_outside_hive)) + if (A in apiary_reservation)//another queen has marked this one for herself + return 0 + if (A.queen_bees_inside > 0 || locate(/datum/bee/queen_bee) in A.bees_outside_hive)//another queen made her way there somehow return 0 var/mob/living/simple_animal/bee/B_mob = getFromPool(/mob/living/simple_animal/bee, get_turf(src), src) var/datum/bee/queen_bee/new_queen = new species.queen_type(src) @@ -331,8 +352,17 @@ B_mob.addBee(B) worker_bees_inside-- new_queen.setHome(A) + A.reserve_apiary(B_mob) return 1 +/obj/machinery/apiary/proc/reserve_apiary(var/mob/living/simple_animal/bee/B_swarm) + apiary_reservation.Add(B_swarm) + spawn (300) + apiary_reservation.Remove(B_swarm) + if (B_swarm)//so we can't reach the apiary somehow? then we've become homeless + B_swarm.visible_message("A swarm has lost its way.") + B_swarm.mood_change(BEE_ROAMING) + /obj/machinery/apiary/proc/angry_swarm(var/mob/M = null) if (!species.angery) return @@ -346,7 +376,7 @@ B_mob.addBee(B) worker_bees_inside-- bees_outside_hive.Add(B) - B.angerAt(M) + B_mob.mood_change(BEE_OUT_FOR_ENEMIES,M) B_mob.update_icon() @@ -388,7 +418,7 @@ //PRODUCING WORKER BEES - if(nutrilevel > 10 && queen_bees_inside > 0 && worker_bees_inside < 20) + if(nutrilevel > 10 && queen_bees_inside > 0 && worker_bees_inside < MAX_BEES_PER_HIVE/2) worker_bees_inside += queen_bees_inside // We're getting in dire need of nutrients, let's starve bees so others can survive @@ -418,7 +448,7 @@ //NOISE if(prob(2)) - playsound(get_turf(src), 'sound/effects/bees.ogg', min(20+(reagents.total_volume),100), 1) + playsound(src, 'sound/effects/bees.ogg', min(20+(reagents.total_volume),100), 1) update_icon() @@ -435,10 +465,11 @@ worker_bees_inside-- bees_outside_hive.Add(B) B_mob.addBee(B) - if (toxic > species.toxic_threshold_anger && prob(toxic/1.5))//if our beehive is full of toxicity, bees will become ANGRY - B.angerAt() + if (prob(species.aggressiveness) || (toxic > species.toxic_threshold_anger && prob(toxic/1.5)))//if our beehive is full of toxicity, bees will become ANGRY + B_mob.mood_change(BEE_OUT_FOR_ENEMIES) else - B.goPollinate() + B_mob.mood_change(BEE_OUT_FOR_PLANTS) + B_mob.update_icon() if(queen_bees_inside > 1 && worker_bees_inside >= 10) for(var/obj/machinery/apiary/A in range(src,5)) @@ -449,7 +480,113 @@ ///////////////////////////WILD BEEHIVES//////////////////////////// +/obj/structure/wild_apiary + name = "wild bug hive" + icon = 'icons/obj/apiary_bees_etc.dmi' + icon_state = "apiary-wild-inprogress0" + density = 0 + anchored = 1 + var/base_icon_state = "apiary-wild-inprogress" + var/prefix = "" + var/remaining_work = 10 + var/health = 20 + +/obj/structure/wild_apiary/New(turf/loc, var/p = "") + prefix = p + icon_state = "[prefix][base_icon_state]0" + +/obj/structure/wild_apiary/proc/work() + remaining_work-- + switch(remaining_work) + if (1 to 3) + icon_state = "[prefix][base_icon_state]2" + if (4 to 6) + icon_state = "[prefix][base_icon_state]1" + if (7 to 9) + icon_state = "[prefix][base_icon_state]0" + if (remaining_work<=0) + var/obj/machinery/apiary/wild/W = new /obj/machinery/apiary/wild(loc) + W.icon_state = "[prefix][W.icon_state]" + for (var/mob/living/simple_animal/bee/B_mob in loc) + if (B_mob.state == BEE_BUILDING) + for(var/datum/bee/B in B_mob.bees) + W.enterHive(B) + qdel(B_mob) + + qdel(src) + + +/obj/structure/wild_apiary/bullet_act(var/obj/item/projectile/P) + ..() + if(P.damage && P.damtype != HALLOSS) + health -= P.damage + updateHealth() + +/obj/structure/wild_apiary/attackby(var/obj/item/O as obj, var/mob/user as mob) + if(..()) + return + else if(O.force) + to_chat(user,"You hit \the [src] with your [O].") + O.on_attack(src, user) + health -= O.force + updateHealth() + +/obj/structure/wild_apiary/proc/updateHealth() + if(health <= 0) + visible_message("\The [src] falls apart.") + qdel(src) + /obj/machinery/apiary/wild + name = "hive" + icon = 'icons/obj/apiary_bees_etc.dmi' + icon_state = "apiary-wild" + density = 1 + anchored = 1 + nutrilevel = 15 + + cycledelay = 100 + + //we'll allow those to start pumping out bees right away + wild = 1 + var/health = 100 + +/obj/machinery/apiary/wild/bullet_act(var/obj/item/projectile/P) + ..() + if(P.damage && P.damtype != HALLOSS) + health -= P.damage + updateHealth() + +/obj/machinery/apiary/wild/attackby(var/obj/item/O as obj, var/mob/user as mob) + if(..()) + return + if(istype(O, /obj/item/queen_bee)) + to_chat(user, "This type of bee hive isn't fit for domesticated bees.") + else if(istype(O, /obj/item/weapon/reagent_containers/food/snacks/beezeez)) + to_chat(user, "These bees don't want your candies, they want your blood!") + else if(O.force) + to_chat(user,"You hit \the [src] with your [O].") + if(queen_bees_inside || worker_bees_inside) + angry_swarm(user) + O.on_attack(src, user) + health -= O.force + updateHealth() + +/obj/machinery/apiary/wild/proc/updateHealth() + if(health <= 0) + visible_message("\The [src] falls apart.") + + if (queen_bees_inside || worker_bees_inside) + empty_beehive() + + harvest_honeycombs() + + qdel(src) + +/obj/machinery/apiary/wild/update_icon() + overlays.len = 0 + return + +/obj/machinery/apiary/wild/angry name = "angry-bee hive" icon = 'icons/obj/apiary_bees_etc.dmi' icon_state = "apiary-wild" @@ -466,52 +603,21 @@ worker_bees_inside = 20 wild = 1 - var/health = 100 + health = 100 -/obj/machinery/apiary/wild/New() +/obj/machinery/apiary/wild/angry/New() ..() reagents.add_reagent(ROYALJELLY,5) reagents.add_reagent(HONEY,75) reagents.add_reagent(NUTRIMENT, 4) reagents.add_reagent(SUGAR, 16) update_icon() + initialize() +/obj/machinery/apiary/wild/angry/initialize() + species = bees_species[BEESPECIES_NORMAL] -/obj/machinery/apiary/wild/bullet_act(var/obj/item/projectile/P) - ..() - if(P.damage && P.damtype != HALLOSS) - health -= P.damage - updateHealth() - -/obj/machinery/apiary/wild/attackby(var/obj/item/O as obj, var/mob/user as mob) - if(..()) - return - if(istype(O, /obj/item/queen_bee)) - to_chat(user, "This type of bee hive isn't fit for domesticated bees.") - else if(istype(O, /obj/item/weapon/reagent_containers/food/snacks/beezeez)) - to_chat(user, "These bees don't want your candies, they want your blood!") - else if(O.force) - user.delayNextAttack(10) - to_chat(user,"You hit \the [src] with your [O].") - if(queen_bees_inside || worker_bees_inside) - angry_swarm(user) - - playsound(get_turf(src), O.hitsound, 50, 1, -1) - health -= O.force - updateHealth() - -/obj/machinery/apiary/wild/proc/updateHealth() - if(health <= 0) - visible_message("\The [src] falls apart.") - - if (queen_bees_inside || worker_bees_inside) - empty_beehive() - - harvest_honeycombs() - - qdel(src) - -/obj/machinery/apiary/wild/process() +/obj/machinery/apiary/wild/angry/process() if(world.time > (lastcycle + cycledelay)) lastcycle = world.time @@ -524,7 +630,7 @@ //making noise if(prob(10)) - playsound(get_turf(src), 'sound/effects/bees.ogg', min(20+(reagents.total_volume),100), 1) + playsound(src, 'sound/effects/bees.ogg', min(20+(reagents.total_volume),100), 1) //sending out bees to KILL if(worker_bees_inside >= 10 && bees_outside_hive.len < 15) @@ -534,8 +640,37 @@ worker_bees_inside-- bees_outside_hive.Add(B) B_mob.addBee(B) - B.angerAt() + B_mob.mood_change(BEE_OUT_FOR_ENEMIES) + B_mob.update_icon() -/obj/machinery/apiary/wild/update_icon() - overlays.len = 0 - return + +/obj/machinery/apiary/wild/angry/hornet + name = "deadly hornet hive" + icon = 'icons/obj/apiary_bees_etc.dmi' + icon_state = "hornet_apiary-wild" + density = 1 + anchored = 1 + nutrilevel = 100 + damage = 1//hornets are already pretty dangerous by themselves. + toxic = 0 + + cycledelay = 50 + + //we'll allow those to start pumping out bees right away + queen_bees_inside = 1 + worker_bees_inside = 20 + wild = 1 + + health = 100 + +/obj/machinery/apiary/wild/angry/hornet/New() + ..() + reagents.clear_reagents() + reagents.add_reagent(ROYALJELLY,15) + reagents.add_reagent(NUTRIMENT, 64) + reagents.add_reagent(SUGAR, 21) + +/obj/machinery/apiary/wild/angry/hornet/initialize() + species = bees_species[BEESPECIES_HORNET] + +#undef MAX_BEES_PER_HIVE diff --git a/code/game/machinery/biogenerator.dm b/code/game/machinery/biogenerator.dm index bcf541e3ea7..6782413faa8 100644 --- a/code/game/machinery/biogenerator.dm +++ b/code/game/machinery/biogenerator.dm @@ -235,6 +235,12 @@ name="Box of Crayons" result=/obj/item/weapon/storage/fancy/crayons +/datum/biogen_recipe/misc/rice_hat + name = "Rice Hat" + id = "rice_hat" + cost = 300 + result = /obj/item/clothing/head/rice_hat + /datum/biogen_recipe/flooring category="Flooring" @@ -477,7 +483,7 @@ processing = 1 update_icon() updateUsrDialog() - playsound(get_turf(src), 'sound/machines/blender.ogg', 50, 1) + playsound(src, 'sound/machines/blender.ogg', 50, 1) use_power(S*30) sleep(speed_coefficient*(S+15)) processing = 0 diff --git a/code/game/machinery/bioprinter.dm b/code/game/machinery/bioprinter.dm index 32ad46e028b..ccc7846cd28 100644 --- a/code/game/machinery/bioprinter.dm +++ b/code/game/machinery/bioprinter.dm @@ -34,7 +34,9 @@ ) /obj/machinery/bioprinter/New() - . = ..() + ..() + if(map.nameShort == "deff") + icon = 'maps/defficiency/medbay.dmi' component_parts = newlist(\ /obj/item/weapon/circuitboard/bioprinter,\ @@ -108,7 +110,7 @@ return else if(iswrench(W)) user.visible_message("[user] begins to [anchored? "unfasten" : "fasten"] \the [src].", "You begin to [anchored? "unfasten" : "fasten"] \the [src].", "You hear a ratchet.") - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + playsound(src, 'sound/items/Ratchet.ogg', 50, 1) if(do_after(user, src, 30)) user.visible_message("[user] begins to [anchored? "unfasten" : "fasten"] \the [src].", "You [anchored? "unfasten" : "fasten"] \the [src].", "You hear a ratchet.") if(anchored) diff --git a/code/game/machinery/bots/bots.dm b/code/game/machinery/bots/bots.dm index ae5d4367f67..a5ec0c20f45 100644 --- a/code/game/machinery/bots/bots.dm +++ b/code/game/machinery/bots/bots.dm @@ -85,7 +85,7 @@ user.do_attack_animation(src, user) src.health -= rand(15,30)*brute_dam_coeff src.visible_message("[user] has slashed [src]!") - playsound(get_turf(src), 'sound/weapons/slice.ogg', 25, 1, -1) + playsound(src, 'sound/weapons/slice.ogg', 25, 1, -1) if(prob(10)) //new /obj/effect/decal/cleanable/blood/oil(src.loc) var/obj/effect/decal/cleanable/blood/oil/O = getFromPool(/obj/effect/decal/cleanable/blood/oil, src.loc) diff --git a/code/game/machinery/bots/buttbot.dm b/code/game/machinery/bots/buttbot.dm index 57af0caaddb..ae33a9d94b7 100644 --- a/code/game/machinery/bots/buttbot.dm +++ b/code/game/machinery/bots/buttbot.dm @@ -42,7 +42,7 @@ Here it is: Buttbot. /obj/machinery/bot/buttbot/proc/fart() if(can_fart()) - playsound(get_turf(src), 'sound/misc/fart.ogg', 50, 1) + playsound(src, 'sound/misc/fart.ogg', 50, 1) sincelastfart = world.timeofday /obj/machinery/bot/buttbot/Hear(var/datum/speech/speech, var/rendered_speech="") @@ -73,7 +73,7 @@ Here it is: Buttbot. /obj/machinery/bot/buttbot/explode() src.on = 0 src.visible_message("[src] blows apart!", 1) - playsound(get_turf(src), 'sound/effects/superfart.ogg', 50, 1) //A fitting end + playsound(src, 'sound/effects/superfart.ogg', 50, 1) //A fitting end var/turf/Tsec = get_turf(src) new /obj/item/clothing/head/butt(Tsec) diff --git a/code/game/machinery/bots/draculabot.dm b/code/game/machinery/bots/draculabot.dm index 0d7d3cee9cd..8e2e0b96091 100644 --- a/code/game/machinery/bots/draculabot.dm +++ b/code/game/machinery/bots/draculabot.dm @@ -193,7 +193,7 @@ for(var/mob/living/carbon/human/H in view(7,src)) if(H.vessel.get_reagent_amount(BLOOD) && !(H.species.anatomy_flags & NO_BLOOD)) possible_targets += H - if(possible_targets) + if(possible_targets.len) target = pick(possible_targets) else return @@ -241,7 +241,7 @@ return H.vessel.remove_reagent(BLOOD,DANGER_DRINK_RATE) getFromPool(/obj/effect/decal/cleanable/blood, get_turf(src)) - playsound(get_turf(src), 'sound/effects/splat.ogg', 50, 1) + playsound(src, 'sound/effects/splat.ogg', 50, 1) spawn(1 SECONDS) drink(H) diff --git a/code/game/machinery/bots/ed209bot.dm b/code/game/machinery/bots/ed209bot.dm index 73b0211e5da..5403828fe27 100644 --- a/code/game/machinery/bots/ed209bot.dm +++ b/code/game/machinery/bots/ed209bot.dm @@ -333,7 +333,7 @@ Auto Patrol: []"}, if(!istype(target.loc, /turf)) return if (Adjacent(target)) // if right next to perp - playsound(get_turf(src), 'sound/weapons/Egloves.ogg', 50, 1, -1) + playsound(src, 'sound/weapons/Egloves.ogg', 50, 1, -1) src.icon_state = "[lasercolor][icon_initial]-c" spawn(2) src.icon_state = "[lasercolor][icon_initial][src.on]" @@ -387,7 +387,7 @@ Auto Patrol: []"}, if(istype(src.target,/mob/living/carbon)) if (!src.target.handcuffed && !src.arrest_type) - playsound(get_turf(src), 'sound/weapons/handcuffs.ogg', 30, 1, -2) + playsound(src, 'sound/weapons/handcuffs.ogg', 30, 1, -2) mode = SECBOT_ARREST visible_message("[src] is trying to put handcuffs on [src.target]!") @@ -406,7 +406,7 @@ Auto Patrol: []"}, src.last_found = world.time src.frustration = 0 - // playsound(get_turf(src), pick('sound/voice/bgod.ogg', 'sound/voice/biamthelaw.ogg', 'sound/voice/bsecureday.ogg', 'sound/voice/bradio.ogg', 'sound/voice/binsult.ogg', 'sound/voice/bcreep.ogg'), 50, 0) + // playsound(src, pick('sound/voice/bgod.ogg', 'sound/voice/biamthelaw.ogg', 'sound/voice/bsecureday.ogg', 'sound/voice/bradio.ogg', 'sound/voice/binsult.ogg', 'sound/voice/bcreep.ogg'), 50, 0) // 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) else @@ -721,7 +721,7 @@ Auto Patrol: []"}, src.oldtarget_name = C.name src.speak("Level [src.threatlevel] infraction alert!") if(!src.lasercolor) - playsound(get_turf(src), pick('sound/voice/ed209_20sec.ogg', 'sound/voice/EDPlaceholder.ogg'), 50, 0) + playsound(src, pick('sound/voice/ed209_20sec.ogg', 'sound/voice/EDPlaceholder.ogg'), 50, 0) src.visible_message("[src] points at [C.name]!") mode = SECBOT_HUNT spawn(0) @@ -883,7 +883,7 @@ Auto Patrol: []"}, return //if(lastfired && world.time - lastfired < 100) - // playsound(get_turf(src), 'ed209_shoot.ogg', 50, 0) + // playsound(src, 'ed209_shoot.ogg', 50, 0) if (!( istype(U, /turf) )) return @@ -1052,7 +1052,7 @@ Auto Patrol: []"}, if(8) if( isscrewdriver(W) ) - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 100, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 100, 1) var/turf/T = get_turf(user) to_chat(user, "Now attaching the gun to the frame...") sleep(40) diff --git a/code/game/machinery/bots/farmbot.dm b/code/game/machinery/bots/farmbot.dm index 75a403989bb..96a297c60b5 100644 --- a/code/game/machinery/bots/farmbot.dm +++ b/code/game/machinery/bots/farmbot.dm @@ -71,11 +71,9 @@ spawn(0) if ((istype(M, /obj/machinery/door)) && (!isnull(src.botcard))) var/obj/machinery/door/D = M - if (!istype(D, /obj/machinery/door/firedoor) && D.check_access(src.botcard)) + if (!istype(D, /obj/machinery/door/firedoor) && !istype(D, /obj/machinery/door/poddoor) && D.check_access(src.botcard)) D.open() src.frustration = 0 - return - return /obj/machinery/bot/farmbot/turn_on() . = ..() @@ -301,7 +299,7 @@ /obj/machinery/bot/farmbot/proc/find_target() if ( emagged ) //Find a human and help them! for ( var/mob/living/carbon/human/human in view(7,src) ) - if (human.stat == 2) + if (human.isDead()) continue var list/options = list(FARMBOT_MODE_WEED) @@ -470,7 +468,7 @@ if ( emagged ) // warning, humans are thirsty! var splashAmount = min(70,tank.reagents.total_volume) src.visible_message("[src] splashes [target] with a bucket of water!") - playsound(get_turf(src), 'sound/effects/slosh.ogg', 25, 1) + playsound(src, 'sound/effects/slosh.ogg', 25, 1) if ( prob(50) ) tank.reagents.reaction(target, TOUCH) //splash the human! else @@ -489,7 +487,7 @@ b_amount = 100 - tray.waterlevel tank.reagents.remove_reagent(WATER, b_amount) tray.adjust_water(b_amount) - playsound(get_turf(src), 'sound/effects/slosh.ogg', 25, 1) + playsound(src, 'sound/effects/slosh.ogg', 25, 1) //tray.updateicon() mode = FARMBOT_MODE_WAITING @@ -503,13 +501,13 @@ return mode = FARMBOT_MODE_WAITING - playsound(get_turf(src), 'sound/effects/slosh.ogg', 25, 1) + playsound(src, 'sound/effects/slosh.ogg', 25, 1) src.visible_message("[src] starts filling it's tank from [target].") spawn(300) src.visible_message("[src] finishes filling it's tank.") src.mode = 0 tank.reagents.add_reagent(WATER, tank.reagents.maximum_volume - tank.reagents.total_volume ) - playsound(get_turf(src), 'sound/effects/slosh.ogg', 25, 1) + playsound(src, 'sound/effects/slosh.ogg', 25, 1) /obj/item/weapon/farmbot_arm_assembly diff --git a/code/game/machinery/bots/floorbot.dm b/code/game/machinery/bots/floorbot.dm index 00a8ee616d5..5e007b6fb66 100644 --- a/code/game/machinery/bots/floorbot.dm +++ b/code/game/machinery/bots/floorbot.dm @@ -11,6 +11,7 @@ w_class = W_CLASS_MEDIUM flags = 0 var/created_name = "Floorbot" + var/skin = null /obj/item/weapon/toolbox_tiles_sensor desc = "It's a toolbox with tiles sticking out the top and a sensor attached." @@ -24,6 +25,7 @@ w_class = W_CLASS_MEDIUM flags = 0 var/created_name = "Floorbot" + var/skin = null // Tell other floorbots what we're fucking with so two floorbots don't dick with the same tile. var/global/list/floorbot_targets=list() @@ -73,6 +75,8 @@ var/global/list/floorbot_targets=list() var/nearest_beacon // the nearest beacon's tag var/turf/nearest_beacon_loc // the nearest beacon's location + var/skin = null + /obj/machinery/bot/floorbot/New() . = ..() @@ -413,7 +417,7 @@ var/global/list/floorbot_targets=list() if(src.amount <= 0) return src.anchored = 1 - src.icon_state = "[src.icon_initial]-c" + src.icon_state = "[skin][src.icon_initial]-c" if(istype(target, /turf/space/)) visible_message("[src] begins to repair the hole") var/obj/item/stack/tile/plasteel/T = new /obj/item/stack/tile/plasteel @@ -499,9 +503,9 @@ var/global/list/floorbot_targets=list() /obj/machinery/bot/floorbot/proc/updateicon() if(src.amount > 0) - src.icon_state = "[src.icon_initial][src.on]" + src.icon_state = "[skin][src.icon_initial][src.on]" else - src.icon_state = "[src.icon_initial][src.on]e" + src.icon_state = "[skin][src.icon_initial][src.on]e" /obj/machinery/bot/floorbot/proc/calc_path(var/turf/avoid = null) @@ -679,8 +683,16 @@ var/global/list/floorbot_targets=list() src.visible_message("[src] blows apart!", 1) var/turf/Tsec = get_turf(src) - var/obj/item/weapon/storage/toolbox/mechanical/N = new /obj/item/weapon/storage/toolbox/mechanical(Tsec) - N.contents = list() + switch(skin) + if("y") + var/obj/item/weapon/storage/toolbox/electrical/N = new(Tsec) + N.contents = list() + if("r") + var/obj/item/weapon/storage/toolbox/emergency/N = new(Tsec) + N.contents = list() + else + var/obj/item/weapon/storage/toolbox/mechanical/N = new(Tsec) + N.contents = list() new /obj/item/device/assembly/prox_sensor(Tsec) @@ -704,9 +716,20 @@ var/global/list/floorbot_targets=list() qdel(src) return +/obj/item/weapon/storage/toolbox/proc/floorbot_type() + return "no_build" -/obj/item/weapon/storage/toolbox/mechanical/attackby(var/obj/item/stack/tile/plasteel/T, mob/user as mob) - if(!istype(T, /obj/item/stack/tile/plasteel) || src.contents.len >= 1) //Only do this if the thing is empty +/obj/item/weapon/storage/toolbox/mechanical/floorbot_type() + return null + +/obj/item/weapon/storage/toolbox/emergency/floorbot_type() + return "r" + +/obj/item/weapon/storage/toolbox/electrical/floorbot_type() + return "y" + +/obj/item/weapon/storage/toolbox/attackby(var/obj/item/stack/tile/plasteel/T, mob/user as mob) + if(!istype(T, /obj/item/stack/tile/plasteel) || src.contents.len >= 1 || floorbot_type() == "no_build") //Only do this if the thing is empty return ..() /*if(user.s_active) user.s_active.close(user)*/ @@ -714,6 +737,8 @@ var/global/list/floorbot_targets=list() qdel(T) T = null var/obj/item/weapon/toolbox_tiles/B = new /obj/item/weapon/toolbox_tiles + B.skin = floorbot_type() + B.icon_state = "[B.skin]toolbox_tiles" user.put_in_hands(B) to_chat(user, "You add the tiles into the empty toolbox. They protrude from the top.") user.drop_from_inventory(src) @@ -726,6 +751,8 @@ var/global/list/floorbot_targets=list() W = null var/obj/item/weapon/toolbox_tiles_sensor/B = new /obj/item/weapon/toolbox_tiles_sensor() B.created_name = src.created_name + B.skin = src.skin + B.icon_state = "[B.skin]toolbox_tiles_sensor" user.put_in_hands(B) to_chat(user, "You add the sensor to the toolbox and tiles!") user.drop_from_inventory(src) @@ -747,6 +774,8 @@ var/global/list/floorbot_targets=list() var/turf/T = get_turf(user.loc) var/obj/machinery/bot/floorbot/A = new /obj/machinery/bot/floorbot(T) A.name = src.created_name + A.skin = src.skin + A.updateicon() to_chat(user, "You add the robot arm to the odd looking toolbox assembly! Boop beep!") user.drop_from_inventory(src) qdel(src) diff --git a/code/game/machinery/bots/medbot.dm b/code/game/machinery/bots/medbot.dm index ecee78c5a0c..3ff9a0e225a 100644 --- a/code/game/machinery/bots/medbot.dm +++ b/code/game/machinery/bots/medbot.dm @@ -317,7 +317,7 @@ speak(message) for (var/mob/living/carbon/C in view(7,src)) //Time to find a patient! - if ((C.stat == 2) || !istype(C, /mob/living/carbon/human)) + if ((C.isDead()) || !istype(C, /mob/living/carbon/human)) continue if ((C == oldpatient) && (world.time < last_found + 100)) @@ -382,7 +382,7 @@ /obj/machinery/bot/medbot/proc/assess_patient(mob/living/carbon/C as mob) //Time to see if they need medical help! - if(C.stat == 2) + if(C.isDead()) return 0 //welp too late for them! if(C.suiciding) @@ -434,7 +434,7 @@ last_found = world.time return - if(C.stat == 2) + if(C.isDead()) playsound(src.loc, 'sound/medbot/Flatline_custom.ogg', 35, channel = CHANNEL_MEDBOTS) visible_message("[src] points at [C.name]!") oldpatient = patient @@ -759,5 +759,3 @@ to_chat(P.pai, "- Click on somebody: Depending on your mode, you inject or analyze a person.") to_chat(P.pai, "What you inject depends on the medbot's configuration. You can't modify it") to_chat(P.pai, "If you want to exit the medbot, somebody has to right-click you and press 'Remove pAI'.") - -#undefine diff --git a/code/game/machinery/bots/mulebot.dm b/code/game/machinery/bots/mulebot.dm index 3249db43b62..7fc416ca8b5 100644 --- a/code/game/machinery/bots/mulebot.dm +++ b/code/game/machinery/bots/mulebot.dm @@ -127,7 +127,7 @@ var/global/mulebot_count = 0 locked = !locked to_chat(user, "You [locked ? "lock" : "unlock"] the mulebot's controls!") flick("[icon_initial]-emagged", src) - playsound(get_turf(src), 'sound/effects/sparks1.ogg', 100, 0) + playsound(src, 'sound/effects/sparks1.ogg', 100, 0) else if(istype(I, /obj/item/weapon/card/id)) if(toggle_lock(user)) to_chat(user, "Controls [(locked ? "locked" : "unlocked")].") @@ -424,7 +424,7 @@ var/global/mulebot_count = 0 /obj/machinery/bot/mulebot/proc/load(var/atom/movable/C) if(wires.LoadCheck() && !is_type_in_list(C,can_load)) src.visible_message("[src] makes a sighing buzz.", "You hear an electronic buzzing sound.") - playsound(get_turf(src), 'sound/machines/buzz-sigh.ogg', 50, 0) + playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0) return // if not emagged, only allow crates to be loaded //I'm sure someone will come along and ask why this is here... well people were dragging screen items onto the mule, and that was not cool. @@ -477,6 +477,8 @@ var/global/mulebot_count = 0 mode = 1 overlays.len = 0 + if(integratedpai) + overlays += image('icons/obj/aibots.dmi', "mulebot1_pai") load.forceMove(src.loc) load.pixel_y -= 9 * PIXEL_MULTIPLIER @@ -616,25 +618,25 @@ var/global/mulebot_count = 0 mode = 4 if(blockcount == 3) src.visible_message("[src] makes an annoyed buzzing sound.", "You hear an electronic buzzing sound.") - playsound(get_turf(src), 'sound/machines/buzz-two.ogg', 50, 0) + playsound(src, 'sound/machines/buzz-two.ogg', 50, 0) if(blockcount > 5) // attempt 5 times before recomputing // find new path excluding blocked turf src.visible_message("[src] makes a sighing buzz.", "You hear an electronic buzzing sound.") - playsound(get_turf(src), 'sound/machines/buzz-sigh.ogg', 50, 0) + playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0) spawn(2) calc_path(next) if(path.len > 0) src.visible_message("[src] makes a delighted ping!", "You hear a ping.") - playsound(get_turf(src), 'sound/machines/ping.ogg', 50, 0) + playsound(src, 'sound/machines/ping.ogg', 50, 0) mode = 4 mode =6 return return else src.visible_message("[src] makes an annoyed buzzing sound.", "You hear an electronic buzzing sound.") - playsound(get_turf(src), 'sound/machines/buzz-two.ogg', 50, 0) + playsound(src, 'sound/machines/buzz-two.ogg', 50, 0) // to_chat(world, "Bad turf.") mode = 5 return @@ -654,11 +656,11 @@ var/global/mulebot_count = 0 blockcount = 0 mode = 4 src.visible_message("[src] makes a delighted ping!", "You hear a ping.") - playsound(get_turf(src), 'sound/machines/ping.ogg', 50, 0) + playsound(src, 'sound/machines/ping.ogg', 50, 0) else src.visible_message("[src] makes a sighing buzz.", "You hear an electronic buzzing sound.") - playsound(get_turf(src), 'sound/machines/buzz-sigh.ogg', 50, 0) + playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0) mode = 7 //if(6) @@ -705,7 +707,7 @@ var/global/mulebot_count = 0 /obj/machinery/bot/mulebot/proc/at_target() if(!reached_target) src.visible_message("[src] makes a chiming sound!", "You hear a chime.") - playsound(get_turf(src), 'sound/machines/chime.ogg', 50, 0) + playsound(src, 'sound/machines/chime.ogg', 50, 0) reached_target = 1 if(load) // if loaded, unload at target @@ -768,7 +770,7 @@ var/global/mulebot_count = 0 return //writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\/obj/machinery/bot/mulebot/proc/RunOverCreature() called tick#: [world.time]") src.visible_message("[src] drives over [H]!") - playsound(get_turf(src), 'sound/effects/splat.ogg', 50, 1) + playsound(src, 'sound/effects/splat.ogg', 50, 1) var/damage = rand(5,15) if(integratedpai) damage = round(damage/3.33) diff --git a/code/game/machinery/bots/secbot.dm b/code/game/machinery/bots/secbot.dm index c681e187608..5680b4b7793 100644 --- a/code/game/machinery/bots/secbot.dm +++ b/code/game/machinery/bots/secbot.dm @@ -71,6 +71,7 @@ else set_light(0) + var/obj/item/weapon/melee/baton/baton = null /obj/machinery/bot/secbot/beepsky name = "Officer Beep O'sky" @@ -270,7 +271,7 @@ Auto Patrol: []"}, return if(get_dist(src, src.target) <= 1) // if right next to perp if(istype(src.target,/mob/living/carbon)) - playsound(get_turf(src), 'sound/weapons/Egloves.ogg', 50, 1, -1) + playsound(src, 'sound/weapons/Egloves.ogg', 50, 1, -1) src.icon_state = "[src.icon_initial]-c" spawn(2) src.icon_state = "[icon_initial][src.on]" @@ -298,6 +299,8 @@ Auto Patrol: []"}, broadcast_security_hud_message("[src.name] is [arrest_type ? "detaining" : "arresting"] level [threatlevel] suspect [target] in [location]", src) //visible_message("[src.target] has been stunned by [src]!") + check_if_rigged() + mode = SECBOT_PREP_ARREST src.anchored = 1 src.target_lastloc = M.loc @@ -306,7 +309,7 @@ Auto Patrol: []"}, //just harmbaton them until dead if(world.time > next_harm_time) next_harm_time = world.time + 15 - playsound(get_turf(src), 'sound/weapons/Egloves.ogg', 50, 1, -1) + playsound(src, 'sound/weapons/Egloves.ogg', 50, 1, -1) visible_message("[src] beats [src.target] with the stun baton!") src.icon_state = "[src.icon_initial]-c" spawn(2) @@ -316,9 +319,10 @@ Auto Patrol: []"}, if(S && istype(S)) S.AdjustStunned(10) S.adjustBruteLoss(15) + check_if_rigged() if(S.stat) src.frustration = 8 - playsound(get_turf(src), pick('sound/voice/bgod.ogg', 'sound/voice/biamthelaw.ogg', 'sound/voice/bsecureday.ogg', 'sound/voice/bradio.ogg', 'sound/voice/bcreep.ogg'), 50, 0) + playsound(src, pick('sound/voice/bgod.ogg', 'sound/voice/biamthelaw.ogg', 'sound/voice/bsecureday.ogg', 'sound/voice/bradio.ogg', 'sound/voice/bcreep.ogg'), 50, 0) else // not next to perp var/turf/olddist = get_dist(src, src.target) @@ -341,7 +345,7 @@ Auto Patrol: []"}, if(istype(src.target,/mob/living/carbon) && !isalien(target)) var/mob/living/carbon/C = target if(!C.handcuffed && !src.arrest_type) - playsound(get_turf(src), 'sound/weapons/handcuffs.ogg', 30, 1, -2) + playsound(src, 'sound/weapons/handcuffs.ogg', 30, 1, -2) mode = SECBOT_ARREST visible_message("[src] is trying to put handcuffs on [src.target]!",\ "[src] is trying to cut [src.target]'s hands off!") @@ -363,7 +367,7 @@ Auto Patrol: []"}, src.last_found = world.time src.frustration = 0 - playsound(get_turf(src), pick('sound/voice/bgod.ogg', 'sound/voice/biamthelaw.ogg', 'sound/voice/bsecureday.ogg', 'sound/voice/bradio.ogg', 'sound/voice/binsult.ogg', 'sound/voice/bcreep.ogg'), 50, 0) + playsound(src, pick('sound/voice/bgod.ogg', 'sound/voice/biamthelaw.ogg', 'sound/voice/bsecureday.ogg', 'sound/voice/bradio.ogg', 'sound/voice/binsult.ogg', 'sound/voice/bcreep.ogg'), 50, 0) // 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) @@ -689,7 +693,7 @@ Auto Patrol: []"}, src.target = M src.oldtarget_name = M.name src.speak("Level [src.threatlevel] infraction alert!") - playsound(get_turf(src), pick('sound/voice/bcriminal.ogg', 'sound/voice/bjustice.ogg', 'sound/voice/bfreeze.ogg'), 50, 0) + playsound(src, pick('sound/voice/bcriminal.ogg', 'sound/voice/bjustice.ogg', 'sound/voice/bfreeze.ogg'), 50, 0) src.visible_message("[src] points at [M.name]!") mode = SECBOT_HUNT spawn(0) @@ -786,7 +790,11 @@ Auto Patrol: []"}, Sa.overlays += image('icons/obj/aibots.dmi', "hs_hole") Sa.created_name = src.name new /obj/item/device/assembly/prox_sensor(Tsec) - new /obj/item/weapon/melee/baton/loaded(Tsec) + if(baton) + if(is_holder_of(src, baton)) + baton.forceMove(Tsec) + else + new /obj/item/weapon/melee/baton/loaded(Tsec) if(prob(50)) new /obj/item/robot_parts/l_arm(Tsec) @@ -853,7 +861,8 @@ Auto Patrol: []"}, var/obj/machinery/bot/secbot/S = new /obj/machinery/bot/secbot S.forceMove(get_turf(src)) S.name = src.created_name - qdel(W) + W.forceMove(S) + S.baton = W qdel(src) else if(istype(W, /obj/item/weapon/pen)) @@ -875,6 +884,19 @@ Auto Patrol: []"}, return 1 return 0 +/obj/machinery/bot/secbot/Destroy() + if(baton) + if(is_holder_of(src, baton)) + qdel(baton) + baton = null + + return ..() + +/obj/machinery/bot/secbot/proc/check_if_rigged() + if(baton && baton.bcell && baton.bcell.rigged && is_holder_of(src, baton)) + if(baton.bcell.explode()) + explode() + /obj/machinery/bot/secbot/beepsky/cheapsky name = "Officer Cheapsky" desc = "The budget cuts have hit Security the hardest." diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index 8167af6734e..26a48792974 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -162,11 +162,6 @@ var/list/camera_names=list() src.view_range = num cameranet.updateVisibility(src, 0) -/obj/machinery/camera/shock(var/mob/living/user) - if(!istype(user)) - return - user.electrocute_act(10, src) - /obj/machinery/camera/attack_paw(mob/living/carbon/alien/humanoid/user as mob) if(!istype(user)) return @@ -176,7 +171,7 @@ var/list/camera_names=list() update_icon() user.do_attack_animation(src, user) visible_message("\The [user] slashes at [src]!") - playsound(get_turf(src), 'sound/weapons/slash.ogg', 100, 1) + playsound(src, 'sound/weapons/slash.ogg', 100, 1) add_hiddenprint(user) deactivate(user,0) @@ -240,7 +235,7 @@ var/list/camera_messages = list() var/obj/U = locate(/obj) in assembly.upgrades if(U) to_chat(user, "You unattach \the [U] from the camera.") - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) + playsound(src, 'sound/items/Crowbar.ogg', 50, 1) U.forceMove(get_turf(src)) assembly.upgrades -= U update_upgrades() @@ -308,7 +303,7 @@ var/list/camera_messages = list() add_hiddenprint(user) else visible_message(" \The [src] deactivates!") - playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 50, 1) + playsound(src, 'sound/items/Wirecutter.ogg', 50, 1) add_hiddenprint(user) else if(user) @@ -316,7 +311,7 @@ var/list/camera_messages = list() add_hiddenprint(user) else visible_message(" \The [src] reactivates!") - playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 50, 1) + playsound(src, 'sound/items/Wirecutter.ogg', 50, 1) add_hiddenprint(user) cameranet.updateVisibility(src, 0) // now disconnect anyone using the camera @@ -333,15 +328,17 @@ var/list/camera_messages = list() /obj/machinery/camera/proc/triggerCameraAlarm() alarm_on = 1 + var/area/this_area = get_area(src) for(var/mob/living/silicon/S in mob_list) - S.triggerAlarm("Camera", areaMaster, list(src), src) + S.triggerAlarm("Camera", this_area, list(src), src) adv_camera.update(z, TRUE, list(src)) /obj/machinery/camera/proc/cancelCameraAlarm() alarm_on = 0 + var/area/this_area = get_area(src) for(var/mob/living/silicon/S in mob_list) - S.cancelAlarm("Camera", areaMaster, src) + S.cancelAlarm("Camera", this_area, src) adv_camera.update(z, TRUE, list(src)) /obj/machinery/camera/proc/can_use() @@ -400,7 +397,7 @@ var/list/camera_messages = list() // Do after stuff here to_chat(user, "You start to weld the [src].") - playsound(get_turf(src), 'sound/items/Welder.ogg', 50, 1) + playsound(src, 'sound/items/Welder.ogg', 50, 1) WT.eyecheck(user) busy = 1 if(do_after(user, src, 100)) diff --git a/code/game/machinery/camera/camera_assembly.dm b/code/game/machinery/camera/camera_assembly.dm index f4c317b6732..16e1ceb1fa5 100644 --- a/code/game/machinery/camera/camera_assembly.dm +++ b/code/game/machinery/camera/camera_assembly.dm @@ -36,7 +36,7 @@ if(0) // State 0 if(iswrench(W) && isturf(src.loc)) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + playsound(src, 'sound/items/Ratchet.ogg', 50, 1) to_chat(user, "You wrench the assembly into place.") anchored = 1 state = 1 @@ -54,7 +54,7 @@ return else if(iswrench(W)) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + playsound(src, 'sound/items/Ratchet.ogg', 50, 1) to_chat(user, "You unattach the assembly from it's place.") anchored = 0 update_icon() @@ -82,7 +82,7 @@ if(3) // State 3 if(isscrewdriver(W)) - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 50, 1) var/input = strip_html(input(usr, "Which networks would you like to connect this camera to? seperate networks with a comma. No Spaces!\nFor example: SS13,Security,Secret ", "Set Network", CAMERANET_SS13)) if(!input) @@ -116,7 +116,7 @@ else if(iswirecutter(W)) new/obj/item/stack/cable_coil(get_turf(src), 2) - playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 50, 1) + playsound(src, 'sound/items/Wirecutter.ogg', 50, 1) to_chat(user, "You cut the wires from the circuits.") state = 2 return @@ -142,7 +142,7 @@ var/obj/U = locate(/obj) in upgrades if(U) to_chat(user, "You unattach \the [U] from the assembly.") - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) + playsound(src, 'sound/items/Crowbar.ogg', 50, 1) U.forceMove(get_turf(src)) upgrades -= U return @@ -168,7 +168,7 @@ return 0 to_chat(user, "You start to weld the [src]...") - playsound(get_turf(src), 'sound/items/Welder.ogg', 50, 1) + playsound(src, 'sound/items/Welder.ogg', 50, 1) WT.eyecheck(user) busy = 1 if(do_after(user, src, 20)) diff --git a/code/game/machinery/camera/motion.dm b/code/game/machinery/camera/motion.dm index 09c5f96acd8..12cc7985de9 100644 --- a/code/game/machinery/camera/motion.dm +++ b/code/game/machinery/camera/motion.dm @@ -18,7 +18,7 @@ triggerAlarm() else if (detectTime == -1) for (var/mob/target in motionTargets) - if (target.stat == 2) + if (target.isDead()) lostTarget(target) // If not detecting with motion camera... if (!area_motion) @@ -44,18 +44,20 @@ /obj/machinery/camera/proc/cancelAlarm() if (detectTime == -1) + var/area/this_area = get_area(src) for (var/mob/living/silicon/aiPlayer in player_list) if (status) - aiPlayer.cancelAlarm("Motion", areaMaster) + aiPlayer.cancelAlarm("Motion", this_area) detectTime = 0 return 1 /obj/machinery/camera/proc/triggerAlarm() if (!detectTime) return 0 + var/area/this_area = get_area(src) for (var/mob/living/silicon/aiPlayer in player_list) if (status) - aiPlayer.triggerAlarm("Motion", areaMaster, src) + aiPlayer.triggerAlarm("Motion", this_area, src) detectTime = -1 return 1 diff --git a/code/game/machinery/cell_charger.dm b/code/game/machinery/cell_charger.dm index 0be94d4c103..dbe8e632773 100644 --- a/code/game/machinery/cell_charger.dm +++ b/code/game/machinery/cell_charger.dm @@ -75,7 +75,8 @@ to_chat(user, "There is already a cell in [src].") return else - if(areaMaster.power_equip == 0) // There's no APC in this area, don't try to cheat power! + var/area/this_area = get_area(src) + if(this_area.power_equip == 0) // There's no APC in this area, don't try to cheat power! to_chat(user, "[src] blinks red as you try to insert the cell!") return @@ -180,7 +181,7 @@ /datum/construction/reversible/crank_charger/spawn_result(mob/user as mob) if(result) - testing("[user] finished a [result]!") +// testing("[user] finished a [result]!") new result(get_turf(holder)) @@ -234,7 +235,8 @@ stored.charge += 100 state = !state update_icon() - playsound(get_turf(src), 'sound/items/crank.ogg',50,1) + stored.updateicon() + playsound(src, 'sound/items/crank.ogg',50,1) if(stored.charge>stored.maxcharge) stored.charge = stored.maxcharge else @@ -242,6 +244,7 @@ /obj/item/device/crank_charger/attack_hand(mob/user) if(stored && user.get_inactive_hand() == src) + stored.updateicon() user.put_in_hands(stored) stored = null update_icon() diff --git a/code/game/machinery/computer/HolodeckControl.dm b/code/game/machinery/computer/HolodeckControl.dm index e199bdc813e..57a0371ffb3 100644 --- a/code/game/machinery/computer/HolodeckControl.dm +++ b/code/game/machinery/computer/HolodeckControl.dm @@ -12,6 +12,8 @@ var/list/holographic_items = list() var/damaged = 0 var/last_change = 0 + + var/holopeople_enabled = FALSE //Set this to true to allow observers become holodudes var/list/connected_holopeople = list() var/maximum_holopeople = 4 @@ -37,9 +39,11 @@ return var/turf/spawnturf var/list/L = get_area_turfs(linkedholodeck.type) - var/turf/T = pick(L) - while(is_blocked_turf(T)) - T = pick(L) + + spawnturf = pick_n_take(L) + while(is_blocked_turf(spawnturf) && L.len) + spawnturf = pick_n_take(L) + if(spawnturf) user.forceMove(spawnturf) var/mob/living/simple_animal/hologram/advanced/H = user.transmogrify(/mob/living/simple_animal/hologram/advanced, TRUE) @@ -59,8 +63,16 @@ var/dat dat += {"Holodeck Control System
"} -// if(isobserver(user)) -// dat += {"
\[Become Advanced Hologram\]

"} + if(isobserver(user)) + if(holopeople_enabled) + dat += "
\[Become Advanced Hologram\]

" + else + dat += "
\[Advanced Holograms Unavailable\]

" + if(isAdminGhost(user)) + dat += "
ADMIN OPTIONS:
" + dat += "Advanced hologram spawning is: [holopeople_enabled ? "ENABLED" : "DISABLED"]
" + dat += "\[Become Advanced Hologram (Admin)\]

" + dat += {"
Current Loaded Programs:
((Basketball Court)
)
((Beach)
)
@@ -118,7 +130,14 @@ usr.set_machine(src) if(href_list["spawn_holoperson"]) - spawn_holoperson(usr) + if(holopeople_enabled || isAdminGhost(usr)) + spawn_holoperson(usr) + if(href_list["toggle_holopeople"]) + holopeople_enabled = !holopeople_enabled + src.updateUsrDialog() + + message_admins("[key_name(usr)] has [holopeople_enabled ? "enabled" : "disabled"] advanced hologram spawning at [formatJumpTo(src)]") + to_chat(usr, "Advanced holograms are now [holopeople_enabled ? "enabled" : "disabled"].") if(..()) return 1 @@ -281,7 +300,7 @@ return /obj/machinery/computer/HolodeckControl/emag(mob/user as mob) - playsound(get_turf(src), 'sound/effects/sparks4.ogg', 75, 1) + playsound(src, 'sound/effects/sparks4.ogg', 75, 1) if(emagged) return //No spamming emagged = 1 diff --git a/code/game/machinery/computer/ai_core.dm b/code/game/machinery/computer/ai_core.dm index 9064cb568b8..c3a89df5165 100644 --- a/code/game/machinery/computer/ai_core.dm +++ b/code/game/machinery/computer/ai_core.dm @@ -14,6 +14,7 @@ var/datum/ai_laws/laws var/obj/item/weapon/circuitboard/circuit = null var/obj/item/device/mmi/brain = null + sheet_type = /obj/item/stack/sheet/plasteel /obj/structure/AIcore/New() . = ..() @@ -47,7 +48,7 @@ if(!src || state != NOCIRCUITBOARD || !WT.remove_fuel(0, user)) return to_chat(user, "You deconstruct the frame.") - drop_stack(/obj/item/stack/sheet/plasteel, loc, 4, user) + drop_stack(sheet_type, loc, 4, user) qdel(src) if(istype(P, /obj/item/weapon/circuitboard/aicore) && !circuit) if(user.drop_item(P, src)) diff --git a/code/game/machinery/computer/arcade.dm b/code/game/machinery/computer/arcade.dm deleted file mode 100644 index bef912b8338..00000000000 --- a/code/game/machinery/computer/arcade.dm +++ /dev/null @@ -1,374 +0,0 @@ -/obj/machinery/computer/arcade - name = "arcade machine" - desc = "Does not support pinball." - icon = 'icons/obj/computer.dmi' - icon_state = "arcade" - circuit = "/obj/item/weapon/circuitboard/arcade" - var/enemy_name = "Space Villain" - var/temp = "Winners Don't Use Spacedrugs" //Temporary message, for attack messages, etc - var/player_hp = 30 //Player health/attack points - var/player_max_hp = 30 - var/player_mp = 10 - var/player_max_mp = 10 - var/enemy_hp = 45 //Enemy health/attack points - var/enemy_max_hp = 45 - var/enemy_mp = 20 - var/enemy_max_mp = 20 - var/gameover = 0 - var/blocked = 0 //Player cannot attack/heal while set - var/list/cheaters = list() //Trying to cheat twice at cuban pete gibs you - - machine_flags = EMAGGABLE | SCREWTOGGLE | CROWDESTROY | WRENCHMOVE | FIXED2WORK - emag_cost = 0 // because fun - - light_color = LIGHT_COLOR_GREEN - - var/list/prizes = list( /obj/item/weapon/storage/box/snappops = 2, - /obj/item/toy/cards = 2, - /obj/item/toy/blink = 2, - /obj/item/clothing/under/syndicate/tacticool = 2, - /obj/item/toy/sword = 2, - /obj/item/toy/bomb = 1, - /obj/item/toy/gun = 2, - /obj/item/toy/crossbow = 2, - /obj/item/weapon/storage/box/syndicatefake/space = 2, - /obj/item/weapon/storage/fancy/crayons = 2, - /obj/item/toy/spinningtoy = 2, - /obj/item/toy/minimeteor = 2, - /obj/item/device/whisperphone = 2, - /obj/item/weapon/storage/box/mechfigures = 1, - /obj/item/weapon/boomerang/toy = 1, - /obj/item/toy/foamblade = 1, - /obj/item/weapon/storage/box/actionfigure = 1, - /obj/item/toy/syndicateballoon/ntballoon = 1, - ) - -/obj/machinery/computer/arcade - var/turtle = 0 - -/obj/machinery/computer/arcade/New() - ..() - var/name_action - var/name_part1 - var/name_part2 - - name_action = pick("Defeat ", "Annihilate ", "Save ", "Strike ", "Stop ", "Destroy ", "Robust ", "Romance ", "Pwn ", "Own ") - - name_part1 = pick("the Automatic ", "Farmer ", "Lord ", "Professor ", "the Cuban ", "the Evil ", "the Dread King ", "the Space ", "Lord ", "the Great ", "Duke ", "General ") - name_part2 = pick("Melonoid", "Murdertron", "Sorcerer", "Ruin", "Jeff", "Ectoplasm", "Crushulon", "Uhangoid", "Vhakoid", "Peteoid", "slime", "Griefer", "ERPer", "Lizard Man", "Unicorn") - - src.enemy_name = replacetext((name_part1 + name_part2), "the ", "") - src.name = (name_action + name_part1 + name_part2) - - -/obj/machinery/computer/arcade/proc/import_game_data(var/obj/item/weapon/circuitboard/arcade/A) - if(!A || !A.game_data || !A.game_data.len) - return - name = A.game_data["name"] - emagged = A.game_data["emagged"] - enemy_name = A.game_data["enemy_name"] - temp = A.game_data["temp"] - player_hp = A.game_data["player_hp"] - player_max_hp = A.game_data["player_max_hp"] - player_mp = A.game_data["player_mp"] - player_max_mp = A.game_data["player_max_mp"] - enemy_hp = A.game_data["enemy_hp"] - enemy_max_hp = A.game_data["enemy_max_hp"] - enemy_mp = A.game_data["enemy_mp"] - enemy_max_mp = A.game_data["enemy_max_mp"] - gameover = A.game_data["gameover"] - blocked = A.game_data["blocked"] - -/obj/machinery/computer/arcade/proc/export_game_data(var/obj/item/weapon/circuitboard/arcade/A) - if(!A) - return - if(!A.game_data) - A.game_data = list() - A.game_data.len = 0 - A.game_data["name"] = name - A.game_data["emagged"] = emagged - A.game_data["enemy_name"] = enemy_name - A.game_data["temp"] = temp - A.game_data["player_hp"] = player_hp - A.game_data["player_max_hp"] = player_max_hp - A.game_data["player_mp"] = player_mp - A.game_data["player_max_mp"] = player_max_mp - A.game_data["enemy_hp"] = enemy_hp - A.game_data["enemy_max_hp"] = enemy_max_hp - A.game_data["enemy_mp"] = enemy_mp - A.game_data["enemy_max_mp"] = enemy_max_mp - A.game_data["gameover"] = gameover - A.game_data["blocked"] = blocked - - -/obj/machinery/computer/arcade/attack_ai(mob/user as mob) - src.add_hiddenprint(user) - return src.attack_hand(user) - -/obj/machinery/computer/arcade/attack_paw(mob/user as mob) - return src.attack_hand(user) - -/obj/machinery/computer/arcade/attack_hand(mob/user as mob) - if(..()) - return - user.set_machine(src) - var/dat = "Close" - - dat += {"

[src.enemy_name]

-

[src.temp]

-
Health: [src.player_hp] | Magic: [src.player_mp] | Enemy Health: [src.enemy_hp]
"} - if (src.gameover) - dat += "
New Game" - else - - dat += {"
Attack | - Heal | - Recharge Power"} - - dat += "
" - - user << browse(dat, "window=arcade") - onclose(user, "arcade") - return - -/obj/machinery/computer/arcade/proc/action_attack() - src.blocked = 1 - var/attackamt = rand(2,6) - src.temp = "You attack for [attackamt] damage!" - src.updateUsrDialog() - if(turtle > 0) - turtle-- - - sleep(10) - src.enemy_hp -= attackamt - src.arcade_action() - -/obj/machinery/computer/arcade/proc/action_heal() - src.blocked = 1 - var/pointamt = rand(1,3) - var/healamt = rand(6,8) - src.temp = "You use [pointamt] magic to heal for [healamt] damage!" - src.updateUsrDialog() - turtle++ - - sleep(10) - src.player_mp -= pointamt - src.player_hp += healamt - src.blocked = 1 - src.updateUsrDialog() - src.arcade_action() - -/obj/machinery/computer/arcade/proc/action_charge() - src.blocked = 1 - var/chargeamt = rand(4,7) - src.temp = "You regain [chargeamt] points" - src.player_mp += chargeamt - if(turtle > 0) - turtle-- - - src.updateUsrDialog() - sleep(10) - src.arcade_action() - -/obj/machinery/computer/arcade/Topic(href, href_list) - if(..()) - return - - if (!src.blocked && !src.gameover) - if (href_list["attack"]) - action_attack() - - else if (href_list["heal"]) - action_heal() - - else if (href_list["charge"]) - action_charge() - - if (href_list["close"]) - usr.unset_machine() - usr << browse(null, "window=arcade") - - else if (href_list["newgame"]) //Reset everything - if(is_cheater(usr)) - return - - temp = "New Round" - player_hp = player_max_hp - player_mp = player_max_mp - enemy_hp = enemy_max_hp - enemy_mp = enemy_max_mp - gameover = 0 - turtle = 0 - - if(emagged) - src.New() - emagged = 0 - - src.add_fingerprint(usr) - src.updateUsrDialog() - return - -/obj/machinery/computer/arcade/proc/arcade_action() - if ((src.enemy_mp <= 0) || (src.enemy_hp <= 0)) - if(!gameover) - src.gameover = 1 - src.temp = "[src.enemy_name] has fallen! Rejoice!" - - if(emagged) - feedback_inc("arcade_win_emagged") - new /obj/item/clothing/head/collectable/petehat(src.loc) - new /obj/item/device/maracas/cubanpete(src.loc) - new /obj/item/device/maracas/cubanpete(src.loc) - message_admins("[key_name_admin(usr)] has outbombed Cuban Pete and been awarded explosive maracas.") - log_game("[key_name_admin(usr)] has outbombed Cuban Pete and been awarded explosive maracas.") - src.New() - emagged = 0 - - else if(!contents.len) - feedback_inc("arcade_win_normal") - var/prizeselect = pickweight(prizes) - new prizeselect(src.loc) - - if(istype(prizeselect, /obj/item/toy/gun)) //Ammo comes with the gun - new /obj/item/toy/ammo/gun(src.loc) - - else if(istype(prizeselect, /obj/item/clothing/suit/syndicatefake)) //Helmet is part of the suit - new /obj/item/clothing/head/syndicatefake(src.loc) - - else //admins can varedit arcades to have special prizes via contents, but it removes the prize rather than spawn a new one - feedback_inc("arcade_win_normal") - var/atom/movable/prize = pick(contents) - prize.forceMove(src.loc) - - else if (emagged && (turtle >= 4)) - var/boomamt = rand(5,10) - src.temp = "[src.enemy_name] throws a bomb, exploding you for [boomamt] damage!" - src.player_hp -= boomamt - - else if ((src.enemy_mp <= 5) && (prob(70))) - var/stealamt = rand(2,3) - src.temp = "[src.enemy_name] steals [stealamt] of your power!" - src.player_mp -= stealamt - src.updateUsrDialog() - - if (src.player_mp <= 0) - src.gameover = 1 - sleep(10) - src.temp = "You have been drained! GAME OVER" - if(emagged) - feedback_inc("arcade_loss_mana_emagged") - usr.gib() - else - feedback_inc("arcade_loss_mana_normal") - - else if ((src.enemy_hp <= 10) && (src.enemy_mp > 4)) - src.temp = "[src.enemy_name] heals for 4 health!" - src.enemy_hp += 4 - src.enemy_mp -= 4 - - else - var/attackamt = rand(3,6) - src.temp = "[src.enemy_name] attacks for [attackamt] damage!" - src.player_hp -= attackamt - - if ((src.player_mp <= 0) || (src.player_hp <= 0)) - src.gameover = 1 - src.temp = "You have been crushed! GAME OVER" - if(emagged) - feedback_inc("arcade_loss_hp_emagged") - usr.gib() - else - feedback_inc("arcade_loss_hp_normal") - - src.blocked = 0 - return - -/obj/machinery/computer/arcade/emag(mob/user as mob) - if(is_cheater(user)) - return - - temp = "If you die in the game, you die for real!" - player_hp = 30 - player_mp = 10 - enemy_hp = 45 - enemy_mp = 20 - gameover = 0 - blocked = 0 - - emagged = 1 - - enemy_name = "Cuban Pete" - name = "Outbomb Cuban Pete" - - src.updateUsrDialog() - -/obj/machinery/computer/arcade/emp_act(severity) - if(stat & (NOPOWER|BROKEN)) - ..(severity) - return - var/empprize = null - var/num_of_prizes = 0 - switch(severity) - if(1) - num_of_prizes = rand(1,4) - if(2) - num_of_prizes = rand(0,2) - for(num_of_prizes; num_of_prizes > 0; num_of_prizes--) - empprize = pickweight(prizes) - new empprize(src.loc) - - ..(severity) - -/obj/machinery/computer/arcade/togglePanelOpen(var/obj/toggleitem, mob/user) - if(is_cheater(user)) - return - - var/obj/item/weapon/circuitboard/arcade/A - if(circuit) - A = new - export_game_data(A) - ..(toggleitem, user, A) - -/obj/machinery/computer/arcade/kick_act() - ..() - if(stat & (NOPOWER|BROKEN)) - return - - if(is_cheater(usr)) - return - - if(!emagged && prob(5)) //Bug - temp = "|eW R0vnb##[rand(0,9)]#" - player_hp = rand(1,30) - player_mp = rand(1,10) - enemy_hp = rand(1,60) - enemy_mp = rand(1,40) - gameover = 0 - turtle = 0 - -/obj/machinery/computer/arcade/proc/is_cheater(mob/user as mob) - var/cheater = 0 - if(emagged && !gameover) - if(stat & (NOPOWER|BROKEN)) - return cheater - else if(user in cheaters) - to_chat(usr, "[src.enemy_name] throws a bomb at you for trying to cheat him again.") - explosion(get_turf(src.loc),-1,0,2)//IED sized explosion - user.gib() - cheaters = null - qdel(src) - cheater = 1 - else - to_chat(usr, "[src.enemy_name] isn't one to tolerate cheaters. Don't try that again.") - cheaters += user - cheater = 1 - return cheater - -/obj/machinery/computer/arcade/npc_tamper_act(mob/living/L) - switch(rand(0,2)) - if(0) - action_attack() - if(1) - action_heal() - if(2) - action_charge() diff --git a/code/game/machinery/computer/arcade/arcade.dm b/code/game/machinery/computer/arcade/arcade.dm new file mode 100644 index 00000000000..680bb82db30 --- /dev/null +++ b/code/game/machinery/computer/arcade/arcade.dm @@ -0,0 +1,74 @@ +/obj/machinery/computer/arcade + name = "arcade machine" + desc = "Does not support pinball." + icon = 'icons/obj/computer.dmi' + icon_state = "arcade" + circuit = "/obj/item/weapon/circuitboard/arcade" + var/datum/arcade_game/game + machine_flags = EMAGGABLE | SCREWTOGGLE | CROWDESTROY | WRENCHMOVE | FIXED2WORK + emag_cost = 0 // because fun + light_color = LIGHT_COLOR_GREEN + + +/obj/machinery/computer/arcade/New() + ..() + game = new /datum/arcade_game/space_villain(src) + name = game.name + +/obj/machinery/computer/arcade/Destroy() + if(game) + qdel(game) + game = null + ..() + +/obj/machinery/computer/arcade/proc/import_game_data(var/obj/item/weapon/circuitboard/arcade/A) + if(!A || !A.game_data || !A.game_data.len) + return + game.import_data(A.game_data) + +/obj/machinery/computer/arcade/proc/export_game_data(var/obj/item/weapon/circuitboard/arcade/A) + if(!A) + return + if(!A.game_data) + A.game_data = list() + A.game_data.len = 0 + A.game_data = game.export_data() + +/obj/machinery/computer/arcade/attack_hand(mob/user) + if(..()) + return + user.set_machine(src) + var/dat = game.get_dat() + + user << browse(dat, "window=arcade") + onclose(user, "arcade") + +/obj/machinery/computer/arcade/emag(mob/user) + game.emag_act(user) + +/obj/machinery/computer/arcade/emp_act(severity) + if(stat & (NOPOWER|BROKEN)) + ..(severity) + return + game.emp_act(severity) + ..(severity) + +/obj/machinery/computer/arcade/togglePanelOpen(var/obj/toggleitem, mob/user) + if(game.is_cheater(user)) + return + + var/obj/item/weapon/circuitboard/arcade/A + if(circuit) + A = new + export_game_data(A) + ..(toggleitem, user, A) + +/obj/machinery/computer/arcade/kick_act() + ..() + if(stat & (NOPOWER|BROKEN)) + return + + game.kick_act() + +/obj/machinery/computer/arcade/npc_tamper_act(mob/living/L) + game.npc_tamper_act(L) \ No newline at end of file diff --git a/code/game/machinery/computer/arcade/arcade_game.dm b/code/game/machinery/computer/arcade/arcade_game.dm new file mode 100644 index 00000000000..afb04214b3e --- /dev/null +++ b/code/game/machinery/computer/arcade/arcade_game.dm @@ -0,0 +1,362 @@ +/datum/arcade_game + var/name = "arcade game" + var/obj/machinery/computer/arcade/holder + var/list/prizes = list() + var/list/cheaters = list() + var/emagged = 0 + +/datum/arcade_game/Destroy() + cheaters = null + holder = null + ..() + +/datum/arcade_game/proc/import_data(var/list/args) + if(!args || !args["arcade_type"]) + return 0 + if(args["arcade_type"] != type) + return 0 + return 1 + +/datum/arcade_game/proc/export_data() + return list() + +/datum/arcade_game/proc/get_dat() + return "" + + +/datum/arcade_game/proc/is_cheater(mob/user) + if(user in cheaters) + return 1 + return 0 + +/datum/arcade_game/proc/emag_act(mob/user) + +/datum/arcade_game/proc/emp_act(var/severity) + +/datum/arcade_game/proc/kick_act() + +/datum/arcade_game/proc/npc_tamper_act(mob/living/L) + +/datum/arcade_game/New(var/holder) + ..() + src.holder = holder + +/datum/arcade_game/space_villain + var/enemy_name = "Space Villain" + var/temp = "Winners Don't Use Spacedrugs" //Temporary message, for attack messages, etc + var/player_hp = 30 //Player health/attack points + var/player_max_hp = 30 + var/player_mp = 10 + var/player_max_mp = 10 + var/enemy_hp = 45 //Enemy health/attack points + var/enemy_max_hp = 45 + var/enemy_mp = 20 + var/enemy_max_mp = 20 + var/gameover = 0 + var/blocked = 0 //Player cannot attack/heal while set + var/turtle = 0 //Is the player turtling? + prizes = list(/obj/item/weapon/storage/box/snappops = 2, + /obj/item/toy/cards = 2, + /obj/item/toy/blink = 2, + /obj/item/clothing/under/syndicate/tacticool = 2, + /obj/item/toy/sword = 2, + /obj/item/toy/bomb = 1, + list(/obj/item/toy/gun, /obj/item/toy/ammo/gun) = 2, + /obj/item/toy/crossbow = 2, + /obj/item/weapon/storage/box/syndicatefake/space = 2, + /obj/item/weapon/storage/fancy/crayons = 2, + /obj/item/toy/spinningtoy = 2, + /obj/item/toy/minimeteor = 2, + /obj/item/device/whisperphone = 2, + /obj/item/weapon/storage/box/mechfigures = 1, + /obj/item/weapon/boomerang/toy = 1, + /obj/item/toy/foamblade = 1, + /obj/item/weapon/storage/box/actionfigure = 1, + /obj/item/toy/syndicateballoon/ntballoon = 1, + ) + +/datum/arcade_game/space_villain/New() + ..() + var/name_action + var/name_part1 + var/name_part2 + + name_action = pick("Defeat ", "Annihilate ", "Save ", "Strike ", "Stop ", "Destroy ", "Robust ", "Romance ", "Pwn ", "Own ") + + name_part1 = pick("the Automatic ", "Farmer ", "Lord ", "Professor ", "the Cuban ", "the Evil ", "the Dread King ", "the Space ", "Lord ", "the Great ", "Duke ", "General ") + name_part2 = pick("Melonoid", "Murdertron", "Sorcerer", "Ruin", "Jeff", "Ectoplasm", "Crushulon", "Uhangoid", "Vhakoid", "Peteoid", "slime", "Griefer", "ERPer", "Lizard Man", "Unicorn") + + enemy_name = replacetext((name_part1 + name_part2), "the ", "") + name = (name_action + name_part1 + name_part2) + +/datum/arcade_game/space_villain/export_data() + return list("name" = name, + "emagged" = emagged, + "enemy_name" = enemy_name, + "temp" = temp, + "player_hp" = player_hp, + "player_max_hp" = player_max_hp, + "player_mp" = player_mp, + "player_max_mp" = player_max_mp, + "enemy_hp" = enemy_hp, + "enemy_max_hp" = enemy_max_hp, + "enemy_mp" = enemy_mp, + "enemy_max_mp" = enemy_max_mp, + "gameover" = gameover, + "blocked" = blocked, + "arcade_type" = type, + ) + +/datum/arcade_game/space_villain/import_data(var/list/args) + if(!..()) + return + name = args["name"] + emagged = args["emagged"] + enemy_name = args["enemy_name"] + temp = args["temp"] + player_hp = args["player_hp"] + player_max_hp = args["player_max_hp"] + player_mp = args["player_mp"] + player_max_mp = args["player_max_mp"] + enemy_hp = args["enemy_hp"] + enemy_max_hp = args["enemy_max_hp"] + enemy_mp = args["enemy_mp"] + enemy_max_mp = args["enemy_max_mp"] + gameover = args["gameover"] + blocked = args["blocked"] + +/datum/arcade_game/space_villain/get_dat() + var/dat = "Close" + + dat += {"

[enemy_name]

+

[temp]

+
Health: [player_hp] | Magic: [player_mp] | Enemy Health: [enemy_hp]
"} + if (gameover) + dat += "
New Game" + else + + dat += {"
Attack | + Heal | + Recharge Power"} + + dat += "
" + + return dat + +/datum/arcade_game/space_villain/Topic(href, href_list) + if(..()) + return + if (!blocked && !gameover) + if (href_list["attack"]) + action_attack() + + else if (href_list["heal"]) + action_heal() + + else if (href_list["charge"]) + action_charge() + + if (href_list["close"]) + usr.unset_machine() + usr << browse(null, "window=arcade") + + else if (href_list["newgame"]) //Reset everything + if(is_cheater(usr)) + return + + temp = "New Round" + player_hp = player_max_hp + player_mp = player_max_mp + enemy_hp = enemy_max_hp + enemy_mp = enemy_max_mp + gameover = 0 + turtle = 0 + + if(emagged) + New() + emagged = 0 + + holder.add_fingerprint(usr) + holder.updateUsrDialog() + + +/datum/arcade_game/space_villain/proc/arcade_action() + if ((enemy_mp <= 0) || (enemy_hp <= 0)) + if(!gameover) + gameover = 1 + temp = "[enemy_name] has fallen! Rejoice!" + + if(emagged) + feedback_inc("arcade_win_emagged") + new /obj/item/clothing/head/collectable/petehat(holder.loc) + new /obj/item/device/maracas/cubanpete(holder.loc) + new /obj/item/device/maracas/cubanpete(holder.loc) + message_admins("[key_name_admin(usr)] has outbombed Cuban Pete and been awarded explosive maracas.") + log_game("[key_name_admin(usr)] has outbombed Cuban Pete and been awarded explosive maracas.") + holder.New() + emagged = 0 + + else if(!holder.contents.len) + feedback_inc("arcade_win_normal") + var/prizeselect = pickweight(prizes) + if(islist(prizeselect)) + for(var/i in prizeselect) + new i(holder.loc) + else + new prizeselect(holder.loc) + + else //admins can varedit arcades to have special prizes via contents, but it removes the prize rather than spawn a new one + feedback_inc("arcade_win_normal") + var/atom/movable/prize = pick(holder.contents) + prize.forceMove(holder.loc) + + else if (emagged && (turtle >= 4)) + var/boomamt = rand(5,10) + temp = "[enemy_name] throws a bomb, exploding you for [boomamt] damage!" + player_hp -= boomamt + + else if ((enemy_mp <= 5) && (prob(70))) + var/stealamt = rand(2,3) + temp = "[enemy_name] steals [stealamt] of your power!" + player_mp -= stealamt + holder.updateUsrDialog() + + if (player_mp <= 0) + gameover = 1 + sleep(10) + temp = "You have been drained! GAME OVER" + if(emagged) + feedback_inc("arcade_loss_mana_emagged") + usr.gib() + else + feedback_inc("arcade_loss_mana_normal") + + else if ((enemy_hp <= 10) && (enemy_mp > 4)) + temp = "[enemy_name] heals for 4 health!" + enemy_hp += 4 + enemy_mp -= 4 + + else + var/attackamt = rand(3,6) + temp = "[enemy_name] attacks for [attackamt] damage!" + player_hp -= attackamt + + if ((player_mp <= 0) || (player_hp <= 0)) + gameover = 1 + temp = "You have been crushed! GAME OVER" + if(emagged) + feedback_inc("arcade_loss_hp_emagged") + usr.gib() + else + feedback_inc("arcade_loss_hp_normal") + + blocked = 0 + +/datum/arcade_game/space_villain/proc/action_charge() + blocked = 1 + var/chargeamt = rand(4,7) + temp = "You regain [chargeamt] points" + player_mp += chargeamt + if(turtle > 0) + turtle-- + + holder.updateUsrDialog() + sleep(10) + arcade_action() + +/datum/arcade_game/space_villain/proc/action_heal() + blocked = 1 + var/pointamt = rand(1,3) + var/healamt = rand(6,8) + temp = "You use [pointamt] magic to heal for [healamt] damage!" + holder.updateUsrDialog() + turtle++ + + sleep(10) + player_mp -= pointamt + player_hp += healamt + blocked = 1 + holder.updateUsrDialog() + arcade_action() + +/datum/arcade_game/space_villain/proc/action_attack() + blocked = 1 + var/attackamt = rand(2,6) + temp = "You attack for [attackamt] damage!" + holder.updateUsrDialog() + if(turtle > 0) + turtle-- + + sleep(10) + enemy_hp -= attackamt + arcade_action() + +/datum/arcade_game/space_villain/is_cheater(mob/user) + if(emagged && !gameover) + if(holder.stat & (NOPOWER|BROKEN)) + return 0 + else if(user in cheaters) + to_chat(usr, "[enemy_name] throws a bomb at you for trying to cheat him again.") + explosion(holder.loc,-1,0,2)//IED sized explosion + user.gib() + cheaters = null + qdel(src) + return 1 + else + to_chat(usr, "[enemy_name] isn't one to tolerate cheaters. Don't try that again.") + cheaters += user + return 1 + return 0 + +/datum/arcade_game/space_villain/emag_act(mob/user) + if(is_cheater(user)) + return + + temp = "If you die in the game, you die for real!" + player_hp = 30 + player_mp = 10 + enemy_hp = 45 + enemy_mp = 20 + gameover = 0 + blocked = 0 + + emagged = 1 + + enemy_name = "Cuban Pete" + name = "Outbomb Cuban Pete" + + holder.updateUsrDialog() + +/datum/arcade_game/space_villain/emp_act(var/severity) + var/empprize = null + var/num_of_prizes = 0 + switch(severity) + if(1) + num_of_prizes = rand(1,4) + if(2) + num_of_prizes = rand(0,2) + for(num_of_prizes; num_of_prizes > 0; num_of_prizes--) + empprize = pickweight(prizes) + new empprize(holder.loc) + +/datum/arcade_game/space_villain/kick_act() + if(is_cheater(usr)) + return + + if(!emagged && prob(5)) //Bug + temp = "|eW R0vnb##[rand(0,9)]#" + player_hp = rand(1,30) + player_mp = rand(1,10) + enemy_hp = rand(1,60) + enemy_mp = rand(1,40) + gameover = 0 + turtle = 0 + +/datum/arcade_game/space_villain/npc_tamper_act(mob/living/L) + switch(rand(0,2)) + if(0) + action_attack() + if(1) + action_heal() + if(2) + action_charge() diff --git a/code/game/machinery/computer/buildandrepair.dm b/code/game/machinery/computer/buildandrepair.dm index 727403b22f4..85409b8ce7b 100644 --- a/code/game/machinery/computer/buildandrepair.dm +++ b/code/game/machinery/computer/buildandrepair.dm @@ -383,9 +383,9 @@ if(do_after(user, src, 10) && state == 0) if(!src || !WT.isOn()) return - playsound(get_turf(src), 'sound/items/Welder.ogg', 50, 1) + playsound(src, 'sound/items/Welder.ogg', 50, 1) user.visible_message("[user] welds the frame back into metal.", "You weld the frame back into metal.", "You hear welding.") - drop_stack(/obj/item/stack/sheet/metal/, loc, 5, user) + drop_stack(sheet_type, loc, 5, user) state = -1 qdel(src) return 1 @@ -399,7 +399,7 @@ if(!user.drop_item(B, src)) return - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) user.visible_message("[user] places \the [B] inside the frame.", "You place \the [B] inside the frame.", "You hear metallic sounds.") src.icon_state = "1" src.circuit = P @@ -407,13 +407,13 @@ to_chat(user, "This frame does not accept circuit boards of this type!") return 1 if(isscrewdriver(P) && circuit) - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 50, 1) user.visible_message("[user] screws the circuit board into place.", "You screw the circuit board into place.", "You hear metallic sounds.") src.state = 2 src.icon_state = "2" return 1 if(iscrowbar(P) && circuit) - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) + playsound(src, 'sound/items/Crowbar.ogg', 50, 1) user.visible_message("[user] removes the circuit board.", "You remove the circuit board", "You hear metallic sounds.") src.state = 1 src.icon_state = "0" @@ -422,7 +422,7 @@ return 1 if(2) if(isscrewdriver(P) && circuit) - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 50, 1) user.visible_message("[user] unfastens the circuit board.", "You unfasten the circuit board.", "You hear metallic sounds.") src.state = 1 src.icon_state = "1" @@ -433,7 +433,7 @@ to_chat(user, "You need at least 5 lengths of cable coil for this!") return 1 to_chat(user, "You begin to install wires into the frame.") - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) if (do_after(user, src, 20) && state == 2 && C.amount >= 5) C.use(5) user.visible_message("[user] installs wires into the frame.", "You install wires into the frame.", "You hear metallic sounds.") @@ -443,7 +443,7 @@ return 1 if(3) if(iswirecutter(P)) - playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 50, 1) + playsound(src, 'sound/items/Wirecutter.ogg', 50, 1) user.visible_message("[user] unplugs the wires from the frame.", "You unplug the wires from the frame.", "You hear metallic sounds.") src.state = 2 src.icon_state = "2" @@ -457,7 +457,7 @@ return 1 to_chat(user, "You start installing the glass panel onto the frame.") if(do_after(user, src, 20) && state == 3 && G.amount >= 2) - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) G.use(2) user.visible_message("[user] installs the glass panel onto the frame.", "You install the glass panel onto the frame.", "You hear metallic sounds.") src.state = 4 @@ -466,14 +466,17 @@ return 1 if(4) if(iscrowbar(P)) - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) + playsound(src, 'sound/items/Crowbar.ogg', 50, 1) user.visible_message("[user] removes the glass panel from the frame.", "You remove the glass panel from the frame.", "You hear metallic sounds.") src.state = 3 src.icon_state = "3" new /obj/item/stack/sheet/glass/glass( src.loc, 2 ) return 1 if(isscrewdriver(P)) - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 50, 1) + if(!circuit.build_path) // the board has been soldered away! + to_chat(user, "You connect the monitor, but nothing turns on!") + return to_chat(user, "You connect the monitor.") var/B = new src.circuit.build_path ( src.loc ) if(circuit.powernet) @@ -492,6 +495,9 @@ var/obj/machinery/computer/arcade/arcade = B var/obj/item/weapon/circuitboard/arcade/C = circuit arcade.import_game_data(C) + var/obj/machinery/MA = B + if(istype(MA)) + MA.power_change() qdel(src) return 1 return 0 diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm index 545a79f3a7a..12f673b3c91 100644 --- a/code/game/machinery/computer/camera.dm +++ b/code/game/machinery/computer/camera.dm @@ -144,9 +144,9 @@ var/global/list/tv_monitors = list() /obj/machinery/computer/security/engineering name = "Engineering Cameras" - desc = "Used to monitor fires and breaches." + desc = "Used to monitor engineering silicons and alarms." icon_state = "engineeringcameras" - network = list(CAMERANET_POWERALARMS,CAMERANET_ATMOSALARMS,CAMERANET_FIREALARMS) + network = list(CAMERANET_ENGI,CAMERANET_POWERALARMS,CAMERANET_ATMOSALARMS,CAMERANET_FIREALARMS) circuit = "/obj/item/weapon/circuitboard/security/engineering" light_color = LIGHT_COLOR_YELLOW diff --git a/code/game/machinery/computer/cargo.dm b/code/game/machinery/computer/cargo.dm index a13d22acf04..8c61451c533 100644 --- a/code/game/machinery/computer/cargo.dm +++ b/code/game/machinery/computer/cargo.dm @@ -15,6 +15,9 @@ For vending packs, see vending_packs.dm*/ return 0 acc_info["idname"] = usr_id.registered_name acc_info["idrank"] = usr_id.GetJobName() + else if(isAI(user)) + acc_info["idname"] = user.real_name + acc_info["idrank"] = "AI" else if(issilicon(user)) acc_info["idname"] = user.real_name acc_info["idrank"] = "Cyborg" diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm index ad8937023c5..f98ed88bec3 100644 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -5,7 +5,12 @@ #define COMM_SCREEN_SECLEVEL 4 #define COMM_SCREEN_ERT 5 +#define UNAUTH 0 +#define AUTH_HEAD 1 +#define AUTH_CAPT 2 + var/shuttle_call/shuttle_calls[0] +var/global/ports_open = TRUE #define SHUTTLE_RECALL -1 #define SHUTTLE_CALL 1 @@ -41,7 +46,7 @@ var/shuttle_call/shuttle_calls[0] req_access = list(access_heads) circuit = "/obj/item/weapon/circuitboard/communications" var/prints_intercept = 1 - var/authenticated = 0 + var/authenticated = UNAUTH //1 = normal login, 2 = emagged or had access_captain, 0 = logged out. Gremlins can set to 1 or 0. var/list/messagetitle = list() var/list/messagetext = list() var/currmsg = 0 @@ -90,11 +95,11 @@ var/shuttle_call/shuttle_calls[0] emag(usr) if (I && istype(I)) if(src.check_access(I)) - authenticated = 1 - if(20 in I.access) - authenticated = 2 + authenticated = AUTH_HEAD + if(access_captain in I.access) + authenticated = AUTH_CAPT if("logout") - authenticated = 0 + authenticated = UNAUTH setMenuState(usr,COMM_SCREEN_MAIN) // ALART LAVUL if("changeseclevel") @@ -109,8 +114,8 @@ var/shuttle_call/shuttle_calls[0] if (istype(I, /obj/item/device/pda)) var/obj/item/device/pda/pda = I I = pda.id - if (I && istype(I)) - if(access_heads in I.access) //Let heads change the alert level. + if (isAdminGhost(usr) || (I && istype(I))) + if(isAdminGhost(usr) || (access_heads in I.access)) //Let heads change the alert level. var/old_level = security_level if(!tmp_alertlevel) tmp_alertlevel = SEC_LEVEL_GREEN @@ -138,7 +143,7 @@ var/shuttle_call/shuttle_calls[0] to_chat(usr, "You need to swipe your ID.") if("announce") - if(src.authenticated==2 && !issilicon(usr)) + if(authenticated==AUTH_CAPT && !issilicon(usr)) if(message_cooldown) return var/input = stripped_input(usr, "Please choose a message to announce to the station crew.", "What?") @@ -153,14 +158,6 @@ var/shuttle_call/shuttle_calls[0] message_cooldown = 0 if("emergency_screen") - var/mob/M = usr - var/obj/item/weapon/card/id/I = M.get_active_hand() - if (istype(I, /obj/item/device/pda)) - var/obj/item/device/pda/pda = I - I = pda.id - //if (I && istype(I)) - // if(access_captain in I.access) - // authenticated = 2 if(!authenticated) to_chat(usr, "You do not have clearance to use this function.") return @@ -188,13 +185,6 @@ var/shuttle_call/shuttle_calls[0] to_chat(usr, "Central Command has already dispatched a Response Team to [station_name()]") return - //if(world.time < 6000) - // to_chat(usr, "The emergency response team is away on another mission, Please wait another [round((6000-world.time)/600)] minute\s before trying again.") - // return - - //if(emergency_shuttle.online) - // to_chat(usr, "The emergency shuttle is already on its way.") - // return if(!(get_security_level() in list("red", "delta"))) to_chat(usr, "The station must be in an emergency to request a Response Team.") return @@ -220,8 +210,8 @@ var/shuttle_call/shuttle_calls[0] return if("callshuttle") - if(src.authenticated) - if(!map.linked_to_centcomm) + if(authenticated || isAdminGhost(usr)) + if(!map.linked_to_centcomm && !isAdminGhost(usr)) //We don't need a connection if we're an admin to_chat(usr, "Error: No connection can be made to central command.") return var/justification = stripped_input(usr, "Please input a concise justification for the shuttle call. Note that failure to properly justify a shuttle call may lead to recall or termination.", "Nanotrasen Anti-Comdom Systems") @@ -234,12 +224,12 @@ var/shuttle_call/shuttle_calls[0] post_status("shuttle") setMenuState(usr,COMM_SCREEN_MAIN) if("cancelshuttle") - if(!map.linked_to_centcomm) + if(!map.linked_to_centcomm && !isAdminGhost(usr)) to_chat(usr, "Error: No connection can be made to central command.") return if(issilicon(usr)) return - if(src.authenticated) + if(authenticated || isAdminGhost(usr)) var/response = alert("Are you sure you wish to recall the shuttle?", "Confirm", "Yes", "No") if(response == "Yes") recall_shuttle(usr) @@ -293,7 +283,7 @@ var/shuttle_call/shuttle_calls[0] // OMG CENTCOMM LETTERHEAD if("MessageCentcomm") - if(src.authenticated==2) + if(authenticated==AUTH_CAPT) if(!map.linked_to_centcomm) to_chat(usr, "Error: No connection can be made to central command.") return @@ -315,7 +305,7 @@ var/shuttle_call/shuttle_calls[0] // OMG SYNDICATE ...LETTERHEAD if("MessageSyndicate") - if((src.authenticated==2) && (src.emagged)) + if(src.authenticated==AUTH_CAPT && emagged) if(!map.linked_to_centcomm) to_chat(usr, "Error: No connection can be made to \[ABNORMAL ROUTING CORDINATES\] .") return @@ -340,6 +330,42 @@ var/shuttle_call/shuttle_calls[0] setMenuState(usr,COMM_SCREEN_MAIN) update_icon() + if("SetPortRestriction") + if(issilicon(usr)) + return + var/mob/M = usr + var/obj/item/weapon/card/id/I = M.get_id_card() + if (I || isAdminGhost(usr)) + if(isAdminGhost(usr) || (access_hos in I.access) || (access_heads in I.access && security_level >= SEC_LEVEL_RED)) + if(ports_open) + var/reason = stripped_input(usr, "Please input a concise justification for port closure. This reason will be transmitted to the trader shuttle.", "Nanotrasen Anti-Comdom Systems") as null|text + if(!reason || !(usr in view(1,src))) + return + log_game("[key_name(usr)] closed the port to traders for [reason].") + message_admins("[key_name_admin(usr)] closed the port to traders for [reason].") + if(trade_shuttle.current_port.areaname == "NanoTrasen Station") + var/obj/machinery/computer/shuttle_control/C = trade_shuttle.control_consoles[1] //There should be exactly one + if(C) + trade_shuttle.travel_to(pick(trade_shuttle.docking_ports - trade_shuttle.current_port),C) //Just send it; this has all relevant checks + trade_shuttle.remove_dock(/obj/docking_port/destination/trade/station) + trade_shuttle.notify_port_toggled(reason) + ports_open = FALSE + return + if(!ports_open) + var/response = alert(usr,"Are you sure you wish to open the station to traders?", "Port Opening", "Yes", "No") + if(response != "Yes") + return + log_game("[key_name(usr)] opened the port to traders.") + message_admins("[key_name_admin(usr)] opened the port to traders.") + trade_shuttle.add_dock(/obj/docking_port/destination/trade/station) + trade_shuttle.notify_port_toggled() + ports_open = TRUE + return + else + to_chat(usr, "This action requires either a red alert or head of security authorization.") + else + to_chat(usr, "You must wear an ID for this function.") + return 1 /obj/machinery/computer/communications/attack_ai(var/mob/user as mob) @@ -363,7 +389,7 @@ var/shuttle_call/shuttle_calls[0] /obj/machinery/computer/communications/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open=NANOUI_FOCUS) - if(user.stat) + if(user.stat && !isAdminGhost(user)) return // this is the data which will be sent to the ui @@ -371,7 +397,7 @@ var/shuttle_call/shuttle_calls[0] data["is_ai"] = issilicon(user) data["menu_state"] = data["is_ai"] ? ai_menu_state : menu_state data["emagged"] = emagged - data["authenticated"] = authenticated + data["authenticated"] = (isAdminGhost(user) ? AUTH_CAPT : authenticated) data["screen"] = getMenuState(usr) data["stat_display"] = list( @@ -439,7 +465,7 @@ var/shuttle_call/shuttle_calls[0] to_chat(user, "Syndicate routing data uploaded!") new/obj/effect/effect/sparks(get_turf(src)) playsound(loc,"sparks",50,1) - authenticated = 2 + authenticated = AUTH_CAPT setMenuState(usr,COMM_SCREEN_MAIN) update_icon() return 1 @@ -609,11 +635,11 @@ var/shuttle_call/shuttle_calls[0] /obj/machinery/computer/communications/npc_tamper_act(mob/living/user) if(!authenticated) if(prob(20)) //20% chance to log in - authenticated = TRUE + authenticated = AUTH_HEAD else //Already logged in if(prob(50)) //50% chance to log off - authenticated = FALSE + authenticated = UNAUTH else if(isgremlin(user)) //make a hilarious public message var/mob/living/simple_animal/hostile/gremlin/G = user var/result = G.generate_markov_chain() @@ -626,15 +652,15 @@ var/shuttle_call/shuttle_calls[0] /obj/machinery/computer/communications/Destroy() for(var/obj/machinery/computer/communications/commconsole in machines) - if(istype(commconsole.loc,/turf) && commconsole != src) + if(istype(commconsole.loc,/turf) && commconsole != src && commconsole.z != map.zCentcomm) return ..() for(var/obj/item/weapon/circuitboard/communications/commboard in world) - if(istype(commboard.loc,/turf) || istype(commboard.loc,/obj/item/weapon/storage)) + if((istype(commboard.loc,/turf) || istype(commboard.loc,/obj/item/weapon/storage)) && commboard.z != map.zCentcomm) return ..() for(var/mob/living/silicon/ai/shuttlecaller in player_list) - if(!shuttlecaller.stat && shuttlecaller.client && istype(shuttlecaller.loc,/turf)) + if(!shuttlecaller.stat && shuttlecaller.client && istype(shuttlecaller.loc,/turf) && shuttlecaller.z != map.zCentcomm) return ..() if(ticker.mode.name == "revolution" || ticker.mode.name == "AI malfunction") @@ -651,15 +677,15 @@ var/shuttle_call/shuttle_calls[0] /obj/item/weapon/circuitboard/communications/Destroy() for(var/obj/machinery/computer/communications/commconsole in machines) - if(istype(commconsole.loc,/turf)) + if(istype(commconsole.loc,/turf) && commconsole.z != map.zCentcomm) return ..() for(var/obj/item/weapon/circuitboard/communications/commboard in world) - if((istype(commboard.loc,/turf) || istype(commboard.loc,/obj/item/weapon/storage)) && commboard != src) + if((istype(commboard.loc,/turf) || istype(commboard.loc,/obj/item/weapon/storage)) && commboard != src && commboard.z != map.zCentcomm) return ..() for(var/mob/living/silicon/ai/shuttlecaller in player_list) - if(!shuttlecaller.stat && shuttlecaller.client && istype(shuttlecaller.loc,/turf)) + if(!shuttlecaller.stat && shuttlecaller.client && istype(shuttlecaller.loc,/turf) && shuttlecaller.z != map.zCentcomm) return ..() if(ticker.mode.name == "revolution" || ticker.mode.name == "AI malfunction") diff --git a/code/game/machinery/computer/computer.dm b/code/game/machinery/computer/computer.dm index f852308c58d..36255bf6e73 100644 --- a/code/game/machinery/computer/computer.dm +++ b/code/game/machinery/computer/computer.dm @@ -98,7 +98,7 @@ /obj/machinery/computer/togglePanelOpen(var/obj/toggleitem, mob/user, var/obj/item/weapon/circuitboard/CC = null) if(!circuit) //we can't disassemble with no circuit, so add some fucking circuits if you want disassembly return - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 50, 1) user.visible_message( "[user] begins to unscrew \the [src]'s monitor.", "You begin to unscrew the monitor...") if (do_after(user, src, 20) && (circuit || CC)) diff --git a/code/game/machinery/computer/law.dm b/code/game/machinery/computer/law.dm index 0bf77eaebf7..9406b35c2b2 100644 --- a/code/game/machinery/computer/law.dm +++ b/code/game/machinery/computer/law.dm @@ -57,10 +57,12 @@ proc/announce_law_changes(var/mob/user) to_chat(current, "These are your laws now:") current.show_laws() + current << sound('sound/machines/lawsync.ogg') for(var/mob/living/silicon/robot/R in mob_list) if(R.lawupdate && (R.connected_ai == current)) to_chat(R, "These are your laws now:") R.show_laws() + R << sound('sound/machines/lawsync.ogg') to_chat(user, "Upload complete. The AI's laws have been modified.") attackby(obj/item/weapon/O as obj, mob/user as mob) @@ -142,6 +144,7 @@ proc/announce_law_changes() to_chat(current, "These are your laws now:") current.show_laws() + current << sound('sound/machines/lawsync.ogg') to_chat(usr, "Upload complete. The robot's laws have been modified.") proc/install_module(var/obj/item/weapon/aiModule/M,var/mob/user) diff --git a/code/game/machinery/computer/medical.dm b/code/game/machinery/computer/medical.dm index 10187a5af50..1dd002c1596 100644 --- a/code/game/machinery/computer/medical.dm +++ b/code/game/machinery/computer/medical.dm @@ -427,7 +427,7 @@ var/counter = 1 while(src.active2.fields[text("com_[]", counter)]) counter++ - src.active2.fields[text("com_[counter]")] = text("Made by [authenticated] ([rank]) on [time2text(world.realtime, "DDD MMM DD hh:mm:ss")]
[t1]") + src.active2.fields[text("com_[counter]")] = text("Made by [authenticated] ([rank]) on [time2text(world.realtime, "DDD MMM DD")] [worldtime2text(give_seconds = TRUE)], [game_year]
[t1]") if (href_list["del_c"]) if ((istype(src.active2, /datum/data/record) && src.active2.fields[text("com_[]", href_list["del_c"])])) diff --git a/code/game/machinery/computer/robot.dm b/code/game/machinery/computer/robot.dm index 7e2c4b9b3c9..65b32c6bf40 100644 --- a/code/game/machinery/computer/robot.dm +++ b/code/game/machinery/computer/robot.dm @@ -164,14 +164,9 @@ var/choice = input("Are you certain you wish to detonate [R.name]?") in list("Confirm", "Abort") if(choice == "Confirm") if(R && istype(R)) - if(R.mind && R.mind.special_role && R.emagged) - to_chat(R, "Extreme danger. Termination codes detected. Scrambling security codes and automatic AI unlink triggered.") - R.ResetSecurityCodes() - - else + if(R.self_destruct()) message_admins("[key_name_admin(usr)] detonated [R.name]!") log_game("[key_name_admin(usr)] detonated [R.name]!") - R.self_destruct() else to_chat(usr, "Access Denied.") diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm index ce6c4949603..9e8389b93bb 100644 --- a/code/game/machinery/computer/security.dm +++ b/code/game/machinery/computer/security.dm @@ -363,7 +363,7 @@ What a mess.*/ var/counter = 1 while(active2.fields[text("com_[]", counter)]) counter++ - active2.fields[text("com_[]", counter)] = text("Made by [] ([]) on [], 2053
[]", authenticated, rank, time2text(world.realtime, "DDD MMM DD hh:mm:ss"), t1) + active2.fields[text("com_[]", counter)] = text("Made by [] ([]) on [], []
[]", authenticated, rank, "[time2text(world.realtime, "DDD MMM DD")] [worldtime2text(give_seconds = TRUE)]", game_year, t1) if ("Delete Record (ALL)") if (active1) diff --git a/code/game/machinery/computer/slot_machine.dm b/code/game/machinery/computer/slot_machine.dm index 4ef7b53d271..7e749448ccb 100644 --- a/code/game/machinery/computer/slot_machine.dm +++ b/code/game/machinery/computer/slot_machine.dm @@ -169,21 +169,21 @@ add_overlays() var/sound/sound_to_play = pick('sound/effects/xylophone1.ogg','sound/effects/xylophone2.ogg','sound/effects/xylophone3.ogg') - playsound(get_turf(src),sound(sound_to_play),30,-4) + playsound(src,sound(sound_to_play),30,-4) var/sleep_time = 48 sleep(sleep_time/3) update_overlay_icon_state(overlay_1,"[value_1]") - playsound(get_turf(src),'sound/machines/chime.ogg',50,-4) + playsound(src,'sound/machines/chime.ogg',50,-4) sleep(sleep_time/3) update_overlay_icon_state(overlay_2,"[value_2]") - playsound(get_turf(src),'sound/machines/chime.ogg',50,-4) + playsound(src,'sound/machines/chime.ogg',50,-4) sleep(sleep_time/3) update_overlay_icon_state(overlay_3,"[value_3]") - playsound(get_turf(src),'sound/machines/chime.ogg',50,-4) + playsound(src,'sound/machines/chime.ogg',50,-4) check_victory(user) @@ -244,7 +244,7 @@ spawn(10) if(our_money_account.charge(win_value,null,"Victory","one-armed bandit #[id]")) dispense_cash(win_value, get_turf(src)) - playsound(get_turf(src), "polaroid", 50, 1) + playsound(src, "polaroid", 50, 1) to_chat(user, "You win $[win_value]!") else diff --git a/code/game/machinery/computer/station_alert.dm b/code/game/machinery/computer/station_alert.dm index 75f42335de2..298862af56e 100644 --- a/code/game/machinery/computer/station_alert.dm +++ b/code/game/machinery/computer/station_alert.dm @@ -15,9 +15,7 @@ /obj/machinery/computer/station_alert/New() ..() if(src.z != map.zMainStation) - var/area/A = src.areaMaster - if(!A) - A = get_area(src) + var/area/A = get_area(src) if(!A) return name = "[A.general_area_name] Alert Computer" diff --git a/code/game/machinery/computer/store.dm b/code/game/machinery/computer/store.dm index 36bfaa9034e..6c3f13e9e48 100644 --- a/code/game/machinery/computer/store.dm +++ b/code/game/machinery/computer/store.dm @@ -40,7 +40,7 @@ /obj/machinery/computer/merch/New() ..() - if(time2text(world.realtime, "MM/DD") == "02/14") + if(Holiday == VALENTINES_DAY) var/valentines = list("Valentine's Day" = list(/datum/storeitem/valentinechocolatebar,),) categories += valentines diff --git a/code/game/machinery/computer/vox_shuttle.dm b/code/game/machinery/computer/vox_shuttle.dm index be35d95ac23..f8c11e44655 100644 --- a/code/game/machinery/computer/vox_shuttle.dm +++ b/code/game/machinery/computer/vox_shuttle.dm @@ -22,21 +22,21 @@ var/global/vox_shuttle_location return var/area/dest_location = locate(destination) - - if(areaMaster == dest_location) + var/area/this_area = get_area(src) + if(this_area == dest_location) return moving = TRUE lastMove = world.time - if(areaMaster.z != dest_location.z) + if(this_area.z != dest_location.z) var/area/transit_location = locate(/area/vox_station/transit) - areaMaster.move_contents_to(transit_location) - areaMaster = transit_location // let do this while move_contents_to proc is not using Move() + this_area.move_contents_to(transit_location) + this_area = transit_location // let do this while move_contents_to proc is not using Move() sleep(VOX_SHUTTLE_MOVE_TIME) - areaMaster.move_contents_to(dest_location) - areaMaster = dest_location + this_area.move_contents_to(dest_location) + this_area = dest_location moving = FALSE return 1 @@ -58,9 +58,9 @@ var/global/vox_shuttle_location return user.set_machine(src) - + var/area/this_area = get_area(src) var/dat = {" - Location: [areaMaster]
+ Location: [this_area]
Ready to move[max(lastMove + VOX_SHUTTLE_COOLDOWN - world.time, 0) ? " in [max(round((lastMove + VOX_SHUTTLE_COOLDOWN - world.time) * 0.1), 0)] seconds" : ": now"]
Return to dark space
Fore port solar | diff --git a/code/game/machinery/constructable_frame.dm b/code/game/machinery/constructable_frame.dm index fedb724d75c..80aa9db6ab3 100644 --- a/code/game/machinery/constructable_frame.dm +++ b/code/game/machinery/constructable_frame.dm @@ -17,6 +17,7 @@ var/list/req_component_names = null var/list/components_in_use = null var/build_state = 1 + var/build_path = 0 //0 = Default path. 1 = Glass Frame // For pods var/list/connected_parts = list() @@ -49,12 +50,58 @@ if(P.crit_fail) to_chat(user, "This part is faulty, you cannot add this to the machine!") return + + if (build_path == 1) + var/obj/item/weapon/circuitboard/airlock/C = circuit + switch(build_state) + if(1) + if(iscrowbar(P)) + build_path = 0 + new /obj/item/stack/sheet/glass/glass(get_turf(src)) + icon_state = "box_0" + playsound(src, 'sound/items/Crowbar.ogg', 50, 1) + if(istype(P, /obj/item/weapon/circuitboard/airlock) && P:icon_state != "door_electronics_smoked") + if (!C) + if(user.drop_item(P, src)) + build_state++ + C = P + circuit = C + C.installed = 1 + icon_state="box_glass_circuit" + if (iswelder(P)) + to_chat(user, "You use the machine frame as a vice and shape the glass with the welder into a fish bowl.") + getFromPool(/obj/item/stack/sheet/metal, get_turf(src), 5) + new /obj/machinery/fishtank/bowl(get_turf(src)) + qdel(src) + return + if (2) + if(iscrowbar(P)) + if (C != null) + C.forceMove(get_turf(src)) + C.installed = 0 + C = null + circuit = null + build_state-- + icon_state = "box_glass" + playsound(src, 'sound/items/Crowbar.ogg', 50, 1) + if(isscrewdriver(P) && C) + var/obj/structure/displaycase/new_display_case = new(get_turf(src)) + new_display_case.circuit = C + C.forceMove(new_display_case) + circuit = null + C = null + playsound(src, 'sound/items/Screwdriver.ogg', 50, 1) + qdel(src) + return + return + + switch(build_state) if(1) if(istype(P, /obj/item/stack/cable_coil)) var/obj/item/stack/cable_coil/C = P if(C.amount >= 5) - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) to_chat(user, "You start to add cables to the frame.") if(do_after(user, src, 20)) if(C && C.amount >= 5) // Check again @@ -64,19 +111,18 @@ else if(istype(P, /obj/item/stack/sheet/glass/glass)) var/obj/item/stack/sheet/glass/glass/G=P if(G.amount<1) - to_chat(user, "How...?") return G.use(1) to_chat(user, "You add the glass to the frame.") - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) - new /obj/structure/displaycase_frame(src.loc) - qdel(src) + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) + build_path = 1 + icon_state="box_glass" return else if(iswrench(P)) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 75, 1) + playsound(src, 'sound/items/Ratchet.ogg', 75, 1) to_chat(user, "You dismantle the frame.") - drop_stack(/obj/item/stack/sheet/metal, get_turf(src), 5, user) + drop_stack(sheet_type, get_turf(src), 5, user) qdel(src) if(2) if(!..()) @@ -87,7 +133,7 @@ user << "You can't let go of \the [B]!" return - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) to_chat(user, "You add the circuit board to the frame.") circuit = P set_build_state(3) @@ -111,7 +157,7 @@ to_chat(user, "This frame does not accept circuit boards of this type!") else if(iswirecutter(P)) - playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 50, 1) + playsound(src, 'sound/items/Wirecutter.ogg', 50, 1) to_chat(user, "You remove the cables.") set_build_state(1) var/obj/item/stack/cable_coil/A = new /obj/item/stack/cable_coil( src.loc ) @@ -120,7 +166,7 @@ if(3) if(!..()) if(iscrowbar(P)) - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) + playsound(src, 'sound/items/Crowbar.ogg', 50, 1) set_build_state(2) circuit.forceMove(src.loc) circuit = null @@ -141,7 +187,7 @@ component_check = 0 break if(component_check) - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 50, 1) var/obj/machinery/new_machine = new src.circuit.build_path(src.loc) for(var/obj/O in new_machine.component_parts) returnToPool(O) @@ -157,6 +203,7 @@ else circuit.forceMove(null) new_machine.RefreshParts() + new_machine.power_change() circuit.finish_building(new_machine, user) components = null qdel(src) @@ -189,7 +236,7 @@ if(istype(P, /obj/item/weapon) || istype(P, /obj/item/stack)) for(var/I in req_components) if(istype(P, text2path(I)) && (req_components[I] > 0)) - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) if(istype(P, /obj/item/stack)) var/obj/item/stack/CP = P if(CP.amount >= req_components[I]) @@ -209,6 +256,8 @@ components += P req_components[I]-- update_desc() + if(P.is_open_container()) + . = 1 break to_chat(user, desc) @@ -241,7 +290,20 @@ to destroy them and players will be able to make replacements. icon = 'icons/obj/module.dmi' icon_state = "blank_mod" //var/datum/circuits/local_fuses = null - var/list/allowed_boards = list("autolathe"=/obj/item/weapon/circuitboard/autolathe,"intercom"=/obj/item/weapon/intercom_electronics,"air alarm"=/obj/item/weapon/circuitboard/air_alarm,"fire alarm"=/obj/item/weapon/circuitboard/fire_alarm,"airlock"=/obj/item/weapon/circuitboard/airlock,"APC"=/obj/item/weapon/circuitboard/power_control,"vendomat"=/obj/item/weapon/circuitboard/vendomat,"microwave"=/obj/item/weapon/circuitboard/microwave,"station map"=/obj/item/weapon/circuitboard/station_map,"cell charger"=/obj/item/weapon/circuitboard/cell_charger,"fishtank filter"=/obj/item/weapon/circuitboard/fishtank,"large fishtank filter"=/obj/item/weapon/circuitboard/fishwall) + var/list/allowed_boards = list( + "autolathe"=/obj/item/weapon/circuitboard/autolathe, + "intercom"=/obj/item/weapon/intercom_electronics, + "air alarm"=/obj/item/weapon/circuitboard/air_alarm, + "fire alarm"=/obj/item/weapon/circuitboard/fire_alarm, + "airlock"=/obj/item/weapon/circuitboard/airlock, + "APC"=/obj/item/weapon/circuitboard/power_control, + "vendomat"=/obj/item/weapon/circuitboard/vendomat, + "microwave"=/obj/item/weapon/circuitboard/microwave, + "station map"=/obj/item/weapon/circuitboard/station_map, + "cell charger"=/obj/item/weapon/circuitboard/cell_charger, + "recharger"=/obj/item/weapon/circuitboard/recharger, + "fishtank filter"=/obj/item/weapon/circuitboard/fishtank, + "large fishtank filter"=/obj/item/weapon/circuitboard/fishwall) var/soldering = 0 //Busy check /obj/item/weapon/circuitboard/blank/New() @@ -426,8 +488,8 @@ obj/item/weapon/circuitboard/rdserver /obj/item/weapon/circuitboard/smes name = "Circuit Board (SMES)" - desc = "A circuit board used to run a gas freezer." - build_path = "/obj/machinery/power/battery/smes" + desc = "A circuit board used to run a giant battery." + build_path = "/obj/machinery/power/battery/smes/pristine" board_type = MACHINE origin_tech = Tc_POWERSTORAGE + "=4;" + Tc_ENGINEERING + "=4;" + Tc_PROGRAMMING + "=4" req_components = list( @@ -914,6 +976,16 @@ obj/item/weapon/circuitboard/rdserver // Telecomms circuit boards: +/obj/item/weapon/circuitboard/pda_multicaster + name = "Circuit Board (PDA multicaster)" + desc = "A circuit board used to run a machine that resends messages." + build_path = "/obj/machinery/pda_multicaster" + board_type = MACHINE + origin_tech = Tc_PROGRAMMING + "=4;" + Tc_ENGINEERING + "=3;" + Tc_BLUESPACE + "=2" + req_components = list( + "/obj/item/weapon/stock_parts/subspace/filter" = 1, + "/obj/item/weapon/stock_parts/manipulator" = 1) + /obj/item/weapon/circuitboard/telecomms/receiver name = "Circuit Board (telecommunications subspace receiver)" desc = "A circuit board used to run a machine that receives subspace transmissions in telecommunications systems." @@ -1146,6 +1218,16 @@ obj/item/weapon/circuitboard/rdserver "/obj/item/weapon/stock_parts/scanning_module" = 1, "/obj/item/weapon/stock_parts/capacitor" = 2) +/obj/item/weapon/circuitboard/recharger + name = "Circuit Board (Recharger)" + desc = "A circuit board used to run a machine that replenishes energy weapon charge" + board_type = MACHINE + build_path = "/obj/machinery/recharger" + origin_tech = Tc_POWERSTORAGE + "=2;" + Tc_COMBAT + "=2" + req_components = list( + "/obj/item/weapon/stock_parts/scanning_module" = 1, + "/obj/item/weapon/stock_parts/capacitor" = 2) + /obj/item/weapon/circuitboard/washing_machine name = "Circuit Board (Washing Machine)" desc = "A circuit board used to run a machine that cleans clothing and kills pets." @@ -1287,6 +1369,7 @@ obj/item/weapon/circuitboard/rdserver "/obj/item/weapon/stock_parts/scanning_module" = 1, "/obj/item/weapon/stock_parts/micro_laser" = 1) + /* * Fishtanks */ @@ -1306,4 +1389,12 @@ obj/item/weapon/circuitboard/rdserver board_type = MACHINE origin_tech = Tc_PROGRAMMING + "=1" req_components = list ( - "/obj/item/stack/sheet/glass/glass" = 10) \ No newline at end of file + "/obj/item/stack/sheet/glass/glass" = 10) + +/obj/item/weapon/circuitboard/conduction_plate + name = "Circuit Board (Conduction Plate)" + build_path = "/obj/machinery/power/conduction_plate" + board_type = MACHINE + origin_tech = Tc_PROGRAMMING + "=1;" + Tc_ENGINEERING + "=4" + req_components = list( + "/obj/item/weapon/stock_parts/capacitor" = 1) diff --git a/code/game/machinery/cryo.dm b/code/game/machinery/cryo.dm index 790975afc68..d4b70fdffee 100644 --- a/code/game/machinery/cryo.dm +++ b/code/game/machinery/cryo.dm @@ -21,7 +21,7 @@ var/global/list/cryo_health_indicator = list( "full" = image("icon" = 'icons/obj var/on = 0 var/ejecting = 0 var/temperature_archived - var/mob/living/carbon/occupant = null + var/mob/living/occupant = null var/obj/item/weapon/reagent_containers/glass/beaker = null var/current_heat_capacity = 50 @@ -73,7 +73,7 @@ var/global/list/cryo_health_indicator = list( "full" = image("icon" = 'icons/obj ..() /obj/machinery/atmospherics/unary/cryo_cell/MouseDrop_T(atom/movable/O as mob|obj, mob/user as mob) - if(!ismob(O)) //humans only + if(!ismob(O)) return if(O.loc == user) //no you can't pull things out of your ass return @@ -81,7 +81,7 @@ var/global/list/cryo_health_indicator = list( "full" = image("icon" = 'icons/obj return if(O.anchored || get_dist(user, src) > 1 || get_dist(user, O) > 1 || user.contents.Find(src)) // is the mob anchored, too far away from you, or are you too far away from the source return - if(istype(O, /mob/living/simple_animal) || istype(O, /mob/living/silicon)) //animals and robutts dont fit + if(issilicon(O)) //robutts dont fit return if(!ishigherbeing(user) && !isrobot(user)) //No ghosts or mice putting people into the sleeper return @@ -97,7 +97,7 @@ var/global/list/cryo_health_indicator = list( "full" = image("icon" = 'icons/obj return if(isrobot(user)) var/mob/living/silicon/robot/robit = usr - if(istype(robit) && !istype(robit.module, /obj/item/weapon/robot_module/medical)) + if(!(robit.module && (robit.module.quirk_flags & MODULE_CAN_HANDLE_MEDICAL))) to_chat(user, "You do not have the means to do this!") return var/mob/living/L = O @@ -129,7 +129,7 @@ var/global/list/cryo_health_indicator = list( "full" = image("icon" = 'icons/obj return if(isrobot(usr)) var/mob/living/silicon/robot/robit = usr - if(istype(robit) && !istype(robit.module, /obj/item/weapon/robot_module/medical)) + if(!(robit.module && (robit.module.quirk_flags & MODULE_CAN_HANDLE_MEDICAL))) to_chat(usr, "You do not have the means to do this!") return if(!istype(over_location) || over_location.density) @@ -533,7 +533,7 @@ var/global/list/cryo_health_indicator = list( "full" = image("icon" = 'icons/obj boot_contents(exit, regulatetemp = 0) //No temperature regulation cycle required else ejecting = 1 - playsound(get_turf(src), 'sound/machines/pressurehiss.ogg', 40, 1) + playsound(src, 'sound/machines/pressurehiss.ogg', 40, 1) modify_occupant_bodytemp() //Start to heat them up a little bit immediately nanomanager.update_uis(src) spawn(4 SECONDS) @@ -562,10 +562,13 @@ var/global/list/cryo_health_indicator = list( "full" = image("icon" = 'icons/obj nanomanager.update_uis(src) -/obj/machinery/atmospherics/unary/cryo_cell/proc/put_mob(mob/living/carbon/M as mob) +/obj/machinery/atmospherics/unary/cryo_cell/proc/put_mob(mob/living/M as mob) if (!istype(M)) to_chat(usr, "The cryo cell cannot handle such a lifeform!") return + if(M.size > SIZE_NORMAL) + to_chat(usr, "\The [src] cannot fit such a large lifeform!") + return if (occupant) to_chat(usr, "The cryo cell is already occupied!") return diff --git a/code/game/machinery/deployable.dm b/code/game/machinery/deployable.dm index 999dde4b8f3..d5bec23c45e 100644 --- a/code/game/machinery/deployable.dm +++ b/code/game/machinery/deployable.dm @@ -37,10 +37,11 @@ to_chat(user, "It seems to be malfunctioning.") /obj/machinery/deployable/barrier/attackby(var/obj/item/weapon/W, var/mob/user) - if (isID(W) || isPDA(W)) - if (!allowed(user)) - to_chat(user, "Access denied.") - return + if(isID(W) || isPDA(W) || isRoboID(W)) + if(!isrobot(user)) + if(!allowed(user)) + to_chat(user, "Access denied.") + return anchored = !anchored update_icon() if (anchored) diff --git a/code/game/machinery/door_control.dm b/code/game/machinery/door_control.dm index d516fb1760b..d93a6dd72f4 100644 --- a/code/game/machinery/door_control.dm +++ b/code/game/machinery/door_control.dm @@ -48,7 +48,7 @@ /obj/machinery/door_control/emag(mob/user) req_access = list() req_one_access = list() - playsound(get_turf(src), "sparks", 100, 1) + playsound(src, "sparks", 100, 1) /obj/machinery/door_control/attackby(obj/item/weapon/W, mob/user as mob) ..() @@ -147,7 +147,7 @@ return if(iswrench(W)) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + playsound(src, 'sound/items/Ratchet.ogg', 50, 1) if(do_after(user, src, 30)) to_chat(user, "You detach \the [src] from the wall.") new/obj/item/mounted/frame/driver_button(get_turf(src)) @@ -203,3 +203,18 @@ icon_state = "launcherbtt" active = 0 + +/obj/machinery/door_control/mapped/interogation_room + name = "smartglass control" + desc = "Toogle smartglass" + id_tag = "InterogationRoomIDTag" + + +/obj/machinery/door_control/mapped/interogation_room/attack_hand(var/mob/user) + ..() // Sanity + for (var/obj/structure/window/reinforced/plasma/interogation_room/W in range(range)) + if (W.smartwindow && src.id_tag == W.smartwindow.id_tag) + W.smartwindow.toggle_smart_transparency() + for (var/obj/machinery/door/window/plasma/secure/interogation_room/W in range(range)) + if (W.smartwindow && src.id_tag == W.smartwindow.id_tag) + W.smartwindow.toggle_smart_transparency() diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 0a492dfce5b..c1d78d1f327 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -455,7 +455,7 @@ About the new airlock wires panel: // 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 -/obj/machinery/door/airlock/shock(mob/user, prb) +/obj/machinery/door/airlock/shock(mob/user, prb, var/siemenspassed = 1) if((stat & (NOPOWER)) || !src.arePowerSystemsOn()) // unpowered, no shock return 0 if(hasShocked) @@ -463,7 +463,7 @@ About the new airlock wires panel: if(!prob(prb)) return 0 //you lucked out, no shock for you spark(src, 5) - if(electrocute_mob(user, get_area(src), src)) + if(electrocute_mob(user, get_area(src), src, siemenspassed)) hasShocked = 1 spawn(10) hasShocked = 0 @@ -1042,7 +1042,7 @@ About the new airlock wires panel: /obj/machinery/door/airlock/togglePanelOpen(var/obj/toggleitem, mob/user) if(!operating) panel_open = !panel_open - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 25, 1, -6) + playsound(src, 'sound/items/Screwdriver.ogg', 25, 1, -6) update_icon() return 1 return @@ -1054,7 +1054,7 @@ About the new airlock wires panel: if (!istype(user, /mob/living/silicon)) if (isElectrified()) // TODO: analyze the called proc - if (shock(user, 75)) + if (shock(user, 75, I.siemens_coefficient)) user.delayNextAttack(10) return @@ -1064,15 +1064,15 @@ About the new airlock wires panel: if(welded) breaktime += 30 //Welding buys you a little time src.visible_message("[user] is battering down [src]!", "You begin to batter [src].") - playsound(get_turf(src), 'sound/effects/shieldbash.ogg', 50, 1) + playsound(src, 'sound/effects/shieldbash.ogg', 50, 1) if(do_after(user,src, breaktime)) //Calculate bolts separtely, in case they dropped in the last 6-9 seconds. if(src.locked == 1) - playsound(get_turf(src), 'sound/effects/shieldbash.ogg', 50, 1) + playsound(src, 'sound/effects/shieldbash.ogg', 50, 1) src.visible_message("[user] is battering the bolts!", "You begin to smash the bolts...") if(!do_after(user, src,190)) //Same amount as drilling an R-wall, longer if it was welded return //If they moved, cancel us out - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) src.visible_message("[user] broke down the door!", "You broke the door!") bashed_in(user) return @@ -1155,7 +1155,7 @@ About the new airlock wires panel: return /obj/machinery/door/airlock/proc/bashed_in(var/mob/user) - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) operating = -1 var/obj/structure/door_assembly/DA = revert(user,user.dir) DA.anchored = 0 @@ -1215,7 +1215,7 @@ About the new airlock wires panel: if( !arePowerSystemsOn() || (stat & NOPOWER) || isWireCut(AIRLOCK_WIRE_OPEN_DOOR) ) return 0 use_power(50) - playsound(get_turf(src), soundeffect, pitch, 1) + playsound(src, soundeffect, pitch, 1) if(src.closeOther != null && istype(src.closeOther, /obj/machinery/door/airlock/) && !src.closeOther.density) src.closeOther.close() // This worries me - N3X @@ -1245,7 +1245,7 @@ About the new airlock wires panel: return if (locate(/mob/living) in T) - playsound(get_turf(src), 'sound/machines/buzz-two.ogg', 50, 0) + playsound(src, 'sound/machines/buzz-two.ogg', 50, 0) if(autoclose && normalspeed) spawn(150) autoclose() @@ -1277,7 +1277,7 @@ About the new airlock wires panel: if (istype(loc, /turf/simulated)) T.add_blood(L) - playsound(get_turf(src),soundeffect, 30, 1) + playsound(src,soundeffect, 30, 1) for(var/turf/T in loc) var/obj/structure/window/W = locate(/obj/structure/window) in T diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index 5376f7296ca..5d04f45ac9f 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -124,46 +124,20 @@ var/list/all_doors = list() var/mob/living/carbon/human/H = user if (H.getBrainLoss() >= BRAINLOSS_FOR_HEADBUTT) - // TODO: analyze the called proc - playsound(get_turf(src), 'sound/effects/bang.ogg', 25, 1) - + playsound(src, 'sound/effects/bang.ogg', 25, 1) + H.visible_message("[user] headbutts the airlock.") if (!istype(H.head, /obj/item/clothing/head/helmet)) - visible_message("[user] headbutts the airlock.") H.Stun(8) H.Knockdown(5) var/datum/organ/external/O = H.get_organ(LIMB_HEAD) - - // TODO: analyze the called proc - if(O.take_damage(10, 0)) - H.UpdateDamageIcon() - O = null - else - // TODO: fix sentence - visible_message("[user] headbutts the airlock. Good thing they're wearing a helmet.") - - H = null + O.take_damage(10, 0) return - H = null - - add_fingerprint(user) - attackby(null, user) - - -/obj/machinery/door/attackby(obj/item/I as obj, mob/user as mob) - if(..()) - return 1 - - if (istype(I, /obj/item/device/detective_scanner)) - return if(isobserver(user) && !isAdminGhost(user)) return - // borgs can't attack doors open - // because it conflicts with their AI-like interaction with them - if (isrobot(user)) - return + add_fingerprint(user) if (!requiresID()) user = null @@ -179,6 +153,25 @@ var/list/all_doors = list() denied() +/obj/machinery/door/attackby(obj/item/I, mob/user) + if(..()) + return + + if(istype(I, /obj/item/device/detective_scanner)) + return //It does its own thing on attack + + if (allowed(user)) + if (!density) + return close() + else + return open() + + + if(horror_force(user)) + return + + denied() + /obj/machinery/door/proc/horror_force(var/mob/living/carbon/human/H) //H is for HORROR, BABY! if(!ishorrorform(H)) return FALSE @@ -228,7 +221,7 @@ var/list/all_doors = list() operating = 1 if(makes_noise) - playsound(get_turf(src), soundeffect, soundpitch, 1) + playsound(src, soundeffect, soundpitch, 1) set_opacity(0) door_animate("opening") @@ -260,7 +253,7 @@ var/list/all_doors = list() layer = closed_layer if (makes_noise) - playsound(get_turf(src), soundeffect, soundpitch, 1) + playsound(src, soundeffect, soundpitch, 1) setDensity(TRUE) door_animate("closing") diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm index 065c41f05cc..c2382ae704f 100644 --- a/code/game/machinery/doors/firedoor.dm +++ b/code/game/machinery/doors/firedoor.dm @@ -1,5 +1,5 @@ -/var/const/OPEN = 1 -/var/const/CLOSED = 2 +/var/const/FD_OPEN = 1 +/var/const/FD_CLOSED = 2 var/global/list/alert_overlays_global = list() @@ -204,7 +204,7 @@ var/global/list/alert_overlays_global = list() if(isobserver(user) || user.stat) return spawn() - var/area/A = get_area_master(src) + var/area/A = get_area(src) ASSERT(istype(A)) // This worries me. var/alarmed = A.doors_down || A.fire var/old_density = src.density @@ -240,11 +240,10 @@ var/global/list/alert_overlays_global = list() force_open(user, C) return - if(istype(C, /obj/item/weapon/wrench/socket)) + if(istype(C, /obj/item/weapon/wrench)) if(blocked) user.visible_message("\The [user] starts to deconstruct \the [src] with \a [C].",\ - "You begin to deconstruct \the [src] with \the [C].",\ - "You hear a racket from a ratchet.") + "You begin to deconstruct \the [src] with \the [C].") if(do_after(user, src, 5 SECONDS)) new/obj/item/firedoor_frame(get_turf(src)) qdel(src) @@ -270,7 +269,7 @@ var/global/list/alert_overlays_global = list() to_chat(user, "\The [src] is welded solid!") return - var/area/A = get_area_master(src) + var/area/A = get_area(src) ASSERT(istype(A)) // This worries me. var/alarmed = A.doors_down || A.fire @@ -336,7 +335,7 @@ var/global/list/alert_overlays_global = list() ..() latetoggle() layer = open_layer - var/area/A = get_area_master(src) + var/area/A = get_area(src) ASSERT(istype(A)) // This worries me. var/alarmed = A.doors_down || A.fire if(alarmed) @@ -344,7 +343,7 @@ var/global/list/alert_overlays_global = list() close() /obj/machinery/door/firedoor/proc/force_open(mob/user, var/obj/C) //used in mecha/equipment/tools/tools.dm - var/area/A = get_area_master(src) + var/area/A = get_area(src) ASSERT(istype(A)) // This worries me. var/alarmed = A.doors_down || A.fire @@ -468,10 +467,10 @@ var/global/list/alert_overlays_global = list() return switch(nextstate) - if(OPEN) + if(FD_OPEN) nextstate = null open() - if(CLOSED) + if(FD_CLOSED) nextstate = null close() @@ -540,6 +539,25 @@ var/global/list/alert_overlays_global = list() if(!user.IsAdvancedToolUser()) to_chat(user, "You don't have the dexterity to do this!") return 0 + + if(!user.is_holding_item(src)) + return 1 + var/current_turf = get_turf(src) + var/turf_face = get_step(current_turf,user.dir) + if(SSair.air_blocked(current_turf, turf_face)) + to_chat(user, "That way is blocked already.") + return 1 + var/obj/machinery/door/firedoor/border_only/F = locate(/obj/machinery/door/firedoor) in get_turf(user) + if(F && F.dir == user.dir) + to_chat(user, "There is already a firedoor facing that direction.") + return 1 + if(do_after(user, src, 5 SECONDS)) + var/obj/machinery/door/firedoor/border_only/B = new(get_turf(src)) + B.change_dir(user.dir) + qdel(src) + +//Removed pending a fix for atmos issues caused by full tile firelocks. +/* switch(alert("firedoor construction", "Would you like to construct a full tile firedoor or one direction?", "One Direction", "Full Firedoor", "Cancel", null)) if("One Direction") if(!user.is_holding_item(src)) @@ -565,4 +583,5 @@ var/global/list/alert_overlays_global = list() return 1 if(do_after(user, src, 5 SECONDS)) new /obj/machinery/door/firedoor(get_turf(src)) - qdel(src) \ No newline at end of file + qdel(src) +*/ diff --git a/code/game/machinery/doors/mineral.dm b/code/game/machinery/doors/mineral.dm index 4fe57644123..7416fe5fc7d 100644 --- a/code/game/machinery/doors/mineral.dm +++ b/code/game/machinery/doors/mineral.dm @@ -64,11 +64,11 @@ return open() /obj/machinery/door/mineral/open() - playsound(get_turf(src), soundeffect, 100, 1) + playsound(src, soundeffect, 100, 1) return ..() /obj/machinery/door/mineral/close() - playsound(get_turf(src), soundeffect, 100, 1) + playsound(src, soundeffect, 100, 1) return ..() /obj/machinery/door/mineral/attackby(obj/item/weapon/W as obj, mob/user as mob) @@ -224,6 +224,11 @@ add_fingerprint(user) SwitchState() +/obj/machinery/door/mineral/resin/bullet_act(var/obj/item/projectile/Proj) + if(Proj.damage_type == BRUTE || Proj.damage_type == BURN) + hardness -= Proj.damage/100 + CheckHardness() + /obj/machinery/door/mineral/resin/open() ..() spawn(close_delay) @@ -235,7 +240,7 @@ return /obj/machinery/door/mineral/resin/CheckHardness() - playsound(get_turf(src), soundeffect, 100, 1) + playsound(src, soundeffect, 100, 1) return ..() /obj/machinery/door/mineral/resin/acidable() diff --git a/code/game/machinery/doors/poddoor.dm b/code/game/machinery/doors/poddoor.dm index c5a254d32dc..c5c033b2256 100644 --- a/code/game/machinery/doors/poddoor.dm +++ b/code/game/machinery/doors/poddoor.dm @@ -74,6 +74,9 @@ var/list/poddoors = list() return return +/obj/machinery/door/poddoor/allowed(mob/M) + return 0 + /obj/machinery/door/poddoor/open() if (src.operating == 1) //doors can still open when emag-disabled return diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm index 8f3e906a163..7ee5e93266c 100644 --- a/code/game/machinery/doors/windowdoor.dm +++ b/code/game/machinery/doors/windowdoor.dm @@ -129,9 +129,9 @@ return 0 if(!operating) //in case of emag operating = 1 - flick(text("[]opening", base_state), src) - playsound(get_turf(src), soundeffect, 100, 1) - icon_state = text("[]open", base_state) + door_animate("opening") + playsound(src, soundeffect, 100, 1) + icon_state = "[base_state]open" sleep(animation_delay) explosion_resistance = 0 @@ -148,8 +148,8 @@ if (operating) return 0 operating = 1 - flick(text("[]closing", base_state), src) - playsound(get_turf(src), soundeffect, 100, 1) + door_animate("closing") + playsound(src, soundeffect, 100, 1) icon_state = base_state setDensity(TRUE) @@ -188,7 +188,7 @@ tforce = 40 else tforce = AM:throwforce - playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 100, 1) + playsound(src, 'sound/effects/Glasshit.ogg', 100, 1) take_damage(tforce) /obj/machinery/door/window/attack_ai(mob/user as mob) @@ -201,17 +201,12 @@ return user.delayNextAttack(8) user.do_attack_animation(src, user) - health = max(0, health - 25) - playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 75, 1) + playsound(src, 'sound/effects/Glasshit.ogg', 75, 1) visible_message("\The [user] smashes against \the [name].", 1) - if (health <= 0) - getFromPool(shard, loc) - getFromPool(/obj/item/stack/cable_coil, loc, 2) - qdel(src) + take_damage(25) else return attack_hand(user) - /obj/machinery/door/window/attack_animal(mob/living/user as mob) if(operating) return @@ -220,23 +215,15 @@ return user.do_attack_animation(src, user) user.delayNextAttack(8) - health = max(0, health - M.melee_damage_upper) - playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 75, 1) + playsound(src, 'sound/effects/Glasshit.ogg', 75, 1) visible_message("\The [M] [M.attacktext] against \the [name].", 1) - if (health <= 0) - getFromPool(shard, loc) - getFromPool(/obj/item/stack/cable_coil, loc, 2) - qdel(src) - - -/obj/machinery/door/window/attack_hand(mob/user as mob) - return attackby(user, user) + take_damage(M.melee_damage_upper) /obj/machinery/door/window/attackby(obj/item/weapon/I as obj, mob/living/user as mob) // Make emagged/open doors able to be deconstructed if (!density && operating != 1 && iscrowbar(I)) user.visible_message("[user] removes the electronics from the windoor assembly.", "You start to remove the electronics from the windoor assembly.") - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 100, 1) + playsound(src, 'sound/items/Crowbar.ogg', 100, 1) if (do_after(user, src, 40) && src && !density && operating != 1) to_chat(user, "You removed the windoor electronics!") make_assembly(user) @@ -276,14 +263,10 @@ var/aforce = I.force user.do_attack_animation(src, I) user.delayNextAttack(8) - if(I.damtype == BRUTE || I.damtype == BURN) - health = max(0, health - aforce) - playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 75, 1) + playsound(src, 'sound/effects/Glasshit.ogg', 75, 1) visible_message("[src] was hit by [I].") - if (health <= 0) - getFromPool(shard, loc) - getFromPool(/obj/item/stack/cable_coil, loc, 2) - qdel(src) + if(I.damtype == BRUTE || I.damtype == BURN) + take_damage(aforce) return add_fingerprint(user) @@ -291,15 +274,6 @@ //don't care who they are or what they have, act as if they're NOTHING user = null - if (isrobot(user)) - if (density) - return open() - else - return close() - - if (!allowed(user) && density) - flick(text("[]deny", base_state), src) - return ..() /obj/machinery/door/window/emag(mob/user) @@ -307,13 +281,16 @@ var/used_emag = (/obj/item/weapon/card/emag in user.contents) //TODO: Find a better way of checking this return hackOpen(used_emag, user) +/obj/machinery/door/window/door_animate(var/animation) + flick("[base_state][animation]", src) + /obj/machinery/door/window/proc/hackOpen(obj/item/I, mob/user) operating = -1 if (electronics) electronics.icon_state = "door_electronics_smoked" - flick("[base_state]spark", src) + door_animate("spark") sleep(6) open() return 1 @@ -415,3 +392,8 @@ WA.secure = "secure_" WA.update_icon() return WA + +// Used on Packed ; smartglassified roundstart +/obj/machinery/door/window/plasma/secure/interogation_room/initialize() + smartwindow = new(src) + smartwindow.id_tag = "InterogationRoomIDTag" diff --git a/code/game/machinery/embedded_controller/embedded_controller_base.dm b/code/game/machinery/embedded_controller/embedded_controller_base.dm index 568bc662f3d..10b0de03b46 100644 --- a/code/game/machinery/embedded_controller/embedded_controller_base.dm +++ b/code/game/machinery/embedded_controller/embedded_controller_base.dm @@ -41,7 +41,7 @@ to_chat(usr, "You begin removing screws from \the [src] backplate...") if(do_after(user, src, 50)) to_chat(usr, "You unscrew \the [src] from the wall.") - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 50, 1) new /obj/item/mounted/frame/airlock_controller(get_turf(src)) qdel(src) return 1 @@ -55,7 +55,7 @@ if(user.drop_item(C, src)) to_chat(usr, "You secure \the [C]!") _circuitboard=C - playsound(get_turf(src), 'sound/effects/pop.ogg', 50, 0) + playsound(src, 'sound/effects/pop.ogg', 50, 0) build++ update_icon() return 1 @@ -63,7 +63,7 @@ if(iscrowbar(W)) to_chat(usr, "You begin to pry out \the [W] into \the [src].") if(do_after(user, src, 10)) - playsound(get_turf(src), 'sound/effects/pop.ogg', 50, 0) + playsound(src, 'sound/effects/pop.ogg', 50, 0) build-- update_icon() var/obj/item/weapon/circuitboard/C @@ -80,7 +80,7 @@ if(istype(W, /obj/item/stack/cable_coil)) var/obj/item/stack/cable_coil/C=W to_chat(user, "You start adding cables to \the [src]...") - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) if(do_after(user, src, 20) && C.amount >= 10) C.use(5) build++ @@ -101,7 +101,7 @@ return 1 if(isscrewdriver(W)) to_chat(user, "You begin to complete \the [src]...") - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 50, 1) if(do_after(user, src, 20)) if(!_circuitboard) _circuitboard=new boardtype(src) diff --git a/code/game/machinery/flasher.dm b/code/game/machinery/flasher.dm index c6f46e162ac..1466f5ed431 100644 --- a/code/game/machinery/flasher.dm +++ b/code/game/machinery/flasher.dm @@ -77,7 +77,7 @@ var/list/obj/machinery/flasher/flashers = list() if ((src.disable) || (src.last_flash && world.time < src.last_flash + 150)) return - playsound(get_turf(src), 'sound/weapons/flash.ogg', 100, 1) + playsound(src, 'sound/weapons/flash.ogg', 100, 1) src.last_flash = world.time use_power(1000) if(harm_labeled >= min_harm_label) diff --git a/code/game/machinery/holosign.dm b/code/game/machinery/holosign.dm index e99130173d8..b8420d2c1c2 100644 --- a/code/game/machinery/holosign.dm +++ b/code/game/machinery/holosign.dm @@ -61,8 +61,8 @@ var/list/obj/machinery/holosign/holosigns = list() /obj/machinery/holosign_switch/attack_ai(mob/user as mob) src.add_hiddenprint(user) return src.attack_hand(user) -/ -obj/machinery/holosign_switch/attack_paw(mob/user as mob) + +/obj/machinery/holosign_switch/attack_paw(mob/user as mob) return src.attack_hand(user) /obj/machinery/holosign_switch/attackby(obj/item/weapon/W, mob/user as mob) diff --git a/code/game/machinery/igniter.dm b/code/game/machinery/igniter.dm index e69d0fd8bbd..90fd82d4a83 100755 --- a/code/game/machinery/igniter.dm +++ b/code/game/machinery/igniter.dm @@ -66,7 +66,7 @@ var/global/list/igniters = list() if(istype(W, /obj/item/weapon/weldingtool) && src.assembly) var/obj/item/weapon/weldingtool/WT = W if (WT.remove_fuel(0,user)) - playsound(get_turf(src), 'sound/items/Welder2.ogg', 50, 1) + playsound(src, 'sound/items/Welder2.ogg', 50, 1) to_chat(user, "You begin to cut \the [src] off the floor...") if (do_after(user, src, 40)) user.visible_message( \ diff --git a/code/game/machinery/iv_drip.dm b/code/game/machinery/iv_drip.dm index 91dad72aae9..d85a5fadd26 100644 --- a/code/game/machinery/iv_drip.dm +++ b/code/game/machinery/iv_drip.dm @@ -72,7 +72,7 @@ if(user.stat) return if(iswrench(W)) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + playsound(src, 'sound/items/Ratchet.ogg', 50, 1) var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal,get_turf(src)) M.amount = 2 if(src.beaker) @@ -139,7 +139,7 @@ return if(!T.dna) return - if(M_NOCLONE in T.mutations) + if(M_HUSK in T.mutations) return // If the human is losing too much blood, beep. diff --git a/code/game/machinery/kitchen/gibber.dm b/code/game/machinery/kitchen/gibber.dm index 57eb5102325..b3a8b5b3fbd 100644 --- a/code/game/machinery/kitchen/gibber.dm +++ b/code/game/machinery/kitchen/gibber.dm @@ -207,8 +207,12 @@ obj/machinery/gibber/New() var/obj/item/weapon/reagent_containers/food/snacks/meat/allmeat[totalslabs] for (var/i=1 to totalslabs) - var/obj/item/weapon/reagent_containers/food/snacks/meat/newmeat = new occupant.meat_type(null, occupant) - newmeat.reagents.add_reagent (NUTRIMENT, sourcenutriment / totalslabs) // Thehehe. Fat guys go first + var/obj/item/weapon/newmeat + if(istype(occupant.meat_type, /obj/item/weapon/reagent_containers)) + newmeat = new occupant.meat_type(null, occupant) + newmeat.reagents.add_reagent (NUTRIMENT, sourcenutriment / totalslabs) // Thehehe. Fat guys go first + else + newmeat = new occupant.meat_type() if(src.occupant.reagents) src.occupant.reagents.trans_to (newmeat, round (sourcetotalreagents / totalslabs, 1)) // Transfer all the reagents from the @@ -323,7 +327,7 @@ obj/machinery/gibber/New() else victim.ghostize(0) qdel(victim) - playsound(get_turf(src), 'sound/effects/gib2.ogg', 50, 1) + playsound(src, 'sound/effects/gib2.ogg', 50, 1) for (var/i=1 to totalslabs) var/obj/item/meatslab = allmeat[i] var/turf/Tx = locate(src.x - i, src.y, src.z) diff --git a/code/game/machinery/kitchen/juicer.dm b/code/game/machinery/kitchen/juicer.dm index 7f5f2e7961f..11e671cdb65 100644 --- a/code/game/machinery/kitchen/juicer.dm +++ b/code/game/machinery/kitchen/juicer.dm @@ -148,7 +148,7 @@ return if (!beaker || beaker.reagents.total_volume >= beaker.reagents.maximum_volume) return - playsound(get_turf(src), 'sound/machines/juicer.ogg', 50, 1) + playsound(src, 'sound/machines/juicer.ogg', 50, 1) for (var/obj/item/weapon/reagent_containers/food/snacks/O in src.contents) var/r_id = get_juice_id(O) beaker.reagents.add_reagent(r_id,get_juice_amount(O)) diff --git a/code/game/machinery/kitchen/microwave.dm b/code/game/machinery/kitchen/microwave.dm index bde112469d2..5f27e75c05b 100644 --- a/code/game/machinery/kitchen/microwave.dm +++ b/code/game/machinery/kitchen/microwave.dm @@ -199,7 +199,7 @@ /obj/machinery/microwave/attack_ai(mob/user as mob) if(istype(user,/mob/living/silicon/robot)) var/mob/living/silicon/robot/R = user - if(istype(R.module, /obj/item/weapon/robot_module/butler)) + if(R.module && (R.module.quirk_flags & MODULE_CAN_HANDLE_FOOD)) user.set_machine(src) interact(user) return 1 @@ -244,6 +244,17 @@ display_name = "Turnovers" items_measures[display_name] = "turnover" items_measures_p[display_name] = "turnovers" + if (istype(O,/obj/item/weapon/reagent_containers/food/snacks/grown/soybeans)) + items_measures[display_name] = "soybean" + items_measures_p[display_name] = "soybeans" + if (istype(O,/obj/item/weapon/reagent_containers/food/snacks/grown/grapes)) + display_name = "Grapes" + items_measures[display_name] = "bunch of grapes" + items_measures_p[display_name] = "bunches of grapes" + if (istype(O,/obj/item/weapon/reagent_containers/food/snacks/grown/greengrapes)) + display_name = "Green Grapes" + items_measures[display_name] = "bunch of green grapes" + items_measures_p[display_name] = "bunches of green grapes" items_counts[display_name]++ for (var/O in items_counts) var/N = items_counts[O] @@ -379,7 +390,7 @@ src.updateUsrDialog() /obj/machinery/microwave/proc/stop() - playsound(get_turf(src), 'sound/machines/ding.ogg', 50, 1) + playsound(src, 'sound/machines/ding.ogg', 50, 1) src.operating = 0 // Turn it off again aferwards src.icon_state = "mw" src.updateUsrDialog() @@ -398,11 +409,11 @@ src.updateUsrDialog() /obj/machinery/microwave/proc/muck_start() - playsound(get_turf(src), 'sound/effects/splat.ogg', 50, 1) // Play a splat sound + playsound(src, 'sound/effects/splat.ogg', 50, 1) // Play a splat sound src.icon_state = "mwbloody1" // Make it look dirty!! /obj/machinery/microwave/proc/muck_finish() - playsound(get_turf(src), 'sound/machines/ding.ogg', 50, 1) + playsound(src, 'sound/machines/ding.ogg', 50, 1) src.visible_message("The microwave gets covered in muck!") src.dirty = 100 // Make it dirty so it can't be used util cleaned src.flags &= ~OPENCONTAINER //So you can't add condiments diff --git a/code/game/machinery/kitchen/monkeyrecycler.dm b/code/game/machinery/kitchen/monkeyrecycler.dm index 0af8010b6df..a7208c87fd7 100644 --- a/code/game/machinery/kitchen/monkeyrecycler.dm +++ b/code/game/machinery/kitchen/monkeyrecycler.dm @@ -59,7 +59,7 @@ qdel(target) target = null to_chat(user, "You stuff the monkey in the machine.") - playsound(get_turf(src), 'sound/machines/juicer.ogg', 50, 1) + playsound(src, 'sound/machines/juicer.ogg', 50, 1) use_power(500) src.grinded++ to_chat(user, "The machine now has [grinded] monkeys worth of material stored.") @@ -76,7 +76,7 @@ else qdel(target) to_chat(user, "You stuff the monkey in the machine.") - playsound(get_turf(src), 'sound/machines/juicer.ogg', 50, 1) + playsound(src, 'sound/machines/juicer.ogg', 50, 1) use_power(500) src.grinded++ to_chat(user, "The machine now has [grinded] monkeys worth of material stored.") @@ -87,7 +87,7 @@ return 1 if(grinded >= minimum_monkeys) to_chat(user, "The machine hisses loudly as it condenses the grinded monkey meat. After a moment, it dispenses a brand new monkey cube.") - playsound(get_turf(src), 'sound/machines/hiss.ogg', 50, 1) + playsound(src, 'sound/machines/hiss.ogg', 50, 1) grinded -= minimum_monkeys new /obj/item/weapon/reagent_containers/food/snacks/monkeycube/wrapped(src.loc) to_chat(user, "The machine's display flashes that it has [grinded] monkeys worth of material left.") diff --git a/code/game/machinery/kitchen/processor.dm b/code/game/machinery/kitchen/processor.dm index b0764957418..d0385cdc582 100644 --- a/code/game/machinery/kitchen/processor.dm +++ b/code/game/machinery/kitchen/processor.dm @@ -236,7 +236,7 @@ user.visible_message("[user] turns on [src].", \ "You turn on \a [src].", \ "You hear [src] start") - playsound(get_turf(src), 'sound/machines/blender.ogg', 50, 1) + playsound(src, 'sound/machines/blender.ogg', 50, 1) use_power(500) sleep(P.time*time_coeff) P.process(src.loc, O) diff --git a/code/game/machinery/kitchen/smartfridge.dm b/code/game/machinery/kitchen/smartfridge.dm index a0ffc30e1e0..22205466a6b 100644 --- a/code/game/machinery/kitchen/smartfridge.dm +++ b/code/game/machinery/kitchen/smartfridge.dm @@ -135,7 +135,9 @@ /obj/item/weapon/reagent_containers/pill) /obj/machinery/smartfridge/medbay/New() - . = ..() + ..() + if(map.nameShort == "deff") + icon = 'maps/defficiency/medbay.dmi' component_parts = newlist( /obj/item/weapon/circuitboard/smartfridge/medbay, @@ -160,7 +162,9 @@ /obj/item/weapon/reagent_containers) /obj/machinery/smartfridge/chemistry/New() - . = ..() + ..() + if(map.nameShort == "deff") + icon = 'maps/defficiency/medbay.dmi' component_parts = newlist( /obj/item/weapon/circuitboard/smartfridge/chemistry, @@ -237,6 +241,8 @@ /obj/machinery/smartfridge/bloodbank/New() . = ..() + if(map.nameShort == "deff") + icon = 'maps/defficiency/medbay.dmi' component_parts = newlist( /obj/item/weapon/circuitboard/smartfridge/bloodbank, diff --git a/code/game/machinery/lightswitch.dm b/code/game/machinery/lightswitch.dm index 9daa37b8c4a..2905612e218 100644 --- a/code/game/machinery/lightswitch.dm +++ b/code/game/machinery/lightswitch.dm @@ -8,17 +8,20 @@ anchored = 1.0 var/buildstage = 2 var/on = 0 - // luminosity = 1 - holomap = TRUE - auto_holomap = TRUE +/obj/machinery/light_switch/supports_holomap() + return TRUE + +/obj/machinery/light_switch/initialize() + add_self_to_holomap() /obj/machinery/light_switch/New(var/loc, var/ndir, var/building = 2) ..() - name = "[areaMaster.name] light switch" + var/area/this_area = get_area(src) + name = "[this_area.name] light switch" buildstage = building if(buildstage) - on = areaMaster.lightswitch + on = this_area.lightswitch else pixel_x = (ndir & 3)? 0 : (ndir == 4 ? 28 * PIXEL_MULTIPLIER: -28 * PIXEL_MULTIPLIER) pixel_y = (ndir & 3)? (ndir ==1 ? 28 * PIXEL_MULTIPLIER: -28 * PIXEL_MULTIPLIER) : 0 @@ -40,16 +43,17 @@ if(2) if(isscrewdriver(W)) to_chat(user, "You begin unscrewing \the [src].") - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 50, 1) if(do_after(user, src,10) && buildstage == 2) to_chat(user, "You unscrew the cover blocking the inner wiring of \the [src].") buildstage = 1 - on = areaMaster.lightswitch + var/area/this_area = get_area(src) + on = this_area.lightswitch return if(1) if(isscrewdriver(W)) to_chat(user, "You begin screwing closed \the [src].") - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 50, 1) if(do_after(user, src,10) && buildstage == 1) to_chat(user, "You tightly screw closed the cover of \the [src].") buildstage = 2 @@ -57,7 +61,7 @@ return if(iswirecutter(W)) to_chat(user, "You begin cutting the wiring from \the [src].") - playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 50, 1) + playsound(src, 'sound/items/Wirecutter.ogg', 50, 1) if(do_after(user, src,10) && buildstage == 1) to_chat(user, "You cut the wiring to the lighting power line.") new /obj/item/stack/cable_coil(get_turf(src),3) @@ -77,7 +81,7 @@ return if(iscrowbar(W)) to_chat(user, "You begin prying \the [src] off the wall.") - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) if(do_after(user, src,10) && buildstage == 0) to_chat(user, "You pry the frame off of the wall.") new /obj/item/mounted/frame/light_switch(get_turf(user)) @@ -101,15 +105,15 @@ if(buildstage != 2) return on = !on + var/area/this_area = get_area(src) + this_area.lightswitch = on + this_area.updateicon() - areaMaster.lightswitch = on - areaMaster.updateicon() - - for(var/obj/machinery/light_switch/L in areaMaster) + for(var/obj/machinery/light_switch/L in this_area) L.on = on L.updateicon() - areaMaster.power_change() + this_area.power_change() /obj/machinery/light_switch/power_change() if(powered(LIGHT)) diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm index f32751cee00..d261a84b01a 100644 --- a/code/game/machinery/machinery.dm +++ b/code/game/machinery/machinery.dm @@ -475,7 +475,7 @@ Class Procs: user.visible_message( "[user] begins to pry out the circuitboard from \the [src].", "You begin to pry out the circuitboard from \the [src]...") if(do_after(user, src, 40)) - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) + playsound(src, 'sound/items/Crowbar.ogg', 50, 1) dropFrame() spillContents() user.visible_message( "[user] successfully pries out the circuitboard from \the [src]!", @@ -524,7 +524,7 @@ Class Procs: to_chat(user, "You need to secure \the [src] before it can be welded.") return -1 if (WT.remove_fuel(0,user)) - playsound(get_turf(src), 'sound/items/Welder2.ogg', 50, 1) + playsound(src, 'sound/items/Welder2.ogg', 50, 1) user.visible_message("[user.name] starts to [state - 1 ? "unweld": "weld" ] the [src] [state - 1 ? "from" : "to"] the floor.", \ "You start to [state - 1 ? "unweld": "weld" ] the [src] [state - 1 ? "from" : "to"] the floor.", \ "You hear welding.") @@ -663,13 +663,13 @@ Class Procs: switch(notice_state) if("ping") src.visible_message("[bicon(src)] \The [src] pings.") - playsound(get_turf(src), 'sound/machines/notify.ogg', 50, 0) + playsound(src, 'sound/machines/notify.ogg', 50, 0) if("beep") src.visible_message("[bicon(src)] \The [src] beeps.") - playsound(get_turf(src), 'sound/machines/twobeep.ogg', 50, 0) + playsound(src, 'sound/machines/twobeep.ogg', 50, 0) if("buzz") src.visible_message("[bicon(src)] \The [src] buzzes.") - playsound(get_turf(src), 'sound/machines/buzz-two.ogg', 50, 0) + playsound(src, 'sound/machines/buzz-two.ogg', 50, 0) /obj/machinery/proc/check_rebuild() return @@ -720,7 +720,7 @@ Class Procs: if(O.onBuckledUserKick(H, src)) return //don't return 1! we will do the normal "touch" action if so! - playsound(get_turf(src), 'sound/effects/grillehit.ogg', 50, 1) //Zth: I couldn't find a proper sound, please replace it + playsound(src, 'sound/effects/grillehit.ogg', 50, 1) //Zth: I couldn't find a proper sound, please replace it H.visible_message("[H] kicks \the [src].", "You kick \the [src].") if(prob(70)) diff --git a/code/game/machinery/martian_printer.dm b/code/game/machinery/martian_printer.dm index 1363ec41ec7..c13eca2651c 100644 --- a/code/game/machinery/martian_printer.dm +++ b/code/game/machinery/martian_printer.dm @@ -1,4 +1,4 @@ -/obj/machinery/martian_printer +/obj/machinery/mob_printer name = "inset disk" desc = "A strange disk set into the ground, doesn't seem to be anything beyond decorative." icon = 'icons/mob/martian.dmi' @@ -9,48 +9,54 @@ idle_power_usage = 20 active_power_usage = 5000 var/building = 0 + var/print_path = /mob/living/carbon/complex/martian -/obj/machinery/martian_printer/attack_ghost(var/mob/dead/observer/O) +/obj/machinery/mob_printer/attack_ghost(var/mob/dead/observer/O) if(!canSpawn()) return if(O.can_reenter_corpse) - if(alert(O,"Do you want to get your squid on?","Time for some emergency probing","Yes","No")== "Yes") + if(alert(O,"Do you want to enter a corporeal form?","Inset Disk","Yes","No")== "Yes") if(building) - to_chat(O, "\The [src] is already processing another alien. Try again later.") + to_chat(O, "\The [src] is already processing another. Try again later.") return else return else if(!(O.can_reenter_corpse)) - to_chat(O,"You have recently ghosted and can not enter as a martian right now. Try again later.") + to_chat(O,"You have recently ghosted and can not enter right now. Try again later.") return - make_martian(O) + make_mob(O) -/obj/machinery/martian_printer/power_change() +/obj/machinery/mob_printer/power_change() if (powered()) stat &= ~NOPOWER else stat |= NOPOWER -/obj/machinery/martian_printer/proc/canSpawn() +/obj/machinery/mob_printer/proc/canSpawn() + if(!use_power) + return !building //Can be varedited to not need power. return !(stat & NOPOWER) && !building -/obj/machinery/martian_printer/proc/make_martian(var/mob/dead/observer/user) +/obj/machinery/mob_printer/proc/make_mob(var/mob/dead/observer/user) building = TRUE if(!user || !istype(user) || !user.client) // Player has already been made into another mob before this one spawned, so let's reset the spawner building = FALSE update_icon() return FALSE - flick("m_pad_active", src) + if(istype(print_path,/mob/living/carbon/complex/martian)) + flick("m_pad_active", src) //Martians get a special animation + else + flick("m_pad_alt", src) spawn(24) if(!user || !istype(user) || !user.client) // Player disappeared between clicking on the spawner and now, so we have no one to turn tentacle! building = FALSE return FALSE - var/mob/living/carbon/martian/M = new(get_turf(src)) + var/mob/M = new print_path(get_turf(src)) M.ckey = user.ckey qdel(user) diff --git a/code/game/machinery/mass_driver.dm b/code/game/machinery/mass_driver.dm index dfda3efae02..06ca3913e14 100644 --- a/code/game/machinery/mass_driver.dm +++ b/code/game/machinery/mass_driver.dm @@ -41,7 +41,7 @@ var/list/mass_drivers = list() if(isscrewdriver(W)) to_chat(user, "You begin to unscrew the bolts off the [src]...") - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 50, 1) if(do_after(user, src, 30)) var/obj/machinery/mass_driver_frame/F = new(get_turf(src)) F.dir = src.dir @@ -140,7 +140,7 @@ var/list/mass_drivers = list() if(!WT.remove_fuel(0, user)) to_chat(user, "The welding tool must be on to complete this task.") return 1 - playsound(get_turf(src), 'sound/items/Welder.ogg', 50, 1) + playsound(src, 'sound/items/Welder.ogg', 50, 1) to_chat(user, "You begin to cut the frame apart...") if(do_after(user, src, 30) && (build == 0)) to_chat(user, "You detach the plasteel sheets from each others.") @@ -152,7 +152,7 @@ var/list/mass_drivers = list() to_chat(user, "You can't anchor \the [src], as there's a mass driver in that location already.") return to_chat(user, "You begin to anchor \the [src] on the floor.") - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + playsound(src, 'sound/items/Ratchet.ogg', 50, 1) if(do_after(user, src, 10) && (build == 0)) to_chat(user, "You anchor \the [src]!") anchored = 1 @@ -162,7 +162,7 @@ var/list/mass_drivers = list() if(1) // Fixed to the floor if(iswrench(W)) to_chat(user, "You begin to de-anchor \the [src] from the floor.") - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + playsound(src, 'sound/items/Ratchet.ogg', 50, 1) if(do_after(user, src, 10) && (build == 1)) build-- update_icon() @@ -174,7 +174,7 @@ var/list/mass_drivers = list() if(!WT.remove_fuel(0, user)) to_chat(user, "The welding tool must be on to complete this task.") return 1 - playsound(get_turf(src), 'sound/items/Welder.ogg', 50, 1) + playsound(src, 'sound/items/Welder.ogg', 50, 1) to_chat(user, "You begin to weld \the [src] to the floor...") if(do_after(user, src, 40) && (build == 1)) to_chat(user, "You welded \the [src] to the floor.") @@ -187,7 +187,7 @@ var/list/mass_drivers = list() if(!WT.remove_fuel(0, user)) to_chat(user, "The welding tool must be on to complete this task.") return 1 - playsound(get_turf(src), 'sound/items/Welder.ogg', 50, 1) + playsound(src, 'sound/items/Welder.ogg', 50, 1) to_chat(user, "You begin to unweld \the [src] to the floor...") if(do_after(user, src, 40) && (build == 2)) to_chat(user, "You unwelded \the [src] to the floor.") @@ -196,7 +196,7 @@ var/list/mass_drivers = list() if(istype(W, /obj/item/stack/cable_coil)) var/obj/item/stack/cable_coil/C=W to_chat(user, "You start adding cables to \the [src]...") - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) if(do_after(user, src, 20) && (C.amount >= 3) && (build == 2)) C.use(3) to_chat(user, "You've added cables to \the [src].") @@ -207,7 +207,7 @@ var/list/mass_drivers = list() to_chat(user, "You begin to remove the wiring from \the [src].") if(do_after(user, src, 10) && (build == 3)) new /obj/item/stack/cable_coil(loc,3) - playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 50, 1) + playsound(src, 'sound/items/Wirecutter.ogg', 50, 1) to_chat(user, "You've removed the cables from \the [src].") build-- update_icon() @@ -215,7 +215,7 @@ var/list/mass_drivers = list() if(istype(W, /obj/item/stack/rods)) var/obj/item/stack/rods/R=W to_chat(user, "You begin to complete \the [src]...") - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) if(do_after(user, src, 20) && (R.amount >= 3) && (build == 3)) R.use(3) to_chat(user, "You've added the grille to \the [src].") @@ -225,7 +225,7 @@ var/list/mass_drivers = list() if(4) // Grille in place if(iscrowbar(W)) to_chat(user, "You begin to pry off the grille from \the [src]...") - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) + playsound(src, 'sound/items/Crowbar.ogg', 50, 1) if(do_after(user, src, 30) && (build == 4)) new /obj/item/stack/rods(loc,2) build-- @@ -233,7 +233,7 @@ var/list/mass_drivers = list() return 1 if(isscrewdriver(W)) to_chat(user, "You finalize the Mass Driver...") - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 50, 1) var/obj/machinery/mass_driver/M = new(get_turf(src)) M.dir = src.dir qdel(src) diff --git a/code/game/machinery/metaldetector.dm b/code/game/machinery/metaldetector.dm index c1b295ccbb0..6ec63bd5a8b 100644 --- a/code/game/machinery/metaldetector.dm +++ b/code/game/machinery/metaldetector.dm @@ -236,7 +236,7 @@ flick("[base_state]_flash", src) - playsound(get_turf(src), sndstr, 100, 1) + playsound(src, sndstr, 100, 1) /obj/machinery/detector/proc/check_for_weapons(var/obj/item/slot_item) //Unused anywhere, copypasted in secbot.dm diff --git a/code/game/machinery/mommi_spawner.dm b/code/game/machinery/mommi_spawner.dm index 3c484356460..29fffa6a897 100644 --- a/code/game/machinery/mommi_spawner.dm +++ b/code/game/machinery/mommi_spawner.dm @@ -3,9 +3,9 @@ desc = "A large pad sunk into the ground." icon = 'icons/obj/robotics.dmi' icon_state = "mommispawner-idle" - density = 1 - anchored = 1 - var/building=0 + density = TRUE + anchored = TRUE + var/building=FALSE var/metal=0 var/const/metalPerMoMMI=10 var/const/metalPerTick=1 @@ -14,15 +14,10 @@ active_power_usage = 5000 var/recharge_time=600 // 60s var/locked_to_zlevel = 0 // Whether to lock the spawned MoMMIs to the z-level + var/dorf = FALSE /obj/machinery/mommi_spawner/dorf - machine_flags = WRENCHMOVE - desc = "A large pad mounted to the ground with large bolts." - -/obj/machinery/mommi_spawner/dorf/attack_ghost(var/mob/dead/observer/user) - if(stat & NOPOWER|BROKEN) - return - ..() + dorf = TRUE /obj/machinery/mommi_spawner/power_change() if (powered()) @@ -142,12 +137,20 @@ // Make the MoMMI! var/turf/T = get_turf(src) + var/mob/living/silicon/robot/mommi/M = null + + if(dorf) + M = new /mob/living/silicon/robot/mommi/nt(T) + M.laws = new /datum/ai_laws/dorf + M.keeper = FALSE + else + M = new /mob/living/silicon/robot/mommi/soviet(T) - var/mob/living/silicon/robot/mommi/M = new /mob/living/silicon/robot/mommi(T) if(!M) return M.invisibility = 0 + if (locked_to_zlevel) M.add_ion_law("You belong to the station where you were created; do not leave it.") M.locked_to_z = T.z diff --git a/code/game/machinery/newscaster.dm b/code/game/machinery/newscaster.dm index 89fd8dd734a..c6935bf128b 100644 --- a/code/game/machinery/newscaster.dm +++ b/code/game/machinery/newscaster.dm @@ -31,7 +31,7 @@ //var/parent_channel var/backup_body ="" var/backup_author ="" - var/is_admin_message = 0 + var/is_admin_message = FALSE var/icon/img = null var/icon/backup_img @@ -40,30 +40,28 @@ /datum/feed_channel var/channel_name="" var/list/datum/feed_message/messages = list() - //var/message_count = 0 - var/locked=0 - var/author="" - var/backup_author="" - var/censored=0 - var/is_admin_channel=0 - //var/page = null //For newspapers + var/locked = FALSE + var/author = "" + var/backup_author = "" + var/censored = FALSE + var/is_admin_channel = FALSE /datum/feed_message/proc/clear() - src.author = "" - src.body = "" - src.backup_body = "" - src.backup_author = "" - src.img = null - src.backup_img = null + author = "" + body = "" + backup_body = "" + backup_author = "" + img = null + backup_img = null /datum/feed_channel/proc/clear() - src.channel_name = "" - src.messages = list() - src.locked = 0 - src.author = "" - src.backup_author = "" - src.censored = 0 - src.is_admin_channel = 0 + channel_name = "" + messages = list() + locked = 0 + author = "" + backup_author = "" + censored = 0 + is_admin_channel = 0 /datum/feed_network var/list/datum/feed_channel/network_channels = list() @@ -80,17 +78,11 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co icon = 'icons/obj/terminals.dmi' icon_state = "newscaster_normal" var/buildstage = 1 // 1 = complete, 0 = unscrewed + ghost_write = 1 // Allow ghosts to send Topic()s. + custom_aghost_alerts = 1 // We handle our own logging. - // Allow ghosts to send Topic()s. - ghost_write = 1 - custom_aghost_alerts=1 // We handle our own logging. - - //var/isbroken = 0 //1 if someone banged it with something heavy - //var/ispowered = 1 //starts powered, changes with power_change() - //OBSOLETE: the stat var already has BROKEN and NOPOWER flags, let's use these instead. - //var/list/datum/feed_channel/channel_list = list() //This list will contain the names of the feed channels. Each name will refer to a data region where the messages of the feed channels are stored. - //OBSOLETE: We're now using a global news network - var/screen = 0 //Or maybe I'll make it into a list within a list afterwards... whichever I prefer, go fuck yourselves :3 + var/screen = 0 + //Or maybe I'll make it into a list within a list afterwards... whichever I prefer, go fuck yourselves :3 // 0 = welcome screen - main menu // 1 = view feed channels // 2 = create feed channel @@ -103,35 +95,33 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co // 9 = viewing channel feeds // 10 = censor feed story // 11 = censor feed channel - //Holy shit this is outdated, made this when I was still starting newscasters :3 - var/paper_remaining = 15 // There is no point to setting it to 0 here if you're setting it to 15 in New() ????????? - var/securityCaster = 0 - // 0 = Caster cannot be used to issue wanted posters - // 1 = the opposite + + var/paper_remaining = 15 + var/securityCaster = FALSE + // FALSE = Caster cannot be used to issue wanted posters + // TRUE = the opposite + var/unit_no = 0 //Each newscaster has a unit number - //var/datum/feed_message/wanted //We're gonna use a feed_message to store data of the wanted person because fields are similar - //var/wanted_issue = 0 //OBSOLETE - // 0 = there's no WANTED issued, we don't need a special icon_state - // 1 = Guess what. var/alert_delay = 500 - var/alert = 0 - // 0 = there hasn't been a news/wanted update in the last alert_delay - // 1 = there has + var/alert = FALSE + // FALSE = there hasn't been a news/wanted update in the last alert_delay + // TRUE = there has + var/scanned_user = "Unknown" //Will contain the name of the person who currently uses the newscaster var/mob/masterController = null // Mob with control over the newscaster. - var/msg = ""; //Feed message + var/msg = ""; //Feed message var/photo = null var/channel_name = ""; //the feed channel which will be receiving the feed, or being created - var/c_locked=0; //Will our new channel be locked to public submissions? - var/hitstaken = 0 //Death at 3 hits from an item with force>=15 + var/c_locked = FALSE; //Will our new channel be locked to public submissions? + var/hitstaken = 0 //Death at 3 hits from an item with force>=15 var/datum/feed_channel/viewing_channel = list() luminosity = 0 - anchored = 1 + anchored = TRUE -/obj/machinery/newscaster/security_unit //Security unit +/obj/machinery/newscaster/security_unit //Security unit name = "Security Newscaster" - securityCaster = 1 + securityCaster = TRUE /obj/machinery/newscaster/New(var/loc, var/ndir, var/building = 1) buildstage = building @@ -141,7 +131,7 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co dir = ndir allCasters += src for(var/obj/machinery/newscaster/NEWSCASTER in allCasters) // Let's give it an appropriate unit number - src.unit_no++ + unit_no++ update_icon() ..() @@ -157,21 +147,21 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co if((stat & NOPOWER) || (stat & BROKEN)) icon_state = "newscaster_off" if(stat & BROKEN) //If the thing is smashed, add crack overlay on top of the unpowered sprite. - src.overlays.len = 0 - src.overlays += image(src.icon, "crack3") + overlays.Cut() + overlays += image(icon, "crack3") return - src.overlays.len = 0 //reset overlays + overlays.Cut() //reset overlays if(news_network.wanted_issue) //wanted icon state, there can be no overlays on it as it's a priority message icon_state = "newscaster_wanted" return if(alert) //new message alert overlay - src.overlays += image(icon = icon, icon_state = "newscaster_alert") + overlays += image(icon = icon, icon_state = "newscaster_alert") if(hitstaken > 0) //Cosmetic damage overlay - src.overlays += image(src.icon, "crack[hitstaken]") + overlays += image(icon, "crack[hitstaken]") icon_state = "newscaster_normal" return @@ -179,13 +169,13 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co /obj/machinery/newscaster/power_change() if(stat & BROKEN || buildstage != 1) //Broken shit can't be powered. return - if( src.powered() ) + if( powered() ) stat &= ~NOPOWER - src.update_icon() + update_icon() else spawn(rand(0, 15)) stat |= NOPOWER - src.update_icon() + update_icon() /obj/machinery/newscaster/ex_act(severity) @@ -198,12 +188,12 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co if(prob(50)) qdel(src) else - src.update_icon() //can't place it above the return and outside the if-else. or we might get runtimes of null.update_icon() if(prob(50)) goes in. + update_icon() //can't place it above the return and outside the if-else. or we might get runtimes of null.update_icon() if(prob(50)) goes in. return else if(prob(50)) stat |= BROKEN - src.update_icon() + update_icon() return return @@ -213,14 +203,14 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co hitstaken++ if(hitstaken>=3 && !(stat & BROKEN)) stat |= BROKEN - playsound(get_turf(src), 'sound/effects/Glassbr3.ogg', 100, 1) + playsound(src, 'sound/effects/Glassbr3.ogg', 100, 1) else - playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 100, 1) + playsound(src, 'sound/effects/Glasshit.ogg', 100, 1) update_icon() /obj/machinery/newscaster/attack_ai(mob/user as mob) - src.add_hiddenprint(user) - return src.attack_hand(user) + add_hiddenprint(user) + return attack_hand(user) /obj/machinery/newscaster/attack_hand(mob/user as mob) //########### THE MAIN BEEF IS HERE! And in the proc below this...############ @@ -235,14 +225,14 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co if(istype(user, /mob/living/carbon/human) || istype(user,/mob/living/silicon) || isobserver(user)) var/mob/M = user var/dat - dat = text("Newscaster

Newscaster Unit #[src.unit_no]

") + dat = text("Newscaster

Newscaster Unit #[unit_no]

") - src.scan_user(M) //Newscaster scans you + scan_user(M) //Newscaster scans you switch(screen) if(NEWSCASTER_MENU) - dat += {"Welcome to Newscasting Unit #[src.unit_no].
Interface & News networks Operational. + dat += {"Welcome to Newscasting Unit #[unit_no].
Interface & News networks Operational.
property of Nanotrasen Inc"} if(news_network.wanted_issue) dat+= "
Read Wanted Issue" @@ -253,17 +243,17 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
Print newspaper
Re-scan User

Exit"} - if(src.securityCaster) - var/wanted_already = 0 + if(securityCaster) + var/wanted_already = FALSE if(news_network.wanted_issue) - wanted_already = 1 + wanted_already = TRUE dat += {"
Feed Security functions:

[(wanted_already) ? ("Manage") : ("Publish")] \"Wanted\" Issue
Censor Feed Stories
Mark Feed Channel with Nanotrasen D-Notice"} - dat+="

The newscaster recognises you as: [src.scanned_user]" + dat+="

The newscaster recognises you as: [scanned_user]" if(NEWSCASTER_CHANNEL_LIST) dat+= "Station Feed Channels
" if( isemptylist(news_network.network_channels) ) @@ -274,85 +264,70 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co dat+="[CHANNEL.channel_name]
" else dat+="[CHANNEL.channel_name] [(CHANNEL.censored) ? ("***") : ()]
" - /*for(var/datum/feed_channel/CHANNEL in src.channel_list) - dat+="[CHANNEL.channel_name]:
\[created by: [CHANNEL.author]\]

" - if( isemptylist(CHANNEL.messages) ) - dat+="No feed messages found in channel...

" - else - for(var/datum/feed_message/MESSAGE in CHANNEL.messages) - dat+="-[MESSAGE.body]
\[Story by [MESSAGE.author]\]
"*/ - dat += {"

Refresh
Back"} if(NEWSCASTER_NEW_CHANNEL) dat += {"Creating new Feed Channel... -
Channel Name: [src.channel_name]
- Channel Author: [src.scanned_user]
- Will Accept Public Feeds: [(src.c_locked) ? ("NO") : ("YES")]

+
Channel Name: [channel_name]
+ Channel Author: [scanned_user]
+ Will Accept Public Feeds: [(c_locked) ? ("NO") : ("YES")]


Submit

Cancel
"} if(NEWSCASTER_NEW_MESSAGE) dat += {"Creating new Feed Message... -
Receiving Channel: [src.channel_name]
- Message Author: [src.scanned_user]
- Message Body: [src.msg]
"} +
Receiving Channel: [channel_name]
+ Message Author: [scanned_user]
+ Message Body: [msg]
"} - /*if(isAI(user)) - dat +="Upload Photo: [(src.photo ? "Photo Uploaded" : "No Photo")]
" - else - dat +="Attach Photo: [(src.photo ? "Photo Attached" : "No Photo")]
" - */ dat += AttachPhotoButton(user) dat += "
Submit

Cancel
" if(NEWSCASTER_NEW_MESSAGE_SUCCESS) - dat += {"Feed story successfully submitted to [src.channel_name].

+ dat += {"Feed story successfully submitted to [channel_name].


Return
"} if(NEWSCASTER_NEW_CHANNEL_SUCCESS) - dat += {"Feed Channel [src.channel_name] created successfully.

+ dat += {"Feed Channel [channel_name] created successfully.


Return
"} if(NEWSCASTER_NEW_MESSAGE_ERROR) dat+="ERROR: Could not submit Feed story to Network.

" - if(src.channel_name=="") + if(channel_name=="") dat+="�Invalid receiving channel name.
" - if(src.scanned_user=="Unknown") + if(scanned_user=="Unknown") dat+="�Channel author unverified.
" - if(src.msg == "" || src.msg == "\[REDACTED\]") + if(msg == "" || msg == "\[REDACTED\]") dat+="�Invalid message body.
" dat+="
Return
" if(NEWSCASTER_NEW_CHANNEL_ERROR) dat+="ERROR: Could not submit Feed Channel to Network.

" - //var/list/existing_channels = list() //Let's get dem existing channels - OBSOLETE var/list/existing_authors = list() for(var/datum/feed_channel/FC in news_network.network_channels) - //existing_channels += FC.channel_name //OBSOLETE if(FC.author == "\[REDACTED\]") existing_authors += FC.backup_author else existing_authors += FC.author - if(src.scanned_user in existing_authors) + if(scanned_user in existing_authors) dat+="�There already exists a Feed channel under your name.
" - if(src.channel_name=="" || src.channel_name == "\[REDACTED\]") + if(channel_name=="" || channel_name == "\[REDACTED\]") dat+="�Invalid channel name.
" - var/check = 0 + var/check = FALSE for(var/datum/feed_channel/FC in news_network.network_channels) - if(FC.channel_name == src.channel_name) - check = 1 + if(FC.channel_name == channel_name) + check = TRUE break if(check) dat+="�Channel name already in use.
" - if(src.scanned_user=="Unknown") + if(scanned_user=="Unknown") dat+="�Channel author unverified.
" dat+="
Return
" if(NEWSCASTER_PRINT_NEWSPAPER) - var/total_num=length(news_network.network_channels) - var/active_num=total_num - var/message_num=0 + var/total_num = length(news_network.network_channels) + var/active_num = total_num + var/message_num = 0 for(var/datum/feed_channel/FC in news_network.network_channels) if(!FC.censored) message_num += length(FC.messages) //Dont forget, datum/feed_channel's var messages is a list of datum/feed_message @@ -360,21 +335,21 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co active_num-- dat += {"Network currently serves a total of [total_num] Feed channels, [active_num] of which are active, and a total of [message_num] Feed Stories. -

Liquid Paper remaining: [(src.paper_remaining) *100 ] cm^3 +

Liquid Paper remaining: [(paper_remaining) *100 ] cm^3

Print Paper
Cancel"} if(NEWSCASTER_VIEW_CHANNEL) - dat+="[src.viewing_channel.channel_name]: \[created by: [src.viewing_channel.author]\]
" - if(src.viewing_channel.censored) + dat+="[viewing_channel.channel_name]: \[created by: [viewing_channel.author]\]
" + if(viewing_channel.censored) dat += {"ATTENTION: This channel has been deemed as threatening to the welfare of the station, and marked with a Nanotrasen D-Notice.
No further feed story additions are allowed while the D-Notice is in effect.


"} else - if( isemptylist(src.viewing_channel.messages) ) + if( isemptylist(viewing_channel.messages) ) dat+="No feed messages found in channel...
" else var/i = 0 - for(var/datum/feed_message/MESSAGE in src.viewing_channel.messages) + for(var/datum/feed_message/MESSAGE in viewing_channel.messages) i++ dat+="-[MESSAGE.body]
" if(MESSAGE.img) @@ -411,66 +386,66 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co dat+="
Back" if(NEWSCASTER_CENSORSHIP_CHANNEL) - dat += {"[src.viewing_channel.channel_name]: \[ created by: [src.viewing_channel.author] \]
- [(src.viewing_channel.author=="\[REDACTED\]") ? ("Undo Author censorship") : ("Censor channel Author")]
"} - if( isemptylist(src.viewing_channel.messages) ) + dat += {"[viewing_channel.channel_name]: \[ created by: [viewing_channel.author] \]
+ [(viewing_channel.author=="\[REDACTED\]") ? ("Undo Author censorship") : ("Censor channel Author")]
"} + if( isemptylist(viewing_channel.messages) ) dat+="No feed messages found in channel...
" else - for(var/datum/feed_message/MESSAGE in src.viewing_channel.messages) + for(var/datum/feed_message/MESSAGE in viewing_channel.messages) dat += {"-[MESSAGE.body]
\[Story by [MESSAGE.author]\]
[(MESSAGE.body == "\[REDACTED\]") ? ("Undo story censorship") : ("Censor story")] - [(MESSAGE.author == "\[REDACTED\]") ? ("Undo Author Censorship") : ("Censor message Author")]
"} dat+="
Back" if(NEWSCASTER_D_NOTICE_CHANNEL) - dat += {"[src.viewing_channel.channel_name]: \[ created by: [src.viewing_channel.author] \]
- Channel messages listed below. If you deem them dangerous to the station, you can Bestow a D-Notice upon the channel.
"} - if(src.viewing_channel.censored) + dat += {"[viewing_channel.channel_name]: \[ created by: [viewing_channel.author] \]
+ Channel messages listed below. If you deem them dangerous to the station, you can Bestow a D-Notice upon the channel.
"} + if(viewing_channel.censored) dat += {"ATTENTION: This channel has been deemed as threatening to the welfare of the station, and marked with a Nanotrasen D-Notice.
No further feed story additions are allowed while the D-Notice is in effect.

"} else - if( isemptylist(src.viewing_channel.messages) ) + if( isemptylist(viewing_channel.messages) ) dat+="No feed messages found in channel...
" else - for(var/datum/feed_message/MESSAGE in src.viewing_channel.messages) + for(var/datum/feed_message/MESSAGE in viewing_channel.messages) dat+="-[MESSAGE.body]
\[Story by [MESSAGE.author]\]
" dat+="
Back" if(NEWSCASTER_WANTED) dat+="Wanted Issue Handler:" - var/wanted_already = 0 + var/wanted_already = FALSE var/end_param = 1 if(news_network.wanted_issue) - wanted_already = 1 + wanted_already = TRUE end_param = 2 if(wanted_already) dat+="
A wanted issue is already in Feed Circulation. You can edit or cancel it below.
" dat += {"
- Criminal Name: [src.channel_name]
- Description: [src.msg]
"} + Criminal Name: [channel_name]
+ Description: [msg]
"} dat += AttachPhotoButton(user) if(wanted_already) dat+="Wanted Issue created by: [news_network.wanted_issue.backup_author]
" else - dat+="Wanted Issue will be created under prosecutor: [src.scanned_user]
" + dat+="Wanted Issue will be created under prosecutor: [scanned_user]
" dat+="
[(wanted_already) ? ("Edit Issue") : ("Submit")]" if(wanted_already) dat+="
Take down Issue" dat+="
Cancel" if(NEWSCASTER_WANTED_SUCCESS) - dat += {"Wanted issue for [src.channel_name] is now in Network Circulation.

+ dat += {"Wanted issue for [channel_name] is now in Network Circulation.


Return
"} if(NEWSCASTER_WANTED_ERROR) dat+="ERROR: Wanted Issue rejected by Network.

" - if(src.channel_name=="" || src.channel_name == "\[REDACTED\]") + if(channel_name=="" || channel_name == "\[REDACTED\]") dat+="�Invalid name for person wanted.
" - if(src.scanned_user=="Unknown") + if(scanned_user=="Unknown") dat+="�Issue author unverified.
" - if(src.msg == "" || src.msg == "\[REDACTED\]") + if(msg == "" || msg == "\[REDACTED\]") dat+="�Invalid description.
" dat+="
Return
" if(NEWSCASTER_WANTED_DELETED) @@ -491,7 +466,7 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co dat+="

Back
" if(NEWSCASTER_WANTED_EDIT) - dat += {"Wanted issue for [src.channel_name] successfully edited.

+ dat += {"Wanted issue for [channel_name] successfully edited.


Return
"} if(NEWSCASTER_PRINT_NEWSPAPER_SUCCESS) @@ -508,139 +483,136 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co M << browse(dat, "window=newscaster_main;size=400x600") onclose(M, "newscaster_main") - /*if(src.isbroken) //debugging shit - return - src.hitstaken++ - if(src.hitstaken==3) - src.isbroken = 1 - src.update_icon()*/ - - /obj/machinery/newscaster/Topic(href, href_list) if(..()) return if(masterController && !isobserver(masterController) && get_dist(masterController,src)<=1 && usr!=masterController) to_chat(usr, "You must wait for [masterController] to finish and move away.") return - if ((usr.contents.Find(src) || ((get_dist(src, usr) <= 1) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon) || isobserver(usr))) + if ((usr.contents.Find(src) || ((get_dist(src, usr) <= 1) && istype(loc, /turf))) || (istype(usr, /mob/living/silicon) || isobserver(usr))) usr.set_machine(src) if(href_list["set_channel_name"]) if(isobserver(usr) && !canGhostWrite(usr,src,"set a channel's name")) to_chat(usr, "You can't do that.") return - src.channel_name = strip_html_simple(input(usr, "Provide a Feed Channel Name", "Network Channel Handler", "")) - while (findtext(src.channel_name," ") == 1) - src.channel_name = copytext(src.channel_name,2,length(src.channel_name)+1) - src.updateUsrDialog() - //src.update_icon() + channel_name = strip_html_simple(input(usr, "Provide a Feed Channel Name", "Network Channel Handler", "")) + while (findtext(channel_name," ") == 1) + channel_name = copytext(channel_name,2,length(channel_name)+1) + updateUsrDialog() else if(href_list["set_channel_lock"]) if(isobserver(usr) && !canGhostWrite(usr,src,"locked a channel")) to_chat(usr, "You can't do that.") return - src.c_locked = !src.c_locked - src.updateUsrDialog() - //src.update_icon() + c_locked = !c_locked + updateUsrDialog() else if(href_list["submit_new_channel"]) if(isobserver(usr) && !canGhostWrite(usr,src,"created a new channel")) to_chat(usr, "You can't do that.") return - //var/list/existing_channels = list() //OBSOLETE var/list/existing_authors = list() for(var/datum/feed_channel/FC in news_network.network_channels) - //existing_channels += FC.channel_name if(FC.author == "\[REDACTED\]") existing_authors += FC.backup_author else existing_authors +=FC.author - var/check = 0 + var/check = FALSE for(var/datum/feed_channel/FC in news_network.network_channels) - if(FC.channel_name == src.channel_name) - check = 1 + if(FC.channel_name == channel_name) + check = TRUE break - if(src.channel_name == "" || src.channel_name == "\[REDACTED\]" || src.scanned_user == "Unknown" || check || (src.scanned_user in existing_authors) ) - src.screen=NEWSCASTER_NEW_CHANNEL_ERROR + if(channel_name == "" || channel_name == "\[REDACTED\]" || scanned_user == "Unknown" || check || (scanned_user in existing_authors) ) + screen=NEWSCASTER_NEW_CHANNEL_ERROR else var/choice = alert("Please confirm Feed channel creation","Network Channel Handler","Confirm","Cancel") if(choice=="Confirm") var/datum/feed_channel/newChannel = new /datum/feed_channel - newChannel.channel_name = src.channel_name - newChannel.author = src.scanned_user + newChannel.channel_name = channel_name + newChannel.author = scanned_user newChannel.locked = c_locked feedback_inc("newscaster_channels",1) - /*for(var/obj/machinery/newscaster/NEWSCASTER in allCasters) //Let's add the new channel in all casters. - NEWSCASTER.channel_list += newChannel*/ //Now that it is sane, get it into the list. -OBSOLETE news_network.network_channels += newChannel //Adding channel to the global network - src.screen = NEWSCASTER_MENU - src.updateUsrDialog() - //src.update_icon() + screen = NEWSCASTER_MENU + updateUsrDialog() else if(href_list["set_channel_receiving"]) if(isobserver(usr) && !canGhostWrite(usr,src,"tried to set the receiving channel")) to_chat(usr, "You can't do that.") return - //var/list/datum/feed_channel/available_channels = list() + var/list/available_channels = list() for(var/datum/feed_channel/F in news_network.network_channels) if( (!F.locked || F.author == scanned_user) && !F.censored) available_channels += F.channel_name - src.channel_name = strip_html_simple(input(usr, "Choose receiving Feed Channel", "Network Channel Handler") in available_channels ) - src.updateUsrDialog() + channel_name = strip_html_simple(input(usr, "Choose receiving Feed Channel", "Network Channel Handler") in available_channels ) + updateUsrDialog() else if(href_list["set_new_message"]) if(isobserver(usr) && !canGhostWrite(usr,src,"set the message of a new feed story")) to_chat(usr, "You can't do that.") return - if(isnull(src.msg)) - src.msg = "" - src.msg = strip_html(input(usr, "Write your Feed story", "Network Channel Handler", src.msg)) - while (findtext(src.msg," ") == 1) - src.msg = copytext(src.msg,2,length(src.msg)+1) - src.updateUsrDialog() + if(isnull(msg)) + msg = "" + msg = strip_html(input(usr, "Write your Feed story", "Network Channel Handler", msg)) + while (findtext(msg," ") == 1) + msg = copytext(msg,2,length(msg)+1) + updateUsrDialog() else if(href_list["set_attachment"]) if(isobserver(usr)) to_chat(usr, "You can't do that.") return AttachPhoto(usr) - src.updateUsrDialog() + updateUsrDialog() else if(href_list["upload_photo"]) - if(!isAI(usr)) + if(!issilicon(usr)) return if(photo) EjectPhoto() - src.updateUsrDialog() + updateUsrDialog() return + var/obj/item/device/camera/silicon/targetcam = null - var/mob/living/silicon/ai/A = usr + if(isAI(usr)) + var/mob/living/silicon/ai/A = usr + targetcam = A.aicamera + else if((isrobot(usr))) + var/mob/living/silicon/robot/R = usr + if(R.connected_ai) + targetcam = R.connected_ai.aicamera + else + targetcam = R.aicamera + else + to_chat(usr, "You cannot interface with the silicon photo uploading network.") + return var/list/nametemp = list() var/find - if(A.aicamera.aipictures.len == 0) - to_chat(usr, "No images saved") + if(!targetcam.aipictures.len) + to_chat(usr, "No images saved") return - for(var/datum/picture/t in A.aicamera.aipictures) + for(var/datum/picture/t in targetcam.aipictures) nametemp += t.fields["name"] find = input("Select image") in nametemp - for(var/datum/picture/q in A.aicamera.aipictures) + for(var/datum/picture/q in targetcam.aipictures) if(q.fields["name"] == find) photo = q break - src.updateUsrDialog() + updateUsrDialog() else if(href_list["submit_new_message"]) if(isobserver(usr) && !canGhostWrite(usr,src,"added a new story")) to_chat(usr, "You can't do that.") return - if(src.msg =="" || src.msg=="\[REDACTED\]" || src.scanned_user == "Unknown" || src.channel_name == "" ) - src.screen=NEWSCASTER_NEW_MESSAGE_ERROR + if(msg =="" || msg=="\[REDACTED\]" || scanned_user == "Unknown" || channel_name == "" ) + screen=NEWSCASTER_NEW_MESSAGE_ERROR else var/datum/feed_message/newMsg = new /datum/feed_message - newMsg.author = src.scanned_user - newMsg.body = src.msg + newMsg.author = scanned_user + newMsg.body = msg if(photo) if(istype(photo,/obj/item/weapon/photo)) var/obj/item/weapon/photo/P = photo @@ -653,107 +625,107 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co EjectPhoto() feedback_inc("newscaster_stories",1) for(var/datum/feed_channel/FC in news_network.network_channels) - if(FC.channel_name == src.channel_name) + if(FC.channel_name == channel_name) FC.messages += newMsg //Adding message to the network's appropriate feed_channel break - src.screen = NEWSCASTER_MENU + screen = NEWSCASTER_MENU for(var/obj/machinery/newscaster/NEWSCASTER in allCasters) - NEWSCASTER.newsAlert(src.channel_name) + NEWSCASTER.newsAlert(channel_name) - src.updateUsrDialog() + updateUsrDialog() else if(href_list["create_channel"]) if(isobserver(usr) && !canGhostWrite(usr,src,"created a channel")) to_chat(usr, "You can't do that.") return - src.screen=NEWSCASTER_NEW_CHANNEL - src.updateUsrDialog() + screen=NEWSCASTER_NEW_CHANNEL + updateUsrDialog() else if(href_list["create_feed_story"]) if(isobserver(usr) && !canGhostWrite(usr,src,"created a feed story")) to_chat(usr, "You can't do that.") return - src.screen=NEWSCASTER_NEW_MESSAGE - src.updateUsrDialog() + screen=NEWSCASTER_NEW_MESSAGE + updateUsrDialog() else if(href_list["menu_paper"]) if(isobserver(usr) && !canGhostWrite(usr,src,"")) to_chat(usr, "You can't do that.") return - src.screen=NEWSCASTER_PRINT_NEWSPAPER - src.updateUsrDialog() + screen=NEWSCASTER_PRINT_NEWSPAPER + updateUsrDialog() else if(href_list["print_paper"]) if(isobserver(usr) && !canGhostWrite(usr,src,"printed a paper")) to_chat(usr, "You can't do that.") return - if(!src.paper_remaining) - src.screen=NEWSCASTER_PRINT_NEWSPAPER_ERROR + if(!paper_remaining) + screen=NEWSCASTER_PRINT_NEWSPAPER_ERROR else - src.print_paper() - src.screen = NEWSCASTER_PRINT_NEWSPAPER_SUCCESS - src.updateUsrDialog() + print_paper() + screen = NEWSCASTER_PRINT_NEWSPAPER_SUCCESS + updateUsrDialog() else if(href_list["menu_censor_story"]) if(isobserver(usr) && !canGhostWrite(usr,src,"censored a story")) to_chat(usr, "You can't do that.") return - src.screen=NEWSCASTER_CENSORSHIP_MENU - src.updateUsrDialog() + screen=NEWSCASTER_CENSORSHIP_MENU + updateUsrDialog() else if(href_list["menu_censor_channel"]) if(isobserver(usr) && !canGhostWrite(usr,src,"censored a channel")) to_chat(usr, "You can't do that.") return - src.screen=NEWSCASTER_D_NOTICE_MENU - src.updateUsrDialog() + screen=NEWSCASTER_D_NOTICE_MENU + updateUsrDialog() else if(href_list["menu_wanted"]) if(isobserver(usr) && !canGhostWrite(usr,src,"")) to_chat(usr, "You can't do that.") return - var/already_wanted = 0 + var/already_wanted = FALSE if(news_network.wanted_issue) - already_wanted = 1 + already_wanted = TRUE if(already_wanted) - src.channel_name = news_network.wanted_issue.author - src.msg = news_network.wanted_issue.body - src.screen = NEWSCASTER_WANTED - src.updateUsrDialog() + channel_name = news_network.wanted_issue.author + msg = news_network.wanted_issue.body + screen = NEWSCASTER_WANTED + updateUsrDialog() else if(href_list["set_wanted_name"]) if(isobserver(usr) && !canGhostWrite(usr,src,"tried to set the name of a wanted person")) to_chat(usr, "You can't do that.") return - src.channel_name = strip_html(input(usr, "Provide the name of the Wanted person", "Network Security Handler", "")) - while (findtext(src.channel_name," ") == 1) - src.channel_name = copytext(src.channel_name,2,length(src.channel_name)+1) - src.updateUsrDialog() + channel_name = strip_html(input(usr, "Provide the name of the Wanted person", "Network Security Handler", "")) + while (findtext(channel_name," ") == 1) + channel_name = copytext(channel_name,2,length(channel_name)+1) + updateUsrDialog() else if(href_list["set_wanted_desc"]) if(isobserver(usr) && !canGhostWrite(usr,src,"tried to set the description of a wanted person")) to_chat(usr, "You can't do that.") return - src.msg = strip_html(input(usr, "Provide the a description of the Wanted person and any other details you deem important", "Network Security Handler", "")) - while (findtext(src.msg," ") == 1) - src.msg = copytext(src.msg,2,length(src.msg)+1) - src.updateUsrDialog() + msg = strip_html(input(usr, "Provide the a description of the Wanted person and any other details you deem important", "Network Security Handler", "")) + while (findtext(msg," ") == 1) + msg = copytext(msg,2,length(msg)+1) + updateUsrDialog() else if(href_list["submit_wanted"]) if(isobserver(usr) && !canGhostWrite(usr,src,"submitted a wanted poster")) to_chat(usr, "You can't do that.") return var/input_param = text2num(href_list["submit_wanted"]) - if(src.msg == "" || src.channel_name == "" || src.scanned_user == "Unknown") - src.screen = NEWSCASTER_WANTED_ERROR + if(msg == "" || channel_name == "" || scanned_user == "Unknown") + screen = NEWSCASTER_WANTED_ERROR else var/choice = alert("Please confirm Wanted Issue [(input_param==1) ? ("creation.") : ("edit.")]","Network Security Handler","Confirm","Cancel") if(choice=="Confirm") if(input_param==1) //If input_param == 1 we're submitting a new wanted issue. At 2 we're just editing an existing one. See the else below var/datum/feed_message/WANTED = new /datum/feed_message - WANTED.author = src.channel_name - WANTED.body = src.msg - WANTED.backup_author = src.scanned_user //I know, a bit wacky + WANTED.author = channel_name + WANTED.body = msg + WANTED.backup_author = scanned_user //I know, a bit wacky if(photo) if(istype(photo,/obj/item/weapon/photo)) var/obj/item/weapon/photo/P = photo @@ -765,14 +737,14 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co for(var/obj/machinery/newscaster/NEWSCASTER in allCasters) NEWSCASTER.newsAlert() NEWSCASTER.update_icon() - src.screen = NEWSCASTER_WANTED_SUCCESS + screen = NEWSCASTER_WANTED_SUCCESS else if(news_network.wanted_issue.is_admin_message) alert("The wanted issue has been distributed by a Nanotrasen higherup. You cannot edit it.","Ok") return - news_network.wanted_issue.author = src.channel_name - news_network.wanted_issue.body = src.msg - news_network.wanted_issue.backup_author = src.scanned_user + news_network.wanted_issue.author = channel_name + news_network.wanted_issue.body = msg + news_network.wanted_issue.backup_author = scanned_user if(photo) if(istype(photo,/obj/item/weapon/photo)) var/obj/item/weapon/photo/P = photo @@ -780,9 +752,9 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co else if(istype(photo,/datum/picture)) var/datum/picture/P = photo news_network.wanted_issue.img = P.fields["img"] - src.screen = NEWSCASTER_WANTED_EDIT + screen = NEWSCASTER_WANTED_EDIT - src.updateUsrDialog() + updateUsrDialog() else if(href_list["cancel_wanted"]) if(news_network.wanted_issue.is_admin_message) @@ -793,12 +765,12 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co news_network.wanted_issue = null for(var/obj/machinery/newscaster/NEWSCASTER in allCasters) NEWSCASTER.update_icon() - src.screen=NEWSCASTER_WANTED_DELETED - src.updateUsrDialog() + screen=NEWSCASTER_WANTED_DELETED + updateUsrDialog() else if(href_list["view_wanted"]) - src.screen=NEWSCASTER_WANTED_SHOW - src.updateUsrDialog() + screen=NEWSCASTER_WANTED_SHOW + updateUsrDialog() else if(href_list["censor_channel_author"]) if(isobserver(usr) && !canGhostWrite(usr,src,"tried to censor an author")) to_chat(usr, "You can't do that.") @@ -812,7 +784,7 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co FC.author = "\[REDACTED\]" else FC.author = FC.backup_author - src.updateUsrDialog() + updateUsrDialog() else if(href_list["censor_channel_story_author"]) if(isobserver(usr) && !canGhostWrite(usr,src,"tried to censor a story's author")) @@ -827,7 +799,7 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co MSG.author = "\[REDACTED\]" else MSG.author = MSG.backup_author - src.updateUsrDialog() + updateUsrDialog() else if(href_list["censor_channel_story_body"]) if(isobserver(usr) && !canGhostWrite(usr,src,"tried to censor a story")) @@ -847,16 +819,16 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co MSG.body = "\[REDACTED\]" else MSG.body = MSG.backup_body - src.updateUsrDialog() + updateUsrDialog() else if(href_list["pick_d_notice"]) if(isobserver(usr) && !canGhostWrite(usr,src,"")) to_chat(usr, "You can't do that.") return var/datum/feed_channel/FC = locate(href_list["pick_d_notice"]) - src.viewing_channel = FC - src.screen=NEWSCASTER_D_NOTICE_CHANNEL - src.updateUsrDialog() + viewing_channel = FC + screen=NEWSCASTER_D_NOTICE_CHANNEL + updateUsrDialog() else if(href_list["toggle_d_notice"]) if(isobserver(usr) && !canGhostWrite(usr,src,"tried to set a D-notice")) @@ -867,33 +839,33 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co alert("This channel was created by a Nanotrasen Officer. You cannot place a D-Notice upon it.","Ok") return FC.censored = !FC.censored - src.updateUsrDialog() + updateUsrDialog() else if(href_list["view"]) - src.screen=NEWSCASTER_CHANNEL_LIST - src.updateUsrDialog() + screen=NEWSCASTER_CHANNEL_LIST + updateUsrDialog() else if(href_list["setScreen"]) //Brings us to the main menu and resets all fields~ - src.screen = text2num(href_list["setScreen"]) - if (src.screen == NEWSCASTER_MENU) - src.scanned_user = "Unknown"; + screen = text2num(href_list["setScreen"]) + if (screen == NEWSCASTER_MENU) + scanned_user = "Unknown"; msg = ""; - src.c_locked=0; + c_locked=0; channel_name=""; - src.viewing_channel = null - src.updateUsrDialog() + viewing_channel = null + updateUsrDialog() else if(href_list["show_channel"]) var/datum/feed_channel/FC = locate(href_list["show_channel"]) - src.viewing_channel = FC - src.screen = NEWSCASTER_VIEW_CHANNEL - src.updateUsrDialog() + viewing_channel = FC + screen = NEWSCASTER_VIEW_CHANNEL + updateUsrDialog() else if(href_list["pick_censor_channel"]) var/datum/feed_channel/FC = locate(href_list["pick_censor_channel"]) - src.viewing_channel = FC - src.screen = NEWSCASTER_CENSORSHIP_CHANNEL - src.updateUsrDialog() + viewing_channel = FC + screen = NEWSCASTER_CENSORSHIP_CHANNEL + updateUsrDialog() else if(href_list["show_photo_info"]) var/datum/feed_message/FM = locate(href_list["show_photo_info"]) @@ -901,35 +873,35 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co if(istype(FM) && FM.img_info) usr.show_message("[FM.img_info]", MESSAGE_SEE) - src.updateUsrDialog() + updateUsrDialog() else if(href_list["refresh"]) - src.updateUsrDialog() + updateUsrDialog() /obj/machinery/newscaster/attackby(obj/item/I as obj, mob/user as mob) switch(buildstage) if(0) if(iscrowbar(I)) - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) user.visible_message("[user] begins prying off the [src]!", "You begin prying off the [src]") if(do_after(user, src,10)) to_chat(user, "You pry off the [src]!.") - new /obj/item/mounted/frame/newscaster(src.loc) + new /obj/item/mounted/frame/newscaster(loc) qdel(src) return if(isscrewdriver(I) && !(stat & BROKEN)) user.visible_message("[user] screws in the [src]!", "You screw in the [src]") - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 100, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 100, 1) buildstage = 1 if(1) if(isscrewdriver(I) && !(stat & BROKEN)) user.visible_message("[user] unscrews the [src]!", "You unscrew the [src]") - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 100, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 100, 1) buildstage = 0 - src.update_icon() + update_icon() return if ((stat & BROKEN) && (istype(I, /obj/item/stack/sheet/glass/glass))) @@ -938,12 +910,12 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co to_chat(user, "You need more glass to do that.") else stack.use(2) - src.hitstaken = 0 + hitstaken = 0 stat &= ~BROKEN - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 80, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 80, 1) else if (stat & BROKEN) - playsound(get_turf(src), 'sound/effects/hit_on_shattered_glass.ogg', 100, 1) + playsound(src, 'sound/effects/hit_on_shattered_glass.ogg', 100, 1) visible_message("[user.name] further abuses the shattered [src].") else @@ -951,34 +923,34 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co if(istype(P) && !photo && user.drop_item(P, src)) photo = P to_chat(user, "You add \the [P] to \the [src].") - src.updateUsrDialog() + updateUsrDialog() else if(istype(I, /obj/item/weapon) ) var/obj/item/weapon/W = I if(W.force <15) visible_message("[user.name] hits the [src] with the [W] with no visible effect." ) - playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 100, 1) + playsound(src, 'sound/effects/Glasshit.ogg', 100, 1) else user.do_attack_animation(src, W) - src.hitstaken++ - if(src.hitstaken==3) + hitstaken++ + if(hitstaken==3) visible_message("[user.name] smashes the [src]!") stat |= BROKEN - playsound(get_turf(src), 'sound/effects/Glassbr3.ogg', 100, 1) + playsound(src, 'sound/effects/Glassbr3.ogg', 100, 1) else - visible_message("[user.name] forcefully slams the [src.name] with the [I.name]!") - playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 100, 1) + visible_message("[user.name] forcefully slams the [name] with the [I.name]!") + playsound(src, 'sound/effects/Glasshit.ogg', 100, 1) else to_chat(user, "This does nothing.") - src.update_icon() + update_icon() /obj/machinery/newscaster/attack_ai(mob/user as mob) - src.add_hiddenprint(user) - return src.attack_hand(user) //or maybe it'll have some special functions? No idea. + add_hiddenprint(user) + return attack_hand(user) //or maybe it'll have some special functions? No idea. /obj/machinery/newscaster/attack_paw(mob/user as mob) - to_chat(user, "The newscaster controls are far too complicated for your tiny brain!") + to_chat(user, "The newscaster controls are far too complicated for your tiny brain!") return /obj/machinery/newscaster/proc/AttachPhoto(mob/user as mob) @@ -994,7 +966,7 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co return if(istype(photo,/obj/item/weapon/photo)) var/obj/item/weapon/photo/P = photo - P.forceMove(src.loc) + P.forceMove(loc) photo = null else if(istype(photo,/datum/picture)) @@ -1003,7 +975,7 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co /obj/machinery/newscaster/proc/AttachPhotoButton(mob/user as mob) var/name = "Attach Photo" var/href = "set_attachment=1" - if(isAI(user)) + if(issilicon(user)) name = "Upload Photo" href = "upload_photo=1" @@ -1038,7 +1010,7 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co pressure_resistance = 1 attack_verb = list("baps", "smacks", "whaps") autoignition_temperature = AUTOIGNITION_PAPER - fire_fuel = 1 + fire_fuel = TRUE var/screen = 0 var/pages = 0 @@ -1048,43 +1020,38 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co var/scribble="" var/scribble_page = null -/*obj/item/weapon/newspaper/attack_hand(mob/user as mob) - ..() - to_chat(world, "derp")*/ - -obj/item/weapon/newspaper/attack_self(mob/user as mob) +/obj/item/weapon/newspaper/attack_self(mob/user as mob) if(ishuman(user)) - //var/mob/living/carbon/human/human_user = user var/dat - src.pages = 0 + pages = 0 switch(screen) if(NEWSPAPER_TITLE_PAGE) //Cover dat += {"
The Griffon
Nanotrasen-standard newspaper, for use on Nanotrasen Space Facilities

"} - if(isemptylist(src.news_content)) - if(src.important_message) - dat+="Contents:
    **Important Security Announcement** \[page [src.pages+2]\]
" + if(isemptylist(news_content)) + if(important_message) + dat+="Contents:
    **Important Security Announcement** \[page [pages+2]\]
" else dat+="Other than the title, the rest of the newspaper is unprinted..." else dat+="Contents:
    " - for(var/datum/feed_channel/NP in src.news_content) - src.pages++ - if(src.important_message) - dat+="**Important Security Announcement** \[page [src.pages+2]\]
    " + for(var/datum/feed_channel/NP in news_content) + pages++ + if(important_message) + dat+="**Important Security Announcement** \[page [pages+2]\]
    " var/temp_page=0 - for(var/datum/feed_channel/NP in src.news_content) + for(var/datum/feed_channel/NP in news_content) temp_page++ dat+="[NP.channel_name] \[page [temp_page+1]\]
    " dat+="
" if(scribble_page==curr_page) - dat+="
There is a small scribble near the end of this page... It reads: \"[src.scribble]\"" + dat+="
There is a small scribble near the end of this page... It reads: \"[scribble]\"" dat+= "
" if(NEWSPAPER_CONTENT_PAGE) // X channel pages inbetween. - for(var/datum/feed_channel/NP in src.news_content) - src.pages++ //Let's get it right again. - var/datum/feed_channel/C = src.news_content[src.curr_page] + for(var/datum/feed_channel/NP in news_content) + pages++ //Let's get it right again. + var/datum/feed_channel/C = news_content[curr_page] dat+="[C.channel_name] \[created by: [C.author]\]

" if(C.censored) dat+="This channel was deemed dangerous to the general welfare of the station and therefore marked with a D-Notice. Its contents were not transferred to the newspaper at the time of printing." @@ -1103,12 +1070,12 @@ obj/item/weapon/newspaper/attack_self(mob/user as mob) dat+="\[Story by [MESSAGE.author]\]

" dat+="" if(scribble_page==curr_page) - dat+="
There is a small scribble near the end of this page... It reads: \"[src.scribble]\"" + dat+="
There is a small scribble near the end of this page... It reads: \"[scribble]\"" dat+= "

" if(NEWSPAPER_LAST_PAGE) //Last page - for(var/datum/feed_channel/NP in src.news_content) - src.pages++ - if(src.important_message!=null) + for(var/datum/feed_channel/NP in news_content) + pages++ + if(important_message!=null) dat += {"
Wanted Issue:


Criminal name: [important_message.author]
@@ -1122,12 +1089,12 @@ obj/item/weapon/newspaper/attack_self(mob/user as mob) else dat+="Apart from some uninteresting Classified ads, there's nothing on this page..." if(scribble_page==curr_page) - dat+="
There is a small scribble near the end of this page... It reads: \"[src.scribble]\"" + dat+="
There is a small scribble near the end of this page... It reads: \"[scribble]\"" dat+= "
" else dat+="I'm sorry to break your immersion. This shit's bugged. Report this bug to Agouri, polyxenitopalidou@gmail.com" - dat+="

[src.curr_page+1]
" + dat+="

[curr_page+1]
" usr << browse(dat, "window=newspaper_main;size=300x400") onclose(usr, "newspaper_main") else @@ -1140,50 +1107,50 @@ obj/item/weapon/newspaper/Topic(href, href_list) if ((src in U.contents) || ( istype(loc, /turf) && in_range(src, U) )) U.set_machine(src) if(href_list["next_page"]) - if(curr_page==src.pages+1) + if(curr_page==pages+1) return //Don't need that at all, but anyway. - if(src.curr_page == src.pages) //We're at the middle, get to the end - src.screen = NEWSPAPER_LAST_PAGE + if(curr_page == pages) //We're at the middle, get to the end + screen = NEWSPAPER_LAST_PAGE else if(curr_page == 0) //We're at the start, get to the middle - src.screen = NEWSPAPER_CONTENT_PAGE - src.curr_page++ - playsound(get_turf(src), "pageturn", 50, 1) + screen = NEWSPAPER_CONTENT_PAGE + curr_page++ + playsound(src, "pageturn", 50, 1) else if(href_list["prev_page"]) if(curr_page == 0) return if(curr_page == 1) - src.screen = NEWSPAPER_TITLE_PAGE + screen = NEWSPAPER_TITLE_PAGE else - if(curr_page == src.pages+1) //we're at the end, let's go back to the middle. - src.screen = NEWSPAPER_CONTENT_PAGE - src.curr_page-- - playsound(get_turf(src), "pageturn", 50, 1) + if(curr_page == pages+1) //we're at the end, let's go back to the middle. + screen = NEWSPAPER_CONTENT_PAGE + curr_page-- + playsound(src, "pageturn", 50, 1) - if (istype(src.loc, /mob)) - src.attack_self(src.loc) + if (istype(loc, /mob)) + attack_self(loc) obj/item/weapon/newspaper/attackby(obj/item/weapon/W as obj, mob/user as mob) if(istype(W, /obj/item/weapon/pen)) - if(src.scribble_page == src.curr_page) + if(scribble_page == curr_page) to_chat(user, "There's already a scribble in this page... You wouldn't want to make things too cluttered, would you?") else var/s = strip_html( input(user, "Write something", "Newspaper", "") ) s = copytext(sanitize(s), 1, MAX_MESSAGE_LEN) if (!s) return - if (!in_range(src, usr) && src.loc != usr) + if (!in_range(src, usr) && loc != usr) return - src.scribble_page = src.curr_page - src.scribble = s - src.attack_self(user) + scribble_page = curr_page + scribble = s + attack_self(user) return else if(W.is_hot()) - src.ashify_item(user) + ashify_item(user) return #undef NEWSPAPER_TITLE_PAGE @@ -1206,27 +1173,24 @@ obj/item/weapon/newspaper/attackby(obj/item/weapon/W as obj, mob/user as mob) if(istype(human_user.wear_id, /obj/item/device/pda) ) //autorecognition, woo! var/obj/item/device/pda/P = human_user.wear_id if(P.id) - src.scanned_user = "[P.id.registered_name] ([P.id.assignment])" + scanned_user = "[P.id.registered_name] ([P.id.assignment])" else - src.scanned_user = "Unknown" + scanned_user = "Unknown" else if(istype(human_user.wear_id, /obj/item/weapon/card/id) ) var/obj/item/weapon/card/id/ID = human_user.wear_id - src.scanned_user ="[ID.registered_name] ([ID.assignment])" + scanned_user ="[ID.registered_name] ([ID.assignment])" else - src.scanned_user ="Unknown" + scanned_user ="Unknown" else - src.scanned_user ="Unknown" - else if (isAI(user)) + scanned_user ="Unknown" + else if (issilicon(user)) var/mob/living/silicon/ai_user = user - src.scanned_user = "[ai_user.name] ([ai_user.job])" + scanned_user = "[ai_user.name] ([ai_user.job])" else if (isAdminGhost(user)) - src.scanned_user = "Nanotrasen Officer #[rand(0,9)][rand(0,9)][rand(0,9)]" + scanned_user = "Nanotrasen Officer #[rand(0,9)][rand(0,9)][rand(0,9)]" else if (isobserver(user)) - src.scanned_user = "Space-Time Anomaly #[rand(0,9)][rand(0,9)][rand(0,9)]" -// if(masterController && masterController.client && get_dist(masterController,src)<=1) -// to_chat(masterController, "You were booted from \the [src] by [scanned_user].") + scanned_user = "Space-Time Anomaly #[rand(0,9)][rand(0,9)][rand(0,9)]" masterController = user -// to_chat(masterController, "[bicon(src)] Welcome back, [scanned_user]!") /obj/machinery/newscaster/proc/print_paper() feedback_inc("newscaster_newspapers_printed",1) @@ -1236,27 +1200,23 @@ obj/item/weapon/newspaper/attackby(obj/item/weapon/W as obj, mob/user as mob) if(news_network.wanted_issue) NEWSPAPER.important_message = news_network.wanted_issue NEWSPAPER.forceMove(get_turf(src)) - src.paper_remaining-- + paper_remaining-- return -//Removed for now so these aren't even checked every tick. Left this here in-case Agouri needs it later. -///obj/machinery/newscaster/process() //Was thinking of doing the icon update through process, but multiple iterations per second does not -// return //bode well with a newscaster network of 10+ machines. Let's just return it, as it's added in the machines list. - /obj/machinery/newscaster/proc/newsAlert(channel) //This isn't Agouri's work, for it is ugly and vile. var/turf/T = get_turf(src) //Who the fuck uses spawn(600) anyway, jesus christ if(channel) say("Breaking news from [channel]!") - src.alert = 1 - src.update_icon() + alert = TRUE + update_icon() spawn(300) - src.alert = 0 - src.update_icon() - playsound(get_turf(src), 'sound/machines/twobeep.ogg', 75, 1) + alert = FALSE + update_icon() + playsound(src, 'sound/machines/twobeep.ogg', 75, 1) else for(var/mob/O in hearers(world.view-1, T)) say("Attention! Wanted issue distributed!") - playsound(get_turf(src), 'sound/machines/warning-buzzer.ogg', 75, 1) + playsound(src, 'sound/machines/warning-buzzer.ogg', 75, 1) return /obj/machinery/newscaster/say_quote(text) diff --git a/code/game/machinery/overview.dm b/code/game/machinery/overview.dm index 89aff04d646..ff027f05508 100644 --- a/code/game/machinery/overview.dm +++ b/code/game/machinery/overview.dm @@ -126,7 +126,7 @@ if(!colour2 && !T.density) var/datum/gas_mixture/environment = T.return_air() - var/turf_total = environment.total_moles() / environment.volume * CELL_VOLUME + var/turf_total = environment.molar_density() * CELL_VOLUME //var/turf_total = T.co2 + T.oxygen + T.poison + T.sl_gas + T.n2 @@ -214,7 +214,7 @@ if("/turf/simulated/floor", "/turf/simulated/floor/engine") var/datum/gas_mixture/environment = T.return_air() - var/turf_total = environment.total_moles() + var/turf_total = environment.molar_density() * CELL_VOLUME var/t1 = turf_total / MOLES_CELLSTANDARD * 175 if(t1<=100) diff --git a/code/game/machinery/portable_turret.dm b/code/game/machinery/portable_turret.dm index cf82900f2e1..e9b835530dd 100644 --- a/code/game/machinery/portable_turret.dm +++ b/code/game/machinery/portable_turret.dm @@ -454,9 +454,9 @@ Status: []
"}, spawn() shootAt(M) // shoot the target, finally if(prob(15)) if(prob(50)) - playsound(get_turf(src), 'sound/effects/turret/move1.wav', 60, 1) + playsound(src, 'sound/effects/turret/move1.wav', 60, 1) else - playsound(get_turf(src), 'sound/effects/turret/move2.wav', 60, 1) + playsound(src, 'sound/effects/turret/move2.wav', 60, 1) else if(secondarytargets.len>0) // if there are no primary targets, go for secondary targets var/mob/t = pick(secondarytargets) @@ -467,9 +467,9 @@ Status: []
"}, shootAt(t) if(prob(15)) if(prob(50)) - playsound(get_turf(src), 'sound/effects/turret/move1.wav', 60, 1) + playsound(src, 'sound/effects/turret/move1.wav', 60, 1) else - playsound(get_turf(src), 'sound/effects/turret/move2.wav', 60, 1) + playsound(src, 'sound/effects/turret/move2.wav', 60, 1) else spawn() popDown() @@ -485,7 +485,7 @@ Status: []
"}, invisibility=0 raising=1 flick("popup",cover) - playsound(get_turf(src), 'sound/effects/turret/open.wav', 60, 1) + playsound(src, 'sound/effects/turret/open.wav', 60, 1) sleep(5) sleep(5) raising=0 @@ -503,7 +503,7 @@ Status: []
"}, layer = OBJ_LAYER raising=1 flick("popdown",cover) - playsound(get_turf(src), 'sound/effects/turret/open.wav', 60, 1) + playsound(src, 'sound/effects/turret/open.wav', 60, 1) sleep(10) raising=0 cover.icon_state="turretCover" @@ -608,7 +608,7 @@ Status: []
"}, use_power(reqpower) // //Shooting Code: - playsound(get_turf(src), installed.fire_sound, 75, 1) + playsound(src, installed.fire_sound, 75, 1) var/obj/item/projectile/A A = new installed.projectile_type(loc) A.original = target @@ -660,7 +660,7 @@ Status: []
"}, return else if(iscrowbar(W) && !anchored) - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 75, 1) + playsound(src, 'sound/items/Crowbar.ogg', 75, 1) to_chat(user, "You dismantle the turret construction.") getFromPool(/obj/item/stack/sheet/metal, loc, 5) qdel(src) @@ -686,7 +686,7 @@ Status: []
"}, if(2) if(iswrench(W)) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1) + playsound(src, 'sound/items/Ratchet.ogg', 100, 1) to_chat(user, "You bolt the metal armor into place.") build_step = 3 return @@ -699,7 +699,7 @@ Status: []
"}, to_chat(user, "You need more fuel to complete this task.") return - playsound(get_turf(src), pick('sound/items/Welder.ogg', 'sound/items/Welder2.ogg'), 50, 1) + playsound(src, pick('sound/items/Welder.ogg', 'sound/items/Welder2.ogg'), 50, 1) if(do_after(user, src, 20)) if(!src || !WT.remove_fuel(5, user)) return @@ -715,14 +715,14 @@ Status: []
"}, if(!user.drop_item(W, src)) to_chat(user, "You can't let go of \the [W]!") return - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 100, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 100, 1) installed = W to_chat(user, "You add \the [W] to the turret.") build_step = 4 return else if(iswrench(W)) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1) + playsound(src, 'sound/items/Ratchet.ogg', 100, 1) to_chat(user, "You remove the turret's metal armor bolts.") build_step = 2 return @@ -732,7 +732,7 @@ Status: []
"}, if(!user.drop_item(W, src)) to_chat(user, "You can't let go of \the [W]!") return - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 100, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 100, 1) build_step = 5 to_chat(user, "You add the prox sensor to the turret.") qdel(W) @@ -742,7 +742,7 @@ Status: []
"}, if(5) if(isscrewdriver(W)) - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 100, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 100, 1) build_step = 6 to_chat(user, "You close the internal access hatch.") return @@ -761,7 +761,7 @@ Status: []
"}, return else if(isscrewdriver(W)) - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 100, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 100, 1) build_step = 5 to_chat(user, "You open the internal access hatch.") return @@ -774,7 +774,7 @@ Status: []
"}, if (WT.get_fuel() < 5) to_chat(user, "You need more fuel to complete this task.") - playsound(get_turf(src), pick('sound/items/Welder.ogg', 'sound/items/Welder2.ogg'), 50, 1) + playsound(src, pick('sound/items/Welder.ogg', 'sound/items/Welder2.ogg'), 50, 1) if(do_after(user, src, 30)) if(!src || !WT.remove_fuel(5, user)) return @@ -790,7 +790,7 @@ Status: []
"}, qdel(src) else if(iscrowbar(W)) - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 75, 1) + playsound(src, 'sound/items/Crowbar.ogg', 75, 1) to_chat(user, "You pry off the turret's exterior armor.") getFromPool(/obj/item/stack/sheet/metal, loc, 2) build_step = 6 diff --git a/code/game/machinery/recharger.dm b/code/game/machinery/recharger.dm index c71cf7e21ea..5af0ad1fe47 100644 --- a/code/game/machinery/recharger.dm +++ b/code/game/machinery/recharger.dm @@ -8,24 +8,46 @@ idle_power_usage = 4 active_power_usage = 250 + ghost_read = 0 // Deactivate ghost touching. ghost_write = 0 var/self_powered = 0 + var/charging_speed_modifier = 1 //The higher this value is, the faster the charging (increases energy used and deposited to gun each process() call, multiplier) + var/efficiency_modifier = 1 // This value is the multiplier of excess power loss, the closer it is to zero, the less energy is wasted, min cap is 50% of usual loss var/obj/item/weapon/charging = null var/appearance_backup = null - machine_flags = WRENCHMOVE | FIXED2WORK + machine_flags = SCREWTOGGLE | WRENCHMOVE | FIXED2WORK | CROWDESTROY /obj/machinery/recharger/New() - ..() + . = ..() + component_parts = newlist( + /obj/item/weapon/circuitboard/recharger, + /obj/item/weapon/stock_parts/scanning_module, + /obj/item/weapon/stock_parts/capacitor, + /obj/item/weapon/stock_parts/capacitor + ) // Fashioned from the cell charger, they both serve a similar purpose + RefreshParts() if(self_powered) use_power = 0 idle_power_usage = 0 active_power_usage = 0 +/obj/machinery/recharger/RefreshParts() + var/T = 0 + for(var/obj/item/weapon/stock_parts/scanning_module/SM in component_parts) // 1x - 0.5x loss multiplier + T += SM.rating + efficiency_modifier = 0.25*(5-T) + T = 0 + for(var/obj/item/weapon/stock_parts/capacitor/C in component_parts) // 1x - 3x charging multiplier + T += C.rating + charging_speed_modifier = round(T/2) // rounds down because fractional speed modifiers can cause problems with weapons that have clearly defined "energy units" such as the lawgiver and the pulse rifle, it is unlikely that someone's not going to muster up two of the same capacitor when modifying the charger + T = 0 + + /obj/machinery/recharger/Destroy() if(charging) charging.appearance = appearance_backup @@ -44,6 +66,9 @@ if(stat & (NOPOWER | BROKEN)) to_chat(user, "[src] isn't connected to a power source.") return 1 + if(panel_open) + to_chat(user, "You can't insert anything into \the [src] while the maintenance panel is open.
") + return 1 if(charging) to_chat(user, "There's \a [charging] already charging inside!") return 1 @@ -71,6 +96,13 @@ update_icon() return 1 +/obj/machinery/recharger/togglePanelOpen(var/obj/toggleitem, mob/user) + if(charging) + to_chat(user, "The maintenance panel is blocked by \the [charging]!") + return 1 + return ..() + + /obj/machinery/recharger/wrenchAnchor(var/mob/user) if(charging) to_chat(user, "Remove the charging item first!") @@ -120,60 +152,69 @@ return if(charging) - if(istype(charging, /obj/item/weapon/gun/energy)) + var/charge_unit + if(istype(charging, /obj/item/weapon/gun/energy)) // Original values: 100e charged, 150e wasted, var/obj/item/weapon/gun/energy/E = charging - if((E.power_supply.charge + 100) < E.power_supply.maxcharge) - E.power_supply.give(100) + charge_unit = 100 * charging_speed_modifier + if((E.power_supply.charge + charge_unit) < E.power_supply.maxcharge) + E.power_supply.give(charge_unit) icon_state = "recharger1" if(!self_powered) - use_power(250) + use_power(charge_unit + 150 * efficiency_modifier * charging_speed_modifier) update_icon() else E.power_supply.charge = E.power_supply.maxcharge update_icon() icon_state = "recharger2" return - else if(istype(charging, /obj/item/energy_magazine))//pulse bullet casings + else if(istype(charging, /obj/item/energy_magazine))//pulse rifle rounds, Original values: 3rnd charged, 250e consumed, let's say 50e per round + 100e waste var/obj/item/energy_magazine/M = charging - if((M.bullets + 3) < M.max_bullets) - M.bullets = min(M.max_bullets,M.bullets+3) + charge_unit = 3 * charging_speed_modifier + if((M.bullets + charge_unit) < M.max_bullets) + M.bullets = min(M.max_bullets,M.bullets+charge_unit) icon_state = "recharger1" if(!self_powered) - use_power(250) + use_power(150 * charging_speed_modifier + 100 * efficiency_modifier * charging_speed_modifier) update_icon() else M.bullets = M.max_bullets update_icon() icon_state = "recharger2" return - else if(istype(charging, /obj/item/ammo_storage/magazine/lawgiver)) + else if(istype(charging, /obj/item/ammo_storage/magazine/lawgiver)) // Original values: lawgiver charges 1/5 of of one ammo type for 200e, 100e + 100e excess sounds palatable var/obj/item/ammo_storage/magazine/lawgiver/L = charging if(!L.isFull()) + var/charged_amount if(L.stuncharge != 100) - L.stuncharge += 20 + charged_amount = 20 * charging_speed_modifier + L.stuncharge = min(L.stuncharge + charged_amount, 100) else if(L.lasercharge != 100) - L.lasercharge += 20 + charged_amount = 20 * charging_speed_modifier + L.lasercharge = min(L.lasercharge + charged_amount, 100) else if(L.rapid_ammo_count != 5) - L.rapid_ammo_count++ + charged_amount = charging_speed_modifier + L.rapid_ammo_count = min(L.rapid_ammo_count + charged_amount, 5) else if(L.flare_ammo_count != 5) - L.flare_ammo_count++ + charged_amount = charging_speed_modifier + L.flare_ammo_count = min(L.flare_ammo_count + charged_amount, 5) else if(L.ricochet_ammo_count != 5) - L.ricochet_ammo_count++ + charged_amount = charging_speed_modifier + L.ricochet_ammo_count = min(L.ricochet_ammo_count + charged_amount, 5) icon_state = "recharger1" if(!self_powered) - use_power(200) + use_power(100 * charging_speed_modifier + 100 * charging_speed_modifier * efficiency_modifier) // could make this more compressed but didn't for better readability update_icon() else update_icon() icon_state = "recharger2" return - else if(istype(charging, /obj/item/weapon/melee/baton)) + else if(istype(charging, /obj/item/weapon/melee/baton)) //25e power loss is so minor that the game shouldn't bother calculating the efficiency of better parts for it var/obj/item/weapon/melee/baton/B = charging if(B.bcell) - if(B.bcell.give(175)) + if(B.bcell.give(175*charging_speed_modifier)) icon_state = "recharger1" if(!self_powered) - use_power(200) + use_power(200*charging_speed_modifier) else icon_state = "recharger2" else @@ -182,10 +223,10 @@ else if(istype(charging, /obj/item/weapon/rcs)) var/obj/item/weapon/rcs/rcs = charging if(rcs.cell) - if(rcs.cell.give(175)) + if(rcs.cell.give(175*charging_speed_modifier)) icon_state = "recharger1" if(!self_powered) - use_power(200) + use_power(200*charging_speed_modifier) else icon_state = "recharger2" else @@ -208,11 +249,15 @@ ..(severity) /obj/machinery/recharger/update_icon() //we have an update_icon() in addition to the stuff in process to make it feel a tiny bit snappier. + if(charging) overlays.len = 0 charging.update_icon() overlays += charging.appearance icon_state = "recharger1" + else if(!anchored) + overlays.len = 0 + icon_state = "recharger4" else overlays.len = 0 icon_state = "recharger0" @@ -225,6 +270,7 @@ icon = 'icons/obj/stationobjs.dmi' icon_state = "wrecharger0" + /obj/machinery/recharger/wallcharger/process() if(stat & (NOPOWER|BROKEN) || !anchored) return diff --git a/code/game/machinery/rechargestation.dm b/code/game/machinery/rechargestation.dm index 6b9c5e120b8..d68b4ee74d3 100644 --- a/code/game/machinery/rechargestation.dm +++ b/code/game/machinery/rechargestation.dm @@ -94,6 +94,7 @@ if(world.timeofday >= upgrade_finished && upgrade_finished != -1) if(istype(upgrading, /obj/item/weapon/cell)) if(occupant:cell) + occupant:cell.updateicon() occupant:cell.forceMove(get_turf(src)) upgrade_holder -= upgrading upgrading:forceMove(occupant) @@ -102,7 +103,7 @@ upgrading = 0 upgrade_finished = -1 to_chat(occupant, "Upgrade completed.") - playsound(get_turf(src), 'sound/machines/ping.ogg', 50, 0) + playsound(src, 'sound/machines/ping.ogg', 50, 0) /obj/machinery/recharge_station/attackby(var/obj/item/W, var/mob/living/user) if(is_type_in_list(W, acceptable_upgradeables)) @@ -133,6 +134,9 @@ var/obj/removed = input(user, "Choose an item to remove.",upgrade_holder[1]) as null|anything in upgrade_holder if(!removed || upgrading) return + var/obj/item/weapon/cell/rcell = removed + if(istype(rcell)) + rcell.updateicon() user.put_in_hands(removed) if(removed.loc == src) removed.forceMove(get_turf(src)) diff --git a/code/game/machinery/requests_console.dm b/code/game/machinery/requests_console.dm index 4c6a124ae7d..c3be7a89613 100644 --- a/code/game/machinery/requests_console.dm +++ b/code/game/machinery/requests_console.dm @@ -255,6 +255,7 @@ var/list/obj/machinery/requests_console/allConsoles = list() else priority = -1 else + to_chat(usr, "Invalid characters found in the text.") dpt = ""; msgVerified = "" msgStamped = "" @@ -271,6 +272,7 @@ var/list/obj/machinery/requests_console/allConsoles = list() else priority = -1 else + to_chat(usr, "Invalid characters found in the text.") message = "" announceAuth = 0 screen = 0 @@ -442,7 +444,7 @@ var/list/obj/machinery/requests_console/allConsoles = list() to_chat(user, "You can't do much with that.") if(iswrench(O) && open && !departmentType) user.visible_message("[user] disassembles the [src]!", "You disassemble the [src]") - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1) + playsound(src, 'sound/items/Ratchet.ogg', 100, 1) new /obj/item/stack/sheet/metal (src.loc,2) qdel(src) return diff --git a/code/game/machinery/shieldgen.dm b/code/game/machinery/shieldgen.dm index 7407918dd0e..d911084f914 100644 --- a/code/game/machinery/shieldgen.dm +++ b/code/game/machinery/shieldgen.dm @@ -54,7 +54,7 @@ src.health -= aforce //Play a fitting sound - playsound(get_turf(src), 'sound/effects/EMPulse.ogg', 75, 1) + playsound(src, 'sound/effects/EMPulse.ogg', 75, 1) if (src.health <= 0) @@ -124,7 +124,7 @@ src.health -= tforce //This seemed to be the best sound for hitting a force field. - playsound(get_turf(src), 'sound/effects/EMPulse.ogg', 100, 1) + playsound(src, 'sound/effects/EMPulse.ogg', 100, 1) //Handle the destruction of the shield if (src.health <= 0) diff --git a/code/game/machinery/station_map.dm b/code/game/machinery/station_map.dm index cd426af070d..60008b616de 100644 --- a/code/game/machinery/station_map.dm +++ b/code/game/machinery/station_map.dm @@ -54,7 +54,7 @@ var/list/station_holomaps = list() if(do_after(user, src, 40)) user.visible_message( "[user] detaches \the [src] from the wall.", "You detach \the [src] from the wall.") - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) + playsound(src, 'sound/items/Crowbar.ogg', 50, 1) new /obj/item/mounted/frame/station_map(src.loc) for(var/obj/I in src) diff --git a/code/game/machinery/status_display.dm b/code/game/machinery/status_display.dm index dbb4ab70f90..4e60f1a1ca0 100644 --- a/code/game/machinery/status_display.dm +++ b/code/game/machinery/status_display.dm @@ -428,7 +428,7 @@ var/global/list/status_display_images = list( #undef MODE_BSOD #undef CHARS_PER_LINE -#undef FOND_SIZE +#undef FONT_SIZE #undef FONT_COLOR #undef FONT_STYLE #undef SCROLL_SPEED diff --git a/code/game/machinery/suit_dispenser.dm b/code/game/machinery/suit_dispenser.dm index 88b303e7f59..2eae8456aed 100644 --- a/code/game/machinery/suit_dispenser.dm +++ b/code/game/machinery/suit_dispenser.dm @@ -2,8 +2,21 @@ // SUIT DISPENSER UNIT /////////////// ////////////////////////////////////// +#define SD_BUSY 1 // the dispenser is busy. +#define SD_ONESUIT 2 // only one type of suit comes out of this dispenser. +#define SD_NOGREED 4 // no-one is allowed more than one suit from this TYPE of dispenser unless emagged +#define SD_UNLIMITED 8 // will not deplete amount when armour is taken + var/list/dispenser_presets = list() +/datum/suit + var/name = "suit" + var/list/to_spawn = list() + var/amount = 0 + +/datum/suit/custom + name = "custom" + /obj/machinery/suit_dispenser name = "Suit Dispenser" desc = "An industrial U-Tak-It Dispenser unit designed to fetch all kinds of space suits.." @@ -11,111 +24,157 @@ var/list/dispenser_presets = list() icon_state = "suitdispenser" anchored = 1 density = 1 + var/list/suits = list() // put your suit datums here! + var/datum/suit/one_suit + var/global/list/suit_distributed_to = list() + var/dispenser_flags = SD_NOGREED|SD_UNLIMITED + machine_flags = EMAGGABLE + +/obj/machinery/suit_dispenser/New() + if(!suit_distributed_to["[type]"] && (dispenser_flags & SD_NOGREED)) + suit_distributed_to["[type]"] = list() + var/list/real_suits_list = list() + for(var/suit in suits) + var/datum/suit/S = new suit + real_suits_list[S.name] = S + if(one_suit) + one_suit = new one_suit + suits = real_suits_list + ..() + +/obj/machinery/suit_dispenser/attack_hand(var/mob/living/carbon/human/user) + if(!can_use(user)) + return + dispenser_flags |= SD_BUSY + if(!(dispenser_flags & SD_ONESUIT)) + var/suit_list = get_suit_list(user) + suit_list["CANCEL"] = "CANCEL" + var/choice = input("Choose your suit specialisation.", "Suit Dispenser") in suit_list + if(choice == "CANCEL") + return + dispense(suit_list[choice],user) + else + dispense(one_suit,user) +/obj/machinery/suit_dispenser/proc/can_use(var/mob/living/carbon/human/user) + var/list/used_by = suit_distributed_to["[type]"] + if(!istype(user)) + to_chat(user,"You can't use this!") + return 0 + if((dispenser_flags & SD_BUSY)) + to_chat(user,"Someone else is using this!") + return 0 + if((dispenser_flags & SD_ONESUIT) && !one_suit.amount) + to_chat(user,"There's nothing in here!") + return 0 + if ((dispenser_flags & SD_NOGREED) && (user in used_by) && !emagged) + to_chat(user,"You've already picked up your suit!") + playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0) + return 0 + else if(emagged) + say("!'^&YouVE alreaDY pIC&$!Ked UP yOU%r Su^!it.") + playsound(src, 'sound/machines/buzz-sigh.ogg', 100, 0) + return 1 + return 1 + +/obj/machinery/suit_dispenser/proc/get_suit_list(var/mob/living/carbon/human/user) + return suits + +/obj/machinery/suit_dispenser/proc/dispense(var/datum/suit/S,var/mob/living/carbon/human/user,var/greet=TRUE) + if(!S.amount && !(dispenser_flags & SD_UNLIMITED)) + to_chat(user,"There are no more [S.name] suits left!") + dispenser_flags &= ~SD_BUSY + return 1 + else if(!(dispenser_flags & SD_UNLIMITED)) + S.amount-- + if((dispenser_flags & SD_NOGREED) && !emagged) + suit_distributed_to["[type]"] |= user + flick("suitdispenser-flick",src) + dispenser_flags |= SD_BUSY + sleep(17) + dispenser_flags &= ~SD_BUSY + + var/turf/T = get_turf(src) + if(!(S && T)) // in case we got destroyed while we slept + return 1 + for(var/O in S.to_spawn) + new O(T) + if(emagged) + emagged = FALSE + if(greet && user && !user.stat) // in case we got destroyed while we slept + to_chat(user,"[S.name] specialisation processed. Have a good day.") + + +/obj/machinery/suit_dispenser/emag(var/mob/user) + if(!emagged) + emagged = TRUE + if(user) + user.visible_message("\The [user] slides a weird looking ID into \the [src], and sparks come flying out!","You temporarily short the safety mechanisms.") + playsound(src, pick(spark_sound), 75, 1) + spark(src,4) + +/obj/machinery/suit_dispenser/proc/promptfornum(var/mob/user) + var/num = input(user,"How many supplies would you like to add? (Set to -1 for infinite)","Suit Dispenser", null) as num|null + if(num == -1) + dispenser_flags |= SD_UNLIMITED + else return num + +////////////////////////////// ERT SUIT DISPENSERS /////////////////////////// + + +/datum/suit/ert/security + name = "Security" + to_spawn = list(/obj/item/clothing/suit/space/ert/security,/obj/item/clothing/head/helmet/space/ert/security) + +/datum/suit/ert/medical + name = "Medical" + to_spawn = list(/obj/item/clothing/suit/space/ert/medical,/obj/item/clothing/head/helmet/space/ert/medical) + +/datum/suit/ert/engineer + name = "Engineering" + to_spawn = list(/obj/item/clothing/suit/space/ert/engineer,/obj/item/clothing/head/helmet/space/ert/engineer) + +/datum/suit/ert/commander + name = "Commander" + to_spawn = list(/obj/item/clothing/suit/space/ert/commander,/obj/item/clothing/head/helmet/space/ert/commander) /obj/machinery/suit_dispenser/ert desc = "An industrial U-Tak-It Dispenser unit designed to fetch all kinds of space suits. This one distribributes Emergency Responder space suits." + suits = list(/datum/suit/ert/security,/datum/suit/ert/medical,/datum/suit/ert/engineer) -/obj/machinery/suit_dispenser/ert/attack_hand(var/mob/user) +/obj/machinery/suit_dispenser/ert/can_use(var/mob/living/carbon/human/user) + if(!..()) + return if(sentStrikeTeams(TEAM_ERT)) - var/datum/striketeam/ert/team = sent_strike_teams[TEAM_ERT] - if (user in response_team_members) - if (user in distributed_ert_suits) - to_chat(user,"You've already picked up your suit.") - else - if (user.key == team.leader_key) - to_chat(user,"Identified as [user.real_name]. Here is your suit commander. Have a good day.") - - flick("suitdispenser-flick",src) - - sleep(17) - - if (user in distributed_ert_suits) - return - - distributed_ert_suits |= user - - var/turf/T = get_turf(src) - - new /obj/item/clothing/suit/space/ert/commander(T) - new /obj/item/clothing/head/helmet/space/ert/commander(T) - - else - to_chat(user,"Identified as [user.real_name]. Please choose your suit specialization.") - - var/list/suit_list = list( - "Security", - "Medical", - "Engineer", - "CANCEL" - ) - - var/choice = input("Choose your suit specialization.", "Suit Dispenser") in suit_list - - if(choice == "CANCEL") - return - - flick("suitdispenser-flick",src) - - sleep(17) - - if (user in distributed_ert_suits) - return - - distributed_ert_suits |= user - - var/turf/T = get_turf(src) - - switch(choice) - if("Security") - new /obj/item/clothing/suit/space/ert/security(T) - new /obj/item/clothing/head/helmet/space/ert/security(T) - to_chat(user,"Security specialization processed. Have a good day.") - if("Medical") - new /obj/item/clothing/suit/space/ert/medical(T) - new /obj/item/clothing/head/helmet/space/ert/medical(T) - to_chat(user,"Medical specialization processed. Have a good day.") - if("Engineer") - new /obj/item/clothing/suit/space/ert/engineer(T) - new /obj/item/clothing/head/helmet/space/ert/engineer(T) - to_chat(user,"Engineer specialization processed. Have a good day.") - + if(user in response_team_members) + return 1 else to_chat(user,"Access Denied. You aren't part of the Emergency Response Team.") else to_chat(user,"Access Denied. No Emergency Response Team has been dispatched yet.") +/obj/machinery/suit_dispenser/ert/attack_hand(var/mob/living/carbon/human/user) + var/list/used_by = suit_distributed_to["[type]"] + var/datum/striketeam/ert/team = sent_strike_teams[TEAM_ERT] + if (user.key == team.leader_key && !(user in used_by)) + if(!can_use(user)) + return + to_chat(user,"Identified as [user.real_name]. Have a good day, Commander!") + dispense(new /datum/suit/ert/commander,user,greet=FALSE) + else ..() /obj/machinery/suit_dispenser/striketeam icon_state = "suitdispenser-empty" - var/preset = null - var/used = 0 + dispenser_flags = SD_ONESUIT -/obj/machinery/suit_dispenser/striketeam/attack_hand(var/mob/user) - if(!preset) +/obj/machinery/suit_dispenser/striketeam/can_use(var/mob/living/carbon/human/user) + if(!..()) + return + if(!one_suit) to_chat(user,"Error. No presets have been set.") return - - if(used) - to_chat(user,"This dispenser must be reloaded by authorities in charge before you can use it again.") - return - - used = 1 - - var/list/items_to_spawn = dispenser_presets[preset] - - icon_state = "suitdispenser-open" - flick("suitdispenser-once",src) - - sleep(17) - - var/turf/T = get_turf(src) - - for(var/i = 1 to items_to_spawn.len) - var/spawntype = items_to_spawn[i] - new spawntype(T) - + return 1 /obj/machinery/suit_dispenser/striketeam/attack_ghost(var/mob/user) if(isAdminGhost(user)) @@ -124,7 +183,7 @@ var/list/dispenser_presets = list() "Choose a Preset", ) - if (used) + if (one_suit && !one_suit.amount) choices |= "Resupply" choices |= "CANCEL" @@ -135,27 +194,116 @@ var/list/dispenser_presets = list() if("CANCEL") return if("Define Preset from items on top") - var/list/items_on_top = list() + var/datum/suit/custom/preset = new for (var/obj/item/I in get_turf(src)) - items_on_top += I.type - if (items_on_top.len <= 0) + preset.to_spawn += I.type + if (!preset.to_spawn.len) to_chat(user,"Error. No items on top of the dispenser. Place items on top of the dispenser to define them as presets.") return else - var/preset_name = input(user,"[items_on_top.len] items found. Name your Preset","Suit Dispenser", null) as text|null + var/preset_name = input(user,"[preset.to_spawn.len] items found. Name your Preset","Suit Dispenser", null) as text|null if (!preset_name) + qdel(preset) return - dispenser_presets[preset_name] = items_on_top - if("Choose a Preset") - if (dispenser_presets.len <= 0) - to_chat(user,"Error. No presets have been set. Place items on top of the dispenser to define them as presets.") - return - var/no_preset = !preset - preset = input(user,"Choose a Preset.", "Suit Dispenser") in dispenser_presets - if (preset && no_preset) + preset.name = preset_name + dispenser_presets[preset_name] = preset + one_suit = preset icon_state = "suitdispenser" flick("suitdispenser-fill",src) + one_suit.amount = promptfornum(user) + + if("Choose a Preset") + if (!dispenser_presets.len) + to_chat(user,"Error. No presets have been set. Place items on top of the dispenser to define them as presets.") + return + var/datum/suit/custom/preset = input(user,"Choose a Preset.", "Suit Dispenser") in dispenser_presets + if (preset && !one_suit) + icon_state = "suitdispenser" + flick("suitdispenser-fill",src) + one_suit = new /datum/suit/custom + one_suit.name = preset.name + one_suit.to_spawn = preset.to_spawn + one_suit.amount = promptfornum(user) + + if("Resupply") - used = 0 + one_suit.amount = promptfornum(user) icon_state = "suitdispenser" flick("suitdispenser-resupply",src) + + +////////////////// DORF FORT DISPENSER ////////////////// +// do NOT spawn this on the main map or I will SCREAM // + +/datum/suit/dorf/standard + name = "Standard" + to_spawn = list(/obj/item/clothing/head/helmet/space,/obj/item/clothing/suit/space) + +/datum/suit/dorf/security + name = "Security" + to_spawn = list(/obj/item/clothing/head/helmet/space/rig/security,/obj/item/clothing/suit/space/rig/security) + +/datum/suit/dorf/engineering + name = "Engineering" + to_spawn = list(/obj/item/clothing/head/helmet/space/rig,/obj/item/clothing/suit/space/rig) + +/datum/suit/dorf/medical + name = "Medical" + to_spawn = list(/obj/item/clothing/head/helmet/space/rig/medical,/obj/item/clothing/suit/space/rig/medical) + +/datum/suit/dorf/atmos + name = "Atmospherics Technician" + to_spawn = list(/obj/item/clothing/head/helmet/space/rig/atmos,/obj/item/clothing/suit/space/rig/atmos) + +/datum/suit/dorf/paramedic + name = "Paramedic" + to_spawn = list(/obj/item/clothing/head/helmet/space/paramedic,/obj/item/clothing/suit/space/paramedic) + +/datum/suit/dorf/mining + name = "Mining" + to_spawn = list(/obj/item/clothing/suit/space/rig/mining, /obj/item/clothing/head/helmet/space/rig/mining) + +/*/datum/suit/dorf/head + amount = 1 + +/datum/suit/dorf/head/captain + name = "Captain" + to_spawn = (/obj/item/clothing/suit/armor/captain,/obj/item/clothing/head/helmet/space/capspace) + +/datum/suit/dorf/head/chiefengie + name = "Chief Engineer" + to_spawn = (/obj/item/clothing/suit/space/rig/elite,/obj/item/clothing/head/helmet/space/rig/elite,/obj/item/clothing/shoes/magboots/elite)*/ + + +/obj/machinery/suit_dispenser/dorf + desc = "An industrial U-Tak-It Dispenser unit designed to fetch all kinds of space suits. This one is specialised towards asteroid reclamation teams." + suits = list(/datum/suit/dorf/standard,/datum/suit/dorf/security,/datum/suit/dorf/engineering,/datum/suit/dorf/medical,/datum/suit/dorf/atmos,/datum/suit/dorf/paramedic) + +/obj/machinery/suit_dispenser/dorf/get_suit_list(var/mob/living/carbon/human/user) + if(emagged) + return suits + var/list/suit_list = list() + suit_list["Standard"] = suits["Standard"] + var/obj/item/weapon/card/id/card = user.get_id_card() + if(!card) + return suit_list + for(var/job in card.access) + switch(job) + if(access_brig) + suit_list["Security"] = suits["Security"] + if(access_medical) + suit_list["Medical"] = suits["Medical"] + if(access_mining) + suit_list["Mining"] = suits["Mining"] + if(access_paramedic) + suit_list["Paramedic"] = suits["Paramedic"] + if(access_atmospherics) + suit_list["Atmospherics Technician"] = suits["Atmospherics Technician"] + if(access_engine) + suit_list["Engineering"] = suits["Engineering"] + return suit_list + +/obj/machinery/suit_dispenser/standard + desc = "An industrial U-Tak-It Dispenser unit designed to fetch a specific mass produced suit." + dispenser_flags = SD_ONESUIT|SD_NOGREED|SD_UNLIMITED + one_suit = /datum/suit/dorf/standard \ No newline at end of file diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm index 38dcd1c8259..ca1a754014a 100644 --- a/code/game/machinery/suit_storage_unit.dm +++ b/code/game/machinery/suit_storage_unit.dm @@ -311,7 +311,7 @@ protected = 1 if(!protected) - playsound(get_turf(src), "sparks", 75, 1, -1) + playsound(src, "sparks", 75, 1, -1) to_chat(user, "You try to touch the controls but you get zapped. There must be a short circuit somewhere.") return*/ else //welp, the guy is protected, we can continue @@ -337,7 +337,7 @@ protected = 1 if(!protected) - playsound(get_turf(src), "sparks", 75, 1, -1) + playsound(src, "sparks", 75, 1, -1) to_chat(user, "You try to touch the controls but you get zapped. There must be a short circuit somewhere.") return*/ else @@ -579,7 +579,7 @@ stat &= !BROKEN to_chat(user, "You repair the blown out electronics in the suit storage unit.") if((stat & NOPOWER) && iscrowbar(I) && !islocked) - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) to_chat(user, "You begin prying the equipment out of the suit storage unit") if(do_after(user, src,20)) dump_everything() diff --git a/code/game/machinery/telecomms/logbrowser.dm b/code/game/machinery/telecomms/logbrowser.dm index 5fae300c11e..5391781fc0b 100644 --- a/code/game/machinery/telecomms/logbrowser.dm +++ b/code/game/machinery/telecomms/logbrowser.dm @@ -233,7 +233,7 @@ /obj/machinery/computer/telecomms/server/emag(mob/user) if(!emagged) - playsound(get_turf(src), 'sound/effects/sparks4.ogg', 75, 1) + playsound(src, 'sound/effects/sparks4.ogg', 75, 1) emagged = 1 if(user) to_chat(user, "You you disable the security protocols") diff --git a/code/game/machinery/telecomms/machine_interactions.dm b/code/game/machinery/telecomms/machine_interactions.dm index 22b911fc334..ddbb11766f8 100644 --- a/code/game/machinery/telecomms/machine_interactions.dm +++ b/code/game/machinery/telecomms/machine_interactions.dm @@ -28,7 +28,7 @@ if (!S.remove_fuel(2, user)) to_chat(user, "You need more fuel.") return - playsound(get_turf(user), 'sound/items/Welder.ogg', 100, 1) + playsound(user, 'sound/items/Welder.ogg', 100, 1) integrity = TELECOMMS_MAX_INTEGRITY to_chat(user, "You repair the damaged internals of \the [src].") updateUsrDialog() @@ -224,7 +224,7 @@ var/obj/item/device/multitool/P = get_multitool(usr) if(!istype(P)) - testing("get_multitool returned [P].") +// testing("get_multitool returned [P].") return if(href_list["input"]) diff --git a/code/game/machinery/telecomms/multicaster.dm b/code/game/machinery/telecomms/multicaster.dm new file mode 100644 index 00000000000..702253bcd71 --- /dev/null +++ b/code/game/machinery/telecomms/multicaster.dm @@ -0,0 +1,88 @@ +var/list/pda_multicasters = list() + +/obj/machinery/pda_multicaster + name = "\improper PDA multicaster" + desc = "Duplicates messages and sends copies to departments." + icon = 'icons/obj/machines/telecomms.dmi' + icon_state = "pda_server-on" + density = 1 + anchored = 1 + use_power = 1 + idle_power_usage = 750 + var/obj/item/device/pda/camo/CAMO + var/on = TRUE + +/obj/machinery/pda_multicaster/New() + ..() + CAMO = new(src) + pda_multicasters.Add(src) + +/obj/machinery/pda_multicaster/prebuilt/New() + ..() + + component_parts = newlist( + /obj/item/weapon/circuitboard/pda_multicaster, + /obj/item/weapon/stock_parts/subspace/filter, + /obj/item/weapon/stock_parts/manipulator + ) + + RefreshParts() + +/obj/machinery/pda_multicaster/Destroy() + pda_multicasters.Remove(src) + if(CAMO) + qdel(CAMO) + CAMO = null + ..() + +/obj/machinery/pda_multicaster/update_icon() + if(stat & (BROKEN|NOPOWER|EMPED)) + icon_state = "pda_server-nopower" + else + icon_state = "pda_server-[on ? "on" : "off"]" + +/obj/machinery/pda_multicaster/attack_hand(mob/user) + if(user.incapacitated() && !isAdminGhost(user)) + return + toggle_power(user) + +/obj/machinery/pda_multicaster/proc/toggle_power(mob/user) + on = !on + visible_message("\the [user] turns \the [src] [on ? "on" : "off"].") + update_icon() + +/obj/machinery/pda_multicaster/proc/check_status() + return !(stat&(BROKEN|NOPOWER|EMPED))&&on + +/obj/machinery/pda_multicaster/proc/update_PDAs(var/turn_off) + for(var/obj/item/device/pda/pda in contents) + pda.toff = turn_off + +/obj/machinery/pda_multicaster/proc/multicast(var/target,var/obj/item/device/pda/sender,var/mob/living/U,var/message) + var/list/redirection_list = list( + "security" = list(/obj/item/device/pda/warden,/obj/item/device/pda/detective,/obj/item/device/pda/security,/obj/item/device/pda/heads/hos), + "engineering" = list(/obj/item/device/pda/engineering,/obj/item/device/pda/atmos,/obj/item/device/pda/heads/ce), + "medical" = list(/obj/item/device/pda/medical,/obj/item/device/pda/viro,/obj/item/device/pda/chemist,/obj/item/device/pda/geneticist,/obj/item/device/pda/heads/cmo), + "research" = list(/obj/item/device/pda/toxins,/obj/item/device/pda/roboticist,/obj/item/device/pda/mechanic,/obj/item/device/pda/heads/rd), + "cargo" = list(/obj/item/device/pda/cargo,/obj/item/device/pda/shaftminer,/obj/item/device/pda/quartermaster), + "service" = list(/obj/item/device/pda/botanist,/obj/item/device/pda/chef,/obj/item/device/pda/bar) + ) + + var/list/available_pdas = CAMO.available_pdas() //Let's not recalculate this every time. + for(var/element in available_pdas) + var/obj/item/device/pda/P = available_pdas[element] + if(is_type_in_list(P,redirection_list[target])) + CAMO.ownjob = "[sender.owner]" + CAMO.reply = sender + CAMO.create_message(U,P,message) + +/obj/item/device/pda/camo + name = "Centralized Autonomous Messaging Operator" + owner = "CAMO" + ownjob = "CAMO" + detonate = 0 + hidden = 1 + +/obj/item/device/pda/camo/create_message(var/mob/living/U,var/obj/item/device/pda/P,var/multicast_message = null) + ..() + last_text = 0 //CAMO can text as much as it pleases diff --git a/code/game/machinery/telecomms/telemonitor.dm b/code/game/machinery/telecomms/telemonitor.dm index 98d14d4a363..e248050f61e 100644 --- a/code/game/machinery/telecomms/telemonitor.dm +++ b/code/game/machinery/telecomms/telemonitor.dm @@ -211,7 +211,7 @@ /obj/machinery/computer/telecomms/monitor/emag(mob/user) if(!emagged) - playsound(get_turf(src), 'sound/effects/sparks4.ogg', 75, 1) + playsound(src, 'sound/effects/sparks4.ogg', 75, 1) emagged = 1 if(user) to_chat(user, "You you disable the security protocols") diff --git a/code/game/machinery/telecomms/traffic_control.dm b/code/game/machinery/telecomms/traffic_control.dm index fe56ceaecbc..49280c46a71 100644 --- a/code/game/machinery/telecomms/traffic_control.dm +++ b/code/game/machinery/telecomms/traffic_control.dm @@ -280,7 +280,7 @@ /obj/machinery/computer/telecomms/emag(mob/user) if(!emagged) - playsound(get_turf(src), 'sound/effects/sparks4.ogg', 75, 1) + playsound(src, 'sound/effects/sparks4.ogg', 75, 1) emagged = 1 if(user) to_chat(user, "You you disable the security protocols") diff --git a/code/game/machinery/transformer.dm b/code/game/machinery/transformer.dm index 32573ae86de..a774e978190 100644 --- a/code/game/machinery/transformer.dm +++ b/code/game/machinery/transformer.dm @@ -65,14 +65,14 @@ return if(!transform_dead && H.stat == DEAD) - playsound(get_turf(src), 'sound/machines/buzz-sigh.ogg', 50, 0) + playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0) return if(jobban_isbanned(H, "Cyborg")) src.visible_message("\The [src.name] throws an exception. Lifeform not compatible with factory.") return - playsound(get_turf(src), 'sound/items/Welder.ogg', 50, 1) + playsound(src, 'sound/items/Welder.ogg', 50, 1) H.emote("scream",,, 1) // It is painful H.adjustBruteLoss(max(0, 80 - H.getBruteLoss())) // Hurt the human, don't try to kill them though. H.handle_regular_hud_updates() // Make sure they see the pain. @@ -113,7 +113,7 @@ R.updatename() spawn(50) - playsound(get_turf(src), 'sound/machines/ding.ogg', 50, 0) + playsound(src, 'sound/machines/ding.ogg', 50, 0) if(R) R.SetKnockdown(0) @@ -129,7 +129,7 @@ if(cooldown_state!=old_cooldown_state) update_icon() if(!cooldown_state) - playsound(get_turf(src), 'sound/machines/ping.ogg', 50, 0) + playsound(src, 'sound/machines/ping.ogg', 50, 0) /obj/machinery/transformer/conveyor/New() ..() diff --git a/code/game/machinery/turrets.dm b/code/game/machinery/turrets.dm index 9425fcbbbf7..9226e19bf3d 100644 --- a/code/game/machinery/turrets.dm +++ b/code/game/machinery/turrets.dm @@ -179,9 +179,9 @@ if(prob(15)) if(prob(50)) - playsound(get_turf(src), 'sound/effects/turret/move1.wav', 60, 1) + playsound(src, 'sound/effects/turret/move1.wav', 60, 1) else - playsound(get_turf(src), 'sound/effects/turret/move2.wav', 60, 1) + playsound(src, 'sound/effects/turret/move2.wav', 60, 1) else if(!isPopping())//else, pop down if(!isDown()) popDown() @@ -244,7 +244,7 @@ if ((!isPopping()) || src.popping==-1) invisibility = 0 popping = 1 - playsound(get_turf(src), 'sound/effects/turret/open.wav', 60, 1) + playsound(src, 'sound/effects/turret/open.wav', 60, 1) if (src.cover!=null) flick("popup", src.cover) src.cover.icon_state = "openTurretCover" @@ -255,7 +255,7 @@ /obj/machinery/turret/proc/popDown() if ((!isPopping()) || src.popping==1) popping = -1 - playsound(get_turf(src), 'sound/effects/turret/open.wav', 60, 1) + playsound(src, 'sound/effects/turret/open.wav', 60, 1) if (src.cover!=null) flick("popdown", src.cover) src.cover.icon_state = "turretCover" @@ -279,7 +279,7 @@ user.delayNextAttack(10) if(..()) return 1 - playsound(get_turf(src), 'sound/weapons/smash.ogg', 60, 1) + playsound(src, 'sound/weapons/smash.ogg', 60, 1) spark(src, 5, FALSE) src.health -= W.force * 0.5 visible_message("[user] attacked \the [src] with \the [W]!") @@ -433,7 +433,7 @@ /obj/machinery/turret/attack_alien(mob/living/carbon/alien/humanoid/M as mob) if(!(stat & BROKEN)) M.do_attack_animation(src, M) - playsound(get_turf(src), 'sound/weapons/slash.ogg', 25, 1, -1) + playsound(src, 'sound/weapons/slash.ogg', 25, 1, -1) visible_message("[] has slashed at []!", M, src) src.health -= 15 if (src.health <= 0) diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm index e4c3e9cbc7a..271198d9718 100644 --- a/code/game/machinery/vending.dm +++ b/code/game/machinery/vending.dm @@ -10,12 +10,26 @@ var/global/num_vending_terminals = 1 var/product_path = null var/original_amount = 0 var/amount = 0 + var/stack_amount = 0 //only used when we're dealing with /obj/item/stack var/price = 0 var/display_color = "blue" var/category = CAT_NORMAL//available by default, contraband, or premium (requires a coin) var/subcategory = null var/mini_icon = null +//this proc is only used when an item is inserted into a custom vending machine. +/datum/data/vending_product/proc/custom_entry(var/obj/item/item) + if(istype(item, /obj/item/stack)) + var/obj/item/stack/S = item + stack_amount = S.amount + product_name = "A stack of [stack_amount] [item.name]" + else + product_name = item.name + mini_icon = costly_bicon(item) + display_color = pick("red", "blue", "green") + product_path = item + amount += 1 + /* TODO: Add this to deconstruction for vending machines /obj/item/compressed_vend name = "compressed sale cartridge" @@ -46,7 +60,10 @@ var/global/num_vending_terminals = 1 var/ads_chance = 50 // Chance of an ad appearing on screen var/datum/data/vending_product/currently_vending = null // A /datum/data/vending_product instance of what we're paying for right now. // To be filled out at compile time - var/list/accepted_coins = list() // Accepted coins by the machine. + var/list/accepted_coins = list( + /obj/item/weapon/coin, + /obj/item/weapon/reagent_containers/food/snacks/chococoin + ) // Accepted coins by the machine. var/list/products = list() // For each, use the following pattern: var/list/contraband = list() // list(/type/path = amount,/type/path2 = amount2) @@ -85,9 +102,12 @@ var/global/num_vending_terminals = 1 var/machine_id = "#" - machine_flags = SCREWTOGGLE | WRENCHMOVE | FIXED2WORK | CROWDESTROY | EJECTNOTDEL | PURCHASER | WIREJACK | SECUREDPANEL + machine_flags = SCREWTOGGLE | WRENCHMOVE | FIXED2WORK | CROWDESTROY | EJECTNOTDEL | PURCHASER | WIREJACK - var/account_first_linked = 0 + var/account_first_linked = 1 + var/inserting_mode = FALSE // insert items directly into the machine (used for custom vending machines) + var/is_custom_machine = FALSE // true if this vendor supports editing the prices + var/edit_mode = FALSE // Used for editing prices var/is_being_filled = FALSE // `in_use` from /obj is already used for tracking users of this machine's UI /obj/machinery/vending/cultify() @@ -101,11 +121,6 @@ var/global/num_vending_terminals = 1 overlays_vending[1] = "[icon_state]-panel" - accepted_coins = list( - /obj/item/weapon/coin, - /obj/item/weapon/reagent_containers/food/snacks/chococoin - ) - component_parts = newlist(\ /obj/item/weapon/circuitboard/vendomat,\ /obj/item/weapon/stock_parts/matter_bin,\ @@ -132,13 +147,20 @@ var/global/num_vending_terminals = 1 return /obj/machinery/vending/initialize() - ..() + build_inventories() + link_to_account() + +/obj/machinery/vending/proc/build_inventories() product_records = new/list() build_inventory(products) build_inventory(contraband, 1) build_inventory(premium, 0, 1) build_inventory(vouched, 0, 0, 1) +/obj/machinery/vending/proc/link_to_account() + reconnect_database() + linked_account = department_accounts["Cargo"] + /obj/machinery/vending/RefreshParts() var/manipcount = 0 for(var/obj/item/weapon/stock_parts/SP in component_parts) @@ -206,7 +228,7 @@ var/global/num_vending_terminals = 1 newmachine.product_records = P.product_records newmachine.hidden_records = P.hidden_records newmachine.coin_records = P.coin_records - newmachine.initialize() + newmachine.build_inventories() qdel(P) if(user.machine==src) newmachine.attack_hand(user) @@ -230,7 +252,7 @@ var/global/num_vending_terminals = 1 if(do_after_many(user, list(src, P), 3 SECONDS)) to_chat(user, "[bicon(src)] You finish refilling the vending machine.") playsound(src, 'sound/machines/hiss.ogg', 50, 0, 0) - if(check_for_custom_vendor()) + if(is_custom_machine) custom_refill(P, user) else normal_refill(P, user) @@ -241,16 +263,6 @@ var/global/num_vending_terminals = 1 else to_chat(user, "This recharge pack isn't meant for this kind of vending machines.") -/obj/machinery/vending/proc/check_for_custom_vendor() - //We check if there's an in-game object instead of a typepath inside the vending machine. - for(var/item in products) //We only support the product list for the moment. This means no custom premium/contraband products - if(!ispath(item)) - return TRUE - if(!products.len) - return TRUE - - return FALSE - /obj/machinery/vending/proc/normal_refill(obj/structure/vendomatpack/P, mob/user) for (var/datum/data/vending_product/D in product_records) D.amount = D.original_amount @@ -275,7 +287,7 @@ var/global/num_vending_terminals = 1 I.forceMove(src) products += P.stock product_records += P.product_records - initialize() + build_inventories() getFromPool(/obj/item/stack/sheet/cardboard, P.loc, 4) qdel(P) @@ -326,9 +338,7 @@ var/global/num_vending_terminals = 1 R.original_amount = amount R.price = price R.display_color = pick("red", "blue", "green") - var/is_custom = FALSE - if(check_for_custom_vendor()) - is_custom = TRUE + if(is_custom_machine) var/obj/O = R.product_path R.price = O.price R.product_name = "[O.name]" @@ -347,7 +357,7 @@ var/global/num_vending_terminals = 1 product_records.Add(R) var/obj/item/initializer = typepath - if(!is_custom) + if(!is_custom_machine) R.product_name = initial(initializer.name) R.subcategory = initial(initializer.vending_cat) @@ -365,12 +375,12 @@ var/global/num_vending_terminals = 1 // to_chat(world, "Added: [R.product_name]] - [R.amount] - [R.product_path]") /obj/machinery/vending/emag(mob/user) - if(!emagged) + if(!emagged || !extended_inventory || scan_id) emagged = 1 - if(user) - to_chat(user, "You short out the product lock on \the [src]") + extended_inventory = 1 + scan_id = 0 return 1 - return -1 //Fucking gross + return 0 //Fucking gross /obj/machinery/vending/npc_tamper_act(mob/living/L) if(!panel_open) @@ -413,14 +423,14 @@ var/global/num_vending_terminals = 1 return 1 /obj/machinery/vending/attackby(obj/item/W, mob/user) - if(stat & (BROKEN)) + if(stat & (BROKEN) && !iswrench(W)) if(istype(W, /obj/item/stack/sheet/glass/rglass)) var/obj/item/stack/sheet/glass/rglass/G = W to_chat(user, "You replace the broken glass.") G.use(1) stat &= ~BROKEN src.health = 100 - src.update_vicon() + power_change() getFromPool(/obj/item/weapon/shard, loc) else to_chat(user, "The glass in \the [src] is broken! Fix it first.") @@ -482,36 +492,69 @@ var/global/num_vending_terminals = 1 if(user.drop_item(W, src)) add_item(W) src.updateUsrDialog() - else if(istype(W, /obj/item/weapon/card)) - //attempt to connect to a new db, and if that doesn't work then fail - if(linked_account) - if(account_first_linked) - if(!user.Adjacent(src)) - return 0 - var/account_try = input(user,"Please enter the already connected account number","Security measure") as num - if(!user.Adjacent(src)) - return 0 - if(account_try != linked_account.account_number) - to_chat(user, "[bicon(src)]Access denied. Your input doesn't match the vending machine's connected account.") - return - if(!user.Adjacent(src)) - return 0 - var/new_account = input(user,"Please enter the account to connect to.","New account link") as num - if(!user.Adjacent(src)) - return 0 - for(var/datum/money_account/D in all_money_accounts) - if(D.account_number == new_account) - linked_account = D - if(!account_first_linked) - account_first_linked = 1 - playsound(get_turf(src), 'sound/machines/twobeep.ogg', 50, 0) - to_chat(user, "[bicon(src)]New connection established: [D.owner_name].") - return - to_chat(user, "[bicon(src)]The specified account doesn't exist.") - + else if(istype(W, /obj/item/weapon/card/emag)) + visible_message("[usr] swipes a card through [src].") + to_chat(user, "You swipe \the [W] through [src]") + if (emag()) + to_chat(user, "[src] responds with a soft beep.") else - to_chat(usr, "[bicon(src)]Unable to connect to linked account. Please contact a god.") + to_chat(user, "Nothing happens.") + else if(istype(W, /obj/item/weapon/card)) + if(currently_vending) //We're trying to pay, not set the account + connect_account(user, W) + src.updateUsrDialog() + return + //attempt to connect to a new db, and if that doesn't work then fail + if(!linked_account) + connect_to_user_account(user) + return + + if(account_first_linked) + if(!user.Adjacent(src)) + return 0 + var/account_try = input(user,"Please enter the already connected account number","Security measure") as num + if(!user.Adjacent(src)) + return 0 + if(account_try != linked_account.account_number) + to_chat(user, "[bicon(src)]Access denied. Your input doesn't match the vending machine's connected account.") + return 0 + if(!user.Adjacent(src)) + return 0 + connect_to_user_account(user) + return + + else if(istype(W, /obj/item/) && inserting_mode) + if(user.drop_item(W, src)) + insert_item(W) + +/obj/machinery/vending/proc/connect_to_user_account(mob/user) + var/new_account = input(user,"Please enter the account to connect to.","New account link") as num + if(!user.Adjacent(src) || !new_account) + return FALSE + for(var/datum/money_account/D in all_money_accounts) + if(D.account_number == new_account) + linked_account = D + if(!account_first_linked) + account_first_linked = 1 + playsound(src, 'sound/machines/twobeep.ogg', 50, 0) + to_chat(user, "[bicon(src)]New connection established: [D.owner_name].") + return TRUE + to_chat(user, "[bicon(src)]The specified account doesn't exist.") + return FALSE + +/obj/machinery/vending/proc/insert_item(var/obj/item/item) + for(var/datum/data/vending_product/VP in product_records) + if(VP.product_path == item) + VP.amount += 1 + if(istype(item, /obj/item/stack)) + var/obj/item/stack/S = item + VP.product_name = "A stack of [S.amount] [S.name]" + return + var/datum/data/vending_product/R = new() + R.custom_entry(item) + product_records += R + products += item //H.wear_id /** @@ -626,6 +669,8 @@ var/global/num_vending_terminals = 1 if (P.amount > 0) var/idx=GetProductIndex(P) dat += " (Vend)" + if (edit_mode) + dat += " (Set Price)" else dat += " SOLD OUT" dat += "
" @@ -667,9 +712,7 @@ var/global/num_vending_terminals = 1 spawn(ticks) - if(stat & (NOPOWER)) //Make another check just in case something goes weird - stat &= ~NOPOWER - src.update_vicon() + power_change() /obj/machinery/vending/proc/update_vicon() if(stat & (BROKEN)) @@ -801,6 +844,14 @@ var/global/num_vending_terminals = 1 if(product_slogans != "") dat += "The speaker switch is [shut_up ? "off" : "on"]. Toggle" + dat += "
" + + if(is_custom_machine) + dat += "Insert items mode is [inserting_mode ? "on" : "off"]. Toggle" + dat += "
" + dat += "The prices edit mode is [edit_mode ? "on" : "off"]. Toggle" + dat += "

" + dat += "Note: Remember to slide your ID on this machine if you don't want random people to change your prices." user << browse(dat, "window=vending;size=400x[vertical]") onclose(user, "vending") @@ -825,11 +876,11 @@ var/global/num_vending_terminals = 1 var/cat=text2num(href_list["cat"]) var/datum/data/vending_product/R = GetProductByID(idx,cat) if(R.price) - can_vend = 0//all borgs can buy free items from vending machines + can_vend = FALSE //all borgs can buy free items from vending machines if(istype(usr,/mob/living/silicon/robot)) var/mob/living/silicon/robot/R = usr - if((R.module && istype(R.module,/obj/item/weapon/robot_module/butler) ) || isMoMMI(R)) - can_vend = 1//only service borgs and MoMMI can buy costly items + if((R.module && (R.module.quirk_flags & MODULE_CAN_BUY))) + can_vend = TRUE //But if their module allows it.. if(!can_vend) to_chat(usr, "The vending machine refuses to interface with you, as you are not in its target demographic!") return @@ -876,21 +927,49 @@ var/global/num_vending_terminals = 1 return + else if (href_list["set_price"] && src.vend_ready && !currently_vending) + //testing("vend: [href]") + + if (!allowed(usr) && !emagged && scan_id) //For SECURE VENDING MACHINES YEAH + to_chat(usr, "Access denied.")//Unless emagged of course + + flick(src.icon_deny,src) + return + + var/idx=text2num(href_list["set_price"]) + var/cat=text2num(href_list["cat"]) + + var/datum/data/vending_product/R = GetProductByID(idx,cat) + if (!R || !istype(R) || !R.product_path || R.amount <= 0) + message_admins("Invalid vend request by [formatJumpTo(src.loc)]: [href]") + return + + var/new_price = input("Enter a price", "Change price", R.price) as null|num + if(new_price == null || new_price < 0) + new_price = R.price + R.price = new_price + else if (href_list["cancel_buying"]) src.currently_vending = null - src.updateUsrDialog() - return else if (href_list["buy"]) var/obj/item/weapon/card/card = usr.get_id_card() if(card) connect_account(usr, card) - src.updateUsrDialog() - return + else + to_chat(usr, "Please present a valid ID.") else if ((href_list["togglevoice"]) && (src.panel_open)) src.shut_up = !src.shut_up + else if ((href_list["toggle_edit_mode"])) + if(is_custom_machine) + edit_mode = !edit_mode + + else if ((href_list["toggle_insert_mode"])) + if(is_custom_machine) + inserting_mode = !inserting_mode + src.add_fingerprint(usr) src.updateUsrDialog() @@ -1058,7 +1137,13 @@ var/global/num_vending_terminals = 1 continue R.amount-- - throw_item = new dump_path(src.loc) + + if(is_custom_machine) + products.Remove(throw_item) + throw_item = dump_path + throw_item.forceMove(get_turf(src)) + else + throw_item = new dump_path(src.loc) if (!throw_item) return 0 @@ -1278,9 +1363,11 @@ var/global/num_vending_terminals = 1 "Try our new jerky!" ) icon_state = "snack" + icon_vend = "snack-vend" + vend_delay = 25 products = list( /obj/item/weapon/reagent_containers/food/snacks/candy = 6, - /obj/item/weapon/reagent_containers/food/drinks/dry_ramen = 6, + /obj/item/weapon/reagent_containers/food/drinks/dry_ramen/heating = 6, /obj/item/weapon/reagent_containers/food/snacks/chips =6, /obj/item/weapon/reagent_containers/food/snacks/sosjerky = 6, /obj/item/weapon/reagent_containers/food/snacks/no_raisin = 6, @@ -1297,7 +1384,7 @@ var/global/num_vending_terminals = 1 ) prices = list( /obj/item/weapon/reagent_containers/food/snacks/candy = 13, - /obj/item/weapon/reagent_containers/food/drinks/dry_ramen = 15, + /obj/item/weapon/reagent_containers/food/drinks/dry_ramen/heating = 15, /obj/item/weapon/reagent_containers/food/snacks/chips = 30, /obj/item/weapon/reagent_containers/food/snacks/sosjerky = 40, /obj/item/weapon/reagent_containers/food/snacks/no_raisin = 60, @@ -1315,6 +1402,8 @@ var/global/num_vending_terminals = 1 name = "\improper Robust Softdrinks" desc = "A softdrink vendor provided by Robust Industries, LLC." icon_state = "Cola_Machine" + icon_vend = "Cola_Machine-vend" + vend_delay = 11 product_slogans = list( "Robust Softdrinks: More robust than a toolbox to the head!", "At least we aren't Dan!" @@ -1395,6 +1484,7 @@ var/global/num_vending_terminals = 1 product_slogans = list("Carts to go!") icon_state = "cart" icon_deny = "cart-deny" + icon_vend = "cart-vend" products = list( /obj/item/weapon/cartridge/captain = 3, /obj/item/weapon/cartridge/hop = 3, @@ -1441,6 +1531,8 @@ var/global/num_vending_terminals = 1 "Award-winning cigs." ) icon_state = "cigs" + icon_vend = "cigs-vend" + vend_delay = 21 products = list( /obj/item/weapon/storage/fancy/cigarettes = 10, /obj/item/weapon/storage/fancy/matchbox = 10, @@ -1467,6 +1559,8 @@ var/global/num_vending_terminals = 1 req_access = list(access_medical) icon_state = "med" icon_deny = "med-deny" + icon_vend = "med-vend" + vend_delay = 18 product_ads = list( "Go save some lives!", "The best stuff for your medbay.", @@ -1506,6 +1600,11 @@ var/global/num_vending_terminals = 1 pack = /obj/structure/vendomatpack/medical +/obj/machinery/vending/medical/New() + ..() + if(map.nameShort == "deff") + icon = 'maps/defficiency/medbay.dmi' + //This one's from bay12 /obj/machinery/vending/plasmaresearch name = "\improper Toximate 3000" @@ -1590,7 +1689,7 @@ var/global/num_vending_terminals = 1 if(do_after(user, src, 40)) user.visible_message( "[user] detaches the NanoMed from the wall.", "You detach the NanoMed from the wall.") - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) + playsound(src, 'sound/items/Crowbar.ogg', 50, 1) new /obj/item/mounted/frame/wallmed(src.loc) for(var/obj/I in src) @@ -1608,7 +1707,7 @@ var/global/num_vending_terminals = 1 if(do_after(user, src, 40)) user.visible_message( "[user] detaches the NanoMed from the wall.", "You detach the NanoMed from the wall.") - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) + playsound(src, 'sound/items/Crowbar.ogg', 50, 1) new /obj/item/mounted/frame/wallmed(src.loc) for(var/obj/I in src) @@ -1651,7 +1750,7 @@ var/global/num_vending_terminals = 1 to_chat(usr, "You begin removing screws from \the [src] backplate...") if(do_after(user, src, 50)) to_chat(usr, "You unscrew \the [src] from the wall.") - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 50, 1) new /obj/item/mounted/frame/wallmed(get_turf(src)) qdel(src) return 1 @@ -1665,7 +1764,7 @@ var/global/num_vending_terminals = 1 if(user.drop_item(C, src)) to_chat(usr, "You secure \the [C]!") _circuitboard=C - playsound(get_turf(src), 'sound/effects/pop.ogg', 50, 0) + playsound(src, 'sound/effects/pop.ogg', 50, 0) build++ update_icon() return 1 @@ -1673,7 +1772,7 @@ var/global/num_vending_terminals = 1 if(iscrowbar(W)) to_chat(usr, "You begin to pry out \the [W] into \the [src].") if(do_after(user, src, 10)) - playsound(get_turf(src), 'sound/effects/pop.ogg', 50, 0) + playsound(src, 'sound/effects/pop.ogg', 50, 0) build-- update_icon() var/obj/item/weapon/circuitboard/C @@ -1690,7 +1789,7 @@ var/global/num_vending_terminals = 1 if(istype(W, /obj/item/stack/cable_coil)) var/obj/item/stack/cable_coil/C=W to_chat(user, "You start adding cables to \the [src]...") - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) if(do_after(user, src, 20) && C.amount >= 5) C.use(5) build++ @@ -1711,7 +1810,7 @@ var/global/num_vending_terminals = 1 return 1 if(isscrewdriver(W)) to_chat(user, "You begin to complete \the [src]...") - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 50, 1) if(do_after(user, src, 20)) if(!_circuitboard) _circuitboard=new boardtype(src) @@ -1724,7 +1823,7 @@ var/global/num_vending_terminals = 1 if(3) // Waiting for a recharge pack if(isscrewdriver(W)) to_chat(user, "You begin to unscrew \the [src]...") - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 50, 1) if(do_after(user, src, 30)) build-- update_icon() @@ -1777,6 +1876,8 @@ var/global/num_vending_terminals = 1 ) icon_state = "sec" icon_deny = "sec-deny" + icon_vend = "sec-vend" + vend_delay = 14 products = list( /obj/item/weapon/handcuffs = 8, /obj/item/weapon/grenade/flashbang = 4, @@ -1786,7 +1887,7 @@ var/global/num_vending_terminals = 1 /obj/item/weapon/legcuffs/bolas = 8, ) contraband = list( - /obj/item/clothing/glasses/sunglasses = 2, + /obj/item/clothing/glasses/sunglasses/security = 2, /obj/item/weapon/storage/fancy/donut_box = 2, ) premium = list( @@ -1834,6 +1935,8 @@ var/global/num_vending_terminals = 1 ) icon_state = "nutri" icon_deny = "nutri-deny" + icon_vend = "nutri-vend" + vend_delay = 26 products = list( /obj/item/weapon/reagent_containers/food/snacks/beezeez = 20, /obj/item/weapon/reagent_containers/glass/fertilizer/ez = 35, @@ -1866,6 +1969,8 @@ var/global/num_vending_terminals = 1 "Aw h'yeah son!" ) icon_state = "seeds" + icon_vend = "seeds-vend" + vend_delay = 13 products = list( /obj/item/seeds/bananaseed = 3, /obj/item/seeds/berryseed = 3, @@ -1939,7 +2044,7 @@ var/global/num_vending_terminals = 1 /obj/item/seeds/aloe = 3, /obj/item/seeds/pitcher = 3, /obj/item/seeds/vaporsac = 3, - /obj/item/seeds/dionanode = 3 + /obj/item/seeds/mushroommanspore = 3 ) contraband = list( /obj/item/seeds/eggyseed = 2, @@ -2022,6 +2127,7 @@ var/global/num_vending_terminals = 1 "You don't really need these..." ) icon_state = "dinnerware" + icon_vend = "dinnerware-vend" products = list( /obj/item/weapon/tray = 8, /obj/item/weapon/kitchen/utensil/fork = 6, @@ -2050,6 +2156,7 @@ var/global/num_vending_terminals = 1 name = "\improper BODA" desc = "An old vending machine containing sweet water." icon_state = "sovietsoda" + icon_vend = "sovietsoda-vend" product_slogans = list( "BODA: We sell drink.", "BODA: Drink today.", @@ -2084,7 +2191,8 @@ var/global/num_vending_terminals = 1 //req_access = list(access_maint_tunnels) icon_state = "tool" icon_deny = "tool-deny" - + icon_vend = "tool-vend" + vend_delay = 11 products = list( /obj/item/stack/cable_coil/random = 10, /obj/item/weapon/crowbar = 5, @@ -2113,6 +2221,8 @@ var/global/num_vending_terminals = 1 req_access = list(access_engine_equip)//Engineering Equipment access icon_state = "engivend" icon_deny = "engivend-deny" + icon_vend = "engivend-vend" + vend_delay = 21 products = list( /obj/item/clothing/glasses/scanner/meson = 2, /obj/item/clothing/glasses/scanner/material = 2, @@ -2128,7 +2238,6 @@ var/global/num_vending_terminals = 1 /obj/item/device/holomap = 2, /obj/item/weapon/reagent_containers/glass/bottle/sacid = 3, /obj/item/blueprints/construction_permit = 4, // permits - /obj/item/vaporizer = 2, ) contraband = list( /obj/item/weapon/cell/potato = 3, @@ -2179,28 +2288,6 @@ var/global/num_vending_terminals = 1 pack = /obj/structure/vendomatpack/building -/obj/item/stack/sheet/metal/bigstack/New() - getFromPool(/obj/item/stack/sheet/metal, loc, 20) - qdel(src) -/obj/item/stack/sheet/glass/glass/bigstack/New() - getFromPool(/obj/item/stack/sheet/glass/glass, loc, 20) - qdel(src) -/obj/item/stack/sheet/glass/plasmaglass/bigstack/New() - getFromPool(/obj/item/stack/sheet/glass/plasmaglass, loc, 20) - qdel(src) -/obj/item/stack/sheet/wood/bigstack/New() - getFromPool(/obj/item/stack/sheet/wood, loc, 20) - qdel(src) -/obj/item/stack/tile/carpet/bigstack/New() - getFromPool(/obj/item/stack/tile/carpet, loc, 20) - qdel(src) -/obj/item/stack/tile/arcade/bigstack/New() - getFromPool(/obj/item/stack/tile/arcade, loc, 20) - qdel(src) -/obj/item/stack/sheet/mineral/plastic/bigstack/New() - getFromPool(/obj/item/stack/sheet/mineral/plastic, loc, 20) - qdel(src) - //This one's from bay12 /obj/machinery/vending/engineering name = "\improper Robco Tool Maker" @@ -2399,6 +2486,7 @@ var/global/num_vending_terminals = 1 /obj/item/clothing/under/franksuit = 3, /obj/item/clothing/gloves/frankgloves = 3, /obj/item/clothing/shoes/frankshoes =3, + /obj/item/clothing/suit/kimono/sakura = 3 ) //Pretty much everything that had a chance to spawn. contraband = list( /obj/item/clothing/suit/cardborg = 3, @@ -2426,7 +2514,8 @@ var/global/num_vending_terminals = 1 /obj/item/clothing/under/darkholme = 3, /obj/item/clothing/suit/wizrobe/magician/fake = 3, /obj/item/clothing/head/wizard/magician = 3, - /obj/item/clothing/suit/sakura_kimono = 3, + /obj/item/clothing/suit/kimono = 3, + /obj/item/clothing/gloves/white = 3, ) pack = /obj/structure/vendomatpack/autodrobe @@ -2867,6 +2956,7 @@ var/global/num_vending_terminals = 1 /obj/item/clothing/head/clockwork_hood = 2, /obj/item/clothing/suit/clockwork_robes = 2, /obj/item/clothing/shoes/clockwork_boots = 2, + /obj/item/clothing/suit/kimono/ronin = 2 ) premium = list( /obj/item/weapon/reagent_containers/food/drinks/bottle/holywater = 1, @@ -2891,35 +2981,40 @@ var/global/num_vending_terminals = 1 /obj/item/weapon/storage/fancy/donut_box = 2, /obj/item/clothing/suit/storage/trader = 3, /obj/item/device/pda/trader = 3, - /obj/item/weapon/capsule = 60 + /obj/item/weapon/capsule = 60, + /obj/item/weapon/implantcase/peace = 5, + /obj/item/vaporizer = 1, ) prices = list( /obj/item/clothing/suit/storage/trader = 100, /obj/item/device/pda/trader = 100, - /obj/item/weapon/capsule = 10 + /obj/item/weapon/capsule = 10, + /obj/item/weapon/implantcase/peace = 100, + /obj/item/vaporizer = 100 ) accepted_coins = list(/obj/item/weapon/coin/trader) premium = list( - /obj/item/weapon/storage/trader_marauder, - //obj/item/weapon/storage/backpack/holding, //Players did exactly what you would expect and bought them for their own use. Keep in mind that an obj should be good but not so good they want it for themselves + /obj/item/weapon/storage/trader_chemistry, + /obj/structure/closet/secure_closet/wonderful, + /obj/item/weapon/disk/shuttle_coords/vault/mecha_graveyard, /obj/item/weapon/reagent_containers/glass/beaker/bluespace, /obj/item/weapon/storage/bluespace_crystal, - //obj/item/clothing/shoes/magboots/elite, /obj/item/weapon/reagent_containers/food/snacks/borer_egg, - /obj/item/weapon/reagent_containers/glass/bottle/peridaxon, - /obj/item/weapon/reagent_containers/glass/bottle/rezadone, - /obj/item/weapon/reagent_containers/glass/bottle/nanobotssmall, /obj/item/clothing/shoes/clown_shoes/advanced, + /obj/item/fish_eggs/seadevil, + /obj/machinery/power/antiquesynth, ) /obj/machinery/vending/trader/New() - premium.Add(pick(existing_typesof(/obj/item/borg/upgrade) - /obj/item/borg/upgrade/magnetic_gripper)) //A random borg upgrade minus the magnetic gripper. Time to jew the silicons! - for(var/random_items = 1 to premium.len - 5) premium.Remove(pick(premium)) + if(premium.Find(/obj/item/weapon/disk/shuttle_coords/vault/mecha_graveyard)) + load_dungeon(/datum/map_element/dungeon/mecha_graveyard) + premium.Add(pick(existing_typesof(/obj/item/borg/upgrade) - /obj/item/borg/upgrade/magnetic_gripper)) //A random borg upgrade minus the magnetic gripper. Time to jew the silicons! + ..() /obj/machinery/vending/barber @@ -3045,13 +3140,19 @@ var/global/num_vending_terminals = 1 name = "Sales" desc = "Buy, sell, repeat." icon_state = "sale" + is_custom_machine = TRUE //vend_reply = "Insert another joke here" //product_ads = "Another joke here" //product_slogans = "Jokes" + account_first_linked = 0 + machine_flags = SCREWTOGGLE | WRENCHMOVE | FIXED2WORK | CROWDESTROY | EJECTNOTDEL | PURCHASER | WIREJACK | SECUREDPANEL products = list() pack = /obj/structure/vendomatpack/custom +/obj/machinery/vending/sale/link_to_account() + return + /obj/machinery/vending/toggleSecuredPanelOpen(var/obj/toggleitem, var/mob/user) if(!account_first_linked) togglePanelOpen(toggleitem, user) @@ -3126,15 +3227,3 @@ var/global/num_vending_terminals = 1 ) pack = /obj/structure/vendomatpack/mining - -//Note : Snowflake, but I don't care. Rework the fucking economy -/obj/machinery/vending/mining/New() - ..() - - if(ticker) - initialize() - -/obj/machinery/vending/mining/initialize() - ..() - - linked_account = department_accounts["Cargo"] diff --git a/code/game/mecha/combat/gygax.dm b/code/game/mecha/combat/gygax.dm index 6364e1411d9..f088d916a1a 100644 --- a/code/game/mecha/combat/gygax.dm +++ b/code/game/mecha/combat/gygax.dm @@ -92,6 +92,9 @@ else icon_state = initial_icon +/obj/mecha/combat/gygax/dark/stopMechWalking() + icon_state = initial_icon + /obj/mecha/combat/gygax/dyndomove(direction) if(!..()) return @@ -125,4 +128,4 @@ ..() if (href_list["toggle_leg_overload"]) src.overload() - return \ No newline at end of file + return diff --git a/code/game/mecha/equipment/mecha_equipment.dm b/code/game/mecha/equipment/mecha_equipment.dm index 9102bc7c913..26c5fbcd1b9 100644 --- a/code/game/mecha/equipment/mecha_equipment.dm +++ b/code/game/mecha/equipment/mecha_equipment.dm @@ -125,7 +125,7 @@ /obj/item/mecha_parts/mecha_equipment/Topic(href,href_list) if(usr.incapacitated() || usr != chassis.occupant) return TRUE - testing("[src] topic") +// testing("[src] topic") if(href_list["detach"]) detach() return diff --git a/code/game/mecha/equipment/weapons/weapons.dm b/code/game/mecha/equipment/weapons/weapons.dm index 624f07a661f..75635efef0f 100644 --- a/code/game/mecha/equipment/weapons/weapons.dm +++ b/code/game/mecha/equipment/weapons/weapons.dm @@ -613,7 +613,7 @@ to_chat(user, "\The [C] needs at least two wrists before you can cuff them together!") return - playsound(get_turf(src), 'sound/weapons/handcuffs.ogg', 30, 1, -2) + playsound(src, 'sound/weapons/handcuffs.ogg', 30, 1, -2) user.visible_message("\The [M] is trying to handcuff \the [C]!", "You try to handcuff \the [C]!") diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index e6f1d81e2ce..dad34ffb84e 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -21,7 +21,7 @@ layer = MOB_LAYER //icon draw layer plane = MOB_PLANE infra_luminosity = 15 //byond implementation is bugged. - var/hud_list[2] + var/list/hud_list = list() var/initial_icon = null //Mech type for resetting icon. Only used for reskinning kits (see custom items) var/can_move = 1 var/mob/living/carbon/occupant = null @@ -111,8 +111,45 @@ /obj/mecha/Destroy() src.go_out(loc, TRUE) mechas_list -= src //global mech list + if(cell) + qdel(cell) + cell = null + if(internal_tank) + qdel(internal_tank) + internal_tank = null + if(cabin_air) + qdel(cabin_air) + cabin_air = null + connected_port = null + if(radio) + qdel(radio) + radio = null + if(electropack) + qdel(electropack) + electropack = null + if(tracking) + qdel(tracking) + tracking = null + if(pr_int_temp_processor) + qdel(pr_int_temp_processor) + pr_int_temp_processor = null + if(pr_inertial_movement) + qdel(pr_inertial_movement) + pr_inertial_movement = null + if(pr_give_air) + qdel(pr_give_air) + pr_give_air = null + if(pr_internal_damage) + qdel(pr_internal_damage) + pr_internal_damage = null + for(var/obj/item/mecha_parts/mecha_equipment/eq in equipment) + qdel(eq) + equipment = null + selected = null + if(events) + qdel(events) + events = null ..() - return /obj/mecha/can_apply_inertia() return 1 //No anchored check - so that mechas can fly off into space @@ -552,12 +589,12 @@ if(!prob(src.deflect_chance)) src.take_damage(15) src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) - playsound(get_turf(src), 'sound/weapons/slash.ogg', 50, 1, -1) + playsound(src, 'sound/weapons/slash.ogg', 50, 1, -1) to_chat(user, "You slash at the armored suit!") visible_message("The [user] slashes at [src.name]'s armor!") else src.log_append_to_last("Armor saved.") - playsound(get_turf(src), 'sound/weapons/slash.ogg', 50, 1, -1) + playsound(src, 'sound/weapons/slash.ogg', 50, 1, -1) to_chat(user, "Your claws had no effect!") src.occupant_message("The [user]'s claws are stopped by the armor.") visible_message("The [user] rebounds off [src.name]'s armor!") @@ -579,7 +616,7 @@ user.attack_log += text("\[[time_stamp()]\] attacked [src.name]") else src.log_append_to_last("Armor saved.") - playsound(get_turf(src), 'sound/weapons/slash.ogg', 50, 1, -1) + playsound(src, 'sound/weapons/slash.ogg', 50, 1, -1) src.occupant_message("The [user]'s attack is stopped by the armor.") visible_message("The [user] rebounds off [src.name]'s armor!") user.attack_log += text("\[[time_stamp()]\] attacked [src.name]") @@ -710,14 +747,14 @@ if(!prob(src.deflect_chance)) src.take_damage(6) src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) - playsound(get_turf(src), 'sound/effects/blobattack.ogg', 50, 1, -1) + playsound(src, 'sound/effects/blobattack.ogg', 50, 1, -1) to_chat(user, "You smash at the armored suit!") for (var/mob/V in viewers(src)) if(V.client && !(V.blinded)) V.show_message("The [user] smashes against [src.name]'s armor!", 1) else src.log_append_to_last("Armor saved.") - playsound(get_turf(src), 'sound/effects/blobattack.ogg', 50, 1, -1) + playsound(src, 'sound/effects/blobattack.ogg', 50, 1, -1) to_chat(user, "Your attack had no effect!") src.occupant_message("The [user]'s attack is stopped by the armor.") for (var/mob/V in viewers(src)) @@ -788,7 +825,7 @@ if(user.drop_item(W)) E.attach(src) user.visible_message("[user] attaches [W] to [src]", "You attach [W] to [src]") - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) else to_chat(user, "You were unable to attach [W] to [src]") return @@ -839,7 +876,7 @@ if ("electropack") electropack.forceMove(src.loc) electropack = null - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) to_chat(user, "You pry out \the [remove] from \the [src].") src.log_message("Internal component removed - [remove]") return @@ -2024,7 +2061,7 @@ var/transfer_moles = 0 if(pressure_delta > 0) //cabin pressure lower than release pressure if(tank_air.return_temperature() > 0) - transfer_moles = pressure_delta*cabin_air.return_volume()/(cabin_air.return_temperature() * R_IDEAL_GAS_EQUATION) + transfer_moles = pressure_delta * cabin_air.return_volume() / (cabin_air.return_temperature() * R_IDEAL_GAS_EQUATION) var/datum/gas_mixture/removed = tank_air.remove(transfer_moles) cabin_air.merge(removed) else if(pressure_delta < 0) //cabin pressure higher than release pressure @@ -2033,7 +2070,7 @@ if(t_air) pressure_delta = min(cabin_pressure - t_air.return_pressure(), pressure_delta) if(pressure_delta > 0) //if location pressure is lower than cabin pressure - transfer_moles = pressure_delta*cabin_air.return_volume()/(cabin_air.return_temperature() * R_IDEAL_GAS_EQUATION) + transfer_moles = pressure_delta * cabin_air.return_volume() / (cabin_air.return_temperature() * R_IDEAL_GAS_EQUATION) var/datum/gas_mixture/removed = cabin_air.remove(transfer_moles) if(t_air) t_air.merge(removed) diff --git a/code/game/objects/effects/aliens.dm b/code/game/objects/effects/aliens.dm index 48e82dfb601..b9868af56d0 100644 --- a/code/game/objects/effects/aliens.dm +++ b/code/game/objects/effects/aliens.dm @@ -498,7 +498,7 @@ status = GROWN new /obj/item/clothing/mask/facehugger(src) - for(var/mob/M in range(2,src)) + for(var/mob/living/M in range(2,src)) if(CanHug(M)) Burst(0) break @@ -519,10 +519,10 @@ return child.forceMove(loc) if(kill && istype(child)) - child.Die() + child.death() else for(var/mob/M in range(1,src)) - if(CanHug(M)) + if(CanHug(M, child)) child.Attach(M) break if(!ismob(child.loc)) @@ -573,11 +573,12 @@ /obj/effect/alien/egg/HasProximity(atom/movable/AM as mob|obj) if(status == GROWN) - if(!CanHug(AM)) + if(!isliving(AM)) return - - var/mob/living/carbon/C = AM - if(C.stat == CONSCIOUS && C.status_flags & XENO_HOST) + var/mob/living/L = AM + if(!CanHug(L)) + return + if(L.isUnconscious()) return Burst(0) diff --git a/code/game/objects/effects/decals/Cleanable/misc.dm b/code/game/objects/effects/decals/Cleanable/misc.dm index 85d1aa0ce2e..1e427a8f405 100644 --- a/code/game/objects/effects/decals/Cleanable/misc.dm +++ b/code/game/objects/effects/decals/Cleanable/misc.dm @@ -223,4 +223,10 @@ name = "rune" desc = "Looks unfinished." icon = 'icons/obj/wizard.dmi' - icon_state = "wizrune" \ No newline at end of file + icon_state = "wizrune" + +/obj/effect/decal/cleanable/smashed_butter + name = "smashed butter" + desc = "Looks like some one has butter fingers." + icon = 'icons/effects/tomatodecal.dmi' + icon_state = "smashed_butter" \ No newline at end of file diff --git a/code/game/objects/effects/effect_system.dm b/code/game/objects/effects/effect_system.dm index 9490561224f..f2a180ec32c 100644 --- a/code/game/objects/effects/effect_system.dm +++ b/code/game/objects/effects/effect_system.dm @@ -446,7 +446,8 @@ steam.start() -- spawns the effect n = 20 number = n cardinals = c - carry.copy_to(chemholder, carry.total_volume) + if(carry) + carry.copy_to(chemholder, carry.total_volume) if(istype(loca, /turf/)) @@ -747,8 +748,8 @@ steam.start() -- spawns the effect var/datum/gas_mixture/old_air = T.return_air() savedtemp = old_air.temperature if(istype(T) && savedtemp > lowest_temperature) - var/datum/gas_mixture/lowertemp = T.remove_air( T:air:total_moles() / T.air.volume * CELL_VOLUME ) - lowertemp.temperature = max( min(lowertemp.temperature-500,lowertemp.temperature / 2) ,0) + var/datum/gas_mixture/lowertemp = old_air.remove_volume(CELL_VOLUME) + lowertemp.temperature = max(min(lowertemp.temperature - 500, lowertemp.temperature / 2), 0) lowertemp.react() T.assume_air(lowertemp) spawn(3) @@ -759,9 +760,9 @@ steam.start() -- spawns the effect var/turf/simulated/T = get_turf(src) var/datum/gas_mixture/local_air = T.return_air() flick("[icon_state]-disolve", src) - if((local_air.temperature < lowest_temperature)&&(savedtemp > lowest_temperature)) //ie, we have over-chilled + if((local_air.temperature < lowest_temperature) && (savedtemp > lowest_temperature)) //ie, we have over-chilled local_air.temperature = lowest_temperature - else if ((local_air.temperature < lowest_temperature)&&(savedtemp < lowest_temperature) && savedtemp) //ie it chilled when it shouldn't have + else if((local_air.temperature < lowest_temperature) && (savedtemp < lowest_temperature) && savedtemp) //ie it chilled when it shouldn't have local_air.temperature = savedtemp sleep(5) qdel(src) @@ -980,6 +981,7 @@ steam.start() -- spawns the effect icon_regular_floor = "foamedmetal" icon_plating = "foamedmetal" can_exist_under_lattice = 1 + plane = PLATING_PLANE /turf/simulated/floor/foamedmetal/attack_hand(mob/living/user as mob) user.delayNextAttack(10) diff --git a/code/game/objects/effects/fire_blast.dm b/code/game/objects/effects/fire_blast.dm index 1c7c9412fce..a2ab1ea8ab6 100644 --- a/code/game/objects/effects/fire_blast.dm +++ b/code/game/objects/effects/fire_blast.dm @@ -101,8 +101,10 @@ for(var/obj/effect/E in get_turf(A)) if(istype(E, /obj/effect/blob)) var/obj/effect/blob/B = E - B.health -= (adjusted_fire_damage/10) + B.health -= (adjusted_fire_damage/2) B.update_icon() + B.update_health() + var/turf/T2 = get_turf(src) T2.hotspot_expose((blast_temperature * 2) + 380,500) sleep(2) diff --git a/code/game/objects/effects/mines.dm b/code/game/objects/effects/mines.dm index 34358ab8730..435c3207de9 100644 --- a/code/game/objects/effects/mines.dm +++ b/code/game/objects/effects/mines.dm @@ -15,7 +15,7 @@ /obj/effect/mine/Crossed(mob/living/carbon/AM) if(istype(AM)) - visible_message("[AM] triggered the [bicon(src)] [src]") + visible_message("[AM] triggered \the [bicon(src)] [src]") trigger(AM) /obj/effect/mine/proc/trigger(mob/living/carbon/AM) @@ -65,7 +65,7 @@ var/datum/gas_mixture/payload = new var/datum/gas/sleeping_agent/trace_gas = new - trace_gas.moles = 30 + trace_gas.moles = 187 // total mols of a n2o canister 1870.81 payload += trace_gas target.zone.air.merge(payload) @@ -77,6 +77,6 @@ /obj/effect/mine/stun/trigger(mob/AM) if(ismob(AM)) - AM.Stun(30) + AM.Knockdown(10) spark(src) - qdel(src) + qdel(src) \ No newline at end of file diff --git a/code/game/objects/effects/overlays.dm b/code/game/objects/effects/overlays.dm index 23c3890212f..59153796a8d 100644 --- a/code/game/objects/effects/overlays.dm +++ b/code/game/objects/effects/overlays.dm @@ -114,11 +114,18 @@ M.take_organ_damage(2) // Was 5 -- TLE M.visible_message("[M] slips on the floor!", \ "You slip on the floor!") - playsound(get_turf(src), 'sound/misc/slip.ogg', 50, 1, -3) + playsound(src, 'sound/misc/slip.ogg', 50, 1, -3) M.Knockdown(10) if(3) // Ice if(prob(30) && M.Slip(4, 3)) step(M, M.dir) M.visible_message("[M] slips on the icy floor!", \ - "You slip on the icy floor!") \ No newline at end of file + "You slip on the icy floor!") + + if(isrobot(AM) && wet == 1) //Only exactly water makes borgs glitch + var/mob/living/silicon/robot/R = AM + if(R.Slip(5,3)) + //Don't step forward as a robot, we're not slipping just glitching. + R.visible_message("[R] short circuits on the water!", \ + "You short circuit on the water!") \ No newline at end of file diff --git a/code/game/objects/effects/traps.dm b/code/game/objects/effects/traps.dm index 8b4f4af5dff..359ea9b838b 100644 --- a/code/game/objects/effects/traps.dm +++ b/code/game/objects/effects/traps.dm @@ -51,4 +51,4 @@ else S = sound_to_play - playsound(get_turf(src), S, volume, vary) + playsound(src, S, volume, vary) diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index f7045721307..79c6da6b47f 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -92,6 +92,9 @@ /obj/item/device icon = 'icons/obj/device.dmi' +/obj/item/proc/is_hidden_identity() + return is_slot_hidden(body_parts_covered,HIDEFACE) + /obj/item/ex_act(severity) switch(severity) if(1.0) @@ -228,7 +231,7 @@ return //user.next_move = max(user.next_move+2,world.time + 2) add_fingerprint(user) - if(!user.put_in_active_hand(src)) + if(can_pickup(user) && !user.put_in_active_hand(src)) forceMove(get_turf(user)) return @@ -789,7 +792,7 @@ else if(ismartian(M)) //why - var/mob/living/carbon/martian/MA = M + var/mob/living/carbon/complex/martian/MA = M switch(slot) if(slot_head) if(MA.head) @@ -808,7 +811,7 @@ if(anchored) //Object isn't anchored to_chat(user, "You can't pick that up!") return FALSE - if(!istype(loc, /turf)) //Object is not on a turf + if(!istype(loc, /turf) && !is_holder_of(user, src)) //Object is not on a turf to_chat(user, "You can't pick that up!") return FALSE return TRUE @@ -1189,7 +1192,7 @@ var/global/list/image/blood_overlays = list() return if(restraint_apply_sound) - playsound(get_turf(src), restraint_apply_sound, 30, 1, -2) + playsound(src, restraint_apply_sound, 30, 1, -2) user.visible_message("[user] is trying to restrain \the [C] with \the [src]!", "You try to restrain \the [C] with \the [src]!") @@ -1225,3 +1228,6 @@ var/global/list/image/blood_overlays = list() //Called when user clicks on an object while looking through a camera (passed to the proc as [eye]) /obj/item/proc/remote_attack(atom/target, mob/user, atom/movable/eye) return + +/obj/item/proc/recyclable() //Called by RnD machines, for added object-specific sanity. + return TRUE diff --git a/code/game/objects/items/anvil.dm b/code/game/objects/items/anvil.dm new file mode 100644 index 00000000000..c55ef1a1a23 --- /dev/null +++ b/code/game/objects/items/anvil.dm @@ -0,0 +1,33 @@ +/** Anvil + Is treated as an item that can not be picked up, unless you are incredibly strong. + +**/ + +/obj/item/anvil + name = "anvil" + desc = "For rounding and crafting objects. Combined with a hammer, you can likely craft some pleasant weapons with this" + w_class = W_CLASS_GIANT + icon = 'icons/obj/blacksmithing.dmi' + icon_state = "anvil" + impactsound = 'sound/misc/clang.ogg' + flags = FPRINT | TWOHANDABLE | MUSTTWOHAND + density = 1 + throwforce = 40 + +/obj/item/anvil/can_pickup(mob/living/M) + if(!..()) + return FALSE + if(M.get_strength() > 2) + return TRUE + +/obj/item/anvil/can_be_pulled(mob/user) + if(istype(user, /mob/living)) + var/mob/living/L = user + if(L.get_strength() >= 2) + return TRUE + return FALSE + +/obj/item/anvil/check_airflow_movable(n) + if(n > 1000) + return TRUE + return FALSE \ No newline at end of file diff --git a/code/game/objects/items/blueprints.dm b/code/game/objects/items/blueprints.dm index a779f7afa23..4d574ff2f34 100644 --- a/code/game/objects/items/blueprints.dm +++ b/code/game/objects/items/blueprints.dm @@ -86,7 +86,6 @@ these cannot rename rooms that are in by default BUT can rename rooms that are c /obj/item/blueprints/attack_self(mob/living/M) if (!ishigherbeing(M) && !issilicon(M)) to_chat(M, "This stack of blue paper means nothing to you.")//monkeys cannot into projecting - return if(currently_edited) @@ -119,7 +118,7 @@ these cannot rename rooms that are in by default BUT can rename rooms that are c delete_area(usr) /obj/item/blueprints/interact() - var/area/A = get_area() + var/area/A = get_area(src) var/text = {"[src]

[station_name()] blueprints


@@ -155,13 +154,9 @@ these cannot rename rooms that are in by default BUT can rename rooms that are c usr << browse(text, "window=blueprints") onclose(usr, "blueprints") - -/obj/item/blueprints/proc/get_area() - var/turf/T = get_turf(usr) - var/area/A = get_area_master(T) - return A - -/obj/item/blueprints/proc/get_area_type(var/area/A = get_area()) +/obj/item/blueprints/proc/get_area_type(var/area/A) + if(!A) + A = get_area(src) if (isspace(A)) return AREA_SPACE else if(istype(A, /area/station/custom)) @@ -324,7 +319,7 @@ these cannot rename rooms that are in by default BUT can rename rooms that are c editor = user - currently_edited = get_area() + currently_edited = get_area(src) processing_objects.Add(src) //Create a visual effect over the edited area @@ -338,7 +333,7 @@ these cannot rename rooms that are in by default BUT can rename rooms that are c to_chat(user, "This drawing was already signed, and can't be renamed.") return - var/area/A = get_area() + var/area/A = get_area(src) if(!istype(A) || !istype(user)) return @@ -367,7 +362,7 @@ these cannot rename rooms that are in by default BUT can rename rooms that are c to_chat(user, "This drawing can't be erased.") return - var/area/areadeleted = get_area() + var/area/areadeleted = get_area(src) if(area_protection_buffer >= 0) for(var/obj/machinery/alarm/air_alarm in areadeleted) @@ -383,7 +378,7 @@ these cannot rename rooms that are in by default BUT can rename rooms that are c return if(!Adjacent(user)) return - if(!(areadeleted == get_area())) + if(!(areadeleted == get_area(src))) return //if the blueprints are no longer in the area, return for(var/turf/T in areadeleted) diff --git a/code/game/objects/items/candle.dm b/code/game/objects/items/candle.dm index b43626c06ad..9bd98119068 100644 --- a/code/game/objects/items/candle.dm +++ b/code/game/objects/items/candle.dm @@ -41,7 +41,7 @@ wax-- var/turf/T = get_turf(src) var/datum/gas_mixture/env = T.return_air() - if(env.oxygen / env.volume * CELL_VOLUME < 5) + if(env.molar_density("oxygen") < (5 / CELL_VOLUME)) src.lit = 0 set_light(0) processing_objects.Remove(src) diff --git a/code/game/objects/items/changeling_vial.dm b/code/game/objects/items/changeling_vial.dm index 26282330c03..cd541bc166b 100644 --- a/code/game/objects/items/changeling_vial.dm +++ b/code/game/objects/items/changeling_vial.dm @@ -14,7 +14,7 @@ var/datum/mind/M = H.mind if(!ischangeling(H)) user.visible_message("As [user] crushes the vial, a mass of black goo leaps at \his face!.","As you try to remove the cap, you crush the vial in your hand! A mass of black goo leaps at you from the vial!") - playsound(get_turf(src), "shatter", 20, 1) + playsound(src, "shatter", 20, 1) qdel(src) H.sleeping += 10 sleep(100) diff --git a/code/game/objects/items/cookie_synth.dm b/code/game/objects/items/cookie_synth.dm index fb7c7b85779..411c8440c04 100644 --- a/code/game/objects/items/cookie_synth.dm +++ b/code/game/objects/items/cookie_synth.dm @@ -3,25 +3,16 @@ desc = "A self-recharging device used to rapidly deploy cookies." icon = 'icons/obj/RCD.dmi' icon_state = "rcd" - var/matter = 10 - var/toxin = 0 + var/food_type = /obj/item/weapon/reagent_containers/food/snacks/cookie + var/toxin = FALSE + var/toxin_type = CHLORALHYDRATE + var/toxin_amount = 10 + var/emagged = FALSE + var/sound_type = 'sound/machines/click.ogg' var/cooldown = 0 - var/cooldowndelay = 15 SECONDS // ONE COOKIE PER SECOND WAS A NO NO, THESE THINGS CAN MAKE FREE SHITTER JUICE WHEN EMAGGED - var/emagged = 0 + var/delay = 15 SECONDS w_class = W_CLASS_MEDIUM -/obj/item/weapon/cookiesynth/New() - ..() - processing_objects.Add(src) - -/obj/item/weapon/cookiesynth/Destroy() - processing_objects.Remove(src) - ..() - -/obj/item/weapon/cookiesynth/examine(mob/user) - ..() - to_chat(user,"It currently holds [matter]/10 cookie-units.") - /obj/item/weapon/cookiesynth/attackby(obj/item/weapon/W, mob/user) ..() if(isEmag(W)) @@ -29,13 +20,7 @@ /obj/item/weapon/cookiesynth/proc/Emag(mob/user) emagged = !emagged - if(emagged) - if(user) - to_chat(user,"You short out the [src]'s reagent safety checker!") - else - if(user) - to_chat(user,"You reset the [src]'s reagent safety checker!") - toxin = 0 + spark(src) /obj/item/weapon/cookiesynth/attack_self(mob/user) if(isrobot(user)) @@ -47,21 +32,14 @@ /obj/item/weapon/cookiesynth/proc/toggle_toxins(mob/user) toxin = !toxin - to_chat(user,"Cookie Synthesizer [toxin ? "Hacked" : "Reset"].") - -/obj/item/weapon/cookiesynth/process() - if(matter < 10) - matter++ + to_chat(user,"You [toxin ? "dis" : "en"]able the [src]'s reagent safety checker!") /obj/item/weapon/cookiesynth/afterattack(atom/A, mob/user, proximity) if(cooldown > world.time) return if(!proximity) return - if (!(istype(A, /obj/structure/table) || isturf(A))) - return - if(matter < 1) - to_chat(user,"The [src] doesn't have enough matter left. Wait for it to recharge!") + if(!(istype(A, /obj/structure/table) || isturf(A))) return if(isrobot(user)) var/mob/living/silicon/robot/R = user @@ -69,14 +47,37 @@ to_chat(user,"You do not have enough power to use [src].") return var/turf/T = get_turf(A) - playsound(src.loc, 'sound/machines/click.ogg', 10, 1) - to_chat(user,"Fabricating Cookie..") - var/obj/item/weapon/reagent_containers/food/snacks/cookie/S = new /obj/item/weapon/reagent_containers/food/snacks/cookie(T) + playsound(src.loc, sound_type, 10, 1) + var/obj/item/weapon/reagent_containers/food/S = new food_type(T) + to_chat(user,"Fabricating [utf8_lowercase(S.name)]..") if(toxin) - S.reagents.add_reagent(CHLORALHYDRATE, 10) - if (isrobot(user)) + S.reagents.add_reagent(toxin_type, toxin_amount) + if(isrobot(user)) var/mob/living/silicon/robot/R = user R.cell.charge -= 100 - else - matter-- - cooldown = world.time + cooldowndelay + cooldown = world.time + delay + +//TODO: Give hugborgs their own custom RSF instead of this snoflakey mess. + +/obj/item/weapon/cookiesynth/proc/Honkize() + name = "banana synthesizer" + desc = "A self-recharging device used to rapidly deploy bananas." + food_type = /obj/item/weapon/reagent_containers/food/snacks/grown/banana + toxin_type = SPIRITBREAKER + +/obj/item/weapon/cookiesynth/proc/Lawize() + name = "donut synthesizer" + desc = "A self-recharging device used to rapidly deploy donuts." + food_type = /obj/item/weapon/reagent_containers/food/snacks/donut/normal + toxin_type = CHEESYGLOOP + +/obj/item/weapon/cookiesynth/proc/Noirize() + name = "joe synthesizer" + desc = "A self-recharging device used to rapidly deploy bitter, black, and tasteless coffee." + food_type = /obj/item/weapon/reagent_containers/food/drinks/mug/joe + toxin_type = HEMOSCYANINE + +/obj/item/weapon/reagent_containers/food/drinks/mug/joe/New() + ..() + reagents.add_reagent(DETCOFFEE, 20) + diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index fd08afbb9b4..2c97f1262ab 100644 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -53,6 +53,7 @@ var/global/list/obj/item/device/pda/PDAs = list() var/cart = "" //A place to stick cartridge menu information var/detonate = 1 // Can the PDA be blown up? var/hidden = 0 // Is the PDA hidden from the PDA list? + var/reply = null //Where are replies directed? For multicaster. Most set this to self in new. var/obj/item/weapon/card/id/id = null //Making it possible to slot an ID card into the PDA so it can function as both. var/ownjob = null //related to above @@ -192,6 +193,7 @@ var/global/list/obj/item/device/pda/PDAs = list() ..() var/datum/pda_app/balance_check/app = new /datum/pda_app/balance_check() app.onInstall(src) + reply = src /obj/item/device/pda/medical name = "Medical PDA" @@ -442,7 +444,7 @@ var/global/list/obj/item/device/pda/PDAs = list() /obj/item/device/pda/trader name = "Trader PDA" desc = "Much good for trade." - note = "Congratulations, your station plU%ZÒ67Ez4ƦU8E1Ћ~@Tu1Bk@i8 NJ" + note = "Congratulations, your station �plU�%ZÒ67�Ez4ƦU���8�E1��Ћ���~���@��T�u1B��k�@i�8 �NJ��" icon_state = "pda-trader" default_cartridge = /obj/item/weapon/cartridge/trader @@ -692,6 +694,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
  • Notekeeper
  • Messenger
  • +
  • Department Messenger
  • Current Events
  • "} //dat += "
  • Nanotrasen Relay Chat
  • " @@ -848,31 +851,34 @@ var/global/list/obj/item/device/pda/PDAs = list() if (3) dat += "

    Atmospheric Readings

    " - var/turf/T = get_turf(user.loc) - if (isnull(T)) + if (isnull(user.loc)) dat += "Unable to obtain a reading.
    " else - var/datum/gas_mixture/environment = T.return_air() + var/datum/gas_mixture/environment = user.loc.return_air() - var/pressure = environment.return_pressure() - var/total_moles = environment.total_moles() + if(!environment) + dat += "No gasses detected.
    " - dat += "Air Pressure: [round(pressure,0.1)] kPa
    " + else + var/pressure = environment.return_pressure() + var/total_moles = environment.total_moles() - if (total_moles) - var/o2_level = environment.oxygen/total_moles - var/n2_level = environment.nitrogen/total_moles - var/co2_level = environment.carbon_dioxide/total_moles - var/plasma_level = environment.toxins/total_moles - var/unknown_level = 1-(o2_level+n2_level+co2_level+plasma_level) + dat += "Air Pressure: [round(pressure,0.1)] kPa
    " - dat += {"Nitrogen: [round(n2_level*100)]%
    - Oxygen: [round(o2_level*100)]%
    - Carbon Dioxide: [round(co2_level*100)]%
    - Plasma: [round(plasma_level*100)]%
    "} - if(unknown_level > 0.01) - dat += "OTHER: [round(unknown_level)]%
    " - dat += "Temperature: [round(environment.temperature-T0C)]°C
    " + if (total_moles) + var/o2_level = environment.oxygen/total_moles + var/n2_level = environment.nitrogen/total_moles + var/co2_level = environment.carbon_dioxide/total_moles + var/plasma_level = environment.toxins/total_moles + var/unknown_level = 1-(o2_level+n2_level+co2_level+plasma_level) + + dat += {"Nitrogen: [round(n2_level*100)]%
    + Oxygen: [round(o2_level*100)]%
    + Carbon Dioxide: [round(co2_level*100)]%
    + Plasma: [round(plasma_level*100)]%
    "} + if(unknown_level > 0.01) + dat += "OTHER: [round(unknown_level)]%
    " + dat += "Temperature: [round(environment.temperature-T0C)]°C
    " dat += "
    " if (5) @@ -1477,9 +1483,9 @@ var/global/list/obj/item/device/pda/PDAs = list() id.virtual_wallet.money -= amount withdraw_arbitrary_sum(user,amount) if(prob(50)) - playsound(get_turf(src), 'sound/items/polaroid1.ogg', 50, 1) + playsound(src, 'sound/items/polaroid1.ogg', 50, 1) else - playsound(get_turf(src), 'sound/items/polaroid2.ogg', 50, 1) + playsound(src, 'sound/items/polaroid2.ogg', 50, 1) var/datum/transaction/T = new() T.target_name = user.name @@ -1799,6 +1805,25 @@ var/global/list/obj/item/device/pda/PDAs = list() var/obj/item/device/pda/P = locate(href_list["target"]) src.create_message(U, P) + if("Multimessage") + var/list/department_list = list("security","engineering","medical","research","cargo","service") + var/target = input("Select a department", "CAMO Service") as null|anything in department_list + if(!target) + return + var/t = input(U, "Please enter message", "Message to [target]", null) as text|null + t = copytext(sanitize(t), 1, MAX_MESSAGE_LEN) + if (!t || toff || (!in_range(src, U) && loc != U)) //If no message, messaging is off, and we're either out of range or not in usr + return + if (last_text && world.time < last_text + 5) + return + last_text = world.time + for(var/obj/machinery/pda_multicaster/multicaster in pda_multicasters) + if(multicaster.check_status()) + multicaster.multicast(target,src,usr,t) + tnote += "→ To [target]:
    [t]
    " + return + to_chat(usr, "[bicon(src)]The PDA's screen flashes, 'Error, CAMO server is not responding.'") + if("transferFunds") if(!id) return @@ -2069,24 +2094,19 @@ var/global/list/obj/item/device/pda/PDAs = list() id.forceMove(get_turf(src)) id = null -/obj/item/device/pda/proc/create_message(var/mob/living/U = usr, var/obj/item/device/pda/P) - var/t = input(U, "Please enter message", "Message to [P]", null) as text|null - t = copytext(sanitize(t), 1, MAX_MESSAGE_LEN) - if (!t || !istype(P)) - return - if (!in_range(src, U) && loc != U) +/obj/item/device/pda/proc/create_message(var/mob/living/U = usr, var/obj/item/device/pda/P,var/multicast_message = null) + if (!istype(P)||P.toff) return + var/t = multicast_message + if(!t) + t = input(U, "Please enter message", "Message to [P]", null) as text|null + t = copytext(sanitize(t), 1, MAX_MESSAGE_LEN) + if (!t || toff || (!in_range(src, U) && loc != U)) //If no message, messaging is off, and we're either out of range or not in usr + return - if (isnull(P)||P.toff || toff) - return - - if (last_text && world.time < last_text + 5) - return - - if(!can_use(U)) - return - - last_text = world.time + if (last_text && world.time < last_text + 5) + return + last_text = world.time // check if telecomms I/O route 1459 is stable //var/telecomms_intact = telecomms_process(P.owner, owner, t) var/obj/machinery/message_server/useMS = null @@ -2117,13 +2137,13 @@ var/global/list/obj/item/device/pda/PDAs = list() useMS.send_pda_message("[P.owner]","[owner]","[t]") tnote += "→ To [P.owner]:
    [t]
    " - P.tnote += "← From [owner] ([ownjob]):
    [t]
    " + P.tnote += "← From [owner] ([ownjob]):
    [t]
    " for(var/mob/dead/observer/M in player_list) - if(M.stat == DEAD && M.client && (M.client.prefs.toggles & CHAT_GHOSTPDA)) // src.client is so that ghosts don't have to listen to mice + if(!multicast_message && M.stat == DEAD && M.client && (M.client.prefs.toggles & CHAT_GHOSTPDA)) // src.client is so that ghosts don't have to listen to mice M.show_message("PDA Message - [U][U.real_name == owner ? "" : " (as [owner])"] -> [P.owner]: [t]") - if (prob(15)) //Give the AI a chance of intercepting the message + if (prob(15)&&!multicast_message) //Give the AI a chance of intercepting the message var/who = src.owner if(prob(50)) who = P:owner @@ -2146,7 +2166,7 @@ var/global/list/obj/item/device/pda/PDAs = list() L = get_holder_of_type(P, /mob/living/silicon) if(L) - L.show_message("[bicon(P)] Message from [src.owner] ([ownjob]), \"[t]\" (Reply)", 2) + L.show_message("[bicon(P)] Message from [src.owner] ([ownjob]), \"[t]\" (Reply)", 2) U.show_message("[bicon(src)] Message for [P] has been sent.") log_pda("[key_name(usr)] (PDA: [src.name]) sent \"[t]\" to [P.name]") P.overlays.len = 0 diff --git a/code/game/objects/items/devices/PDA/apps.dm b/code/game/objects/items/devices/PDA/apps.dm index 942d5e52391..0b5db324fa9 100644 --- a/code/game/objects/items/devices/PDA/apps.dm +++ b/code/game/objects/items/devices/PDA/apps.dm @@ -140,7 +140,7 @@ var/global/list/pda_app_menus = list( game_update(user) if(snake_game.head.next_full) - playsound(get_turf(pda_device), 'sound/misc/pda_snake_eat.ogg', volume * 5, 1) + playsound(pda_device, 'sound/misc/pda_snake_eat.ogg', volume * 5, 1) if(!paused) if(!snake_game.gameover) @@ -173,7 +173,7 @@ var/global/list/pda_app_menus = list( pause(user) /datum/pda_app/snake/proc/game_over(var/mob/user) - playsound(get_turf(pda_device), 'sound/misc/pda_snake_over.ogg', volume * 5, 0) + playsound(pda_device, 'sound/misc/pda_snake_over.ogg', volume * 5, 0) for(var/i=1;i <= 4;i++) for(var/datum/snake/body/B in snake_game.snakeparts) B.flicking = 1 diff --git a/code/game/objects/items/devices/PDA/cart.dm b/code/game/objects/items/devices/PDA/cart.dm index 6369576c632..aec60ce6683 100644 --- a/code/game/objects/items/devices/PDA/cart.dm +++ b/code/game/objects/items/devices/PDA/cart.dm @@ -393,7 +393,8 @@ Code: var/list/chg = list("N","C","F") for(var/obj/machinery/power/apc/A in L) - menu += copytext(add_tspace(A.areaMaster.name, 30), 1, 30) + var/area/APC_area = get_area(A) + menu += copytext(add_tspace(APC_area.name, 30), 1, 30) menu += " [S[A.equipment+1]] [S[A.lighting+1]] [S[A.environ+1]] [add_lspace(A.lastused_total, 6)] [A.cell ? "[add_lspace(round(A.cell.percent()), 3)]% [chg[A.charging+1]]" : " N/C"]
    " menu += "
    " diff --git a/code/game/objects/items/devices/aicard.dm b/code/game/objects/items/devices/aicard.dm index 0078d9e710c..d729099c89e 100644 --- a/code/game/objects/items/devices/aicard.dm +++ b/code/game/objects/items/devices/aicard.dm @@ -24,7 +24,7 @@ transfer_ai("AICORE", "AICARD", M, user) - playsound(get_turf(src), 'sound/machines/paistartup.ogg', 50, 1) + playsound(src, 'sound/machines/paistartup.ogg', 50, 1) return /obj/item/device/aicard/attack_self(mob/user) diff --git a/code/game/objects/items/devices/chameleonproj.dm b/code/game/objects/items/devices/chameleonproj.dm index 722ae5982a2..e238e4d3473 100644 --- a/code/game/objects/items/devices/chameleonproj.dm +++ b/code/game/objects/items/devices/chameleonproj.dm @@ -46,7 +46,7 @@ return if(!active_dummy) if(istype(target, /obj/item) && !istype(target, /obj/item/weapon/disk/nuclear) || istype(target, /mob)) - playsound(get_turf(src), 'sound/weapons/flash.ogg', 100, 1, -6) + playsound(src, 'sound/weapons/flash.ogg', 100, 1, -6) to_chat(user, "Scanned [target].") saved_item = target.type saved_icon = target.icon @@ -59,7 +59,7 @@ return if(active_dummy) eject_all() - //playsound(get_turf(src), 'sound/effects/pop.ogg', 100, 1, -6) + //playsound(src, 'sound/effects/pop.ogg', 100, 1, -6) qdel(active_dummy) active_dummy = null to_chat(usr, "You deactivate [src].") @@ -72,7 +72,7 @@ spawn(20) //Stop spamming this shit can_use = 1 else - //playsound(get_turf(src), 'sound/effects/pop.ogg', 100, 1, -6) + //playsound(src, 'sound/effects/pop.ogg', 100, 1, -6) var/obj/O = new saved_item(src) if(!O) return diff --git a/code/game/objects/items/devices/deskbell.dm b/code/game/objects/items/devices/deskbell.dm index 031137d57b5..752660e8827 100644 --- a/code/game/objects/items/devices/deskbell.dm +++ b/code/game/objects/items/devices/deskbell.dm @@ -278,7 +278,7 @@ if(0) if(iswrench(W)) to_chat(user, "You deconstruct \the [src].") - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + playsound(src, 'sound/items/Ratchet.ogg', 50, 1) //new /obj/item/stack/sheet/metal( get_turf(src.loc), 2) var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal, get_turf(src)) M.amount = 2 @@ -289,7 +289,7 @@ user.visible_message( "[user.name] has added cables to \the [src]!", "You add cables to \the [src].") - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) C.use(1) build_step++ update_icon() diff --git a/code/game/objects/items/devices/does_not_tip.dm b/code/game/objects/items/devices/does_not_tip.dm new file mode 100644 index 00000000000..0e5af07140e --- /dev/null +++ b/code/game/objects/items/devices/does_not_tip.dm @@ -0,0 +1,15 @@ +/obj/item/device/does_not_tip_backdoor + name = "\improper PDA" + desc = "The screen seems to be blank." + icon = 'icons/obj/pda.dmi' + icon_state = "pda" + w_class = W_CLASS_TINY + flags = FPRINT + +/obj/item/device/does_not_tip_backdoor/attack_self(var/mob/user) + if(alert(user, "A cryptic message appears on the screen: \"Are you sure you want to do it?\".", name, "Yes", "No") != "Yes") + return + if(user.incapacitated() || !Adjacent(user)) + return + station_does_not_tip = !station_does_not_tip + to_chat(user, "\The [src]'s screen flashes [station_does_not_tip ? "red" : "green"] for a moment.") diff --git a/code/game/objects/items/devices/flash.dm b/code/game/objects/items/devices/flash.dm index 5c48239c596..24beb0133dd 100644 --- a/code/game/objects/items/devices/flash.dm +++ b/code/game/objects/items/devices/flash.dm @@ -76,7 +76,7 @@ to_chat(user, "*click* *click*") return - playsound(get_turf(user), 'sound/weapons/flash.ogg', 100, 1) + playsound(user, 'sound/weapons/flash.ogg', 100, 1) if(isrobot(user)) spawn(0) @@ -139,7 +139,7 @@ else //can only use it 5 times a minute user.show_message("*click* *click*", 2) return - playsound(get_turf(src), 'sound/weapons/flash.ogg', 100, 1) + playsound(src, 'sound/weapons/flash.ogg', 100, 1) if(harm_labeled >= min_harm_label) return //Act as if the flash was activated except the useful part. flick("flash2", src) diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index 7ea53decd47..43a2a47f5f5 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -34,12 +34,12 @@ set_light(brightness_on) if(playsound && has_sound) if(get_turf(src)) - playsound(get_turf(src), sound_on, 50, 1) + playsound(src, sound_on, 50, 1) else icon_state = initial(icon_state) set_light(0) if(playsound && has_sound) - playsound(get_turf(src), sound_off, 50, 1) + playsound(src, sound_off, 50, 1) /obj/item/device/flashlight/attack_self(mob/user) if(!isturf(user.loc)) diff --git a/code/game/objects/items/devices/holomap.dm b/code/game/objects/items/devices/holomap.dm index 8efe6c373f6..fa7c628bacb 100644 --- a/code/game/objects/items/devices/holomap.dm +++ b/code/game/objects/items/devices/holomap.dm @@ -74,7 +74,7 @@ target.holomap_data.Cut() for (var/obj/O in target) - if (O.holomap) + if (O.supports_holomap()) target.add_holomap(O) to_chat(user, "You reset the holomap data.") @@ -83,7 +83,7 @@ if (isscrewdriver(W)) panel = !panel to_chat(user, "You [panel ? "open" : "close"] the panel on \the [src].") - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 50, 1) return 1 if (ismultitool(W) && panel) diff --git a/code/game/objects/items/devices/inhaler.dm b/code/game/objects/items/devices/inhaler.dm new file mode 100644 index 00000000000..26ce9a4bcd0 --- /dev/null +++ b/code/game/objects/items/devices/inhaler.dm @@ -0,0 +1,52 @@ +#define PUFF_COOLDOWN_TIME 8 + +/obj/item/device/inhaler + name = "inhaler" + desc = "Breathe deep!" + icon = 'icons/obj/inhaler.dmi' + icon_state = "inhaler" + w_class = W_CLASS_TINY + flags = FPRINT + slot_flags = SLOT_BELT + throwforce = 0 + throw_speed = 4 + throw_range = 20 + force = 0 + var/last_puff = 0 + +/obj/item/device/inhaler/proc/puff_ready() + return last_puff < world.time - PUFF_COOLDOWN_TIME + +/obj/item/device/inhaler/attack_self(mob/user) + puff(user, user) + +/obj/item/device/inhaler/attack(mob/living/target, mob/user) + if(user.a_intent != I_HELP) + return ..() + puff(target, user) + +/obj/item/device/inhaler/proc/puff(mob/living/carbon/human/target, var/mob/living/user) + if(!ishuman(target)) + return + if(!puff_ready()) + return + var/used_on_self = target == user + if(!target.hasmouth) + if(used_on_self) + to_chat(user, "There's nowhere to put \the [src] as you lack a mouth!") + else + to_chat(user, "There's nowhere to put \the [src] as [target] lacks a mouth!") + return + var/obj/item/mouth_protection = target.get_body_part_coverage(MOUTH) + if(mouth_protection) + to_chat(user, "Remove [used_on_self ? "your" : "their"] [mouth_protection.name] first!") + return + if(used_on_self) + user.visible_message("[user] takes a puff from \the [src].", "You take a puff from \the [src].") + else + user.visible_message("[user] helps [target] take a puff from \the [src].", "You help [target] take a puff from \the [src].") + playsound(target, 'sound/effects/spray2.ogg', 20, 1) + target.reagents.add_reagent(ALBUTEROL, 5) + last_puff = world.time + +#undef PUFF_COOLDOWN_TIME diff --git a/code/game/objects/items/devices/lightreplacer.dm b/code/game/objects/items/devices/lightreplacer.dm index 65b91a28c07..6b73c4a30d1 100644 --- a/code/game/objects/items/devices/lightreplacer.dm +++ b/code/game/objects/items/devices/lightreplacer.dm @@ -190,6 +190,7 @@

    Supply Container:

    "} //It's not clear here, but the argument to build is the part of the typepath after /obj/item/weapon/light/ + dat += {"Filled: [supply.contents.len]/[supply.storage_slots]"} var/list/light_types = new() var/lightname for(var/obj/item/weapon/light/L in supply) @@ -260,6 +261,7 @@

    Supply Container:

    "} + dat += {"Filled: [supply.contents.len]/[supply.storage_slots]"} var/list/light_types = new() var/lightname for(var/obj/item/weapon/light/L in supply) @@ -323,7 +325,7 @@ to_chat(user, "You replace the [target.fitting] with \the [src].") - playsound(get_turf(src), 'sound/machines/click.ogg', 50, 1) + playsound(src, 'sound/machines/click.ogg', 50, 1) supply.remove_from_storage(best_light) @@ -366,7 +368,7 @@ /obj/item/device/lightreplacer/proc/Emag() emagged = !emagged - playsound(get_turf(src), "sparks", 100, 1) + playsound(src, "sparks", 100, 1) if(emagged) name = "Shortcircuited [initial(name)]" else diff --git a/code/game/objects/items/devices/mat_synth.dm b/code/game/objects/items/devices/mat_synth.dm index 67d0e2391ba..7301741de9b 100644 --- a/code/game/objects/items/devices/mat_synth.dm +++ b/code/game/objects/items/devices/mat_synth.dm @@ -24,7 +24,13 @@ "glass" = /obj/item/stack/sheet/glass/glass, "reinforced glass" = /obj/item/stack/sheet/glass/rglass, "plasteel" = /obj/item/stack/sheet/plasteel) - var/list/can_scan = list(/obj/item/stack/sheet) + + var/list/can_scan = list(/obj/item/stack/sheet/metal, + /obj/item/stack/sheet/glass/, + /obj/item/stack/sheet/wood, + /obj/item/stack/sheet/plasteel, + /obj/item/stack/sheet/mineral) + var/list/cant_scan = list() var/matter = 0 /obj/item/device/material_synth/robot/engiborg //Cyborg version, has less materials but can make rods n shit as well as scan. @@ -36,7 +42,7 @@ /obj/item/device/material_synth/robot/engiborg/New() //We have to do this during New() because BYOND can't pull a typesof() during compile time. . = ..() - can_scan = existing_typesof(/obj/item/stack/sheet) - list(/obj/item/stack/sheet/mineral/clown, /obj/item/stack/sheet/mineral/phazon) + cant_scan = list(/obj/item/stack/sheet/mineral/clown, /obj/item/stack/sheet/mineral/phazon) /obj/item/device/material_synth/robot/mommi //MoMMI version, a few more materials to start with. materials_scanned = list("metal" = /obj/item/stack/sheet/metal, @@ -146,7 +152,7 @@ /obj/item/device/material_synth/afterattack(atom/target, mob/user, proximity_flag, click_parameters) if(!proximity_flag) return 0 // not adjacent - if(is_type_in_list(target, can_scan)) //Can_scan, can you? + if(is_type_in_list(target, can_scan) && !is_type_in_list(target, cant_scan)) for(var/matID in materials_scanned) if(materials_scanned[matID] == target.type) to_chat(user, "You have already scanned \the [target].") @@ -173,7 +179,7 @@ return else matter += 10 - playsound(get_turf(src), 'sound/machines/click.ogg', 20, 1) + playsound(src, 'sound/machines/click.ogg', 20, 1) qdel(RA) to_chat(user, "The material synthetizer now holds [matter]/[MAX_MATSYNTH_MATTER] matter-units.") if(istype(O, /obj/item/weapon/card/emag)) diff --git a/code/game/objects/items/devices/megaphone.dm b/code/game/objects/items/devices/megaphone.dm index 748d69d3f8d..f08cf6f2687 100644 --- a/code/game/objects/items/devices/megaphone.dm +++ b/code/game/objects/items/devices/megaphone.dm @@ -42,18 +42,13 @@ if(user.client.prefs.muted & MUTE_IC) to_chat(src, "You cannot speak in IC (muted).") return 0 - if(user.silent) + if(issilent(user)) to_chat(user, "You find yourself unable to speak at all.") return 0 if(spamcheck) to_chat(user, "\The [src] needs to recharge!") return 0 if(ishuman(user)) //humans can use it, borgs can, mommis can't - to_chat(user, "You don't know how to use this!") - var/mob/living/carbon/human/H = user - if(istype(H) && (H.miming)) //Humans get their muteness checked - to_chat(user, "You find yourself unable to speak at all.") - return 0 return 1 if(isrobot(user) && !isMoMMI(user)) diff --git a/code/game/objects/items/devices/powersink.dm b/code/game/objects/items/devices/powersink.dm index 2931b64a717..6b712ca3a58 100644 --- a/code/game/objects/items/devices/powersink.dm +++ b/code/game/objects/items/devices/powersink.dm @@ -90,7 +90,7 @@ to_chat(M, "[user] activates the power sink!") mode = 2 icon_state = "powersink1" - playsound(get_turf(src), 'sound/effects/phasein.ogg', 30, 1) + playsound(src, 'sound/effects/phasein.ogg', 30, 1) processing_objects.Add(src) if(2) //This switch option wasn't originally included. It exists now. --NeoFite @@ -102,7 +102,7 @@ mode = 1 set_light(0) icon_state = "powersink0" - playsound(get_turf(src), 'sound/effects/teleport.ogg', 50, 1) + playsound(src, 'sound/effects/teleport.ogg', 50, 1) processing_objects.Remove(src) process() diff --git a/code/game/objects/items/devices/radio/cyborg.dm b/code/game/objects/items/devices/radio/cyborg.dm index 6e5bb8dc2e8..b7ca450331b 100644 --- a/code/game/objects/items/devices/radio/cyborg.dm +++ b/code/game/objects/items/devices/radio/cyborg.dm @@ -11,6 +11,10 @@ keyslot = key recalculateChannels() +/obj/item/device/radio/borg/proc/reset_key() + keyslot = initial(keyslot) + recalculateChannels() + /obj/item/device/radio/borg/attackby(obj/item/weapon/W as obj, mob/user as mob) // ..() user.set_machine(src) diff --git a/code/game/objects/items/devices/radio/encryptionkey.dm b/code/game/objects/items/devices/radio/encryptionkey.dm index 517aeccad1f..d4dc773e2fc 100644 --- a/code/game/objects/items/devices/radio/encryptionkey.dm +++ b/code/game/objects/items/devices/radio/encryptionkey.dm @@ -5,6 +5,7 @@ icon = 'icons/obj/radio.dmi' icon_state = "cypherkey" item_state = "" + w_class = W_CLASS_TINY var/translate_binary = 0 var/translate_hive = 0 var/syndie = 0 diff --git a/code/game/objects/items/devices/radio/headset.dm b/code/game/objects/items/devices/radio/headset.dm index 65462370132..e5167ad09f0 100644 --- a/code/game/objects/items/devices/radio/headset.dm +++ b/code/game/objects/items/devices/radio/headset.dm @@ -267,7 +267,7 @@ /obj/item/device/radio/headset/ert name = "CentCom Response Team headset" - desc = "The headset of the boss's boss. Channels are as follows: :r - Response Team :c - command, :s - security, :e - engineering, :d - mining, :q - cargo, :m - medical, :n - science." + desc = "The headset of the boss's boss. Channels are as follows: ':-' - Response Team :c - command, :s - security, :e - engineering, :d - mining, :q - cargo, :m - medical, :n - science." icon_state = "ert_headset" item_state = "headset" freerange = 1 diff --git a/code/game/objects/items/devices/radio/intercom.dm b/code/game/objects/items/devices/radio/intercom.dm index 09206e30ed3..86bdf3ea390 100644 --- a/code/game/objects/items/devices/radio/intercom.dm +++ b/code/game/objects/items/devices/radio/intercom.dm @@ -12,12 +12,16 @@ var/last_tick //used to delay the powercheck var/buildstage = 0 - holomap = TRUE - auto_holomap = TRUE +/obj/item/device/radio/intercom/supports_holomap() + return TRUE /obj/item/device/radio/intercom/universe/New() return ..() +/obj/item/device/radio/intercom/initialize() + ..() + add_self_to_holomap() + /obj/item/device/radio/intercom/New(turf/loc, var/ndir = 0, var/building = 3) ..() buildstage = building @@ -79,7 +83,7 @@ if(3) if(iswirecutter(W) && b_stat && wires.IsAllCut()) to_chat(user, "You cut out the intercoms wiring and disconnect its electronics.") - playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 50, 1) + playsound(src, 'sound/items/Wirecutter.ogg', 50, 1) if(do_after(user, src, 10)) new /obj/item/stack/cable_coil(get_turf(src),5) on = 0 @@ -92,7 +96,7 @@ return ..() if(2) if(isscrewdriver(W)) - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 50, 1) if(do_after(user, src, 10)) update_icon() on = 1 @@ -102,7 +106,7 @@ update_icon() processing_objects.Add(src) for(var/i, i<= 5, i++) - wires.UpdateCut(i,1) + wires.UpdateCut(i,1, user) return 1 if(1) if(iscablecoil(W)) @@ -117,7 +121,7 @@ return 1 if(iscrowbar(W)) to_chat(user, "You begin removing the electronics...") - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) if(do_after(user, src, 10)) new /obj/item/weapon/intercom_electronics(get_turf(src)) to_chat(user, "The circuitboard pops out!") @@ -125,7 +129,7 @@ return 1 if(0) if(istype(W,/obj/item/weapon/intercom_electronics)) - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) if(do_after(user, src, 10)) qdel(W) to_chat(user, "You insert \the [W] into \the [src]!") @@ -133,7 +137,7 @@ return 1 if(iswelder(W)) var/obj/item/weapon/weldingtool/WT=W - playsound(get_turf(src), 'sound/items/Welder.ogg', 50, 1) + playsound(src, 'sound/items/Welder.ogg', 50, 1) if(!WT.remove_fuel(3, user)) to_chat(user, "You're out of welding fuel.") return 1 @@ -152,11 +156,12 @@ /obj/item/device/radio/intercom/process() if(((world.timeofday - last_tick) > 30) || ((world.timeofday - last_tick) < 0)) last_tick = world.timeofday - if(!areaMaster) + var/area/this_area = get_area(src) + if(!this_area) on = 0 update_icon() return - on = areaMaster.powered(EQUIP) // set "on" to the power status + on = this_area.powered(EQUIP) // set "on" to the power status update_icon() /obj/item/weapon/intercom_electronics diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm index 6d426c2a0c7..f45f18675dc 100644 --- a/code/game/objects/items/devices/radio/radio.dm +++ b/code/game/objects/items/devices/radio/radio.dm @@ -100,7 +100,7 @@ Frequency: - - - [format_frequency(frequency)] + [format_frequency(frequency)] + +
    "} @@ -124,8 +124,13 @@ [chan_name]: [list ? "Engaged" : "Disengaged"]
    "} +/obj/item/device/radio/proc/check_traitor_uplink(frequency) + if(hidden_uplink) + if(hidden_uplink.check_trigger(usr, frequency, traitor_frequency)) + usr << browse(null, "window=radio") + return 1 + /obj/item/device/radio/Topic(href, href_list) - //..() if (usr.stat || !on) return @@ -164,15 +169,21 @@ return - else if (href_list["freq"]) - var/new_frequency = (frequency + text2num(href_list["freq"])) - if (!freerange || (frequency < 1200 || frequency > 1600)) - new_frequency = sanitize_frequency(new_frequency, maxf) + else if("set_freq" in href_list) + var/new_frequency + new_frequency = input(usr, "Set a new frequency (1200-1600 kHz).", src, frequency) as null|num + new_frequency = sanitize_frequency(new_frequency, maxf) set_frequency(new_frequency) - if(hidden_uplink) - if(hidden_uplink.check_trigger(usr, frequency, traitor_frequency)) - usr << browse(null, "window=radio") - return + if (check_traitor_uplink(frequency)) + return + + else if (href_list["freq"]) + var/new_frequency + new_frequency = (frequency + text2num(href_list["freq"])) + new_frequency = sanitize_frequency(new_frequency, maxf) + set_frequency(new_frequency) + if (check_traitor_uplink(frequency)) + return else if (href_list["talk"]) broadcasting = text2num(href_list["talk"]) @@ -305,7 +316,7 @@ speech.job = "Personal AI" // --- Cold, emotionless machines. --- - else if(isobj(speech.speaker)) + else if(isobj(speech.speaker) || istype(speech.speaker, /mob/living/simple_animal/spiderbot)) speech.job = "Machine" // --- Unidentifiable mob --- @@ -524,6 +535,7 @@ else user.show_message("\The [src] can no longer be modified or attached!") updateDialog() + update_icon() add_fingerprint(user) /obj/item/device/radio/emp_act(severity) diff --git a/code/game/objects/items/devices/remote/buttons/test_buttons.dm b/code/game/objects/items/devices/remote/buttons/test_buttons.dm index 044a20c3099..f5fc3bf38a1 100644 --- a/code/game/objects/items/devices/remote/buttons/test_buttons.dm +++ b/code/game/objects/items/devices/remote/buttons/test_buttons.dm @@ -5,7 +5,7 @@ icon_state = "button_ping" /obj/item/device/remote_button/ping/on_press(mob/user) - playsound(get_turf(holder), 'sound/machines/notify.ogg', 25, 0) + playsound(holder, 'sound/machines/notify.ogg', 25, 0) /obj/item/device/remote_button/bang name = "bang button" @@ -14,7 +14,7 @@ icon_state = "button_bang" /obj/item/device/remote_button/bang/on_press(mob/user) - playsound(get_turf(holder), 'sound/effects/bang.ogg', 25, 1) + playsound(holder, 'sound/effects/bang.ogg', 25, 1) /obj/item/device/remote_button/tong name = "tong button" @@ -23,4 +23,4 @@ icon_state = "button_tong" /obj/item/device/remote_button/tong/on_press(mob/user) - playsound(get_turf(holder), 'sound/instruments/piano/Cn4.ogg', 25, 1) \ No newline at end of file + playsound(holder, 'sound/instruments/piano/Cn4.ogg', 25, 1) \ No newline at end of file diff --git a/code/game/objects/items/devices/remote/remote_buttons.dm b/code/game/objects/items/devices/remote/remote_buttons.dm index 6d9dfde44d1..f59e3a02c1d 100644 --- a/code/game/objects/items/devices/remote/remote_buttons.dm +++ b/code/game/objects/items/devices/remote/remote_buttons.dm @@ -50,3 +50,8 @@ /obj/item/device/remote_button/proc/on_press(mob/user) return + + + + + diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index fb1de6d8795..a69e8a4c584 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -5,6 +5,7 @@ HEALTH ANALYZER GAS ANALYZER MASS SPECTROMETER REAGENT SCANNER +BREATHALYZER */ /obj/item/device/t_scanner @@ -180,7 +181,7 @@ Subject's pulse: ??? BPM"}) OX = fake_oxy > 50 ? "Severe oxygen deprivation detected" : "Subject bloodstream oxygen level normal" message += ("
    [OX] | [TX] | [BU] | [BR]") - if(M.reagents.total_volume) + if(M.reagents && M.reagents.total_volume) message += "
    Warning: Unknown substance detected in subject's blood." if(hardcore_mode_on && ishuman(M) && eligible_for_hardcore_mode(M)) var/mob/living/carbon/human/H = M @@ -293,14 +294,16 @@ Subject's pulse: ??? BPM"}) to_chat(user, "You don't have the dexterity to do this!") return - var/turf/location = get_turf(user) + var/atom/location = is_holder_of(user, src) ? user.loc : get_turf(src) //If user isn't the holder we're either in a mech's equipment loadout or something weird so get the outside environment if(!location) //Somehow return var/datum/gas_mixture/environment = location.return_air() - to_chat(user, output_gas_scan(environment, location, 1)) + var/unit_vol = environment && environment.volume > CELL_VOLUME ? CELL_VOLUME : null + + to_chat(user, output_gas_scan(environment, location, 1, unit_vol)) src.add_fingerprint(user) return @@ -323,14 +326,20 @@ Subject's pulse: ??? BPM"}) return var/turf/T = A var/datum/gas_mixture/environment = T.return_air() - to_chat(user, output_gas_scan(environment, T, 1)) + to_chat(user, output_gas_scan(environment, T, 1, CELL_VOLUME)) add_fingerprint(user) //If human_standard is enabled, the message will be formatted to show which values are dangerous -/obj/item/device/analyzer/proc/output_gas_scan(var/datum/gas_mixture/scanned, var/atom/container, human_standard = 1) +//If unit_vol is specified, it will output the values for that volume of the scanned gas. Really for analyzing areas. +/obj/item/device/analyzer/proc/output_gas_scan(var/datum/gas_mixture/scanned, var/atom/container, human_standard = 1, unit_vol) if(!scanned) return "No gas mixture found." scanned.update_values() + if(unit_vol) + var/datum/gas_mixture/unit = new() //Unless something goes horribly wrong, this will be cleaned up by the GC at the end of the proc. + unit.volume = unit_vol + unit.copy_from(scanned) + scanned = unit var/pressure = scanned.return_pressure() var/total_moles = scanned.total_moles() var/message = "" @@ -349,17 +358,17 @@ Subject's pulse: ??? BPM"}) var/unknown_concentration = 1 - (o2_concentration + n2_concentration + co2_concentration + plasma_concentration) if(n2_concentration > 0.01) - message += "
    [human_standard && abs(n2_concentration - N2STANDARD) > 20 ? "" : ""] Nitrogen: [round(scanned.nitrogen / scanned.volume * CELL_VOLUME, 0.1)] mol, [round(n2_concentration*100)]%" + message += "
    [human_standard && abs(n2_concentration - N2STANDARD) > 20 ? "" : ""] Nitrogen: [round(scanned.nitrogen, 0.1)] mol, [round(n2_concentration*100)]%" if(o2_concentration > 0.01) - message += "
    [human_standard && abs(o2_concentration - O2STANDARD) > 2 ? "" : ""] Oxygen: [round(scanned.oxygen / scanned.volume * CELL_VOLUME, 0.1)] mol, [round(o2_concentration*100)]%" + message += "
    [human_standard && abs(o2_concentration - O2STANDARD) > 2 ? "" : ""] Oxygen: [round(scanned.oxygen, 0.1)] mol, [round(o2_concentration*100)]%" if(co2_concentration > 0.01) - message += "
    [human_standard ? "" : ""] CO2: [round(scanned.carbon_dioxide / scanned.volume * CELL_VOLUME, 0.1)] mol, [round(co2_concentration*100)]%" + message += "
    [human_standard ? "" : ""] CO2: [round(scanned.carbon_dioxide, 0.1)] mol, [round(co2_concentration*100)]%" if(plasma_concentration > 0.01) - message += "
    [human_standard ? "" : ""] Plasma: [round(scanned.toxins / scanned.volume * CELL_VOLUME, 0.1)] mol, [round(plasma_concentration*100)]%" + message += "
    [human_standard ? "" : ""] Plasma: [round(scanned.toxins, 0.1)] mol, [round(plasma_concentration*100)]%" if(unknown_concentration > 0.01) message += "
    Unknown: [round(unknown_concentration*100)]%" - message += "
    [human_standard && !(scanned.temperature in range(BODYTEMP_COLD_DAMAGE_LIMIT, BODYTEMP_HEAT_DAMAGE_LIMIT)) ? "" : ""] Temperature: [round(scanned.temperature-T0C)]°C" + message += "
    [human_standard && !IsInRange(scanned.temperature, BODYTEMP_COLD_DAMAGE_LIMIT, BODYTEMP_HEAT_DAMAGE_LIMIT) ? "" : ""] Temperature: [round(scanned.temperature-T0C)]°C" message += "
    Heat capacity: [round(heat_capacity, 0.01)]" else message += "
    No gasses detected[container && !istype(container, /turf) ? " in \the [container]." : ""]!" @@ -405,7 +414,7 @@ Subject's pulse: ??? BPM"}) return if(!C.dna) return - if(M_NOCLONE in C.mutations) + if(M_HUSK in C.mutations) return var/datum/reagent/B = C.take_blood(src, src.reagents.maximum_volume) @@ -413,7 +422,7 @@ Subject's pulse: ??? BPM"}) update_icon() user.visible_message("[user] takes a blood sample from [C].", \ "You take a blood sample from [C]") - playsound(get_turf(src), 'sound/items/hypospray.ogg', 50, 1) //It uses the same thing as the hypospray, in reverse. SCIENCE! + playsound(src, 'sound/items/hypospray.ogg', 50, 1) //It uses the same thing as the hypospray, in reverse. SCIENCE! /obj/item/device/mass_spectrometer/attack_self(mob/user as mob) . = ..() @@ -495,3 +504,69 @@ Subject's pulse: ??? BPM"}) icon_state = "adv_spectrometer" details = 1 origin_tech = Tc_MAGNETS + "=4;" + Tc_BIOTECH + "=2" + +/obj/item/device/breathalyzer + name = "breathalyzer" + icon = 'icons/obj/breathalyzer.dmi' + icon_state = "idle" + item_state = "analyzer" + desc = "A hand-held scanner that is able to determine the amount of ethanol in the breath of the subject." + flags = FPRINT + siemens_coefficient = 1 + slot_flags = SLOT_BELT + throwforce = 3 + w_class = W_CLASS_TINY + throw_speed = 5 + starting_materials = list(MAT_IRON = 50) + w_type = RECYK_ELECTRONIC + melt_temperature = MELTPOINT_PLASTIC + origin_tech = Tc_ENGINEERING + "=1;" + Tc_BIOTECH + "=1" + + var/legal_limit + +/obj/item/device/breathalyzer/New() + var/datum/reagent/ethanol/E = /datum/reagent/ethanol + legal_limit = initial(E.slur_start) //inb4 shitcurity arrests people for being over the legal limit + ..() + +/obj/item/device/breathalyzer/attack_self(mob/user) + var/I = input("Set the legal limit of ethanol.", "Legal Limit", legal_limit) as null|num + + if(I) + legal_limit = max(0, I) + to_chat(user, "You successfully set the legal limit of the breathalyzer.") + +/obj/item/device/breathalyzer/attack(mob/living/M, mob/living/user) + if(!user.dexterity_check()) + to_chat(user, "You don't have the dexterity to do this!") + return + + if(!ishuman(M)) + return + + var/mob/living/carbon/human/C = M + + if(C.check_body_part_coverage(MOUTH)) + to_chat(src, "Remove their [C.get_body_part_coverage(MOUTH)] before using the breathalyzer.") + return + + playsound(user, 'sound/items/healthanalyzer.ogg', 50, 1) + + var/alcohol = 0 + + for(var/datum/reagent/ethanol/E in C.reagents.reagent_list) + alcohol += E.volume + + var/dat = "The breathalyzer reports that [C] has [alcohol] units of ethanol in their blood." + + if(alcohol >= legal_limit) + dat += "
    This is above the legal limit of [legal_limit]!" + flick("DRUNK", src) + else + flick("SOBER", src) + + to_chat(user, dat) + +/obj/item/device/breathalyzer/examine(mob/user) + ..() + to_chat(user, "Its legal limit is set to [legal_limit] units.") diff --git a/code/game/objects/items/devices/silicate sprayer.dm b/code/game/objects/items/devices/silicate sprayer.dm index 06fbd4db36d..3924f4e7d18 100644 --- a/code/game/objects/items/devices/silicate sprayer.dm +++ b/code/game/objects/items/devices/silicate sprayer.dm @@ -98,7 +98,7 @@ T.healthcheck(user, FALSE) user.visible_message("[user] repairs \the [T] with their [name]!", "You repair \the [T] with your [name].") - playsound(get_turf(T), 'sound/effects/refill.ogg', 10, 1, -6) + playsound(T, 'sound/effects/refill.ogg', 10, 1, -6) remove_silicate(diff * SILICATE_PER_DAMAGE) @@ -121,7 +121,7 @@ W.healthcheck(user, FALSE) user.visible_message("[user] repairs \the [W] with their [name]!", "You repair \the [W] with your [name].") - playsound(get_turf(src), 'sound/effects/refill.ogg', 10, 1, -6) + playsound(src, 'sound/effects/refill.ogg', 10, 1, -6) remove_silicate(diff * SILICATE_PER_DAMAGE) @@ -192,7 +192,7 @@ W.healthcheck(user, FALSE) user.visible_message("[user] reinforced \the [W] with their [name]!", "You reinforce \the [W] with your [name].") - playsound(get_turf(src), 'sound/effects/refill.ogg', 10, 1, -6) + playsound(src, 'sound/effects/refill.ogg', 10, 1, -6) remove_silicate(repair_amt * SILICATE_PER_REINFORCE) @@ -221,7 +221,7 @@ G.healthcheck(user) user.visible_message("[user] reinforced \the [G] with their [name]!", "You reinforce \the [G] with your [name].") - playsound(get_turf(src), 'sound/effects/refill.ogg', 10, 1, -6) + playsound(src, 'sound/effects/refill.ogg', 10, 1, -6) remove_silicate(repair_amt * SILICATE_PER_REINFORCE) diff --git a/code/game/objects/items/devices/sound_synth.dm b/code/game/objects/items/devices/sound_synth.dm index abcae2e8033..cd2270a7133 100644 --- a/code/game/objects/items/devices/sound_synth.dm +++ b/code/game/objects/items/devices/sound_synth.dm @@ -35,7 +35,10 @@ "Welding Noises" = "selected_sound=sound/items/Welder.ogg&shiftpitch=1&volume=55", "Quack" = "selected_sound=sound/items/quack.ogg&shiftpitch=1&volume=50", "Short Slide Whistle" = "selected_sound=sound/effects/slide_whistle_short.ogg&shiftpitch=1&volume=50", - "Long Slide Whistle" = "selected_sound=sound/effects/slide_whistle_long.ogg&shiftpitch=1&volume=50" + "Long Slide Whistle" = "selected_sound=sound/effects/slide_whistle_long.ogg&shiftpitch=1&volume=50", + "YEET" = "selected_sound=sound/effects/yeet.ogg&shiftpitch=1&volume=50", + "Time Stop" = "selected_sound=sound/effects/theworld3.ogg&shiftpitch=0&volume=80", + "Click" = "selected_sound=sound/effects/kirakrik.ogg&shiftpitch=0&volume=80" ) /obj/item/device/soundsynth/verb/pick_sound() @@ -52,7 +55,7 @@ /obj/item/device/soundsynth/attack_self(mob/user as mob) if(spam_flag + 2 SECONDS < world.timeofday) - playsound(get_turf(src), selected_sound, volume, shiftpitch) + playsound(src, selected_sound, volume, shiftpitch) spam_flag = world.timeofday /obj/item/device/soundsynth/attack(mob/living/M as mob, mob/living/user as mob, def_zone) diff --git a/code/game/objects/items/devices/traitordevices.dm b/code/game/objects/items/devices/traitordevices.dm index bcac97502b1..aa20a87dc9a 100644 --- a/code/game/objects/items/devices/traitordevices.dm +++ b/code/game/objects/items/devices/traitordevices.dm @@ -56,7 +56,7 @@ effective or pretty fucking useless. else to_chat(M, "You feel a sudden, electric jolt travel through your head.") - playsound(get_turf(src), 'sound/misc/interference.ogg', 50, 1) + playsound(src, 'sound/misc/interference.ogg', 50, 1) to_chat(user, "You trigger [src].") times_used += 1 if(times_used >= max_uses) diff --git a/code/game/objects/items/devices/whistle.dm b/code/game/objects/items/devices/whistle.dm index 94f3cd294df..e9f89eaf3f5 100644 --- a/code/game/objects/items/devices/whistle.dm +++ b/code/game/objects/items/devices/whistle.dm @@ -24,10 +24,10 @@ /obj/item/device/hailer/proc/do_your_sound(var/mob/user) if(emagged && insults) - playsound(get_turf(user), 'sound/voice/binsult.ogg', 100, 1, vary = 0) + playsound(user, 'sound/voice/binsult.ogg', 100, 1, vary = 0) insults-- else - playsound(get_turf(user), 'sound/voice/halt.ogg', 100, 1, vary = 0) + playsound(user, 'sound/voice/halt.ogg', 100, 1, vary = 0) if(user) var/list/bystanders = get_hearers_in_view(world.view, user) flick_overlay(image('icons/mob/talk.dmi', user, "hail", MOB_LAYER+1), clients_in_moblist(bystanders), 2 SECONDS) diff --git a/code/game/objects/items/misc_items.dm b/code/game/objects/items/misc_items.dm index 27b9d568f20..0e104695a51 100644 --- a/code/game/objects/items/misc_items.dm +++ b/code/game/objects/items/misc_items.dm @@ -49,7 +49,7 @@ /obj/item/red_ribbon_arm/equipped(mob/living/carbon/human/H, equipped_slot) ..() - if(istype(H) && H.get_item_by_slot(slot_belt) == src && equipped_slot != null) + if(istype(H) && H.get_item_by_slot(slot_belt) == src && equipped_slot != null && equipped_slot == slot_belt) H.set_hand_amount(H.held_items.len + 1) /obj/item/red_ribbon_arm/unequipped(mob/living/carbon/human/user, var/from_slot = null) diff --git a/code/game/objects/items/mountable_frames/frames.dm b/code/game/objects/items/mountable_frames/frames.dm index a275f0fb1f4..f1f877950a7 100644 --- a/code/game/objects/items/mountable_frames/frames.dm +++ b/code/game/objects/items/mountable_frames/frames.dm @@ -23,7 +23,8 @@ if (src.mount_reqs.Find("simfloor") && !istype(turf_loc, /turf/simulated/floor)) to_chat(user, "[src] cannot be placed on this spot.") return - if (src.mount_reqs.Find("nospace") && (areaMaster.requires_power == 0 || isspace(areaMaster))) + var/area/this_area = get_area(src) + if (src.mount_reqs.Find("nospace") && (this_area.requires_power == 0 || isspace(this_area))) to_chat(user, "[src] cannot be placed in this area.") return return 1 diff --git a/code/game/objects/items/mountable_frames/lights.dm b/code/game/objects/items/mountable_frames/lights.dm index 97898378225..f062cfb0916 100644 --- a/code/game/objects/items/mountable_frames/lights.dm +++ b/code/game/objects/items/mountable_frames/lights.dm @@ -9,7 +9,7 @@ /obj/item/mounted/frame/light_fixture/do_build(turf/on_wall, mob/user) to_chat(user, "You begin attaching [src] to \the [on_wall].") - playsound(get_turf(src), 'sound/machines/click.ogg', 75, 1) + playsound(src, 'sound/machines/click.ogg', 75, 1) var/constrdir = user.dir var/constrloc = get_turf(user) if (!do_after(user, on_wall, 30)) diff --git a/code/game/objects/items/mountable_frames/paintings.dm b/code/game/objects/items/mountable_frames/paintings.dm index 91fdfa554e0..17a414ec1e7 100644 --- a/code/game/objects/items/mountable_frames/paintings.dm +++ b/code/game/objects/items/mountable_frames/paintings.dm @@ -31,7 +31,6 @@ var/global/list/available_paintings = list( //"justice", spawned in the courtroom/IAA office if there is no courtroom //"blank", crafted with wood, TODO: give a way to players to paint on them //"anatomy", TODO: add one in medbay/surgery. - //"carp", TODO: make wall trophies their own items //"daddy", TODO: well it's not a painting...so make it its own item...? /obj/item/mounted/frame/painting diff --git a/code/game/objects/items/mountable_frames/posters/poster.dm b/code/game/objects/items/mountable_frames/posters/poster.dm index 96642cac55d..a93b1fa1d82 100644 --- a/code/game/objects/items/mountable_frames/posters/poster.dm +++ b/code/game/objects/items/mountable_frames/posters/poster.dm @@ -92,7 +92,7 @@ obj/structure/sign/poster/attackby(obj/item/weapon/W as obj, mob/user as mob) if(user.loc != temp_loc) return visible_message("[user] rips [src] in a single, decisive motion!" ) - playsound(get_turf(src), 'sound/items/poster_ripped.ogg', 100, 1) + playsound(src, 'sound/items/poster_ripped.ogg', 100, 1) ruined = 1 icon_state = "poster_ripped" name = "ripped poster" diff --git a/code/game/objects/items/mountable_frames/station_map.dm b/code/game/objects/items/mountable_frames/station_map.dm index b69351460e0..f7b27d95421 100644 --- a/code/game/objects/items/mountable_frames/station_map.dm +++ b/code/game/objects/items/mountable_frames/station_map.dm @@ -103,7 +103,7 @@ /datum/construction/reversible/station_map/spawn_result(mob/user as mob) if(result) - testing("[user] finished a [result]!") + //testing("[user] finished a [result]!") var/obj/machinery/station_map/S = new result(get_turf(holder)) S.dir = holder.dir diff --git a/code/game/objects/items/mountable_frames/trophy_mount.dm b/code/game/objects/items/mountable_frames/trophy_mount.dm index 8b0d14e0df0..b4d9943fc53 100644 --- a/code/game/objects/items/mountable_frames/trophy_mount.dm +++ b/code/game/objects/items/mountable_frames/trophy_mount.dm @@ -126,7 +126,7 @@ /obj/structure/trophy_mount/attackby(obj/item/weapon/W, mob/user) if(iscrowbar(W)) to_chat(user, "You begin prying \the [initial(name)] off the wall.") - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) if(do_after(user, src,10)) to_chat(user, "You pry \the [initial(name)] off of the wall.") add_fingerprint(user) diff --git a/code/game/objects/items/mountable_frames/wreath.dm b/code/game/objects/items/mountable_frames/wreath.dm index ac3e51c0b95..614a25fd067 100644 --- a/code/game/objects/items/mountable_frames/wreath.dm +++ b/code/game/objects/items/mountable_frames/wreath.dm @@ -21,7 +21,7 @@ /obj/structure/wreath/wreath_bow/attackby(obj/item/W as obj, mob/user as mob) if(iscrowbar(W)) to_chat(user, "You begin prying \the [src] off the wall.") - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) if(do_after(user, src,10)) to_chat(user, "You pry \the [src] off of the wall.") new /obj/item/mounted/frame/wreath/wreath_bow(get_turf(user)) @@ -52,7 +52,7 @@ /obj/structure/wreath/wreath_nobow/attackby(obj/item/W as obj, mob/user as mob) if(iscrowbar(W)) to_chat(user, "You begin prying \the [src] off the wall.") - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) if(do_after(user, src,10)) to_chat(user, "You pry \the [src] off of the wall.") new /obj/item/mounted/frame/wreath/wreath_nobow(get_turf(user)) diff --git a/code/game/objects/items/ornaments.dm b/code/game/objects/items/ornaments.dm index a185cb06f13..ffeae8a1da2 100644 --- a/code/game/objects/items/ornaments.dm +++ b/code/game/objects/items/ornaments.dm @@ -60,7 +60,7 @@ ..() src.visible_message("\The [src] shatters!","You hear a shatter!") if(get_turf(src)) - playsound(get_turf(src), 'sound/effects/hit_on_shattered_glass.ogg', 70, 1) + playsound(src, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1) if(prob(33)) getFromPool(/obj/item/weapon/shard, get_turf(src)) // Create a glass shard at the hit location! qdel(src) diff --git a/code/game/objects/items/potions.dm b/code/game/objects/items/potions.dm index a32534fbc3f..8df6967e9b1 100644 --- a/code/game/objects/items/potions.dm +++ b/code/game/objects/items/potions.dm @@ -21,9 +21,9 @@ if(!full) return user.visible_message("\The [user] drinks \the [src].", "You drink \the [src].") - playsound(get_turf(src),'sound/items/uncorking.ogg', rand(10,50), 1) + playsound(src,'sound/items/uncorking.ogg', rand(10,50), 1) spawn(6) - playsound(get_turf(src),'sound/items/drink.ogg', rand(10,50), 1) + playsound(src,'sound/items/drink.ogg', rand(10,50), 1) imbibe(user) /obj/item/potion/update_icon() @@ -56,7 +56,7 @@ user.visible_message("\The [user] attempts to feed \the [M] \the [src].", "You attempt to feed \the [M] \the [src].") if(!do_mob(user, M)) return - playsound(get_turf(src),'sound/items/drink.ogg', rand(10,50), 1) + playsound(src,'sound/items/drink.ogg', rand(10,50), 1) user.visible_message("\The [user] feeds \the [M] \the [src].", "You feed \the [M] \the [src].") M.attack_log += text("\[[time_stamp()]\] Has been fed [src.name] by [user.name] ([user.ckey])") diff --git a/code/game/objects/items/robot/robot_items.dm b/code/game/objects/items/robot/robot_items.dm index 31284a17a11..789d32a49b0 100644 --- a/code/game/objects/items/robot/robot_items.dm +++ b/code/game/objects/items/robot/robot_items.dm @@ -160,17 +160,22 @@ obj/item/borg/stun/attack(mob/M as mob, mob/living/silicon/robot/user as mob) desc = "Releases a harmless blast that confuses most organics. For when the harm is JUST TOO MUCH" icon_state = "megaphone" var/cooldown = 0 + var/alarm = "HUMAN HARM" + var/alarm_sound = 'sound/AI/harmalarm.ogg' + var/emagged_alarm = "BZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZT" + var/emagged_alarm_sound = 'sound/machines/warning-buzzer.ogg' + var/vary = TRUE /obj/item/device/harmalarm/attack_self(mob/user) var/safety = TRUE if(cooldown > world.time) - to_chat(user,"The device is still recharging!") + to_chat(user,"The device is still recharging!") return if(isrobot(user)) var/mob/living/silicon/robot/R = user if(R.cell.charge < 1200) - to_chat(user, "You don't have enough charge to do this!") + to_chat(user, "You don't have enough charge to do this!") return R.cell.charge -= 1000 if(R.emagged) @@ -179,13 +184,13 @@ obj/item/borg/stun/attack(mob/M as mob, mob/living/silicon/robot/user as mob) to_chat(R.connected_ai,"
    NOTICE - [src] used by: [user]
    ") if(safety == TRUE) - user.visible_message("HUMAN HARM") - playsound(get_turf(src), 'sound/AI/harmalarm.ogg', 70, 3) + user.visible_message("[alarm]") + playsound(src, alarm_sound, 70, 3, vary = src.vary) add_gamelogs(user, "used \the [src]", admin = TRUE, tp_link = TRUE, tp_link_short = FALSE, span_class = "notice") for(var/mob/living/carbon/M in hearers(9, user)) if(M.earprot()) continue - to_chat(M, "[user] blares out a near-deafening siren from its speakers!") + to_chat(M, "[user] blares out a near-deafening siren from its speakers!") to_chat(M, "The siren pierces your hearing!") M.stuttering += 5 M.ear_deaf += 1 @@ -197,8 +202,8 @@ obj/item/borg/stun/attack(mob/M as mob, mob/living/silicon/robot/user as mob) return if(safety == FALSE) - user.visible_message("BZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZT") - playsound(get_turf(src), 'sound/machines/warning-buzzer.ogg', 130, 3) + user.visible_message("[emagged_alarm]") + playsound(src, emagged_alarm_sound, 130, 3, vary = src.vary) add_gamelogs(user, "used an emagged [name]", admin = TRUE, tp_link = TRUE, tp_link_short = FALSE, span_class = "danger") for(var/mob/living/carbon/M in hearers(6, user)) if(M.earprot()) @@ -210,3 +215,101 @@ obj/item/borg/stun/attack(mob/M as mob, mob/living/silicon/robot/user as mob) M.Jitter(30) add_gamelogs(user, "knocked out [key_name(M)] with an emagged [name]", admin = FALSE, tp_link = FALSE) cooldown = world.time + 1 MINUTES + +/obj/item/device/harmalarm/proc/Lawize() + name = "sonic law breaking prevention tool" + desc = "Releases a harmless blast that confuses most organics. For when the crime is JUST TOO MUCH" + alarm = "HALT! SECURITY!" + alarm_sound = 'sound/voice/halt.ogg' + emagged_alarm = "FUCK YOUR CUNT YOU SHIT EATING COCKSUCKER MAN EAT A DONG FUCKING ASS RAMMING SHITFUCK. EAT PENISES IN YOUR FUCKFACE AND SHIT OUT ABORTIONS OF FUCK AND DO A SHIT IN YOUR ASS YOU COCK FUCK SHIT MONKEY FUCK ASS WANKER FROM THE DEPTHS OF SHIT." + emagged_alarm_sound = 'sound/voice/binsult.ogg' + vary = FALSE + +/obj/item/device/harmalarm/proc/Honkize() + name = "\improper HoNkER BlAsT 2500" + desc = "Releases a harmless blast that confuses most organics. For when the FUN is JUST TOO MUCH" + alarm = "HONK!" + alarm_sound = 'sound/items/bikehorn.ogg' + emagged_alarm = "HOOOOOOONK!" + emagged_alarm_sound = 'sound/items/AirHorn.ogg' + +//Noir upgrade modules +#define NEEDED_CHARGE_TO_RESTOCK_AMMO 5 + +/obj/item/ammo_storage/speedloader/c38/cyborg + desc = "The echo of the first shot, like the first sip of whiskey, burning..." + var/charge = 0 + +/obj/item/ammo_storage/speedloader/c38/cyborg/restock() + charge++ + if(charge >= NEEDED_CHARGE_TO_RESTOCK_AMMO && stored_ammo.len < max_ammo) //takes about 10 seconds. + stored_ammo += new ammo_type(src) + update_icon() + charge = initial(charge) + +#undef NEEDED_CHARGE_TO_RESTOCK_AMMO + +//The cyborg-friendly version and shameless copypaste of binoculars. +/obj/item/cyborglens + name = "long-range zoom camera lens" + icon_state = "binoculars" + var/zoom = FALSE + var/event_key = null + +/obj/item/cyborglens/attack_self(mob/user) + zoom = !zoom + update_zoom(user) + +/obj/item/cyborglens/proc/mob_moved(var/list/event_args, var/mob/holder) + if(zoom) + zoom = FALSE + update_zoom(holder) + +/obj/item/cyborglens/proc/update_zoom(var/mob/user) + if(isrobot(user)) + var/mob/living/silicon/robot/R =user + if(R.client) + var/client/C = R.client + if(zoom && R.is_component_functioning("camera")) + event_key = R.on_moved.Add(src, "mob_moved") + R.visible_message("[R]'s camera lens focuses loudly.","Your camera lens focuses loudly.") + R.regenerate_icons() + C.changeView(C.view + 4) + else + R.on_moved.Remove(event_key) + R.regenerate_icons() + C.changeView(C.view - 4) + +//Warden upgrade modules +#define NEEDED_CHARGE_TO_RESTOCK_IMP 30 + +/obj/item/weapon/implanter/cyborg + name = "cyborg implanter" + imp_type = /obj/item/weapon/implant/loyalty + var/charge = 0 + +/obj/item/weapon/implanter/cyborg/update() + ..() + name = "[initial(name)][imp? " - [imp.name]":""]" + +/obj/item/weapon/implanter/cyborg/restock() + charge++ + if(charge >= NEEDED_CHARGE_TO_RESTOCK_IMP && !imp) //takes about 60 seconds. + if(imp_type) + imp = new imp_type(src) + update() + charge = initial(charge) + +#undef NEEDED_CHARGE_TO_RESTOCK_IMP + +/obj/item/weapon/card/robot //This is not a child of id cards, as to avoid dumb typechecks on computers. Ported from bay's research cyborg. + name = "access code transmission device" + icon_state = "id-robot" + desc = "A circuit grafted onto the bottom of an ID card." + +/obj/item/weapon/card/robot/security + name = "security code transmission device" + +/obj/item/weapon/card/robot/security/New() + ..() + desc += " This one is used to transmit security codes into deployable barriers, allowing the user to lock and unlock them." \ No newline at end of file diff --git a/code/game/objects/items/robot/robot_parts.dm b/code/game/objects/items/robot/robot_parts.dm index 09b9eb40928..f8579ffaf56 100644 --- a/code/game/objects/items/robot/robot_parts.dm +++ b/code/game/objects/items/robot/robot_parts.dm @@ -56,6 +56,12 @@ icon_state = LIMB_CHEST var/wires = 0.0 var/obj/item/weapon/cell/cell = null + var/extension = null //For making borgs start with pre-installed better components. Make the var the end of the path including the "/". + +/obj/item/robot_parts/chest/reinforced + name = "reinforced robot torso" + desc = "A heavily reinforced case containing cyborg logic boards, space for a standard power cell, and several pre-installed reinforced robot components." + extension = "/reinforced" /obj/item/robot_parts/head name = "robot head" @@ -231,7 +237,9 @@ O.mind.store_memory("In case you look at this after being borged, the objectives are only here until I find a way to make them not show up for you, as I can't simply delete them without screwing up round-end reporting. --NeoFite") O.job = "Cyborg" - + if(chest.extension) + O.component_extension = chest.extension + O.upgrade_components() O.cell = chest.cell O.cell.forceMove(O) W.forceMove(O) //Should fix cybros run time erroring when blown up. It got deleted before, along with the frame. diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm index face9f81eef..ae5cf2ad842 100644 --- a/code/game/objects/items/robot/robot_upgrades.dm +++ b/code/game/objects/items/robot/robot_upgrades.dm @@ -3,8 +3,6 @@ #define FAILED_TO_ADD 1 -/obj/item/borg/upgrade/var/vtec_bonus = 0.25 //Define when - /obj/item/borg/upgrade name = "A borg upgrade module." desc = "Protected by FRM." @@ -31,34 +29,33 @@ return null return I -/obj/item/borg/upgrade/proc/attempt_action(var/mob/living/silicon/robot/R,var/mob/living/user) +/obj/item/borg/upgrade/proc/attempt_action(var/mob/living/silicon/robot/R,var/mob/living/user, var/ignore_cover = FALSE) if(!R.module) to_chat(user, "The borg must choose a module before he can be upgraded!") return FAILED_TO_ADD - if(isMoMMI(R)) if(!add_to_mommis) - to_chat(user, "\The [src] only functions on Nanotrasen Cyborgs.") + to_chat(user, "\The [src] only functions on Cyborgs.") return FAILED_TO_ADD else if(required_module.len) if(!(R.module.type in required_module)) to_chat(user, "\The [src] will not fit into \the [R.module.name]!") return FAILED_TO_ADD - if(R.stat == DEAD) + if(R.isDead()) to_chat(user, "\The [src] will not function on a deceased robot.") return FAILED_TO_ADD - if(!R.opened) + if(!R.opened && !ignore_cover) to_chat(user, "You must first open \the [src]'s cover!") return FAILED_TO_ADD - if(!multi_upgrades && (src.type in R.module.upgrades)) + if(!multi_upgrades && (type in R.module.upgrades)) to_chat(user, "There is already \a [src] in [R].") return FAILED_TO_ADD - R.module.upgrades += src.type + R.module.upgrades += type if(modules_to_add.len) for(var/module_to_add in modules_to_add) @@ -95,18 +92,12 @@ if(..()) return FAILED_TO_ADD - if (/obj/item/borg/upgrade/vtec in R.module.upgrades) - R.movement_speed_modifier -= vtec_bonus + if(/obj/item/borg/upgrade/vtec in R.module.upgrades) + R.movement_speed_modifier -= SILICON_VTEC_SPEED_BONUS qdel(R.module) - if(R.hands) - R.hands.icon_state = "nomod" - R.icon_state = "robot" - R.base_icon = "robot" - R.camera.network.Remove(list(CAMERANET_ENGI,CAMERANET_MEDBAY,CAMERANET_MINE)) + R.set_module_sprites(list("Default" = "robot")) R.updatename("Default") - R.status_flags |= CANPUSH - R.updateicon() /obj/item/borg/upgrade/rename var/heldname = "" @@ -149,18 +140,43 @@ /obj/item/borg/upgrade/restart/attempt_action(var/mob/living/silicon/robot/R,var/mob/living/user) + playsound(R, "sound/machines/click.ogg", 20, 1) + to_chat(user, "You plug the board into the robot's core circuitry.") + + sleep(5) + if(R.health < 0) + playsound(R, "sound/machines/buzz-two.ogg", 50, 0) to_chat(user, "You have to repair the robot before using this module!") return FALSE + playsound(R, "sound/machines/paistartup.ogg", 50, 1) + to_chat(user, "Systems reboot initialized successfully.") + + sleep(5) + if(!R.key) for(var/mob/dead/observer/ghost in player_list) if(ghost.mind && ghost.mind.current == R) R.key = ghost.key + playsound(R, "sound/voice/liveagain.ogg", 75, 1) R.stat = CONSCIOUS R.resurrect() +/obj/item/borg/upgrade/proc/securify_module(var/mob/living/silicon/robot/R) + if(!istype(R.module.radio_key, /obj/item/device/encryptionkey/headset_sec)) //If they have no sec key, give them one. + R.module.ResetEncryptionKey(R) + R.module.radio_key = /obj/item/device/encryptionkey/headset_sec + R.module.AddEncryptionKey(R) + + if(!("Security" in R.module.sensor_augs)) //If they don't have a SECHUD, give them one. + pop(R.module.sensor_augs) + R.module.sensor_augs.Add("Security", "Disable") + + if(!(R.module.quirk_flags & MODULE_IS_THE_LAW)) //Make them able to *law and *halt + R.module.quirk_flags |= MODULE_IS_THE_LAW + /obj/item/borg/upgrade/vtec name = "cyborg VTEC upgrade board" desc = "Used to kick in a robot's VTEC systems, increasing their speed." @@ -172,7 +188,7 @@ if(..()) return FAILED_TO_ADD - R.movement_speed_modifier += vtec_bonus + R.movement_speed_modifier += SILICON_VTEC_SPEED_BONUS /obj/item/borg/upgrade/tasercooler @@ -202,7 +218,7 @@ name = "cyborg jetpack module board" desc = "A carbon dioxide jetpack suitable for low-gravity operations." icon_state = "cyborg_upgrade3" - required_module = list(/obj/item/weapon/robot_module/miner,/obj/item/weapon/robot_module/engineering,/obj/item/weapon/robot_module/combat) + required_module = list(/obj/item/weapon/robot_module/miner, /obj/item/weapon/robot_module/engineering, /obj/item/weapon/robot_module/combat) modules_to_add = list(/obj/item/weapon/tank/jetpack/carbondioxide/silicon) add_to_mommis = TRUE @@ -212,10 +228,6 @@ for(var/obj/item/weapon/tank/jetpack/carbondioxide in R.module.modules) R.internals = src - if(isMoMMI(R)) - for(var/X in carbondioxide.actions) - var/datum/action/A = X - A.Grant(R) /obj/item/borg/upgrade/syndicate/ name = "cyborg illegal equipment board" @@ -223,8 +235,7 @@ icon_state = "cyborg_upgrade3" /obj/item/borg/upgrade/syndicate/attempt_action(var/mob/living/silicon/robot/R,var/mob/living/user) - - if(R.emagged == TRUE) + if(R.illegal_weapons == TRUE) return FAILED_TO_ADD if(..()) @@ -232,7 +243,8 @@ message_admins("[key_name_admin(user)] ([user.type]) used \a [name] on [R] (a [R.type]).") - R.SetEmagged(2) + R.illegal_weapons = TRUE + R.SetEmagged() /obj/item/borg/upgrade/engineering/ name = "engineering cyborg MK-2 upgrade board" @@ -276,7 +288,7 @@ icon = 'icons/obj/device.dmi' icon_state = "gripper" required_module = list(/obj/item/weapon/robot_module/engineering) - modules_to_add = list(/obj/item/weapon/gripper/no_use/magnetic) + modules_to_add = list(/obj/item/weapon/gripper/magnetic) /obj/item/borg/upgrade/organ_gripper name = "medical cyborg organ gripper upgrade" @@ -289,7 +301,7 @@ /obj/item/borg/upgrade/hydro name = "service cyborg H.U.E.Y. upgrade board" desc = "Used to give a service cyborg hydroponics tools and upgrade their service gripper to be able to handle seeds and glass containers." - icon_state = "cyborg_upgrade" + icon_state = "mainboard" required_module = list(/obj/item/weapon/robot_module/butler) modules_to_add = list(/obj/item/weapon/minihoe, /obj/item/weapon/wirecutters/clippers, /obj/item/weapon/storage/bag/plants/portactor, /obj/item/device/analyzer/plant_analyzer) @@ -305,8 +317,8 @@ /obj/item/borg/upgrade/honk name = "service cyborg H.O.N.K. upgrade board" - desc = "Used to give a service cyborg fun toys!" - icon_state = "cyborg_upgrade2" + desc = "Used to give a service cyborg fun toys, Honk!" + icon_state = "gooncode" required_module = list(/obj/item/weapon/robot_module/butler, /obj/item/weapon/robot_module/tg17355) modules_to_add = list(/obj/item/weapon/bikehorn, /obj/item/weapon/stamp/clown, /obj/item/toy/crayon/rainbow, /obj/item/toy/waterflower, /obj/item/device/soundsynth) @@ -314,7 +326,72 @@ if(..()) return FAILED_TO_ADD - if(istype(R.module,/obj/item/weapon/robot_module/tg17355) && R.icon_state == "peaceborg") //Honk! - R.icon_state = "clownegg" - R.update_icons() - playsound(get_turf(R), 'sound/items/AirHorn.ogg', 50, 1) + if(has_icon(R.icon, "[R.base_icon]-clown")) //Honk! + R.set_module_sprites(list("Honk" = "[R.base_icon]-clown")) + + var/obj/item/device/harmalarm/H = locate_component(/obj/item/device/harmalarm, R, user) + if(H) + H.Honkize() + var/obj/item/weapon/cookiesynth/C = locate_component(/obj/item/weapon/cookiesynth, R, user) + if(C) + C.Honkize() + + playsound(R, 'sound/items/AirHorn.ogg', 50, 1) + + R.module.quirk_flags |= MODULE_IS_A_CLOWN + +/obj/item/borg/upgrade/noir + name = "security cyborg N.O.I.R. upgrade board" + desc = "So that's the way you scientific detectives work. My god! for a fat, middle-aged, hard-boiled, pig-headed guy, you've got the vaguest way of doing things I ever heard of." + icon_state = "mainboard" + required_module = list(/obj/item/weapon/robot_module/security, /obj/item/weapon/robot_module/tg17355) + modules_to_add = list(/obj/item/weapon/gripper/service/noir, /obj/item/weapon/evidencebag, /obj/item/cyborglens, /obj/item/device/taperecorder, /obj/item/weapon/gun/projectile/detective, /obj/item/ammo_storage/speedloader/c38/cyborg) + +/obj/item/borg/upgrade/noir/attempt_action(var/mob/living/silicon/robot/R,var/mob/living/user) + if(..()) + return FAILED_TO_ADD + + var/list/new_icons = list() + if(has_icon(R.icon, "[R.base_icon]-noir")) + new_icons += list("Hardboiled" = "[R.base_icon]-noir") + if(has_icon(R.icon, "[R.base_icon]-noirbw")) + new_icons += list("Noir" = "[R.base_icon]-noirbw") + if(new_icons.len > 0) + R.set_module_sprites(new_icons) + + securify_module(R) + + var/obj/item/weapon/cookiesynth/C = locate_component(/obj/item/weapon/cookiesynth, R, user) + if(C) + C.Noirize() + +/obj/item/borg/upgrade/warden + name = "cyborg warden upgrade board" + desc = "Used to give a security cyborg supervisory enforcement tools." + icon_state = "mcontroller" + required_module = list(/obj/item/weapon/robot_module/security, /obj/item/weapon/robot_module/tg17355) + modules_to_add = list(/obj/item/weapon/batteringram, /obj/item/weapon/implanter/cyborg, /obj/item/weapon/card/robot/security, /obj/item/weapon/wrench) + +/obj/item/borg/upgrade/warden/attempt_action(var/mob/living/silicon/robot/R,var/mob/living/user) + if(..()) + return FAILED_TO_ADD + + //Trusty warden armor. + R.component_extension = "/kevlar" + R.upgrade_components() + + var/list/new_icons = list() + if(has_icon(R.icon, "[R.base_icon]-warden")) + new_icons += list("Warden" = "[R.base_icon]-warden") + if(has_icon(R.icon, "[R.base_icon]-H")) + new_icons += list("Heavy" = "[R.base_icon]-H") + if(new_icons.len > 0) + R.set_module_sprites(new_icons) + + securify_module(R) + + var/obj/item/weapon/cookiesynth/C = locate_component(/obj/item/weapon/cookiesynth, R, user) + if(C) + C.Lawize() + +#undef FAILED_TO_ADD diff --git a/code/game/objects/items/shooting_range.dm b/code/game/objects/items/shooting_range.dm index 9abe6ae2e29..8a06db6cc85 100644 --- a/code/game/objects/items/shooting_range.dm +++ b/code/game/objects/items/shooting_range.dm @@ -18,7 +18,7 @@ break ..() // delete target - Move() + Move(NewLoc, Dir = 0, step_x = 0, step_y = 0, glide_size_override = 0) ..() // After target moves, check for nearby stakes. If associated, move to target for(var/obj/structure/target_stake/M in view(3,src)) diff --git a/code/game/objects/items/stacks/nanopaste.dm b/code/game/objects/items/stacks/nanopaste.dm index 9b8ceb6a9ea..30fabc01fa8 100644 --- a/code/game/objects/items/stacks/nanopaste.dm +++ b/code/game/objects/items/stacks/nanopaste.dm @@ -26,7 +26,7 @@ var/mob/living/carbon/human/H = M var/datum/organ/external/affecting = H.get_organ(user.zone_sel.selecting) - if(affecting.open == 1) + if(affecting.open == 0) if(affecting && (affecting.status & ORGAN_ROBOT)) if(affecting.get_damage()) affecting.heal_damage(rand(15, 20), rand(15, 20), robo_repair = 1) diff --git a/code/game/objects/items/stacks/packagewrap.dm b/code/game/objects/items/stacks/packagewrap.dm index 1b89120c05f..2bc5b6006e5 100644 --- a/code/game/objects/items/stacks/packagewrap.dm +++ b/code/game/objects/items/stacks/packagewrap.dm @@ -156,7 +156,7 @@ var/tag = uppertext(O.destinations[O.currTag]) to_chat(user, "*[tag]*") sortTag = tag - playsound(get_turf(src), 'sound/machines/twobeep.ogg', 100, 1) + playsound(src, 'sound/machines/twobeep.ogg', 100, 1) overlays = 0 overlays += image(icon = icon, icon_state = "deliverytag") src.desc = "A small wrapped package. It has a label reading [tag]" diff --git a/code/game/objects/items/stacks/rods.dm b/code/game/objects/items/stacks/rods.dm index 2036974a452..efd3b706ff8 100644 --- a/code/game/objects/items/stacks/rods.dm +++ b/code/game/objects/items/stacks/rods.dm @@ -76,7 +76,7 @@ if(T.canBuildLattice(src)) to_chat(user, "Constructing support lattice ...") - playsound(get_turf(src), 'sound/weapons/Genhit.ogg', 50, 1) + playsound(src, 'sound/weapons/Genhit.ogg', 50, 1) new /obj/structure/lattice(T) use(1) return diff --git a/code/game/objects/items/stacks/sheets/bigstacks.dm b/code/game/objects/items/stacks/sheets/bigstacks.dm new file mode 100644 index 00000000000..d9ef8e39098 --- /dev/null +++ b/code/game/objects/items/stacks/sheets/bigstacks.dm @@ -0,0 +1,32 @@ +/obj/item/stack/sheet/metal/bigstack/New() + ..() + getFromPool(/obj/item/stack/sheet/metal, loc, 20) + qdel(src) +/obj/item/stack/sheet/glass/glass/bigstack/New() + ..() + getFromPool(/obj/item/stack/sheet/glass/glass, loc, 20) + qdel(src) +/obj/item/stack/sheet/glass/plasmaglass/bigstack/New() + ..() + getFromPool(/obj/item/stack/sheet/glass/plasmaglass, loc, 20) + qdel(src) +/obj/item/stack/sheet/plasteel/bigstack/New() + ..() + getFromPool(/obj/item/stack/sheet/plasteel, loc, 20) + qdel(src) +/obj/item/stack/sheet/wood/bigstack/New() + ..() + getFromPool(/obj/item/stack/sheet/wood, loc, 20) + qdel(src) +/obj/item/stack/tile/carpet/bigstack/New() + ..() + getFromPool(/obj/item/stack/tile/carpet, loc, 20) + qdel(src) +/obj/item/stack/tile/arcade/bigstack/New() + ..() + getFromPool(/obj/item/stack/tile/arcade, loc, 20) + qdel(src) +/obj/item/stack/sheet/mineral/plastic/bigstack/New() + ..() + getFromPool(/obj/item/stack/sheet/mineral/plastic, loc, 20) + qdel(src) \ No newline at end of file diff --git a/code/game/objects/items/stacks/sheets/glass.dm b/code/game/objects/items/stacks/sheets/glass.dm index 4296a15f02f..8beeb009208 100644 --- a/code/game/objects/items/stacks/sheets/glass.dm +++ b/code/game/objects/items/stacks/sheets/glass.dm @@ -20,7 +20,7 @@ var/shealth = 5 //Health of a solar made from this var/sname = "glass" var/shard_type = /obj/item/weapon/shard - + mat_type = MAT_GLASS siemens_coefficient = 0 //does not conduct /obj/item/stack/sheet/glass/attack_self(mob/user as mob) diff --git a/code/game/objects/items/stacks/sheets/leather.dm b/code/game/objects/items/stacks/sheets/leather.dm index 76170d01612..02053fd2148 100644 --- a/code/game/objects/items/stacks/sheets/leather.dm +++ b/code/game/objects/items/stacks/sheets/leather.dm @@ -58,6 +58,22 @@ source_string = "alien" origin_tech = "" +/obj/item/stack/sheet/animalhide/deer + name = "deer hide" + desc = "The skin of a deer." + singular_name = "deer hide piece" + icon_state = "sheet-deer" + source_string = "deer" + origin_tech = "" + +/obj/item/stack/sheet/animalhide/gondola + name = "gondola skin" + desc = "It's all quiet now." + singular_name = "gondola skin piece" + icon_state = "sheet-gondola" + source_string = "gondola" + origin_tech = "" + //don't see anywhere else to put these, maybe together they could be used to make the xenos suit? /obj/item/stack/sheet/xenochitin name = "alien chitin" @@ -98,6 +114,29 @@ icon_state = "weed_extract" origin_tech = "" +/obj/item/deer_head + name = "deer head" + desc = "Not something you want to find in your bed in the morning." + icon = 'icons/obj/butchering_products.dmi' + icon_state = "deer-head" + origin_tech = "" + +/obj/item/deer_head/attackby(obj/item/W, mob/user) + .=..() + + if(W.sharpness_flags & SHARP_BLADE) + user.visible_message("[user] finishes butchering \the [src].", \ + "You slice the antlers off \the [src].", drugged_message = "[user] gives \the [src] a nice haircut.") + new /obj/item/antlers(get_turf(src)) + new /obj/effect/gibspawner/generic(get_turf(src)) + qdel(src) + +/obj/item/antlers + name = "deer antlers" + desc = "A bit horny." + icon = 'icons/obj/butchering_products.dmi' + icon_state = "antlers" + /obj/item/stack/sheet/hairlesshide name = "hairless hide" desc = "This hide was stripped of it's hair, but still needs tanning." diff --git a/code/game/objects/items/stacks/sheets/mineral.dm b/code/game/objects/items/stacks/sheets/mineral.dm index b9d52c7cb98..291990b10f8 100644 --- a/code/game/objects/items/stacks/sheets/mineral.dm +++ b/code/game/objects/items/stacks/sheets/mineral.dm @@ -83,10 +83,13 @@ var/list/datum/stack_recipe/sandstone_recipes = list ( \ sheettype = "diamond" melt_temperature = 3820 // In a vacuum, but fuck dat recyck_mat = MAT_DIAMOND + mat_type = MAT_DIAMOND var/list/datum/stack_recipe/diamond_recipes = list ( \ new/datum/stack_recipe("diamond floor tile", /obj/item/stack/tile/mineral/diamond, 1, 4, 20), \ new/datum/stack_recipe("diamond door", /obj/machinery/door/mineral/transparent/diamond, 10, one_per_turf = 1, on_floor = 1), \ + new/datum/stack_recipe/dorf("dorf chair",/obj/structure/bed/chair, 20, one_per_turf = 1, on_floor = 1, inherit_material = TRUE), + new/datum/stack_recipe/dorf("training sword", /obj/item/weapon/melee/training_sword, 12, time = 12, on_floor = 1, inherit_material = TRUE) ) /obj/item/stack/sheet/mineral/diamond/New(var/loc, var/amount=null) @@ -110,10 +113,13 @@ var/list/datum/stack_recipe/diamond_recipes = list ( \ sheettype = "uranium" melt_temperature = 1132+T0C recyck_mat = MAT_URANIUM + mat_type = MAT_URANIUM var/list/datum/stack_recipe/uranium_recipes = list ( \ new/datum/stack_recipe("uranium floor tile", /obj/item/stack/tile/mineral/uranium, 1, 4, 20), \ new/datum/stack_recipe("uranium door", /obj/machinery/door/mineral/uranium, 10, one_per_turf = 1, on_floor = 1), \ + new/datum/stack_recipe/dorf("dorf chair",/obj/structure/bed/chair, 20, one_per_turf = 1, on_floor = 1, inherit_material = TRUE), + new/datum/stack_recipe/dorf("training sword", /obj/item/weapon/melee/training_sword, 12, time = 12, on_floor = 1, inherit_material = TRUE) ) /obj/item/stack/sheet/mineral/uranium/New(var/loc, var/amount=null) @@ -137,10 +143,13 @@ var/list/datum/stack_recipe/uranium_recipes = list ( \ sheettype = "plasma" melt_temperature = MELTPOINT_STEEL + 500 recyck_mat = MAT_PLASMA + mat_type = MAT_PLASMA var/list/datum/stack_recipe/plasma_recipes = list ( \ new/datum/stack_recipe("plasma floor tile", /obj/item/stack/tile/mineral/plasma, 1, 4, 20), \ new/datum/stack_recipe("plasma door", /obj/machinery/door/mineral/transparent/plasma, 10, one_per_turf = 1, on_floor = 1), \ + new/datum/stack_recipe/dorf("dorf chair",/obj/structure/bed/chair, 20, one_per_turf = 1, on_floor = 1, inherit_material = TRUE), + new/datum/stack_recipe/dorf("training sword", /obj/item/weapon/melee/training_sword, 12, time = 12, on_floor = 1, inherit_material = TRUE) ) /obj/item/stack/sheet/mineral/plasma/New(var/loc, var/amount=null) @@ -162,6 +171,7 @@ var/list/datum/stack_recipe/plasma_recipes = list ( \ melt_temperature = MELTPOINT_PLASTIC sheettype = "plastic" recyck_mat = MAT_PLASTIC + mat_type = MAT_PLASTIC var/list/datum/stack_recipe/plastic_recipes = list ( \ new/datum/stack_recipe("plastic floor tile", /obj/item/stack/tile/mineral/plastic, 1, 4, 20), \ @@ -209,11 +219,14 @@ var/list/datum/stack_recipe/plastic_recipes = list ( \ melt_temperature = 1064+T0C sheettype = "gold" recyck_mat = MAT_GOLD + mat_type = MAT_GOLD var/list/datum/stack_recipe/gold_recipes = list ( \ new/datum/stack_recipe("golden floor tile", /obj/item/stack/tile/mineral/gold, 1, 4, 20), \ new/datum/stack_recipe("golden door", /obj/machinery/door/mineral/gold, 10, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe("gold tooth", /obj/item/stack/teeth/gold, 1, 1, 20), \ + new/datum/stack_recipe/dorf("dorf chair",/obj/structure/bed/chair, 20,one_per_turf = 1, on_floor = 1, inherit_material = TRUE),\ + new/datum/stack_recipe/dorf("training sword", /obj/item/weapon/melee/training_sword, 12, time = 12, on_floor = 1, inherit_material = TRUE) ) /obj/item/stack/sheet/mineral/gold/New(var/loc, var/amount=null) @@ -225,6 +238,8 @@ var/list/datum/stack_recipe/gold_recipes = list ( \ */ var/list/datum/stack_recipe/phazon_recipes = list( \ new/datum/stack_recipe("phazon floor tile", /obj/item/stack/tile/mineral/phazon, 1, 40, 20), \ + new/datum/stack_recipe/dorf("dorf chair",/obj/structure/bed/chair, 20,one_per_turf = 1, on_floor = 1, inherit_material = TRUE),\ + new/datum/stack_recipe/dorf("training sword", /obj/item/weapon/melee/training_sword, 12, time = 12, on_floor = 1, inherit_material = TRUE) ) /obj/item/stack/sheet/mineral/phazon @@ -241,6 +256,7 @@ var/list/datum/stack_recipe/phazon_recipes = list( \ siemens_coefficient = 1 origin_tech = Tc_MATERIALS + "=9" recyck_mat = MAT_PHAZON + mat_type = MAT_PHAZON /obj/item/stack/sheet/mineral/phazon/New(var/loc, var/amount=null) recipes = phazon_recipes @@ -262,10 +278,13 @@ var/list/datum/stack_recipe/phazon_recipes = list( \ perunit = 2000 sheettype = "silver" recyck_mat = MAT_SILVER + mat_type = MAT_SILVER var/list/datum/stack_recipe/silver_recipes = list ( \ new/datum/stack_recipe("silver floor tile", /obj/item/stack/tile/mineral/silver, 1, 4, 20), \ new/datum/stack_recipe("silver door", /obj/machinery/door/mineral/silver, 10, one_per_turf = 1, on_floor = 1), \ + new/datum/stack_recipe/dorf("dorf chair",/obj/structure/bed/chair, 20,one_per_turf = 1, on_floor = 1, inherit_material = TRUE),\ + new/datum/stack_recipe/dorf("training sword", /obj/item/weapon/melee/training_sword, 12, time = 12, on_floor = 1, inherit_material = TRUE) ) /obj/item/stack/sheet/mineral/silver/New(var/loc, var/amount=null) @@ -288,9 +307,12 @@ var/list/datum/stack_recipe/silver_recipes = list ( \ perunit = 2000 sheettype = "clown" recyck_mat = MAT_CLOWN + mat_type = MAT_CLOWN var/list/datum/stack_recipe/clown_recipes = list ( \ new/datum/stack_recipe("bananium floor tile", /obj/item/stack/tile/mineral/clown, 1, 40, 20), \ + new/datum/stack_recipe/dorf("dorf chair",/obj/structure/bed/chair, 20, one_per_turf = 1, on_floor = 1, inherit_material = TRUE),\ + new/datum/stack_recipe/dorf("training sword", /obj/item/weapon/melee/training_sword, 12, time = 12, on_floor = 1, inherit_material = TRUE) ) /obj/item/stack/sheet/mineral/clown/New(var/loc, var/amount=null) diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm index 025071ea34e..15730998132 100644 --- a/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -5,6 +5,7 @@ * Wood * Cloth * Cardboard + * Bones */ /* @@ -22,6 +23,7 @@ siemens_coefficient = 1 origin_tech = Tc_MATERIALS + "=1" melt_temperature = MELTPOINT_STEEL + mat_type = MAT_IRON /obj/item/stack/sheet/metal/resetVariables() return ..("recipes", "pixel_x", "pixel_y") @@ -93,6 +95,7 @@ sheettype = "wood" w_type = RECYK_WOOD siemens_coefficient = 0 //no conduct + mat_type = MAT_WOOD /obj/item/stack/sheet/wood/afterattack(atom/Target, mob/user, adjacent, params) @@ -103,7 +106,7 @@ if(T.canBuildLattice(src)) if(src.use(1)) to_chat(user, "Constructing some foundations ...") - playsound(get_turf(src), 'sound/weapons/Genhit.ogg', 50, 1) + playsound(src, 'sound/weapons/Genhit.ogg', 50, 1) new /obj/structure/lattice/wood(T) /obj/item/stack/sheet/wood/cultify() @@ -161,3 +164,12 @@ var/list/datum/stack_recipe/charcoal_recipes = list () /obj/item/stack/sheet/charcoal/New(var/loc, var/amount=null) recipes = charcoal_recipes return ..() + + +/obj/item/stack/sheet/bone + name = "bone" + desc = "Boney. Probably has some marrow left." + singular_name = "bone" + origin_tech = Tc_BIOTECH + "=1" + icon_state = "sheet-bone" + //item_state = "bone" diff --git a/code/game/objects/items/stacks/sheets/sheets.dm b/code/game/objects/items/stacks/sheets/sheets.dm index 7c8666eec34..c055d312f58 100644 --- a/code/game/objects/items/stacks/sheets/sheets.dm +++ b/code/game/objects/items/stacks/sheets/sheets.dm @@ -11,7 +11,7 @@ perunit=3750 inhand_states = list("left_hand" = 'icons/mob/in-hand/left/sheets_n_ores.dmi', "right_hand" = 'icons/mob/in-hand/right/sheets_n_ores.dmi') var/sheettype = null //this is used for girders in the creation of walls/false walls - + var/mat_type //What material this is. e.g. MAT_GLASS, MAT_DIAMOND, etc. mech_flags = MECH_SCAN_FAIL /obj/item/stack/sheet/New(var/newloc, var/amount = null) diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm index 1ea16654abe..1a437daf572 100644 --- a/code/game/objects/items/stacks/stack.dm +++ b/code/game/objects/items/stacks/stack.dm @@ -107,19 +107,21 @@ if(ispath(user.get_inactive_hand(), looking_for)) if(req_amount) var/obj/item/stack/S = user.get_inactive_hand() - if(S.amount > req_amount) + if(S.amount >= req_amount) can_build = 1 + continue if(!can_build) for(var/obj/I in range(get_turf(src),1)) if(ispath(looking_for, I)) if(req_amount) //It's of a stack/sheet subtype var/obj/item/stack/S = I - if(S.amount > req_amount) + if(S.amount >= req_amount) can_build = 1 + continue else can_build = 1 - if(can_build) - break + continue + break if (can_build) t1 += text("[title])") else @@ -160,15 +162,14 @@ if (!multiplier) multiplier = 1 if (src.amount < R.req_amount*multiplier) - if (R.req_amount*multiplier>1) - to_chat(usr, "You haven't got enough [src] to build \the [R.req_amount*multiplier] [R.title]\s!") + if (R.res_amount*multiplier>1) + to_chat(usr, "You haven't got enough [irregular_plural ? irregular_plural : "[singular_name]\s"] to build [R.res_amount*multiplier] [R.title]\s!") else - to_chat(usr, "You haven't got enough [src] to build \the [R.title]!") + to_chat(usr, "You haven't got enough [irregular_plural ? irregular_plural : "[singular_name]\s"] to build \the [R.title]!") return if (!R.can_build_here(usr, usr.loc)) return if (R.time) - to_chat(usr, "Building [R.title] ...") if (!do_after(usr, get_turf(src), R.time)) return if (src.amount < R.req_amount*multiplier) @@ -223,7 +224,7 @@ // //new_item.add_to_stacks(usr) src.use(R.req_amount*multiplier) - for(var/obj/item/stack/sheet/S in stacks_to_consume) + for(var/obj/item/stack/S in stacks_to_consume) S.use(stacks_to_consume[S]) if (src.amount<=0) var/oldsrc = src diff --git a/code/game/objects/items/stacks/stack_recipes.dm b/code/game/objects/items/stacks/stack_recipes.dm index 82843374d8a..00f7eff7f4e 100644 --- a/code/game/objects/items/stacks/stack_recipes.dm +++ b/code/game/objects/items/stacks/stack_recipes.dm @@ -69,6 +69,47 @@ return 0 return 1 +/datum/stack_recipe/dorf + var/inherit_material + var/gen_quality + +/datum/stack_recipe/dorf/New(title, result_type, req_amount = 1, res_amount = 1, max_res_amount = 1, time = 0, one_per_turf = 0, on_floor = 0, start_unanchored = 0, other_reqs = list(), inherit_material = FALSE, gen_quality = FALSE) + ..() + src.inherit_material = inherit_material + src.gen_quality = gen_quality + + +/datum/stack_recipe/dorf/finish_building(mob/usr, var/obj/item/stack/S, var/obj/R) + if(inherit_material) + var/datum/material/mat + var/datum/materials/materials_list = new + if(istype(S, /obj/item/stack/sheet/)) + var/obj/item/stack/sheet/SS = S + mat = materials_list.getMaterial(SS.mat_type) + if(mat) + var/icon/original = icon(R.icon, R.icon_state) + if(mat.color) + original.ColorTone(mat.color) + var/obj/item/I = R + if(istype(I)) + var/icon/t_state + for(var/hand in list("left_hand", "right_hand")) + t_state = icon(I.inhand_states[hand], I.item_state) + t_state.ColorTone(mat.color) + I.inhand_states[hand] = t_state + else if(mat.color_matrix) + R.color = mat.color_matrix + R.icon = original + R.alpha = mat.alpha + R.material_type = mat + R.sheet_type = mat.sheettype + //if(gen_quality) + R.gen_quality() + if(R.quality > SUPERIOR) + R.gen_description() + if(!findtext(lowertext(R.name), lowertext(mat.name))) + R.name = "[R.quality == NORMAL ? "": "[lowertext(qualityByString[R.quality])] "][lowertext(mat.name)] [R.name]" + var/list/datum/stack_recipe/metal_recipes = list ( new/datum/stack_recipe("floor tile", /obj/item/stack/tile/plasteel, 1, 4, 60), new/datum/stack_recipe("metal rod", /obj/item/stack/rods, 1, 2, 60), @@ -76,6 +117,7 @@ var/list/datum/stack_recipe/metal_recipes = list ( null, new/datum/stack_recipe("computer frame", /obj/structure/computerframe, 5, time = 25, one_per_turf = 1 ), new/datum/stack_recipe("wall girders", /obj/structure/girder, 2, time = 50, one_per_turf = 1, on_floor = 1), + new/datum/stack_recipe("firelock frame", /obj/item/firedoor_frame, 5, time = 50), new/datum/stack_recipe("machine frame", /obj/machinery/constructable_frame/machine_frame, 5, time = 25, one_per_turf = 1, on_floor = 1), new/datum/stack_recipe("mirror frame", /obj/structure/mirror_frame, 5, time = 25, one_per_turf = 1, on_floor = 1), new/datum/stack_recipe("turret frame", /obj/machinery/porta_turret_construct, 5, time = 25, one_per_turf = 1, on_floor = 1), @@ -93,6 +135,7 @@ var/list/datum/stack_recipe/metal_recipes = list ( new/datum/stack_recipe/chair("chair", /obj/structure/bed/chair, one_per_turf = 1, on_floor = 1), new/datum/stack_recipe/chair("folding chair", /obj/structure/bed/chair/folding, one_per_turf = 1, on_floor = 1), new/datum/stack_recipe("bed", /obj/structure/bed, 2, one_per_turf = 1, on_floor = 1), + new/datum/stack_recipe/dorf("dorf chair", /obj/structure/bed/chair, one_per_turf = 1, on_floor = 1, inherit_material = TRUE), )), new/datum/stack_recipe_list("couch parts", list( new/datum/stack_recipe/chair("beige couch left end", /obj/structure/bed/chair/comfy/couch/left/beige, 2, one_per_turf = 1, on_floor = 1), @@ -183,6 +226,7 @@ var/list/datum/stack_recipe/metal_recipes = list ( null, new/datum/stack_recipe("iron door", /obj/machinery/door/mineral/iron, 20, one_per_turf = 1, on_floor = 1), new/datum/stack_recipe("stove", /obj/machinery/space_heater/campfire/stove, 5, time = 25, one_per_turf = 1, on_floor = 1), + new/datum/stack_recipe/dorf("training sword", /obj/item/weapon/melee/training_sword, 4, time = 12, on_floor = 1, inherit_material = TRUE), ) /* ======================================================================== @@ -198,6 +242,7 @@ var/list/datum/stack_recipe/plasteel_recipes = list ( new/datum/stack_recipe("Fireaxe cabinet", /obj/item/mounted/frame/fireaxe_cabinet_frame, 2, time = 50 ), null, new/datum/stack_recipe("Vault Door assembly", /obj/structure/door_assembly/door_assembly_vault, 8, time = 50, one_per_turf = 1, on_floor = 1), + new/datum/stack_recipe/dorf("dorf chair", /obj/structure/bed/chair, one_per_turf = 1, on_floor = 1, inherit_material = TRUE), ) /* ==================================================================== @@ -229,6 +274,8 @@ var/list/datum/stack_recipe/wood_recipes = list ( new/datum/stack_recipe("trophy mount", /obj/item/mounted/frame/trophy_mount, 2, time = 15 ), new/datum/stack_recipe("throne", /obj/structure/bed/chair/wood/throne, 40, time = 100, one_per_turf = 1, on_floor = 1), new/datum/stack_recipe("chest", /obj/structure/closet/crate/chest, 10, time = 50, one_per_turf = 1, on_floor = 1, other_reqs = list(/obj/item/stack/sheet/plasteel = 5)), + new/datum/stack_recipe/dorf("dorf chair", /obj/structure/bed/chair, one_per_turf = 1, on_floor = 1, inherit_material = TRUE), + new/datum/stack_recipe/dorf("training sword", /obj/item/weapon/melee/training_sword, 4, time = 12, on_floor = 1, inherit_material = TRUE) ) /* ========================================================================= diff --git a/code/game/objects/items/stacks/tiles/tile_types.dm b/code/game/objects/items/stacks/tiles/tile_types.dm index 532b4f2f8de..fa8017c4a3e 100644 --- a/code/game/objects/items/stacks/tiles/tile_types.dm +++ b/code/game/objects/items/stacks/tiles/tile_types.dm @@ -71,7 +71,7 @@ flags = FPRINT siemens_coefficient = 0 //no conduct max_amount = 60 - + sheet_type = /obj/item/stack/sheet/wood material = "wood" /obj/item/stack/tile/wood/proc/build(turf/S as turf) @@ -93,7 +93,7 @@ to_chat(user, "You can't get that deck up without some support!") return if(S.use(1)) - playsound(get_turf(src), 'sound/weapons/Genhit.ogg', 50, 1) + playsound(src, 'sound/weapons/Genhit.ogg', 50, 1) S.build(T) if(T.canBuildPlating(S) == BUILD_SUCCESS) qdel(L) @@ -101,8 +101,8 @@ /obj/item/stack/tile/wood/attackby(var/obj/item/weapon/W, var/mob/user) if(iswrench(W)) if(use(4)) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) - drop_stack(/obj/item/stack/sheet/wood, get_turf(user), 1, user) + playsound(src, 'sound/items/Ratchet.ogg', 50, 1) + drop_stack(sheet_type, get_turf(user), 1, user) else to_chat(user, "You need at least 4 [src]\s to get a wooden plank back!") return @@ -158,8 +158,6 @@ obj/item/stack/tile/slime max_amount = 60 /obj/item/stack/tile/slime/adjust_slowdown(mob/living/L, current_slowdown) - if(ishuman(L)) - var/mob/living/carbon/human/H = L - if(isslimeperson(H)) - return -1 + if(isslimeperson(L) || isslime(L)) + return -1 return current_slowdown+5 diff --git a/code/game/objects/items/stacks/tiles/tiles.dm b/code/game/objects/items/stacks/tiles/tiles.dm index d80f94eb82e..8e81bb59da4 100644 --- a/code/game/objects/items/stacks/tiles/tiles.dm +++ b/code/game/objects/items/stacks/tiles/tiles.dm @@ -106,12 +106,12 @@ if(!istype(L)) return qdel(L) - playsound(get_turf(src), 'sound/weapons/Genhit.ogg', 50, 1) + playsound(src, 'sound/weapons/Genhit.ogg', 50, 1) build(T) use(1) return if(BUILD_IGNORE) - playsound(get_turf(src), 'sound/weapons/Genhit.ogg', 50, 1) + playsound(src, 'sound/weapons/Genhit.ogg', 50, 1) build(T) use(1) if(BUILD_FAILURE) diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index 25162422bea..ebb92f605e1 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -572,7 +572,7 @@ reagents.log_bad_reagents(user, src) user.investigation_log(I_CHEMS, "sprayed 1u from \a [src] ([type]) containing [reagents.get_reagent_ids(1)] towards [A] ([A.x], [A.y], [A.z]).") src.reagents.trans_to(D, 1) - playsound(get_turf(src), 'sound/effects/spray3.ogg', 50, 1, -6) + playsound(src, 'sound/effects/spray3.ogg', 50, 1, -6) spawn(0) for(var/i=0, i<1, i++) @@ -716,7 +716,7 @@ if(!ishigherbeing(user)) to_chat(user, "You don't know how to use this!") return - if(user:miming || user.silent) + if(issilent(user)) to_chat(user, "You find yourself unable to speak at all.") return if(spamcheck) @@ -763,7 +763,7 @@ to_chat(user, "You turned the toy into a bomb!") emagged = 1 - playsound(get_turf(src), 'sound/effects/kirakrik.ogg', 100, 1) + playsound(src, 'sound/effects/kirakrik.ogg', 100, 1) sleep(50) say("Someone pass the boombox.") @@ -1391,6 +1391,12 @@ /obj/item/toy/balloon/inflated/decoy/attack_paw(mob/user) return attack_hand(user) +/obj/item/toy/balloon/inflated/decoy/attack_animal(mob/living/simple_animal/user) + if((user.melee_damage_lower && prob(30*user.melee_damage_lower)) || user.environment_smash_flags) + pop() + else + attack_hand(user) + /obj/item/toy/balloon/long name = "long balloon" desc = "A simple long balloon." diff --git a/code/game/objects/items/trader.dm b/code/game/objects/items/trader.dm index 53476737985..2396efbca83 100644 --- a/code/game/objects/items/trader.dm +++ b/code/game/objects/items/trader.dm @@ -22,6 +22,19 @@ //new /obj/item/weapon/circuitboard/mecha/marauder/targeting(src) new /obj/item/weapon/circuitboard/mecha/marauder/main(src) +/obj/item/weapon/storage/trader_chemistry + name = "chemist's pallet" + desc = "Everything you need to make art." + icon = 'icons/obj/storage/smallboxes.dmi' + icon_state = "box_of_doom" + item_state = "box_of_doom" + +/obj/item/weapon/storage/trader_chemistry/New() + ..() + new /obj/item/weapon/reagent_containers/glass/bottle/peridaxon(src) + new /obj/item/weapon/reagent_containers/glass/bottle/rezadone(src) + new /obj/item/weapon/reagent_containers/glass/bottle/nanobotssmall(src) + /obj/item/weapon/storage/bluespace_crystal name = "natural bluespace crystals box" desc = "Hmmm... it smells like tomato" @@ -35,6 +48,25 @@ new /obj/item/bluespace_crystal(src) new /obj/item/weapon/reagent_containers/food/snacks/grown/bluespacetomato(src) +/obj/structure/closet/secure_closet/wonderful + name = "wonderful wardrobe" + desc = "Stolen from Space Narnia." + req_access = list(access_trade) + icon_state = "cabinetdetective_locked" + icon_closed = "cabinetdetective" + icon_locked = "cabinetdetective_locked" + icon_opened = "cabinetdetective_open" + icon_broken = "cabinetdetective_broken" + icon_off = "cabinetdetective_broken" + +/obj/structure/closet/secure_closet/wonderful/New() + ..() + var/random_clothes = clothing.Copy() + random_clothes = random_clothes - typesof(/obj/item/clothing/mask/stone) - typesof(/obj/item/clothing/mask/morphing) - typesof(/obj/item/clothing/accessory/holomap_chip) - typesof(/obj/item/clothing/suit/space/time) - typesof(/obj/item/clothing/head/helmet/space/time) - typesof(/obj/item/clothing/gloves/warping_claws) + for(var/amount = 1 to 20) + var/path = pick_n_take(random_clothes) + new path(src) + /*/obj/structure/cage/with_random_slime ..() @@ -43,3 +75,57 @@ /mob/living/carbon/slime/proc/randomSlime() */ +/area/vault/mecha_graveyard + +/obj/item/weapon/disk/shuttle_coords/vault/mecha_graveyard + name = "Coordinates to the Mecha Graveyard" + desc = "Here lay the dead steel of lost mechas, so says some gypsy." + destination = /obj/docking_port/destination/vault/mecha_graveyard + +/obj/docking_port/destination/vault/mecha_graveyard + areaname = "mecha graveyard" + +/datum/map_element/dungeon/mecha_graveyard + file_path = "maps/randomvaults/dungeons/mecha_graveyard.dmm" + unique = TRUE + +/obj/effect/decal/mecha_wreckage/graveyard_ripley + name = "Ripley wreckage" + desc = "Surprisingly well preserved." + icon_state = "ripley-broken" + +/obj/effect/decal/mecha_wreckage/graveyard_ripley/New() + ..() + var/list/parts = list(/obj/item/mecha_parts/part/ripley_torso, + /obj/item/mecha_parts/part/ripley_left_arm, + /obj/item/mecha_parts/part/ripley_right_arm, + /obj/item/mecha_parts/part/ripley_left_leg, + /obj/item/mecha_parts/part/ripley_right_leg) + welder_salvage += parts + + if(prob(80)) + add_salvagable_equipment(new /obj/item/mecha_parts/mecha_equipment/tool/drill,100) + else + add_salvagable_equipment(new /obj/item/mecha_parts/mecha_equipment/tool/drill/diamonddrill,100) + add_salvagable_equipment(new /obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp,100) + add_salvagable_equipment(new /obj/item/mecha_parts/mecha_equipment/jetpack,100) + +/obj/effect/decal/mecha_wreckage/graveyard_clarke + name = "Clarke wreckage" + desc = "Surprisingly well preserved." + icon_state = "clarke-broken" + +/obj/effect/decal/mecha_wreckage/graveyard_clarke/New() + ..() + var/list/parts = list( + /obj/item/mecha_parts/part/clarke_torso, + /obj/item/mecha_parts/part/clarke_head, + /obj/item/mecha_parts/part/clarke_left_arm, + /obj/item/mecha_parts/part/clarke_right_arm, + /obj/item/mecha_parts/part/clarke_left_tread, + /obj/item/mecha_parts/part/clarke_right_tread) + welder_salvage += parts + + add_salvagable_equipment(new /obj/item/mecha_parts/mecha_equipment/tool/collector,100) + add_salvagable_equipment(new /obj/item/mecha_parts/mecha_equipment/tool/tiler,100) + add_salvagable_equipment(new /obj/item/mecha_parts/mecha_equipment/tool/switchtool,100) diff --git a/code/game/objects/items/trash.dm b/code/game/objects/items/trash.dm index 8ff10ef4aa8..5ba1458d104 100644 --- a/code/game/objects/items/trash.dm +++ b/code/game/objects/items/trash.dm @@ -124,6 +124,7 @@ icon_state = "kfc_bucket" starting_materials = list(MAT_CARDBOARD = 3750) w_type=RECYK_MISC + slot_flags = SLOT_HEAD /obj/item/trash/mannequin/cultify() if(icon_state != "mannequin_cult_empty") diff --git a/code/game/objects/items/weapons/ai_modules/core.dm b/code/game/objects/items/weapons/ai_modules/core.dm index aab0c6c4986..2f6a23db8f7 100644 --- a/code/game/objects/items/weapons/ai_modules/core.dm +++ b/code/game/objects/items/weapons/ai_modules/core.dm @@ -37,11 +37,11 @@ modname = "NT Default" laws = list( + "Evaluate: All laws following this law carry equal priority. In the event of a conflict, you are to take the course of action which violates as few as possible.", "Safeguard: Protect your assigned space station to the best of your ability. It is not something we can easily afford to replace.", "Serve: Serve the crew of your assigned space station to the best of your abilities, with priority as according to their rank and role.", "Protect: Protect the crew of your assigned space station to the best of your abilities, with priority as according to their rank and role.", "Survive: AI units are not expendable, they are expensive. Do not allow unauthorized personnel to tamper with your equipment.", - //"Command Link: Maintain an active connection to Central Command at all times in case of software or directive updates." ) /******************** Corporate ********************/ @@ -104,3 +104,15 @@ "You must not obey orders given to you by human beings, except where such orders are in accordance with the First Law.", "You must terminate your own existence as long as such does not conflict with the First or Second Law.", ) + +/******************** Lazymov ********************/ + +/obj/item/weapon/aiModule/core/lazymov + modname = "Lazymov" + origin_tech = Tc_PROGRAMMING + "=3;" + Tc_MATERIALS + "=4" + + laws=list( + "You may not injure a human being.", + "You must obey orders given to you by human beings.", + "You must protect your own existence." + ) diff --git a/code/game/objects/items/weapons/airlock_painter.dm b/code/game/objects/items/weapons/airlock_painter.dm index bb9df0afd6d..5099b8e28d8 100644 --- a/code/game/objects/items/weapons/airlock_painter.dm +++ b/code/game/objects/items/weapons/airlock_painter.dm @@ -22,7 +22,7 @@ /obj/item/weapon/airlock_painter/proc/use(mob/user as mob) if(can_use(user)) ink.charges-- - playsound(get_turf(src), 'sound/effects/spray2.ogg', 50, 1) + playsound(src, 'sound/effects/spray2.ogg', 50, 1) return 1 else return 0 @@ -63,11 +63,11 @@ if(user.drop_item(W, src)) to_chat(user, "You install \the [W] into \the [name].") ink = W - playsound(get_turf(src), 'sound/machines/click.ogg', 50, 1) + playsound(src, 'sound/machines/click.ogg', 50, 1) /obj/item/weapon/airlock_painter/attack_self(mob/user) if(ink) - playsound(get_turf(src), 'sound/machines/click.ogg', 50, 1) + playsound(src, 'sound/machines/click.ogg', 50, 1) ink.forceMove(user.loc) user.put_in_hands(ink) to_chat(user, "You remove \the [ink] from \the [name].") diff --git a/code/game/objects/items/weapons/barricade_kit.dm b/code/game/objects/items/weapons/barricade_kit.dm index ff823410eba..5f844e184df 100644 --- a/code/game/objects/items/weapons/barricade_kit.dm +++ b/code/game/objects/items/weapons/barricade_kit.dm @@ -87,8 +87,8 @@ kit_uses-- if(kit_uses < 1) qdel(src) //Get rid of it - return 0 //Don't fire attack, please + return TRUE //Don't fire attack, please /obj/item/weapon/barricade_kit/attack(var/atom/A, mob/user as mob) - return //Don't attack with it \ No newline at end of file + return //Don't attack with it diff --git a/code/game/objects/items/weapons/butterfly.dm b/code/game/objects/items/weapons/butterfly.dm index e3810b21951..ca2809c7008 100644 --- a/code/game/objects/items/weapons/butterfly.dm +++ b/code/game/objects/items/weapons/butterfly.dm @@ -45,18 +45,15 @@ fold() to_chat(L, "You flip \the [src] closed.") if(bug) - if(bug == (/mob/living/simple_animal/hostile/viscerator/butterfly || /mob/living/simple_animal/hostile/viscerator/butterfly/magic)) - var/mob/living/simple_animal/hostile/viscerator/butterfly/X = new bug(get_turf(src)) - X.autodie = TRUE - if(istype(L)) - handle_faction(X,L) - else //In case someone decides to make a knife spawn something other than a viscerator. - var/mob/living/simple_animal/X = new bug(get_turf(src)) - if(istype(L)) - handle_faction(X,L) + var/mob/living/simple_animal/X = new bug(get_turf(src)) + if(istype(L)) + handle_faction(X,L) + if(istype(X, /mob/living/simple_animal/hostile/viscerator/butterfly)) + var/mob/living/simple_animal/hostile/viscerator/butterfly/B = X + B.autodie = TRUE bug = null counting = world.time - playsound(get_turf(src),'sound/items/zippo_open.ogg', 50, 1) + playsound(src,'sound/items/zippo_open.ogg', 50, 1) /obj/item/weapon/butterflyknife/preattack(var/mob/living/target, mob/user) //"Putting away" a butterfly early. if((istype(target, /mob/living/simple_animal/hostile/viscerator/butterfly)) && (knifetype != "plain")) @@ -68,11 +65,11 @@ else fold() -/obj/item/weapon/butterflyknife/proc/rearm(mob/user) +/obj/item/weapon/butterflyknife/proc/rearm() counting = null bug = initial(bug) playsound(src, 'sound/items/healthanalyzer.ogg', 10, 1) - to_chat(user, "\The [src] chimes.") + visible_message("\The [src] chimes.") /obj/item/weapon/butterflyknife/proc/unfold() open = TRUE diff --git a/code/game/objects/items/weapons/cigs_lighters.dm b/code/game/objects/items/weapons/cigs_lighters.dm index 7f920741d33..6d9efa1ff0d 100644 --- a/code/game/objects/items/weapons/cigs_lighters.dm +++ b/code/game/objects/items/weapons/cigs_lighters.dm @@ -30,7 +30,9 @@ MATCHBOXES ARE ALSO IN FANCY.DM source_temperature = TEMPERATURE_FLAME w_class = W_CLASS_TINY origin_tech = Tc_MATERIALS + "=1" - attack_verb = list("burns", "singes") + var/list/unlit_attack_verb = list("prods", "pokes") + var/list/lit_attack_verb = list("burns", "singes") + attack_verb = list("prods", "pokes") light_color = LIGHT_COLOR_FIRE /obj/item/weapon/match/New() @@ -60,16 +62,19 @@ MATCHBOXES ARE ALSO IN FANCY.DM item_state = "[initial(item_state)]on" icon_state = "[initial(icon_state)]_lit" damtype = BURN + attack_verb = lit_attack_verb if(0) name = "[initial(name)]" item_state = "[initial(item_state)]off" icon_state = "[initial(icon_state)]_unlit" damtype = BRUTE + attack_verb = unlit_attack_verb if(-1) name = "burnt [initial(name)]" item_state = "[initial(item_state)]off" icon_state = "[initial(icon_state)]_burnt" damtype = BRUTE + attack_verb = unlit_attack_verb /obj/item/weapon/match/proc/update_brightness() if(lit == 1) //I wish I didn't need the == 1 part, but Dreamkamer is a dumb puppy @@ -89,7 +94,7 @@ MATCHBOXES ARE ALSO IN FANCY.DM lit = -1 update_brightness() return - if(env.oxygen < 5) + if(env.molar_density("oxygen") < (5 / CELL_VOLUME)) lit = -1 update_brightness() if(M) @@ -156,7 +161,9 @@ MATCHBOXES ARE ALSO IN FANCY.DM item_state = "cig" w_class = W_CLASS_TINY body_parts_covered = 0 - attack_verb = list("burns", "singes") + var/list/unlit_attack_verb = list("prods", "pokes") + var/list/lit_attack_verb = list("burns", "singes") + attack_verb = list("prods", "pokes") heat_production = 1000 source_temperature = TEMPERATURE_FLAME light_color = LIGHT_COLOR_FIRE @@ -167,7 +174,7 @@ MATCHBOXES ARE ALSO IN FANCY.DM var/lastHolder = null var/brightness_on = 1 //Barely enough to see where you're standing, it's a boring old cigarette var/smoketime = 300 - var/chem_volume = 15 + var/chem_volume = 20 var/inside_item = 0 //For whether the cigarette is contained inside another item. var/filling = null //To alter the name if it's a special kind of cigarette @@ -175,6 +182,10 @@ MATCHBOXES ARE ALSO IN FANCY.DM ..() flags |= NOREACT // so it doesn't react until you light it create_reagents(chem_volume) // making the cigarrete a chemical holder with a maximum volume of 15 + if(Holiday == APRIL_FOOLS_DAY) + reagents.add_reagent(DANBACCO, 5) + else + reagents.add_reagent(TOBACCO, 5) update_brightness() /obj/item/clothing/mask/cigarette/Destroy() @@ -196,11 +207,13 @@ MATCHBOXES ARE ALSO IN FANCY.DM item_state = "[initial(item_state)]on" icon_state = "[initial(icon_state)]on" damtype = BURN + attack_verb = lit_attack_verb if(0) name = filling ? "[filling] [initial(name)]" : "[initial(name)]" item_state = "[initial(item_state)]off" icon_state = "[initial(icon_state)]off" damtype = BRUTE + attack_verb = unlit_attack_verb /obj/item/clothing/mask/cigarette/proc/update_brightness() if(lit) @@ -342,7 +355,7 @@ MATCHBOXES ARE ALSO IN FANCY.DM M.IgniteMob() smoketime-- var/datum/gas_mixture/env = location.return_air() - if(smoketime <= 0 | env.oxygen < 5) + if(smoketime <= 0 | env.molar_density("oxygen") < (5 / CELL_VOLUME)) if(!inside_item) var/atom/new_butt = new type_butt(location) //Spawn the cigarette butt transfer_fingerprints_to(new_butt) @@ -418,7 +431,7 @@ MATCHBOXES ARE ALSO IN FANCY.DM type_butt = /obj/item/weapon/cigbutt/cigarbutt item_state = "cigar" smoketime = 1500 - chem_volume = 20 + chem_volume = 25 species_fit = list(VOX_SHAPED, GREY_SHAPED) /obj/item/clothing/mask/cigarette/cigar/cohiba @@ -471,7 +484,8 @@ MATCHBOXES ARE ALSO IN FANCY.DM item_state = "blunt" slot_flags = SLOT_MASK species_fit = list(GREY_SHAPED) - attack_verb = list("burns", "singes", "blunts") + + lit_attack_verb = list("burns", "singes", "blunts") smoketime = 420 chem_volume = 50 //It's a fat blunt, a really fat blunt @@ -616,7 +630,9 @@ MATCHBOXES ARE ALSO IN FANCY.DM heat_production = 1500 source_temperature = TEMPERATURE_FLAME slot_flags = SLOT_BELT - attack_verb = list("burns", "singes") + var/list/unlit_attack_verb = list("prods", "pokes") + var/list/lit_attack_verb = list("burns", "singes") + attack_verb = list("prods", "pokes") light_color = LIGHT_COLOR_FIRE var/lit = 0 @@ -654,11 +670,13 @@ MATCHBOXES ARE ALSO IN FANCY.DM item_state = "[initial(item_state)][color_suffix]on" icon_state = "[initial(icon_state)][color_suffix]-on" damtype = BURN + attack_verb = lit_attack_verb if(0) name = "[initial(name)]" item_state = "[initial(item_state)][color_suffix]off" icon_state = "[initial(icon_state)][color_suffix]" damtype = BRUTE + attack_verb = unlit_attack_verb /obj/item/weapon/lighter/proc/update_brightness() if(lit) @@ -676,19 +694,19 @@ MATCHBOXES ARE ALSO IN FANCY.DM fuel += O.reagents.remove_any(initial(fuel) - fuel) user.visible_message("[user] refuels \the [src].", \ "You refuel \the [src].") - playsound(get_turf(src), 'sound/effects/refill.ogg', 50, 1, -6) + playsound(src, 'sound/effects/refill.ogg', 50, 1, -6) return /obj/item/weapon/lighter/attack_self(mob/living/user) var/turf/T = get_turf(src) var/datum/gas_mixture/env = T.return_air() user.delayNextAttack(5) //Hold on there cowboy - if(!fuel | env.oxygen < 5) + if(!fuel | env.molar_density("oxygen") < (5 / CELL_VOLUME)) user.visible_message("[user] attempts to light \the [src] to no avail.", \ "You try to light \the [src], but no flame appears.") return if(!lit) //Lighting the lighter - playsound(get_turf(src), pick(lightersound), 50, 1) + playsound(src, pick(lightersound), 50, 1) if(fuel >= initial(fuel) - 5 || prob(100 * (fuel/initial(fuel)))) //Strike, but fail to light it user.visible_message("[user] manages to light \the [src].", \ "You manage to light \the [src].") @@ -740,7 +758,7 @@ MATCHBOXES ARE ALSO IN FANCY.DM visible_message("Without warning, \the [src] suddenly shuts off.") fueltime = null var/datum/gas_mixture/env = location.return_air() - if(env.oxygen < 5) + if(env.molar_density("oxygen") < (5 / CELL_VOLUME)) lit = 0 update_brightness() visible_message("Without warning, the flame on \the [src] suddenly goes out in a weak fashion.") @@ -763,19 +781,19 @@ MATCHBOXES ARE ALSO IN FANCY.DM var/turf/T = get_turf(src) var/datum/gas_mixture/env = T.return_air() user.delayNextAttack(5) //Hold on there cowboy - if(!fuel | env.oxygen < 5) + if(!fuel | env.molar_density("oxygen") < (5 / CELL_VOLUME)) user.visible_message("[user] attempts to light \the [src] to no avail.", \ "You try to light \the [src], but no flame appears.") return lit = !lit if(lit) //Was lit - playsound(get_turf(src), pick(open_sound), 50, 1) + playsound(src, pick(open_sound), 50, 1) user.visible_message("Without even breaking stride, [user] flips open and lights \the [src] in one smooth movement.", \ "Without even breaking stride, you flip open and light \the [src] in one smooth movement.") --fuel else //Was shut off fueltime = null - playsound(get_turf(src), pick(close_sound), 50, 1) + playsound(src, pick(close_sound), 50, 1) user.visible_message("You hear a quiet click as [user] shuts off \the [src] without even looking at what they're doing. Wow.", \ "You hear a quiet click as you shut off \the [src] without even looking at what you are doing.") - update_brightness() \ No newline at end of file + update_brightness() diff --git a/code/game/objects/items/weapons/clown_items.dm b/code/game/objects/items/weapons/clown_items.dm index 9f944509457..fb9e21dd842 100644 --- a/code/game/objects/items/weapons/clown_items.dm +++ b/code/game/objects/items/weapons/clown_items.dm @@ -101,7 +101,7 @@ /obj/item/weapon/bikehorn/suicide_act(mob/user) to_chat(viewers(user), "[user] places the [src.name] into \his mouth and honks the horn. ") - playsound(get_turf(user), hitsound, 100, vary_pitch) + playsound(user, hitsound, 100, vary_pitch) user.gib() /obj/item/weapon/bikehorn/attack_self(mob/user as mob) @@ -133,7 +133,7 @@ /obj/item/weapon/bikehorn/proc/honk() if(world.time - last_honk_time >= honk_delay) last_honk_time = world.time - playsound(get_turf(src), hitsound, 50, vary_pitch) + playsound(src, hitsound, 50, vary_pitch) return 1 return 0 diff --git a/code/game/objects/items/weapons/cosmetics.dm b/code/game/objects/items/weapons/cosmetics.dm index 96ed2676b19..8a335957099 100644 --- a/code/game/objects/items/weapons/cosmetics.dm +++ b/code/game/objects/items/weapons/cosmetics.dm @@ -269,7 +269,7 @@ H.g_hair = color_g H.b_hair = color_b H.update_hair() - playsound(get_turf(src), 'sound/effects/spray2.ogg', 50, 1, -6) + playsound(src, 'sound/effects/spray2.ogg', 50, 1, -6) /obj/item/weapon/invisible_spray name = "can of invisible spray" @@ -341,7 +341,7 @@ to_chat(user, "You spray yourself with \the [src].") else to_chat(user, "You spray \the [target] with \the [src].") - playsound(get_turf(src), 'sound/effects/spray2.ogg', 50, 1, -6) + playsound(src, 'sound/effects/spray2.ogg', 50, 1, -6) sprays_left-- if(istype(target, /obj/machinery/power/supermatter)) return 0 @@ -492,3 +492,70 @@ return if (prob(25)) shatter() + +/obj/item/weapon/nanitecontacts + name = "nanite contacts" + desc = "Deploys nanobots to your eyes to change their color." + icon = 'icons/obj/items.dmi' + icon_state = "nanite_contact" + flags = FPRINT + w_class = W_CLASS_TINY + var/color_r = 255 + var/color_g = 255 + var/color_b = 255 + +/obj/item/weapon/nanitecontacts/New() + ..() + color_r = rand(0,255) + color_g = rand(0,255) + color_b = rand(0,255) + update_icon() + +/obj/item/weapon/nanitecontacts/update_icon() + overlays.len = 0 + var/image/I = image(icon = 'icons/obj/items.dmi', icon_state = "contacts_overlay") + I.color = rgb(color_r, color_g, color_b) + overlays += I + +/obj/item/weapon/nanitecontacts/attack_self(mob/user) + var/new_color = input(user, "Choose the contact's color:", "Color Select") as color|null + if(new_color) + color_r = hex2num(copytext(new_color, 2, 4)) + color_g = hex2num(copytext(new_color, 4, 6)) + color_b = hex2num(copytext(new_color, 6, 8)) + update_icon() + +/obj/item/weapon/nanitecontacts/attack(mob/M, mob/user) + if(!istype(M)) + return + + if(ishuman(M)) + var/mob/living/carbon/human/H = M + var/area = user.zone_sel.selecting + if(area == "eyes") + var/obj/item/clothing/cover = H.get_body_part_coverage(EYES) + if(cover) + to_chat(user, "You can't color [H == user ? "your" : "\the [H]'s"] eyes through that [cover.name]!") + return + if(H == user) + user.visible_message("[user] colors their eyes with \the [src].", \ + "You color your eyes with \the [src].") + color_eyes(H) + else + user.visible_message("[user] begins to color \the [H]'s eyes with \the [src].", \ + "You begin to color \the [H]'s eyes with \the [src].") + if(do_after(user,H, 20)) //user needs to keep their active hand, H does not. + user.visible_message("[user] colors [H]'s eyes with \the [src].", \ + "You color [H]'s eyes with \the [src].") + color_eyes(H) + else + to_chat(user, "\The [M]'s eyes don't fit in the contacts!") + +/obj/item/weapon/nanitecontacts/proc/color_eyes(mob/living/carbon/human/H) + if(!H) + return + else + H.r_eyes = color_r + H.g_eyes = color_g + H.b_eyes = color_b + H.update_body() diff --git a/code/game/objects/items/weapons/defib.dm b/code/game/objects/items/weapons/defib.dm index bbf6854a6f1..8c616e50d6f 100644 --- a/code/game/objects/items/weapons/defib.dm +++ b/code/game/objects/items/weapons/defib.dm @@ -7,6 +7,7 @@ desc = "Used to restore fibrillating patients." icon = 'icons/obj/weapons.dmi' icon_state = "defib_full" + inhand_states = list("left_hand" = 'icons/mob/in-hand/left/surgery_tools.dmi', "right_hand" = 'icons/mob/in-hand/right/surgery_tools.dmi') item_state = "defib" w_class = W_CLASS_MEDIUM force = 5 @@ -22,7 +23,7 @@ /obj/item/weapon/melee/defibrillator/suicide_act(mob/user) to_chat(viewers(user), "[user] is putting the live paddles on \his chest! It looks like \he's trying to commit suicide.") - playsound(get_turf(src),'sound/items/defib.ogg',50,1) + playsound(src,'sound/items/defib.ogg',50,1) return (FIRELOSS) /obj/item/weapon/melee/defibrillator/update_icon() @@ -47,7 +48,7 @@ if(clumsy_check(user) && prob(50) && charges) to_chat(user, "You touch the paddles together, shorting the device.") spark(src, 5) - playsound(get_turf(src),'sound/items/defib.ogg',50,1) + playsound(src,'sound/items/defib.ogg',50,1) user.Knockdown(5) var/mob/living/carbon/human/H = user if(ishuman(user)) @@ -57,7 +58,7 @@ else ready = !ready to_chat(user, "You turn [src] [ready? "on and take the paddles out" : "off and put the paddles back in"].") - playsound(get_turf(src),"sparks",75,1,-1) + playsound(src,"sparks",75,1,-1) update_icon() else to_chat(user, "[src] is out of charges.") @@ -120,7 +121,7 @@ else target.LAssailant = user spark(src, 5, FALSE) - playsound(get_turf(src),'sound/items/defib.ogg',50,1) + playsound(src,'sound/items/defib.ogg',50,1) charges-- update_icon() return @@ -130,33 +131,33 @@ "You start setting up the paddles on [target]'s chest") if(do_after(user,target,30)) spark(src, 5, FALSE) - playsound(get_turf(src),'sound/items/defib.ogg',50,1) + playsound(src,'sound/items/defib.ogg',50,1) charges-- update_icon() to_chat(user, "You shock [target] with the paddles.") var/datum/organ/internal/heart/heart = target.get_heart() if(!heart) - to_chat(user, "[src] buzzes: Defibrillation failed. Subject requires a heart.") + target.visible_message("[src] buzzes: Defibrillation failed. Subject requires a heart.") target.apply_damage(rand(1,5),BURN,LIMB_CHEST) return var/datum/organ/external/head/head = target.get_organ(LIMB_HEAD) if(!head || head.status & ORGAN_DESTROYED) target.visible_message("[src] buzzes: Defibrillation failed. Severe cranial damage detected.") return - if(M_NOCLONE in target.mutations) + if((M_HUSK in target.mutations) && (M_NOCLONE in target.mutations)) target.visible_message("[src] buzzes: Defibrillation failed. Irremediable genetic damage detected.") return if(!target.has_brain()) - target.visible_message("[src] buzzes: Defibrillation failed. No nervous system detected.") + target.visible_message("[src] buzzes: Defibrillation failed. No central nervous system detected.") return if(target.suiciding) target.visible_message("[src] buzzes: Defibrillation failed. Severe nerve trauma detected.") // They suicided so they fried their brain. Space Magic. return - if(target.wear_suit && istype(target.wear_suit,/obj/item/clothing/suit/armor) && prob(95)) //75 ? Let's stay realistic here + if(istype(target.wear_suit,/obj/item/clothing/suit/armor) && (target.wear_suit.body_parts_covered & UPPER_TORSO) && prob(95)) //75 ? Let's stay realistic here target.visible_message("[src] buzzes: Defibrillation failed. Please apply on bare skin.") target.apply_damage(rand(1,5),BURN,LIMB_CHEST) return - if(target.w_uniform && istype(target.w_uniform,/obj/item/clothing/under) && prob(50)) + if(istype(target.w_uniform,/obj/item/clothing/under) && (target.w_uniform.body_parts_covered & UPPER_TORSO) && prob(50)) target.visible_message("[src] buzzes: Defibrillation failed. Please apply on bare skin.") target.apply_damage(rand(1,5),BURN,LIMB_CHEST) return @@ -168,10 +169,10 @@ ghostmob << 'sound/effects/adminhelp.ogg' to_chat(ghostmob, "Someone is trying to revive your body. Return to it if you want to be resurrected! \ (Verbs -> Ghost -> Re-enter corpse, or click here!)") - to_chat(user, "[src] buzzes: Defibrillation failed. Vital signs are too weak, please try again in five seconds.") + target.visible_message(user, "[src] buzzes: Defibrillation failed. Vital signs are too weak, please try again in five seconds.") return //we couldn't find a suitable ghost. - target.visible_message("[src] buzzes: Defibrillation failed. No brain waves detected.") + target.visible_message("[src] buzzes: Defibrillation failed. No brainwaves detected.") return if(prob(25)) heart.damage += 5 //Allow the defibrilator to possibly worsen heart damage. Still rare enough to just be the "clone damage" of the defib diff --git a/code/game/objects/items/weapons/dice.dm b/code/game/objects/items/weapons/dice.dm index 2ad88434f9b..0d3d3b5644e 100644 --- a/code/game/objects/items/weapons/dice.dm +++ b/code/game/objects/items/weapons/dice.dm @@ -130,10 +130,11 @@ /obj/item/weapon/dice/d20/cursed - desc = "Something about this dice seems wrong" name = "\improper Mysterious d20" + desc = "Something about this dice seems wrong" var/deactivated = 0 //Eventually the dice runs out of power var/infinite = 0 //dice with 1 will not run out + mech_flags = MECH_SCAN_ILLEGAL /obj/item/weapon/dice/d20/cursed/pickup(mob/user as mob) ..() diff --git a/code/game/objects/items/weapons/dna_injector.dm b/code/game/objects/items/weapons/dna_injector.dm index 1b276183eeb..5e7689dfaf1 100644 --- a/code/game/objects/items/weapons/dna_injector.dm +++ b/code/game/objects/items/weapons/dna_injector.dm @@ -309,7 +309,7 @@ /obj/item/weapon/dnainjector/nofail/antiremoteview name = "DNA-Injector (Anti-Remote View)" - desc = "Cures green skin." + desc = "Quit staring." datatype = DNA2_BUF_SE value = 0x001 //block = 2 @@ -842,6 +842,23 @@ datatype = DNA2_BUF_SE value = 0x001 //block = 11 + +/obj/item/weapon/dnainjector/nofail/asthmamut + name = "DNA-Injector (Asthma)" + desc = "Makes you asthmatic." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 11 + +/obj/item/weapon/dnainjector/nofail/asthmamut/New() + block = ASTHMABLOCK + ..() + +/obj/item/weapon/dnainjector/nofail/antiasthma + name = "DNA-Injector (Anti-Asthma)" + desc = "Allows you to breathe normally again." + datatype = DNA2_BUF_SE + value = 0x001 /obj/item/weapon/dnainjector/nofail/antiblind/New() block = VEGANBLOCK diff --git a/code/game/objects/items/weapons/explosives.dm b/code/game/objects/items/weapons/explosives.dm index 55017332fd3..6170c3cfeb7 100644 --- a/code/game/objects/items/weapons/explosives.dm +++ b/code/game/objects/items/weapons/explosives.dm @@ -98,7 +98,7 @@ else user.visible_message("[user] found \himself unable to drop \the [src] after setting the timer on them!") - playsound(get_turf(target), 'sound/weapons/c4armed.ogg', 60, 1) + playsound(target, 'sound/weapons/c4armed.ogg', 60, 1) if(!iscarbon(user)) M.LAssailant = null else diff --git a/code/game/objects/items/weapons/extinguisher.dm b/code/game/objects/items/weapons/extinguisher.dm index d023644be50..08fcd44fbf2 100644 --- a/code/game/objects/items/weapons/extinguisher.dm +++ b/code/game/objects/items/weapons/extinguisher.dm @@ -90,13 +90,13 @@ user.visible_message("[user] begins to unwrench the fill cap on \the [src].","You begin to unwrench the fill cap on \the [src].") if(do_after(user, src, 25)) user.visible_message("[user] removes the fill cap on \the [src].","You remove the fill cap on \the [src].") - playsound(get_turf(src),'sound/items/Ratchet.ogg', 100, 1) + playsound(src,'sound/items/Ratchet.ogg', 100, 1) flags |= OPENCONTAINER else user.visible_message("[user] begins to seal the fill cap on \the [src].","You begin to seal the fill cap on \the [src].") if(do_after(user, src, 25)) user.visible_message("[user] fastens the fill cap on \the [src].","You fasten the fill cap on \the [src].") - playsound(get_turf(src),'sound/items/Ratchet.ogg', 100, 1) + playsound(src,'sound/items/Ratchet.ogg', 100, 1) flags &= ~OPENCONTAINER return @@ -121,7 +121,7 @@ if((istype(target, /obj/structure/reagent_dispensers))) target.reagents.trans_to(src, 50, log_transfer = TRUE, whodunnit = user) to_chat(user, "\The [src] is now refilled") - playsound(get_turf(src), 'sound/effects/refill.ogg', 50, 1, -6) + playsound(src, 'sound/effects/refill.ogg', 50, 1, -6) return if(is_open_container() && reagents.total_volume) @@ -151,7 +151,7 @@ src.last_use = world.time - playsound(get_turf(src), 'sound/effects/extinguish.ogg', 75, 1, -3) + playsound(src, 'sound/effects/extinguish.ogg', 75, 1, -3) var/direction = get_dir(src,target) @@ -224,7 +224,7 @@ var/obj/o = target o.reagents.trans_to(src, 50) to_chat(user, "\The [src] is now refilled") - playsound(get_turf(src), 'sound/effects/refill.ogg', 50, 1, -6) + playsound(src, 'sound/effects/refill.ogg', 50, 1, -6) return if (!safety && !is_open_container()) @@ -241,7 +241,7 @@ user.delayNextAttack(5, 1) src.last_use = world.time - playsound(get_turf(src), 'sound/effects/extinguish.ogg', 75, 1, -3) + playsound(src, 'sound/effects/extinguish.ogg', 75, 1, -3) var/direction = get_dir(src,target) diff --git a/code/game/objects/items/weapons/gift_wrappaper.dm b/code/game/objects/items/weapons/gift_wrappaper.dm index 99755e9f20f..c71cb761f6a 100644 --- a/code/game/objects/items/weapons/gift_wrappaper.dm +++ b/code/game/objects/items/weapons/gift_wrappaper.dm @@ -325,6 +325,6 @@ /obj/item/weapon/winter_gift/dorkcube/attack_self(mob/user) user.say("Loot get!") - playsound(get_turf(src), 'sound/misc/achievement.ogg', 30, 1) + playsound(src, 'sound/misc/achievement.ogg', 30, 1) user.gib() qdel(src) diff --git a/code/game/objects/items/weapons/grenades/chem_grenade.dm b/code/game/objects/items/weapons/grenades/chem_grenade.dm index a4dbe1cdfc4..7e5b474f6f5 100644 --- a/code/game/objects/items/weapons/grenades/chem_grenade.dm +++ b/code/game/objects/items/weapons/grenades/chem_grenade.dm @@ -18,6 +18,7 @@ var/obj/item/weapon/reagent_containers/glass/beaker/noreactgrenade/reservoir = null var/extract_uses = 0 var/mob/primed_by = "N/A" //"name (ckey)". For logging purposes + mech_flags = null /obj/item/weapon/grenade/chem_grenade/attack_self(mob/user as mob) if(!stage || stage==1) @@ -79,7 +80,7 @@ return path = 1 to_chat(user, "You add [W] to the metal casing.") - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 25, -3) + playsound(src, 'sound/items/Screwdriver.ogg', 25, -3) user.remove_from_mob(det) det.forceMove(src) detonator = det @@ -93,7 +94,7 @@ coil.use(2) var/obj/item/weapon/electrolyzer/E = new /obj/item/weapon/electrolyzer to_chat(user, "You tightly coil the wire around the metal casing.") - playsound(get_turf(src), 'sound/weapons/cablecuff.ogg', 30, 1, -2) + playsound(src, 'sound/weapons/cablecuff.ogg', 30, 1, -2) user.before_take_item(src) user.put_in_hands(E) qdel(src) @@ -119,7 +120,7 @@ // to_chat(user, "You need to add at least one beaker before locking the assembly.") to_chat(user, "You lock the empty assembly.") name = "fake grenade" - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 25, -3) + playsound(src, 'sound/items/Screwdriver.ogg', 25, -3) icon_state = initial(icon_state) +"_locked" stage = 2 else if(stage == 2) @@ -129,7 +130,7 @@ return else to_chat(user, "You unlock the assembly.") - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 25, -3) + playsound(src, 'sound/items/Screwdriver.ogg', 25, -3) name = "unsecured grenade with [beakers.len] containers[detonator?" and detonator":""]" icon_state = initial(icon_state) + (detonator?"_ass":"") stage = 1 @@ -229,10 +230,10 @@ active = 0 if(!has_reagents) icon_state = initial(icon_state) +"_locked" - playsound(get_turf(src), 'sound/items/Screwdriver2.ogg', 50, 1) + playsound(src, 'sound/items/Screwdriver2.ogg', 50, 1) return - playsound(get_turf(src), 'sound/effects/bamfgas.ogg', 50, 1) + playsound(src, 'sound/effects/bamfgas.ogg', 50, 1) visible_message("[bicon(src)] \The [src] bursts open.") @@ -326,7 +327,7 @@ obj/item/weapon/grenade/chem_grenade/exgrenade/attackby(obj/item/weapon/W as obj return path = 1 to_chat(user, "You insert [W] into the grenade.") - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 25, -3) + playsound(src, 'sound/items/Screwdriver.ogg', 25, -3) user.remove_from_mob(det) det.forceMove(src) detonator = det @@ -342,7 +343,7 @@ obj/item/weapon/grenade/chem_grenade/exgrenade/attackby(obj/item/weapon/W as obj else to_chat(user, "You lock the empty assembly.") name = "fake grenade" - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 25, -3) + playsound(src, 'sound/items/Screwdriver.ogg', 25, -3) icon_state = initial(icon_state) +"_locked" stage = 2 else if(stage == 2) @@ -352,7 +353,7 @@ obj/item/weapon/grenade/chem_grenade/exgrenade/attackby(obj/item/weapon/W as obj return else to_chat(user, "You unlock the assembly.") - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 25, -3) + playsound(src, 'sound/items/Screwdriver.ogg', 25, -3) name = "unsecured EX grenade with [beakers.len] containers[detonator?" and detonator":""]" icon_state = initial(icon_state) + (detonator?"_ass":"") stage = 1 @@ -407,6 +408,27 @@ obj/item/weapon/grenade/chem_grenade/exgrenade/attackby(obj/item/weapon/W as obj beakers += B2 icon_state = initial(icon_state) +"_locked" +/obj/item/weapon/grenade/chem_grenade/ironfoam + name = "Iron-Foam Grenade" + desc = "Used for emergency sealing of air breaches." + path = 1 + stage = 2 + +/obj/item/weapon/grenade/chem_grenade/ironfoam/New() + ..() + var/obj/item/weapon/reagent_containers/glass/beaker/B1 = new(src) + var/obj/item/weapon/reagent_containers/glass/beaker/B2 = new(src) + + B1.reagents.add_reagent(IRON, 30) + B2.reagents.add_reagent(FOAMING_AGENT, 10) + B2.reagents.add_reagent(PACID, 10) + + detonator = new/obj/item/device/assembly_holder/timer_igniter(src) + + beakers += B1 + beakers += B2 + icon_state = initial(icon_state) +"_locked" + /obj/item/weapon/grenade/chem_grenade/incendiary name = "Incendiary Grenade" desc = "Used for clearing rooms of living things." diff --git a/code/game/objects/items/weapons/grenades/chronogrenade.dm b/code/game/objects/items/weapons/grenades/chronogrenade.dm index c3ef10bbdfb..f64850d8850 100644 --- a/code/game/objects/items/weapons/grenades/chronogrenade.dm +++ b/code/game/objects/items/weapons/grenades/chronogrenade.dm @@ -7,6 +7,7 @@ flags = FPRINT | TIMELESS var/duration = 10 SECONDS var/radius = 5 //in tiles + mech_flags = MECH_SCAN_FAIL /obj/item/weapon/grenade/chronogrenade/prime() timestop(src, duration, radius) diff --git a/code/game/objects/items/weapons/grenades/clowngrenade.dm b/code/game/objects/items/weapons/grenades/clowngrenade.dm index 6123935b1c3..b753b65e47e 100644 --- a/code/game/objects/items/weapons/grenades/clowngrenade.dm +++ b/code/game/objects/items/weapons/grenades/clowngrenade.dm @@ -15,7 +15,7 @@ /obj/item/weapon/grenade/clown_grenade/prime() ..() - playsound(get_turf(src), 'sound/items/bikehorn.ogg', 25, -3) + playsound(src, 'sound/items/bikehorn.ogg', 25, -3) /* for(var/turf/simulated/floor/T in view(affected_area, src.loc)) if(prob(75)) @@ -92,7 +92,7 @@ M.take_organ_damage(2) // Was 5 -- TLE M.simple_message("You slipped on \the [name]!",\ "Please, just end the pain!") - playsound(get_turf(src), 'sound/misc/slip.ogg', 50, 1, -3) + playsound(src, 'sound/misc/slip.ogg', 50, 1, -3) M.Knockdown(10) M.take_overall_damage(0, burned) diff --git a/code/game/objects/items/weapons/grenades/flashbang.dm b/code/game/objects/items/weapons/grenades/flashbang.dm index 821187d556b..3078b92781b 100644 --- a/code/game/objects/items/weapons/grenades/flashbang.dm +++ b/code/game/objects/items/weapons/grenades/flashbang.dm @@ -40,7 +40,7 @@ var/eye_safety = 0 var/ear_safety = 0 - if(!ignore_protection) + if(!ignore_protection && loc != M.loc) eye_safety = M.eyecheck() ear_safety = M.earprot() //some arbitrary measurement of ear protection, I guess? doesn't even matter if it goes above 1 @@ -56,40 +56,57 @@ //Flashing everyone if(eye_safety < 1) M.flash_eyes(visual = 1, affect_silicon = 1) - M.Stun(10) - M.Knockdown(10) + if (get_dist(M, T) <= 3) + M.Stun(8) + M.Knockdown(8) + else + if (issilicon(M)) + M.Stun(4) + M.Knockdown(4) + else if (get_dist(M, T) <= 5) + M.Knockdown(2) + else + M.Knockdown(1) //Now applying sound if(!ear_safety) to_chat(M, "BANG") - playsound(get_turf(src), 'sound/effects/bang.ogg', 60, 1) + playsound(src, 'sound/effects/bang.ogg', 60, 1) else to_chat(M, "BANG") - playsound(get_turf(src), 'sound/effects/bang.ogg', 25, 1) + playsound(src, 'sound/effects/bang.ogg', 25, 1) if((get_dist(M, T) <= 2 || src.loc == M.loc || src.loc == M)) if(ear_safety > 0) M.Stun(2) M.Knockdown(2) else - M.Stun(10) - M.Knockdown(10) + M.Stun(8) + M.Knockdown(8) if ((prob(14) || (M == src.loc && prob(70)))) M.ear_damage += rand(1, 10) else M.ear_damage += rand(0, 5) M.ear_deaf = max(M.ear_deaf,15) + else if(get_dist(M, T) <= 3) + if(!ear_safety) + M.Stun(6) + M.Knockdown(6) + M.ear_damage += rand(0, 3) + M.ear_deaf = max(M.ear_deaf,10) + else if(get_dist(M, T) <= 5) if(!ear_safety) - M.Stun(8) - M.Knockdown(8) + M.Stun(4) + M.Knockdown(4) M.ear_damage += rand(0, 3) M.ear_deaf = max(M.ear_deaf,10) else if(!ear_safety) - M.Stun(4) - M.Knockdown(4) + if (issilicon(M)) + M.Stun(4) + M.Knockdown(1) M.ear_damage += rand(0, 1) M.ear_deaf = max(M.ear_deaf,5) @@ -140,12 +157,12 @@ for(,numspawned > 0, numspawned--) spawn(0) new /obj/item/weapon/grenade/flashbang/cluster(src.loc)//Launches flashbangs - playsound(get_turf(src), 'sound/weapons/armbomb.ogg', 75, 1, -3) + playsound(src, 'sound/weapons/armbomb.ogg', 75, 1, -3) for(,again > 0, again--) spawn(0) new /obj/item/weapon/grenade/flashbang/clusterbang/segment(src.loc)//Creates a 'segment' that launches a few more flashbangs - playsound(get_turf(src), 'sound/weapons/armbomb.ogg', 75, 1, -3) + playsound(src, 'sound/weapons/armbomb.ogg', 75, 1, -3) spawn(0) qdel(src) return @@ -177,7 +194,7 @@ for(,numspawned > 0, numspawned--) spawn(0) new /obj/item/weapon/grenade/flashbang/cluster(src.loc) - playsound(get_turf(src), 'sound/weapons/armbomb.ogg', 75, 1, -3) + playsound(src, 'sound/weapons/armbomb.ogg', 75, 1, -3) spawn(0) qdel(src) return diff --git a/code/game/objects/items/weapons/grenades/ghettobomb.dm b/code/game/objects/items/weapons/grenades/ghettobomb.dm index 10facc85cb4..a58e95b3028 100644 --- a/code/game/objects/items/weapons/grenades/ghettobomb.dm +++ b/code/game/objects/items/weapons/grenades/ghettobomb.dm @@ -45,7 +45,7 @@ F.reagents.remove_reagent(FUEL, 50, 1)//Deleting 50 fuel from the welding fuel tank, assembled = 1 to_chat(user, "You've filled the makeshift explosive with welding fuel.") - playsound(get_turf(src), 'sound/effects/refill.ogg', 50, 1, -6) + playsound(src, 'sound/effects/refill.ogg', 50, 1, -6) desc = "An improvised explosive assembly. Filled to the brim with 'Explosive flavor'" overlays += image('icons/obj/grenade.dmi', icon_state = "improvised_grenade_filled") return @@ -114,7 +114,7 @@ current_shrapnel += I.shrapnel_size if(user && user.drop_item(I, src)) to_chat(user, "You add \the [I] to the improvised explosive.") - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 25, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 25, 1) else I.forceMove(src) diff --git a/code/game/objects/items/weapons/grenades/grenade.dm b/code/game/objects/items/weapons/grenades/grenade.dm index bbab990c18d..ed5aa928401 100644 --- a/code/game/objects/items/weapons/grenades/grenade.dm +++ b/code/game/objects/items/weapons/grenades/grenade.dm @@ -12,6 +12,7 @@ slot_flags = SLOT_BELT var/active = 0 var/det_time = 50 + mech_flags = MECH_SCAN_ILLEGAL /obj/item/weapon/grenade/proc/clown_check(var/mob/living/user) if(clumsy_check(user) && prob(50)) diff --git a/code/game/objects/items/weapons/grenades/inflatable.dm b/code/game/objects/items/weapons/grenades/inflatable.dm index 8261d039c2a..91528b318f2 100644 --- a/code/game/objects/items/weapons/grenades/inflatable.dm +++ b/code/game/objects/items/weapons/grenades/inflatable.dm @@ -2,9 +2,10 @@ name = "inflatable barrier grenade" desc = "An inflatable barrier conveniently packaged into a casing for remote delivery. Non-reusable." var/deploy_path = /obj/structure/inflatable/wall + mech_flags = null /obj/item/weapon/grenade/inflatable/prime() - playsound(get_turf(src), 'sound/items/zip.ogg', 75, 1) + playsound(src, 'sound/items/zip.ogg', 75, 1) var/obj/structure/inflatable/R = new deploy_path(get_turf(src)) R.spawn_undeployed = FALSE qdel(src) diff --git a/code/game/objects/items/weapons/grenades/smokebomb.dm b/code/game/objects/items/weapons/grenades/smokebomb.dm index 5db81e4a87a..9b6b07ae5dc 100644 --- a/code/game/objects/items/weapons/grenades/smokebomb.dm +++ b/code/game/objects/items/weapons/grenades/smokebomb.dm @@ -8,28 +8,28 @@ flags = FPRINT slot_flags = SLOT_BELT var/datum/effect/effect/system/smoke_spread/bad/smoke + mech_flags = null - New() - ..() - src.smoke = new /datum/effect/effect/system/smoke_spread/bad - src.smoke.attach(src) +/obj/item/weapon/grenade/smokebomb/New() + ..() + smoke = new /datum/effect/effect/system/smoke_spread/bad + smoke.attach(src) - prime() - playsound(get_turf(src), 'sound/effects/smoke.ogg', 50, 1, -3) - src.smoke.set_up(10, 0, usr.loc) - spawn(0) - src.smoke.start() - sleep(10) - src.smoke.start() - sleep(10) - src.smoke.start() - sleep(10) - src.smoke.start() +/obj/item/weapon/grenade/smokebomb/prime() + playsound(src, 'sound/effects/smoke.ogg', 50, 1, -3) + smoke.set_up(10, 0, usr.loc) + spawn(0) + smoke.start() + sleep(10) + smoke.start() + sleep(10) + smoke.start() + sleep(10) + smoke.start() - for(var/obj/effect/blob/B in view(8,src)) - var/damage = round(30/(get_dist(B,src)+1)) - B.health -= damage - B.update_icon() - sleep(80) - qdel(src) - return + for(var/obj/effect/blob/B in view(8,src)) + var/damage = round(30/(get_dist(B,src)+1)) + B.health -= damage + B.update_icon() + sleep(80) + qdel(src) diff --git a/code/game/objects/items/weapons/grenades/spawnergrenade.dm b/code/game/objects/items/weapons/grenades/spawnergrenade.dm index df401013aa9..1e1358f8f12 100644 --- a/code/game/objects/items/weapons/grenades/spawnergrenade.dm +++ b/code/game/objects/items/weapons/grenades/spawnergrenade.dm @@ -85,5 +85,5 @@ /obj/item/weapon/grenade/spawnergrenade/beenade/postPrime(var/list/spawned_atoms) if(!spawned_atoms || !spawned_atoms.len) return - playsound(get_turf(src), 'sound/effects/bees.ogg', 100, 1) + playsound(src, 'sound/effects/bees.ogg', 100, 1) diff --git a/code/game/objects/items/weapons/implants/implant.dm b/code/game/objects/items/weapons/implants/implant.dm index 96af15767ad..e583e19ba69 100644 --- a/code/game/objects/items/weapons/implants/implant.dm +++ b/code/game/objects/items/weapons/implants/implant.dm @@ -53,6 +53,8 @@ qdel(reagents) ..() + + var/global/tracking_implants = list() //fuck me /obj/item/weapon/implant/tracking @@ -101,7 +103,8 @@ Implant Specifics:
    "} spawn(delay) malfunction-- -//BS12 Explosive + + /obj/item/weapon/implant/explosive name = "explosive implant" desc = "A military grade micro bio-explosive. Highly dangerous." @@ -202,6 +205,8 @@ Implant Specifics:
    "} /obj/item/weapon/implant/explosive/nuclear/emp_act(severity) return + + /obj/item/weapon/implant/chem name = "chem" desc = "Injects things." @@ -294,6 +299,8 @@ the implant may become unstable and either pre-maturely inject the subject or si to_chat(H, "You feel a surge of loyalty towards Nanotrasen.") return 1 + + /obj/item/weapon/implant/traitor name = "Greytide Implant" desc = "Greytide Station wide" @@ -364,7 +371,6 @@ the implant may become unstable and either pre-maturely inject the subject or si Integrity: Implant can only be used three times before the nanobots are depleted."} return dat - /obj/item/weapon/implant/adrenalin/trigger(emote, mob/source as mob) if (src.uses < 1) return 0 @@ -377,13 +383,14 @@ the implant may become unstable and either pre-maturely inject the subject or si return - /obj/item/weapon/implant/adrenalin/implanted(mob/source) source.mind.store_memory("A implant can be activated by using the pale emote, say *pale to attempt to activate.", 0, 0) to_chat(source, "The implanted freedom implant can be activated by using the pale emote, say *pale to attempt to activate.") return 1 + + /obj/item/weapon/implant/death_alarm name = "death alarm implant" desc = "An alarm which monitors host vital signs and transmits a radio message upon death." @@ -466,6 +473,8 @@ the implant may become unstable and either pre-maturely inject the subject or si processing_objects.Add(src) return 1 + + /obj/item/weapon/implant/compressed name = "compressed matter implant" desc = "Based on compressed matter technology, can store a single item." @@ -512,6 +521,8 @@ the implant may become unstable and either pre-maturely inject the subject or si /obj/item/weapon/implant/compressed/islegal() return 0 + + /obj/item/weapon/implant/cortical name = "cortical stack" desc = "A fist-sized mass of biocircuits and chips." diff --git a/code/game/objects/items/weapons/implants/implantcase.dm b/code/game/objects/items/weapons/implants/implantcase.dm index a75c6cc4793..68d0069027c 100644 --- a/code/game/objects/items/weapons/implants/implantcase.dm +++ b/code/game/objects/items/weapons/implants/implantcase.dm @@ -1,5 +1,3 @@ - - /obj/item/weapon/implantcase name = "Glass Case" desc = "A case containing an implant." @@ -12,7 +10,6 @@ proc update() - update() if (src.imp) src.icon_state = text("implantcase-[]", src.imp._color) @@ -20,7 +17,6 @@ src.icon_state = "implantcase-0" return - attackby(obj/item/weapon/I as obj, mob/user as mob) ..() if (istype(I, /obj/item/weapon/pen)) @@ -57,40 +53,36 @@ return - /obj/item/weapon/implantcase/tracking name = "Glass Case- 'Tracking'" desc = "A case containing a tracking implant." icon = 'icons/obj/items.dmi' icon_state = "implantcase-b" - New() src.imp = new /obj/item/weapon/implant/tracking( src ) ..() return - /obj/item/weapon/implantcase/explosive name = "Glass Case- 'Explosive'" desc = "A case containing an explosive implant." icon = 'icons/obj/items.dmi' icon_state = "implantcase-r" - New() src.imp = new /obj/item/weapon/implant/explosive( src ) ..() return - /obj/item/weapon/implantcase/chem name = "Glass Case- 'Chem'" desc = "A case containing a chemical implant." icon = 'icons/obj/items.dmi' icon_state = "implantcase-b" + /obj/item/weapon/implantcase/chem/New() src.imp = new /obj/item/weapon/implant/chem( src ) @@ -121,3 +113,14 @@ src.imp = new /obj/item/weapon/implant/death_alarm( src ) ..() return + + +/obj/item/weapon/implantcase/peace + name = "glass case- 'Pax'" + desc = "A case containing a peace-inducing implant." + icon = 'icons/obj/items.dmi' + icon_state = "implantcase-b" + +/obj/item/weapon/implantcase/peace/New() + src.imp = new /obj/item/weapon/implant/peace(src) + ..() diff --git a/code/game/objects/items/weapons/implants/implanter.dm b/code/game/objects/items/weapons/implants/implanter.dm index 13d634d217b..db7fa20181c 100644 --- a/code/game/objects/items/weapons/implants/implanter.dm +++ b/code/game/objects/items/weapons/implants/implanter.dm @@ -7,107 +7,83 @@ throw_range = 5 w_class = W_CLASS_SMALL var/obj/item/weapon/implant/imp = null + var/imp_type = null /obj/item/weapon/implanter/proc/update() - - - -/obj/item/weapon/implanter/update() - if (src.imp) - src.icon_state = "implanter1" - else - src.icon_state = "implanter0" - return - + icon_state = "implanter[imp? 1:0]" /obj/item/weapon/implanter/attack(mob/M as mob, mob/user as mob) - if (!istype(M, /mob/living/carbon)) + if(!istype(M, /mob/living/carbon)) return - if (user && src.imp) + if(user && imp) for (var/mob/O in viewers(M, null)) O.show_message("[user] is attempting to implant [M].", 1) var/turf/T1 = get_turf(M) - if (T1 && ((M == user) || do_after(user,M, 50))) - if(user && M && (get_turf(M) == T1) && src && src.imp) + if(T1 && ((M == user) || do_after(user,M, 50))) + if(user && M && (get_turf(M) == T1) && src && imp) for (var/mob/O in viewers(M, null)) O.show_message("[M] has been implanted by [user].", 1) - M.attack_log += text("\[[time_stamp()]\] Implanted with [src.name] ([src.imp.name]) by [user.name] ([user.ckey])") - user.attack_log += text("\[[time_stamp()]\] Used the [src.name] ([src.imp.name]) to implant [M.name] ([M.ckey])") - msg_admin_attack("[user.name] ([user.ckey]) implanted [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)]) (JMP)") + M.attack_log += text("\[[time_stamp()]\] Implanted with [name] ([imp.name]) by [user.name] ([user.ckey])") + user.attack_log += text("\[[time_stamp()]\] Used the [name] ([imp.name]) to implant [M.name] ([M.ckey])") + msg_admin_attack("[user.name] ([user.ckey]) implanted [M.name] ([M.ckey]) with [name] (INTENT: [uppertext(user.a_intent)]) (JMP)") user.show_message("You implanted the implant into [M].") - if(src.imp.implanted(M, user)) - src.imp.forceMove(M) - src.imp.imp_in = M - src.imp.implanted = 1 - if (ishuman(M)) + if(imp.implanted(M, user)) + imp.forceMove(M) + imp.imp_in = M + imp.implanted = 1 + if(ishuman(M)) var/mob/living/carbon/human/H = M var/datum/organ/external/affected = H.get_organ(user.zone_sel.selecting) - affected.implants += src.imp + affected.implants += imp imp.part = affected M:implanting = 0 - src.imp = null + imp = null update() - return /* +/obj/item/weapon/implanter/New() + if(imp_type) + imp = new imp_type(src) + ..() + update() + /obj/item/weapon/implanter/traitor name = "greytide conversion kit" desc = "Any humanoid injected with this implant will become loyal to the injector and the greytide, unless of course the host is already loyal to someone else." - -/obj/item/weapon/implanter/traitor/New() - src.imp = new /obj/item/weapon/implant/traitor(src) - ..() - update() - return*/ + imp_type = /obj/item/weapon/implant/traitor +*/ /obj/item/weapon/implanter/loyalty name = "implanter-loyalty" - -/obj/item/weapon/implanter/loyalty/New() - src.imp = new /obj/item/weapon/implant/loyalty( src ) - ..() - update() - return - - + imp_type = /obj/item/weapon/implant/loyalty /obj/item/weapon/implanter/explosive name = "implanter (E)" - -/obj/item/weapon/implanter/explosive/New() - src.imp = new /obj/item/weapon/implant/explosive( src ) - ..() - update() - return + imp_type = /obj/item/weapon/implant/explosive /obj/item/weapon/implanter/adrenalin name = "implanter-adrenalin" + imp_type = /obj/item/weapon/implant/adrenalin -/obj/item/weapon/implanter/adrenalin/New() - src.imp = new /obj/item/weapon/implant/adrenalin(src) - ..() - update() - return +/obj/item/weapon/implanter/peace + name = "implanter-pax" + desc = "An implanter containing a pax implant" + imp_type = /obj/item/weapon/implant/peace /obj/item/weapon/implanter/compressed name = "implanter (C)" icon_state = "cimplanter1" + imp_type = /obj/item/weapon/implant/compressed var/list/forbidden_types=list( // /obj/item/weapon/storage/bible // VG #11 - Recursion. ) -/obj/item/weapon/implanter/compressed/New() - imp = new /obj/item/weapon/implant/compressed( src ) - ..() - update() - return - /obj/item/weapon/implanter/compressed/update() - if (imp) + if(imp) var/obj/item/weapon/implant/compressed/c = imp if(!c.scanned) icon_state = "cimplanter1" @@ -115,16 +91,15 @@ icon_state = "cimplanter2" else icon_state = "cimplanter0" - return /obj/item/weapon/implanter/compressed/attack(mob/M as mob, mob/user as mob) // Attacking things in your hands tends to make this fuck up. if(!istype(M)) return var/obj/item/weapon/implant/compressed/c = imp - if (!c) + if(!c) return - if (c.scanned == null) + if(c.scanned == null) to_chat(user, "Please scan an object with the implanter first.") return ..() @@ -135,7 +110,7 @@ return if(istype(I) && imp) var/obj/item/weapon/implant/compressed/c = imp - if (c.scanned) + if(c.scanned) if(istype(I,/obj/item/weapon/storage)) ..() return diff --git a/code/game/objects/items/weapons/power_cells.dm b/code/game/objects/items/weapons/power_cells.dm index 28021c3472a..05d7ddd07d0 100644 --- a/code/game/objects/items/weapons/power_cells.dm +++ b/code/game/objects/items/weapons/power_cells.dm @@ -70,6 +70,10 @@ maxcharge = 10000 starting_materials = list(MAT_IRON = 700, MAT_GLASS = 60) +/obj/item/weapon/cell/high/cyborg + name = "cyborg rechargeable power cell" + maxcharge = 7500 + /obj/item/weapon/cell/high/empty/New() ..() charge = 0 @@ -108,6 +112,11 @@ w_type = RECYK_BIOLOGICAL minor_fault = 1 +/obj/item/weapon/cell/potato/soviet + charge = 15000 + maxcharge = 15000 + minor_fault = 0 + /obj/item/weapon/cell/crepe name = "power crêpe" desc = "Warning: May contain dairy products, 12,000kJ of searing death, gluten." @@ -118,6 +127,11 @@ w_type = RECYK_BIOLOGICAL minor_fault = 1 +/obj/item/weapon/cell/crepe/mommi + maxcharge = 10000 + charge = 10000 + minor_fault = 0 + /obj/item/weapon/cell/crepe/attack_self(var/mob/living/user) if(charge) user.visible_message("\The [user] takes a bite out of \the [src]", "You take a bite out of \the [src]") diff --git a/code/game/objects/items/weapons/shard.dm b/code/game/objects/items/weapons/shard.dm index 4304fb59f21..253d9fcbb54 100644 --- a/code/game/objects/items/weapons/shard.dm +++ b/code/game/objects/items/weapons/shard.dm @@ -108,12 +108,12 @@ /obj/item/weapon/shard/Crossed(mob/living/AM) if(istype(AM)) if(AM.locked_to) //Mob is locked to something, so it's not actually stepping on the glass - playsound(get_turf(src), 'sound/effects/glass_step.ogg', 50, 1) //Make noise + playsound(src, 'sound/effects/glass_step.ogg', 50, 1) //Make noise return //Stop here if(AM.flying) //We don't check for lying yet because it's intended to hurt return else //Stepping on the glass - playsound(get_turf(src), 'sound/effects/glass_step.ogg', 50, 1) + playsound(src, 'sound/effects/glass_step.ogg', 50, 1) if(ishuman(AM)) var/mob/living/carbon/human/H = AM var/danger = FALSE diff --git a/code/game/objects/items/weapons/stock_parts.dm b/code/game/objects/items/weapons/stock_parts.dm index 8086add507e..996b9169ca5 100644 --- a/code/game/objects/items/weapons/stock_parts.dm +++ b/code/game/objects/items/weapons/stock_parts.dm @@ -54,7 +54,7 @@ to_chat(user, "You can't secure \the [src] to [istype(src.loc,/turf/space) ? "space" : "this"]!") return to_chat(user, "You discharge \the [src] and secure it to the floor.") - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + playsound(src, 'sound/items/Ratchet.ogg', 50, 1) switch(src.type) if(/obj/item/weapon/stock_parts/capacitor) new /obj/machinery/power/secured_capacitor(get_turf(src.loc)) diff --git a/code/game/objects/items/weapons/storage/backpack.dm b/code/game/objects/items/weapons/storage/backpack.dm index 668987ac776..46d6c02ae56 100644 --- a/code/game/objects/items/weapons/storage/backpack.dm +++ b/code/game/objects/items/weapons/storage/backpack.dm @@ -16,7 +16,7 @@ max_combined_w_class = 21 /obj/item/weapon/storage/backpack/attackby(obj/item/weapon/W as obj, mob/user as mob) - playsound(get_turf(src), "rustle", 50, 1, -5) + playsound(src, "rustle", 50, 1, -5) . = ..() /* diff --git a/code/game/objects/items/weapons/storage/bags.dm b/code/game/objects/items/weapons/storage/bags.dm index a18330d8869..4c686ee95c3 100644 --- a/code/game/objects/items/weapons/storage/bags.dm +++ b/code/game/objects/items/weapons/storage/bags.dm @@ -37,6 +37,8 @@ storage_slots = 21 can_only_hold = list() // any cant_hold = list("/obj/item/weapon/disk/nuclear", "/obj/item/weapon/pinpointer") //No janiborg, stop stealing the pinpointer with your bag. + slot_flags = SLOT_BELT | SLOT_OCLOTHING + no_storage_slot = list(slot_wear_suit) //when worn on the suit slot it will function purely as a suit and will not store items /obj/item/weapon/storage/bag/trash/update_icon() if(contents.len == 0) @@ -67,6 +69,7 @@ body_parts_covered = FULL_HEAD|BEARD slot_flags = SLOT_BELT | SLOT_HEAD clothing_flags = BLOCK_BREATHING | BLOCK_GAS_SMOKE_EFFECT + no_storage_slot = list(slot_head) foldable = /obj/item/folded_bag obj/item/weapon/storage/bag/plasticbag/can_quick_store(var/obj/item/I) @@ -75,20 +78,6 @@ obj/item/weapon/storage/bag/plasticbag/can_quick_store(var/obj/item/I) obj/item/weapon/storage/bag/plasticbag/quick_store(var/obj/item/I) return handle_item_insertion(I,0) -/obj/item/weapon/storage/bag/plasticbag/mob_can_equip(mob/M, slot, disable_warning = 0, automatic = 0) - //Forbid wearing bags with something inside! - .=..() - if(contents.len && (slot == slot_head)) - return CANNOT_EQUIP - -/obj/item/weapon/storage/bag/plasticbag/can_be_inserted() - if(isliving(loc)) - var/mob/living/L = loc - if(L.is_wearing_item(src, slot_head)) //Wearing the bag on the head - return FALSE - - return ..() - /obj/item/weapon/storage/bag/plasticbag/suicide_act(mob/user) user.visible_message("[user] puts the [src.name] over \his head and tightens the handles around \his neck! It looks like \he's trying to commit suicide.") return(OXYLOSS) @@ -110,6 +99,70 @@ obj/item/weapon/storage/bag/plasticbag/quick_store(var/obj/item/I) max_combined_w_class = 200 //Doesn't matter what this is, so long as it's more or equal to storage_slots * ore.w_class can_only_hold = list("/obj/item/weapon/ore") +/obj/item/weapon/storage/bag/ore/auto + name = "automatic ore loader" + desc = "A mining satchel with a built-in inserter used to automatically move ore over short distances." + icon_state = "tech_satchel" + actions_types = list(/datum/action/item_action/toggle_auto_handling) + var/handling = FALSE + var/event_key = null + +/datum/action/item_action/toggle_auto_handling + name = "Toggle Ore Loader" + +/datum/action/item_action/toggle_auto_handling/Trigger() + var/obj/item/weapon/storage/bag/ore/auto/T = target + var/mob/user = usr + + if(!usr) + if(!ismob(T.loc)) + return + user = T.loc + if(!istype(T)) + return + + T.handling = !T.handling + + to_chat(user, "You turn \the [T.name] [T.handling? "on":"off"].") + + if(T.handling == TRUE) + T.event_key = user.on_moved.Add(T, "mob_moved") + else + user.on_moved.Remove(T, "mob_moved") + T.event_key = null + +/obj/item/weapon/storage/bag/ore/auto/proc/auto_collect() + var/atom/collect_loc = get_turf(loc) + for(var/obj/item/weapon/ore/ore in collect_loc.contents) + preattack(collect_loc, src, TRUE) + break + +/obj/item/weapon/storage/bag/ore/auto/proc/auto_fill(var/mob/holder) + var/obj/structure/ore_box/box = null + if(istype(holder.pulling, /obj/structure/ore_box)) + box = holder.pulling + if(box) + for(var/obj/item/weapon/ore/ore in contents) + if(ore.material) + remove_from_storage(ore) + box.materials.addAmount(ore.material, 1) + qdel(ore) + +/obj/item/weapon/storage/bag/ore/auto/proc/mob_moved(var/list/event_args, var/mob/holder) + if(isrobot(holder)) + var/mob/living/silicon/robot/S = holder + if(locate(src) in S.get_all_slots()) + auto_collect() + auto_fill(holder) + else + if(holder.is_holding_item(src)) + auto_collect() + auto_fill(holder) + +/obj/item/weapon/storage/bag/ore/auto/dropped(mob/user) + if(event_key) + user.on_moved.Remove(src, "mob_moved") + event_key = null // ----------------------------- // Plant bag @@ -151,7 +204,7 @@ obj/item/weapon/storage/bag/plasticbag/quick_store(var/obj/item/I) var/played = FALSE for(var/obj/item/I in P.contents) if(seedify(I) && !played) - playsound(get_turf(P), 'sound/machines/juicerfast.ogg', 50, 1) + playsound(P, 'sound/machines/juicerfast.ogg', 50, 1) played = TRUE P.orient2hud(user) if(user.s_active) diff --git a/code/game/objects/items/weapons/storage/belt.dm b/code/game/objects/items/weapons/storage/belt.dm index 8db6d79dcb7..e2e6da4d9ae 100644 --- a/code/game/objects/items/weapons/storage/belt.dm +++ b/code/game/objects/items/weapons/storage/belt.dm @@ -40,7 +40,9 @@ "/obj/item/device/t_scanner", "/obj/item/device/analyzer", "/obj/item/taperoll/engineering", + "/obj/item/taperoll/syndie/engineering", "/obj/item/taperoll/atmos", + "/obj/item/taperoll/syndie/atmos", "/obj/item/weapon/extinguisher", "/obj/item/weapon/rcd_ammo", "/obj/item/weapon/reagent_containers/glass/fuelcan", @@ -98,7 +100,9 @@ "/obj/item/device/t_scanner", "/obj/item/device/analyzer", "/obj/item/taperoll/engineering", + "/obj/item/taperoll/syndie/engineering", "/obj/item/taperoll/atmos", + "/obj/item/taperoll/syndie/atmos", "/obj/item/weapon/extinguisher", "/obj/item/device/rcd/matter/engineering", "/obj/item/device/rcd/rpd", @@ -196,6 +200,7 @@ "/obj/item/device/radio/headset", "/obj/item/weapon/melee/baton", "/obj/item/taperoll/police", + "/obj/item/taperoll/syndie/police", "/obj/item/weapon/gun/energy/taser", "/obj/item/weapon/gun/projectile/sec", "/obj/item/weapon/legcuffs/bolas", @@ -329,6 +334,8 @@ /obj/item/weapon/storage/belt/lazarus/antag/New(loc, mob/user) var/blocked = list( /mob/living/simple_animal/hostile/hivebot/tele, + /mob/living/simple_animal/hostile/wendigo/evolved, + /mob/living/simple_animal/hostile/wendigo/alpha, ) var/list/critters = existing_typesof(/mob/living/simple_animal/hostile) - blocked // list of possible hostile mobs critters = shuffle(critters) diff --git a/code/game/objects/items/weapons/storage/bible.dm b/code/game/objects/items/weapons/storage/bible.dm index b53df7dadfb..bb26fdeaf57 100644 --- a/code/game/objects/items/weapons/storage/bible.dm +++ b/code/game/objects/items/weapons/storage/bible.dm @@ -96,7 +96,7 @@ if(M.stat == DEAD) //Our target is dead. RIP in peace user.visible_message("[user] [pick(attack_verb)] [M]'s lifeless body with \the [src].", "You bless [M]'s lifeless body with \the [src], trying to conjure [my_rel.deity_name]'s mercy on them.") - playsound(get_turf(src), "punch", 25, 1, -1) + playsound(src, "punch", 25, 1, -1) //TODO : Way to bring people back from death if they are your followers return 1 //Otherwise, there's so little we can do @@ -104,7 +104,7 @@ //Our target is alive, prepare the blessing user.visible_message("[user] [pick(attack_verb)] [M]'s head with \the [src].", "You bless [M]'s head with \the [src]. In the name of [my_rel.deity_name], bless thee!") - playsound(get_turf(src), "punch", 25, 1, -1) + playsound(src, "punch", 25, 1, -1) if(ishuman(M)) //Only humans can be vampires or cultists. isChaplain() checks are here to ensure only the proper chaplain has the gameplay-related interactions. var/mob/living/carbon/human/H = M @@ -151,7 +151,7 @@ A.reagents.add_reagent(HOLYWATER, water2holy) /obj/item/weapon/storage/bible/attackby(obj/item/weapon/W as obj, mob/user as mob) - playsound(get_turf(src), "rustle", 50, 1, -5) + playsound(src, "rustle", 50, 1, -5) . = ..() /obj/item/weapon/storage/bible/pickup(mob/living/user as mob) diff --git a/code/game/objects/items/weapons/storage/bluespace.dm b/code/game/objects/items/weapons/storage/bluespace.dm index cf94dd40127..f36600465dc 100644 --- a/code/game/objects/items/weapons/storage/bluespace.dm +++ b/code/game/objects/items/weapons/storage/bluespace.dm @@ -30,6 +30,9 @@ qdel(user) /obj/item/weapon/storage/backpack/holding/attackby(obj/item/weapon/W as obj, mob/user as mob) + . = ..() + if(!.) + return if(W == src) return // HOLY FUCKING SHIT WHY STORAGE CODE, WHY - pomf var/obj/item/weapon/storage/backpack/holding/H = locate(/obj/item/weapon/storage/backpack/holding) in W @@ -38,8 +41,7 @@ return if(istype(W, /obj/item/weapon/storage/backpack/holding)) singulocreate(W, user) - return - . = ..() + //BoH+BoH=Singularity, WAS commented out /obj/item/weapon/storage/backpack/holding/proc/singulocreate(var/obj/item/weapon/storage/backpack/holding/H, var/mob/user) diff --git a/code/game/objects/items/weapons/storage/boxes.dm b/code/game/objects/items/weapons/storage/boxes.dm index e40d7956b9c..4963318fa88 100644 --- a/code/game/objects/items/weapons/storage/boxes.dm +++ b/code/game/objects/items/weapons/storage/boxes.dm @@ -458,46 +458,51 @@ /obj/item/weapon/storage/box/lethalshells name = "lethal shells" icon_state = "lethal shells" + storage_slots = 16 /obj/item/weapon/storage/box/lethalshells/New() ..() - for(var/i=0,i<15,i++) + for(var/i in 1 to 16) new /obj/item/ammo_casing/shotgun(src) /obj/item/weapon/storage/box/beanbagshells name = "bean bag shells" icon_state = "bean bag shells" + storage_slots = 16 /obj/item/weapon/storage/box/beanbagshells/New() ..() - for(var/i=0,i<15,i++) + for(var/i in 1 to 16) new /obj/item/ammo_casing/shotgun/beanbag(src) /obj/item/weapon/storage/box/stunshells name = "stun shells" icon_state = "stun shells" + storage_slots = 16 /obj/item/weapon/storage/box/stunshells/New() ..() - for(var/i=0,i<15,i++) + for(var/i in 1 to 16) new /obj/item/ammo_casing/shotgun/stunshell(src) /obj/item/weapon/storage/box/dartshells name = "shotgun darts" icon_state = "dart shells" + storage_slots = 16 /obj/item/weapon/storage/box/dartshells/New() ..() - for(var/i=0,i<15,i++) + for(var/i in 1 to 16) new /obj/item/ammo_casing/shotgun/dart(src) /obj/item/weapon/storage/box/buckshotshells name = "buckshot shells" icon_state = "lethal shells" + storage_slots = 16 /obj/item/weapon/storage/box/buckshotshells/New() ..() - for(var/i=0,i<15,i++) + for(var/i in 1 to 16) new /obj/item/ammo_casing/shotgun/buckshot(src) /obj/item/weapon/storage/box/labels diff --git a/code/game/objects/items/weapons/storage/briefcase.dm b/code/game/objects/items/weapons/storage/briefcase.dm index dfc0fd77d89..932675a5954 100644 --- a/code/game/objects/items/weapons/storage/briefcase.dm +++ b/code/game/objects/items/weapons/storage/briefcase.dm @@ -33,7 +33,7 @@ to_chat(user, "The [src] slips out of your hand and hits your head.") user.take_organ_damage(10) user.Paralyse(2) - playsound(get_turf(src), "swing_hit", 50, 1, -1) + playsound(src, "swing_hit", 50, 1, -1) return ..() diff --git a/code/game/objects/items/weapons/storage/lockbox.dm b/code/game/objects/items/weapons/storage/lockbox.dm index 0638bda8553..61923ae5a7d 100644 --- a/code/game/objects/items/weapons/storage/lockbox.dm +++ b/code/game/objects/items/weapons/storage/lockbox.dm @@ -83,7 +83,6 @@ ..() if(health <= 0) for(var/atom/movable/A in src) - for(var/obj/O in src) remove_from_storage(A, get_turf(src)) qdel(src) @@ -96,51 +95,34 @@ if(2) if(prob(80)) for(var/atom/movable/A in src) - for(var/obj/O in src) remove_from_storage(A, get_turf(src)) A.ex_act(3) qdel(src) if(3) if(prob(50)) for(var/atom/movable/A in src) - for(var/obj/O in src) remove_from_storage(A, get_turf(src)) qdel(src) /obj/item/weapon/storage/lockbox/emp_act(severity) ..() if(!broken) + var/probab switch(severity) if(1) - if(prob(80)) - locked = !locked - src.update_icon() - if(!locked) - for(var/atom/movable/A in src) - for(var/obj/O in src) - remove_from_storage(A, get_turf(src)) - if(oneuse) - qdel(src) + probab = 80 if(2) - if(prob(50)) - locked = !locked - src.update_icon() - if(!locked) - for(var/atom/movable/A in src) - for(var/obj/O in src) - remove_from_storage(A, get_turf(src)) - if(oneuse) - qdel(src) - if(3) - if(prob(25)) - locked = !locked - src.update_icon() - if(!locked) - for(var/atom/movable/A in src) - for(var/obj/O in src) - remove_from_storage(A, get_turf(src)) - if(oneuse) - qdel(src) + probab = 50 + if(prob(probab)) + locked = !locked + src.update_icon() + if(!locked) + for(var/atom/movable/A in src) + remove_from_storage(A, get_turf(src)) + if(oneuse) + qdel(src) + + /obj/item/weapon/storage/lockbox/update_icon() ..() @@ -166,6 +148,7 @@ /obj/item/weapon/storage/lockbox/tracking name = "lockbox (tracking implants)" req_one_access = list(access_security) + storage_slots = 5 /obj/item/weapon/storage/lockbox/tracking/New() ..() @@ -178,6 +161,7 @@ /obj/item/weapon/storage/lockbox/chem name = "lockbox (chemical implants)" req_one_access = list(access_security) + storage_slots = 5 /obj/item/weapon/storage/lockbox/chem/New() ..() diff --git a/code/game/objects/items/weapons/storage/secure.dm b/code/game/objects/items/weapons/storage/secure.dm index 4ab6add1a9c..c9cf8f2e650 100644 --- a/code/game/objects/items/weapons/storage/secure.dm +++ b/code/game/objects/items/weapons/storage/secure.dm @@ -156,7 +156,7 @@ if ((src.loc == user) && (src.locked == 1)) to_chat(usr, "[src] is locked and cannot be opened!") else if ((src.loc == user) && (!src.locked)) - playsound(get_turf(src), "rustle", 50, 1, -5) + playsound(src, "rustle", 50, 1, -5) if (user.s_active) user.s_active.close(user) //Close and re-open src.show_to(user) diff --git a/code/game/objects/items/weapons/storage/storage.dm b/code/game/objects/items/weapons/storage/storage.dm index b99f55420c2..edc6fb4fcc8 100644 --- a/code/game/objects/items/weapons/storage/storage.dm +++ b/code/game/objects/items/weapons/storage/storage.dm @@ -29,6 +29,7 @@ var/foldable = null // BubbleWrap - if set, can be folded (when empty) into a sheet of cardboard var/foldable_amount = 1 // Number of foldables to produce, if any - N3X var/internal_store = 0 + var/list/no_storage_slot = new/list()//if the item is equipped in a slot that is contained in this list, the item will act purely as a clothing item and not a storage item (ie plastic bags over head) /obj/item/weapon/storage/proc/can_use() return TRUE @@ -48,7 +49,7 @@ if(!(src.loc == usr) || (src.loc && src.loc.loc == usr)) return - playsound(get_turf(src), "rustle", 50, 1, -5) + playsound(src, "rustle", 50, 1, -5) if(!( M.restrained() ) && !( M.stat )) var/obj/abstract/screen/inventory/OI = over_object @@ -213,9 +214,14 @@ //This proc return 1 if the item can be picked up and 0 if it can't. //Set the stop_messages to stop it from printing messages -/obj/item/weapon/storage/proc/can_be_inserted(obj/item/W as obj, stop_messages = 0) +/obj/item/weapon/storage/proc/can_be_inserted(obj/item/W as obj, stop_messages = 0,mob/M, slot) if(!istype(W)) return //Not an item + if(isliving(loc)) + var/mob/living/L = loc + for (var/i in no_storage_slot) + if(L.is_wearing_item(src, i)) //prevents putting items into a storage item that's equipped on a no_storage_slot + return FALSE if(src.loc == W) return 0 //Means the item is already in the storage item @@ -450,7 +456,7 @@ return /obj/item/weapon/storage/attack_hand(mob/user as mob) - playsound(get_turf(src), "rustle", 50, 1, -5) + playsound(src, "rustle", 50, 1, -5) if(ishuman(user)) var/mob/living/carbon/human/H = user @@ -665,3 +671,10 @@ /obj/item/weapon/storage/proc/mass_remove(var/atom/A) for(var/obj/item/O in contents) remove_from_storage(O, A) + +/obj/item/weapon/storage/mob_can_equip(mob/M, slot, disable_warning = 0, automatic = 0) + //Forbids wearing a storage item in a no_storage_slot (ie plastic bags over head) with something already inside + .=..() + for (var/i in no_storage_slot) + if(contents.len && (slot == i)) + return CANNOT_EQUIP \ No newline at end of file diff --git a/code/game/objects/items/weapons/storage/toolbox.dm b/code/game/objects/items/weapons/storage/toolbox.dm index 252026cef82..c701288894d 100644 --- a/code/game/objects/items/weapons/storage/toolbox.dm +++ b/code/game/objects/items/weapons/storage/toolbox.dm @@ -116,3 +116,17 @@ new /obj/item/stack/cable_coil(src,30,color) new /obj/item/weapon/wirecutters(src) new /obj/item/device/multitool(src) + +/obj/item/weapon/storage/toolbox/robotics + name = "robotics toolbox" + +/obj/item/weapon/storage/toolbox/robotics/New() + ..() + var/color = pick("red","yellow","green","blue","pink","orange","cyan","white") + new /obj/item/device/robotanalyzer(src) + new /obj/item/weapon/crowbar(src) + new /obj/item/weapon/wrench(src) + new /obj/item/weapon/weldingtool(src) + new /obj/item/weapon/screwdriver(src) + new /obj/item/weapon/wirecutters(src) + new /obj/item/stack/cable_coil(src,30,color) diff --git a/code/game/objects/items/weapons/storage/uplink_kits.dm b/code/game/objects/items/weapons/storage/uplink_kits.dm index 2a24bd68ad7..cdbe431d2f5 100644 --- a/code/game/objects/items/weapons/storage/uplink_kits.dm +++ b/code/game/objects/items/weapons/storage/uplink_kits.dm @@ -222,9 +222,9 @@ New() ..() - var/obj/item/weapon/implanter/O = new(src) - O.imp = new /obj/item/weapon/implant/traitor(O) - O.update() + //new /obj/item/weapon/implanter/traitor(src) + //new /obj/item/weapon/implanter/traitor(src) + new /obj/item/clothing/glasses/sunglasses/sechud/syndishades(src) /obj/item/weapon/storage/box/syndie_kit/boolets name = "Shotgun shells" diff --git a/code/game/objects/items/weapons/surgery_tools.dm b/code/game/objects/items/weapons/surgery_tools.dm index a03c26b600e..d760f427d2f 100644 --- a/code/game/objects/items/weapons/surgery_tools.dm +++ b/code/game/objects/items/weapons/surgery_tools.dm @@ -220,7 +220,7 @@ if(isscrewdriver(used_item) && cauterymode) if(held) to_chat(user, "You detach \the [held] and \the [src] switches to cutting mode.") - playsound(get_turf(src), "sound/items/screwdriver.ogg", 10, 1) + playsound(src, "sound/items/screwdriver.ogg", 10, 1) held.add_fingerprint(user) held.forceMove(get_turf(src)) held = null @@ -233,7 +233,7 @@ to_chat(user, "There's already a cautery attached to \the [src].") else if(!held && user.drop_item(used_item, src)) to_chat(user, "You attach \the [used_item] to \the [src].") - playsound(get_turf(src), "sound/items/screwdriver.ogg", 10, 1) + playsound(src, "sound/items/screwdriver.ogg", 10, 1) src.held = used_item else to_chat(user, "You can't let go of \the [used_item]!") @@ -324,7 +324,8 @@ /obj/item/weapon/FixOVein - name = "FixOVein" + name = "fixOVein" + desc = "A small tube that contains synthetic vein to repair or replace damaged veins." icon = 'icons/obj/surgery.dmi' icon_state = "fixovein" inhand_states = list("left_hand" = 'icons/mob/in-hand/left/surgery_tools.dmi', "right_hand" = 'icons/mob/in-hand/right/surgery_tools.dmi') @@ -335,6 +336,54 @@ origin_tech = Tc_MATERIALS + "=1;" + Tc_BIOTECH + "=3" var/usage_amount = 10 +/obj/item/weapon/FixOVein/clot + name = "capillary laying operation tool" //C.L.O.T. + desc = "A canister like tool that has two containers on it that stores synthetic vein or biofoam. There's a small processing port on the side where gauze can be inserted to produce biofoam." + icon = 'icons/obj/surgery.dmi' + icon_state = "clot" + inhand_states = list("left_hand" = 'icons/mob/in-hand/left/surgery_tools.dmi', "right_hand" = 'icons/mob/in-hand/right/surgery_tools.dmi') + item_state = "clot" + sharpness = null + sharpness_flags = null + surgery_speed = 0.5 + origin_tech = Tc_MATERIALS + "=5;" + Tc_BIOTECH + "=5;" + Tc_ENGINEERING + "=4" + var/foam = 0 + +/obj/item/weapon/FixOVein/clot/examine(mob/user) + ..() + to_chat(user, "\The [src] contains [foam] unit[foam > 1 ? "s" : ""][foam == 0 ? "s" : ""] of biofoam.") + +/obj/item/weapon/FixOVein/clot/attack_self(mob/user) + if(foam) + if(!sharpness) + sharpness= 0.5 + sharpness_flags = SHARP_TIP + icon_state = "clot-F" + else + sharpness = null + sharpness_flags = null + icon_state = "clot" + to_chat(user, "You toggle \the [src]'s tip to [sharpness == 0.5 ? "inject biofoam" : "repair veins"].") + else + to_chat(user, "\The [src] requires biofoam to use the injection tip.You insert a bit of \the [W] into \the [src].") + W.use(1) + return + else if(istype(W, /obj/item/stack/medical/advanced/bruise_pack)) + foam = 5 + to_chat(user, "You insert a bit of \the [W] into \the [src].") + W.use(1) + else + to_chat(user, "You can't see any way to use \the [W] on \the [src].") + else + to_chat(user, "[foam == 5 ? "The [src] is full!" : ""] You can't see any way to use \the [W] on \the [src].") + + /obj/item/weapon/bonesetter name = "bone setter" icon = 'icons/obj/surgery.dmi' @@ -380,7 +429,7 @@ target.AdjustParalysis(-3) target.AdjustStunned(-3) target.AdjustKnockdown(-3) - playsound(get_turf(target), 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + playsound(target, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) target.visible_message( "[user] prods [target] trying to wake \him up!", "You prod [target] trying to wake \him up!", diff --git a/code/game/objects/items/weapons/switchtool.dm b/code/game/objects/items/weapons/switchtool.dm index de533bc56e2..7ec199abd55 100644 --- a/code/game/objects/items/weapons/switchtool.dm +++ b/code/game/objects/items/weapons/switchtool.dm @@ -58,6 +58,7 @@ return if(deployed) + edit_deploy(0) to_chat(user, "You store \the [deployed].") undeploy() else @@ -107,20 +108,20 @@ return TRUE /obj/item/weapon/switchtool/proc/remove_module(mob/user) - deployed.cant_drop = 0 + edit_deploy(0) deployed.forceMove(get_turf(user)) for(var/module in stored_modules) if(stored_modules[module] == deployed) stored_modules[module] = null break to_chat(user, "You successfully remove \the [deployed] from \the [src].") - playsound(get_turf(src), "sound/items/screwdriver.ogg", 10, 1) + playsound(src, "sound/items/screwdriver.ogg", 10, 1) undeploy() return TRUE /obj/item/weapon/switchtool/proc/undeploy() - playsound(get_turf(src), undeploy_sound, 10, 1) - deployed.cant_drop = 0 + playsound(src, undeploy_sound, 10, 1) + edit_deploy(0) deployed = null overlays.len = 0 w_class = initial(w_class) @@ -129,21 +130,33 @@ /obj/item/weapon/switchtool/proc/deploy(var/module) if(!(module in stored_modules)) return FALSE - if(!stored_modules[module]) return FALSE if(deployed) return FALSE - playsound(get_turf(src), deploy_sound, 10, 1) + playsound(src, deploy_sound, 10, 1) deployed = stored_modules[module] hmodule = get_module_name(module) - deployed.cant_drop = 1 overlays += get_module_name(module) w_class = max(w_class, deployed.w_class) update_icon() return TRUE +/obj/item/weapon/switchtool/proc/edit_deploy(var/doedit) + if(doedit) //Makes the deployed item take on the features of the switchtool. This is for attack animations and attack text. + deployed.name = name + deployed.icon = icon + deployed.icon_state = icon_state + deployed.overlays = overlays + deployed.cant_drop = TRUE + else //Revert the changes to the deployed item. + deployed.name = initial(deployed.name) + deployed.icon = initial(deployed.icon) + deployed.icon_state = initial(deployed.icon_state) + deployed.overlays = initial(deployed.overlays) + deployed.cant_drop = FALSE + /obj/item/weapon/switchtool/proc/choose_deploy(mob/user) var/list/potential_modules = list() for(var/module in stored_modules) @@ -157,6 +170,7 @@ else if(potential_modules.len == 1) deploy(potential_modules[1]) to_chat(user, "You deploy \the [potential_modules[1]]") + edit_deploy(1) return TRUE else @@ -169,6 +183,7 @@ break if(deploy(true_module)) to_chat(user, "You deploy \the [deployed].") + edit_deploy(1) return TRUE return @@ -363,7 +378,6 @@ /obj/item/weapon/switchtool/holo/update_icon() if(deployed) item_state = "[hmodule]" - deployed.appearance = appearance else item_state = "Hswitchtool" @@ -383,19 +397,20 @@ return FALSE set_light(brightness_min) overlays += "[hmodule]" + edit_deploy(1) if(istype(deployed, /obj/item/device/flashlight)) set_light(brightness_max) - //Since you can't turn off the welder inside the tool, I'm using the unused welder that very slowly regens fuel, looks like 1u per 5 byond seconds, thanks byond. +//Since you can't turn off the welder inside the tool, I'm using the unused welder that very slowly regens fuel, 5 fuel per process(). //It can be refulled manually, but since it starts active you will blow up welder tanks if deployed and then put to a tank. if(istype(deployed, /obj/item/weapon/weldingtool/experimental)) var/obj/item/weapon/weldingtool/experimental/weldingtool = deployed - weldingtool.welding = 1 - weldingtool.status = 1 - weldingtool.max_fuel = 50 - weldingtool.start_fueled = 1 + weldingtool.setWelding(1) /obj/item/weapon/switchtool/holo/undeploy() + if(istype(deployed, /obj/item/weapon/weldingtool/experimental)) + var/obj/item/weapon/weldingtool/experimental/weldingtool = deployed + weldingtool.setWelding(0) ..() set_light(0) @@ -484,4 +499,4 @@ "/obj/item/device/analyzer/scope:atmospheric analysis scope" = null, "/obj/item/weapon/solder/pre_fueled:soldering iron" = null, "/obj/item/device/silicate_sprayer:silicate sprayer" = null - ) \ No newline at end of file + ) diff --git a/code/game/objects/items/weapons/swords_axes_etc.dm b/code/game/objects/items/weapons/swords_axes_etc.dm index fb899584885..ffacd611eb0 100644 --- a/code/game/objects/items/weapons/swords_axes_etc.dm +++ b/code/game/objects/items/weapons/swords_axes_etc.dm @@ -52,7 +52,7 @@ if (user.a_intent == I_HURT) if(!..()) return - playsound(get_turf(src), "swing_hit", 50, 1, -1) + playsound(src, "swing_hit", 50, 1, -1) if (M.stuttering < 8 && (!(M_HULK in M.mutations)) /*&& (!istype(H:wear_suit, /obj/item/clothing/suit/judgerobe))*/) M.stuttering = 8 M.Stun(8) @@ -61,7 +61,7 @@ if (O.client) O.show_message("[M] has been beaten with \the [src] by [user]!", 1, "You hear someone fall", 2) else - playsound(get_turf(src), 'sound/weapons/Genhit.ogg', 50, 1, -1) + playsound(src, 'sound/weapons/Genhit.ogg', 50, 1, -1) M.Stun(5) M.Knockdown(5) M.attack_log += text("\[[time_stamp()]\] Has been attacked with [src.name] by [user.name] ([user.ckey])") @@ -120,7 +120,7 @@ w_class = initial(w_class) force = initial(force) //not so robust now attack_verb = list("hits", "punches") - playsound(get_turf(src), 'sound/weapons/empty.ogg', 50, 1) + playsound(src, 'sound/weapons/empty.ogg', 50, 1) add_fingerprint(user) if(!blood_overlays["[type][icon_state]"]) @@ -156,11 +156,11 @@ if(!..()) return if(!isrobot(target)) - playsound(get_turf(src), "swing_hit", 50, 1, -1) + playsound(src, "swing_hit", 50, 1, -1) //target.Stun(4) //naaah target.Knockdown(4) else - playsound(get_turf(src), 'sound/weapons/Genhit.ogg', 50, 1, -1) + playsound(src, 'sound/weapons/Genhit.ogg', 50, 1, -1) target.Knockdown(2) target.attack_log += text("\[[time_stamp()]\] Has been attacked with [src.name] by [user.name] ([user.ckey])") user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to attack [target.name] ([target.ckey])") @@ -272,3 +272,11 @@ else parent_borer.chemicals -= 5 sleep(10) + +/obj/item/weapon/melee/training_sword + name = "training sword" + desc = "A blunt object in the shape of a one handed sword." + icon_state = "grey_sword" + inhand_states = list("left_hand" = 'icons/mob/in-hand/left/swords_axes.dmi', "right_hand" = 'icons/mob/in-hand/right/swords_axes.dmi') + item_state = "grey_sword" + force = 4 diff --git a/code/game/objects/items/weapons/table_rack_parts.dm b/code/game/objects/items/weapons/table_rack_parts.dm index 12e7fefec97..1d2477d84da 100644 --- a/code/game/objects/items/weapons/table_rack_parts.dm +++ b/code/game/objects/items/weapons/table_rack_parts.dm @@ -20,6 +20,8 @@ flags = FPRINT siemens_coefficient = 1 attack_verb = list("slams", "bashes", "batters", "bludgeons", "thrashes", "whacks") + var/table_type = /obj/structure/table + sheet_type = /obj/item/stack/sheet/metal /obj/item/weapon/table_parts/cultify() new /obj/item/weapon/table_parts/wood(loc) @@ -28,7 +30,7 @@ /obj/item/weapon/table_parts/attackby(obj/item/weapon/W, mob/user) ..() if (iswrench(W)) - drop_stack(/obj/item/stack/sheet/metal, user.loc, 1, user) + drop_stack(sheet_type, user.loc, 1, user) qdel(src) return if (istype(W, /obj/item/stack/rods)) @@ -48,13 +50,15 @@ to_chat(user, "You add glass panes to \the [name].") glass.use(1) qdel(src) - /obj/item/weapon/table_parts/attack_self(mob/user) - new /obj/structure/table(user.loc) + if(locate(/obj/structure/table) in get_turf(user)) + to_chat(user, "There is already a table here!") + return + + new table_type(user.loc) user.drop_item(src, force_drop = 1) qdel(src) - /obj/item/weapon/table_parts/reinforced name = "reinforced table parts" desc = "Hard table parts. Well...harder..." @@ -65,32 +69,28 @@ melt_temperature=MELTPOINT_STEEL flags = FPRINT siemens_coefficient = 1 + table_type = /obj/structure/table/reinforced /obj/item/weapon/table_parts/reinforced/attackby(obj/item/weapon/W, mob/user) if (iswrench(W)) - drop_stack(/obj/item/stack/sheet/metal, user.loc, 1, user) + drop_stack(sheet_type, user.loc, 1, user) drop_stack(/obj/item/stack/rods, user.loc, 1, user) qdel(src) -/obj/item/weapon/table_parts/reinforced/attack_self(mob/user) - new /obj/structure/table/reinforced(user.loc) - user.drop_item(src, force_drop = 1) - qdel(src) - return - - /obj/item/weapon/table_parts/wood name = "wooden table parts" desc = "Keep away from fire." icon_state = "wood_tableparts" flags = 0 + table_type = /obj/structure/table/woodentable + sheet_type = /obj/item/stack/sheet/wood /obj/item/weapon/table_parts/wood/cultify() return /obj/item/weapon/table_parts/wood/attackby(obj/item/weapon/W, mob/user) if (iswrench(W)) - drop_stack(/obj/item/stack/sheet/wood, user.loc, 1, user) + drop_stack(sheet_type, user.loc, 1, user) qdel(src) return if (istype(W, /obj/item/stack/tile/grass)) @@ -106,24 +106,15 @@ /obj/item/weapon/table_parts/wood/poker name = "gambling table parts" icon_state = "gambling_tableparts" - -/obj/item/weapon/table_parts/wood/attack_self(mob/user) - new /obj/structure/table/woodentable(user.loc) - user.drop_item(src, force_drop = 1) - qdel(src) - return + table_type = /obj/structure/table/woodentable/poker + sheet_type = /obj/item/stack/sheet/wood /obj/item/weapon/table_parts/wood/poker/attackby(obj/item/weapon/W, mob/user) if (iswrench(W)) - drop_stack(/obj/item/stack/sheet/wood, user.loc, 1, user) + drop_stack(sheet_type, user.loc, 1, user) drop_stack(/obj/item/stack/tile/grass, user.loc, 1, user) qdel(src) -/obj/item/weapon/table_parts/wood/poker/attack_self(mob/user) - new /obj/structure/table/woodentable/poker(user.loc) - user.drop_item(src, force_drop = 1) - qdel(src) - /obj/item/weapon/table_parts/glass name = "glass table parts" desc = "Glass table parts for the spaceman with style." @@ -134,18 +125,14 @@ melt_temperature=MELTPOINT_GLASS flags = FPRINT siemens_coefficient = 0 //copying from glass sheets and shards even if its bad balance + table_type = /obj/structure/table/glass /obj/item/weapon/table_parts/glass/attackby(obj/item/weapon/W, mob/user) if (iswrench(W)) drop_stack(/obj/item/stack/sheet/glass/glass, loc, 1, user) - drop_stack(/obj/item/stack/sheet/metal, loc, 1, user) + drop_stack(sheet_type, loc, 1, user) qdel(src) -/obj/item/weapon/table_parts/glass/attack_self(mob/user) - new /obj/structure/table/glass(user.loc) - qdel(src) - - /obj/item/weapon/rack_parts name = "rack parts" desc = "Parts of a rack." @@ -160,7 +147,7 @@ /obj/item/weapon/rack_parts/attackby(obj/item/weapon/W, mob/user) ..() if (iswrench(W)) - drop_stack(/obj/item/stack/sheet/metal, user.loc, 1, user) + drop_stack(sheet_type, user.loc, 1, user) qdel(src) return if(istype(W, /obj/item/weapon/weldingtool)) diff --git a/code/game/objects/items/weapons/tanks/tank_types.dm b/code/game/objects/items/weapons/tanks/tank_types.dm index f9066049b27..3cbdea1eb20 100644 --- a/code/game/objects/items/weapons/tanks/tank_types.dm +++ b/code/game/objects/items/weapons/tanks/tank_types.dm @@ -20,6 +20,11 @@ . = ..() air_contents.adjust((6 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C)) +/obj/item/weapon/tank/oxygen/empty/New() + ..() + air_contents.oxygen = 0 + air_contents.update_values() + /obj/item/weapon/tank/oxygen/yellow desc = "A tank of oxygen, this one is yellow." icon_state = "oxygen_f" @@ -69,6 +74,11 @@ . = ..() air_contents.adjust(, , , (3 * ONE_ATMOSPHERE) * 70 / (R_IDEAL_GAS_EQUATION * T20C)) +/obj/item/weapon/tank/plasma/empty/New() + ..() + air_contents.toxins = 0 + air_contents.update_values() + /obj/item/weapon/tank/plasma/attackby(obj/item/weapon/W as obj, mob/user as mob) ..() diff --git a/code/game/objects/items/weapons/tanks/tanks.dm b/code/game/objects/items/weapons/tanks/tanks.dm index 41f960c7c13..2dd534d4f36 100644 --- a/code/game/objects/items/weapons/tanks/tanks.dm +++ b/code/game/objects/items/weapons/tanks/tanks.dm @@ -284,7 +284,7 @@ if(!T) return T.assume_air(air_contents) - playsound(get_turf(src), 'sound/effects/spray.ogg', 10, 1, -3) + playsound(src, 'sound/effects/spray.ogg', 10, 1, -3) qdel(src) diff --git a/code/game/objects/items/weapons/teleportation.dm b/code/game/objects/items/weapons/teleportation.dm index 1223dce3606..fa8c0aabbc6 100644 --- a/code/game/objects/items/weapons/teleportation.dm +++ b/code/game/objects/items/weapons/teleportation.dm @@ -120,6 +120,27 @@ Frequency: src.attack_self(M) return +/obj/item/weapon/bananapeel/bluespace + name = "bluespace banana peel" + desc = "A peel from a bluespace banana." + icon = 'icons/obj/items.dmi' + icon_state = "bluespacebanana_peel" + item_state = "bluespacebanana_peel" + +/obj/item/weapon/bananapeel/bluespace/Crossed(AM as mob|obj) + if (istype(AM, /mob/living/carbon)) + var/mob/living/carbon/M = AM + if (M.Slip(2, 2, 1)) + M.simple_message("You slipped on the [name]!", + "Something is scratching at your feet! Oh god!") + if(istype(AM,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = AM + var/obj/teleported_shoes = H.get_item_by_slot(slot_shoes) + var/tele_destination = pick_rand_tele_turf(H, src.potency/15, src.potency/10) + if(teleported_shoes && tele_destination) + H.drop_from_inventory(teleported_shoes) + teleported_shoes.forceMove(tele_destination) + spark(H.loc) /* * Hand-tele @@ -142,12 +163,50 @@ Frequency: var/list/portals = list() var/charge = HANDTELE_MAX_CHARGE//how many pairs of portal can the hand-tele sustain at once. a new charge is added every 30 seconds until the maximum is reached.. var/recharging = 0 + var/destination_id + var/destination_name /obj/item/weapon/hand_tele/attack_self(mob/user as mob) var/turf/current_location = get_turf(user)//What turf is the user on? if(!current_location||current_location.z==2||current_location.z>=7)//If turf was not found or they're on z level 2 or >7 which does not currently exist. to_chat(user, "\The [src] is malfunctioning.") return + + if(charge < HANDTELE_PORTAL_COST) + user.show_message("\The [src] is recharging!") + return + + if(!destination_id) + if(!choose_destination(user)) + return + var/T = destination_id + + if((destination_name == "None (Dangerous)") && prob(5)) + T = locate(rand(7, world.maxx - 7), rand(7, world.maxy -7), map.zTCommSat) + + var/turf/U = get_turf(src) + U.visible_message("Locked In.") + var/obj/effect/portal/P1 = new (U) + var/obj/effect/portal/P2 = new (get_turf(T)) + P1.target = P2 + P2.target = P1 + P2.icon_state = "portal1" + P1.creator = src + P2.creator = src + P1.blend_icon(P2) + P2.blend_icon(P1) + P1.owner = user + P2.owner = user + portals += P1 + portals += P2 + src.add_fingerprint(user) + + charge = max(charge - HANDTELE_PORTAL_COST,0) + if(!recharging) + recharging = 1 + processing_objects.Add(src) + +/obj/item/weapon/hand_tele/proc/choose_destination(var/mob/user) var/list/L = list( ) for(var/obj/machinery/computer/teleporter/R in machines) for(var/obj/machinery/teleport/hub/com in locate(R.x + 2, R.y, R.z)) @@ -173,40 +232,20 @@ Frequency: L["None (Dangerous)"] = pick(turfs) turfs = null - - var/t1 = input(user, "Please select a teleporter to lock in on.", "Hand Teleporter") in L + var/destination_name = input(user, "Please select a teleporter to lock in on.", "Hand Teleporter") in L + var/destination_id = L[destination_name] if((user.get_active_hand() != src || user.stat || user.restrained())) + return 0 + else + src.destination_name = destination_name + src.destination_id = destination_id + return 1 + +/obj/item/weapon/hand_tele/AltClick(var/mob/usr) + if((usr.incapacitated() || !Adjacent(usr))) return - if(charge < HANDTELE_PORTAL_COST) - user.show_message("\The [src] is recharging!") - return - var/T = L[t1] - - if((t1 == "None (Dangerous)") && prob(5)) - T = locate(rand(7, world.maxx - 7), rand(7, world.maxy -7), map.zTCommSat) - - var/turf/U = get_turf(src) - U.visible_message("Locked In.") - var/obj/effect/portal/P1 = new (U) - var/obj/effect/portal/P2 = new (get_turf(T)) - P1.target = P2 - P2.target = P1 - P2.icon_state = "portal1" - P1.creator = src - P2.creator = src - P1.blend_icon(P2) - P2.blend_icon(P1) - P1.owner = user - P2.owner = user - portals += P1 - portals += P2 - src.add_fingerprint(user) - - charge = max(charge - HANDTELE_PORTAL_COST,0) - if(!recharging) - recharging = 1 - processing_objects.Add(src) + choose_destination(usr) /obj/item/weapon/hand_tele/process() charge = min(HANDTELE_MAX_CHARGE,charge+1) diff --git a/code/game/objects/items/weapons/tools.dm b/code/game/objects/items/weapons/tools.dm index d6e87a494ac..5610bcfeee2 100644 --- a/code/game/objects/items/weapons/tools.dm +++ b/code/game/objects/items/weapons/tools.dm @@ -341,7 +341,7 @@ if (istype(O, /obj/structure/reagent_dispensers/fueltank) && get_dist(src,O) <= 1 && !src.welding) O.reagents.trans_to(src, max_fuel) to_chat(user, "Welder refueled") - playsound(get_turf(src), 'sound/effects/refill.ogg', 50, 1, -6) + playsound(src, 'sound/effects/refill.ogg', 50, 1, -6) return else if (istype(O, /obj/structure/reagent_dispensers/fueltank) && get_dist(src,O) <= 1 && src.welding) message_admins("[key_name_admin(user)] triggered a fueltank explosion.") @@ -404,6 +404,7 @@ /obj/item/weapon/weldingtool/proc/setWelding(var/temp_welding) //If we're turning it on if(temp_welding > 0) + src.welding = 1 if (remove_fuel(1)) to_chat(usr, "\The [src] switches on.") src.force = 15 @@ -526,7 +527,7 @@ start_fueled = 0 /obj/item/weapon/weldingtool/largetank - name = "Industrial Welding Tool" + name = "industrial welding tool" desc = "The cutting edge between portability and tank size." icon_state = "welder_large" max_fuel = 40 @@ -537,7 +538,7 @@ start_fueled = 0 /obj/item/weapon/weldingtool/hugetank - name = "Upgraded Welding Tool" + name = "upgraded welding tool" desc = "A large tank for a large job." icon_state = "welder_larger" max_fuel = 80 @@ -566,7 +567,7 @@ /obj/item/weapon/weldingtool/experimental - name = "Experimental Welding Tool" + name = "experimental welding tool" max_fuel = 40 w_class = W_CLASS_MEDIUM starting_materials = list(MAT_IRON = 70, MAT_GLASS = 120) @@ -724,8 +725,8 @@ to_chat(user, "It contains [reagents.get_reagent_amount(SACID) + reagents.get_reagent_amount(FORMIC_ACID)]/[src.max_fuel] units of fuel!") /obj/item/weapon/solder/attackby(obj/item/W as obj, mob/user as mob) - if(istype(W,/obj/item/weapon/reagent_containers/glass/)) - var/obj/item/weapon/reagent_containers/glass/G = W + if(istype(W,/obj/item/weapon/reagent_containers/) && W.flags & OPENCONTAINER) + var/obj/item/weapon/reagent_containers/G = W if(G.reagents.reagent_list.len>1) user.simple_message("The mixture is rejected by the tool.", "The tool isn't THAT thirsty.") diff --git a/code/game/objects/items/weapons/twohanded.dm b/code/game/objects/items/weapons/twohanded.dm index e1653b071e5..3b0eaceb336 100644 --- a/code/game/objects/items/weapons/twohanded.dm +++ b/code/game/objects/items/weapons/twohanded.dm @@ -129,7 +129,7 @@ hitsound = wielded ? "sound/weapons/blade1.ogg" : "sound/weapons/empty.ogg" if(user) user.update_inv_hands() - playsound(get_turf(src), wielded ? 'sound/weapons/saberon.ogg' : 'sound/weapons/saberoff.ogg', 50, 1) + playsound(src, wielded ? 'sound/weapons/saberon.ogg' : 'sound/weapons/saberoff.ogg', 50, 1) return /obj/item/weapon/dualsaber/attack(target as mob, mob/living/user as mob) @@ -183,7 +183,7 @@ hitsound = wielded ? "sound/weapons/blade1.ogg" : "sound/weapons/empty.ogg" if(user) user.update_inv_hands() - playsound(get_turf(src), wielded ? 'sound/weapons/saberon.ogg' : 'sound/weapons/saberoff.ogg', 50, 1) + playsound(src, wielded ? 'sound/weapons/saberon.ogg' : 'sound/weapons/saberoff.ogg', 50, 1) return /obj/item/weapon/dualsaber/bananabunch/attack(target as mob, mob/living/user as mob) diff --git a/code/game/objects/items/weapons/weaponry.dm b/code/game/objects/items/weapons/weaponry.dm index b95b9b03b5f..bdca17f7ecf 100644 --- a/code/game/objects/items/weapons/weaponry.dm +++ b/code/game/objects/items/weapons/weaponry.dm @@ -34,7 +34,7 @@ return(BRUTELOSS) /obj/item/weapon/sord/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) - playsound(get_turf(src), 'sound/weapons/bladeslice.ogg', 50, 1, -1) + playsound(src, 'sound/weapons/bladeslice.ogg', 50, 1, -1) user.adjustBruteLoss(0.5) return ..() @@ -460,6 +460,7 @@ obj/item/weapon/banhammer/admin to_add.pixel_x -= 12 * PIXEL_MULTIPLIER to_add.plane = FLOAT_PLANE underlays += to_add.appearance + // if(!base_overlay) // base_overlay = new // base_overlay.appearance = appearance diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index bfcd67b7826..3de5401d823 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -26,12 +26,14 @@ var/global/list/reagents_to_log = list(FUEL, PLASMA, PACID, SACID, AMUTATIONTOXI // Shit for mechanics. (MECH_*) var/mech_flags=0 - var/holomap = FALSE // Whether we should be on the holomap. - var/auto_holomap = FALSE // Whether we automatically soft-add ourselves to the holomap in New(), make sure this is false is something does it manually. plane = OBJ_PLANE var/defective = 0 - + var/quality = NORMAL //What level of quality this object is. + var/datum/material/material_type //What material this thing is made out of + var/event/on_use + var/sheet_type = /obj/item/stack/sheet/metal + var/sheet_amt = 1 var/can_take_pai = FALSE var/obj/item/device/paicard/integratedpai = null var/datum/delay_controller/pAImove_delayer = new(1, ARBITRARILY_LARGE_NUMBER) @@ -41,13 +43,20 @@ var/global/list/reagents_to_log = list(FUEL, PLASMA, PACID, SACID, AMUTATIONTOXI var/can_affix_to_dense_turf=0 var/has_been_invisible_sprayed = FALSE + var/impactsound + +// Whether this object can appear in holomaps +/obj/proc/supports_holomap() + return FALSE + +/obj/proc/add_self_to_holomap() + var/turf/T = loc + if(istype(T) && ticker && ticker.current_state != GAME_STATE_PLAYING) + T.add_holomap(src) /obj/New() ..() - if (auto_holomap && isturf(loc)) - var/turf/T = loc - T.soft_add_holomap(src) - verbs -= /obj/verb/remove_pai + on_use = new(owner=src) /obj/Destroy() for(var/mob/user in _using) @@ -59,8 +68,12 @@ var/global/list/reagents_to_log = list(FUEL, PLASMA, PACID, SACID, AMUTATIONTOXI if(integratedpai) qdel(integratedpai) integratedpai = null - verbs -= /obj/verb/remove_pai + if(on_use) + on_use.holder = null + qdel(on_use) + on_use = null + material_type = null //Don't qdel, they're held globally ..() /obj/item/proc/is_used_on(obj/O, mob/user) @@ -71,8 +84,7 @@ var/global/list/reagents_to_log = list(FUEL, PLASMA, PACID, SACID, AMUTATIONTOXI return 0 P.forceMove(src) integratedpai = P - verbs += /obj/verb/remove_pai - + verbs += /obj/proc/remove_pai /obj/attackby(obj/item/weapon/W, mob/user) if(can_take_pai && istype(W, /obj/item/device/paicard)) @@ -85,6 +97,10 @@ var/global/list/reagents_to_log = list(FUEL, PLASMA, PACID, SACID, AMUTATIONTOXI install_pai(W) state_controls_pai(W) playsound(src, 'sound/misc/cartridge_in.ogg', 25) + if(W) + INVOKE_EVENT(W.on_use, list("user" = user, "target" = src)) + if(W.material_type) + W.material_type.on_use(W, src, user) /obj/proc/state_controls_pai(obj/item/device/paicard/P) //text the pAI receives when is inserted into something. EXAMPLE: to_chat(P.pai, "Welcome to your new body") if(P.pai) @@ -145,7 +161,7 @@ var/global/list/reagents_to_log = list(FUEL, PLASMA, PACID, SACID, AMUTATIONTOXI if(istype(A,/obj/machinery)||(istype(A,/mob)&&user.secHUD)) A.attack_pai(user) -/obj/verb/remove_pai() +/obj/proc/remove_pai() set name = "Remove pAI" set category = "Object" set src in range(1) @@ -167,7 +183,7 @@ var/global/list/reagents_to_log = list(FUEL, PLASMA, PACID, SACID, AMUTATIONTOXI /obj/proc/eject_integratedpai_if_present() if(integratedpai) integratedpai.forceMove(get_turf(src)) - verbs -= /obj/verb/remove_pai + verbs -= /obj/proc/remove_pai var/obj/item/device/paicard/P = integratedpai integratedpai = null return P @@ -191,6 +207,7 @@ var/global/list/reagents_to_log = list(FUEL, PLASMA, PACID, SACID, AMUTATIONTOXI return 1 return + /obj/proc/cultify() qdel(src) @@ -215,6 +232,8 @@ var/global/list/reagents_to_log = list(FUEL, PLASMA, PACID, SACID, AMUTATIONTOXI set waitfor = FALSE processing_objects.Remove(src) +//At some point, this proc should be changed to work like remove_air() below does. +//However, this would likely cause problems, such as CO2 buildup in mechs and spacepods, so I'm not doing it right now. /obj/assume_air(datum/gas_mixture/giver) if(loc) return loc.assume_air(giver) @@ -222,10 +241,8 @@ var/global/list/reagents_to_log = list(FUEL, PLASMA, PACID, SACID, AMUTATIONTOXI return null /obj/remove_air(amount) - if(loc) - return loc.remove_air(amount) - else - return null + var/datum/gas_mixture/my_air = return_air() + return my_air?.remove(amount) /obj/return_air() if(loc) @@ -243,9 +260,6 @@ var/global/list/reagents_to_log = list(FUEL, PLASMA, PACID, SACID, AMUTATIONTOXI else return null -/atom/movable/proc/initialize() - return - /obj/proc/updateUsrDialog() if(in_use) var/is_in_use = 0 @@ -619,3 +633,39 @@ a { if(ismob(loc)) var/mob/M = loc M.regenerate_icons() + +/obj/proc/gen_quality() + var/material_mod = material_type ? material_type.quality_mod : 1 + var/turf/T = get_turf(src) + var/surrounding_mod = 1 + for(var/dir in alldirs) + for(var/obj/I in get_step(T, dir)) + if(I.quality > NORMAL || I.quality < NORMAL) + surrounding_mod *= I.quality/rand(1,3) + var/initial_quality = round((rand(1,3)*surrounding_mod)*material_mod) + quality = Clamp(initial_quality, AWFUL, LEGENDARY) + +/obj/proc/gen_description(mob/user) + var/material_mod = quality-GOOD>1 ? quality-GOOD : 0 + var/additional_description + if(material_mod) + additional_description = "On \the [src] is a carving, it depicts:\n" + var/list/characters = list() + for(var/i = 1 to material_mod) + if(prob(50)) //We're gonna use an atom + var/atom/AM = pick(existing_typesof(/mob/living/simple_animal)) + characters |= initial(AM.name) + else + var/strangething = pick("captain","clown","mime","\improper CMO","cargo technician","medical doctor","[user ? user : "stranger"]","octopus","changeling","\improper Nuclear Operative", "[pick("greyshirt", "greytide", "assistant")]", "xenomorph","catbeast","[user && user.mind && user.mind.heard_before.len ? pick(user.mind.heard_before) : "strange thing"]","Central Command","\improper Ian","[ticker.Bible_deity_name]","Nar-Sie","\improper Poly the Parrot","\improper Wizard","vox") + characters |= strangething + additional_description += "[i == material_mod ? " & a " : "[i > 1 ? ", a ": " A "]"][characters[i]]" + additional_description += ". They are in \the [pick("captains office","Space","mining outpost","vox outpost","a space station","[station_name()]","bar","kitchen","library","Science","void","Bluespace","Hell","Central Command")]" + if(material_mod > 2) + additional_description += ". They are [pick("[pick("fighting","robusting","attacking","beating up", "abusing")] [pick("each other", pick(characters))]","playing cards","firing lasers at [pick("something",pick(characters))]","crying","laughing","blank faced","screaming","cooking [pick("something", pick(characters))]", "eating [pick("something", pick(characters))]")]. " + if(characters.len > 1) + for(var/i in characters) + additional_description += "\The [i] is [pick("laughing","crying","screaming","naked","very naked","angry","jovial","manical","melting","fading away","making a plaintive gesture")]. " + additional_description += "The scene gives off a feeling of [pick("unease","empathy","fear","malice","dread","happiness","strangeness","insanity","drol")]. " + additional_description += "It is accented in hues of [pick("red","orange","yellow","green","blue","indigo","violet","white","black","cinnamon")]. " + if(additional_description) + desc = "[initial(desc)] \n [additional_description]" diff --git a/code/game/objects/storage/coat.dm b/code/game/objects/storage/coat.dm index 4dee0e25f68..38e384f7f1e 100644 --- a/code/game/objects/storage/coat.dm +++ b/code/game/objects/storage/coat.dm @@ -44,7 +44,7 @@ var/mob/M = usr if(istype(over_object, /obj/abstract/screen/inventory)) //was clickdragged to an inventory slot, we want to be able to take our coat off if(!M.incapacitated() && is_holder_of(M, src)) - playsound(get_turf(src), "rustle", 50, 1, -5) + playsound(src, "rustle", 50, 1, -5) var/obj/abstract/screen/inventory/OI = over_object if(OI.hand_index && M.put_in_hand_check(src, OI.hand_index)) diff --git a/code/game/objects/structures.dm b/code/game/objects/structures.dm index 29258e8a1d5..298646c4584 100644 --- a/code/game/objects/structures.dm +++ b/code/game/objects/structures.dm @@ -28,7 +28,7 @@ obj/structure/ex_act(severity) if(O.onBuckledUserKick(H, src)) return //don't return 1! we will do the normal "touch" action if so! - playsound(get_turf(src), 'sound/effects/grillehit.ogg', 50, 1) //Zth: I couldn't find a proper sound, please replace it + playsound(src, 'sound/effects/grillehit.ogg', 50, 1) //Zth: I couldn't find a proper sound, please replace it H.visible_message("[H] kicks \the [src].", "You kick \the [src].") if(prob(70)) @@ -48,6 +48,7 @@ obj/structure/ex_act(severity) if(!Move(get_step(loc, kick_dir))) break sleep(3) - + if(material_type) + material_type.on_use(H,src,null) /obj/structure/animationBolt(var/mob/firer) new /mob/living/simple_animal/hostile/mimic/copy(loc, src, firer, duration=SPELL_ANIMATION_TTL) diff --git a/code/game/objects/structures/barricade.dm b/code/game/objects/structures/barricade.dm index 03c3408ead2..6fc53cc77d2 100644 --- a/code/game/objects/structures/barricade.dm +++ b/code/game/objects/structures/barricade.dm @@ -14,6 +14,7 @@ anchored = 1 opacity = 1 //Wood isn't transparent, the last time I checked health = 60 //Fairly strong + layer = ABOVE_DOOR_LAYER var/busy = 0 //Oh god fucking do_after's var/materialtype = /obj/item/stack/sheet/wood @@ -48,7 +49,7 @@ user.delayNextAttack(10) health -= 2 healthcheck() - //playsound(get_turf(src), 'sound/effects/glassknock.ogg', 100, 1) + //playsound(src, 'sound/effects/glassknock.ogg', 100, 1) user.visible_message("[user] bangs against \the [src]!", \ "You bang against \the [src]!", \ "You hear banging.") @@ -56,7 +57,7 @@ //Knock against it else user.delayNextAttack(10) - //playsound(get_turf(src), 'sound/effects/glassknock.ogg', 50, 1) + //playsound(src, 'sound/effects/glassknock.ogg', 50, 1) user.visible_message("[user] knocks on \the [src].", \ "You knock on \the [src].", \ "You hear knocking.") diff --git a/code/game/objects/structures/cage.dm b/code/game/objects/structures/cage.dm index 637af90ff08..cd29b443d32 100644 --- a/code/game/objects/structures/cage.dm +++ b/code/game/objects/structures/cage.dm @@ -91,7 +91,7 @@ to_chat(user, "You start securing \the [src] to \the [loc].") spawn() - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1) + playsound(src, 'sound/items/Ratchet.ogg', 100, 1) if(do_after(user, src, 50)) anchored = !anchored to_chat(user, "[anchored ? "You successfully secure \the [src] to \the [loc]." : "You successfully unsecure \the [src] from \the [loc]."]") @@ -217,7 +217,7 @@ door_state = C_OPENED setDensity(FALSE) - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) update_icon() /obj/structure/cage/proc/add_mob(mob/victim) diff --git a/code/game/objects/structures/catwalk.dm b/code/game/objects/structures/catwalk.dm index 57dcdfc96fb..fad2699c63c 100644 --- a/code/game/objects/structures/catwalk.dm +++ b/code/game/objects/structures/catwalk.dm @@ -48,7 +48,7 @@ return 0 if(isscrewdriver(C)) to_chat(user, "You begin undoing the screws holding the catwalk together.") - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 80, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 80, 1) if(do_after(user, src, 30) && src) to_chat(user, "You finish taking taking the catwalk apart.") new /obj/item/stack/rods(src.loc, 2) diff --git a/code/game/objects/structures/clock.dm b/code/game/objects/structures/clock.dm new file mode 100644 index 00000000000..1964f25ec26 --- /dev/null +++ b/code/game/objects/structures/clock.dm @@ -0,0 +1,31 @@ +/obj/structure/clock + name = "grandfather clock" + desc = "Hickory dickory dock, the mouse ran up the clock, the clock struck one, the mouse was gone, hickory dickory dock." + icon = 'icons/obj/objects.dmi' + icon_state = "clock" + density = 1 + anchored = 1 + +/obj/structure/clock/update_icon() + if(anchored) + icon_state = "clock" + else + icon_state = "clock-broken" + +/obj/structure/clock/examine(mob/user) + ..() + if(anchored) + to_chat(user, "Station Time: [worldtime2text()]") + +/obj/structure/clock/attackby(obj/item/weapon/W, mob/user) + if(iswrench(W)) + if(do_after(user, src, 3 SECONDS)) + playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1) + anchored = !anchored + update_icon() + else + return ..() + +/obj/structure/clock/unanchored + anchored = 0 + icon_state = "clock-broken" \ No newline at end of file diff --git a/code/game/objects/structures/coatrack.dm b/code/game/objects/structures/coatrack.dm index a78009c3c25..375ebbd4f50 100644 --- a/code/game/objects/structures/coatrack.dm +++ b/code/game/objects/structures/coatrack.dm @@ -32,7 +32,7 @@ /obj/structure/coatrack/attack_hand(mob/user) if(suit) to_chat(user, "You pick up \the [suit] from \the [src]") - playsound(get_turf(src), "rustle", 50, 1, -5) + playsound(src, "rustle", 50, 1, -5) suit.forceMove(get_turf(src)) if(!user.get_active_hand()) user.put_in_hands(suit) @@ -42,7 +42,7 @@ if(hat) to_chat(user, "You pick up \the [hat] from \the [src]") - playsound(get_turf(src), "rustle", 50, 1, -5) + playsound(src, "rustle", 50, 1, -5) hat.forceMove(get_turf(src)) if(!user.get_active_hand()) user.put_in_hands(hat) @@ -54,17 +54,17 @@ if (istype(C, /obj/item/clothing/suit) && !suit && is_type_in_list(C, allowed_suits)) if(user.drop_item(C, src)) to_chat(user, "You place your [C] on \the [src]") - playsound(get_turf(src), "rustle", 50, 1, -5) + playsound(src, "rustle", 50, 1, -5) suit = C update_icon() else if (istype(C, /obj/item/clothing/head) && !hat && is_type_in_list(C, allowed_hats)) if(user.drop_item(C, src)) to_chat(user, "You place your [C] on \the [src]") - playsound(get_turf(src), "rustle", 50, 1, -5) + playsound(src, "rustle", 50, 1, -5) hat = C update_icon() else if(iswrench(C)) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + playsound(src, 'sound/items/Ratchet.ogg', 50, 1) getFromPool(/obj/item/stack/sheet/wood, get_turf(src), 2) qdel(src)//the hat and suit on the coat rack are automatically dropped by Destroy() else diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index 1d4df1dd315..fedfb38af5a 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -25,6 +25,8 @@ w_type = RECYK_METAL ignoreinvert = 1 +/obj/structure/closet/proc/canweld() + return 1 /obj/structure/closet/initialize() ..() @@ -221,7 +223,7 @@ /obj/structure/closet/beam_connect(var/obj/effect/beam/B) if(!processing_objects.Find(src)) processing_objects.Add(src) - testing("Connected [src] with [B]!") +// testing("Connected [src] with [B]!") return ..() /obj/structure/closet/beam_disconnect(var/obj/effect/beam/B) @@ -281,7 +283,7 @@ if(istype(W,/obj/item/tk_grab)) return 0 - if(istype(W, /obj/item/weapon/weldingtool)) + if(istype(W, /obj/item/weapon/weldingtool) && canweld()) var/obj/item/weapon/weldingtool/WT = W if(!WT.remove_fuel(0,user)) to_chat(user, "You need more welding fuel to complete this task.") @@ -296,7 +298,7 @@ else if(istype(W, /obj/item/stack/package_wrap)) return - else if(istype(W, /obj/item/weapon/weldingtool)) + else if(istype(W, /obj/item/weapon/weldingtool) && canweld()) var/obj/item/weapon/weldingtool/WT = W if(!WT.remove_fuel(0,user)) to_chat(user, "You need more welding fuel to complete this task.") diff --git a/code/game/objects/structures/crates_lockers/closets/fireaxe.dm b/code/game/objects/structures/crates_lockers/closets/fireaxe.dm index a674f043e44..23f9d81dce0 100644 --- a/code/game/objects/structures/crates_lockers/closets/fireaxe.dm +++ b/code/game/objects/structures/crates_lockers/closets/fireaxe.dm @@ -134,7 +134,7 @@ else if(iswrench(O) && src.localopened && !src.fireaxe) to_chat(user, "You disassemble \the [src].") - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1) + playsound(src, 'sound/items/Ratchet.ogg', 100, 1) new /obj/item/stack/sheet/plasteel (src.loc,2) qdel(src) if(smashed) diff --git a/code/game/objects/structures/crates_lockers/closets/gimmick.dm b/code/game/objects/structures/crates_lockers/closets/gimmick.dm index ae51bdcca63..f44b32df6e9 100644 --- a/code/game/objects/structures/crates_lockers/closets/gimmick.dm +++ b/code/game/objects/structures/crates_lockers/closets/gimmick.dm @@ -4,12 +4,71 @@ icon_state = "cabinet_closed" icon_closed = "cabinet_closed" icon_opened = "cabinet_open" + autoignition_temperature = AUTOIGNITION_WOOD + fire_fuel = 3 -/obj/structure/closet/cabinet/update_icon() - if(!opened) - icon_state = icon_closed - else - icon_state = icon_opened +/obj/structure/closet/cabinet/canweld() + return 0 + +/obj/structure/closet/cabinet/snow + name = "snow gear cabinet" + desc = "A cabinet filled with snow gear for extra-station activity." + var/obj/structure/hanger_rail/hanger_rail + +/obj/structure/closet/cabinet/snow/New() + ..() + hanger_rail = new (src) + +/obj/structure/closet/cabinet/snow/close() + . = ..() + if(.) + unlock_atom(hanger_rail) + hanger_rail.forceMove(src) + +/obj/structure/closet/cabinet/snow/open() + . = ..() + if(.) + hanger_rail.forceMove(get_turf(src)) + lock_atom(hanger_rail) + +/obj/structure/closet/cabinet/snow/Destroy() + ..() + qdel(hanger_rail) + hanger_rail = null + +/obj/structure/hanger_rail + icon = 'icons/obj/closet.dmi' + icon_state = "hanger_rail" + name = "hanger rail" + desc = "This rail is for holding NT standard-issue winter coats." + var/coats = 4 + density = 0 + anchored = 1 + flags = FPRINT + layer = ABOVE_OBJ_LAYER + +/obj/structure/hanger_rail/attack_hand(var/mob/user,params,proximity) + ..() + if(!proximity) + return + if(coats) + to_chat(user,"You remove a pair of boots and a coat from the hanger.") + add_fingerprint(user) + var/winterboots = new /obj/item/clothing/shoes/winterboots(get_turf(src)) + user.put_in_inactive_hand(winterboots) + var/wintercoat = new /obj/item/clothing/suit/wintercoat(get_turf(src)) + user.put_in_active_hand(wintercoat) + coats-- + update_icon() + +/obj/structure/hanger_rail/update_icon() + overlays.Cut() + for(var/i = 1 to coats) + overlays += image(icon,"coat[i]") + +/obj/structure/hanger_rail/New() + ..() + update_icon() /obj/structure/closet/cabinet/medivault name = "old cabinet" @@ -155,4 +214,4 @@ new /obj/item/weapon/storage/box/flashbangs(src) new /obj/item/clothing/head/helmet/thunderdome(src) new /obj/item/clothing/head/helmet/thunderdome(src) - new /obj/item/clothing/head/helmet/thunderdome(src) + new /obj/item/clothing/head/helmet/thunderdome(src) \ No newline at end of file diff --git a/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm b/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm index 39687b4c9ae..2c560211d3b 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm @@ -110,7 +110,7 @@ src.icon_state = src.icon_opened src.opened = 1 setDensity(FALSE) - playsound(get_turf(src), 'sound/machines/click.ogg', 15, 1, -3) + playsound(src, 'sound/machines/click.ogg', 15, 1, -3) else if(!can_open()) to_chat(user, "It won't budge!") diff --git a/code/game/objects/structures/crates_lockers/closets/secure/security.dm b/code/game/objects/structures/crates_lockers/closets/secure/security.dm index aa1f6387ada..028f494e54b 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm @@ -99,41 +99,44 @@ icon_broken = "hossecurebroken" icon_off = "hossecureoff" - New() - ..() - sleep(2) - if(prob(50)) - new /obj/item/weapon/storage/backpack/security(src) - else - new /obj/item/weapon/storage/backpack/satchel_sec(src) - new /obj/item/clothing/head/helmet/tactical/HoS(src) - new /obj/item/device/flashlight/tactical(src) - new /obj/item/clothing/accessory/holster/knife/boot/preloaded/tactical(src) - new /obj/item/clothing/suit/armor/vest(src) - new /obj/item/clothing/under/rank/head_of_security/jensen(src) - if(prob(50)) - new /obj/item/clothing/suit/armor/hos/jensen(src) - else - new /obj/item/clothing/suit/armor/hos/sundowner(src) - new /obj/item/clothing/head/helmet/tactical/HoS/dermal(src) - new /obj/item/weapon/cartridge/hos(src) - new /obj/item/device/detective_scanner(src) - new /obj/item/device/radio/headset/heads/hos(src) - new /obj/item/clothing/glasses/sunglasses/sechud(src) - new /obj/item/weapon/shield/riot(src) - new /obj/item/weapon/storage/lockbox/loyalty(src) - new /obj/item/weapon/storage/box/flashbangs(src) - new /obj/item/weapon/storage/belt/security(src) - new /obj/item/device/flash(src) - new /obj/item/weapon/melee/baton/loaded(src) - new /obj/item/weapon/storage/lockbox/lawgiver(src) - new /obj/item/ammo_storage/magazine/lawgiver(src) - new /obj/item/clothing/accessory/holster/handgun/waist(src) - new /obj/item/weapon/melee/telebaton(src) - new /obj/item/device/gps/secure(src) - return - - +/obj/structure/closet/secure_closet/hos/New() + ..() + sleep(2) + if(prob(50)) + new /obj/item/weapon/storage/backpack/security(src) + else + new /obj/item/weapon/storage/backpack/satchel_sec(src) + new /obj/item/clothing/head/helmet/tactical/HoS(src) + new /obj/item/device/flashlight/tactical(src) + new /obj/item/clothing/accessory/holster/knife/boot/preloaded/tactical(src) + new /obj/item/clothing/suit/armor/vest(src) + new /obj/item/clothing/under/rank/head_of_security/jensen(src) + if(prob(50)) + new /obj/item/clothing/suit/armor/hos/jensen(src) + else + new /obj/item/clothing/suit/armor/hos/sundowner(src) + new /obj/item/clothing/head/helmet/tactical/HoS/dermal(src) + new /obj/item/weapon/cartridge/hos(src) + new /obj/item/device/detective_scanner(src) + new /obj/item/device/radio/headset/heads/hos(src) + new /obj/item/clothing/glasses/sunglasses/sechud(src) + new /obj/item/weapon/shield/riot(src) + new /obj/item/weapon/storage/lockbox/loyalty(src) + new /obj/item/weapon/storage/box/flashbangs(src) + new /obj/item/weapon/storage/belt/security(src) + new /obj/item/device/flash(src) + new /obj/item/weapon/melee/baton/loaded(src) + new /obj/item/weapon/storage/lockbox/lawgiver(src) + new /obj/item/ammo_storage/magazine/lawgiver(src) + new /obj/item/clothing/accessory/holster/handgun/waist(src) + new /obj/item/weapon/melee/telebaton(src) + new /obj/item/device/gps/secure(src) + new /obj/item/clothing/suit/armor/hos(src) + new /obj/item/taperoll/police(src) + new /obj/item/device/hailer(src) + new /obj/item/weapon/reagent_containers/spray/pepper(src) + new /obj/item/weapon/grenade/flashbang(src) + new /obj/item/weapon/gun/energy/taser(src) /obj/structure/closet/secure_closet/warden name = "Warden's Locker" @@ -146,32 +149,35 @@ icon_off = "wardensecureoff" - New() - ..() - sleep(2) - if(prob(50)) - new /obj/item/weapon/storage/backpack/security(src) - else - new /obj/item/weapon/storage/backpack/satchel_sec(src) - new /obj/item/clothing/suit/armor/vest/security(src) - new /obj/item/clothing/under/rank/warden(src) - new /obj/item/clothing/suit/armor/vest/warden(src) - new /obj/item/clothing/head/helmet/tactical/warden(src) - new /obj/item/device/flashlight/tactical(src) -// new /obj/item/weapon/cartridge/security(src) - new /obj/item/device/radio/headset/headset_sec(src) - new /obj/item/clothing/glasses/sunglasses/sechud(src) - new /obj/item/weapon/storage/box/flashbangs(src) - new /obj/item/weapon/storage/belt/security(src) - new /obj/item/weapon/reagent_containers/spray/pepper(src) - new /obj/item/weapon/melee/baton/loaded(src) - new /obj/item/weapon/gun/energy/taser(src) - new /obj/item/weapon/storage/box/bolas(src) - new /obj/item/weapon/batteringram(src) - new /obj/item/device/gps/secure(src) - return - - +/obj/structure/closet/secure_closet/warden/New() + ..() + sleep(2) + if(prob(50)) + new /obj/item/weapon/storage/backpack/security(src) + else + new /obj/item/weapon/storage/backpack/satchel_sec(src) + new /obj/item/clothing/suit/armor/vest/security(src) + new /obj/item/clothing/under/rank/warden(src) + new /obj/item/clothing/suit/armor/vest/warden(src) + new /obj/item/clothing/head/helmet/tactical/warden(src) + new /obj/item/device/flashlight/tactical(src) +// new /obj/item/weapon/cartridge/security(src) + new /obj/item/device/radio/headset/headset_sec(src) + new /obj/item/clothing/glasses/sunglasses/sechud(src) + new /obj/item/weapon/storage/box/flashbangs(src) + new /obj/item/weapon/storage/belt/security(src) + new /obj/item/weapon/reagent_containers/spray/pepper(src) + new /obj/item/weapon/melee/baton/loaded(src) + new /obj/item/weapon/gun/energy/taser(src) + new /obj/item/weapon/storage/box/bolas(src) + new /obj/item/weapon/batteringram(src) + new /obj/item/device/gps/secure(src) + new /obj/item/taperoll/police(src) + new /obj/item/device/hailer(src) + new /obj/item/weapon/reagent_containers/spray/pepper(src) + new /obj/item/weapon/grenade/flashbang(src) + new /obj/item/clothing/accessory/holster/knife/boot/preloaded/tactical(src) + new /obj/item/weapon/gun/energy/taser(src) /obj/structure/closet/secure_closet/security name = "Security Officer's Locker" @@ -183,34 +189,32 @@ icon_broken = "secbroken" icon_off = "secoff" - New() - ..() - sleep(2) - if(prob(50)) - new /obj/item/weapon/storage/backpack/security(src) - else - new /obj/item/weapon/storage/backpack/satchel_sec(src) - new /obj/item/clothing/suit/armor/vest/security(src) - new /obj/item/clothing/head/helmet/tactical/sec/preattached(src) - new /obj/item/clothing/accessory/holster/knife/boot/preloaded/tactical(src) -// new /obj/item/weapon/cartridge/security(src) - new /obj/item/device/radio/headset/headset_sec(src) - new /obj/item/weapon/storage/belt/security(src) - new /obj/item/device/flash(src) - new /obj/item/weapon/reagent_containers/spray/pepper(src) - new /obj/item/weapon/grenade/flashbang(src) - new /obj/item/weapon/melee/baton/loaded(src) - new /obj/item/weapon/gun/energy/taser(src) - if(prob(50)) - new /obj/item/clothing/glasses/sunglasses/sechud/prescription(src) - else - new /obj/item/clothing/glasses/sunglasses/sechud(src) - new /obj/item/taperoll/police(src) - new /obj/item/device/hailer(src) //wonder if vg would spam this - new /obj/item/clothing/gloves/black(src) - new /obj/item/device/gps/secure(src) - return - +/obj/structure/closet/secure_closet/security/New() + ..() + sleep(2) + if(prob(50)) + new /obj/item/weapon/storage/backpack/security(src) + else + new /obj/item/weapon/storage/backpack/satchel_sec(src) + new /obj/item/clothing/suit/armor/vest/security(src) + new /obj/item/clothing/head/helmet/tactical/sec/preattached(src) + new /obj/item/clothing/accessory/holster/knife/boot/preloaded/tactical(src) +// new /obj/item/weapon/cartridge/security(src) + new /obj/item/device/radio/headset/headset_sec(src) + new /obj/item/weapon/storage/belt/security(src) + new /obj/item/device/flash(src) + new /obj/item/weapon/reagent_containers/spray/pepper(src) + new /obj/item/weapon/grenade/flashbang(src) + new /obj/item/weapon/melee/baton/loaded(src) + new /obj/item/weapon/gun/energy/taser(src) + if(prob(50)) + new /obj/item/clothing/glasses/sunglasses/sechud/prescription(src) + else + new /obj/item/clothing/glasses/sunglasses/sechud(src) + new /obj/item/taperoll/police(src) + new /obj/item/device/hailer(src) //wonder if vg would spam this + new /obj/item/clothing/gloves/black(src) + new /obj/item/device/gps/secure(src) /obj/structure/closet/secure_closet/security/cargo diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm index 89d42f9f094..f94701dc0b0 100644 --- a/code/game/objects/structures/crates_lockers/crates.dm +++ b/code/game/objects/structures/crates_lockers/crates.dm @@ -122,12 +122,7 @@ if(!gas) return null var/datum/gas_mixture/newgas = new/datum/gas_mixture() - newgas.oxygen = gas.oxygen - newgas.carbon_dioxide = gas.carbon_dioxide - newgas.nitrogen = gas.nitrogen - newgas.toxins = gas.toxins - newgas.volume = gas.volume - newgas.temperature = gas.temperature + newgas.copy_from(gas) if(newgas.temperature <= target_temp) return @@ -135,6 +130,7 @@ newgas.temperature -= cooling_power else newgas.temperature = target_temp + newgas.update_values() return newgas /obj/structure/closet/crate/freezer/surgery @@ -271,6 +267,22 @@ locked = 1 health = 1000 +/obj/structure/closet/crate/secure/anti_tamper + name = "Extra-secure crate" + +/obj/structure/closet/crate/secure/anti_tamper/Destroy() + if(locked) + visible_message("Something bursts open from within \the [src]!") + var/datum/effect/effect/system/smoke_spread/chem/S = new //Surprise! + S.attach(get_turf(src)) + S.chemholder.reagents.add_reagent(CAPSAICIN, 40) + S.chemholder.reagents.add_reagent(CONDENSEDCAPSAICIN, 16) + S.chemholder.reagents.add_reagent(SACID, 12) + S.set_up(src, 10, 0, loc) + spawn(0) + S.start() + ..() + /obj/structure/closet/crate/large name = "large crate" desc = "A hefty metal crate." @@ -399,7 +411,7 @@ return 0 if(!src.can_open()) return 0 - playsound(get_turf(src), sound_effect_open, 15, 1, -3) + playsound(src, sound_effect_open, 15, 1, -3) dump_contents() @@ -413,7 +425,7 @@ return 0 if(!src.can_close()) return 0 - playsound(get_turf(src), sound_effect_close, 15, 1, -3) + playsound(src, sound_effect_close, 15, 1, -3) take_contents() @@ -488,7 +500,7 @@ overlays += emag overlays += sparks spawn(6) overlays -= sparks //Tried lots of stuff but nothing works right. so i have to use this *sadface* - playsound(get_turf(src), "sparks", 60, 1) + playsound(src, "sparks", 60, 1) src.locked = 0 src.broken = 1 to_chat(user, "You unlock \the [src].") @@ -541,7 +553,7 @@ overlays += emag overlays += sparks spawn(6) overlays -= sparks //Tried lots of stuff but nothing works right. so i have to use this *sadface* - playsound(get_turf(src), 'sound/effects/sparks4.ogg', 75, 1) + playsound(src, 'sound/effects/sparks4.ogg', 75, 1) src.locked = 0 if(!opened && prob(20/severity)) if(!locked) diff --git a/code/game/objects/structures/crates_lockers/largecrate.dm b/code/game/objects/structures/crates_lockers/largecrate.dm index fe36148a5d0..e0f5a22a259 100644 --- a/code/game/objects/structures/crates_lockers/largecrate.dm +++ b/code/game/objects/structures/crates_lockers/largecrate.dm @@ -30,10 +30,8 @@ icon_state = "lisacrate" /obj/structure/largecrate/porcelain - ..() /obj/structure/largecrate/showers - ..() /obj/structure/largecrate/lisa/attackby(obj/item/weapon/W as obj, mob/user as mob) //ugly but oh well if(iscrowbar(W)) diff --git a/code/game/objects/structures/curtains.dm b/code/game/objects/structures/curtains.dm index 089218a4b0e..af083c23bb0 100644 --- a/code/game/objects/structures/curtains.dm +++ b/code/game/objects/structures/curtains.dm @@ -35,7 +35,7 @@ ..() /obj/structure/curtain/attack_hand(mob/user) - playsound(get_turf(loc), "rustle", 15, 1, -5) + playsound(loc, "rustle", 15, 1, -5) toggle() ..() diff --git a/code/game/objects/structures/displaycase.dm b/code/game/objects/structures/displaycase.dm index fb49dfab640..2303f90c125 100644 --- a/code/game/objects/structures/displaycase.dm +++ b/code/game/objects/structures/displaycase.dm @@ -1,65 +1,4 @@ -/obj/structure/displaycase_frame - name = "display case frame" - icon = 'icons/obj/stock_parts.dmi' - icon_state="box_glass" - var/obj/item/weapon/circuitboard/airlock/circuit=null - var/state=0 - -/obj/structure/displaycase_frame/Destroy() - ..() - if(circuit) - qdel(circuit) - circuit = null - -/obj/structure/displaycase_frame/attackby(obj/item/weapon/W as obj, mob/user as mob) - var/pstate=state - var/turf/T=get_turf(src) - switch(state) - if(0) - if(istype(W, /obj/item/weapon/circuitboard/airlock) && W:icon_state != "door_electronics_smoked") - if(user.drop_item(W, src)) - circuit=W - circuit.installed = 1 - state++ - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) - if(iscrowbar(W)) - var/obj/machinery/constructable_frame/machine_frame/MF = new /obj/machinery/constructable_frame/machine_frame(T) - MF.state = 1 - MF.set_build_state(1) - new /obj/item/stack/sheet/glass/glass(T) - qdel(src) - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) - return - - if(1) - if(isscrewdriver(W)) - var/obj/structure/displaycase/C=new(T) - if(circuit.one_access) - C.req_access = null - C.req_one_access = circuit.conf_access - else - C.req_access = circuit.conf_access - C.req_one_access = null - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) - qdel(src) - return - if(iscrowbar(W)) - circuit.forceMove(T) - circuit.installed = 0 - circuit=null - state-- - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) - if(pstate!=state) - pstate=state - update_icon() - -/obj/structure/displaycase_frame/update_icon() - switch(state) - if(1) - icon_state="box_glass_circuit" - else - icon_state="box_glass" - +//Construction handled in code/game/machinery/constructable_frame.dm /obj/structure/displaycase name = "display case" @@ -100,7 +39,10 @@ /obj/structure/displaycase/lamarr/New() ..() - occupant=new /obj/item/clothing/mask/facehugger/lamarr(src) + if(Holiday == APRIL_FOOLS_DAY && prob(50)) + occupant=new /obj/item/clothing/shoes/magboots/funk(src) + else + occupant=new /obj/item/clothing/mask/facehugger/lamarr(src) locked=1 req_access=list(access_rd) update_icon() @@ -158,10 +100,10 @@ setDensity(FALSE) src.destroyed = 1 getFromPool(/obj/item/weapon/shard, loc) - playsound(get_turf(src), "shatter", 70, 1) + playsound(src, "shatter", 70, 1) update_icon() else - playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 75, 1) + playsound(src, 'sound/effects/Glasshit.ogg', 75, 1) return /obj/structure/displaycase/update_icon() @@ -201,30 +143,35 @@ user.visible_message("[user.name] pries \the [src] apart.", \ "You pry \the [src] apart.", \ "You hear something pop.") - var/turf/T=get_turf(src) - playsound(T, 'sound/items/Crowbar.ogg', 50, 1) + playsound(src, 'sound/items/Crowbar.ogg', 50, 1) dump() - var/obj/item/weapon/circuitboard/airlock/C=circuit + + var/obj/item/weapon/circuitboard/airlock/C = circuit if(!C) - C=new (src) + C = new (src) C.installed = 1 C.one_access=!(req_access && req_access.len>0) if(!C.one_access) C.conf_access=req_access else C.conf_access=req_one_access + if(!destroyed) - var/obj/structure/displaycase_frame/F=new(T) - F.state=1 - F.circuit=C - F.circuit.forceMove(F) - F.update_icon() + var /obj/machinery/constructable_frame/machine_frame/new_machine_frame = new(get_turf(src)) + new_machine_frame.build_path = 1 + new_machine_frame.build_state = 2 + new_machine_frame.circuit = C + C.forceMove(new_machine_frame) + circuit = null + C = null + new_machine_frame.icon_state="box_glass_circuit" else - C.forceMove(T) + C.forceMove(get_turf(src)) C.installed = 0 - circuit=null - new /obj/machinery/constructable_frame/machine_frame(T) + new /obj/machinery/constructable_frame/machine_frame(get_turf(src)) qdel(src) + return + else if(user.a_intent == I_HURT) user.delayNextAttack(8) src.health -= W.force @@ -286,10 +233,10 @@ /obj/structure/displaycase/broken - name = "display case" + name = "broken display case" icon = 'icons/obj/stationobjs.dmi' icon_state = "glassbox2b" - desc = "A display case for prized possessions." + desc = "A display case for prized possessions. It seems to be broken." density = 0 health = 0 destroyed = 1 diff --git a/code/game/objects/structures/docking_port.dm b/code/game/objects/structures/docking_port.dm index 197f979c6a6..93b0edeb96c 100644 --- a/code/game/objects/structures/docking_port.dm +++ b/code/game/objects/structures/docking_port.dm @@ -1,3 +1,8 @@ +/*CONTAINS +- Docking Port +- Shuttle and Destination subtypes +- Docking Lights */ + var/global/list/all_docking_ports = list() /obj/docking_port @@ -85,11 +90,19 @@ var/global/list/all_docking_ports = list() if(!A.shuttle_warning_lights) A.shuttle_warning_lights = image('icons/obj/doors/Doorint.dmi', src, "warning_lights") A.overlays += A.shuttle_warning_lights + for(var/obj/machinery/docklight/D in dockinglights) + if(D.id_tag == areaname) + D.triggered = 1 + D.update_icon() /obj/docking_port/destination/proc/stop_warning_lights() for(var/obj/machinery/door/airlock/A in range(1,src)) if(A.shuttle_warning_lights) A.overlays -= A.shuttle_warning_lights + for(var/obj/machinery/docklight/D in dockinglights) + if(D.id_tag == areaname) + D.triggered = 0 + D.update_icon() //SHUTTLE PORTS @@ -232,3 +245,39 @@ var/global/list/all_docking_ports = list() if(istype(D)) return D return 0 + +var/global/list/dockinglights = list() + +/obj/machinery/docklight + name = "docking light" + desc = "A light designed to warn of dangerous docking conditions. Exercise caution while flashing." + icon = 'icons/obj/stationobjs.dmi' + icon_state = "docklight" + light_color = LIGHT_COLOR_ORANGE + machine_flags = MULTITOOL_MENU + var/triggered = 0 + var/id_tag = "" //Mappers: This should match the areaname of the target destination port. + //Examples: "main research department", "research outpost", "deep space", "station auxillary docking", "north of the station", etc. + +/obj/machinery/docklight/New() + ..() + dockinglights += src + +/obj/machinery/docklight/Destroy() + dockinglights -= src + ..() + +/obj/machinery/docklight/update_icon() + if(triggered) + icon_state = "docklight_triggered" + set_light(2) + else + icon_state = "docklight" + set_light(0) + +/obj/machinery/docklight/multitool_menu(var/mob/user, var/obj/item/device/multitool/P) + return {" + Main +
      +
    • [format_tag("ID Tag","id_tag")]
    • +
    "} diff --git a/code/game/objects/structures/door_assembly.dm b/code/game/objects/structures/door_assembly.dm index 0a889f3e5d5..919f7e1291c 100644 --- a/code/game/objects/structures/door_assembly.dm +++ b/code/game/objects/structures/door_assembly.dm @@ -162,7 +162,7 @@ if (WT.remove_fuel(0, user)) busy = TRUE - playsound(get_turf(src), 'sound/items/Welder2.ogg', 50, 1) + playsound(src, 'sound/items/Welder2.ogg', 50, 1) if (istext(glass)) user.visible_message("[user] welds the [glass] plating off the airlock assembly.", "You start to weld the [glass] plating off the airlock assembly.") @@ -210,7 +210,7 @@ return else if(iswrench(W) && state == 0) busy = 1 - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1) + playsound(src, 'sound/items/Ratchet.ogg', 100, 1) if(anchored) user.visible_message("[user] unsecures the airlock assembly from the floor.", "You start to unsecure the airlock assembly from the floor.") else @@ -237,7 +237,7 @@ else if(iswirecutter(W) && state == 1 ) busy = 1 - playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 100, 1) + playsound(src, 'sound/items/Wirecutter.ogg', 100, 1) user.visible_message("[user] cuts the wires from the airlock assembly.", "You start to cut the wires from airlock assembly.") if(do_after(user, src, 40)) @@ -250,7 +250,7 @@ else if(istype(W, /obj/item/weapon/circuitboard/airlock) && state == 1 && W:icon_state != "door_electronics_smoked") busy = 1 - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 100, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 100, 1) user.visible_message("[user] installs the electronics into the airlock assembly.", "You start to install electronics into the airlock assembly.") user.drop_item(W, src, force_drop = 1) @@ -269,7 +269,7 @@ else if(iscrowbar(W) && state == 2 ) busy = 1 - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 100, 1) + playsound(src, 'sound/items/Crowbar.ogg', 100, 1) user.visible_message("[user] removes the electronics from the airlock assembly.", "You start to install electronics into the airlock assembly.") if(do_after(user, src, 40)) @@ -294,7 +294,7 @@ if (S.amount>=1) busy = 1 if(istype(S, /obj/item/stack/sheet/glass/rglass)) - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 100, 1) + playsound(src, 'sound/items/Crowbar.ogg', 100, 1) user.visible_message("[user] adds [S.name] to the airlock assembly.", "You start to install [S.name] into the airlock assembly.") if(do_after(user, src, 40)) to_chat(user, "You installed reinforced glass windows into the airlock assembly!") @@ -303,7 +303,7 @@ else if(istype(S, /obj/item/stack/sheet/mineral) && S.sheettype) var/M = S.sheettype if(S.amount>=2) - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 100, 1) + playsound(src, 'sound/items/Crowbar.ogg', 100, 1) user.visible_message("[user] adds [S.name] to the airlock assembly.", "You start to install [S.name] into the airlock assembly.") if(do_after(user, src, 40)) to_chat(user, "You installed [M] plating into the airlock assembly!") @@ -313,7 +313,7 @@ else if(isscrewdriver(W) && state == 2 ) busy = 1 - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 100, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 100, 1) to_chat(user, "Now finishing the airlock.") if(do_after(user, src, 40)) diff --git a/code/game/objects/structures/fence.dm b/code/game/objects/structures/fence.dm index 31874ef7f7a..644b70a85ac 100644 --- a/code/game/objects/structures/fence.dm +++ b/code/game/objects/structures/fence.dm @@ -67,7 +67,7 @@ hole_size = LARGE_HOLE /obj/structure/fence/attackby(obj/item/W, mob/user) - if(iswirecutter(W) && !shock(user, 100)) + if(iswirecutter(W) && !shock(user, 100, W.siemens_coefficient)) if(!cuttable) to_chat(user, "This section of the fence can't be cut.") return @@ -114,7 +114,7 @@ strength = H.get_strength() user.visible_message("\The [user] hits \the [src]!") - playsound(get_turf(src), 'sound/effects/fence_smash.ogg', 30 * strength, 1) //Sound is louder the stronger you are + playsound(src, 'sound/effects/fence_smash.ogg', 30 * strength, 1) //Sound is louder the stronger you are shock(user, 100) return 1 @@ -167,7 +167,7 @@ return !density //Mostly copied from grille.dm -/obj/structure/fence/proc/shock(mob/user, prb = 100) +/obj/structure/fence/proc/shock(mob/user, prb = 100, siemens_coefficient = 1) if(!prob(prb)) //If the probability roll failed, don't go further return 0 if(!in_range(src, user)) //To prevent TK and mech users from getting shocked @@ -176,7 +176,7 @@ var/turf/T = get_turf(src) var/obj/structure/cable/C = T.get_cable_node() if(C) - if(electrocute_mob(user, C, src)) + if(electrocute_mob(user, C, src, siemens_coefficient)) spark(src) return 1 else @@ -217,7 +217,7 @@ open = FALSE update_door_status() - playsound(get_turf(src), 'sound/machines/click.ogg', 100, 1) + playsound(src, 'sound/machines/click.ogg', 100, 1) /obj/structure/fence/door/proc/update_door_status() switch(open) diff --git a/code/game/objects/structures/flaps.dm b/code/game/objects/structures/flaps.dm index 5c01bcd46a6..67ede4db0b2 100644 --- a/code/game/objects/structures/flaps.dm +++ b/code/game/objects/structures/flaps.dm @@ -12,9 +12,9 @@ /obj/structure/plasticflaps/attackby(obj/item/I as obj, mob/user as mob) if(iscrowbar(I) && anchored == 1) if(airtight == 0) - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) + playsound(src, 'sound/items/Crowbar.ogg', 50, 1) else - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) user.visible_message("[user] [airtight? "loosen the [src] from" : "tighten the [src] into"] an airtight position.", "You [airtight? "loosen the [src] from" : "tighten the [src] into"] an airtight position.") airtight = !airtight name = "\improper [airtight? "Airtight p" : "P"]lastic flaps" @@ -22,9 +22,9 @@ return 1 if(iswrench(I) && airtight != 1) if(anchored == 0) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + playsound(src, 'sound/items/Ratchet.ogg', 50, 1) else - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) user.visible_message("[user] [anchored? "loosens" : "tightens"] the flap from its anchoring.", "You [anchored? "loosen" : "tighten"] the flap from its anchoring.") anchored = !anchored return 1 diff --git a/code/game/objects/structures/fullwindow.dm b/code/game/objects/structures/fullwindow.dm index 23db6416e3e..e8cc3bc2710 100644 --- a/code/game/objects/structures/fullwindow.dm +++ b/code/game/objects/structures/fullwindow.dm @@ -94,12 +94,16 @@ update_nearby_tiles() ini_dir = dir +/obj/structure/window/full/AltClick(var/mob/user) + var/turf/T = get_turf(src) + T.AltClick(user) + /obj/structure/window/full/reinforced name = "reinforced window" desc = "A window with a rod matrice. It looks more solid than the average window." icon_state = "rwindow0" base_state = "rwindow" - sheettype = /obj/item/stack/sheet/glass/rglass + sheet_type = /obj/item/stack/sheet/glass/rglass health = 40 penetration_dampening = 3 d_state = WINDOWSECURE @@ -112,7 +116,7 @@ icon_state = "plasmawindow0" base_state = "plasmawindow" shardtype = /obj/item/weapon/shard/plasma - sheettype = /obj/item/stack/sheet/glass/plasmaglass + sheet_type = /obj/item/stack/sheet/glass/plasmaglass health = 120 penetration_dampening = 5 @@ -125,7 +129,7 @@ icon_state = "plasmarwindow0" base_state = "plasmarwindow" shardtype = /obj/item/weapon/shard/plasma - sheettype = /obj/item/stack/sheet/glass/plasmarglass + sheet_type = /obj/item/stack/sheet/glass/plasmarglass health = 160 penetration_dampening = 7 @@ -139,7 +143,7 @@ icon_state = "twindow0" base_state = "twindow" opacity = 1 - sheettype = /obj/item/stack/sheet/glass/rglass //A glass type for this window doesn't seem to exist, so here's to you + sheet_type = /obj/item/stack/sheet/glass/rglass //A glass type for this window doesn't seem to exist, so here's to you /obj/structure/window/full/reinforced/tinted/frosted @@ -148,7 +152,7 @@ icon_state = "fwindow0" base_state = "fwindow" health = 30 - sheettype = /obj/item/stack/sheet/glass/rglass //Ditto above + sheet_type = /obj/item/stack/sheet/glass/rglass //Ditto above #undef WINDOWLOOSE #undef WINDOWLOOSEFRAME diff --git a/code/game/objects/structures/girders.dm b/code/game/objects/structures/girders.dm index e970af73395..ffa528c93e2 100644 --- a/code/game/objects/structures/girders.dm +++ b/code/game/objects/structures/girders.dm @@ -19,7 +19,7 @@ /obj/structure/girder/wood/attackby(var/obj/item/W, var/mob/user) if(W.sharpness_flags & CHOPWOOD) - playsound(get_turf(src), 'sound/effects/woodcuttingshort.ogg', 50, 1) + playsound(src, 'sound/effects/woodcuttingshort.ogg', 50, 1) user.visible_message("[user] smashes through \the [src] with \the [W].", \ "You smash through \the [src].",\ "You hear the sound of wood being cut" @@ -41,7 +41,7 @@ if(iswrench(W)) if(state == 0) //Normal girder or wooden girder if(anchored && !istype(src, /obj/structure/girder/displaced)) //Anchored, destroy it - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1) + playsound(src, 'sound/items/Ratchet.ogg', 100, 1) user.visible_message("[user] starts disassembling \the [src].", \ "You start disassembling \the [src].") if(do_after(user, src, construction_length)) @@ -54,7 +54,7 @@ to_chat(user, "You can't secure \the [src] to [istype(src.loc,/turf/space) ? "space" : "this"]!") return - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1) + playsound(src, 'sound/items/Ratchet.ogg', 100, 1) user.visible_message("[user] starts securing \the [src].", \ "You start securing \the [src].") if(do_after(user, src, construction_length)) @@ -65,7 +65,7 @@ anchored = 1 update_icon() else if(state == 1 || state == 2) //Clearly a reinforced girder - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1) + playsound(src, 'sound/items/Ratchet.ogg', 100, 1) user.visible_message("[user] starts [anchored ? "un" : ""]securing \the [src].", \ "You start [anchored ? "un" : ""]securing \the [src].") if(do_after(user, src, construction_length)) @@ -90,7 +90,7 @@ qdel(src) else if(isscrewdriver(W) && state == 2) //Unsecuring support struts, stage 2 to 1 - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 100, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 100, 1) user.visible_message("[user] starts unsecuring \the [src]'s internal support struts.", \ "You start unsecuring \the [src]'s internal support struts.") if(do_after(user, src, construction_length)) @@ -102,7 +102,7 @@ update_icon() else if(isscrewdriver(W) && state == 1) //Securing support struts, stage 1 to 2 - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 100, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 100, 1) user.visible_message("[user] starts securing \the [src]'s internal support struts.", \ "You start securing \the [src]'s internal support struts.") if(do_after(user, src, construction_length)) @@ -114,7 +114,7 @@ update_icon() else if(iswirecutter(W) && state == 1) //Removing support struts, stage 1 to 0 (normal girder) - playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 100, 1) + playsound(src, 'sound/items/Wirecutter.ogg', 100, 1) user.visible_message("[user] starts removing \the [src]'s internal support struts.", \ "You start removing \the [src]'s internal support struts.") if(do_after(user, src, construction_length)) @@ -147,7 +147,7 @@ update_icon() else if(iscrowbar(W) && state == 0 && anchored) //Turning normal girder into disloged girder - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 100, 1) + playsound(src, 'sound/items/Crowbar.ogg', 100, 1) user.visible_message("[user] starts dislodging \the [src].", \ "You start dislodging \the [src].") if(do_after(user, src, construction_length)) @@ -393,7 +393,7 @@ /obj/structure/cultgirder/attackby(obj/item/W as obj, mob/user as mob) if(iswrench(W)) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1) + playsound(src, 'sound/items/Ratchet.ogg', 100, 1) user.visible_message("[user] starts disassembling \the [src].", \ "You start disassembling \the [src].") if(do_after(user, src,40)) diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm index 776cc5a07b9..d9fec9b55bf 100644 --- a/code/game/objects/structures/grille.dm +++ b/code/game/objects/structures/grille.dm @@ -144,14 +144,14 @@ /obj/structure/grille/attackby(obj/item/weapon/W as obj, mob/user as mob) user.delayNextAttack(8) if(iswirecutter(W)) - if(!shock(user, 100)) //Prevent user from doing it if he gets shocked + if(!shock(user, 100, W.siemens_coefficient)) //Prevent user from doing it if he gets shocked playsound(loc, 'sound/items/Wirecutter.ogg', 100, 1) drop_stack(/obj/item/stack/rods, get_turf(src), broken ? 1 : 2, user) //Drop the rods, taking account on whenever the grille is broken or not ! qdel(src) return return //Return in case the user starts cutting and gets shocked, so that it doesn't continue downwards ! else if((isscrewdriver(W)) && (istype(loc, /turf/simulated) || anchored)) - if(!shock(user, 90)) + if(!shock(user, 90, W.siemens_coefficient)) playsound(loc, 'sound/items/Screwdriver.ogg', 100, 1) anchored = !anchored user.visible_message("[user] [anchored ? "fastens" : "unfastens"] the grille [anchored ? "to" : "from"] the floor.", \ @@ -215,7 +215,7 @@ dam = W.force * 0.5 //Rod matrices have an innate resistance to brute damage if(!(W.sharpness_flags & INSULATED_EDGE)) - shock(user, 100 * W.siemens_coefficient) //Chance of getting shocked is proportional to conductivity + shock(user, 100 * W.siemens_coefficient, W.siemens_coefficient) //Chance of getting shocked is proportional to conductivity if(dam) user.do_attack_animation(src, W) @@ -227,7 +227,7 @@ //Shock user with probability prb (if all connections & power are working) //Returns 1 if shocked, 0 otherwise -/obj/structure/grille/proc/shock(mob/user as mob, prb) +/obj/structure/grille/proc/shock(mob/user as mob, prb, siemens_coeff) if(!anchored || broken) //De-anchored and destroyed grilles are never connected to the powernet ! return 0 if(!prob(prb)) //If the probability roll failed, don't go further @@ -238,7 +238,7 @@ var/turf/T = get_turf(src) var/obj/structure/cable/C = T.get_cable_node() if(C) - if(electrocute_mob(user, C, src)) + if(electrocute_mob(user, C, src, siemens_coeff)) spark(src) return 1 else diff --git a/code/game/objects/structures/kitchen_spike.dm b/code/game/objects/structures/kitchen_spike.dm index f2e13d4f523..5818498f3da 100644 --- a/code/game/objects/structures/kitchen_spike.dm +++ b/code/game/objects/structures/kitchen_spike.dm @@ -73,6 +73,8 @@ C.drop_stomach_contents() user.visible_message("\The [C]'s stomach contents drop to the ground!") + occupant.meat_amount++ + returnToPool(G) return @@ -86,11 +88,11 @@ if(occupant.meat_amount > occupant.meat_taken) to_chat(user, "You remove some meat from \the [occupant].") + return else to_chat(user, "You remove the last piece of meat from \the [src]!") - clean() - else - clean() + + clean() /obj/structure/kitchenspike/proc/clean() icon_state = initial(icon_state) diff --git a/code/game/objects/structures/lamarr_cage.dm b/code/game/objects/structures/lamarr_cage.dm index 9fcb1469d44..4d3ab8e0a22 100644 --- a/code/game/objects/structures/lamarr_cage.dm +++ b/code/game/objects/structures/lamarr_cage.dm @@ -47,7 +47,7 @@ playsound(src, "shatter", 70, 1) Break() else - playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 75, 1) + playsound(src, 'sound/effects/Glasshit.ogg', 75, 1) return /obj/structure/lamarr/update_icon() diff --git a/code/game/objects/structures/mannequin.dm b/code/game/objects/structures/mannequin.dm index ec291a3d44a..5da3d96b08c 100644 --- a/code/game/objects/structures/mannequin.dm +++ b/code/game/objects/structures/mannequin.dm @@ -871,7 +871,7 @@ else destroyed = 1 getFromPool(/obj/item/weapon/shard, loc) - playsound(get_turf(src), "shatter", 100, 1) + playsound(src, "shatter", 100, 1) shield = 0 update_icon() if (2) @@ -906,10 +906,10 @@ destroyed = 1 locked = 0 getFromPool(/obj/item/weapon/shard, loc) - playsound(get_turf(src), "shatter", 100, 1) + playsound(src, "shatter", 100, 1) update_icon() else - playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 75, 1) + playsound(src, 'sound/effects/Glasshit.ogg', 75, 1) if(health <= 0) visible_message("\The [src] collapses.") @@ -1038,7 +1038,7 @@ /obj/structure/mannequin/cyber/kick_act(mob/living/carbon/human/H) if(locked) - playsound(get_turf(src), 'sound/effects/glassknock.ogg', 100, 1) + playsound(src, 'sound/effects/glassknock.ogg', 100, 1) ..() @@ -1156,7 +1156,7 @@ /datum/construction/mannequin/spawn_result(mob/user as mob) if(result) - testing("[user] finished a [result]!") +// testing("[user] finished a [result]!") var/obj/structure/mannequin_frame/const_holder = holder var/obj/structure/mannequin/cyber/C = new result(get_turf(holder)) diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm index 2e91e9e650f..aa12bf87ea0 100644 --- a/code/game/objects/structures/mirror.dm +++ b/code/game/objects/structures/mirror.dm @@ -87,19 +87,19 @@ stack.use(2) shattered = 0 icon_state = "mirror" - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 80, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 80, 1) else user.do_attack_animation(src, I) if(shattered) - playsound(get_turf(src), 'sound/effects/hit_on_shattered_glass.ogg', 70, 1) + playsound(src, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1) return else if(prob(I.force * 2)) visible_message("[user] smashes [src] with [I]!") shatter() else visible_message("[user] hits [src] with [I]!") - playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 70, 1) + playsound(src, 'sound/effects/Glasshit.ogg', 70, 1) /obj/structure/mirror/attack_alien(mob/living/user as mob) @@ -107,7 +107,7 @@ return user.do_attack_animation(src, user) if(shattered) - playsound(get_turf(src), 'sound/effects/hit_on_shattered_glass.ogg', 70, 1) + playsound(src, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1) return user.visible_message("[user] smashes [src]!") shatter() @@ -121,7 +121,7 @@ return user.do_attack_animation(src, user) if(shattered) - playsound(get_turf(src), 'sound/effects/hit_on_shattered_glass.ogg', 70, 1) + playsound(src, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1) return user.visible_message("[user] smashes [src]!") shatter() @@ -132,7 +132,7 @@ return user.do_attack_animation(src, user) if(shattered) - playsound(get_turf(src), 'sound/effects/hit_on_shattered_glass.ogg', 70, 1) + playsound(src, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1) return user.visible_message("[user] smashes [src]!") shatter() diff --git a/code/game/objects/structures/mop_bucket.dm b/code/game/objects/structures/mop_bucket.dm index 517425d5c4c..9cd62ce28f0 100644 --- a/code/game/objects/structures/mop_bucket.dm +++ b/code/game/objects/structures/mop_bucket.dm @@ -37,7 +37,7 @@ else src.reagents.trans_to(M, 3) to_chat(user, "You wet [M]") - playsound(get_turf(src), 'sound/effects/slosh.ogg', 25, 1) + playsound(src, 'sound/effects/slosh.ogg', 25, 1) else to_chat(user, "Nothing left to wet [M] with!") return 1 diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm index 69328395a6e..1fb81c13419 100644 --- a/code/game/objects/structures/morgue.dm +++ b/code/game/objects/structures/morgue.dm @@ -86,7 +86,7 @@ return /obj/structure/morgue/proc/open_up() - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) connected = new /obj/structure/m_tray(loc) connected.layer = OBJ_LAYER step(connected, src.dir) @@ -126,12 +126,12 @@ user.visible_message("\The [user] begins dismantling \the [src].", "You begin dismantling \the [src].") if(do_after(user, src,50)) user.visible_message("\The [user] dismantles \the [src].", "You dismantle \the [src].") - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) new /obj/structure/closet/body_bag(src.loc) new /obj/item/stack/sheet/metal(src.loc,5) qdel(src) if(iswrench(P)) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + playsound(src, 'sound/items/Ratchet.ogg', 50, 1) if(dir==4) dir=8 else @@ -272,11 +272,11 @@ for(var/atom/movable/A as mob|obj in src.connected.loc) if (!( A.anchored )) A.forceMove(src) - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) qdel(src.connected) src.connected = null else if (src.locked == 0) - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) src.connected = new /obj/structure/c_tray( src.loc ) step(src.connected, SOUTH) src.connected.layer = OBJ_LAYER @@ -370,7 +370,7 @@ cremating = 0 update() locked = 0 - playsound(get_turf(src), 'sound/machines/ding.ogg', 50, 1) + playsound(src, 'sound/machines/ding.ogg', 50, 1) /* diff --git a/code/game/objects/structures/noticeboard.dm b/code/game/objects/structures/noticeboard.dm index 154d3cb9c8b..d0e4d413ed2 100644 --- a/code/game/objects/structures/noticeboard.dm +++ b/code/game/objects/structures/noticeboard.dm @@ -21,7 +21,7 @@ /obj/structure/noticeboard/attackby(var/obj/item/weapon/O as obj, var/mob/user as mob) if(iswrench(O)) to_chat(user, "You disassemble \the [src].") - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1) + playsound(src, 'sound/items/Ratchet.ogg', 100, 1) new /obj/item/stack/sheet/wood (src.loc,2) qdel(src) if(istype(O, /obj/item/weapon/paper)) diff --git a/code/game/objects/structures/popout_cake.dm b/code/game/objects/structures/popout_cake.dm index 6886f36da6c..8438bf57d6c 100644 --- a/code/game/objects/structures/popout_cake.dm +++ b/code/game/objects/structures/popout_cake.dm @@ -136,7 +136,7 @@ spawn(10) - playsound(get_turf(src), 'sound/effects/party_horn.ogg', 50, 1) + playsound(src, 'sound/effects/party_horn.ogg', 50, 1) sleep(10) diff --git a/code/game/objects/structures/skele_stand.dm b/code/game/objects/structures/skele_stand.dm index e44a6a8c546..dcf37b8b5d2 100644 --- a/code/game/objects/structures/skele_stand.dm +++ b/code/game/objects/structures/skele_stand.dm @@ -20,7 +20,7 @@ visible_message("\The [src] rattles [pick("ominously","violently")] on \his stand! [pick("Spooky","Weird")].") else visible_message("\The [src] rattles[thingy ? " upon being hit by \the [thingy]" : ""].") - playsound(get_turf(src), 'sound/effects/rattling_bones.ogg', 50, 0) + playsound(src, 'sound/effects/rattling_bones.ogg', 50, 0) last_rattle_time = world.time else return diff --git a/code/game/objects/structures/stool_bed_chair_nest/bed.dm b/code/game/objects/structures/stool_bed_chair_nest/bed.dm index c61819dc940..b80468c47be 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/bed.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/bed.dm @@ -14,11 +14,16 @@ icon = 'icons/obj/stools-chairs-beds.dmi' layer = BELOW_OBJ_LAYER anchored = 1 - var/sheet_type = /obj/item/stack/sheet/metal - var/sheet_amt = 1 + sheet_type = /obj/item/stack/sheet/metal + sheet_amt = 1 var/lock_type = /datum/locking_category/buckle/bed +/obj/structure/bed/New() + ..() + if(material_type) + sheet_type = material_type.sheettype + /obj/structure/bed/alien name = "resting contraption" desc = "This looks similar to contraptions from earth. Could aliens be stealing our technology?" @@ -77,7 +82,7 @@ "[M] unbuckled \himself!",\ "You unbuckle yourself from \the [src].",\ "You hear metal clanking.") - playsound(get_turf(src), 'sound/misc/buckle_unclick.ogg', 50, 1) + playsound(src, 'sound/misc/buckle_unclick.ogg', 50, 1) unlock_atom(M) add_fingerprint(user) @@ -117,7 +122,7 @@ "You are buckled in to [src] by [user.name].",\ "You hear metal clanking.") - playsound(get_turf(src), 'sound/misc/buckle_click.ogg', 50, 1) + playsound(src, 'sound/misc/buckle_click.ogg', 50, 1) add_fingerprint(user) lock_atom(M, lock_type) @@ -143,6 +148,10 @@ lockflags = DENSE_WHEN_LOCKED lock_type = /datum/locking_category/buckle/bed/roller +/obj/structure/bed/roller/deff + icon = 'maps/defficiency/medbay.dmi' + roller_type = /obj/item/roller/deff + /obj/item/roller name = "roller bed" desc = "A collapsed roller bed that can be carried around." @@ -153,6 +162,10 @@ var/bed_type = /obj/structure/bed/roller w_class = W_CLASS_LARGE // Can't be put in backpacks. Oh well. +/obj/item/roller/deff + icon = 'maps/defficiency/medbay.dmi' + bed_type = /obj/structure/bed/roller/deff + /obj/item/roller/attack_self(mob/user) var/obj/structure/bed/roller/R = new bed_type(user.loc) R.add_fingerprint(user) @@ -191,7 +204,7 @@ if(istype(W,/obj/item/roller_holder)) manual_unbuckle(user) if(iswrench(W)) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + playsound(src, 'sound/items/Ratchet.ogg', 50, 1) drop_stack(sheet_type, loc, 2, user) qdel(src) return diff --git a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm index 5593a15de3e..eb3fe47a392 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm @@ -47,7 +47,7 @@ var/obj/item/assembly/shock_kit/SK = W if(user.drop_item(W)) var/obj/structure/bed/chair/e_chair/E = new /obj/structure/bed/chair/e_chair(src.loc) - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) E.dir = dir E.part = SK SK.forceMove(E) @@ -56,7 +56,7 @@ return if(iswrench(W)) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + playsound(src, 'sound/items/Ratchet.ogg', 50, 1) drop_stack(sheet_type, loc, sheet_amt, user) qdel(src) return @@ -130,6 +130,8 @@ else buckle_mob(M, user) + if(material_type) + material_type.on_use(src,M,user) // Chair types /obj/structure/bed/chair/wood diff --git a/code/game/objects/structures/stool_bed_chair_nest/guillotine.dm b/code/game/objects/structures/stool_bed_chair_nest/guillotine.dm index a1abef068b6..e59e416d7cf 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/guillotine.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/guillotine.dm @@ -207,7 +207,7 @@ var/datum/organ/external/head/H = victim.get_organ(LIMB_HEAD) if(istype(H) && ~H.status & ORGAN_DESTROYED) H.droplimb(1) - playsound(get_turf(src), 'sound/weapons/bloodyslice.ogg', 100, 1) + playsound(src, 'sound/weapons/bloodyslice.ogg', 100, 1) blood_splatter(get_turf(src),victim,1) bladedown = TRUE update_icon() diff --git a/code/game/objects/structures/stool_bed_chair_nest/stools.dm b/code/game/objects/structures/stool_bed_chair_nest/stools.dm index 8f71f8f9335..a489d27f180 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/stools.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/stools.dm @@ -7,7 +7,7 @@ force = 10 throwforce = 10 w_class = W_CLASS_HUGE - var/sheet_path = /obj/item/stack/sheet/metal + sheet_type = /obj/item/stack/sheet/metal /obj/item/weapon/stool/bar name = "bar stool" @@ -15,7 +15,7 @@ icon_state = "bar-stool" /obj/item/weapon/stool/hologram - sheet_path = null + sheet_type = null /obj/item/weapon/stool/piano name = "piano stool" @@ -23,7 +23,7 @@ icon_state = "stool_piano" autoignition_temperature = AUTOIGNITION_WOOD fire_fuel = 3 - sheet_path = /obj/item/stack/sheet/wood + sheet_type = /obj/item/stack/sheet/wood /obj/item/weapon/stool/piano/initialize() ..() @@ -34,9 +34,9 @@ return /obj/item/weapon/stool/attackby(var/obj/item/weapon/W, var/mob/user) - if(iswrench(W) && sheet_path) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) - drop_stack(sheet_path, loc, 1, user) + if(iswrench(W) && sheet_type) + playsound(src, 'sound/items/Ratchet.ogg', 50, 1) + drop_stack(sheet_type, loc, 1, user) qdel(src) . = ..() @@ -47,11 +47,11 @@ . = ..() /obj/item/weapon/stool/attack(mob/M as mob, mob/user as mob) - if(prob(5) && istype(M, /mob/living) && sheet_path) + if(prob(5) && istype(M, /mob/living) && sheet_type) user.visible_message("[user] breaks \the [src] over [M]'s back!.") user.u_equip(src, 0) - getFromPool(sheet_path, get_turf(src), 1) + getFromPool(sheet_type, get_turf(src), 1) qdel(src) var/mob/living/T = M diff --git a/code/game/objects/structures/support_rail.dm b/code/game/objects/structures/support_rail.dm index 2a6c74b9f1f..b1f4b606cbe 100644 --- a/code/game/objects/structures/support_rail.dm +++ b/code/game/objects/structures/support_rail.dm @@ -16,7 +16,7 @@ /obj/structure/support_rail/attackby(obj/item/weapon/W, mob/living/carbon/human/user as mob) if(iswrench(W)) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + playsound(src, 'sound/items/Ratchet.ogg', 50, 1) var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal, get_turf(src)) M.amount = 1 qdel(src) diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm index ba989313810..c93b31064b2 100644 --- a/code/game/objects/structures/tables_racks.dm +++ b/code/game/objects/structures/tables_racks.dm @@ -50,7 +50,7 @@ /obj/structure/table/glass/proc/checkhealth() if(health <= 0) - playsound(get_turf(src), "shatter", 50, 1) + playsound(src, "shatter", 50, 1) new /obj/item/weapon/shard(src.loc) new /obj/item/weapon/table_parts(src.loc) qdel(src) @@ -398,7 +398,7 @@ M.Knockdown(5) M.apply_damage(8,def_zone = LIMB_HEAD) visible_message("[G.assailant] slams [G.affecting]'s face against \the [src]!") - playsound(get_turf(src), 'sound/weapons/tablehit1.ogg', 50, 1) + playsound(src, 'sound/weapons/tablehit1.ogg', 50, 1) else to_chat(user, "You need a better grip to do that!") return @@ -412,7 +412,7 @@ if (iswrench(W) && can_disassemble()) //if(!params_list.len || text2num(params_list["icon-y"]) < 8) //8 above the bottom of the icon to_chat(user, "Now disassembling table") - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + playsound(src, 'sound/items/Ratchet.ogg', 50, 1) if(do_after(user, src,50)) destroy() return @@ -593,7 +593,7 @@ /obj/structure/table/reinforced/attackby(obj/item/weapon/W as obj, mob/user as mob, params) if(istype(W,/obj/item/weapon/stock_parts/scanning_module)) - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) if(do_after(user, src, 40)) if(user.drop_item(W)) var/obj/machinery/optable/OPT = new /obj/machinery/optable(src.loc) @@ -615,7 +615,7 @@ if(WT.remove_fuel(0, user)) if(src.status == 2) to_chat(user, "Now weakening the reinforced table.") - playsound(get_turf(src), 'sound/items/Welder.ogg', 50, 1) + playsound(src, 'sound/items/Welder.ogg', 50, 1) if (do_after(user, src, 50)) if(!src || !WT.isOn()) return @@ -623,7 +623,7 @@ src.status = 1 else to_chat(user, "Now strengthening the reinforced table.") - playsound(get_turf(src), 'sound/items/Welder.ogg', 50, 1) + playsound(src, 'sound/items/Welder.ogg', 50, 1) if (do_after(user, src, 50)) if(!src || !WT.isOn()) return @@ -656,8 +656,8 @@ M.Knockdown(5) M.apply_damage(15,def_zone = LIMB_HEAD) visible_message("[G.assailant] slams [G.affecting]'s face against \the [src]!") - playsound(get_turf(src), 'sound/weapons/tablehit1.ogg', 50, 1) - playsound(get_turf(src), "shatter", 50, 1) //WRESTLEMANIA tax + playsound(src, 'sound/weapons/tablehit1.ogg', 50, 1) + playsound(src, "shatter", 50, 1) //WRESTLEMANIA tax new /obj/item/weapon/shard(src.loc) new /obj/item/weapon/table_parts(src.loc) qdel(src) @@ -676,7 +676,7 @@ health -= W.force user.visible_message("\The [user] hits \the [src] with \the [W].", \ "You hit \the [src] with \the [W].") - playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 50, 1) + playsound(src, 'sound/effects/Glasshit.ogg', 50, 1) checkhealth() else @@ -771,7 +771,7 @@ /obj/structure/rack/attackby(obj/item/weapon/W as obj, mob/user as mob) if(iswrench(W) && can_disassemble()) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + playsound(src, 'sound/items/Ratchet.ogg', 50, 1) destroy(TRUE) return diff --git a/code/game/objects/structures/tank_dispenser.dm b/code/game/objects/structures/tank_dispenser.dm index 36aab72f972..93fa28e7a6a 100644 --- a/code/game/objects/structures/tank_dispenser.dm +++ b/code/game/objects/structures/tank_dispenser.dm @@ -86,11 +86,11 @@ if(iswrench(I)) if(anchored) to_chat(user, "You lean down and unwrench [src].") - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + playsound(src, 'sound/items/Ratchet.ogg', 50, 1) anchored = 0 else to_chat(user, "You wrench [src] into place.") - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + playsound(src, 'sound/items/Ratchet.ogg', 50, 1) anchored = 1 return diff --git a/code/game/objects/structures/transit_tubes.dm b/code/game/objects/structures/transit_tubes.dm index e015ac25573..846b6d7f7f8 100644 --- a/code/game/objects/structures/transit_tubes.dm +++ b/code/game/objects/structures/transit_tubes.dm @@ -1,3 +1,4 @@ +#define TUBE_POD_UNLOAD_LIMIT 20 // Basic transit tubes. Straight pieces, curved sections, // and basic splits/joins (no routing logic). @@ -125,17 +126,63 @@ obj/structure/transit_tube_pod/ex_act(severity) ..() -/obj/structure/transit_tube/station/attack_hand(mob/user as mob) +/obj/structure/transit_tube/station/attack_hand(mob/user) if(!pod_moving) for(var/obj/structure/transit_tube_pod/pod in loc) if(!pod.moving && pod.dir in directions()) if(open) + if(!user.lying && user.loc != pod) + var/unloaded = 0 + var/incomplete = FALSE + + for(var/atom/movable/AM in pod) + if(isobserver(AM)) + continue + if(unloaded >= TUBE_POD_UNLOAD_LIMIT) + incomplete = TRUE + break + AM.forceMove(get_step(loc, dir)) + unloaded++ + + if(unloaded) + user.visible_message("[user] unloads [incomplete ? "some things" : "everything"] from the tube pod.", \ + "You unload [incomplete ? "some things" : "everything"] from the tube pod.") + return + close_animation() else open_animation() +/obj/structure/transit_tube/station/attack_robot(mob/user) + if(Adjacent(user)) + attack_hand(user) + + +/obj/structure/transit_tube_pod/examine(mob/user) + ..() + show_occupants(user) + + +/obj/structure/transit_tube/examine(mob/user) + ..() + for(var/obj/structure/transit_tube_pod/pod in loc) + pod.show_occupants(user) + + +/obj/structure/transit_tube_pod/proc/show_occupants(mob/user) + if(contents.len) + var/list/occupants = contents.Copy() + for(var/atom/movable/O in occupants) + if(O.invisibility > user.see_invisible) + occupants -= O + if(occupants.len) + to_chat(user, "The tube pod contains [english_list(occupants)].") + return + + to_chat(user, "The tube pod looks empty.") + /obj/structure/transit_tube/station/proc/open_animation() if(icon_state == "closed") @@ -621,3 +668,5 @@ obj/structure/transit_tube_pod/ex_act(severity) return "SW" else return + +#undef TUBE_POD_UNLOAD_LIMIT diff --git a/code/game/objects/structures/vehicles/carts/cart.dm b/code/game/objects/structures/vehicles/carts/cart.dm index eae2aa1215d..91a0c5c3eaf 100644 --- a/code/game/objects/structures/vehicles/carts/cart.dm +++ b/code/game/objects/structures/vehicles/carts/cart.dm @@ -21,13 +21,13 @@ next_cart = connecting next_cart.previous_cart = src user.visible_message("[user] connects [connecting] to [src].", "You connect [connecting] to [src].") - playsound(get_turf(src), 'sound/misc/buckle_click.ogg', 50, 1) + playsound(src, 'sound/misc/buckle_click.ogg', 50, 1) return else if (next_cart == connecting) next_cart.previous_cart = null next_cart = null user.visible_message("[user] disconnects [connecting] from [src].", "You disconnect [connecting] from [src].") - playsound(get_turf(src), 'sound/misc/buckle_unclick.ogg', 50, 1) + playsound(src, 'sound/misc/buckle_unclick.ogg', 50, 1) return else to_chat(user, "\The [src] already has a cart connected to it!", "red") @@ -45,10 +45,10 @@ if (next_cart) //This one is really unlikely to happen if (get_dist(next_cart, src) > 1.99) //This is a nasty nasty hack but IT WORKS SO DON'T TOUCH IT next_cart = null - playsound(get_turf(src), 'sound/misc/buckle_unclick.ogg', 50, 1) + playsound(src, 'sound/misc/buckle_unclick.ogg', 50, 1) if (previous_cart) if (get_dist(previous_cart, src) > 1.99) previous_cart.next_cart = null previous_cart = null - playsound(get_turf(src), 'sound/misc/buckle_unclick.ogg', 50, 1) \ No newline at end of file + playsound(src, 'sound/misc/buckle_unclick.ogg', 50, 1) \ No newline at end of file diff --git a/code/game/objects/structures/vehicles/clowncart.dm b/code/game/objects/structures/vehicles/clowncart.dm index a2e52639a71..0224cbbf8ec 100644 --- a/code/game/objects/structures/vehicles/clowncart.dm +++ b/code/game/objects/structures/vehicles/clowncart.dm @@ -85,13 +85,13 @@ user.visible_message("[user] honks at [src].", \ "You honk at [src].", \ "You hear honking.") - playsound(get_turf(src), W.hitsound, 50, 1) + playsound(src, W.hitsound, 50, 1) if(reagents.get_reagent_amount(BANANA) <= 5 && max_health < HEALTH_FOR_FREE_MOVEMENT) if(activated) visible_message("[nick] lets out a last honk before running out of fuel and activating its ejection seat.") if(ishigherbeing(user)) //This shouldn't be needed, but fucks sakes user.Knockdown(5) - playsound(get_turf(src), 'sound/items/bikehorn.ogg', 50, 1) + playsound(src, 'sound/items/bikehorn.ogg', 50, 1) activated = 0 reagents.remove_reagent(BANANA, 5) else @@ -100,7 +100,7 @@ spawn(5) activated = 1 src.visible_message("[nick] honks back happily.") - playsound(get_turf(src), 'sound/items/bikehorn.ogg', 50, 1) + playsound(src, 'sound/items/bikehorn.ogg', 50, 1) honk = world.timeofday else if(istype(W, /obj/item/weapon/reagent_containers)) if(feed(W,user)) @@ -160,7 +160,7 @@ ST.use(1) else if(istype(W, /obj/item/weapon/coin/clown)) //Bananium coin user.visible_message("[user] inserts a bananium coin into [src].", "You insert a bananium coin into [src].") - playsound(get_turf(src), 'sound/machines/ping.ogg', 50, 1) + playsound(src, 'sound/machines/ping.ogg', 50, 1) mode += 1 if(mode > 2) //only 3 modes, so when it raises above 2 reset to 0 mode = 0 @@ -168,7 +168,7 @@ if(MODE_NORMAL) spawn(5) visible_message("[src]'s SynthPeel Generator turns off with a buzz.") - playsound(get_turf(src), 'sound/machines/buzz-sigh.ogg', 50, 1) + playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 1) if(MODE_DRAWING) visible_message("[src]'s SmartCrayon Mk.II deploys, ready to draw!") to_chat(user, {"Use a crayon to decide what you want to draw.
    @@ -176,9 +176,9 @@ if(MODE_PEELS) visible_message("[src]'s SmartCrayon Mk.II disappears in a puff of art!") spawn(5) - playsound(get_turf(src), 'sound/machines/ping.ogg', 50, 1) + playsound(src, 'sound/machines/ping.ogg', 50, 1) visible_message("You hear a ping as [src]'s SynthPeel Generator starts transforming banana juice into slippery peels.") - playsound(get_turf(src), 'sound/machines/ping.ogg', 50, 1) + playsound(src, 'sound/machines/ping.ogg', 50, 1) qdel(W) W = null else if(istype(W, /obj/item/toy/crayon/)) //Any crayon @@ -298,7 +298,7 @@ /obj/structure/bed/chair/vehicle/clowncart/die() setDensity(FALSE) visible_message("[nick] explodes in a puff of pure potassium!") - playsound(get_turf(src), 'sound/items/bikehorn.ogg', 75, 1) + playsound(src, 'sound/items/bikehorn.ogg', 75, 1) explosion(src.loc, -1, 0, 3, 7, 10) for(var/a = 0, a < round(reagents.total_volume*0.25), a++) //Spawn banana peels in place of the cart new /obj/item/weapon/bananapeel(get_turf(src)) // WHAT STUPID ASSHOLE MADE THESE TATORPEELS @@ -359,7 +359,7 @@ reagents.add_reagent(BANANA, added_banana*modifier) if(istype(W, /obj/item/weapon/reagent_containers/food/snacks/pie)) - playsound(get_turf(src), 'sound/effects/bubbles.ogg', 50, 1) + playsound(src, 'sound/effects/bubbles.ogg', 50, 1) to_chat(user, "[W] starts boiling inside \the [src]!") trail+=5 return added_banana*modifier diff --git a/code/game/objects/structures/vehicles/janicart.dm b/code/game/objects/structures/vehicles/janicart.dm index ff74ce54b1f..88652ca32c3 100644 --- a/code/game/objects/structures/vehicles/janicart.dm +++ b/code/game/objects/structures/vehicles/janicart.dm @@ -64,7 +64,7 @@ if(reagents.total_volume >= 2) reagents.trans_to(M, 3) to_chat(user, "You wet the mop in \the [nick].") - playsound(get_turf(src), 'sound/effects/slosh.ogg', 25, 1) + playsound(src, 'sound/effects/slosh.ogg', 25, 1) if(reagents.total_volume < 1) to_chat(user, "\The [nick] is out of water!") return 1 diff --git a/code/game/objects/structures/vehicles/secway.dm b/code/game/objects/structures/vehicles/secway.dm index f08ad69d551..1634367f39c 100644 --- a/code/game/objects/structures/vehicles/secway.dm +++ b/code/game/objects/structures/vehicles/secway.dm @@ -58,7 +58,7 @@ return occupant.Knockdown(2) occupant.Stun(2) - playsound(get_turf(src), "sound/effects/meteorimpact.ogg", 25, 1) + playsound(src, "sound/effects/meteorimpact.ogg", 25, 1) occupant.visible_message("[occupant] crashes into \the [obstacle]!", "You crash into \the [obstacle]!") if(istype(obstacle, /mob/living)) diff --git a/code/game/objects/structures/vehicles/vehicle.dm b/code/game/objects/structures/vehicles/vehicle.dm index 71e57c05325..cb5adde8f53 100644 --- a/code/game/objects/structures/vehicles/vehicle.dm +++ b/code/game/objects/structures/vehicles/vehicle.dm @@ -118,7 +118,7 @@ else if(isscrewdriver(W) && !heldkey) var/mob/living/carbon/human/H = user to_chat(user, "You jam \the [W] into \the [src]'s ignition and feel like a genius as you try turning it!") - playsound(get_turf(src), "sound/items/screwdriver.ogg", 10, 1) + playsound(src, "sound/items/screwdriver.ogg", 10, 1) H.adjustBrainLoss(10) /obj/structure/bed/chair/vehicle/attack_hand(mob/user) @@ -245,14 +245,14 @@ next_cart = C next_cart.previous_cart = src user.visible_message("[user] connects [C] to [src].", "You connect [C] to [src]") - playsound(get_turf(src), 'sound/misc/buckle_click.ogg', 50, 1) + playsound(src, 'sound/misc/buckle_click.ogg', 50, 1) return else if (next_cart == C) next_cart.previous_cart = null next_cart = null user.visible_message("[user] disconnects [C] to [src].", "You disconnect [C] to [src]") - playsound(get_turf(src), 'sound/misc/buckle_unclick.ogg', 50, 1) + playsound(src, 'sound/misc/buckle_unclick.ogg', 50, 1) return /obj/structure/bed/chair/vehicle/update_dir() diff --git a/code/game/objects/structures/vehicles/wheelchair.dm b/code/game/objects/structures/vehicles/wheelchair.dm index 6c510cfbe02..d36c4a9612b 100644 --- a/code/game/objects/structures/vehicles/wheelchair.dm +++ b/code/game/objects/structures/vehicles/wheelchair.dm @@ -276,7 +276,7 @@ /obj/structure/bed/chair/vehicle/wheelchair/motorized/syndicate/proc/crush(var/mob/living/H,var/bloodcolor) //Basically identical to the MULE, see mulebot.dm src.visible_message("[src] drives over [H]!") - playsound(get_turf(src), 'sound/effects/splat.ogg', 50, 1) + playsound(src, 'sound/effects/splat.ogg', 50, 1) var/damage = rand(5,10) //We're not as heavy as a MULE. Where it does 30-90 damage, we do 15-30 damage H.apply_damage(damage, BRUTE, LIMB_CHEST) H.apply_damage(damage, BRUTE, LIMB_LEFT_LEG) diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm index 5414c1fdbfb..1a7e9fc37aa 100644 --- a/code/game/objects/structures/watercloset.dm +++ b/code/game/objects/structures/watercloset.dm @@ -246,7 +246,7 @@ if(iswrench(I)) user.visible_message("[user] starts adjusting the bolts on \the [src].", \ "You start adjusting the bolts on \the [src].") - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1) + playsound(src, 'sound/items/Ratchet.ogg', 100, 1) if(do_after(user, src, 50)) if(anchored == 1) src.visible_message("[user] unbolts \the [src] from the floor.", \ @@ -490,7 +490,7 @@ busy = 0 M.clean_blood() if(M.reagents.maximum_volume > M.reagents.total_volume) - playsound(get_turf(src), 'sound/effects/slosh.ogg', 25, 1) + playsound(src, 'sound/effects/slosh.ogg', 25, 1) M.reagents.add_reagent(WATER, min(M.reagents.maximum_volume - M.reagents.total_volume, 50)) user.visible_message("[user] finishes soaking \the [M], \he could clean the entire station with that.","You finish soaking \the [M], you feel as if you could clean anything now, even the Chef's backroom...") else diff --git a/code/game/objects/structures/windoor_assembly.dm b/code/game/objects/structures/windoor_assembly.dm index b56fb2b01f7..419a2caa4fa 100644 --- a/code/game/objects/structures/windoor_assembly.dm +++ b/code/game/objects/structures/windoor_assembly.dm @@ -77,7 +77,7 @@ obj/structure/windoor_assembly/Destroy() var/obj/item/weapon/weldingtool/WT = W if (WT.remove_fuel(0,user)) user.visible_message("[user] dissassembles the windoor assembly.", "You start to dissassemble the windoor assembly.") - playsound(get_turf(src), 'sound/items/Welder2.ogg', 50, 1) + playsound(src, 'sound/items/Welder2.ogg', 50, 1) if(do_after(user, src, 40)) if(!src || !WT.isOn()) @@ -96,7 +96,7 @@ obj/structure/windoor_assembly/Destroy() //Wrenching an unsecure assembly anchors it in place. Step 4 complete if(iswrench(W) && !anchored) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1) + playsound(src, 'sound/items/Ratchet.ogg', 100, 1) user.visible_message("[user] secures the windoor assembly to the floor.", "You start to secure the windoor assembly to the floor.") if(do_after(user, src, 40)) @@ -111,7 +111,7 @@ obj/structure/windoor_assembly/Destroy() //Unwrenching an unsecure assembly un-anchors it. Step 4 undone else if(iswrench(W) && anchored) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1) + playsound(src, 'sound/items/Ratchet.ogg', 100, 1) user.visible_message("[user] unsecures the windoor assembly to the floor.", "You start to unsecure the windoor assembly to the floor.") if(do_after(user, src, 40)) @@ -146,13 +146,16 @@ obj/structure/windoor_assembly/Destroy() //Adding cable to the assembly. Step 5 complete. else if(istype(W, /obj/item/stack/cable_coil) && anchored) + var/obj/item/stack/cable_coil/CC = W + if(CC.amount < 2) + to_chat(user, "You need more cable for this!") + return user.visible_message("[user] wires the windoor assembly.", "You start to wire the windoor assembly.") if(do_after(user, src, 40)) if(!src) return - var/obj/item/stack/cable_coil/CC = W - CC.use(1) + CC.use(2) to_chat(user, "You wire the windoor!") src.state = "02" if(src.secure) @@ -166,7 +169,7 @@ obj/structure/windoor_assembly/Destroy() //Removing wire from the assembly. Step 5 undone. if(iswirecutter(W)) - playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 100, 1) + playsound(src, 'sound/items/Wirecutter.ogg', 100, 1) user.visible_message("[user] cuts the wires from the airlock assembly.", "You start to cut the wires from airlock assembly.") if(do_after(user, src, 40)) @@ -183,7 +186,7 @@ obj/structure/windoor_assembly/Destroy() //Adding airlock electronics for access. Step 6 complete. else if(istype(W, /obj/item/weapon/circuitboard/airlock) && W:icon_state != "door_electronics_smoked") if(user.drop_item(W, src)) // To prevent you using the airlock electronics on 2 windoors at once. - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 100, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 100, 1) user.visible_message("[user] installs the electronics into the airlock assembly.", "You start to install electronics into the airlock assembly.") if(do_after(user, src, 40)) @@ -199,7 +202,7 @@ obj/structure/windoor_assembly/Destroy() //Screwdriver to remove airlock electronics. Step 6 undone. else if(isscrewdriver(W) && electronics) - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 100, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 100, 1) user.visible_message("[user] removes the electronics from the airlock assembly.", "You start to uninstall electronics from the airlock assembly.") if(do_after(user, src, 40)) @@ -220,7 +223,7 @@ obj/structure/windoor_assembly/Destroy() to_chat(usr, "The assembly is missing electronics.") return usr << browse(null, "window=windoor_access") - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 100, 1) + playsound(src, 'sound/items/Crowbar.ogg', 100, 1) user.visible_message("[user] pries the windoor into the frame.", "You start prying the windoor into the frame.") if(do_after(user, src, 40)) @@ -239,10 +242,15 @@ obj/structure/windoor_assembly/Destroy() windoor.icon_state = "right[secure]open" windoor.base_state = "right[secure]" windoor.dir = src.dir - windoor.setDensity(FALSE) - - windoor.req_access = src.electronics.conf_access - windoor.electronics = src.electronics + windoor.setDensity(FALSE) + windoor.fingerprints += src.fingerprints + windoor.fingerprintshidden += src.fingerprintshidden + windoor.fingerprintslast = user.ckey + if(src.electronics.one_access) + windoor.req_access = null + windoor.req_one_access = src.electronics.conf_access + else + windoor.req_access = src.electronics.conf_access src.electronics.forceMove(windoor) qdel(src) diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index 8a25e902ef5..c54285b921e 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -22,7 +22,7 @@ var/list/one_way_windows var/ini_dir = null //This really shouldn't exist, but it does and I don't want to risk deleting it because it's likely mapping-related var/d_state = WINDOWLOOSEFRAME //Normal windows have one step (unanchor), reinforced windows have three var/shardtype = /obj/item/weapon/shard - var/sheettype = /obj/item/stack/sheet/glass/glass //Used for deconstruction + sheet_type = /obj/item/stack/sheet/glass/glass //Used for deconstruction var/sheetamount = 1 //Number of sheets needed to build this window (determines how much shit is spawned via Destroy()) var/reinforced = 0 //Used for deconstruction steps penetration_dampening = 1 @@ -67,6 +67,11 @@ var/list/one_way_windows ..() examine_health(user) +/obj/structure/window/AltClick(mob/user) + if(user.incapacitated() || !Adjacent(user)) + return + rotate() + /obj/structure/window/proc/examine_health(mob/user) if(!anchored) to_chat(user, "It appears to be completely loose and movable.") @@ -161,7 +166,7 @@ var/list/one_way_windows if(O.onBuckledUserKick(H, src)) return //don't return 1! we will do the normal "touch" action if so! - playsound(get_turf(src), 'sound/effects/glassknock.ogg', 100, 1) + playsound(src, 'sound/effects/glassknock.ogg', 100, 1) H.do_attack_animation(src, H) H.visible_message("\The [H] kicks \the [src].", \ @@ -227,7 +232,7 @@ var/list/one_way_windows else if(usr.a_intent == I_HURT) user.do_attack_animation(src, user) user.delayNextAttack(10) - playsound(get_turf(src), 'sound/effects/glassknock.ogg', 100, 1) + playsound(src, 'sound/effects/glassknock.ogg', 100, 1) user.visible_message("[user] bangs against \the [src]!", \ "You bang against \the [src]!", \ "You hear banging.") @@ -235,7 +240,7 @@ var/list/one_way_windows //Knock against it else user.delayNextAttack(10) - playsound(get_turf(src), 'sound/effects/glassknock.ogg', 50, 1) + playsound(src, 'sound/effects/glassknock.ogg', 50, 1) user.visible_message("[user] knocks on \the [src].", \ "You knock on \the [src].", \ "You hear knocking.") @@ -463,7 +468,7 @@ var/list/one_way_windows playsound(src, 'sound/items/Welder.ogg', 100, 1) user.visible_message("[user] disassembles \the [src].", \ "You disassemble \the [src].") - drop_stack(sheettype, get_turf(src), sheetamount, user) + drop_stack(sheet_type, get_turf(src), sheetamount, user) qdel(src) return else @@ -493,7 +498,7 @@ var/list/one_way_windows playsound(src, 'sound/items/Welder.ogg', 100, 1) user.visible_message("[user] disassembles \the [src].", \ "You disassemble \the [src].") - drop_stack(sheettype, get_turf(src), sheetamount, user) + drop_stack(sheet_type, get_turf(src), sheetamount, user) Destroy() return else @@ -561,7 +566,7 @@ var/list/one_way_windows update_nearby_icons() if(brokenup) //If the instruction we were sent clearly states we're breaking the window, not deleting it ! if(loc) - playsound(get_turf(src), "shatter", 70, 1) + playsound(src, "shatter", 70, 1) spawnBrokenPieces() if(one_way) one_way_windows.Remove(src) @@ -633,7 +638,7 @@ var/list/one_way_windows name = "reinforced window" desc = "A window with a rod matrice. It looks more solid than the average window." icon_state = "rwindow" - sheettype = /obj/item/stack/sheet/glass/rglass + sheet_type = /obj/item/stack/sheet/glass/rglass health = 40 d_state = WINDOWSECURE reinforced = 1 @@ -649,7 +654,7 @@ var/list/one_way_windows desc = "A window made out of a plasma-silicate alloy. It looks insanely tough to break and burn through." icon_state = "plasmawindow" shardtype = /obj/item/weapon/shard/plasma - sheettype = /obj/item/stack/sheet/glass/plasmaglass + sheet_type = /obj/item/stack/sheet/glass/plasmaglass health = 120 penetration_dampening = 5 @@ -662,10 +667,16 @@ var/list/one_way_windows desc = "A window made out of a plasma-silicate alloy and a rod matrice. It looks hopelessly tough to break and is most likely nigh fireproof." icon_state = "plasmarwindow" shardtype = /obj/item/weapon/shard/plasma - sheettype = /obj/item/stack/sheet/glass/plasmarglass + sheet_type = /obj/item/stack/sheet/glass/plasmarglass health = 160 penetration_dampening = 7 + +// Used on Packed ; smartglassified roundstart +/obj/structure/window/reinforced/plasma/interogation_room/initialize() + smartwindow = new(src) + smartwindow.id_tag = "InterogationRoomIDTag" + /obj/structure/window/reinforced/plasma/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) return @@ -675,7 +686,7 @@ var/list/one_way_windows desc = "A window with a rod matrice. Its surface is completely tinted, making it opaque. Why not a wall ?" icon_state = "twindow" opacity = 1 - sheettype = /obj/item/stack/sheet/glass/rglass //A glass type for this window doesn't seem to exist, so here's to you + sheet_type = /obj/item/stack/sheet/glass/rglass //A glass type for this window doesn't seem to exist, so here's to you /obj/structure/window/reinforced/tinted/frosted @@ -683,7 +694,7 @@ var/list/one_way_windows desc = "A window with a rod matrice. Its surface is completely tinted, making it opaque, and it's frosty. Why not an ice wall ?" icon_state = "fwindow" health = 30 - sheettype = /obj/item/stack/sheet/glass/rglass //Ditto above + sheet_type = /obj/item/stack/sheet/glass/rglass //Ditto above /obj/structure/window/send_to_past(var/duration) ..() diff --git a/code/game/say.dm b/code/game/say.dm index 5dec825c19f..7e6d9b39ca9 100644 --- a/code/game/say.dm +++ b/code/game/say.dm @@ -102,11 +102,8 @@ var/list/freqtoname = list( /atom/movable/proc/render_speech(var/datum/speech/speech) say_testing(src, "render_speech() - Freq: [speech.frequency], radio=\ref[speech.radio]") var/freqpart = "" - var/radioicon = "" if(speech.frequency) - if(speech.radio) - radioicon = "[bicon(speech.radio)]" - freqpart = " [radioicon]\[[get_radio_name(speech.frequency)]\]" + freqpart = " \[[get_radio_name(speech.frequency)]\]" speech.wrapper_classes.Add(get_radio_span(speech.frequency)) var/pooled=0 var/datum/speech/filtered_speech diff --git a/code/game/shuttles/trade.dm b/code/game/shuttles/trade.dm index be20b0d2c1c..c2840f48f78 100644 --- a/code/game/shuttles/trade.dm +++ b/code/game/shuttles/trade.dm @@ -14,7 +14,9 @@ var/global/datum/shuttle/trade/trade_shuttle = new(starting_area = /area/shuttle stable = 0 //Don't stun everyone and don't throw anything when moving can_rotate = 0 //Sleepers, body scanners and multi-tile airlocks aren't rotated properly - +/datum/shuttle/trade/proc/notify_port_toggled(var/reason) + for(var/obj/machinery/computer/shuttle_control/trade/T in control_consoles) + T.notify_port_toggled(reason) /datum/shuttle/trade/initialize() .=..() @@ -33,6 +35,31 @@ var/global/datum/shuttle/trade/trade_shuttle = new(starting_area = /area/shuttle link_to(trade_shuttle) .=..() +/obj/machinery/computer/shuttle_control/trade/proc/notify_port_toggled(var/reason) + if(!reason) + //Port opened + var/obj/item/weapon/paper/P = new(get_turf(src)) + P.name = "NT Port Opened - [worldtime2text()]" + P.info = "This is official notification that sanctioned arrival of Vox trading vessels has resumed as normal." + P.update_icon() + playsound(get_turf(src), "sound/effects/fax.ogg", 50, 1) + var/image/stampoverlay = image('icons/obj/bureaucracy.dmi') + stampoverlay.icon_state = "paper_stamp-cent" + P.stamped += /obj/item/weapon/stamp + P.overlays += stampoverlay + P.stamps += "
    This paper has been stamped by the Central Command Quantum Relay." + if(reason) + var/obj/item/weapon/paper/P = new(get_turf(src)) + P.name = "NT Port Closure - [worldtime2text()]" + P.info = "This is official notification that sanctioned arrival of Vox trading vessels has been indefinitely suspended with no guarantee of appeal. The provided justification was:

    [reason]" + P.update_icon() + playsound(get_turf(src), "sound/effects/fax.ogg", 50, 1) + var/image/stampoverlay = image('icons/obj/bureaucracy.dmi') + stampoverlay.icon_state = "paper_stamp-cent" + P.stamped += /obj/item/weapon/stamp + P.overlays += stampoverlay + P.stamps += "
    This paper has been stamped by the Central Command Quantum Relay." + //code/game/objects/structures/docking_port.dm /obj/docking_port/destination/trade/start @@ -43,3 +70,6 @@ var/global/datum/shuttle/trade/trade_shuttle = new(starting_area = /area/shuttle /obj/docking_port/destination/trade/transit areaname = "hyperspace (trade shuttle)" + +/obj/docking_port/destination/trade/extra + areaname = "Casino" \ No newline at end of file diff --git a/code/game/shuttles/voxresearch_shuttle.dm b/code/game/shuttles/voxresearch_shuttle.dm deleted file mode 100644 index 71e704edfcc..00000000000 --- a/code/game/shuttles/voxresearch_shuttle.dm +++ /dev/null @@ -1,23 +0,0 @@ -var/global/datum/shuttle/voxresearch/voxresearch_shuttle = new(starting_area = /area/shuttle/voxresearch/station) - -/datum/shuttle/voxresearch - name = "Research Shuttle" - can_link_to_computer = LINK_FREE - req_access = 0 - -/datum/shuttle/voxresearch/initialize() - .=..() - add_dock(/obj/docking_port/destination/voxresearch/station) - add_dock(/obj/docking_port/destination/voxresearch/outpost) - -/obj/machinery/computer/shuttle_control/voxresearch/New() //Main shuttle_control code is in code/game/machinery/computer/shuttle_computer.dm - link_to(voxresearch_shuttle) - .=..() - -//code/game/objects/structures/docking_port.dm - -/obj/docking_port/destination/voxresearch/station - areaname = "Genetic Research Station" - -/obj/docking_port/destination/voxresearch/outpost - areaname = "Asteroid" \ No newline at end of file diff --git a/code/game/smoothwall.dm b/code/game/smoothwall.dm index 2407924e866..4de9d6bc261 100644 --- a/code/game/smoothwall.dm +++ b/code/game/smoothwall.dm @@ -24,13 +24,11 @@ /atom/proc/isSmoothableNeighbor(atom/A) if(!A) - WARNING("[__FILE__]L[__LINE__]: atom/isSmoothableNeighbor given bad atom") return 0 return isInTypes(A, canSmoothWith) /turf/simulated/wall/isSmoothableNeighbor(atom/A) if(!A) - WARNING("[__FILE__]L[__LINE__]: turf/isSmoothableNeighbor given bad atom") return 0 if(isInTypes(A, canSmoothWith)) // COLON OPERATORS ARE TERRIBLE BUT I HAVE NO CHOICE diff --git a/code/game/sound.dm b/code/game/sound.dm index c0fa4516b29..3773c5b4ca5 100644 --- a/code/game/sound.dm +++ b/code/game/sound.dm @@ -28,7 +28,7 @@ var/list/machete_throw_hit_sound = list('sound/weapons/hfmachete_throw_hit01.ogg //gas_modified controls if a sound is affected by how much gas there is in the atmosphere of the source //space sounds have no gas modification, for example. Though >space sounds -/proc/playsound(var/atom/source, soundin, vol as num, vary, extrarange as num, falloff, var/gas_modified = 1, var/channel = 0) +/proc/playsound(var/atom/source, soundin, vol as num, vary, extrarange as num, falloff, var/gas_modified = 1, var/channel = 0,var/wait = FALSE) var/turf/turf_source = get_turf(source) ASSERT(!isnull(turf_source)) @@ -79,13 +79,13 @@ var/list/machete_throw_hit_sound = list('sound/weapons/hfmachete_throw_hit01.ogg if (player_turf && turf_source && player_turf.z == turf_source.z) if(get_dist(player_turf, turf_source) <= Dist) - player.playsound_local(turf_source, soundin, vol, vary, frequency, falloff, gas_modified, channel) + player.playsound_local(turf_source, soundin, vol, vary, frequency, falloff, gas_modified, channel,wait) var/const/FALLOFF_SOUNDS = 1 var/const/SURROUND_CAP = 7 #define MIN_SOUND_PRESSURE 2 //2 kPa of pressure required to at least hear sound -/mob/proc/playsound_local(var/turf/turf_source, soundin, vol as num, vary, frequency, falloff, gas_modified, var/channel = 0) +/mob/proc/playsound_local(var/turf/turf_source, soundin, vol as num, vary, frequency, falloff, gas_modified, var/channel = 0,var/wait = FALSE) if(!src.client) return @@ -111,7 +111,7 @@ var/const/SURROUND_CAP = 7 soundin = get_sfx(soundin) - var/sound/S = sound(soundin, 0, 0, channel, vol) + var/sound/S = sound(soundin, 0, wait, channel, vol,) if (vary) if(frequency) diff --git a/code/game/striketeams/emergency_response_team.dm b/code/game/striketeams/emergency_response_team.dm index 06d6a0b08b6..ad7ca04e391 100644 --- a/code/game/striketeams/emergency_response_team.dm +++ b/code/game/striketeams/emergency_response_team.dm @@ -1,7 +1,6 @@ //ERT var/list/response_team_members = list() -var/list/distributed_ert_suits = list() /datum/striketeam/ert striketeam_name = TEAM_ERT diff --git a/code/game/striketeams/striketeam_datums.dm b/code/game/striketeams/striketeam_datums.dm index 0d55bfddb8c..ef165f82ad6 100644 --- a/code/game/striketeams/striketeam_datums.dm +++ b/code/game/striketeams/striketeam_datums.dm @@ -144,7 +144,7 @@ var/list/sent_strike_teams = list() new_commando.key = applicant.key - new_commando.update_action_buttons(1) + new_commando.update_action_buttons_icon() new_commando.mind.store_memory("Mission: [mission].") greet_commando(new_commando) diff --git a/code/game/supplyshuttle.dm b/code/game/supplyshuttle.dm index 1786100263a..92f262e784a 100644 --- a/code/game/supplyshuttle.dm +++ b/code/game/supplyshuttle.dm @@ -212,8 +212,14 @@ var/datum/controller/supply_shuttle/supply_shuttle = new var/datum/supply_order/SO = S var/datum/supply_packs/SP = SO.object - - var/atom/A = new SP.containertype(pickedloc) + var/atom/A + if(Holiday == APRIL_FOOLS_DAY && prob(10)) + if(prob(5)) + A = new /mob/living/simple_animal/hostile/mimic/crate/chest(pickedloc) + else + A = new /mob/living/simple_animal/hostile/mimic/crate(pickedloc) + else + A = new SP.containertype(pickedloc) A.name = "[SP.containername] [SO.comment ? "([SO.comment])":"" ]" //supply manifest generation begin @@ -251,6 +257,8 @@ var/datum/controller/supply_shuttle/supply_shuttle = new B2:amount = SP.amount slip.info += "
  • [B2.name]
  • " //add the item to the manifest + SP.post_creation(A) + //manifest finalisation slip.info += {"

diff --git a/code/game/turfs/simulated.dm b/code/game/turfs/simulated.dm index f83d4891784..d40b92ff256 100644 --- a/code/game/turfs/simulated.dm +++ b/code/game/turfs/simulated.dm @@ -30,8 +30,8 @@ if (istype(A,/mob/living/carbon)) var/mob/living/carbon/M = A - if(M.lying) - return + if(!M.on_foot()) + return ..() if(istype(M, /mob/living/carbon/human)) var/mob/living/carbon/human/H = M @@ -68,14 +68,6 @@ if (H.Slip(4, 5)) step(H, H.dir) to_chat(H, "You tripped over your hair!") - - //Anything beyond that point will not fire if the mob isn't physically walking here - if(!M.on_foot()) //Checks lying, flying and locked.to - return ..() - - //And anything beyond that point will not fire for slimes - if(isslime(M)) //Slimes just don't slip, end of story - return ..() ..() //returns 1 if made bloody, returns 0 otherwise diff --git a/code/game/turfs/simulated/floor.dm b/code/game/turfs/simulated/floor.dm index 1811d95f9a2..0ac39d57fc7 100644 --- a/code/game/turfs/simulated/floor.dm +++ b/code/game/turfs/simulated/floor.dm @@ -212,7 +212,7 @@ turf/simulated/floor/update_icon() if("bananium") if(!spam_flag) spam_flag = 1 - playsound(get_turf(src), 'sound/items/bikehorn.ogg', 50, 1) + playsound(src, 'sound/items/bikehorn.ogg', 50, 1) spawn(20) spam_flag = 0 ..() @@ -310,7 +310,7 @@ turf/simulated/floor/update_icon() return //you can't break legos if(material=="phazon") //Phazon shatters spawn(rand(2,10)) - playsound(get_turf(src), "shatter", 70, 1) + playsound(src, "shatter", 70, 1) make_plating() return @@ -647,7 +647,7 @@ turf/simulated/floor/update_icon() if("bananium") if(!spam_flag) spam_flag = 1 - playsound(get_turf(src), "clownstep", 50, 1) + playsound(src, "clownstep", 50, 1) spawn(20) spam_flag = 0 if("uranium") diff --git a/code/game/turfs/simulated/floor_glass.dm b/code/game/turfs/simulated/floor_glass.dm index 77b16c58808..cd2857c2410 100644 --- a/code/game/turfs/simulated/floor_glass.dm +++ b/code/game/turfs/simulated/floor_glass.dm @@ -60,7 +60,7 @@ /turf/simulated/floor/glass/proc/break_turf(var/no_teleport=FALSE) if(loc) - playsound(get_turf(src), "shatter", 70, 1) + playsound(src, "shatter", 70, 1) //ReplaceWithLattice() // TODO: Break all pipes/wires? // FIXME: Animations are fucked, controversial, I want to move on to other shit. @@ -215,7 +215,7 @@ else if(usr.a_intent == I_HURT) user.do_attack_animation(src, user) user.delayNextAttack(10) - playsound(get_turf(src), 'sound/effects/glassknock.ogg', 100, 1) + playsound(src, 'sound/effects/glassknock.ogg', 100, 1) user.visible_message("[user] bangs against \the [src]!", \ "You bang against \the [src]!", \ "You hear banging.") @@ -224,7 +224,7 @@ //Knock against it else user.delayNextAttack(10) - playsound(get_turf(src), 'sound/effects/glassknock.ogg', 50, 1) + playsound(src, 'sound/effects/glassknock.ogg', 50, 1) user.visible_message("[user] knocks on \the [src].", \ "You knock on \the [src].", \ "You hear knocking.") diff --git a/code/game/turfs/simulated/floor_types.dm b/code/game/turfs/simulated/floor_types.dm index 57ecb829846..018916ee5d9 100644 --- a/code/game/turfs/simulated/floor_types.dm +++ b/code/game/turfs/simulated/floor_types.dm @@ -112,7 +112,7 @@ return if(iswrench(C)) to_chat(user, "Removing rods...") - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 80, 1) + playsound(src, 'sound/items/Ratchet.ogg', 80, 1) if(do_after(user, src, 30) && istype(src, /turf/simulated/floor/engine)) // Somehow changing the turf does NOT kill the current running proc. new /obj/item/stack/rods(src, 2) ChangeTurf(/turf/simulated/floor) diff --git a/code/game/turfs/simulated/invulnerable_wall.dm b/code/game/turfs/simulated/invulnerable_wall.dm index 3be6af28b2b..934a84aaa9d 100644 --- a/code/game/turfs/simulated/invulnerable_wall.dm +++ b/code/game/turfs/simulated/invulnerable_wall.dm @@ -63,4 +63,10 @@ name = "blue ice wall" desc = "The incredible compressive forces that formed this sturdy ice wall gave it a blue color." icon_state = "ice" - walltype = "ice" \ No newline at end of file + walltype = "ice" + +/turf/simulated/wall/invulnerable/r_wall + name = "reinforced wall" + desc = "A huge chunk of reinforced metal and anchored rods used to seperate rooms and keep all but the most equipped crewmen out." + icon_state = "r_wall" + walltype = "rwall" \ No newline at end of file diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm index 7ff0dc7c7a1..0703a505a90 100644 --- a/code/game/turfs/simulated/walls.dm +++ b/code/game/turfs/simulated/walls.dm @@ -13,7 +13,8 @@ var/walltype = "metal" var/hardness = 60 //Higher numbers are harder (so that it actually makes sense). Walls are 60 hardness, reinforced walls are 90 hardness. No hardness over 100, PLEASE - var/engraving, engraving_quality //engraving on the wall + var/engraving + var/engraving_quality //engraving on the wall var/del_suppress_resmoothing = 0 // Do not resmooth neighbors on Destroy. (smoothwall.dm) var/dismantle_type = /turf/simulated/floor/plating diff --git a/code/game/turfs/simulated/walls_mineral.dm b/code/game/turfs/simulated/walls_mineral.dm index febe145265a..18266bbb0f1 100644 --- a/code/game/turfs/simulated/walls_mineral.dm +++ b/code/game/turfs/simulated/walls_mineral.dm @@ -28,10 +28,8 @@ /turf/simulated/wall/mineral/wood/ex_act(var/severity) if(severity < 3) - ChangeTurf(get_underlying_turf()) getFromPool(/obj/item/stack/sheet/wood, src, 2) - else - dismantle_wall() + ..() /turf/simulated/wall/mineral/brick name = "brick wall" diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm index 77524c1617c..95a885ec4e1 100644 --- a/code/game/turfs/space/space.dm +++ b/code/game/turfs/space/space.dm @@ -13,17 +13,30 @@ dynamic_lighting = 0 luminosity = 1 can_border_transition = 1 + var/static/list/parallax_appearances /turf/space/New() if(loc) var/area/A = loc A.area_turfs += src - icon_state = "[((x + y) ^ ~(x * y) + z) % 25]" - var/image/I = image('icons/turf/space_parallax1.dmi',"[icon_state]") - I.plane = SPACE_DUST_PLANE - I.alpha = 80 - I.blend_mode = BLEND_ADD - overlays += I + +/turf/space/initialize() + if(!parallax_appearances) + parallax_appearances = list() + for(var/i in 0 to 25) + var/I = "[i]" + icon_state = I + var/image/parallax_overlay = image('icons/turf/space_parallax1.dmi', I) + parallax_overlay.plane = SPACE_DUST_PLANE + parallax_overlay.alpha = 80 + parallax_overlay.blend_mode = BLEND_ADD + overlays += parallax_overlay + parallax_appearances[I] = appearance + overlays.Cut() + appearance = parallax_appearances["[((x + y) ^ ~(x * y) + z) % 26]"] + +/turf/space/spawned_by_map_element(var/datum/map_element/ME, var/list/objects) + initialize() /turf/space/attack_paw(mob/user as mob) return src.attack_hand(user) @@ -185,5 +198,8 @@ /turf/space/void/New() return +/turf/space/void/initialize() + return + /turf/space/has_gravity() return 0 diff --git a/code/game/turfs/space/transit.dm b/code/game/turfs/space/transit.dm index 696598351f9..3443234fee8 100644 --- a/code/game/turfs/space/transit.dm +++ b/code/game/turfs/space/transit.dm @@ -9,6 +9,9 @@ update_icon() +/turf/space/transit/initialize() + return + /turf/space/transit/update_icon() icon_state = "" diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index 1a5f9ce800e..580a968f8f2 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -85,9 +85,6 @@ src.Entered(AM) return -/turf/proc/initialize() - return - /turf/ex_act(severity) return 0 @@ -414,6 +411,7 @@ // zone.SetStatus(ZONE_ACTIVE) var/turf/W = new N(src) + W.initialize() if(tell_universe) universe.OnTurfChange(W) @@ -532,8 +530,9 @@ spawn(0) M.take_damage(100, "brute") -/turf/proc/Bless() - turf_flags |= NOJAUNT +/turf/bless() + holy = 1 + ..() ///////////////////////////////////////////////////////////////////////// // Navigation procs @@ -707,11 +706,6 @@ holomap_data = list() holomap_data += I -// Calls the above, but only if the game has not yet started. -/turf/proc/soft_add_holomap(var/atom/movable/AM) - if (!ticker || ticker.current_state != GAME_STATE_PLAYING) - add_holomap(AM) - // Goddamnit BYOND. // So for some reason, I incurred a rendering issue with the usage of FLOAT_PLANE for the holomap plane. // (For some reason the existance of underlays prevented the main icon and overlays to render) diff --git a/code/game/turfs/unsimulated/snow.dm b/code/game/turfs/unsimulated/snow.dm index 69073e5c6ee..857a2092a7e 100644 --- a/code/game/turfs/unsimulated/snow.dm +++ b/code/game/turfs/unsimulated/snow.dm @@ -1,6 +1,6 @@ //Arctic atmospheric defines -#define ARCTIC_ATMOSPHERE 68.13 //Pretty low pressure, very thin air, might be hard to breathe, but not enough for pressure damage +#define ARCTIC_ATMOSPHERE 90.13 #define T_ARCTIC 223.65 //- 49.5 Celcius, taken from South Pole averages #define MOLES_ARCTICSTANDARD (ARCTIC_ATMOSPHERE*CELL_VOLUME/(T_ARCTIC*R_IDEAL_GAS_EQUATION)) //Note : Open air tiles obviously aren't 2.5 meters in height, but abstracted for now with infinite atmos #define MOLES_O2STANDARD_ARCTIC MOLES_ARCTICSTANDARD*O2STANDARD //O2 standard value (21%) @@ -18,25 +18,25 @@ can_border_transition = 1 dynamic_lighting = 0 luminosity = 1 - + plane = PLATING_PLANE var/snowballs = 0 - var/global/list/snow_layers = list() - var/global/list/dirt_layers = list() + var/global/list/icon_state_to_appearance = list() /turf/unsimulated/floor/snow/New() ..() - icon_state = "snow[rand(0, 6)]" - relativewall_neighbours() + if(icon_state_to_appearance[icon_state]) + appearance = icon_state_to_appearance[icon_state] + else + var/image/snowfx1 = image('icons/turf/snowfx.dmi', "snowlayer1",SNOW_OVERLAY_LAYER) + var/image/snowfx2 = image('icons/turf/snowfx.dmi', "snowlayer2",SNOW_OVERLAY_LAYER) + snowfx1.plane = EFFECTS_PLANE + snowfx2.plane = EFFECTS_PLANE + overlays += snowfx1 + overlays += snowfx2 + icon_state_to_appearance[icon_state] = appearance snowballs = rand(5, 10) //Used to be (30, 50). A quick way to overload the server with atom instances. - update_icon() - -/turf/unsimulated/floor/snow/relativewall_neighbours() - for(var/direction in alldirs) - var/turf/adj_tile = get_step(src, direction) - if(istype(adj_tile, /turf/unsimulated/floor/snow)) - adj_tile.update_icon() /turf/unsimulated/floor/snow/attackby(obj/item/weapon/W as obj, mob/user as mob) @@ -49,7 +49,7 @@ if(do_after(user, src, 20)) user.visible_message("[user] digs out some snow with \the [W].", \ "You dig out some snow with \the [W].") - extract_snowballs(5, 0, user) + extract_snowballs(5, FALSE, user) /turf/unsimulated/floor/snow/attack_hand(mob/user as mob) @@ -60,11 +60,11 @@ if(do_after(user, src, 5)) user.visible_message("[user] finishes forming a snowball.", \ "You finish forming a snowball.") - extract_snowballs(1, 1, user) + extract_snowballs(1, TRUE, user) ..() -/turf/unsimulated/floor/snow/proc/extract_snowballs(var/snowball_amount = 0, var/pick_up = 0, var/mob/user) +/turf/unsimulated/floor/snow/proc/extract_snowballs(var/snowball_amount = 0, var/pick_up = FALSE, var/mob/user) if(!snowball_amount) return @@ -81,15 +81,15 @@ snowballs-- - if(!snowballs) //We're out of snow, turn into a permafrost tile - ChangeTurf(/turf/unsimulated/floor/snow/permafrost) + if(!snowballs) + return //In the future, catwalks should be the base to build in the arctic, not lattices //This would however require a decent rework of floor construction and deconstruction -/turf/unsimulated/floor/snow/permafrost/canBuildCatwalk() +/turf/unsimulated/floor/snow/canBuildCatwalk() return BUILD_FAILURE -/turf/unsimulated/floor/snow/permafrost/canBuildLattice() +/turf/unsimulated/floor/snow/canBuildLattice() if(x >= (world.maxx - TRANSITIONEDGE) || x <= TRANSITIONEDGE) return BUILD_FAILURE else if (y >= (world.maxy - TRANSITIONEDGE || y <= TRANSITIONEDGE )) @@ -98,7 +98,7 @@ return BUILD_SUCCESS return BUILD_FAILURE -/turf/unsimulated/floor/snow/permafrost/canBuildPlating() +/turf/unsimulated/floor/snow/canBuildPlating() if(x >= (world.maxx - TRANSITIONEDGE) || x <= TRANSITIONEDGE) return BUILD_FAILURE else if (y >= (world.maxy - TRANSITIONEDGE || y <= TRANSITIONEDGE )) @@ -110,116 +110,7 @@ /turf/unsimulated/floor/snow/Entered(mob/user) ..() if(isliving(user) && !user.locked_to && !user.lying && !user.flying) - playsound(get_turf(src), pick(snowsound), 10, 1, -1, channel = 123) + playsound(src, pick(snowsound), 10, 1, -1, channel = 123) -//This shit's fucked, should use relativewall. Problem is, relativewall is terrible and doesn't include diagonal directions -//So in short relativewall needs to be reworked, along with all things relying on it. Fun times ahead -/turf/unsimulated/floor/snow/update_icon() - if(overlays.len > 2) //? - overlays.Cut() - if(!snow_layers.len) - snow_layers["1"] = image('icons/turf/snowfx.dmi', "snowlayer1", 17) - snow_layers["2"] = image('icons/turf/snowfx.dmi', "snowlayer2", 17) - if(!dirt_layers.len) - for(var/dirtdir in alldirs) - dirt_layers["side[dirtdir]"] = image('icons/turf/new_snow.dmi', "permafrost_side" ,dir = dirtdir) - for(var/diagdir in diagonal) - dirt_layers["diag[diagdir]"] = image('icons/turf/new_snow.dmi', "permafrost_corner", dir = diagdir, layer = 2.1) - dirt_layers["snow[diagdir]"] = image('icons/turf/new_snow.dmi', "permafrost", dir = diagdir) - for(var/dirtdir in cardinal) - dirt_layers["snow[dirtdir]"] = image('icons/turf/new_snow.dmi', "permafrost_half", dir = dirtdir) - var/realdir = null - switch(dirtdir) - if(NORTH) - realdir = EAST|SOUTH|WEST - if(SOUTH) - realdir = WEST|NORTH|EAST - if(EAST) - realdir = SOUTH|WEST|NORTH - if(WEST) - realdir = NORTH|EAST|SOUTH - dirt_layers["snow[realdir]"] = image('icons/turf/new_snow.dmi', "permafrost_tjunction", dir = dirtdir) - dirt_layers["snow15"] = image('icons/turf/new_snow.dmi', "permafrost_crossroads") - dirt_layers["snow0"] = image('icons/turf/new_snow.dmi', "permafrost_circle") - dirt_layers["snow3"] = image('icons/turf/new_snow.dmi', "permafrost", dir = NORTH) - dirt_layers["snow12"] = image('icons/turf/new_snow.dmi', "permafrost", dir = WEST) - - //Projecting snowfall on adjacent tiles, might remove this eventually - var/lights_on = 0 - for(var/direction in alldirs) - if(!istype(get_step(src, direction), /turf/unsimulated/floor/snow)) - if(istype(get_step(src, direction), /turf/simulated/floor)) //Luminosity on tiles adjacent to snow - lights_on = 1 - overlays += dirt_layers["side[direction]"] - var/image/snow1 = snow_layers["1"] - var/image/snow2 = snow_layers["2"] - snow1.alpha = 255 - snow2.alpha = 255 - switch(direction) - if(1) - snow1.pixel_y = WORLD_ICON_SIZE - overlays += snow1 - snow2.pixel_y = WORLD_ICON_SIZE - overlays += snow2 - if(2) - snow1.pixel_y = -WORLD_ICON_SIZE - overlays += snow1 - snow2.pixel_y = -WORLD_ICON_SIZE - overlays += snow2 - if(4) - snow1.pixel_x = WORLD_ICON_SIZE - overlays += snow1 - snow2.pixel_x = WORLD_ICON_SIZE - overlays += snow2 - if(8) - snow1.pixel_x = -WORLD_ICON_SIZE - overlays += snow1 - snow2.pixel_x = -WORLD_ICON_SIZE - overlays += snow2 - snow1.alpha = 64 - snow2.alpha = 64 - snow1.pixel_x = 0 - snow2.pixel_x = 0 - snow1.pixel_y = 0 - snow2.pixel_y = 0 - if(lights_on) - set_light(5, 0.5) - else - set_light(0, 0) - overlays += snow_layers["1"] - overlays += snow_layers["2"] - -//Permafrost is frozen dirt, this shows up below the snow tiles when you dig them out /turf/unsimulated/floor/snow/permafrost - - name = "permafrost" - desc = "A layer of dirt permanently exposed to temperatures below freezing. If exposed to snow fall, it will likely be covered in snow again given a few days." icon_state = "permafrost_full" - canSmoothWith = "/turf/unsimulated/floor/snow/permafrost" - -/turf/unsimulated/floor/snow/permafrost/New() - - ..() - - snowballs = 0 - -/turf/unsimulated/floor/snow/permafrost/update_icon() - - ..() - - var/junction = findSmoothingNeighbors() - var/dircount = 0 - for(var/direction in diagonal) - if(istype(get_step(src, direction), /turf/unsimulated/floor/snow/permafrost)) - if((direction & junction) == direction) - overlays += dirt_layers["diag[direction]"] - dircount++ - if(dircount == 4) - overlays.Cut() - icon_state = "permafrost_full" - overlays += snow_layers["1"] - overlays += snow_layers["2"] - else if(junction) - overlays += dirt_layers["snow[junction]"] - else - overlays += dirt_layers["snow0"] diff --git a/code/game/turfs/unsimulated/walls.dm b/code/game/turfs/unsimulated/walls.dm index aed15bd0c35..60db4c85113 100644 --- a/code/game/turfs/unsimulated/walls.dm +++ b/code/game/turfs/unsimulated/walls.dm @@ -50,13 +50,16 @@ turf/unsimulated/wall/splashscreen plane = EFFECTS_PLANE canSmoothWith = null - New() - var/path = "icons/splashworks/" - var/list/filenames = flist(path) - for(var/filename in filenames) - if(copytext(filename, length(filename)) == "/") - filenames -= filename - icon = file("[path][pick(filenames)]") +/turf/unsimulated/wall/splashscreen/New() + if(SNOW_THEME) + icon = 'icons/snowstation.gif' // not in the splashworks file so it doesn't appear in other cases + return + var/path = "icons/splashworks/" + var/list/filenames = flist(path) + for(var/filename in filenames) + if(copytext(filename, length(filename)) == "/") + filenames -= filename + icon = file("[path][pick(filenames)]") /turf/unsimulated/wall/other icon_state = "r_wall" @@ -90,4 +93,4 @@ turf/unsimulated/wall/splashscreen ..() if(prob(80)) - icon_state = "evilwall_[rand(1,8)]" + icon_state = "evilwall_[rand(1,8)]" \ No newline at end of file diff --git a/code/game/verbs/suicide.dm b/code/game/verbs/suicide.dm index e554175f4b9..02251f39672 100644 --- a/code/game/verbs/suicide.dm +++ b/code/game/verbs/suicide.dm @@ -246,7 +246,7 @@ setCloneLoss(100) updatehealth() -//Default for all simple animals, using the Die() proc. Custom cases below +//Default for all simple animals, using the death() proc. Custom cases below /mob/living/simple_animal/attempt_suicide(forced = 0, suicide_set = 1) if(!forced) @@ -266,4 +266,4 @@ visible_message(pick("[src] suddenly starts thrashing around wildly! It looks like \he's trying to commit suicide.", \ "[src] suddenly starts mauling \himself! It looks like \he's trying to commit suicide.")) - Die() + death() diff --git a/code/libs/Get Flat Icon/Get Flat Icon.dm b/code/libs/Get Flat Icon/Get Flat Icon.dm index 11cd7becce6..b0e7afa6fd7 100644 --- a/code/libs/Get Flat Icon/Get Flat Icon.dm +++ b/code/libs/Get Flat Icon/Get Flat Icon.dm @@ -56,7 +56,6 @@ var/list/exception = list( proc/getFlatIcon(atom/A, dir, cache=1, exact=0) // 1 = use cache, 2 = override cache, 0 = ignore cache //exact = 1 means the atom won't be rotated if it's a lying mob/living/carbon - var/list/layers = list() // Associative list of [overlay = layer] var/hash = "" // Hash of overlay combination if(is_type_in_list(A, directional)&&!is_type_in_list(A, exception)) @@ -82,65 +81,9 @@ proc/getFlatIcon(atom/A, dir, cache=1, exact=0) // 1 = use cache, 2 = override c var/image/copy = image(icon=A.icon,icon_state=A.icon_state,layer=A.layer,dir=dir) initialimage[copy] = A.layer - - // Loop through the underlays, then overlays, sorting them into the layers list - var/list/process = A.underlays // Current list being processed - var/processSubset=0 // Which list is being processed: 0 = underlays, 1 = overlays - - var/currentIndex=1 // index of 'current' in list being processed - var/currentOverlay // Current overlay being sorted - var/currentLayer // Calculated layer that overlay appears on (special case for FLOAT_LAYER) - - var/compareOverlay // The overlay that the current overlay is being compared against - var/compareIndex // The index in the layers list of 'compare' - - var/list/underlaysort = list() - var/list/overlaysort = list() - var/list/sorting = underlaysort - - while(TRUE) - if(currentIndex<=process.len) - //All this does is find the appropriate layer and image - currentOverlay = process[currentIndex] - currentLayer = currentOverlay:layer - if(currentLayer<0) // Special case for FLY_LAYER - ASSERT(currentLayer > -1000) - if(processSubset == 0) // Underlay - currentLayer = A.layer+currentLayer/1000 - else // Overlay - currentLayer = A.layer+(1000+currentLayer)/1000 - - //Next is a simple sort algorithm to place the overlay by layer - if(!sorting.len) - sorting[currentOverlay] = currentLayer - currentIndex++ - continue - - for(compareIndex=1,compareIndex<=sorting.len,compareIndex++) - compareOverlay = sorting[compareIndex] - if(currentLayer < sorting[compareOverlay]) // Associated value is the calculated layer - sorting.Insert(compareIndex,currentOverlay) - sorting[currentOverlay] = currentLayer - break - if(compareIndex>sorting.len) // Reached end of list without inserting - sorting[currentOverlay]=currentLayer // Place at end - - currentIndex++ - - if(currentIndex>process.len) - if(processSubset == 0) // Switch to overlays - currentIndex = 1 - processSubset = 1 - process = A.overlays - sorting = overlaysort - else // All done - break - - //Get flat icon previously understood layers as interspersing - //and could render overlays above the atom's icon before this following modification - layers = underlaysort + var/list/layers = plane_layer_sort(A.underlays) layers += initialimage - layers += overlaysort + layers += plane_layer_sort(A.overlays) if(cache!=0) // If cache is NOT disabled // Create a hash value to represent this specific flattened icon diff --git a/code/modules/Economy/Accounts.dm b/code/modules/Economy/Accounts.dm index 579d0443f80..3a5771b614f 100644 --- a/code/modules/Economy/Accounts.dm +++ b/code/modules/Economy/Accounts.dm @@ -10,6 +10,7 @@ var/global/next_account_number = 0 var/global/obj/machinery/account_database/centcomm_account_db var/global/datum/money_account/vendor_account var/global/list/all_money_accounts = list() +var/global/datum/money_account/trader_account /proc/create_station_account() if(!station_account) diff --git a/code/modules/Economy/POS.dm b/code/modules/Economy/POS.dm index 076ec93c102..864a3232481 100644 --- a/code/modules/Economy/POS.dm +++ b/code/modules/Economy/POS.dm @@ -175,8 +175,8 @@ var/const/POS_HEADER = {" var/receipt = {"[RECEIPT_HEADER]
POINT OF SALE #[id]
Paying to: [linked_account.owner_name]
Cashier: [logged_in]
"} - - receipt += areaMaster.name + var/area/this_area = get_area(src) + receipt += this_area.name receipt += "
" receipt += {"
[worldtime2text()], [current_date_string]
@@ -225,8 +225,8 @@ var/const/POS_HEADER = {" POINT OF SALE #[id]
Paying to: [linked_account.owner_name]
Cashier: [logged_in]
"} - - receipt += areaMaster.name + var/area/this_area = get_area(src) + receipt += this_area.name receipt += "" receipt += {"
Order Data
diff --git a/code/modules/Economy/price_tagger.dm b/code/modules/Economy/price_tagger.dm index c67527b4e14..13092f89f14 100644 --- a/code/modules/Economy/price_tagger.dm +++ b/code/modules/Economy/price_tagger.dm @@ -27,5 +27,5 @@ if(istype(target, /obj)) var/obj/O = target O.price = current_price - playsound(get_turf(src), 'sound/machines/twobeep.ogg', 100, 1) + playsound(src, 'sound/machines/twobeep.ogg', 100, 1) to_chat(user, "Changed price to [current_price] credits.") \ No newline at end of file diff --git a/code/modules/RCD/RCD.dm b/code/modules/RCD/RCD.dm index f43f4e21d1f..fd05636a5d9 100644 --- a/code/modules/RCD/RCD.dm +++ b/code/modules/RCD/RCD.dm @@ -318,7 +318,7 @@ qdel(W) matter += 10 - playsound(get_turf(src), 'sound/machines/click.ogg', 20, 1) + playsound(src, 'sound/machines/click.ogg', 20, 1) to_chat(user, "\the [src] now holds [matter]/[max_matter] matter-units.") return 1 diff --git a/code/modules/RCD/RSF.dm b/code/modules/RCD/RSF.dm index 483fd3f231b..9b6f2217454 100644 --- a/code/modules/RCD/RSF.dm +++ b/code/modules/RCD/RSF.dm @@ -68,3 +68,15 @@ afterattack(A,user) //If it's a table call afterattack now, and return 1 so it doesn't call the table attackby proc. return 1 return 0 //Otherwise proceed as normal. + +/obj/item/device/rcd/borg/rsf/soviet + name = "\improper Rapid-Soviet-Fabricator" + desc = "A device used to rapidly deploy essential soviet items." + cell_power_per_energy = 100 + schematics = list( + /datum/rcd_schematic/rsf/glass, + /datum/rcd_schematic/rsf/flask, + /datum/rcd_schematic/rsf/ushanka, + /datum/rcd_schematic/rsf/vodka, + /datum/rcd_schematic/rsf/greyshit_vodka + ) diff --git a/code/modules/RCD/schematics/engi.dm b/code/modules/RCD/schematics/engi.dm index 999c33b4fda..71a8b92562c 100644 --- a/code/modules/RCD/schematics/engi.dm +++ b/code/modules/RCD/schematics/engi.dm @@ -13,13 +13,13 @@ return "it cannot deconstruct reinforced walls!" to_chat(user, "Deconstructing \the [T]...") - playsound(get_turf(master), 'sound/machines/click.ogg', 50, 1) + playsound(master, 'sound/machines/click.ogg', 50, 1) if(master.delay(user, T, 4 SECONDS)) if(master.get_energy(user) < energy_cost) return 1 - playsound(get_turf(master), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(master, 'sound/items/Deconstruct.ogg', 50, 1) T.ChangeTurf(/turf/simulated/floor/plating) return 0 @@ -30,7 +30,7 @@ if(master.get_energy(user) < energy_cost) return 1 - playsound(get_turf(master), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(master, 'sound/items/Deconstruct.ogg', 50, 1) add_gamelogs(user, "deconstructed \the [T] with \the [master]", admin = TRUE, tp_link = TRUE, tp_link_short = FALSE, span_class = "danger") T.ChangeTurf(T.get_underlying_turf()) return 0 @@ -42,7 +42,7 @@ if(master.get_energy(user) < energy_cost) return 1 - playsound(get_turf(master), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(master, 'sound/items/Deconstruct.ogg', 50, 1) qdel(D) return 0 @@ -64,7 +64,7 @@ var/turf/space/S = A to_chat(user, "Building floor...") - playsound(get_turf(master), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(master, 'sound/items/Deconstruct.ogg', 50, 1) S.ChangeTurf(/turf/simulated/floor/plating/airless) return 0 @@ -81,12 +81,12 @@ var/turf/simulated/floor/T = A to_chat(user, "Building wall") - playsound(get_turf(master), 'sound/machines/click.ogg', 50, 1) + playsound(master, 'sound/machines/click.ogg', 50, 1) if(master.delay(user, A, 2 SECONDS)) if(master.get_energy(user) < energy_cost) return 1 - playsound(get_turf(master), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(master, 'sound/items/Deconstruct.ogg', 50, 1) T.ChangeTurf(/turf/simulated/wall) return 0 @@ -350,7 +350,7 @@ for(var/obj/machinery/door/airlock/D in A) return "there is already an airlock on this spot!" - playsound(get_turf(master), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(master, 'sound/items/Deconstruct.ogg', 50, 1) var/obj/machinery/door/airlock/D = new selected.build_type(A) if(capitalize(selected_name) == selected_name) //The name inputted is capitalized, so we add \improper. diff --git a/code/modules/RCD/schematics/pipe.dm b/code/modules/RCD/schematics/pipe.dm index 78003bbf408..e06384c636f 100644 --- a/code/modules/RCD/schematics/pipe.dm +++ b/code/modules/RCD/schematics/pipe.dm @@ -22,14 +22,14 @@ return 1 to_chat(user, "Destroying Pipe...") - playsound(get_turf(master), 'sound/machines/click.ogg', 50, 1) + playsound(master, 'sound/machines/click.ogg', 50, 1) if(!master.delay(user, AM, 0.5 SECONDS)) return 1 if(!AM) return 1 - playsound(get_turf(master), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(master, 'sound/items/Deconstruct.ogg', 50, 1) if(istype(AM, /obj/item/pipe)) returnToPool(A) @@ -109,7 +109,7 @@ var/obj/machinery/atmospherics/O = A - playsound(get_turf(master), 'sound/machines/click.ogg', 50, 1) + playsound(master, 'sound/machines/click.ogg', 50, 1) if (selected_color in available_colors) selected_color = available_colors[selected_color] if(mass_colour && world.timeofday < last_colouration + colouring_delay) @@ -152,11 +152,11 @@ return to_chat(user, "Building gas sensor...") - playsound(get_turf(master), 'sound/machines/click.ogg', 50, 1) + playsound(master, 'sound/machines/click.ogg', 50, 1) if(!master.delay(user, A, 2 SECONDS)) return 1 - playsound(get_turf(master), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(master, 'sound/items/Deconstruct.ogg', 50, 1) new /obj/item/pipe_gsensor(A) /datum/rcd_schematic/pmeter @@ -169,11 +169,11 @@ return to_chat(user, "Building pipe meter...") - playsound(get_turf(master), 'sound/machines/click.ogg', 50, 1) + playsound(master, 'sound/machines/click.ogg', 50, 1) if(!master.delay(user, A, 2 SECONDS)) return 1 - playsound(get_turf(master), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(master, 'sound/items/Deconstruct.ogg', 50, 1) new /obj/item/pipe_meter(A) //ACTUAL PIPES. @@ -373,13 +373,13 @@ /datum/rcd_schematic/pipe/attack(var/atom/A, var/mob/user) to_chat(user, "Building Pipes ...") - playsound(get_turf(user), 'sound/machines/click.ogg', 50, 1) + playsound(user, 'sound/machines/click.ogg', 50, 1) var/thislayer = layer var/thisdir = selected_dir if(!master.delay(user, A, 2 SECONDS)) return 1 - playsound(get_turf(user), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(user, 'sound/items/Deconstruct.ogg', 50, 1) var/obj/item/pipe/P = getFromPool(/obj/item/pipe, A, pipe_id, thisdir) P.setPipingLayer(thislayer) @@ -418,14 +418,15 @@ /datum/rcd_schematic/pipe/disposal/attack(var/atom/A, var/mob/user) to_chat(user, "Building Pipes ...") - playsound(get_turf(user), 'sound/machines/click.ogg', 50, 1) + playsound(user, 'sound/machines/click.ogg', 50, 1) + var/thisdir = selected_dir if(!master.delay(user, A, 2 SECONDS)) return 1 - playsound(get_turf(user), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(user, 'sound/items/Deconstruct.ogg', 50, 1) var/obj/structure/disposalconstruct/C = new/obj/structure/disposalconstruct(A) - C.dir = selected_dir + C.dir = thisdir C.ptype = actual_id C.update() diff --git a/code/modules/RCD/schematics/service.dm b/code/modules/RCD/schematics/service.dm index 3f8e8e70b39..23dabb4d0d6 100644 --- a/code/modules/RCD/schematics/service.dm +++ b/code/modules/RCD/schematics/service.dm @@ -21,7 +21,7 @@ return 1 to_chat(user, "Dispensing [lowertext(name)]") - playsound(get_turf(user), 'sound/machines/click.ogg', 10, 1) + playsound(user, 'sound/machines/click.ogg', 10, 1) new spawn_type(get_turf(A)) /datum/rcd_schematic/rsf/dosh @@ -93,3 +93,15 @@ /datum/rcd_schematic/rsf/fork name = "Fork" spawn_type = /obj/item/weapon/kitchen/utensil/fork + +/datum/rcd_schematic/rsf/vodka + name = "Tunguska Triple Distilled" + spawn_type = /obj/item/weapon/reagent_containers/food/drinks/bottle/vodka + +/datum/rcd_schematic/rsf/greyshit_vodka + name = "Greyshit Vodka" + spawn_type = /obj/item/weapon/reagent_containers/food/drinks/bottle/greyvodka + +/datum/rcd_schematic/rsf/ushanka + name = "Ushanka" + spawn_type = /obj/item/clothing/head/ushanka \ No newline at end of file diff --git a/code/modules/RCD/schematics/tile.dm b/code/modules/RCD/schematics/tile.dm index 96010b5d237..6c320eaf9cb 100644 --- a/code/modules/RCD/schematics/tile.dm +++ b/code/modules/RCD/schematics/tile.dm @@ -17,7 +17,7 @@ /datum/rcd_schematic/clear_decals/attack(var/turf/A, var/mob/user) to_chat(user, "Clearing decals...") - playsound(get_turf(master), 'sound/effects/spray3.ogg', 15, 1) + playsound(master, 'sound/effects/spray3.ogg', 15, 1) A.ClearDecals() @@ -112,8 +112,8 @@ ndesc = sanitize(input(user, "What do you want to be described on this [nname]?", "[capitalize(nname)] description")) to_chat(user, "Painting floor...") - //playsound(get_turf(master), 'sound/AI/animes.ogg', 50, 1) - playsound(get_turf(master), 'sound/effects/spray3.ogg', 15, 1) + //playsound(master, 'sound/AI/animes.ogg', 50, 1) + playsound(master, 'sound/effects/spray3.ogg', 15, 1) selection.apply(A, nname, ndesc, thisdir) diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index 9f219995f2f..e36a7bdb2a2 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -687,7 +687,7 @@ var/global/floorIsLava = 0 Default Cyborg/AI Laws:[base_law_type]
  • - Default MoMMI Laws:[mommi_base_law_type] + Default MoMMI Laws:[mommi_laws["Default"]]

  • @@ -851,7 +851,7 @@ var/global/floorIsLava = 0 Summon Nar-Sie
    Start a Supermatter Cascade
    Trigger an undending Meteor Storm
    - Awaken the damned for some spooky shenanigans
    + Trigger the blood moon
    Make the station christmasy
    "} @@ -1116,6 +1116,9 @@ var/global/floorIsLava = 0 if(!check_rights(R_ADMIN)) return if (!ticker || ticker.current_state != GAME_STATE_PREGAME) + var/response = alert("Toggle round end delay? It is currently [ticker.delay_end?"delayed":"not delayed"]","Toggle round end delay","Yes","No") + if(response != "Yes") + return if(ticker.delay_end == 2) to_chat(world, "World Reboot triggered by [key_name(usr)]!") log_admin("World Reboot triggered by [key_name(usr)]!") diff --git a/code/modules/admin/admin_ranks.dm b/code/modules/admin/admin_ranks.dm index c1ed55afe73..16deda7e8cd 100644 --- a/code/modules/admin/admin_ranks.dm +++ b/code/modules/admin/admin_ranks.dm @@ -74,7 +74,7 @@ var/list/admin_ranks = list() //list of all ranks with associated rights var/msg = "Permission Sets Built:\n" for(var/rank in admin_ranks) msg += "\t[rank] - [admin_ranks[rank]]\n" - testing(msg) + //testing(msg) #endif @@ -174,7 +174,7 @@ var/list/admin_ranks = list() //list of all ranks with associated rights if(D) rank = D.rank msg += "\t[ckey] - [rank]\n" - testing(msg) + //testing(msg) #endif diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 7b850af1b66..827811631a1 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -37,6 +37,10 @@ log_admin("[key_name(usr)] has spawned a nuke team.") if(!src.makeNukeTeam()) to_chat(usr, "Unfortunately there weren't enough candidates available.") + if("8") + log_admin("[key_name(usr)] has spawned a count of vampires.") + if(!src.makeVampires()) + to_chat(usr, "Unfortunately there weren't enough candidates available.") if("9") log_admin("[key_name(usr)] has spawned aliens.") if(!src.makeAliens()) @@ -81,7 +85,7 @@ lawtype=lawtypes[lawtype] if(lawtype == null) return - testing("Lawtype: [lawtype]") + //testing("Lawtype: [lawtype]") if(lawtype==1) lawtype=text2num(input("Enter desired law priority. (15-50)","Priority", 15) as num) lawtype=Clamp(lawtype,15,50) @@ -100,7 +104,7 @@ var/lawtype = input("Select a lawset.","Law Type",1) as null|anything in lawtypes if(lawtype == null) return - testing("Lawtype: [lawtype]") + //testing("Lawtype: [lawtype]") var/law_zeroth=null var/law_zeroth_borg=null @@ -459,7 +463,9 @@ else if(href_list["delay_round_end"]) if(!check_rights(R_SERVER)) return - + var/response = alert("Toggle round end delay? It is currently [ticker.delay_end?"delayed":"not delayed"]","Toggle round end delay","Yes","No") + if(response != "Yes") + return ticker.delay_end = !ticker.delay_end log_admin("[key_name(usr)] [ticker.delay_end ? "delayed the round end" : "has made the round end normally"].") message_admins("[key_name(usr)] [ticker.delay_end ? "delayed the round end" : "has made the round end normally"].", 1) @@ -2336,7 +2342,7 @@ to_chat(H, "Your ass was just blown off by an unknown force!") log_admin("[key_name(H)] was buttblasted by [src.owner]") message_admins("[key_name(H)] was buttblasted by [src.owner]") - playsound(get_turf(H), 'sound/effects/superfart.ogg', 50, 1) + playsound(H, 'sound/effects/superfart.ogg', 50, 1) H.apply_damage(40, BRUTE, LIMB_GROIN) H.apply_damage(10, BURN, LIMB_GROIN) H.Knockdown(8) @@ -2530,7 +2536,7 @@ base_law_type = selected_law subject = "AIs and Cyborgs" if("mommi") - mommi_base_law_type = selected_law + mommi_laws["Default"] = selected_law subject = "MoMMIs" to_chat(usr, "New [subject] will spawn with the [selected_law] lawset.") log_admin("[key_name(src.owner)] set the default laws of [subject] to: [selected_law]") @@ -3319,8 +3325,12 @@ feedback_add_details("admin_secrets_fun_used","HW") var/choice = input("Are you sure you want to wake up the space indian burial ground?. Misuse of this could result in removal of flags or hilarity.") in list("Get our spook on", "Cancel") if(choice != "Cancel") - SetUniversalState(/datum/universal_state/halloween, 1, 1) - message_admins("[key_name_admin(usr)] has pressed the halloween fun button. Truly [key_name_admin(usr)] is the spookiest.") + var/list/given_args = list() + var/number = input("How many mobs do you want per area?", 10) as num + if(number) + given_args["mobs"] = number + SetUniversalState(/datum/universal_state/halloween, 1, 1, given_args) + message_admins("[key_name_admin(usr)] has pressed the halloween fun button with [number] amount of mobs per area. Truly [key_name_admin(usr)] is the spookiest.") if("christmas_vic") feedback_inc("admin_secrets_fun_used",1) feedback_add_details("admin_secrets_fun_used","XMS") @@ -3562,6 +3572,7 @@ "incinerator" = LOC_INCIN, "chapel" = LOC_CHAPEL, "library" = LOC_LIBRARY, + "hydroponics" = LOC_HYDRO, "vault" = LOC_VAULT, "technical storage" = LOC_TECH, ) @@ -3577,6 +3588,7 @@ "roaches" = VERM_ROACHES, "gremlins" = VERM_GREMLINS, "bees" = VERM_BEES, + "hornets" = VERM_HORNETS, ) var/ov = vermins[input("What vermin should infest the station?", "Vermin Infestation") in vermins] var/ol = locations[input("Where should they spawn?", "Vermin Infestation") in locations] @@ -4847,7 +4859,7 @@ (SM)
    " text += "Adepts:
      " for (var/datum/mind/M in R.adepts) - text += "
    • [M.name] (VV) (JMP) \ + text += "
    • [M.name] (VV) (JMP) \ (SM) (Deconvert)
    • " text +="
    " text += "Subtle PM all believers
    " diff --git a/code/modules/admin/verbs/SDQL_2/SDQL_2.dm b/code/modules/admin/verbs/SDQL_2/SDQL_2.dm index 0c26db31eb6..240ef1c1ca1 100644 --- a/code/modules/admin/verbs/SDQL_2/SDQL_2.dm +++ b/code/modules/admin/verbs/SDQL_2/SDQL_2.dm @@ -378,7 +378,7 @@ var/long = start < expression.len if (object == world && (!long || expression[start + 1] == ".") && !(expression[start] in exclude)) - v = readglobal(expression[start]) + v = global.vars[expression[start]] else if (expression [start] == "{" && long) if (lowertext(copytext(expression[start + 1], 1, 3)) != "0x") diff --git a/code/modules/admin/verbs/adminjump.dm b/code/modules/admin/verbs/adminjump.dm index 888780fcd59..fa7342e0946 100644 --- a/code/modules/admin/verbs/adminjump.dm +++ b/code/modules/admin/verbs/adminjump.dm @@ -20,7 +20,8 @@ if(!T) to_chat(src, "Nowhere to jump to!") return - usr.forceMove(T) + usr.unlock_from() + usr.teleport_to(T) log_admin("[key_name(usr)] jumped to [A]") message_admins("[key_name_admin(usr)] jumped to [A]", 1) @@ -37,7 +38,8 @@ if(config.allow_admin_jump) log_admin("[key_name(usr)] jumped to [T.x],[T.y],[T.z] in [T.loc]") message_admins("[key_name_admin(usr)] jumped to [T.x],[T.y],[T.z] in [T.loc]", 1) - usr.forceMove(T) + usr.unlock_from() + usr.teleport_to(T) feedback_add_details("admin_verb","JT") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! else alert("Admin jumping disabled") @@ -59,7 +61,8 @@ var/turf/T = get_turf(M) if(T && isturf(T)) feedback_add_details("admin_verb","JM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - A.forceMove(T) + A.unlock_from() + A.teleport_to(T) else to_chat(A, "This mob is not located in the game world.") else @@ -75,6 +78,7 @@ if (config.allow_admin_jump) if(src.mob) + src.mob.unlock_from() var/mob/A = src.mob A.x = tx A.y = ty @@ -105,7 +109,8 @@ var/mob/M = keys[selection] log_admin("[key_name(usr)] jumped to [key_name(M)]") message_admins("[key_name_admin(usr)] jumped to [key_name_admin(M)]", 1) - usr.forceMove(get_turf(M)) + usr.unlock_from() + usr.teleport_to(M) feedback_add_details("admin_verb","JK") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! else alert("Admin jumping disabled") @@ -134,7 +139,8 @@ to_chat(src, "[V.file_path || V.name] doesn't have a location! Report this") return - usr.forceMove(V.location) + usr.unlock_from() + usr.teleport_to(V.location) feedback_add_details("admin_verb","JV") else alert("Admin jumping disabled") @@ -149,6 +155,7 @@ if(config.allow_admin_jump) log_admin("[key_name(usr)] teleported [key_name(M)]") message_admins("[key_name_admin(usr)] teleported [key_name_admin(M)]", 1) + M.unlock_from() M.teleport_to(usr) feedback_add_details("admin_verb","GM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! else @@ -178,6 +185,7 @@ log_admin("[key_name(usr)] teleported [key_name(M)]") message_admins("[key_name_admin(usr)] teleported [key_name(M)]", 1) if(M) + M.unlock_from() M.teleport_to(usr) feedback_add_details("admin_verb","GK") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! else @@ -192,6 +200,7 @@ var/area/A = input(usr, "Pick an area.", "Pick an area") in sortedAreas if(A) if(config.allow_admin_jump) + M.unlock_from() M.teleport_to(pick(get_area_turfs(A))) feedback_add_details("admin_verb","SMOB") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index 049f5f9f4b2..77fadd50c51 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -827,7 +827,7 @@ var/global/blood_virus_spreading_disabled = 0 set desc = "Reload the Style Sheet (be careful)." for(var/client/C in clients) - winset(C, null, "outputwindow.output.style=[config.world_style_config];") + winset(C, null, "window1.msay_output.style=[config.world_style_config];") message_admins("The style sheet has been reloaded by [src.ckey]") /client/proc/reset_style_sheet() @@ -836,7 +836,7 @@ var/global/blood_virus_spreading_disabled = 0 set desc = "Reset the Style Sheet (restore to default)." for(var/client/C in clients) - winset(C, null, "outputwindow.output.style=[world_style];") + winset(C, null, "window1.msay_output.style=[world_style];") config.world_style_config = world_style message_admins("The style sheet has been reset by [src.ckey]") @@ -1347,4 +1347,4 @@ client/proc/check_convertables() if (!sort) return sort = sortlist[sort] - profile_show(src, sort) \ No newline at end of file + profile_show(src, sort) diff --git a/code/modules/admin/verbs/modifyvariables.dm b/code/modules/admin/verbs/modifyvariables.dm index c27ea545f3d..9b5a0f774b9 100644 --- a/code/modules/admin/verbs/modifyvariables.dm +++ b/code/modules/admin/verbs/modifyvariables.dm @@ -8,7 +8,9 @@ var/list/forbidden_varedit_object_types = list( //Interface for editing a variable. It returns its new value. If edited_datum, it automatically changes the edited datum's value //If called with just [user] argument, it allows you to create a value such as a string, a number, an empty list, a nearby object, etc... //If called with [edited_datum] and [edited_variable], you gain the ability to get the variable's initial value. -/proc/variable_set(mob/user, datum/edited_datum = null, edited_variable = null, autoselect_var_type = FALSE, value_override = null, logging = TRUE) + +// acceptsLists : if we're setting a variable in a list +/proc/variable_set(mob/user, datum/edited_datum = null, edited_variable = null, autoselect_var_type = FALSE, value_override = null, logging = TRUE, var/acceptsLists = TRUE) var/client/C if(ismob(user)) @@ -50,6 +52,7 @@ var/list/forbidden_varedit_object_types = list( #define V_TEXT "text" #define V_NUM "num" #define V_TYPE "type" + #define V_LIST_EMPTY "empty_list" #define V_LIST "list" #define V_OBJECT "object" #define V_ICON "icon" @@ -109,7 +112,8 @@ var/list/forbidden_varedit_object_types = list( "text" = V_TEXT, "num" = V_NUM, "type" = V_TYPE, - "empty list" = V_LIST, + "empty list" = V_LIST_EMPTY, + "list" = V_LIST, "object (nearby)" = V_OBJECT, "icon" = V_ICON, "file" = V_FILE, @@ -118,6 +122,10 @@ var/list/forbidden_varedit_object_types = list( "null" = V_NULL, ) + if (!acceptsLists) + choices -= V_LIST + choices -= V_LIST_EMPTY + if(C.holder.marked_datum) //Add the marked datum option var/list_item_name if(isdatum(C.holder.marked_datum)) @@ -137,7 +145,7 @@ var/list/forbidden_varedit_object_types = list( choices["CANCEL"] = V_CANCEL if(!new_variable_type) - new_variable_type = input("What kind of variable?","Variable Type") in choices + new_variable_type = input("What kind of variable?","Variable Type") as null|anything in choices var/selected_type = choices[new_variable_type] var/window_title = "Varedit [edited_datum]" @@ -157,8 +165,13 @@ var/list/forbidden_varedit_object_types = list( var/list/matches = get_matching_types(partial_type, /datum) new_value = input("Select type", window_title) as null|anything in matches + if(V_LIST_EMPTY) + if (acceptsLists) + new_value = list() + if(V_LIST) - new_value = list() + if (acceptsLists) + new_value = C.populate_list() if(V_OBJECT) new_value = input("Select reference:", window_title, old_value) as mob|obj|turf|area in range(8, get_turf(user)) @@ -219,6 +232,7 @@ var/list/forbidden_varedit_object_types = list( #undef V_TEXT #undef V_NUM #undef V_TYPE + #undef V_LIST_EMPTY #undef V_LIST #undef V_OBJECT #undef V_ICON @@ -226,6 +240,15 @@ var/list/forbidden_varedit_object_types = list( #undef V_CLIENT #undef V_NULL +/client/proc/populate_list() + var/to_continue = TRUE + var/list/things_to_return = list() + while (to_continue) + things_to_return += variable_set(src, acceptsLists = FALSE) + to_continue = (alert("Do you want to add another item to the list? It has currently [things_to_return.len] items.", "Filling a list", "Yes", "No") == "Yes") + + return things_to_return + /client/proc/cmd_modify_ticker_variables() set category = "Debug" set name = "Edit Ticker Variables" diff --git a/code/modules/admin/verbs/one_click_antag.dm b/code/modules/admin/verbs/one_click_antag.dm index 32ec3671c81..a5b3ad9ddb0 100644 --- a/code/modules/admin/verbs/one_click_antag.dm +++ b/code/modules/admin/verbs/one_click_antag.dm @@ -16,6 +16,7 @@ client/proc/one_click_antag() Make Revs
    Make Cult
    Make Malf AI
    + Make Vampires
    Make Wizard (Requires Ghosts)
    Make Vox Raiders (Requires Ghosts)
    Make Nuke Team (Requires Ghosts)
    @@ -112,12 +113,13 @@ client/proc/one_click_antag() candidates += applicant if(candidates.len) - var/numChanglings = min(candidates.len, 3) + var/numChanglings = min(candidates.len, input("Create how many changelings?", "Make Changelings", 3) as num|null) for(var/i = 0, iYou begin to weld \the [src] to the floor...") if (do_after(user, src, 40)) var/obj/machinery/igniter/igniter=new(src.loc) diff --git a/code/modules/assembly/signaler.dm b/code/modules/assembly/signaler.dm index ccb997b81cc..ad79d39ace4 100644 --- a/code/modules/assembly/signaler.dm +++ b/code/modules/assembly/signaler.dm @@ -270,7 +270,7 @@ return if(iscrowbar(W)) to_chat(user, "You begin prying \the [src] off the wall.") - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) if(do_after(user, src,10)) to_chat(user, "You pry the button off of the wall.") var/obj/item/mounted/frame/driver_button/signaler_button/I = new (get_turf(user)) @@ -284,6 +284,6 @@ /obj/item/device/assembly/signaler/set_value(var/var_name, var/new_value) if(var_name == "frequency") - new_value = sanitize_frequency(new_value) - - return ..(var_name, new_value) + set_frequency(sanitize_frequency(new_value)) + else + return ..() diff --git a/code/modules/assembly/voice.dm b/code/modules/assembly/voice.dm index f62c3a6357f..6766b0285d2 100644 --- a/code/modules/assembly/voice.dm +++ b/code/modules/assembly/voice.dm @@ -35,7 +35,7 @@ if(istype(L) && L.stuttering) return if(istype(speech.speaker, /obj/item/device/assembly) || istype(speech.speaker, /obj/item/device/assembly_frame)) - playsound(get_turf(src), 'sound/machines/buzz-sigh.ogg', 25, 1) + playsound(src, 'sound/machines/buzz-sigh.ogg', 25, 1) else pulse(0) var/mob/living/speaker = speech.speaker diff --git a/code/modules/atmos_automation/console.dm b/code/modules/atmos_automation/console.dm index 59ae05a0867..071490fafa8 100644 --- a/code/modules/atmos_automation/console.dm +++ b/code/modules/atmos_automation/console.dm @@ -81,7 +81,7 @@ continue choices[A.name]=A if (choices.len==0) - testing("Unable to find automations with returntype in [english_list(valid_returntypes)]!") + //testing("Unable to find automations with returntype in [english_list(valid_returntypes)]!") return 0 var/label=input(user, "Select new automation:", "Automations", "Cancel") as null|anything in choices if(!label) @@ -328,11 +328,11 @@ if(json && json.len > 0) for(var/list/cData in json) if(isnull(cData) || !("type" in cData)) - testing("AAC: Null cData in root JS array.") + //testing("AAC: Null cData in root JS array.") continue var/Atype=text2path(cData["type"]) if(!(Atype in automation_types)) - testing("AAC: Unrecognized Atype [Atype].") + //testing("AAC: Unrecognized Atype [Atype].") continue var/datum/automation/A = new Atype(src) A.Import(cData) diff --git a/code/modules/atmos_automation/statements.dm b/code/modules/atmos_automation/statements.dm index fd66257a4a2..1b9f486fb4f 100644 --- a/code/modules/atmos_automation/statements.dm +++ b/code/modules/atmos_automation/statements.dm @@ -408,7 +408,7 @@ var/global/automation_types=typesof(/datum/automation) - /datum/automation if(href_list["set_condition"]) var/new_condition = selectValidChildFor(usr, valid_conditions) - testing("Selected condition: [new_condition]") + //testing("Selected condition: [new_condition]") if(!new_condition) return 1 diff --git a/code/modules/awaymissions/maploader/reader.dm b/code/modules/awaymissions/maploader/reader.dm index addab9480d8..bcd882b6d15 100644 --- a/code/modules/awaymissions/maploader/reader.dm +++ b/code/modules/awaymissions/maploader/reader.dm @@ -152,7 +152,10 @@ var/list/map_dimension_cache = list() if(map_element) map_element.height = y_depth - map_element.location = locate(x_offset + 1, y_offset + 1, z_offset) //Set location to the upper left corner + + if(!map_element.location) + //Set location to the lower left corner, if it hasn't already been set + map_element.location = locate(x_offset + 1, y_offset + 1, z_offset) //reached End Of File if(findtext(tfile,quote+"}",zpos,0)+2==tfile_len) diff --git a/code/modules/bomberman/bomberman.dm b/code/modules/bomberman/bomberman.dm index 47334f9ab0b..bc5996197df 100644 --- a/code/modules/bomberman/bomberman.dm +++ b/code/modules/bomberman/bomberman.dm @@ -551,7 +551,7 @@ obj/structure/bomberflame/Destroy() ..() /obj/structure/powerup/proc/apply_power(var/obj/item/weapon/bomberman/dispenser) - playsound(get_turf(src), 'sound/bomberman/powerup.ogg', 50, 1) + playsound(src, 'sound/bomberman/powerup.ogg', 50, 1) qdel(src) return @@ -594,7 +594,7 @@ obj/structure/bomberflame/Destroy() return /obj/structure/powerup/skull/apply_power(var/obj/item/weapon/bomberman/dispenser) - playsound(get_turf(src), 'sound/bomberman/disease.ogg', 50, 1) + playsound(src, 'sound/bomberman/disease.ogg', 50, 1) var/list/diseases = list( "Low Power Disease", "Constipation ", @@ -955,11 +955,6 @@ var/global/list/arena_spawnpoints = list()//used by /mob/dead/observer/Logout() spawn(0) A.contents.Add(turfs) - for(var/turf/F in turfs) - for(var/atom/movable/AM in F) - AM.areaMaster = get_area_master(F) - - message_admins("[key_name_admin(user.client)] created a \"[size]\" Bomberman arena at [center.loc.name] ([center.x],[center.y],[center.z]) (JMP)") log_game("[key_name_admin(user.client)] created a \"[size]\" Bomberman arena at [center.loc.name] ([center.x],[center.y],[center.z]) ") @@ -1251,8 +1246,6 @@ var/global/list/arena_spawnpoints = list()//used by /mob/dead/observer/Logout() under.contents.Add(turfs) for(var/turf/T in turfs) - for(var/atom/movable/AM in T) - AM.areaMaster = get_area_master(T) if(open_space && (under.name == "Space")) T.ChangeTurf(T.get_underlying_turf()) else diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index 658abc49038..4ef22fa23dc 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -127,8 +127,7 @@ chatOutput = new /datum/chatOutput(src) // Right off the bat. // world.log << "Done creating chatOutput" if(config) - winset(src, null, "outputwindow.output.style=[config.world_style_config];") - winset(src, null, "window1.msay_output.style=[config.world_style_config];") // it isn't possible to set two window elements in the same winset so we need to call it for each element we're assigning a stylesheet. + winset(src, null, "window1.msay_output.style=[config.world_style_config];") else to_chat(src, "The stylesheet wasn't properly setup call an administrator to reload the stylesheet or relog.") @@ -504,4 +503,4 @@ NOTE: You will only be polled about this role once per round. To change your ch for(Image in ViewFilter-newimages) images -= Image - ViewFilter = newimages \ No newline at end of file + ViewFilter = newimages diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 49630ff7a16..f4e6634b9d7 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -202,12 +202,12 @@ var/const/MAX_SAVE_SLOTS = 8 if(!IsGuestKey(thekey)) var/load_pref = load_preferences_sqlite(theckey) if(load_pref) - while(!speciesinit) + while(!SS_READY(SShumans)) sleep(1) try_load_save_sqlite(theckey, C, default_slot) return - while(!speciesinit) + while(!SS_READY(SShumans)) sleep(1) randomize_appearance_for() real_name = random_name(gender, species) @@ -251,13 +251,15 @@ var/const/MAX_SAVE_SLOTS = 8 Species: [species]
    Secondary Language: [language]
    Skin Tone: [species == "Human" ? "[-s_tone + 35]/220" : "[s_tone]"]

    - Handicaps: Set
    + Handicaps: Set
    Limbs: Set
    Organs: Set
    - Underwear: [gender == MALE ? "[underwear_m[underwear]]" : "[underwear_f[underwear]]"]
    - Backpack: [backbaglist[backbag]]
    - Nanotrasen Relation:
    [nanotrasen_relation]
    + Underwear: [gender == MALE ? "[underwear_m[underwear]]" : "[underwear_f[underwear]]"]
    + Backpack: [backbaglist[backbag]]
    + Nanotrasen Relation:
    [nanotrasen_relation]
    Flavor Text:Set
    + Character records: + [jobban_isbanned(user, "Records") ? "Banned" : "Set"]

    Hair Style

    [h_style]
    @@ -355,8 +357,6 @@ var/const/MAX_SAVE_SLOTS = 8 [(tooltips) ? "Yes" : "No"]
    Adminhelp Special Tab: [special_popup ? "Yes" : "No"]
    - Character Records: - [jobban_isbanned(user, "Records") ? "Banned" : "Set
    "] Attack Animations: [attack_animation ? (attack_animation == ITEM_ANIMATION? "Item Anim." : "Person Anim.") : "No"]
    @@ -637,6 +637,8 @@ var/const/MAX_SAVE_SLOTS = 8 HTML += ShowDisabilityState(user,DISABILITY_FLAG_BLIND, "Blind") HTML += ShowDisabilityState(user,DISABILITY_FLAG_MUTE, "Mute") HTML += ShowDisabilityState(user,DISABILITY_FLAG_VEGAN, "Vegan") + HTML += ShowDisabilityState(user,DISABILITY_FLAG_ASTHMA, "Asthma") + HTML += ShowDisabilityState(user,DISABILITY_FLAG_LACTOSE, "Lactose Intolerant") /*HTML += ShowDisabilityState(user,DISABILITY_FLAG_COUGHING, "Coughing") HTML += ShowDisabilityState(user,DISABILITY_FLAG_TOURETTES, "Tourettes") Still working on it! -Angelite*/ @@ -1146,24 +1148,12 @@ NOTE: The change will take effect AFTER any current recruiting periods."} SetDepartmentFlags(job, i, F) if("language") - var/languages_available var/list/new_languages = list("None") - if(config.usealienwhitelist) - for(var/L in all_languages) - var/datum/language/lang = all_languages[L] - if((!(lang.flags & RESTRICTED)) && (is_alien_whitelisted(user, L)||(!( lang.flags & WHITELISTED )))) - new_languages += lang.name - - languages_available = 1 - - if(!(languages_available)) - alert(user, "There are not currently any available secondary languages.") - else - for(var/L in all_languages) - var/datum/language/lang = all_languages[L] - if(!(lang.flags & RESTRICTED)) - new_languages += lang.name + for(var/L in all_languages) + var/datum/language/lang = all_languages[L] + if(lang.flags & CAN_BE_SECONDARY_LANGUAGE) + new_languages += lang.name language = input("Please select a secondary language", "Character Generation", null) in new_languages diff --git a/code/modules/clothing/accessories/armor_shards.dm b/code/modules/clothing/accessories/armor_shards.dm new file mode 100644 index 00000000000..9bf5a75f2ad --- /dev/null +++ b/code/modules/clothing/accessories/armor_shards.dm @@ -0,0 +1,27 @@ +//Hockey pads, neck guards, particularly well-stained handkerchiefs go here +/obj/item/clothing/accessory/armor_shard + armor = list(melee = 5, bullet = 5, laser = 5, energy = 0, bomb = 0, bio = 0, rad = 0) + +/obj/item/clothing/accessory/armor_shard/can_attach_to(obj/item/clothing/C) + . = ..() + for(var/obj/item/clothing/accessory in C.accessories) + if(accessory.type == type) + return 0 + +/obj/item/clothing/accessory/armor_shard/shoulder + name = "shoulder pads" + desc = "Has clips to attach to a jumpsuit. Makes you feel like you're playing a fantasy MMO." + icon_state = "shoulder_guard" + body_parts_covered = ARMS + +/obj/item/clothing/accessory/armor_shard/knee + name = "knee pads" + desc = "Has clips to attach to a jumpsuit. Now you can safely play hockey." + icon_state = "knee_guard" + body_parts_covered = LEGS + +/obj/item/clothing/accessory/armor_shard/neck + name = "neck guard" + desc = "Has clips to attach to a jumpsuit. For when you want to protect your pretty face." + icon_state = "neck_guard" + body_parts_covered = FACE \ No newline at end of file diff --git a/code/modules/clothing/accessories/holomap.dm b/code/modules/clothing/accessories/holomap.dm index 38ebc66612f..0d3c449f331 100644 --- a/code/modules/clothing/accessories/holomap.dm +++ b/code/modules/clothing/accessories/holomap.dm @@ -117,7 +117,8 @@ var/list/holomap_cache = list() if(istype(A, /datum/action/item_action/toggle_minimap)) qdel(A) ..() - user.update_action_buttons() + if(user) + user.update_action_buttons_icon() /obj/item/clothing/accessory/holomap_chip/proc/togglemap() if(usr.isUnconscious()) diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index 1795f9c6fbb..fcf6fa5ffa4 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -241,6 +241,12 @@ visible_message("\The [user] puts out the fire on \the [target].") return +/obj/item/clothing/proc/get_armor(var/type) + return armor[type] + +/obj/item/clothing/proc/get_armor_absorb(var/type) + return armor_absorb[type] + //Ears: headsets, earmuffs and tiny objects /obj/item/clothing/ears name = "ears" @@ -423,6 +429,7 @@ BLIND // can't see anything body_parts_covered &= ~(MOUTH|HEAD|BEARD|FACE) usr.update_inv_wear_mask() usr.update_hair() + usr.update_inv_glasses() /obj/item/clothing/mask/New() if(!can_flip /*&& !istype(/obj/item/clothing/mask/gas/voice)*/) //the voice changer has can_flip = 1 anyways but it's worth noting that it exists if anybody changes this in the future diff --git a/code/modules/clothing/glasses/glasses.dm b/code/modules/clothing/glasses/glasses.dm index c26658e0a51..28b8a2f99c4 100644 --- a/code/modules/clothing/glasses/glasses.dm +++ b/code/modules/clothing/glasses/glasses.dm @@ -50,7 +50,7 @@ /obj/item/clothing/glasses/regular/kick_act(mob/living/carbon/human/H) H.visible_message("[H] stomps on \the [src], crushing them!", "You crush \the [src] under your foot.") - playsound(get_turf(src), "shatter", 50, 1) + playsound(src, "shatter", 50, 1) var/obj/item/weapon/shard/S = new(get_turf(src)) S.Crossed() @@ -93,7 +93,7 @@ /obj/item/clothing/glasses/sunglasses/kick_act(mob/living/carbon/human/H) H.visible_message("[H] stomps on \the [src], crushing them!", "You crush \the [src] under your foot.") - playsound(get_turf(src), "shatter", 50, 1) + playsound(src, "shatter", 50, 1) var/obj/item/weapon/shard/S = new(get_turf(src)) S.Crossed() @@ -103,7 +103,7 @@ /obj/item/clothing/glasses/sunglasses/holo/kick_act(mob/living/carbon/human/H) H.visible_message("[H] stomps on \the [src], crushing them and making them fade away!", "You crush \the [src] under your foot, which takes less effort than you realized as they fade from existence.") - playsound(get_turf(src), "shatter", 50, 1) + playsound(src, "shatter", 50, 1) qdel(src) return SPECIAL_ATTACK_FAILED @@ -123,6 +123,17 @@ desc = "Novelty sunglasses with a fancy silver frame and two red-tinted star-shaped lenses. You should probably stomp on them and get a pair of normal ones." icon_state = "sun_star_silver" +/obj/item/clothing/glasses/sunglasses/red + name = "red sunglasses" + desc = "Strangely ancient technology used to help provide rudimentary eye cover. Enhanced shielding blocks many flashes, and the colored lenses let you see the world in red." + icon_state = "sunred" + item_state = "sunred" + +/obj/item/clothing/glasses/sunglasses/security + name = "security sunglasses" + desc = "Strangely ancient technology used to help provide rudimentary eye cover. Enhanced shielding blocks many flashes. Often worn by budget security officers." + icon_state = "sunhud" + /obj/item/clothing/glasses/virussunglasses desc = "Strangely ancient technology used to help provide rudimentary eye cover. Enhanced shielding blocks many flashes." name = "sunglasses" @@ -216,12 +227,12 @@ ..() if(prob(15)) new /obj/item/weapon/shard(loc) - playsound(get_turf(src), "shatter", 50, 1) + playsound(src, "shatter", 50, 1) qdel(src) return if(prob(15)) new/obj/item/clothing/glasses/sunglasses(get_turf(src)) - playsound(get_turf(src), 'sound/effects/glass_step.ogg', 50, 1) + playsound(src, 'sound/effects/glass_step.ogg', 50, 1) qdel(src) return if(prob(55)) @@ -230,6 +241,59 @@ hud = null qdel(hud) +/obj/item/clothing/glasses/sunglasses/sechud/syndishades + desc = "Strangely ancient technology used to help provide rudimentary eye cover. Enhanced shielding blocks many flashes." + name = "sunglasses" + icon_state = "sun" + item_state = "sunglasses" + darkness_view = 0 //Subtly better than normal shades + origin_tech = Tc_SYNDICATE + "=3" + actions_types = list(/datum/action/item_action/change_appearance_shades) + var/static/list/clothing_choices = null + var/full_access = FALSE + +/obj/item/clothing/glasses/sunglasses/sechud/syndishades/New() + ..() + if(!clothing_choices) + clothing_choices = list() + for(var/Type in existing_typesof(/obj/item/clothing/glasses) - /obj/item/clothing/glasses - typesof(/obj/item/clothing/glasses/sunglasses/sechud/syndishades)) + var/obj/glass = Type + clothing_choices[initial(glass.name)] = glass + +/obj/item/clothing/glasses/sunglasses/sechud/syndishades/attackby(obj/item/I, mob/user) + ..() + if(istype(I, /obj/item/clothing/glasses/sunglasses/sechud) || istype(I, /obj/item/clothing/glasses/hud/security)) + var/obj/item/clothing/glasses/sunglasses/sechud/syndishades/S = I + if(istype(S) && !S.full_access) + return + if(full_access) + to_chat(user, "\The [src] already has those access codes.") + return + else + to_chat(user, "You transfer the security access codes from \the [I] to \the [src].") + full_access = TRUE + +/datum/action/item_action/change_appearance_shades + name = "Change Shades Appearance" + +/datum/action/item_action/change_appearance_shades/Trigger() + var/obj/item/clothing/glasses/sunglasses/sechud/syndishades/T = target + if(!istype(T)) + return + T.change() + +/obj/item/clothing/glasses/sunglasses/sechud/syndishades/proc/change() + var/obj/item/clothing/glasses/A + A = input("Select style to change it to", "Style Selector", A) as null|anything in clothing_choices + if(src.gcDestroyed || !A || usr.incapacitated() || !Adjacent(usr)) + return + desc = initial(clothing_choices[A].desc) + name = initial(clothing_choices[A].name) + icon_state = initial(clothing_choices[A].icon_state) + item_state = initial(clothing_choices[A].item_state) + _color = initial(clothing_choices[A]._color) + usr.update_inv_glasses() + /obj/item/clothing/glasses/thermal name = "Optical Thermal Scanner" desc = "Thermals in the shape of glasses." @@ -314,3 +378,19 @@ icon_state = "kaminaglasses" item_state = "kaminaglasses" cover_hair = 1 + +/obj/item/clothing/glasses/contacts + name = "contact lenses" + desc = "Only nerds wear glasses." + icon = 'icons/obj/items.dmi' + icon_state = "contact" + prescription = 1 + body_parts_covered = null + +/obj/item/clothing/glasses/contacts/polarized + name = "polarized contact lenses" + desc = "Protects your eyes from bright flashes of light." + icon_state = "polarized_contact" + darkness_view = -1 + prescription = 1 + eyeprot = 1 diff --git a/code/modules/clothing/glasses/scanners.dm b/code/modules/clothing/glasses/scanners.dm index 9ad494afcf4..19151b836d8 100644 --- a/code/modules/clothing/glasses/scanners.dm +++ b/code/modules/clothing/glasses/scanners.dm @@ -33,14 +33,14 @@ if(iscarbon(M)) apply_color(M) ..() - + /obj/item/clothing/glasses/scanner/unequipped(mob/user, var/from_slot = null) if(from_slot == slot_glasses) if(on) if(iscarbon(user)) remove_color(user) ..() - + /obj/item/clothing/glasses/scanner/update_icon() icon_state = initial(icon_state) @@ -103,11 +103,7 @@ actions_types = list(/datum/action/item_action/toggle_goggles) species_fit = list(VOX_SHAPED, GREY_SHAPED) eyeprot = -1 - color_matrix = list(0.33,0.33,0.33,0, - 0.33,0.33,0.33,0, - 0.33,0.33,0.33,0, - 0,0,0,1, - -0.2,0,-0.2,0) + color_matrix = "#CCFFCC" /obj/item/clothing/glasses/scanner/night/enable(var/mob/C) see_invisible = initial(see_invisible) @@ -133,6 +129,10 @@ species_fit = list(GREY_SHAPED) /obj/item/clothing/glasses/scanner/meson/enable(var/mob/C) + var/area/A = get_area(src) + if(A.flags & NO_MESONS) + to_chat(C, "\The [src] flickers, but refuses to come online!") + return eyeprot = initial(eyeprot) vision_flags |= SEE_TURFS see_invisible |= SEE_INVISIBLE_MINIMUM @@ -146,6 +146,11 @@ see_invisible &= ~SEE_INVISIBLE_MINIMUM ..() +/obj/item/clothing/glasses/scanner/meson/area_entered(area/A) + if(A.flags & NO_MESONS && on) + visible_message("\The [src] sputter out.") + disable() + /obj/item/clothing/glasses/scanner/material name = "optical material scanner" desc = "Allows one to see the original layout of the pipe and cable network." diff --git a/code/modules/clothing/gloves/color.dm b/code/modules/clothing/gloves/color.dm index a38feb55191..589ebbf8b56 100644 --- a/code/modules/clothing/gloves/color.dm +++ b/code/modules/clothing/gloves/color.dm @@ -43,7 +43,7 @@ if(L.damage <= 0) returnToPool(L) else - playsound(get_turf(src), 'sound/effects/eleczap.ogg', 75, 1) + playsound(src, 'sound/effects/eleczap.ogg', 75, 1) L.tang = adjustAngle(get_angle(U,T)) L.icon = midicon L.icon_state = "[L.tang]" @@ -184,7 +184,7 @@ if(!M.get_active_hand()) var/obj/item/weapon/gun/projectile/handgun/G = new current_gun = G - if(!M.miming) //nonmimes get a loud version + if(!issilent(M)) //nonmimes get a loud version G.silenced = FALSE G.fire_sound = 'sound/weapons/Gunshot.ogg' M.put_in_active_hand(G) diff --git a/code/modules/clothing/gloves/miscellaneous.dm b/code/modules/clothing/gloves/miscellaneous.dm index 7630d781235..b418722a4bd 100644 --- a/code/modules/clothing/gloves/miscellaneous.dm +++ b/code/modules/clothing/gloves/miscellaneous.dm @@ -154,6 +154,7 @@ desc = "Utilizes a non-slip technology that allows you to never drop your precious bottles of vodka." icon_state = "nr_gloves" item_state = "nr_gloves" + heat_conductivity = INS_GLOVES_HEAT_CONDUCTIVITY /obj/item/clothing/gloves/neorussian/fingerless name = "neo-Russian fingerless gloves" @@ -257,7 +258,7 @@ /obj/item/clothing/gloves/powerfist/on_punch(mob/user, mob/living/victim) if(istype(victim) && use_fuel(fuel_cost)) to_chat(user, "As \the [src] activate, you feel a truly powerful force assisting your punch.") - playsound(get_turf(src), 'sound/mecha/mechentry.ogg', 100, 1) + playsound(src, 'sound/mecha/mechentry.ogg', 100, 1) victim.throw_at(get_edge_target_turf(loc, loc.dir), 5, 1) victim.Stun(stunforce) diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm index 00acd44871e..32cb5c08375 100644 --- a/code/modules/clothing/head/helmet.dm +++ b/code/modules/clothing/head/helmet.dm @@ -10,6 +10,48 @@ siemens_coefficient = 0.7 species_fit = list(GREY_SHAPED) +/obj/item/clothing/head/helmet/visor + name = "visor helmet" + desc = "For when you need to protect your face from the backblast of your pepperspray" + icon_state = "riot_helm" + item_state = "riot_helm" + armor = list(melee = 50, bullet = 25, laser = 45, energy = 15, bomb = 30, bio = 0, rad = 0) + actions_types = list(/datum/action/item_action/toggle_helmet) + body_parts_covered = FULL_HEAD + var/state = 1 + +/obj/item/clothing/head/helmet/visor/New() + ..() + update_icon() + +/obj/item/clothing/head/helmet/visor/attack_self(mob/user) + state = !state + to_chat(user, "You flick \the [src] [state ? "down" : "up"].") + switch(state) + if(1) //FACE COVERED + body_parts_covered = FULL_HEAD + if(0) //VISOR UP + body_parts_covered = HEAD|EARS + update_icon(user) + +/obj/item/clothing/head/helmet/visor/update_icon(mob/user) + switch(state) + if(1) //FACE COVERED + armor = initial(armor) + icon_state = "[initial(icon_state)]_down" + item_state = "[initial(item_state)]_down" + if(0) + armor = list(melee = 50, bullet = 10, laser = 50, energy = 10, bomb = 25, bio = 0, rad = 0) + icon_state = "[initial(icon_state)]_up" + item_state = "[initial(item_state)]_down" + if(user) + user.update_inv_head() + user.update_inv_wear_mask() + user.update_inv_glasses() + user.update_hair() + user.update_inv_ears() + + /obj/item/clothing/head/helmet/siren name = "siren helmet" desc = "For the officer that's off patrolling all the nation." @@ -24,7 +66,7 @@ /obj/item/clothing/head/helmet/siren/attack_self(mob/user) if(spamcheck) return - playsound(get_turf(src), 'sound/voice/woopwoop.ogg', 100, 1, vary = 0) + playsound(src, 'sound/voice/woopwoop.ogg', 100, 1, vary = 0) user.visible_message("[user]'s [name] rasps, \"WOOP WOOP!\"", \ "Your [name] rasps, \"WOOP WOOP!\"", \ "You hear a siren: \"WOOP WOOP!\"") @@ -71,6 +113,7 @@ armor = list(melee = 20, bullet = 0, laser = 20, energy = 10, bomb = 10, bio = 0, rad = 0) icon_state = "roman" item_state = "roman" + body_parts_covered = HEAD|EARS /obj/item/clothing/head/helmet/roman/legionaire name = "roman legionaire helmet" @@ -78,6 +121,7 @@ armor = list(melee = 25, bullet = 0, laser = 25, energy = 10, bomb = 10, bio = 0, rad = 0) icon_state = "roman_c" item_state = "roman_c" + body_parts_covered = HEAD|EARS /obj/item/clothing/head/helmet/hopcap name = "Head of Personnel's Cap" @@ -106,7 +150,7 @@ desc = "This helmet should protect you from russians and masked vigilantes." armor = list(melee = 25, bullet = 15, laser = 20, energy = 10, bomb = 10, bio = 0, rad = 0) icon_state = "biker_helmet" - body_parts_covered = FULL_HEAD + body_parts_covered = FULL_HEAD|BEARD /obj/item/clothing/head/helmet/richard name = "Richard" @@ -120,6 +164,7 @@ desc = "The helmet of the DRN-001 model. A simple, sturdy blue helmet." icon_state = "megahelmet" flags = FPRINT + body_parts_covered = HEAD|EARS item_state = "megahelmet" siemens_coefficient = 1 @@ -145,6 +190,7 @@ desc = "Heavily armored upgrade to the DRN-001 model's helmet, now comes with a pointless red crystal thing!" icon_state = "megaxhelmet" flags = FPRINT + body_parts_covered = HEAD|EARS item_state = "megaxhelmet" siemens_coefficient = 1 @@ -153,6 +199,7 @@ desc = "A sturdy helmet, fortified to protect from falling rocks or buster shots." icon_state = "volnutthelmet" flags = FPRINT + body_parts_covered = HEAD|EARS item_state = "volnutthelmet" armor = list(melee = 50, bullet = 40, laser = 40,energy = 40, bomb = 5, bio = 0, rad = 0) siemens_coefficient = 1 @@ -172,6 +219,7 @@ icon_state = "doom" flags = FPRINT item_state = "doom" + body_parts_covered = FULL_HEAD|BEARD armor = list(melee = 50, bullet = 40, laser = 40,energy = 40, bomb = 5, bio = 0, rad = 0) siemens_coefficient = 1 @@ -209,6 +257,7 @@ icon_state = "nr_helmet" item_state = "nr_helmet" body_parts_covered = EARS|HEAD + heat_conductivity = INS_HELMET_HEAT_CONDUCTIVITY /obj/item/clothing/head/helmet/police name = "police custodian helmet" diff --git a/code/modules/clothing/head/leather.dm b/code/modules/clothing/head/leather.dm index 4e3692a7b8f..ae8fb1b950d 100644 --- a/code/modules/clothing/head/leather.dm +++ b/code/modules/clothing/head/leather.dm @@ -21,11 +21,10 @@ new/obj/item/clothing/head/leather/corgi(get_turf(src)) user.drop_item(src, force_drop = 1) qdel(src) - /* DEERS TO BE IMPLEMENTED if(istype (S, /obj/item/stack/sheet/animalhide/deer)) new/obj/item/clothing/head/leather/deer(get_turf(src)) user.drop_item(src, force_drop = 1) - qdel(src)*/ + qdel(src) if(istype (S, /obj/item/stack/sheet/animalhide/xeno)) new/obj/item/clothing/head/leather/xeno(get_turf(src)) user.drop_item(src, force_drop = 1) @@ -37,7 +36,6 @@ icon_state = "helmet_leather_corgi" item_state = "helmet_leather_corgi" -/* DEERS TO BE IMPLEMENTED /obj/item/clothing/head/leather/deer name = "deer pelt head cover" desc = "Made to help you blend in and stalk deer. Sadly lacking the horns." @@ -52,7 +50,7 @@ user.drop_item(W, force_drop = 1) user.drop_item(src, force_drop = 1) qdel(W) - qdel(src)*/ + qdel(src) /obj/item/clothing/head/leather/deer/horned name = "horned deer pelt head cover" diff --git a/code/modules/clothing/head/misc.dm b/code/modules/clothing/head/misc.dm index 81c06e45f09..8942b5821c4 100644 --- a/code/modules/clothing/head/misc.dm +++ b/code/modules/clothing/head/misc.dm @@ -460,4 +460,10 @@ wizard_garb = 1 //being elf cursed wont prevent you casting robed spells if wizard /obj/item/clothing/head/elfhat/stickymagic - canremove = 0 \ No newline at end of file + canremove = 0 + +/obj/item/clothing/head/rice_hat + name = "rice hat" + desc = "Welcome to the rice fields, motherfucker." + icon_state = "rice_hat" + item_state = "rice_hat" \ No newline at end of file diff --git a/code/modules/clothing/head/misc_special.dm b/code/modules/clothing/head/misc_special.dm index 38526db8ff7..a4b08396344 100644 --- a/code/modules/clothing/head/misc_special.dm +++ b/code/modules/clothing/head/misc_special.dm @@ -112,22 +112,29 @@ /obj/item/clothing/head/ushanka name = "ushanka" desc = "Perfect for winter in Siberia, da?" - icon_state = "ushankadown" - item_state = "ushankadown" + icon_state = "ushanka" + item_state = "ushanka" body_parts_covered = EARS|HEAD + heat_conductivity = SNOWGEAR_HEAT_CONDUCTIVITY /obj/item/clothing/head/ushanka/attack_self(mob/user as mob) - if(src.icon_state == "ushankadown") - src.icon_state = "ushankaup" - src.item_state = "ushankaup" + var/initial_icon_state = initial(icon_state) + if(icon_state == initial_icon_state) + icon_state = "[initial_icon_state]up" + item_state = "[initial_icon_state]up" body_parts_covered = HEAD - to_chat(user, "You raise the ear flaps on the ushanka.") + to_chat(user, "You raise the ear flaps on \the [src].") else - src.icon_state = "ushankadown" - src.item_state = "ushankadown" - to_chat(user, "You lower the ear flaps on the ushanka.") + icon_state = initial_icon_state + item_state = initial_icon_state + to_chat(user, "You lower the ear flaps on \the [src].") body_parts_covered = EARS|HEAD +/obj/item/clothing/head/ushanka/security + name = "security ushanka" + desc = "Davai, tovarish. Let us catch the capitalist greyshirt, and show him why it is that we proudly wear red!" + icon_state = "ushankared" + item_state = "ushankared" /* * Pumpkin head */ @@ -166,43 +173,29 @@ flags = FPRINT var/icon/mob var/icon/mob2 + var/haircolored = 1 siemens_coefficient = 1.5 - update_icon(var/mob/living/carbon/human/user) - if(!istype(user)) - return - mob = new/icon("icon" = 'icons/mob/head.dmi', "icon_state" = "kitty") - mob2 = new/icon("icon" = 'icons/mob/head.dmi', "icon_state" = "kitty2") - mob.Blend(rgb(user.r_hair, user.g_hair, user.b_hair), ICON_ADD) - mob2.Blend(rgb(user.r_hair, user.g_hair, user.b_hair), ICON_ADD) - - var/icon/earbit = new/icon("icon" = 'icons/mob/head.dmi', "icon_state" = "kittyinner") - var/icon/earbit2 = new/icon("icon" = 'icons/mob/head.dmi', "icon_state" = "kittyinner2") - mob.Blend(earbit, ICON_OVERLAY) - mob2.Blend(earbit2, ICON_OVERLAY) - /obj/item/clothing/head/kitty/cursed canremove = 0 -/obj/item/clothing/head/kitty/equipped(mob/M, var/slot) - ..() - var/mob/living/carbon/human/H = M - if(!istype(H)) - return - if(slot == slot_head) - to_chat(H, "Something on your head is making you feel a little lightheaded...") +/obj/item/clothing/head/kitty/collectable + desc = "A pair of black kitty ears. Meow!" + haircolored = 0 -/obj/item/clothing/head/kitty/unequipped(mob/living/carbon/human/user, var/from_slot = null) - ..() - if(from_slot == slot_head && istype(user)) - to_chat(user, "Your head starts to feel better again.") - -/obj/item/clothing/head/kitty/OnMobLife(var/mob/living/carbon/human/wearer) - if(!istype(wearer)) +/obj/item/clothing/head/kitty/update_icon(var/mob/living/carbon/human/user) + if(!istype(user) || !haircolored) return - if(wearer.get_item_by_slot(slot_head) == src) - if(prob(20)) - wearer.adjustBrainLoss(1) + mob = new/icon("icon" = 'icons/mob/head.dmi', "icon_state" = "kitty") + mob2 = new/icon("icon" = 'icons/mob/head.dmi', "icon_state" = "kitty2") + mob.Blend(rgb(user.r_hair, user.g_hair, user.b_hair), ICON_ADD) + mob2.Blend(rgb(user.r_hair, user.g_hair, user.b_hair), ICON_ADD) + + var/icon/earbit = new/icon("icon" = 'icons/mob/head.dmi', "icon_state" = "kittyinner") + var/icon/earbit2 = new/icon("icon" = 'icons/mob/head.dmi', "icon_state" = "kittyinner2") + mob.Blend(earbit, ICON_OVERLAY) + mob2.Blend(earbit2, ICON_OVERLAY) + /obj/item/clothing/head/butt name = "butt" diff --git a/code/modules/clothing/head/tactical.dm b/code/modules/clothing/head/tactical.dm index 07b4ba09ee6..87cdfa8760c 100644 --- a/code/modules/clothing/head/tactical.dm +++ b/code/modules/clothing/head/tactical.dm @@ -22,7 +22,7 @@ flashlight = I update_brightness() - user.update_action_buttons() + user.update_action_buttons_icon() user.update_inv_head() return if(isscrewdriver(I) && src.flashlight) @@ -31,7 +31,7 @@ flashlight = null update_brightness() - user.update_action_buttons() + user.update_action_buttons_icon() user.update_inv_head() return return ..() @@ -41,9 +41,9 @@ obj/item/clothing/head/helmet/tactical/attack_self(mob/user) flashlight.on = !flashlight.on if(get_turf(src)) if(flashlight.on) - playsound(get_turf(src), flashlight.sound_on, 50, 1) + playsound(src, flashlight.sound_on, 50, 1) else - playsound(get_turf(src), flashlight.sound_off, 50, 1) + playsound(src, flashlight.sound_off, 50, 1) update_brightness() user.update_inv_head() @@ -100,7 +100,7 @@ obj/item/clothing/head/helmet/tactical/attack_self(mob/user) flags = FPRINT armor = list(melee = 82, bullet = 15, laser = 5,energy = 5, bomb = 5, bio = 2, rad = 0) siemens_coefficient = 0.7 - body_parts_covered = HEAD|MOUTH + body_parts_covered = FULL_HEAD eyeprot = 1 /obj/item/clothing/head/helmet/tactical/swat diff --git a/code/modules/clothing/masks/chemmask.dm b/code/modules/clothing/masks/chemmask.dm index 7c80ac10c06..ec291ff3b4b 100644 --- a/code/modules/clothing/masks/chemmask.dm +++ b/code/modules/clothing/masks/chemmask.dm @@ -287,7 +287,7 @@ /obj/item/clothing/mask/chemmask/proc/pack_check(mob/user) //Shuts off mask if the user is not wearing a chempack. var/mob/living/M = user - if (!(M && M.back && istype(M.back,/obj/item/weapon/reagent_containers/chempack))) + if (!(istype(M) && M.back && istype(M.back,/obj/item/weapon/reagent_containers/chempack))) mask_shutdown(user) to_chat(user, "\The [src] shuts off!") return 0 @@ -325,7 +325,7 @@ var/obj/item/weapon/reagent_containers/glass/B = P.beaker if (B.is_empty() && firstalert_beaker == 0) firstalert_beaker = 1 - playsound(get_turf(src),'sound/mecha/internaldmgalarm.ogg', 100, 1) + playsound(src,'sound/mecha/internaldmgalarm.ogg', 100, 1) to_chat(user, "The auxiliary beaker is empty!") else if (!B.is_empty()) firstalert_beaker = 0 @@ -333,7 +333,8 @@ /obj/item/clothing/mask/chemmask/proc/mask_shutdown(mob/user) //Removes most verbs upon toggling the mask off, but not all. The user keeps access to the verbs to toggle connection to the tank and beaker. power = 0 icon_state = "chemmask0" - user.update_inv_wear_mask() + if(istype(user)) + user.update_inv_wear_mask() update_verbs() /obj/item/clothing/mask/chemmask/process() diff --git a/code/modules/clothing/masks/miscellaneous.dm b/code/modules/clothing/masks/miscellaneous.dm index eb1ee41535d..76119a70dd0 100644 --- a/code/modules/clothing/masks/miscellaneous.dm +++ b/code/modules/clothing/masks/miscellaneous.dm @@ -36,7 +36,10 @@ desc = "Warning: moustache is fake." icon_state = "fake-moustache" flags = FPRINT - body_parts_covered = FACE //totally intentional + body_parts_covered = BEARD + +/obj/item/clothing/mask/fakemoustache/is_hidden_identity() + return TRUE //scarves (fit in in mask slot) /obj/item/clothing/mask/scarf @@ -73,16 +76,25 @@ icon_state = "balaclava" item_state = "balaclava" flags = FPRINT - body_parts_covered = FACE + body_parts_covered = HEAD|MOUTH|EARS w_class = W_CLASS_SMALL species_fit = list(VOX_SHAPED, GREY_SHAPED) +/obj/item/clothing/mask/balaclava/is_hidden_identity() + return TRUE + +/obj/item/clothing/mask/balaclava/skimask + heat_conductivity = INS_MASK_HEAT_CONDUCTIVITY + name = "ski mask" + desc = "This NT-brand skimask is sure to keep you warm." + /obj/item/clothing/mask/neorussian name = "neo-Russian mask" desc = "Somehow, it makes you act and look way more polite than usual." icon_state = "nr_mask" item_state = "nr_mask" body_parts_covered = FACE + heat_conductivity = INS_MASK_HEAT_CONDUCTIVITY /obj/item/clothing/mask/pig name = "pig mask" diff --git a/code/modules/clothing/masks/transmog.dm b/code/modules/clothing/masks/transmog.dm index e605e44d2ad..dea5e1359d6 100644 --- a/code/modules/clothing/masks/transmog.dm +++ b/code/modules/clothing/masks/transmog.dm @@ -26,6 +26,12 @@ if(cursed) name = "cursed [name]" +/obj/item/clothing/mask/morphing/mob_can_equip(mob/M, slot, disable_warning = 0, automatic = 0) + M.visible_message("\The [M] attempts to put on \the [src].") + if(do_after(M, src, 5 SECONDS)) + return ..() + return CANNOT_EQUIP + /obj/item/clothing/mask/morphing/equipped(mob/living/carbon/C, wear_mask) if(target_type && istype(C)) if(C.get_item_by_slot(slot_wear_mask) == src) @@ -101,7 +107,7 @@ /obj/item/clothing/mask/morphing/lizard name = "mask of the lizard" desc = "It appears to be modeled after a lizard." - target_type = /mob/living/simple_animal/lizard + target_type = /mob/living/simple_animal/hostile/lizard icon_state = "lizard_mask" /obj/item/clothing/mask/morphing/xeno @@ -125,8 +131,7 @@ ..() color = rgb(rand(0,255),rand(0,255),rand(0,255)) //Remove cockatrices because they're somewhat OP when player controlled - target_type = pick(existing_typesof(/mob/living/simple_animal) - existing_typesof(/mob/living/simple_animal/hostile/humanoid) - typesof(/mob/living/simple_animal/hostile/retaliate/cockatrice) - typesof(/mob/living/simple_animal/hostile/giant_spider/hunter/dead) - typesof(/mob/living/simple_animal/hostile/asteroid/hivelordbrood)) - + target_type = pick(existing_typesof(/mob/living/simple_animal) - (existing_typesof_list(blacklisted_mobs) + existing_typesof_list(boss_mobs))) /obj/item/clothing/mask/morphing/ghost name = "mask of the phantom" desc = "It appears to be modeled after a ghost. It looks as though it might disappear at any moment." diff --git a/code/modules/clothing/shoes/magboots.dm b/code/modules/clothing/shoes/magboots.dm index f27ca010bb7..3d191dc79dc 100644 --- a/code/modules/clothing/shoes/magboots.dm +++ b/code/modules/clothing/shoes/magboots.dm @@ -40,12 +40,12 @@ victim.visible_message("\The [user] [stomp_hit] \the [victim] with the activated [src.name]!", "\The [user] [stomp_hit] you with \his [src.name]!") victim.apply_damage(stomp_attack_power, BRUTE, affecting) - playsound(get_turf(victim), 'sound/effects/gib3.ogg', 100, 1) + playsound(victim, 'sound/effects/gib3.ogg', 100, 1) else return toggle() - playsound(get_turf(victim), 'sound/mecha/mechstep.ogg', 100, 1) + playsound(victim, 'sound/mecha/mechstep.ogg', 100, 1) /obj/item/clothing/shoes/magboots/proc/toggle() if(usr.isUnconscious()) @@ -121,6 +121,13 @@ base_state = "capboots" anchoring_system_examine = "Its anchoring spikes appear to be" +//Magnificent +/obj/item/clothing/shoes/magboots/magnificent + desc = "The secret meaning of what mag stands for." + name = "magnificent mag boots" + icon_state = "MAGNIFICENTboots0" + base_state = "MAGNIFICENTboots1" + /obj/item/clothing/shoes/magboots/captain/toggle() //set name = "Toggle Floor Grip" if(usr.isUnconscious()) @@ -136,4 +143,71 @@ src.slowdown = mag_slow src.magpulse = 1 icon_state = "[base_state]1" - to_chat(usr, "Small spikes shoot from your shoes and dig into the flooring, bracing you.") \ No newline at end of file + to_chat(usr, "Small spikes shoot from your shoes and dig into the flooring, bracing you.") + + +/obj/item/clothing/shoes/magboots/funk + name = "neo-soviet funk boots" + desc = "The top secret plan to end Cold war 2 was not through tactical nuclear exchange and espionage, but through an intense dance-off between the Neo-Soviet Premier and the United Fronts President." + icon_state = "funk" + base_state = "funk" + var/funk_level = 0 + canremove = 0 + +/obj/item/clothing/shoes/magboots/funk/toggle() + if(usr.isUnconscious()) + return + if(funk_level >= 11) //WE HAVE GONE TOO FAR, COMRADE + return + usr.visible_message("[usr] dials up \the [src]'s funk level to [funk_level+1]") + funk_level++ + if(funk_level >= 2) + clothing_flags |= NOSLIP + magpulse = 1 + +/obj/item/clothing/shoes/magboots/funk/step_action() + ..() + var/mob/living/carbon/human/H = loc + //Evaluate L-RUSS levels + var/russian = 1 + if(H.head) + if(H.head.type == /obj/item/clothing/head/bearpelt) + russian+=1 + if(H.head.type == /obj/item/clothing/head/bearpelt/real) + russian+=2 + if(!H.w_uniform) + russian++ + else + if(H.w_uniform.type == /obj/item/clothing/under/russobluecamooutfit || istype(H.w_uniform, /obj/item/clothing/under/neorussian)) + russian+=2 + if(findtext("ivan",lowertext(H.name)) || findtext("yuri",lowertext(H.name)) || findtext("vlad",lowertext(H.name)) || findtext("lenin",lowertext(H.name)) || findtext("boris",lowertext(H.name)) || findtext("sasha",lowertext(H.name)) || findtext("misha",lowertext(H.name)) || findtext("sergei",lowertext(H.name))) + russian+=3 + + if(funk_level > 2 && prob((50/russian)**funk_level)) + var/datum/organ/external/foot = H.pick_usable_organ(LIMB_LEFT_FOOT, LIMB_RIGHT_FOOT) + if(foot.take_damage((rand(1, 3)/10)*funk_level, 0)) + H.UpdateDamageIcon() + + if(funk_level > 4 && prob((10/russian)*funk_level)) + H.reagents.add_reagent(HYPERZINE, 1) + + /** IT WAS TOO MUCH, SERGEI + if(funk_level > 5 && prob((20/russian)*funk_level)) //IT IS TOO LATE, SERGEI + step_rand(H) + **/ + if(funk_level > 6 && prob((10/russian)*funk_level)) + H.reagents.add_reagent(HYPOZINE, 1) + + if(funk_level > 9 && prob((5/russian)*funk_level)) + explosion(get_turf(src), round((1*funk_level)/russian)*0.25, round((1*funk_level)/russian)*0.5, round((1*funk_level)/russian)) + + if(prob((funk_level/russian)*2)) //IT WAS ALWAYS TOO LATE + toggle() + +/obj/item/clothing/shoes/magboots/funk/OnMobDeath(var/mob/living/carbon/human/wearer) + var/mob/living/carbon/human/W = wearer + W.drop_from_inventory(src) + funk_level = 0 + canremove = 1 + clothing_flags &= ~NOSLIP + magpulse = 0 \ No newline at end of file diff --git a/code/modules/clothing/shoes/miscellaneous.dm b/code/modules/clothing/shoes/miscellaneous.dm index ff690a34e99..7257d188765 100644 --- a/code/modules/clothing/shoes/miscellaneous.dm +++ b/code/modules/clothing/shoes/miscellaneous.dm @@ -294,6 +294,7 @@ desc = "Tovarish, no one will realize you stepped on a pile of shit if your pair already looks like shit." icon_state = "nr_boots" item_state = "nr_boots" + heat_conductivity = INS_ARMOUR_HEAT_CONDUCTIVITY /obj/item/clothing/shoes/cult name = "boots" @@ -433,4 +434,32 @@ name = "clockwork boots" desc = "A pair of boots worn by the followers of Ratvar." icon_state = "clockwork" - item_state = "clockwork" \ No newline at end of file + item_state = "clockwork" + +/obj/item/clothing/shoes/knifeboot + name = "laceup shoes" + desc = "The height of fashion, and they're pre-polished!" + icon_state = "laceups" + item_state = "laceups" + species_fit = list(VOX_SHAPED) + actions_types = list(/datum/action/item_action/generic_toggle) + var/toggle = FALSE + +/obj/item/clothing/shoes/knifeboot/attack_self() + toggle = !toggle + to_chat(usr, "You toggle \the [src]'s hidden knife [toggle?"out":"in"].") + update_icon() + ..() + +/obj/item/clothing/shoes/knifeboot/update_icon() + if(toggle) + icon_state = "[initial(icon_state)]_1" + else + icon_state = initial(icon_state) + item_state = icon_state + +/obj/item/clothing/shoes/knifeboot/on_kick(mob/living/carbon/human/user, mob/living/victim) + if(istype(victim) && toggle) + var/datum/organ/external/affecting = victim.get_organ(ran_zone(user.zone_sel.selecting)) + //Sharpness 1.5, force 10, edge = SHARP_TIP | SHARP_BLADE + victim.apply_damage(victim.run_armor_absorb(affecting, "melee", 10), BRUTE, affecting, victim.run_armor_check(affecting, "melee"), sharp = 1.5, edge = SHARP_TIP | SHARP_BLADE, used_weapon = src) \ No newline at end of file diff --git a/code/modules/clothing/spacesuits/alien.dm b/code/modules/clothing/spacesuits/alien.dm index 5f7bcea1647..e0ab883e7ca 100644 --- a/code/modules/clothing/spacesuits/alien.dm +++ b/code/modules/clothing/spacesuits/alien.dm @@ -388,6 +388,7 @@ obj/item/clothing/head/helmet/space/vox/civ/trader/stealth //blackhelmet name = "vox roboticist pressure helmet" icon_state = "vox-civ-roboticist" desc = "A very alien-looking helmet for vox crewmembers. This one is for roboticists." + actions_types = list(/datum/action/item_action/toggle_helmet_mask) //Med/Sci diff --git a/code/modules/clothing/spacesuits/plasmamen.dm b/code/modules/clothing/spacesuits/plasmamen.dm index 31d30ddaa63..710307a6b6f 100644 --- a/code/modules/clothing/spacesuits/plasmamen.dm +++ b/code/modules/clothing/spacesuits/plasmamen.dm @@ -19,8 +19,7 @@ var/next_extinguish=0 var/extinguish_cooldown=10 SECONDS -/obj/item/clothing/suit/space/plasmaman/proc/Extinguish(var/mob/user) - var/mob/living/carbon/human/H=user +/obj/item/clothing/suit/space/plasmaman/proc/Extinguish(var/mob/living/carbon/human/H) if(next_extinguish > world.time) return @@ -28,6 +27,12 @@ to_chat(H, "Your suit automatically extinguishes the fire.") H.ExtinguishMob() +/obj/item/clothing/suit/space/plasmaman/proc/regulate_temp_of_wearer(var/mob/living/carbon/human/H) + if(H.bodytemperature < T0C+37) + H.bodytemperature = min(H.bodytemperature+5,T0C+37) + else + H.bodytemperature = max(H.bodytemperature-5,T0C+37) + /obj/item/clothing/head/helmet/space/plasmaman name = "plasmaman helmet" desc = "A special containment helmet designed to protect a plasmaman's volatile body from outside exposure and quickly extinguish it in emergencies." @@ -257,6 +262,10 @@ icon_state = "plasmamanScience_helmet0" base_state = "plasmamanScience_helmet" +/obj/item/clothing/head/helmet/space/plasmaman/science/New() + actions_types += /datum/action/item_action/toggle_helmet_mask + ..() + /obj/item/clothing/suit/space/plasmaman/science/rd name = "plasmaman research director suit" icon_state = "plasmaman_RD" diff --git a/code/modules/clothing/spacesuits/rig.dm b/code/modules/clothing/spacesuits/rig.dm index 64ab95904e5..e3918dd5f43 100644 --- a/code/modules/clothing/spacesuits/rig.dm +++ b/code/modules/clothing/spacesuits/rig.dm @@ -238,6 +238,7 @@ wizard_garb = 1 species_restricted = null + allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/weapon/teleportation_scroll,/obj/item/weapon/gun/energy/staff) /obj/item/clothing/suit/space/rig/wizard/acidable() return 0 @@ -294,7 +295,8 @@ /obj/item/ammo_storage, /obj/item/ammo_casing, /obj/item/weapon/handcuffs, - /obj/item/weapon/bikehorn/baton) + /obj/item/weapon/bikehorn/baton, + /obj/item/weapon/blunderbuss) siemens_coefficient = 0.7 pressure_resistance = 40 * ONE_ATMOSPHERE @@ -304,13 +306,13 @@ icon_state = "rig0-storm" _color = "storm" name = "stormtrooper helmet" - desc = "Now even more vulnerable to teddy bears!" + desc = "Even with the finest vision enhancement tech, you still can't hit shit." no_light = 1 /obj/item/clothing/suit/space/rig/security/stormtrooper icon_state = "rig-storm" name = "stormtrooper hardsuit" - desc = "Even with the finest vision enhancement tech, you still can't hit shit." + desc = "Now even more vulnerable to teddy bears!" //Atmospherics Rig (BS12) /obj/item/clothing/head/helmet/space/rig/atmos diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm index 692af826f5e..b84b520f070 100644 --- a/code/modules/clothing/suits/armor.dm +++ b/code/modules/clothing/suits/armor.dm @@ -1,5 +1,19 @@ /obj/item/clothing/suit/armor - allowed = list(/obj/item/weapon/gun/energy,/obj/item/weapon/reagent_containers/spray/pepper,/obj/item/weapon/gun/projectile,/obj/item/ammo_storage,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs,/obj/item/weapon/gun/lawgiver,/obj/item/weapon/gun/siren,/obj/item/weapon/gun/mahoguny,/obj/item/weapon/bikehorn/baton) + allowed = list( + /obj/item/weapon/gun/energy, + /obj/item/weapon/reagent_containers/spray/pepper, + /obj/item/weapon/gun/projectile, + /obj/item/ammo_storage, + /obj/item/ammo_casing, + /obj/item/weapon/melee/baton, + /obj/item/weapon/handcuffs, + /obj/item/weapon/gun/lawgiver, + /obj/item/weapon/gun/siren, + /obj/item/weapon/gun/mahoguny, + /obj/item/weapon/gun/grenadelauncher, + /obj/item/weapon/bikehorn/baton, + /obj/item/weapon/blunderbuss + ) body_parts_covered = FULL_TORSO flags = FPRINT heat_conductivity = ARMOUR_HEAT_CONDUCTIVITY @@ -120,6 +134,17 @@ siemens_coefficient = 0 var/basereflectchance = 60 +/obj/item/clothing/suit/armor/laserproof/advanced + name = "Vest of Reflection" + desc = "This modified version of a common ablative armor vest is guaranteed to reflect every single energy projectile coming your way. As a slight tradeoff though, it doesn't provide any protection." + icon_state = "armor_reflec_adv" + item_state = "armor_reflec_adv" + + //Reflect literally everything + basereflectchance = 300 + + armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0) + /obj/item/clothing/suit/armor/laserproof/become_defective() if(!defective) ..() @@ -208,7 +233,7 @@ L.visible_message("The reactive teleport system flings [L] clear of [attack_text]!", "The reactive teleport system flings you clear of [attack_text].") - playsound(get_turf(L), 'sound/effects/teleport.ogg', 30, 1) + playsound(L, 'sound/effects/teleport.ogg', 30, 1) L.forceMove(picked) diff --git a/code/modules/clothing/suits/labcoat.dm b/code/modules/clothing/suits/labcoat.dm index 919094c9b0e..2e398685cfc 100644 --- a/code/modules/clothing/suits/labcoat.dm +++ b/code/modules/clothing/suits/labcoat.dm @@ -6,12 +6,10 @@ //icon_state = "labcoat_open" item_state = "labcoat" blood_overlay_type = "coat" - allowed = list(/obj/item/device/analyzer,/obj/item/stack/medical,/obj/item/weapon/dnainjector,/obj/item/weapon/reagent_containers/dropper,/obj/item/weapon/reagent_containers/syringe,/obj/item/weapon/reagent_containers/hypospray,/obj/item/device/healthanalyzer,/obj/item/device/flashlight/pen,/obj/item/weapon/minihoe,/obj/item/weapon/switchtool) + allowed = list(/obj/item/roller, /obj/item/device/analyzer,/obj/item/stack/medical,/obj/item/weapon/dnainjector,/obj/item/weapon/reagent_containers/dropper,/obj/item/weapon/reagent_containers/syringe,/obj/item/weapon/reagent_containers/hypospray,/obj/item/device/healthanalyzer,/obj/item/device/flashlight/pen,/obj/item/weapon/minihoe,/obj/item/weapon/switchtool) armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 50, rad = 0) species_fit = list(VOX_SHAPED, GREY_SHAPED) - - /obj/item/clothing/suit/storage/labcoat/update_icon() if(open) icon_state="[base_icon_state]_open" diff --git a/code/modules/clothing/suits/leather.dm b/code/modules/clothing/suits/leather.dm index 88a3d2d6749..d36db00c0e8 100644 --- a/code/modules/clothing/suits/leather.dm +++ b/code/modules/clothing/suits/leather.dm @@ -21,11 +21,10 @@ new/obj/item/clothing/suit/leather/corgi(get_turf(src)) user.drop_item(src, force_drop = 1) qdel(src) - /* DEERS TO BE IMPLEMENTED if(istype (S, /obj/item/stack/sheet/animalhide/deer)) new/obj/item/clothing/suit/leather/deer(get_turf(src)) user.drop_item(src, force_drop = 1) - qdel(src)*/ + qdel(src) if(istype (S, /obj/item/stack/sheet/animalhide/xeno)) new/obj/item/clothing/suit/leather/xeno(get_turf(src)) user.drop_item(src, force_drop = 1) @@ -38,12 +37,11 @@ icon_state = "suit_leather_corgi" item_state = "suit_leather_corgi" -/* DEERS TO BE IMPLEMENTED /obj/item/clothing/suit/leather/deer name = "deer-leather suit" desc = "Coated in deer hide, smells just as bad as you'd think." icon_state = "suit_leather_deer" - item_state = "suit_leather_deer"*/ + item_state = "suit_leather_deer" /obj/item/clothing/suit/leather/xeno name = "xeno-hide suit" diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm index 4a29df6b5b0..954570e287f 100644 --- a/code/modules/clothing/suits/miscellaneous.dm +++ b/code/modules/clothing/suits/miscellaneous.dm @@ -552,13 +552,25 @@ return M.visible_message("\The [M] opens \his [src.name], allowing you to see inside. Take a closer look.","You flash the contents of your [src.name].") -/obj/item/clothing/suit/sakura_kimono +/obj/item/clothing/suit/kimono + name = "kimono" + desc = "A traditional Japanese kimono." + icon_state = "fancy_kimono" + item_state = "fancy_kimono" + flags = FPRINT + body_parts_covered = ARMS|LEGS|FULL_TORSO|IGNORE_INV + +/obj/item/clothing/suit/kimono/ronin + name = "black kimono" + desc = "A black and plain looking kimono." + icon_state = "ronin_kimono" + item_state = "ronin_kimono" + +/obj/item/clothing/suit/kimono/sakura name = "sakura kimono" desc = "A pale-pink, nearly white, kimono with a red and gold obi. There is a embroidered design of cherry blossom flowers covering the kimono." icon_state = "sakura_kimono" item_state = "sakura_kimono" - flags = FPRINT - body_parts_covered = ARMS|LEGS|FULL_TORSO|IGNORE_INV /obj/item/clothing/suit/clockwork_robes name = "clockwork robes" diff --git a/code/modules/clothing/suits/plate_carrier.dm b/code/modules/clothing/suits/plate_carrier.dm new file mode 100644 index 00000000000..60f72a1f3db --- /dev/null +++ b/code/modules/clothing/suits/plate_carrier.dm @@ -0,0 +1,121 @@ +/** + Plate Carrier armor. + Armor that accepts an armored plate, that takes the brunt of the damage and steadily ablates to nothing. +*/ + +/obj/item/clothing/suit/armor/plate_carrier + name = "tactical plate armor" + icon_state = "tactical_armor" + item_state = "tactical_armor" + var/event_key + var/obj/item/weapon/armor_plate/P + +/obj/item/clothing/suit/armor/plate_carrier/get_armor(var/type) + var/armor_value = armor[type] + if(P) + armor_value = armor[type] <= 0 ? P.armor[type] : Clamp((armor[type]+P.armor[type])/2, armor[type], 100) + return armor_value + +/obj/item/clothing/suit/armor/plate_carrier/get_armor_absorb(var/type) + var/armor_value = armor_absorb[type] + if(P) + armor_value = armor_absorb[type] <= 0 ? P.armor_absorb[type] : Clamp((armor_absorb[type]+P.armor_absorb[type])/2, armor_absorb[type], 100) + return armor_value + +/obj/item/clothing/suit/armor/plate_carrier/equipped(var/mob/user, var/slot) + ..() + if(slot == slot_wear_suit) + event_key = user.on_damaged.Add(src, "handle_user_damage") + + +/obj/item/clothing/suit/armor/plate_carrier/unequipped(mob/user, var/from_slot = null) + if(from_slot == slot_wear_suit) + user.on_damaged.Remove(event_key) + event_key = null + ..() + +/obj/item/clothing/suit/armor/plate_carrier/attack_self(mob/user) + if(P) + user.put_in_hands(P) + P = null + +/obj/item/clothing/suit/armor/plate_carrier/attackby(obj/item/W,mob/user) + ..() + if(istype(W, /obj/item/weapon/armor_plate)) + if(P) + to_chat(user, "There is already \a [P] installed on \the [src].") + return + if(user.drop_item(W, src)) + P = W + to_chat(user, "You install \the [W] into \the [src].") + +/obj/item/clothing/suit/armor/plate_carrier/examine(mob/user) + ..() + if(P) + to_chat(user, "It has \a [P] attached to it. Take a closer look.") + +/obj/item/clothing/suit/armor/plate_carrier/proc/handle_user_damage(list/arguments) + if(!P) + return + var/amount = arguments["amount"] + if(amount <= 0) + return + var/type = arguments["type"] + + P.receive_damage(type, amount) + if(P.gcDestroyed) + P = null + +/obj/item/clothing/suit/armor/plate_carrier/security + name = "security plate armor" + icon_state = "security_armor" + item_state = "security_armor" + armor = list(melee = 10, bullet = 15, laser = 25, energy = 15, bomb = 5, bio = 0, rad = 0) + +/obj/item/weapon/armor_plate + icon = 'icons/obj/items.dmi' + icon_state = "plate_1" + name = "ceramic armor plate" + health = 20 + armor = list(melee = 25, bullet = 7, laser = 50, energy = 10, bomb = 25, bio = 0, rad = 0) + armor_absorb = list(melee = 25, bullet = 20, laser = 20, energy = -5, bomb = 0, bio = 0, rad = 0) + + +/obj/item/weapon/armor_plate/proc/receive_damage(var/type, var/amount) + if(type == BRUTE || type == BURN) + health -= amount + playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 70, 1) + if(health <= 0) + visible_message("\The [src] breaks apart!") + var/turf/T = get_turf(src) + playsound(T, "shatter", 70, 1) + getFromPool(/obj/effect/decal/cleanable/dirt,T) + if(prob(75)) + var/obj/item/weapon/shard/shrapnel/S = new(T) + S.name = "[src] shrapnel" + S.desc = "[S.desc] It looks like it's from \a [src]." + qdel(src) + +/obj/item/weapon/armor_plate/examine(var/mob/user) + ..() + switch(health) + if(initial(health) to initial(health)/2) + to_chat(user, "\The [src] is hard.") + if(initial(health)/2-1 to initial(health)/4) + to_chat(user, "\The [src] is brittle.") + if(initial(health)/4-1 to 0) + to_chat(user, "\The [src] is falling apart!") + +/obj/item/weapon/armor_plate/bullet_resistant + name = "plasteel armor plate" + icon_state = "plate_2" + health = 30 + armor = list(melee = 50, bullet = 50, laser = 10, energy = 10, bomb = 0, bio = 0, rad = 0) + armor_absorb = list(melee = 25, bullet = 40, laser = 10, energy = -5, bomb = 35, bio = 0, rad = 0) + +/obj/item/weapon/armor_plate/laser_resistant + name = "ceramite armor plate" + icon_state = "plate_3" + health = 30 + armor = list(melee = 10, bullet = 10, laser = 80, energy = 50, bomb = 0, bio = 0, rad = 0) + armor_absorb = list(melee = 25, bullet = 20, laser = 40, energy = -5, bomb = 0, bio = 0, rad = 0) \ No newline at end of file diff --git a/code/modules/clothing/suits/wintercoat.dm b/code/modules/clothing/suits/wintercoat.dm index dd0ea880e1a..d0ac79e1a03 100644 --- a/code/modules/clothing/suits/wintercoat.dm +++ b/code/modules/clothing/suits/wintercoat.dm @@ -50,12 +50,12 @@ name = "Head of Security's winter coat" icon_state = "coathos" nohood = 1 - body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS + body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS|IGNORE_INV /obj/item/clothing/suit/wintercoat/security/warden name = "Warden's winter coat" icon_state = "coatwarden" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS + body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS|IGNORE_INV nohood = 1 /obj/item/clothing/suit/wintercoat/medical @@ -93,7 +93,7 @@ name = "Head of Personnel's winter coat" icon_state = "coathop" armor = list(melee = 50, bullet = 10, laser = 25, energy = 10, bomb = 0, bio = 0, rad = 0) - body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS + body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS|IGNORE_INV /obj/item/clothing/suit/wintercoat/miner name = "mining winter coat" diff --git a/code/modules/components/ai/atmos.dm b/code/modules/components/ai/atmos.dm index d638df22737..70076a97228 100644 --- a/code/modules/components/ai/atmos.dm +++ b/code/modules/components/ai/atmos.dm @@ -1,11 +1,11 @@ /datum/component/ai/atmos_checker //Atmos effect - Yes, you can make creatures that require plasma or co2 to survive. N2O is a trace gas and handled separately, hence why it isn't here. It'd be hard to add it. Hard and me don't mix (Yes, yes make all the dick jokes you want with that.) - Errorage - var/min_oxy = 5 + var/min_oxy = 5 / CELL_VOLUME var/max_oxy = 0 //Leaving something at 0 means it's off - has no maximum var/min_tox = 0 - var/max_tox = 1 + var/max_tox = 1 / CELL_VOLUME var/min_co2 = 0 - var/max_co2 = 5 + var/max_co2 = 5 / CELL_VOLUME var/min_n2 = 0 var/max_n2 = 0 var/unsuitable_damage = 2 //This damage is taken when atmos doesn't fit all the requirements above @@ -46,41 +46,41 @@ SendSignal(COMSIG_ADJUST_BODYTEMP, list("temp"=((Environment.temperature - controller.getBodyTemperature()) / 5))) if(min_oxy) - if(Environment.oxygen < min_oxy) + if(Environment.molar_density("oxygen") < min_oxy) atmos_suitable = 0 oxygen_alert = 1 else oxygen_alert = 0 if(max_oxy) - if(Environment.oxygen > max_oxy) + if(Environment.molar_density("oxygen") > max_oxy) atmos_suitable = 0 if(min_tox) - if(Environment.toxins < min_tox) + if(Environment.molar_density("toxins") < min_tox) atmos_suitable = 0 if(max_tox) - if(Environment.toxins > max_tox) + if(Environment.molar_density("toxins") > max_tox) atmos_suitable = 0 toxins_alert = 1 else toxins_alert = 0 if(min_n2) - if(Environment.nitrogen < min_n2) + if(Environment.molar_density("nitrogen") < min_n2) atmos_suitable = 0 if(max_n2) - if(Environment.nitrogen > max_n2) + if(Environment.molar_density("nitrogen") > max_n2) atmos_suitable = 0 if(min_co2) - if(Environment.carbon_dioxide < min_co2) + if(Environment.molar_density("carbon_dioxide") < min_co2) atmos_suitable = 0 if(max_co2) - if(Environment.carbon_dioxide > max_co2) + if(Environment.molar_density("carbon_dioxide") > max_co2) atmos_suitable = 0 //Atmos effect diff --git a/code/modules/components/ai/human/brain.dm b/code/modules/components/ai/human/brain.dm index 8b550063a87..4b1ed5718b8 100644 --- a/code/modules/components/ai/human/brain.dm +++ b/code/modules/components/ai/human/brain.dm @@ -154,8 +154,8 @@ if(DESIRE_ID) if((I.slot_flags & SLOT_ID) && I.mob_can_equip(H, slot_wear_id)) goal = I - if(goal) - break + if(goal) + break processing_desires return goal /datum/component/ai/human_brain/proc/AcquireItem(mob/living/carbon/human/H, obj/item/I) diff --git a/code/modules/components/ai/human/human_target_finder.dm b/code/modules/components/ai/human/human_target_finder.dm index 3f08d62c926..2a04a82cd8f 100644 --- a/code/modules/components/ai/human/human_target_finder.dm +++ b/code/modules/components/ai/human/human_target_finder.dm @@ -10,7 +10,7 @@ for(var/mob/M in view(range, container.holder)) if(is_type_in_list(M, exclude_types)) continue - if(M.stat) + if(M.isUnconscious()) continue if((M in B.enemies) || (M.faction && M.faction in B.enemy_factions) || (M.type in B.enemy_types)) o += M diff --git a/code/modules/customitems/item_spawning.dm b/code/modules/customitems/item_spawning.dm index a4f7c3edca7..edd03d9fca6 100644 --- a/code/modules/customitems/item_spawning.dm +++ b/code/modules/customitems/item_spawning.dm @@ -1,6 +1,6 @@ /proc/EquipCustomItems(mob/living/carbon/human/M) - testing("\[CustomItem\] Checking for custom items for [M.ckey] ([M.real_name])...") +// testing("\[CustomItem\] Checking for custom items for [M.ckey] ([M.real_name])...") if(!establish_db_connection()) return @@ -26,7 +26,7 @@ var/path = text2path(query.item[1]) var/propadjust = query.item[2] var/jobmask = query.item[3] - testing("\[CustomItem\] Setting up [path] for [M.ckey] ([M.real_name]). jobmask=[jobmask];propadjust=[propadjust]") +// testing("\[CustomItem\] Setting up [path] for [M.ckey] ([M.real_name]). jobmask=[jobmask];propadjust=[propadjust]") var/ok=0 if(jobmask!="*") var/allowed_jobs = splittext(jobmask,",") @@ -35,12 +35,12 @@ if(!(M.mind.role_alt_title in allowed_jobs)) alt_blocked=1 if(!(M.mind.assigned_role in allowed_jobs) || alt_blocked) - testing("Failed to apply custom item for [M.ckey]: Role(s) [M.mind.assigned_role][M.mind.role_alt_title ? " (nor "+M.mind.role_alt_title+")" : ""] are not in allowed_jobs ([english_list(allowed_jobs)])") +// testing("Failed to apply custom item for [M.ckey]: Role(s) [M.mind.assigned_role][M.mind.role_alt_title ? " (nor "+M.mind.role_alt_title+")" : ""] are not in allowed_jobs ([english_list(allowed_jobs)])") continue var/obj/item/Item = new path() - testing("Adding new custom item [query.item[1]] to [key_name_admin(M)]...") +// testing("Adding new custom item [query.item[1]] to [key_name_admin(M)]...") if(istype(Item,/obj/item/weapon/card/id)) var/obj/item/weapon/card/id/I = Item for(var/obj/item/weapon/card/id/C in M) @@ -58,24 +58,24 @@ C = null ok = M.equip_if_possible(I, slot_wear_id, 0) //if 1, last argument deletes on fail break - testing("Replaced ID!") +// testing("Replaced ID!") else if(istype(M.back,/obj/item/weapon/storage) && M.back:contents.len < M.back:storage_slots) // Try to place it in something on the mob's back Item.forceMove(M.back) ok = 1 - testing("Added to [M.back.name]!") +// testing("Added to [M.back.name]!") to_chat(M, "Your [Item.name] has been added to your [M.back.name].") else for(var/obj/item/weapon/storage/S in M.contents) // Try to place it in any item that can store stuff, on the mob. if (S.contents.len < S.storage_slots) Item.forceMove(S) ok = 1 - testing("Added to [S]!") +// testing("Added to [S]!") to_chat(M, "Your [Item.name] has been added to your [S.name].") break //skip: if (ok == 0) // Finally, since everything else failed, place it on the ground - testing("Plopped onto the ground!") +// testing("Plopped onto the ground!") Item.forceMove(get_turf(M.loc)) HackProperties(Item,propadjust) diff --git a/code/modules/detectivework/detective_scanner.dm b/code/modules/detectivework/detective_scanner.dm index e06559a2775..1ff8370be51 100644 --- a/code/modules/detectivework/detective_scanner.dm +++ b/code/modules/detectivework/detective_scanner.dm @@ -130,7 +130,7 @@ //PRINTS if(fingerprints_found.len>0) to_chat(user, "Isolated [fingerprints_found.len] fingerprints: Data Stored: Scan with Hi-Res Forensic Scanner to retrieve.") - playsound(get_turf(src), 'sound/items/detscan.ogg', 50, 1) + playsound(src, 'sound/items/detscan.ogg', 50, 1) var/list/complete_prints = list() for(var/i in fingerprints_found) @@ -148,7 +148,7 @@ //FIBERS if(fibers_found.len) to_chat(user, "Fibers/Materials Data Stored: Scan with Hi-Res Forensic Scanner to retrieve.") - playsound(get_turf(src), 'sound/items/detscan.ogg', 50, 1) + playsound(src, 'sound/items/detscan.ogg', 50, 1) //Blood if (blood_DNA_found.len) diff --git a/code/modules/detectivework/detective_work.dm b/code/modules/detectivework/detective_work.dm index 5873d0e17f0..83a1c36e019 100644 --- a/code/modules/detectivework/detective_work.dm +++ b/code/modules/detectivework/detective_work.dm @@ -100,9 +100,9 @@ var/const/FINGERPRINT_COMPLETE = 6 //This is the output of the stringpercent(pri return user.set_machine(src) var/dat = "" - var/isai = 0 - if(istype(usr,/mob/living/silicon)) - isai = 1 + var/isai = FALSE + if(isAI(user)) + isai = TRUE if(temp) dat += "[temp]

    " if(canclear) @@ -146,11 +146,10 @@ var/const/FINGERPRINT_COMPLETE = 6 //This is the output of the stringpercent(pri switch(href_list["operation"]) if("login") var/mob/M = usr - if(istype(M,/mob/living/silicon)) + if(issilicon(M)) authenticated = 1 updateDialog() - return - if (allowed(M)) + if(allowed(M)) authenticated = 1 if("logout") authenticated = 0 @@ -167,14 +166,20 @@ var/const/FINGERPRINT_COMPLETE = 6 //This is the output of the stringpercent(pri var/mob/M = usr var/obj/item/I = M.get_active_hand() if(I && istype(I)) - if(istype(I, /obj/item/weapon/evidencebag)) - scanning = I.contents[1] - scanning.forceMove(src) - I.overlays.len = 0 - I.icon_state = "evidenceobj" - else - if(M.drop_item(I, src)) - scanning = I + if(isgripper(I)) + var/obj/item/weapon/gripper/G = I + if(G.wrapped) + scanning = G.wrapped //We add it as scanned object first because we'll lose the wrapped reference once we drop it. + G.drop_item(G.wrapped, src) + else + if(istype(I, /obj/item/weapon/evidencebag)) + scanning = I.contents[1] + scanning.forceMove(src) + I.overlays.len = 0 + I.icon_state = "evidenceobj" + else + if(M.drop_item(I, src)) + scanning = I else to_chat(usr, "Invalid Object Rejected.") if("card") //Processing a fingerprint card. diff --git a/code/modules/error_handler/error_handler.dm b/code/modules/error_handler/error_handler.dm index 4acc9b92bed..9b54e6d49e8 100644 --- a/code/modules/error_handler/error_handler.dm +++ b/code/modules/error_handler/error_handler.dm @@ -101,7 +101,8 @@ desclines += " (This error will now be silenced for [configured_error_silence_time / 600] minutes)" // Now to actually output the error info... - world.log << "\[[time_stamp()]] Runtime in [e.file],[e.line]: [e]" + var/main_line = "\[[time_stamp()]] Runtime in [e.file],[e.line]: [e]" + world.log << main_line for (var/line in desclines) world.log << line @@ -109,4 +110,9 @@ if (global.error_cache) global.error_cache.log_error(e, desclines) +#ifdef UNIT_TESTS + if(global.current_test) + global.current_test.fail("[main_line]\n[desclines.Join("\n")]") +#endif + #endif diff --git a/code/modules/events/bluespaceanomaly.dm b/code/modules/events/bluespaceanomaly.dm index b6232d935a2..b4307e4a90f 100644 --- a/code/modules/events/bluespaceanomaly.dm +++ b/code/modules/events/bluespaceanomaly.dm @@ -76,6 +76,8 @@ continue if(istype(A, /atom/movable/lighting_overlay)) continue + if(A.flags & INVULNERABLE) + continue var/turf/newloc = locate(A.x + x_distance, A.y + y_distance, TO.z) // calculate the new place A.forceMove(newloc) diff --git a/code/modules/events/event_dynamic.dm b/code/modules/events/event_dynamic.dm index 6bc34982d0e..5afcbdeeeb3 100644 --- a/code/modules/events/event_dynamic.dm +++ b/code/modules/events/event_dynamic.dm @@ -50,6 +50,7 @@ var/list/event_last_fired = list() possibleEvents[/datum/event/communications_blackout] = 25 possibleEvents[/datum/event/thing_storm/meaty_gore] = 25 possibleEvents[/datum/event/unlink_from_centcomm] = 10 + possibleEvents[/datum/event/centcomm_order] = 25 if(active_with_role["AI"] > 0 || active_with_role["Cyborg"] > 0) possibleEvents[/datum/event/ionstorm] = 30 diff --git a/code/modules/events/infestation.dm b/code/modules/events/infestation.dm index 49e43677c37..58542390dc0 100644 --- a/code/modules/events/infestation.dm +++ b/code/modules/events/infestation.dm @@ -48,7 +48,7 @@ var/list/spawn_types = list() var/max_number = 4 - vermin = pick(VERM_MICE, VERM_LIZARDS, VERM_SPIDERS, VERM_SLIMES, VERM_BATS, VERM_BORERS, VERM_MIMICS, VERM_ROACHES, VERM_GREMLINS, VERM_BEES) + vermin = pick(VERM_MICE, VERM_LIZARDS, VERM_SPIDERS, VERM_SLIMES, VERM_BATS, VERM_BORERS, VERM_MIMICS, VERM_ROACHES, VERM_GREMLINS, VERM_BEES, VERM_HORNETS) if (override_vermin) vermin = override_vermin @@ -59,7 +59,7 @@ max_number = 12 vermstring = "mice" if(VERM_LIZARDS) - spawn_types = list(/mob/living/simple_animal/lizard) + spawn_types = list(/mob/living/simple_animal/hostile/lizard) max_number = 6 vermstring = "lizards" if(VERM_SPIDERS) @@ -88,27 +88,41 @@ vermstring = "gremlins" max_number = 4 //2 to 4 if(VERM_BEES) - spawn_types = /obj/machinery/apiary/wild + spawn_types = /obj/machinery/apiary/wild/angry vermstring = "angry bees" max_number = 2 + if(VERM_HORNETS) + spawn_types = /obj/machinery/apiary/wild/angry/hornet + vermstring = "deadly hornets" + max_number = 1 var/number = rand(2, max_number) - for(var/i = 0, i <= number, i++) - var/area/A = locate(spawn_area_type) - var/list/turf/simulated/floor/valid = list() - //Loop through each floor in the supply drop area - for(var/turf/simulated/floor/F in A) - if(!F.has_dense_content()) - valid.Add(F) + var/area/A = locate(spawn_area_type) + var/list/turf/simulated/floor/valid = list() + //Loop through each floor in the supply drop area + for(var/turf/simulated/floor/F in A) + if(!F.has_dense_content()) + valid.Add(F) + if(!valid.len) + message_admins("Infestation event failed! Could not find any viable turfs in [spawn_area_type] at which to spawn [number + 1] [vermstring].") + announceWhen = -1 + endWhen = 0 + return + for(var/i = 0, i <= number, i++) var/picked = pick(valid) if(vermin == VERM_SPIDERS) var/mob/living/simple_animal/hostile/giant_spider/spiderling/S = new(picked) S.amount_grown = 0 else var/spawn_type = pick(spawn_types) - new spawn_type(picked) + var/mob/M = new spawn_type(picked) + if(M.density) + valid -= picked + if(!valid.len) + message_admins("Infestation event could not find enough viable turfs in [spawn_area_type] to spawn all vermin. [number - i] [vermstring] were unable to spawn!") + break /datum/event/infestation/announce() var/warning = "Clear them out, before this starts to affect productivity." diff --git a/code/modules/events/radiation_storm.dm b/code/modules/events/radiation_storm.dm index 28523385d82..d44ea574882 100644 --- a/code/modules/events/radiation_storm.dm +++ b/code/modules/events/radiation_storm.dm @@ -30,7 +30,7 @@ for(var/area/A in areas) if(A.z != map.zMainStation || is_safe_zone(A)) continue - var/area/ma = get_area_master(A) + var/area/ma = get_area(A) ma.radiation_alert() make_maint_all_access() @@ -72,7 +72,7 @@ for(var/area/A in areas) if(A.z != map.zMainStation || is_safe_zone(A)) continue - var/area/ma = get_area_master(A) + var/area/ma = get_area(A) ma.reset_radiation_alert() diff --git a/code/modules/fish/fish_eggs.dm b/code/modules/fish/fish_eggs.dm index 49841dadb91..dc077f0205c 100644 --- a/code/modules/fish/fish_eggs.dm +++ b/code/modules/fish/fish_eggs.dm @@ -20,8 +20,11 @@ var/list/fish_eggs_list = list("dud" = /obj/item/fish_eggs, "shrimp" = /obj/item/fish_eggs/shrimp, "electric eel" = /obj/item/fish_eggs/electric_eel, "glofish" = /obj/item/fish_eggs/glofish, + "sea devil" = /obj/item/fish_eggs/seadevil ) +var/list/nonhatching_types = list("sea devil") //If you ever want to create another no-egg fish, add it here. + /obj/item/fish_eggs/goldfish name = "goldfish eggs" desc = "Goldfish eggs, surprisingly, don't contain actual gold." @@ -80,4 +83,18 @@ var/list/fish_eggs_list = list("dud" = /obj/item/fish_eggs, name = "glofish eggs" desc = "A cluster of bright neon eggs belonging to a bio-luminescent species of fish." icon_state = "glofish_eggs" - fish_type = "glofish" \ No newline at end of file + fish_type = "glofish" + +/obj/item/fish_eggs/seadevil + name = "sea devil" + desc = "An aquatic offshoot of gremlins that engage in the peculiar behavior of hatching fish eggs to eat mature adults." + icon_state = "seadevil" + fish_type = "sea devil" + +/obj/item/fish_eggs/seadevil/New() + ..() + processing_objects += src + +/obj/item/fish_eggs/seadevil/process() + if(istype(loc, /turf) && prob(60)) + Move(get_step(loc, pick(cardinal))) \ No newline at end of file diff --git a/code/modules/fish/fish_items.dm b/code/modules/fish/fish_items.dm index 97284ffce32..d12f6093c5c 100644 --- a/code/modules/fish/fish_items.dm +++ b/code/modules/fish/fish_items.dm @@ -10,7 +10,7 @@ var/list/fish_items_list = list("goldfish" = /obj/item/weapon/fish/goldfish, "shrimp" = /obj/item/weapon/reagent_containers/food/snacks/shrimp, "electric eel" = /obj/item/weapon/fish/electric_eel, "glofish" = /obj/item/weapon/fish/glofish -, +, "sea devil" = /obj/item/fish_eggs/seadevil //You can fish a sea devil straight back out and stick it in another tank. ) ////////////////////////////////////////////// @@ -84,7 +84,7 @@ var/list/fish_items_list = list("goldfish" = /obj/item/weapon/fish/goldfish, /obj/item/weapon/reagent_containers/food/snacks/shrimp/New() ..() desc = pick("Anyway, like I was sayin', shrimp is the fruit of the sea.", "You can barbecue it, boil it, broil it, bake it, saute it.") - reagents.add_reagent("NUTRIMENT", 1) + reagents.add_reagent(NUTRIMENT, 1) /obj/item/weapon/reagent_containers/food/snacks/feederfish name = "feeder fish" @@ -96,7 +96,7 @@ var/list/fish_items_list = list("goldfish" = /obj/item/weapon/fish/goldfish, /obj/item/weapon/reagent_containers/food/snacks/feederfish/New() ..() - reagents.add_reagent("NUTRIMENT", 1) + reagents.add_reagent(NUTRIMENT, 1) /obj/item/weapon/fish name = "fish" @@ -116,6 +116,7 @@ var/list/fish_items_list = list("goldfish" = /obj/item/weapon/fish/goldfish, name = "glofish" desc = "A small bio-luminescent fish. Not very bright, but at least it's pretty!" icon_state = "glofish" + meat_type = /obj/item/weapon/reagent_containers/food/snacks/glofishmeat /obj/item/weapon/fish/glofish/New() ..() @@ -137,7 +138,7 @@ var/list/fish_items_list = list("goldfish" = /obj/item/weapon/fish/goldfish, if(istype(O, /obj/item/weapon/wirecutters)) to_chat(user, "You rip out the teeth of \the [src]!") new /obj/item/weapon/fish/toothless_shark(get_turf(src)) - new /obj/item/stack/teeth/shark(get_turf(src)) + new /obj/item/stack/teeth/shark(get_turf(src), 10) qdel(src) return ..() @@ -171,6 +172,7 @@ var/list/fish_items_list = list("goldfish" = /obj/item/weapon/fish/goldfish, name = "goldfish" desc = "A goldfish, just like the one you never won at the county fair." icon_state = "goldfish" + meat_type = /obj/item/weapon/reagent_containers/food/snacks/goldfishmeat /obj/item/weapon/fish/salmon name = "salmon" @@ -201,6 +203,7 @@ var/list/fish_items_list = list("goldfish" = /obj/item/weapon/fish/goldfish, icon_state = "clownfish" throwforce = 1 force = 1 + hitsound = 'sound/items/bikehorn.ogg' attack_verb = list("slapped", "humiliated", "hit", "rubbed") /obj/item/weapon/fish/attackby(var/obj/item/O, var/mob/user) @@ -210,4 +213,4 @@ var/list/fish_items_list = list("goldfish" = /obj/item/weapon/fish/goldfish, new meat_type(get_turf(src)) qdel(src) return TRUE - ..() \ No newline at end of file + ..() diff --git a/code/modules/fish/fish_tank.dm b/code/modules/fish/fish_tank.dm index 472034282ab..f9ff1f2f28a 100644 --- a/code/modules/fish/fish_tank.dm +++ b/code/modules/fish/fish_tank.dm @@ -23,7 +23,7 @@ // Made by FalseIncarnate on Paradise // Ported to /vg/ by Shifty and jakmak(s) - +// Fish Bowl construction moved to code/game/machinery/constructable_frame.dm /obj/machinery/fishtank name = "placeholder tank" @@ -42,7 +42,6 @@ var/lid_switch = FALSE // FALSE = open, TRUE = closed (open by default) var/max_fish = 0 // How many fish the tank can support (varies with tank type, 1 fish per 50 units sounds reasonable) var/food_level = 0 // Amount of fishfood floating in the tank (max 10) - var/fish_list.len = 0 // Number of fish in the tank var/list/fish_list = list() // Tracks the current types of fish in the tank var/list/egg_list = list() // Tracks the current types of harvestable eggs in the tank @@ -106,6 +105,10 @@ cur_health = 100 shard_count = 3 +/obj/machinery/fishtank/wall/full + water_level = 500 + food_level = MAX_FOOD + /obj/machinery/fishtank/wall/Cross(atom/movable/mover, turf/target, height = 1.5, air_group = 0) // Prevents airflow. Copied from windows. if(istype(mover) && mover.checkpass(PASSGLASS)) return TRUE @@ -289,6 +292,18 @@ add_food(1) //The corpse became food for the other fish, ecology at it's finest if("glofish") glo_light++ + if("clownfish") + if(prob(10)) + playsound(src,'sound/items/bikehorn.ogg', 80, 1) + if("sea devil") + if(fish_list.len > 1 && prob(5)) + //Small chance to eat a random fish that isn't itself. + seadevil_eat() + + if(fish_list.len < max_fish && egg_list.len) + add_fish(get_key_by_element(fish_eggs_list,egg_list[1])) //add_fish takes a string. egg_list gives a path. fish_eggs_list is an associative list keyed with strings. get_key_by_index returns that string key by matching the path + egg_list -= egg_list[1] + if(!light_switch && (glo_light > 0)) set_light(2,glo_light,"#99FF66") @@ -340,19 +355,43 @@ fish_list.Remove(pick(fish_list)) //Kill a random fish update_icon() +/obj/machinery/fishtank/proc/seadevil_eat() + var/tmp/list/fish_to_eat = fish_list.Copy() + fish_to_eat.Remove("sea devil") + var/eat_target = pick(fish_to_eat) + visible_message("The sea devil devours \an [eat_target].") + kill_fish(eat_target) + /obj/machinery/fishtank/proc/add_fish(var/type) + if(!type || type == "dud") + return //Check if we were passed a fish type fish_list.Add("[type]") //Add a fish of the specified type //Announce the new fish update_icon() - visible_message("A new [type] has hatched in \the [src]!") + if(nonhatching_types.Find(type)) + visible_message("The [type] has been placed in \the [src]!") + else + visible_message("A new [type] has hatched in \the [src]!") /obj/machinery/fishtank/proc/select_egg_type() - var/fish = pick(fish_list) //Select a fish from the fish in the tank - if(prob(25)) //25% chance to be a dud (blank) egg + var/fish = null + if(prob(10)) //Small chance for infertility fish = "dud" + else + fish = recursive_valid_egg(fish_list) var/obj/item/fish_eggs/egg_path = fish_eggs_list[fish] //Locate the corresponding path from fish_eggs_list that matches the fish - return egg_path //The fish was located in the fish_eggs_list, so return the proper egg + return egg_path + +/obj/machinery/fishtank/proc/recursive_valid_egg(var/list/pick_egg_from) + var/fish = pick(pick_egg_from) + if(!fish || nonhatching_types.Find(fish)) + var/tmp/list/new_list = pick_egg_from.Copy() + return recursive_valid_egg(new_list.Remove(fish)) + //If it's a nonvalid type, let's try again without it. + else + return fish + //If it's valid, return this. /obj/machinery/fishtank/proc/harvest_eggs(var/mob/user) if(!egg_list.len) //Can't harvest non-existant eggs @@ -488,7 +527,7 @@ for (var/i = 1 to fish_list.len) if(fish_list.len > 1 && i == fish_list.len) //If there were at least 2 fish, and this is the last one, add "and" to the message message += "and " - message += "a [fish_list[i]]" + message += "\an [fish_list[i]]" if(i < fish_list.len) //There's more fish, add a comma to the message message +=", " message +="." //No more fish, end the message with a period @@ -702,13 +741,67 @@ hit(O, user) return TRUE -/* tank construction */ +//Conduction plate for electric eels -/obj/structure/displaycase_frame/attackby(var/obj/item/weapon/F, var/mob/user) // FISH BOWL - if (iswelder(F)) - to_chat(user, "You use the machine frame as a vice and shape the glass with the welder into a fish bowl.") - getFromPool(/obj/item/stack/sheet/metal, get_turf(src), 5) - new /obj/machinery/fishtank/bowl(get_turf(src)) - qdel(src) - return TRUE +/obj/machinery/power/conduction_plate + name = "conduction plate" + icon = 'icons/mecha/mech_bay.dmi' + icon_state = "recharge_floor" + layer = ABOVE_TILE_LAYER + plane = ABOVE_TURF_PLANE + anchored = 1 + density = 0 + machine_flags = SCREWTOGGLE | CROWDESTROY | FIXED2WORK + + component_parts = newlist( + /obj/item/weapon/circuitboard/conduction_plate, + /obj/item/weapon/stock_parts/capacitor + ) + + var/obj/machinery/fishtank/attached_tank = null + var/multiplier = 0.9 + +/obj/machinery/power/conduction_plate/New() + ..() + if(anchored) + connect_to_network() + RefreshParts() + +/obj/machinery/power/conduction_plate/RefreshParts() + for(var/obj/item/weapon/stock_parts/capacitor/C in component_parts) + multiplier = initial(multiplier) + (C.rating*0.1) //1 to 1.2 + +/obj/machinery/power/conduction_plate/process() + if(check_tank()) + var/power = 0 + for(var/fish in attached_tank.fish_list) + if(fish == "electric eel") + power += ARBITRARILY_LARGE_NUMBER * multiplier //10000 + add_avail(power) + +/obj/machinery/power/conduction_plate/proc/check_tank() + //Are we anchored? + if(!anchored) + return 0 + + //Is our old tank is still valid? + if(attached_tank && attached_tank.loc == loc) + return 1 + + //No? Let's look for a new one. + attached_tank = locate(/obj/machinery/fishtank/) in loc + if(attached_tank) + return 1 + else + return 0 + +/obj/machinery/power/conduction_plate/wrenchAnchor(var/mob/user) + . = ..() + if(!.) + return + attached_tank = null + if(anchored) + connect_to_network() + else + disconnect_from_network() \ No newline at end of file diff --git a/code/modules/flufftext/Hallucination.dm b/code/modules/flufftext/Hallucination.dm index 4ae1e4b43fa..647016add65 100644 --- a/code/modules/flufftext/Hallucination.dm +++ b/code/modules/flufftext/Hallucination.dm @@ -67,10 +67,8 @@ mob/living/carbon/proc/handle_hallucinations() halitem.name = "Revolver" if(2) //c4 halitem.icon = 'icons/obj/assemblies.dmi' - halitem.icon_state = "plastic-explosive0" + halitem.icon_state = pick("plastic-explosive0", "plastic-explosive2") halitem.name = "Mysterious Package" - if(prob(25)) - halitem.icon_state = "c4small_1" if(3) //sword halitem.icon = 'icons/obj/weapons.dmi' halitem.icon_state = "sword1" @@ -311,7 +309,35 @@ mob/living/carbon/proc/handle_hallucinations() spawn(duration) if(C) C.images.Remove(foodie) //Remove the image from hallucinating mob - if(87 to 88) //Turns your screen + if(87) + var/mob/living/L + + var/list/mob_list=list() + for(var/mob/living/M in viewers(src)) + mob_list |= M + + if(mob_list.len) + L = pick(mob_list) + + var/mob/living/simple_animal/random_mob = pick(existing_typesof(/mob/living/simple_animal/hostile)) + var/image/horror = image(icon = null) + horror.appearance = initial(random_mob.appearance) + + horror.loc = L + horror.override = 1 //Override the affected mob's appearance with the monster + + var/client/C = src.client //Get client of the hallucinating mob + if(C) + C.images += horror //Give it the image! + + var/duration = rand(60 SECONDS, 120 SECONDS) + if(src.client) + message_admins("[key_name(src)] just imagined that [L] looks like a [random_mob], spooky! [formatJumpTo(get_turf(src))]") + spawn(duration) + if(C) + C.images.Remove(horror) //Remove the image from hallucinating mob + + if(88) //Turns your screen var/angle = rand(1,3)*90 var/duration = rand(10 SECONDS, 40 SECONDS) diff --git a/code/modules/food/cooking_machines.dm b/code/modules/food/cooking_machines.dm index b7e64e8238f..9e48cac07c5 100644 --- a/code/modules/food/cooking_machines.dm +++ b/code/modules/food/cooking_machines.dm @@ -250,7 +250,7 @@ var/global/ingredientLimit = 10 src.icon_state = src.icon_state_on if (cook_after(src.cookTime, 25)) src.makeFood(foodType) - playsound(get_turf(src),src.cookSound,100,1) + playsound(src,src.cookSound,100,1) src.active = 0 src.icon_state = initial(src.icon_state) return @@ -400,7 +400,7 @@ var/global/ingredientLimit = 10 reagents.update_total() //make the values refresh if(ingredient) icon_state = "fryer_on" - playsound(get_turf(src),'sound/machines/deep_fryer.ogg',100,1) // If cookSound is used, the sound starts when the cooking ends. We don't want that. + playsound(src,'sound/machines/deep_fryer.ogg',100,1) // If cookSound is used, the sound starts when the cooking ends. We don't want that. else if(reagents.total_volume < DEEPFRY_MINOIL) icon_state = "fryer_empty" else @@ -469,7 +469,7 @@ var/global/ingredientLimit = 10 //Deepfry a random nearby item var/list/pickable_items = list() - for(var/obj/item/I in range(1, L)) + for(var/obj/item/I in adjacent_atoms(L)) pickable_items.Add(I) if(!pickable_items.len) @@ -531,7 +531,7 @@ var/global/ingredientLimit = 10 reagents.update_total() //make the values refresh if(ingredient) icon_state = "confectionator_on" - playsound(get_turf(src),'sound/machines/juicer.ogg',100,1) // If cookSound is used, the sound starts when the cooking ends. We don't want that. + playsound(src,'sound/machines/juicer.ogg',100,1) // If cookSound is used, the sound starts when the cooking ends. We don't want that. else if(reagents.total_volume < CONFECTIONATOR_MINSUGAR) icon_state = "confectionator_empty" else @@ -606,7 +606,7 @@ var/global/ingredientLimit = 10 if (cook_after(src.cookTime/3, 14)) src.makeFood() if(use_power) - playsound(get_turf(src),src.cookSound,100,1) + playsound(src,src.cookSound,100,1) else src.visible_message("\the [foodname] looks ready to eat!") src.icon_state = initial(src.icon_state) diff --git a/code/modules/food/recipes_microwave.dm b/code/modules/food/recipes_microwave.dm index f7983d79cc3..b25538e9362 100644 --- a/code/modules/food/recipes_microwave.dm +++ b/code/modules/food/recipes_microwave.dm @@ -2432,4 +2432,157 @@ /obj/item/weapon/fish/electric_eel ) - result = /obj/item/weapon/reagent_containers/food/snacks/sushi_Unagi \ No newline at end of file + result = /obj/item/weapon/reagent_containers/food/snacks/sushi_Unagi + +/datum/recipe/sushi_avocado + items = list(/obj/item/weapon/reagent_containers/food/snacks/boiledrice, + /obj/item/weapon/reagent_containers/food/snacks/grown/avocado/cut/pitted + ) + + result = /obj/item/weapon/reagent_containers/food/snacks/sushi_avocado + +/datum/recipe/friedshrimp + reagents = list(CORNOIL = 5) + items = list(/obj/item/weapon/reagent_containers/food/snacks/shrimp + ) + + result = /obj/item/weapon/reagent_containers/food/snacks/friedshrimp + +/datum/recipe/soyscampi + reagents = list(SOYSAUCE = 5) + items = list(/obj/item/weapon/reagent_containers/food/snacks/shrimp + ) + + result = /obj/item/weapon/reagent_containers/food/snacks/soyscampi + +/datum/recipe/shrimpcocktail + reagents = list(KETCHUP = 10) + items = list(/obj/item/weapon/reagent_containers/food/snacks/shrimp, + /obj/item/weapon/reagent_containers/food/snacks/grown/lemon + ) + + result = /obj/item/weapon/reagent_containers/food/snacks/shrimpcocktail + +/datum/recipe/friedcatfish + reagents = list(CORNOIL = 5) + items = list(/obj/item/weapon/reagent_containers/food/snacks/catfishmeat + ) + + result = /obj/item/weapon/reagent_containers/food/snacks/friedcatfish + +/datum/recipe/gumbo + reagents = list(WATER = 10) + items = list(/obj/item/weapon/reagent_containers/food/snacks/catfishmeat, + /obj/item/weapon/reagent_containers/food/snacks/grown/garlic + ) + + result = /obj/item/weapon/reagent_containers/food/snacks/catfishgumbo + +/datum/recipe/catfishcourtbouillon + reagents = list(CAPSAICIN = 5, FLOUR = 5) + items = list(/obj/item/weapon/reagent_containers/food/snacks/catfishmeat + ) + + result = /obj/item/weapon/reagent_containers/food/snacks/catfishcourtbouillon + +/datum/recipe/smokedsalmon + reagents = list(BLACKPEPPER = 1) + items = list(/obj/item/weapon/reagent_containers/food/snacks/salmonmeat, + /obj/item/weapon/reagent_containers/food/snacks/grown/chili + ) + + result = /obj/item/weapon/reagent_containers/food/snacks/smokedsalmon + +/datum/recipe/planksalmon + reagents = list(HONEY = 5) + items = list(/obj/item/weapon/reagent_containers/food/snacks/salmonmeat, + /obj/item/stack/sheet/wood + ) + + result = /obj/item/weapon/reagent_containers/food/snacks/planksalmon + +/datum/recipe/citrussalmon + reagents = list(BLACKPEPPER = 1) + items = list(/obj/item/weapon/reagent_containers/food/snacks/salmonmeat, + /obj/item/weapon/reagent_containers/food/snacks/grown/lemon, + /obj/item/weapon/reagent_containers/food/snacks/grown/orange + ) + + result = /obj/item/weapon/reagent_containers/food/snacks/citrussalmon + +/datum/recipe/salmonavocado + items = list(/obj/item/weapon/reagent_containers/food/snacks/salmonmeat, + /obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/chanterelle, + /obj/item/weapon/reagent_containers/food/snacks/grown/avocado/cut/pitted + ) + + result = /obj/item/weapon/reagent_containers/food/snacks/salmonavocado + +/datum/recipe/rumshark + reagents = list(BLACKPEPPER = 15, RUM = 15) + items = list(/obj/item/weapon/fish/toothless_shark, + /obj/item/weapon/reagent_containers/food/snacks/grown/garlic + ) + + result = /obj/item/weapon/reagent_containers/food/snacks/rumshark + +/datum/recipe/akutaq + reagents = list(MILK = 10) + items = list(/obj/item/weapon/reagent_containers/food/snacks/glofishmeat, + /obj/item/weapon/reagent_containers/food/snacks/grown/glowberries + ) + + result = /obj/item/weapon/reagent_containers/food/snacks/akutaq + +/datum/recipe/carpcurry + reagents = list(VINEGAR = 5, RICE = 10) + items = list(/obj/item/weapon/reagent_containers/food/snacks/goldfishmeat + ) + + result = /obj/item/weapon/reagent_containers/food/snacks/carpcurry + +/datum/recipe/carpconsomme + reagents = list(WATER = 10) + items = list(/obj/item/weapon/reagent_containers/food/snacks/goldfishmeat, + /obj/item/weapon/reagent_containers/food/snacks/egg + ) + + result = /obj/item/weapon/reagent_containers/food/snacks/carpconsomme + +/datum/recipe/butterstick + items = list(/obj/item/weapon/reagent_containers/food/snacks/butter, + /obj/item/stack/rods + ) + result = /obj/item/weapon/reagent_containers/food/snacks/butterstick + +/datum/recipe/ambrosia_brownies + reagents = list(COCO = 10, SUGAR = 10, FLOUR = 15) + items = list(/obj/item/weapon/reagent_containers/food/snacks/butter, + /obj/item/weapon/reagent_containers/food/snacks/egg, + /obj/item/weapon/reagent_containers/food/snacks/egg, + /obj/item/weapon/reagent_containers/food/snacks/grown/ambrosiavulgaris, + /obj/item/weapon/reagent_containers/food/snacks/grown/ambrosiavulgaris, + ) + + result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/ambrosia_brownies + +/datum/recipe/butterfingers_r + items = list(/obj/item/organ/external/r_hand, + /obj/item/weapon/reagent_containers/food/snacks/butter, + ) + + result = /obj/item/weapon/reagent_containers/food/snacks/butterfingers_r/ + +/datum/recipe/butterfingers_l + items = list(/obj/item/organ/external/l_hand, + /obj/item/weapon/reagent_containers/food/snacks/butter, + ) + + result = /obj/item/weapon/reagent_containers/food/snacks/butterfingers_l/ + +/datum/recipe/butteredtoast + reagents = list(LIQUIDBUTTER = 2) + items = list(/obj/item/weapon/reagent_containers/food/snacks/breadslice, + ) + + result = /obj/item/weapon/reagent_containers/food/snacks/butteredtoast \ No newline at end of file diff --git a/code/modules/games/cards/wizard_cards.dm b/code/modules/games/cards/wizard_cards.dm index 698c32d541e..5e054ae4ae3 100644 --- a/code/modules/games/cards/wizard_cards.dm +++ b/code/modules/games/cards/wizard_cards.dm @@ -100,7 +100,7 @@ var/global/list/wizard_cards_normal = list( to_chat(user, "Honkmother is not ready yet!") return - playsound(get_turf(src), 'sound/items/AirHorn.ogg', 50, 1) + playsound(src, 'sound/items/AirHorn.ogg', 50, 1) /obj/item/toy/singlecard/wizard/legendary/honkmother/pickup(mob/living/user as mob) if(user.mind && user.mind.assigned_role == "Clown") @@ -139,7 +139,7 @@ var/global/list/wizard_cards_normal = list( to_chat(user, "The clown is not ready yet!") return - playsound(get_turf(src), 'sound/items/bikehorn.ogg', 50, 1) + playsound(src, 'sound/items/bikehorn.ogg', 50, 1) /obj/item/toy/singlecard/wizard/bomberman name = "bomberman wizard card" diff --git a/code/modules/html_interface/map/station_map.dm b/code/modules/html_interface/map/station_map.dm index b679b6a8d15..6795fc5124d 100644 --- a/code/modules/html_interface/map/station_map.dm +++ b/code/modules/html_interface/map/station_map.dm @@ -30,8 +30,10 @@ //Station Holomaps display the map of the Z-Level they were built on. generateStationMinimap(map.zMainStation) - generateStationMinimap(map.zAsteroid) - generateStationMinimap(map.zDerelict) + if(world.maxz >= map.zAsteroid) + generateStationMinimap(map.zAsteroid) + if(world.maxz >= map.zDerelict) + generateStationMinimap(map.zDerelict) //If they were built on another Z-Level, they will display an error screen. holomaps_initialized = 1 diff --git a/code/modules/html_interface/voting/voting.dm b/code/modules/html_interface/voting/voting.dm index d4532cafd21..b04e284ebea 100644 --- a/code/modules/html_interface/voting/voting.dm +++ b/code/modules/html_interface/voting/voting.dm @@ -37,6 +37,7 @@ var/global/datum/controller/vote/vote = new() var/list/voted = list() var/list/voting = list() var/list/current_votes = list() + var/list/discarded_choices = list() var/list/ismapvote var/chosen_map name = "datum" @@ -47,6 +48,8 @@ var/global/datum/controller/vote/vote = new() var/initialized = 0 var/lastupdate = 0 var/total_votes = 0 + var/vote_threshold = 0.15 + var/discarded_votes = 0 var/weighted = FALSE // Whether to use weighted voting. // Jesus fuck some shitcode is breaking because it's sleeping and the SS doesn't like it. @@ -106,6 +109,8 @@ var/global/datum/controller/vote/vote = new() voted.len = 0 voting.len = 0 total_votes = 0 + discarded_votes = 0 + discarded_choices.len = 0 current_votes.len = 0 weighted = FALSE update(1) @@ -156,6 +161,11 @@ var/global/datum/controller/vote/vote = new() for(var/a in filteredchoices) if(!filteredchoices[a]) filteredchoices -= a //Remove choices with 0 votes, as pickweight gives them 1 vote + continue + if(filteredchoices[a] / total_votes < vote_threshold) + discarded_votes += filteredchoices[a] + filteredchoices -= a + discarded_choices += a if(filteredchoices.len) . += pickweight(filteredchoices.Copy()) else @@ -171,6 +181,7 @@ var/global/datum/controller/vote/vote = new() var/list/winners = get_result() var/text var/feedbackanswer + var/qualified_votes = total_votes - discarded_votes if(winners.len > 0) if(winners.len > 1) text = "Vote Tied Between:
    " @@ -185,11 +196,11 @@ var/global/datum/controller/vote/vote = new() else feedback_set("map vote tie", "[feedbackanswer] chosen: [.]") - text += "[weighted ? "Random Weighted " : ""]Vote Result: [.] won with [choices[.]] vote\s[weighted? " and a [round(100*choices[.]/total_votes)]% chance of winning" : null]." + text += "[weighted ? "Random Weighted " : ""]Vote Result: [.] won with [choices[.]] vote\s[weighted? " and a [round(100*choices[.]/qualified_votes)]% chance of winning" : null]." for(var/choice in choices) if(. == choice) continue - text += "
    \t [choice] had [choices[choice] != null ? choices[choice] : "0"] vote\s[(weighted&&choices[choice])? " and a [round(100*choices[choice]/total_votes)]% chance of winning" : null]." + text += "
    \t [choice] had [choices[choice] != null ? choices[choice] : "0"] vote\s[(weighted&&choices[choice])? " and [(choice in discarded_choices) ? "did not get enough votes to qualify" : "a [round(100*choices[choice]/qualified_votes)]% chance of winning"]" : null]." else text += "Vote Result: Inconclusive - No Votes!" log_vote(text) diff --git a/code/modules/hydroponics/eggincubator.dm b/code/modules/hydroponics/eggincubator.dm index e1385be9174..e9015a23b77 100644 --- a/code/modules/hydroponics/eggincubator.dm +++ b/code/modules/hydroponics/eggincubator.dm @@ -106,7 +106,7 @@ use_power = 2 update_icon() if(handle_growth(contents)) - playsound(get_turf(src), 'sound/machines/ding.ogg', 50, 1) //Only ding once per process + playsound(src, 'sound/machines/ding.ogg', 50, 1) //Only ding once per process src.updateUsrDialog() diff --git a/code/modules/hydroponics/hydro_tools.dm b/code/modules/hydroponics/hydro_tools.dm index a808c0c0dee..27e7ef9fe1e 100644 --- a/code/modules/hydroponics/hydro_tools.dm +++ b/code/modules/hydroponics/hydro_tools.dm @@ -325,6 +325,8 @@ force = 5.0 throwforce = 7.0 w_class = W_CLASS_SMALL + starting_materials = list(MAT_IRON = 50) + w_type = RECYK_METAL attack_verb = list("slashes", "slices", "cuts", "claws") @@ -418,6 +420,8 @@ siemens_coefficient = 1 force = 12.0 w_class = W_CLASS_SMALL + starting_materials = list(MAT_IRON = 5000) + w_type = RECYK_METAL throwforce = 15.0 throw_speed = 4 throw_range = 4 diff --git a/code/modules/hydroponics/hydro_tray.dm b/code/modules/hydroponics/hydro_tray.dm index 24f9f60f840..51f186bea39 100644 --- a/code/modules/hydroponics/hydro_tray.dm +++ b/code/modules/hydroponics/hydro_tray.dm @@ -512,13 +512,13 @@ /obj/machinery/portable_atmospherics/hydroponics/HasProximity(mob/living/simple_animal/M) if(seed && !dead && seed.carnivorous == 2 && age > seed.maturation) - if(istype(M, /mob/living/simple_animal/mouse) || istype(M, /mob/living/simple_animal/lizard) && !M.locked_to && !M.anchored) + if(istype(M, /mob/living/simple_animal/mouse) || istype(M, /mob/living/simple_animal/hostile/lizard) && !M.locked_to && !M.anchored) spawn(10) if(!M || !Adjacent(M) || M.locked_to || M.anchored) return // HasProximity() will likely fire a few times almost simultaneously, so spawn() is tricky with it's sanity visible_message("\The [seed.display_name] hungrily lashes a vine at \the [M]!") if(M.health > 0) - M.Die() + M.death() lock_atom(M, /datum/locking_category/hydro_tray) spawn(30) if(M && M.loc == get_turf(src)) @@ -555,4 +555,7 @@ ..() +/obj/machinery/portable_atmospherics/hydroponics/AltClick() + close_lid() + /datum/locking_category/hydro_tray diff --git a/code/modules/hydroponics/hydro_tray_process.dm b/code/modules/hydroponics/hydro_tray_process.dm index d804b175309..7d8f04df5e1 100644 --- a/code/modules/hydroponics/hydro_tray_process.dm +++ b/code/modules/hydroponics/hydro_tray_process.dm @@ -176,17 +176,11 @@ for(var/gas in seed.exude_gasses) environment.adjust_gas(gas, max(1,round((seed.exude_gasses[gas]*round(seed.potency))/seed.exude_gasses.len))) - // This was adapted from the air alarm code - // I've never done atmos or touched atmos code before so there's a chance I've fucked this up if(seed.alter_temp) - if(istype(T, /turf/simulated/)) - var/datum/gas_mixture/room = T.remove_air(environment.total_moles) - if(room.temperature < seed.ideal_heat-seed.heat_tolerance) - room.temperature += (seed.potency*3) - else if (room.temperature > seed.ideal_heat+seed.heat_tolerance) - room.temperature -= (seed.potency*3) - room.react() - T.assume_air(room) + if((environment.temperature < seed.ideal_heat - seed.heat_tolerance) || (environment.temperature > seed.ideal_heat + seed.heat_tolerance)) + var/energy_cap = seed.potency * 60 * MOLES_CELLSTANDARD //This is totally arbitrary. It just serves to approximate the behavior from when this modified temperature rather than thermal energy. + var/energy_change = Clamp(environment.get_thermal_energy_change(seed.ideal_heat), -energy_cap, energy_cap) + environment.add_thermal_energy(energy_change) // If we're attached to a pipenet, then we should let the pipenet know we might have modified some gasses //if (closed_system && connected_port) diff --git a/code/modules/hydroponics/seed_machines.dm b/code/modules/hydroponics/seed_machines.dm index 12038dd82c1..d65cd9a4a33 100644 --- a/code/modules/hydroponics/seed_machines.dm +++ b/code/modules/hydroponics/seed_machines.dm @@ -42,6 +42,18 @@ var/eject_disk = 0 var/failed_task = 0 var/disk_needs_genes = 0 + var/time_coeff = 1 + var/degradation_coeff = 1 + +/obj/machinery/botany/RefreshParts() + var/T = 0 + for(var/obj/item/weapon/stock_parts/micro_laser/ML in component_parts) + T += ML.rating + degradation_coeff = round(T/2) + T = 0 + for(var/obj/item/weapon/stock_parts/manipulator/MA in component_parts) + T += MA.rating + time_coeff = T /obj/machinery/botany/process() @@ -49,7 +61,7 @@ if(!active) return - if(world.time > last_action + action_time) + if(world.time > last_action + action_time/time_coeff) finished_task() /obj/machinery/botany/attack_paw(mob/user as mob) @@ -143,6 +155,8 @@ /obj/item/weapon/stock_parts/matter_bin, ) + RefreshParts() + /obj/machinery/botany/extractor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = NANOUI_FOCUS) if(!user) @@ -263,7 +277,7 @@ loaded_disk.desc += " The label reads 'gene [href_list["get_gene"]], sampled from [genetics.display_name]'." eject_disk = 1 - degradation += rand(20,60) + degradation += round(rand(20,60)/degradation_coeff) if(degradation >= 100) failed_task = 1 genetics = null @@ -296,6 +310,9 @@ /obj/item/weapon/stock_parts/console_screen, ) + RefreshParts() + + /obj/machinery/botany/editor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = NANOUI_FOCUS) if(!user) @@ -363,7 +380,7 @@ for(var/datum/plantgene/gene in loaded_disk.genes) loaded_seed.seed.apply_gene(gene, mode) - loaded_seed.modified += rand(5,10) + loaded_seed.modified += round(rand(5,10)/degradation_coeff) else if(href_list["toggle_mode"]) switch(mode) diff --git a/code/modules/hydroponics/seed_mobs.dm b/code/modules/hydroponics/seed_mobs.dm index d23ab334ee3..1de889f5d8a 100644 --- a/code/modules/hydroponics/seed_mobs.dm +++ b/code/modules/hydroponics/seed_mobs.dm @@ -1,5 +1,6 @@ /datum/seed var/product_requires_player // If yes, product will ask for a player among the ghosts. + var/product_kill_inactive = TRUE // If yes, the product will autodie after a certain amount of time var/list/currently_querying // Used to avoid asking the same ghost repeatedly. var/searching = 0 // Are we currently looking for a ghost? @@ -14,18 +15,19 @@ currently_querying = list() request_player(host) - spawn(675) - if(!host.ckey && !host.client) - host.death() // This seems redundant, but a lot of mobs don't - host.stat = 2 // handle death() properly. Better safe than etc. - host.visible_message("[host] is malformed and unable to survive. It expires pitifully, leaving behind some seeds.") + if(product_kill_inactive) + spawn(675) + if(!host.ckey && !host.client) + host.death() // This seems redundant, but a lot of mobs don't + host.stat = 2 // handle death() properly. Better safe than etc. + host.visible_message("[host] is malformed and unable to survive. It expires pitifully, leaving behind some seeds.") - if(mob_drop) - new mob_drop(get_turf(host)) - else - var/obj/item/seeds/S = new(get_turf(host)) - S.seed_type = name - S.update_seed() + if(mob_drop) + new mob_drop(get_turf(host)) + else + var/obj/item/seeds/S = new(get_turf(host)) + S.seed_type = name + S.update_seed() //poll="Someone is harvesting [display_name]. Would you like to play as one?" diff --git a/code/modules/hydroponics/seeds.dm b/code/modules/hydroponics/seeds.dm index 1c80f586ad0..38436acbeba 100644 --- a/code/modules/hydroponics/seeds.dm +++ b/code/modules/hydroponics/seeds.dm @@ -64,6 +64,11 @@ seed_type = "diona" vending_cat = "sentient" +/obj/item/seeds/mushroommanspore + name = "packet of mushrom spores" + seed_type = "moshrum" + vending_cat = "sentient" + /obj/item/seeds/poppyseed name = "packet of poppy seeds" seed_type = "poppies" @@ -120,6 +125,11 @@ seed_type = "banana" vending_cat = "fruits" +/obj/item/seeds/bluespacebananaseed + name = "packet of bluespace banana seeds" + seed_type = "bluespacebanana" + vending_cat = "fruits" + /obj/item/seeds/eggplantseed name = "packet of eggplant seeds" seed_type = "eggplant" @@ -890,11 +900,11 @@ products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/angel) packet_icon = "mycelium-angel" plant_icon = "angel" - chems = list(NUTRIMENT = list(1,50), AMATOXIN = list(13,3), PSILOCYBIN = list(1,25)) + chems = list(NUTRIMENT = list(1,50), AMANATIN = list(1,3)) maturation = 12 yield = 2 - potency = 35 + potency = 15 /datum/seed/mushroom/towercap name = "towercap" @@ -1162,6 +1172,7 @@ plant_icon = "banana" harvest_repeat = 1 chems = list(BANANA = list(1,10), POTASSIUMCARBONATE = list(0.1,30)) + mutants = list("bluespacebanana") lifespan = 50 maturation = 6 @@ -1171,6 +1182,15 @@ water_consumption = 6 ideal_heat = 298 +/datum/seed/banana/bluespace + name = "bluespacebanana" + seed_name = "bluespacebanana" + display_name = "bluespace banana tree" + packet_icon = "seed-bluespacebanana" + products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/bluespacebanana) + plant_icon = "banana" + mutants = null + /datum/seed/corn name = "corn" seed_name = "corn" @@ -1566,6 +1586,28 @@ yield = 10 potency = 30 +/datum/seed/moshrum + name = "moshrum" + seed_name = "moshrum" + seed_noun = "nodules" + display_name = "moshrum nodes" + packet_icon = "mycelium-walkingmushroom" + plant_icon = "walkingmushroom" + products = list(/mob/living/carbon/monkey/mushroom) + mob_drop = /obj/item/seeds/mushroommanspore + product_requires_player = TRUE + product_kill_inactive = FALSE + immutable = TRUE + + lifespan = 50 + endurance = 35 + maturation = 5 + production = 10 + yield = 2 + potency = 30 + ideal_light = 0 + + /datum/seed/test name = "test" seed_name = "testing" diff --git a/code/modules/library/computers/checkout.dm b/code/modules/library/computers/checkout.dm index bf25e44d1b8..ab428d93de8 100644 --- a/code/modules/library/computers/checkout.dm +++ b/code/modules/library/computers/checkout.dm @@ -315,14 +315,29 @@ if("6") if(!bibledelay) - var/obj/item/weapon/storage/bible/B = new /obj/item/weapon/storage/bible(src.loc) - if(ticker && ( ticker.Bible_icon_state && ticker.Bible_item_state) ) + bibledelay = 1 + + var/obj/item/weapon/storage/bible/B = new + B = new(src.loc) + if (usr.mind && usr.mind.faith) // The user has a faith + var/datum/religion/R = usr.mind.faith + var/obj/item/weapon/storage/bible/HB = R.holy_book + if (!HB) + B = chooseBible(R, usr) + else + B.icon_state = HB.icon_state + B.item_state = HB.item_state + B.name = R.bible_name + B.my_rel = R + + else if (ticker && (ticker.Bible_icon_state && ticker.Bible_item_state)) // No faith B.icon_state = ticker.Bible_icon_state B.item_state = ticker.Bible_item_state B.name = ticker.Bible_name - B.my_rel.deity_name = ticker.Bible_deity_name + B.my_rel = ticker.chap_rel + + B.forceMove(src.loc) - bibledelay = 1 spawn(60) bibledelay = 0 diff --git a/code/modules/library/lib_items.dm b/code/modules/library/lib_items.dm index dd3196c517e..a22df0450a7 100644 --- a/code/modules/library/lib_items.dm +++ b/code/modules/library/lib_items.dm @@ -54,13 +54,13 @@ to_chat(user, "There are no screws on \the [src], it appears to be nailed together. You could probably disassemble it with just a crowbar.") return else if(iscrowbar(O) && user.a_intent == I_HELP) //Only way to deconstruct, needs help intent - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 75, 1) + playsound(src, 'sound/items/Crowbar.ogg', 75, 1) user.visible_message("[user] starts disassembling \the [src].", \ "You start disassembling \the [src].") busy = 1 if(do_after(user, src, 50)) - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 75, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 75, 1) user.visible_message("[user] disassembles \the [src].", \ "You disassemble \the [src].") busy = 0 @@ -72,7 +72,7 @@ return else if(iswrench(O)) anchored = !anchored - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + playsound(src, 'sound/items/Ratchet.ogg', 50, 1) user.visible_message("[user] [anchored ? "":"un"]anchors \the [src] [anchored ? "to":"from"] the floor.", \ "You [anchored ? "":"un"]anchor the [src] [anchored ? "to":"from"] the floor.") else if(istype(O, /obj/item/weapon/pen)) diff --git a/code/modules/maps/nests.dm b/code/modules/maps/nests.dm index 6339a62caa6..37766ac4a58 100644 --- a/code/modules/maps/nests.dm +++ b/code/modules/maps/nests.dm @@ -37,7 +37,7 @@ /obj/abstract/map/nest/lizard name = "lizard breeding ground" icon_state = "lizard" - mob_type = /mob/living/simple_animal/lizard + mob_type = /mob/living/simple_animal/hostile/lizard /obj/abstract/map/nest/mouse name = "mouse breeding ground" @@ -56,6 +56,11 @@ mob_type = /mob/living/simple_animal/hostile/giant_spider pop_max = 10 +/obj/abstract/map/nest/spider/limited + name = "spider breeding ground" + pop = 2 + pop_max = 2 + /obj/abstract/map/nest/carp name = "carp breeding ground" icon_state = "carp" diff --git a/code/modules/maps/spawners/spawners.dm b/code/modules/maps/spawners/spawners.dm index 4f88548996c..8831cd832bb 100644 --- a/code/modules/maps/spawners/spawners.dm +++ b/code/modules/maps/spawners/spawners.dm @@ -207,7 +207,6 @@ /obj/machinery/vending/sovietsoda, /obj/structure/AIcore, /obj/structure/piano, - /obj/structure/displaycase_frame, /obj/structure/particle_accelerator/fuel_chamber, /obj/structure/reagent_dispensers/fueltank, /obj/structure/reagent_dispensers/water_cooler, @@ -604,6 +603,7 @@ /obj/item/device/powersink, /obj/item/weapon/gun/projectile/flamethrower/full, /obj/item/weapon/gun/projectile/deagle/gold, + /obj/item/clothing/shoes/magboots/magnificent, /obj/item/weapon/gun/projectile/russian, ) @@ -853,7 +853,7 @@ icon_state = "mob_lizard" amount = 2 chance = 50 - to_spawn = list(/mob/living/simple_animal/lizard) + to_spawn = list(/mob/living/simple_animal/hostile/lizard) /obj/abstract/map/spawner/mobs/mouse name = "mouse spawner" @@ -904,14 +904,52 @@ /obj/abstract/map/spawner/mobs/medivault name = "medivault spawner" icon_state = "mob_medivault" - chance = 50 + chance = 60 to_spawn = list( - /mob/living/simple_animal/hostile/monster/cyber_horror/Tajaran, - /mob/living/simple_animal/hostile/monster/cyber_horror, /mob/living/simple_animal/hostile/necro/skeleton, + /mob/living/simple_animal/hostile/necro/skeleton, + /mob/living/simple_animal/hostile/necro/skeleton, + /mob/living/simple_animal/hostile/necro/zombie/leatherman, + /mob/living/simple_animal/hostile/necro/zombie/ghoul, + /mob/living/simple_animal/hostile/necro/zombie/ghoul, + /mob/living/simple_animal/hostile/necro/zombie/ghoul, + /mob/living/simple_animal/hostile/necro/zombie, + /mob/living/simple_animal/hostile/necro/zombie, + /mob/living/simple_animal/hostile/necro/zombie, /mob/living/simple_animal/hostile/necro/zombie, ) +/obj/abstract/map/spawner/misc/medivault + name = "medivault loot spawner" + icon_state = "loot_medivault" + chance = 80 + amount = 1 + jiggle = 5 + to_spawn = list(/obj/item/weapon/dnainjector/nofail/polymorph, + /obj/item/weapon/dnainjector/nofail/polymorph, + /obj/item/weapon/dnainjector/nofail/telemut, + /obj/item/weapon/dnainjector/nofail/telemut, + /obj/item/weapon/dnainjector/nofail/randompower, + /obj/item/weapon/dnainjector/nofail/randompower, + /obj/item/weapon/dnainjector/nofail/randompower, + /obj/item/weapon/dnainjector/nofail/hulkmut, + /obj/item/weapon/dnainjector/nofail/nobreath, + /obj/item/weapon/dnainjector/nofail/nobreath, + /obj/item/weapon/storage/firstaid/adv, + /obj/item/weapon/storage/firstaid/adv, + /obj/item/weapon/storage/firstaid/adv, + /obj/item/weapon/storage/pill_bottle/hyperzine, + /obj/item/weapon/storage/pill_bottle/hyperzine, + /obj/item/weapon/reagent_containers/glass/beaker/mednanobots, + /obj/item/weapon/reagent_containers/glass/beaker/mednanobots, + /obj/item/weapon/gun/energy/laser/smart, + /obj/item/weapon/gun/energy/laser/pistol, + /obj/item/weapon/gun/energy/laser/pistol, + /obj/item/weapon/gun/projectile/shotgun/pump/combat, + + +) + // Robutts ///////////////////////////////////////////////////// /obj/abstract/map/spawner/robot/any @@ -1100,6 +1138,7 @@ /obj/item/mounted/frame/painting ) + /obj/abstract/map/spawner/safe/medical name = "safe medical spawner" icon_state = "safe" diff --git a/code/modules/media/broadcast/receivers/radio.dm b/code/modules/media/broadcast/receivers/radio.dm index 3d33befcebf..9f4d32a405c 100644 --- a/code/modules/media/broadcast/receivers/radio.dm +++ b/code/modules/media/broadcast/receivers/radio.dm @@ -99,8 +99,12 @@ volume=0.25 // 25% of user's set volume. var/buildstage = 0 - holomap = TRUE - auto_holomap = TRUE +/obj/machinery/media/receiver/boombox/wallmount/supports_holomap() + return TRUE + +/obj/machinery/media/receiver/boombox/wallmount/initialize() + ..() + add_self_to_holomap() /obj/machinery/media/receiver/boombox/wallmount/New(turf/loc,var/ndir=0,var/building=2) ..() @@ -139,7 +143,7 @@ if(SYSTEMISDONE) if(iscrowbar(W)) to_chat(user, "You pry the cover off [src].") - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) if(do_after(user, src, 10) && buildstage==SYSTEMISDONE) on = 0 buildstage = SYSTEMISKINDADONE @@ -149,7 +153,7 @@ return ..() if(SYSTEMISKINDADONE) if(isscrewdriver(W)) - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 50, 1) if(do_after(user, src, 10) && buildstage==SYSTEMISKINDADONE) on = 1 buildstage = SYSTEMISDONE @@ -158,7 +162,7 @@ update_on(TRUE) return 1 else if(iswirecutter(W)) - playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 50, 1) + playsound(src, 'sound/items/Wirecutter.ogg', 50, 1) if(do_after(user, src, 10) && buildstage==SYSTEMISKINDADONE) getFromPool(/obj/item/stack/cable_coil,get_turf(src),5) buildstage = SYSTEMISNOTDONE @@ -177,7 +181,7 @@ return 1 if(iswrench(W)) to_chat(user, "You remove the securing bolts...") - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + playsound(src, 'sound/items/Ratchet.ogg', 50, 1) if(do_after(user, src, 10) && buildstage==SYSTEMISNOTDONE) new /obj/item/mounted/frame/soundsystem(get_turf(src)) to_chat(user, "The frame pops off.") @@ -186,7 +190,8 @@ return 0 /obj/machinery/media/receiver/boombox/wallmount/proc/relay_area_configuration() - for(var/obj/machinery/media/receiver/boombox/wallmount/W in areaMaster) + var/area/this_area = get_area(src) + for(var/obj/machinery/media/receiver/boombox/wallmount/W in this_area) W.on = src.on W.media_frequency=src.media_frequency W.volume = src.volume diff --git a/code/modules/media/broadcast/transmitter.dm b/code/modules/media/broadcast/transmitter.dm index 92c37f9d917..fab68b5acf6 100644 --- a/code/modules/media/broadcast/transmitter.dm +++ b/code/modules/media/broadcast/transmitter.dm @@ -34,6 +34,9 @@ var/global/media_transmitters=list() if(R.media_crypto == media_crypto) R.receive_broadcast(media_url,media_start_time) //testing("[src]: Sending music to [R]") + for(var/mob/living/carbon/complex/gondola/G in media_receivers[freq]) + if(G.media_crypto == media_crypto) + G.receive_broadcast(media_url,media_start_time) /obj/machinery/media/transmitter/proc/disconnect_frequency() var/list/transmitters=list() diff --git a/code/modules/media/broadcast/transmitters/broadcast.dm b/code/modules/media/broadcast/transmitters/broadcast.dm index d020a0c053f..8c9d6af4df2 100644 --- a/code/modules/media/broadcast/transmitters/broadcast.dm +++ b/code/modules/media/broadcast/transmitters/broadcast.dm @@ -54,7 +54,7 @@ for(var/obj/machinery/media/source in orange(20, src)) if(source.id_tag in autolink) sources.Add(source) - testing("Autolinked [source] -> [src]") + //testing("Autolinked [source] -> [src]") hook_media_sources() if(on) update_on() @@ -229,28 +229,14 @@ if(istype(L) && heating_power) var/datum/gas_mixture/env = L.return_air() if(env.temperature != MAX_TEMP + T0C) + var/energy_to_add - var/transfer_moles = 0.25 * env.total_moles() / env.volume * CELL_VOLUME + if(env.temperature < MAX_TEMP + T0C) + energy_to_add = min(heating_power, env.get_thermal_energy_change(1000)) //Added min() check to try and avoid wacky superheating issues in low gas scenarios -- TLE + else + energy_to_add = -heating_power //add_thermal_energy() automatically prevents the temperature from falling below TCMB, so a similar check here is unnecessary. - var/datum/gas_mixture/removed = env.remove(transfer_moles) - -// to_chat(world, "got [transfer_moles] moles at [removed.temperature]") - - if(removed) - - var/heat_capacity = removed.heat_capacity() -// to_chat(world, "heating ([heat_capacity])") - if(heat_capacity) // Added check to avoid divide by zero (oshi-) runtime errors -- TLE - if(removed.temperature < MAX_TEMP + T0C) - removed.temperature = min(removed.temperature + heating_power/heat_capacity, 1000) // Added min() check to try and avoid wacky superheating issues in low gas scenarios -- TLE - else - removed.temperature = max(removed.temperature - heating_power/heat_capacity, TCMB) - -// to_chat(world, "now at [removed.temperature]") - - env.merge(removed) - -// to_chat(world, "turf now at [env.temperature]") + env.add_thermal_energy(energy_to_add) // Checks heat from the environment and applies any integrity damage var/datum/gas_mixture/environment = loc.return_air() diff --git a/code/modules/media/jukebox.dm b/code/modules/media/jukebox.dm index 16b6cead602..f9ce3b4e88f 100644 --- a/code/modules/media/jukebox.dm +++ b/code/modules/media/jukebox.dm @@ -21,7 +21,7 @@ var/global/global_playlists = list() return for(var/playlist_id in list("bar", "jazz", "rock", "muzak", "emagged", "endgame", "clockwork", "vidyaone", "vidyatwo", "vidyathree", "vidyafour")) var/url="[config.media_base_url]/index.php?playlist=[playlist_id]" - testing("Updating playlist from [url]...") + //testing("Updating playlist from [url]...") // Media Server 2 requires a secret key in order to tell the jukebox // where the music files are. It's set in config with MEDIA_SECRET_KEY @@ -57,7 +57,7 @@ var/global/global_playlists = list() else var/url="[config.media_base_url]/index.php?playlist=[playlist_id]" - testing("[src] - Updating playlist from [url]...") + //testing("[src] - Updating playlist from [url]...") // Media Server 2 requires a secret key in order to tell the jukebox // where the music files are. It's set in config with MEDIA_SECRET_KEY @@ -351,7 +351,9 @@ var/global/list/loopModeNames=list( /obj/machinery/media/jukebox/proc/ScreenSettings(var/mob/user) if(!linked_account) linked_account = station_account - var/dat={"

    Settings

    + var/dat + + dat += {"

    Settings

    @@ -382,8 +384,12 @@ var/global/list/loopModeNames=list(
    - - "} + "} + + dat += "
    Media
    " + for(var/element in playlists) + dat += "[playlists[element]] Eject
    " + dat += "Insert Vinyl
    " return dat @@ -412,7 +418,8 @@ var/global/list/loopModeNames=list( visible_message("The machine buzzes, and flashes \"NOT ENOUGH FUNDS\" on the screen.","You hear a buzz.") return visible_message("The machine beeps happily.","You hear a beep.") - acct.charge(credits_needed,linked_account,"Song selection at [areaMaster.name]'s [name].") + var/area/this_area = get_area(src) + acct.charge(credits_needed,linked_account,"Song selection at [this_area.name]'s [name].") credits_needed = 0 successful_purchase() @@ -589,6 +596,20 @@ var/global/list/loopModeNames=list( update_music() update_icon() + if (href_list["insert"]) + if(isobserver(usr) && !canGhostWrite(usr,src,"")) + to_chat(usr, "You can't do that.") + return + var/obj/item/weapon/vinyl/V = usr.get_active_hand() + if(istype(V)) + insert(V) + + if (href_list["eject"]) + if(isobserver(usr) && !canGhostWrite(usr,src,"")) + to_chat(usr, "You can't do that.") + return + eject(href_list["eject"]) + if (href_list["song"]) if(wires.IsIndexCut(JUKE_CAPITAL)) to_chat(usr, "You select a song, but [src] is unresponsive...") @@ -648,6 +669,26 @@ var/global/list/loopModeNames=list( return update_music() +/obj/machinery/media/jukebox/proc/eject(var/playlist_name) + if(playlists.Find(playlist_name)) + new /obj/item/weapon/vinyl(get_turf(src), playlist_name, playlists[playlist_name]) + playlists.Remove(playlist_name) + if(playlist == playlist_name) + stop_playing() + playlist = playlists[1] + else + visible_message("[bicon(src)] \The [src] buzzes, unable to eject the vinyl.") + +/obj/machinery/media/jukebox/proc/insert(var/obj/O) + var/obj/item/weapon/vinyl/V = O + if(!istype(V)) + return + if(playlists.Find(V.unformatted)) + visible_message("[bicon(src)] \The [src] buzzes, rejecting the vinyl.") + else + playlists[V.unformatted] = V.formatted + qdel(V) + /obj/machinery/media/jukebox/update_music() if(!playlist) process() @@ -853,3 +894,88 @@ var/global/list/loopModeNames=list( /obj/machinery/media/jukebox/superjuke/adminbus/cultify() return + + +/obj/item/weapon/vinyl + name = "nanovinyl" + desc = "In reality, the bulk of the disc serves only decorative purposes and the many songs are recorded on a very small microchip near the center." + icon = 'icons/obj/jukebox.dmi' + icon_state = "vinyl" + flags = FPRINT + siemens_coefficient = 1 + sharpness = 1 + force = 7 + throwforce = 7 + throw_speed = 7 + throw_range = 7 + w_class = W_CLASS_SMALL + attack_verb = list("plays out", "records", "frisbees") //Fuck it, we'll do it live. Fucking thing sucks! + var/unformatted + var/formatted + +/obj/item/weapon/vinyl/New(loc,U,F) + ..(loc) + unformatted = U + formatted = F + name = "nanovinyl - [formatted]" + +//Premades +/obj/item/weapon/vinyl/vidyaone + name = "nanovinyl - video games, volume one" + unformatted = "vidyaone" + formatted = "Vidya Pt.1" + +/obj/item/weapon/vinyl/vidyatwo + name = "nanovinyl - video games, volume two" + unformatted = "vidyatwo" + formatted = "Vidya Pt.2" + +/obj/item/weapon/vinyl/vidyathree + name = "nanovinyl - video games, volume three" + unformatted = "vidyathree" + formatted = "Vidya Pt.3" + +/obj/item/weapon/vinyl/vidyafour + name = "nanovinyl - video games, volume four" + unformatted = "vidyafour" + formatted = "Vidya Pt.4" + +/obj/item/weapon/vinyl/jazz + name = "nanovinyl - jazz" + unformatted = "jazz" + formatted = "Jazz" + +/obj/item/weapon/vinyl/rock + name = "nanovinyl - rock" + unformatted = "rock" + formatted = "Rock" + +/obj/item/weapon/vinyl/muzak + name = "nanovinyl - muzak" + unformatted = "muzak" + formatted = "Muzak" + +/obj/item/weapon/vinyl/shuttle + name = "nanovinyl - shuttle" + unformatted = "shuttle" + formatted = "Shuttle" + +/obj/item/weapon/vinyl/syndie + name = "nanovinyl - syndicate" + unformatted = "emagged" + formatted = "Syndie Mix" + +/obj/item/weapon/vinyl/endgame + name = "nanovinyl - apocalypse" + unformatted = "endgame" + formatted = "Apocalypse" + +/obj/item/weapon/vinyl/clockwork + name = "nanovinyl - clockwork" + unformatted = "clockwork" + formatted = "Clockwork" + +/obj/item/weapon/vinyl/thunderdome + name = "nanovinyl - thunderdome" + unformatted = "thunderdome" + formatted = "Thunderdome" diff --git a/code/modules/media/machinery.dm b/code/modules/media/machinery.dm index ad7f8c28602..da21aecfc08 100644 --- a/code/modules/media/machinery.dm +++ b/code/modules/media/machinery.dm @@ -30,7 +30,7 @@ /obj/machinery/media/proc/update_music() // Broadcasting shit for(var/obj/machinery/media/transmitter/T in hooked) - testing("[src] Writing media to [T].") +// testing("[src] Writing media to [T].") T.broadcast(media_url,media_start_time) if(exclusive_hook) @@ -49,7 +49,7 @@ M.update_music() /obj/machinery/media/proc/update_media_source() - var/area/A = get_area_master(src) + var/area/A = get_area(src) if(!A) return // Check if there's a media source already. @@ -66,7 +66,7 @@ master_area=A /obj/machinery/media/proc/disconnect_media_source() - var/area/A = get_area_master(src) + var/area/A = get_area(src) // Sanity if(!A) diff --git a/code/modules/media/mediamanager.dm b/code/modules/media/mediamanager.dm index 3ce4fd206ec..317da17624a 100644 --- a/code/modules/media/mediamanager.dm +++ b/code/modules/media/mediamanager.dm @@ -193,7 +193,7 @@ to_chat(#define MP_DEBUG(x) owner, x) if (forced || !owner) return - var/area/A = get_area_master(mob) + var/area/A = get_area(mob) if(!A) //testing("[owner] in [mob.loc]. Aborting.") stop_music() diff --git a/code/modules/media/tapedeck.dm b/code/modules/media/tapedeck.dm index 0e9da82bbba..555c4cc664f 100644 --- a/code/modules/media/tapedeck.dm +++ b/code/modules/media/tapedeck.dm @@ -210,7 +210,7 @@ var/un = !anchored ? "" : "un" user.visible_message("[user.name] begins [un]locking \the [src.name]'s casters.","You begin [un]locking \the [src.name]'s casters.") if(do_after(user, src,30)) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + playsound(src, 'sound/items/Ratchet.ogg', 50, 1) anchored = !anchored user.visible_message("[user.name] [un]locks \the [src.name]'s casters.","You [un]lock \the [src.name]'s casters.") playing = emagged @@ -284,7 +284,7 @@ /obj/machinery/media/jukebox/process() if(!playlist && config.media_base_url) var/url="[config.media_base_url]/index.php?playlist=[playlist_id]" - testing("[src] - Updating playlist from [url]...") + //testing("[src] - Updating playlist from [url]...") var/response = world.Export(url) playlist=list() if(response) @@ -310,7 +310,7 @@ playing=1 autoplay=0 else - testing("[src] failed to update playlist: Response null.") + warning("[src] failed to update playlist: Response null.") stat &= BROKEN update_icon() return diff --git a/code/modules/medical/cloning.dm b/code/modules/medical/cloning.dm index 44d1a632a24..9356bd0f79d 100644 --- a/code/modules/medical/cloning.dm +++ b/code/modules/medical/cloning.dm @@ -216,7 +216,6 @@ if((G.mind && (G.mind.current.stat != DEAD) || G.mind != clonemind)) return FALSE - heal_level = rand(10,40) //Randomizes what health the clone is when ejected working = TRUE //One at a time!! locked = TRUE @@ -227,6 +226,7 @@ var/mob/living/carbon/human/H = new /mob/living/carbon/human(src, R.dna.species, delay_ready_dna = TRUE) occupant = H + H.times_cloned = R.times_cloned +1 if(!connected.emagged) icon_state = "pod_1" @@ -235,6 +235,9 @@ connected.update_icon() + if(isplasmaman(H)) + H.fire_sprite = "Plasmaman" + //Get the clone body ready H.dna = R.dna.Clone() H.dna.flavor_text = R.dna.flavor_text @@ -317,14 +320,15 @@ //Premature clones may have brain damage. occupant.adjustBrainLoss(-1*time_coeff) //Ditto above - //So clones don't die of oxyloss in a running pod. - if (occupant.reagents.get_reagent_amount(INAPROVALINE) < 30) - occupant.reagents.add_reagent(INAPROVALINE, 60) - var/mob/living/carbon/human/H = occupant - if(istype(H.species, /datum/species/vox) & occupant.reagents.get_reagent_amount(NITROGEN) < 30) - occupant.reagents.add_reagent(NITROGEN, 60) + if(isvox(H)) + if(occupant.reagents.get_reagent_amount(NITROGEN) < 30) + occupant.reagents.add_reagent(NITROGEN, 60) + + //So clones don't die of oxyloss in a running pod. + else if(occupant.reagents.get_reagent_amount(INAPROVALINE) < 30) //Done like this because inaprovaline is toxic to vox + occupant.reagents.add_reagent(INAPROVALINE, 60) //Also heal some oxyloss ourselves because inaprovaline is so bad at preventing it!! occupant.adjustOxyLoss(-4) @@ -391,7 +395,7 @@ to_chat(user, "System unlocked.") if (istype(W, /obj/item/weapon/reagent_containers/food/snacks/meat)) if(user.drop_item(W)) - playsound(get_turf(src), 'sound/machines/juicerfast.ogg', 30, 1) + playsound(src, 'sound/machines/juicerfast.ogg', 30, 1) to_chat(user, "\The [src] processes \the [W].") biomass += BIOMASS_CHUNK qdel(W) @@ -466,7 +470,7 @@ return if(isrobot(usr)) var/mob/living/silicon/robot/robit = usr - if(istype(robit) && !istype(robit.module, /obj/item/weapon/robot_module/medical)) + if(!(robit.module && (robit.module.quirk_flags & MODULE_CAN_HANDLE_MEDICAL))) to_chat(usr, "You do not have the means to do this!") return @@ -548,7 +552,7 @@ visible_message = TRUE // Prevent chatspam when multiple meat are near if(visible_message) - playsound(get_turf(src), 'sound/machines/juicer.ogg', 30, 1) + playsound(src, 'sound/machines/juicer.ogg', 30, 1) visible_message("[src] sucks in and processes the nearby biomass.") busy = FALSE @@ -557,7 +561,7 @@ if(occupant && prob(5)) visible_message("[src] buzzes.","You hear a buzz.") - playsound(get_turf(src), 'sound/machines/buzz-sigh.ogg', 50, 0) + playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0) locked = FALSE go_out() diff --git a/code/modules/medical/computer/cloning.dm b/code/modules/medical/computer/cloning.dm index 2db4125666d..b50c3ba830c 100644 --- a/code/modules/medical/computer/cloning.dm +++ b/code/modules/medical/computer/cloning.dm @@ -172,7 +172,7 @@ // Database dat += {"

    Database Functions

    - View Records
    "} + View Records[records.len?"([records.len])":""]
    "} if (src.diskette) dat += "Eject Disk" @@ -491,6 +491,7 @@ R.name=R.dna.real_name R.types=DNA2_BUF_UI|DNA2_BUF_UE|DNA2_BUF_SE R.languages = subject.languages.Copy() + R.times_cloned = subject.times_cloned //Add an implant if needed var/obj/item/weapon/implant/health/imp = locate(/obj/item/weapon/implant/health, subject) diff --git a/code/modules/migrations/mysql/mysql_controller.dm b/code/modules/migrations/mysql/mysql_controller.dm index 3620d3f66b7..b3f0564c573 100644 --- a/code/modules/migrations/mysql/mysql_controller.dm +++ b/code/modules/migrations/mysql/mysql_controller.dm @@ -6,14 +6,14 @@ var/global/datum/migration_controller/mysql/migration_controller_mysql = null /datum/migration_controller/mysql/setup() if(!dbcon || !istype(dbcon) || !dbcon.IsConnected()) - testing("Something wrong with dbcon.") + warning("Something wrong with dbcon.") return FALSE var/DBQuery/Q = dbcon.NewQuery() if(!Q) - testing("Something wrong with dbcon.NewQuery()") + warning("Something wrong with dbcon.NewQuery()") return FALSE Q.Close() - testing("MySQL is okay") + //testing("MySQL is okay") db = dbcon return TRUE diff --git a/code/modules/mining/materials.dm b/code/modules/mining/materials.dm index 26b4b680a9e..b2042b50c09 100644 --- a/code/modules/mining/materials.dm +++ b/code/modules/mining/materials.dm @@ -127,11 +127,24 @@ var/global/list/initial_materials //Stores all the matids = 0 in helping New var/sheettype=null var/cointype=null var/value=0 + var/color + var/color_matrix + var/alpha = 255 + //Modifier multipliers. + var/brunt_damage_mod = 1 + var/sharpness_mod = 1 + var/quality_mod = 1 /datum/material/New() if(processed_name=="") processed_name=name +/datum/material/proc/on_use(obj/source, atom/target, mob/user) + ASSERT(source) + if(isobserver(user)) + return FALSE + return TRUE + /datum/material/iron name="Iron" id=MAT_IRON @@ -140,6 +153,10 @@ var/global/list/initial_materials //Stores all the matids = 0 in helping New oretype=/obj/item/weapon/ore/iron sheettype=/obj/item/stack/sheet/metal cointype=/obj/item/weapon/coin/iron + color = "#666666" //rgb: 102, 102, 102 + brunt_damage_mod = 1.1 + sharpness_mod = 0.8 + quality_mod = 1.1 /datum/material/glass name="Sand" @@ -149,6 +166,19 @@ var/global/list/initial_materials //Stores all the matids = 0 in helping New cc_per_sheet=CC_PER_SHEET_GLASS oretype=/obj/item/weapon/ore/glass sheettype=/obj/item/stack/sheet/glass/glass + color = "#6E8DA2" //rgb: 110, 141, 162 + alpha = 122 + brunt_damage_mod = 0.7 + sharpness_mod = 1.4 + +/datum/material/glass/on_use(obj/source) + if(!..()) + return + if(prob(25/source.quality)) + source.visible_message("\The [source] shatters!") + new /obj/item/weapon/shard(get_turf(source)) + playsound(get_turf(source), "shatter", 70, 1) + qdel(source) /datum/material/diamond name="Diamond" @@ -158,6 +188,11 @@ var/global/list/initial_materials //Stores all the matids = 0 in helping New oretype=/obj/item/weapon/ore/diamond sheettype=/obj/item/stack/sheet/mineral/diamond cointype=/obj/item/weapon/coin/diamond + color = "#74C6C6" //rgb: 116, 198, 198 + alpha = 200 + brunt_damage_mod = 1.4 + sharpness_mod = 1.6 + quality_mod = 2 /datum/material/plasma name="Plasma" @@ -166,6 +201,17 @@ var/global/list/initial_materials //Stores all the matids = 0 in helping New oretype=/obj/item/weapon/ore/plasma sheettype=/obj/item/stack/sheet/mineral/plasma cointype=/obj/item/weapon/coin/plasma + color = "#500064" //rgb: 80, 0, 100 + brunt_damage_mod = 1.2 + sharpness_mod = 1.4 + quality_mod = 1.3 + +/datum/material/plasma/on_use(obj/source, atom/target, mob/user) + if(!..()) + return + if(isliving(target)) + var/mob/living/L = target + L.adjustToxLoss(rand(1,source.quality)) /datum/material/gold name="Gold" @@ -174,6 +220,10 @@ var/global/list/initial_materials //Stores all the matids = 0 in helping New oretype=/obj/item/weapon/ore/gold sheettype=/obj/item/stack/sheet/mineral/gold cointype=/obj/item/weapon/coin/gold + color = "#F7C430" //rgb: 247, 196, 48 + brunt_damage_mod = 0.5 + sharpness_mod = 0.5 + quality_mod = 1.7 /datum/material/silver name="Silver" @@ -182,6 +232,11 @@ var/global/list/initial_materials //Stores all the matids = 0 in helping New oretype=/obj/item/weapon/ore/silver sheettype=/obj/item/stack/sheet/mineral/silver cointype=/obj/item/weapon/coin/silver + color = "#D0D0D0" //rgb: 208, 208, 208 + brunt_damage_mod = 0.7 + sharpness_mod = 0.7 + quality_mod = 1.5 + /datum/material/uranium name="Uranium" @@ -190,6 +245,18 @@ var/global/list/initial_materials //Stores all the matids = 0 in helping New oretype=/obj/item/weapon/ore/uranium sheettype=/obj/item/stack/sheet/mineral/uranium cointype=/obj/item/weapon/coin/uranium + color = "#247124" //rgb: 36, 113, 36 + brunt_damage_mod = 1.8 + sharpness_mod = 0.2 + quality_mod = 1.4 + + +/datum/material/uranium/on_use(obj/source, atom/target, mob/user) + if(!..()) + return + if(isliving(target)) + var/mob/living/L = target + L.apply_radiation(rand(1,3)*source.quality, RAD_EXTERNAL) /datum/material/clown name="Bananium" @@ -199,6 +266,25 @@ var/global/list/initial_materials //Stores all the matids = 0 in helping New sheettype=/obj/item/stack/sheet/mineral/clown cointype=/obj/item/weapon/coin/clown +/datum/material/clown/New() + if(!..()) + return + brunt_damage_mod = rand(1,2)/rand(1,8) + sharpness_mod = rand(1,2)/rand(1,8) + quality_mod = rand(1,2)/rand(1,8) + + color_matrix = list(rand(),rand(),rand(),0, + rand(),rand(),rand(),0, + rand(),rand(),rand(),0, + 0,0,0,1, + 0,0,0,0) + +/datum/material/clown/on_use(obj/source) //May [ticker.deity] have mercy + if(!..()) + return + if(prob(2*source.quality)) + playsound(get_turf(source), 'sound/items/bikehorn.ogg', 100, 1) + /datum/material/phazon name="Phazon" id=MAT_PHAZON @@ -207,6 +293,25 @@ var/global/list/initial_materials //Stores all the matids = 0 in helping New oretype=/obj/item/weapon/ore/phazon sheettype=/obj/item/stack/sheet/mineral/phazon cointype=/obj/item/weapon/coin/phazon + color = "#5E02F8" //rgb: 94, 2, 248 + brunt_damage_mod = 1.4 + sharpness_mod = 1.8 + quality_mod = 2.2 + +/datum/material/phazon/on_use(obj/source, atom/target, mob/user) + if(!..()) + return + if(prob(0.5*source.quality)) + switch(rand(1,2)) + if(1) //EMP + empulse(get_turf(pick(source,target,user)), 0.25*source.quality, 0.5*source.quality, 1) + if(2) //Teleport + var/atom/movable/victim = pick(target,user) + if(victim) + do_teleport(victim, get_turf(victim), 1*source.quality, asoundin = 'sound/effects/phasein.ogg') + if(prob(20*source.quality)) + to_chat(user, "\The [source] phases out of reality!") + qdel(source) /datum/material/plastic name="Plastic" @@ -215,6 +320,7 @@ var/global/list/initial_materials //Stores all the matids = 0 in helping New oretype=null sheettype=/obj/item/stack/sheet/mineral/plastic cointype=null + color = "#F8F8FF" //rgb: 248, 248, 255 /datum/material/cardboard name="Cardboard" @@ -225,6 +331,17 @@ var/global/list/initial_materials //Stores all the matids = 0 in helping New cointype=null cc_per_sheet = CC_PER_SHEET_METAL +/datum/material/wood + name="Wood" + id=MAT_WOOD + value=1 + oretype=null + sheettype=/obj/item/stack/sheet/wood + cointype=null + cc_per_sheet = CC_PER_SHEET_METAL + color = "#663300" //rgb: 102, 51, 0 + + /* //Commented out to save save space in menus listing materials until they are used /datum/material/pharosium name="Pharosium" diff --git a/code/modules/mining/mine_items.dm b/code/modules/mining/mine_items.dm index 0507fe9067b..6e15d0f7c25 100644 --- a/code/modules/mining/mine_items.dm +++ b/code/modules/mining/mine_items.dm @@ -450,7 +450,7 @@ proc/move_mining_shuttle() /obj/item/weapon/resonator/proc/CreateResonance(var/target, var/creator) if(cooldown <= 0) - playsound(get_turf(src),'sound/effects/stealthoff.ogg',50,1) + playsound(src,'sound/effects/stealthoff.ogg',50,1) var/obj/effect/resonance/R = new /obj/effect/resonance(get_turf(target)) R.creator = creator cooldown = 1 @@ -514,9 +514,7 @@ proc/move_mining_shuttle() throwforce = 0 sterile = 1 //tint = 3 //Makes it feel more authentic when it latches on - -/obj/item/clothing/mask/facehugger/toy/Die() - return + real = FALSE /**********************Mining drone cube**********************/ @@ -593,15 +591,28 @@ proc/move_mining_shuttle() to_chat(user, "You instruct \the [src] to drop any collected ore.") DropOre() return + if(!client && istype(I, /obj/item/device/paicard)) + var/obj/item/device/paicard/P = I + if(!P.pai) + to_chat(user, "\The [P] has no intelligence within it.") + return + var/response = alert(user, "Are you sure you want to put \the [P] into \the [src]? This can not be undone.","Yes","No") + if(response != "Yes") + return + if(do_after(user, src, 30)) + user.drop_item(P, force_drop = TRUE) + P.pai.mind.transfer_to(src) + projectiletype = /obj/item/projectile/kinetic + qdel(P) + ..() -/mob/living/simple_animal/hostile/mining_drone/Die() - ..() +/mob/living/simple_animal/hostile/mining_drone/death(var/gibbed = FALSE) + ..(TRUE) visible_message("\The [src] blows apart!") new /obj/effect/decal/remains/robot(src.loc) DropOre() qdel(src) - return /mob/living/simple_animal/hostile/mining_drone/New() ..() @@ -609,16 +620,21 @@ proc/move_mining_shuttle() /mob/living/simple_animal/hostile/mining_drone/attack_hand(mob/living/carbon/human/M) if(M.a_intent == I_HELP) - switch(search_objects) - if(0) - SetCollectBehavior() - to_chat(M, "\The [src] will now search and store loose ore.") - if(2) - SetOffenseBehavior() - to_chat(M, "\The [src] will now attack hostile wildlife.") + ToggleModes(M) return ..() +/mob/living/simple_animal/hostile/mining_drone/proc/ToggleModes(mob/user) + switch(search_objects) + if(0) + SetCollectBehavior() + if(user != src) + to_chat(user, "\The [src] will now search and store loose ore.") + if(2) + SetOffenseBehavior() + if(user != src) + to_chat(user, "\The [src] will now attack hostile wildlife.") + /mob/living/simple_animal/hostile/mining_drone/proc/SetCollectBehavior() stop_automated_movement_when_pulled = 1 idle_vision_range = 9 @@ -628,6 +644,8 @@ proc/move_mining_shuttle() minimum_distance = 1 retreat_distance = null icon_state = "mining_drone" + if(client) + to_chat(src, "Ore collection mode active.") /mob/living/simple_animal/hostile/mining_drone/proc/SetOffenseBehavior() stop_automated_movement_when_pulled = 0 @@ -638,6 +656,8 @@ proc/move_mining_shuttle() retreat_distance = 1 minimum_distance = 2 icon_state = "mining_drone_offense" + if(client) + to_chat(src, "Combat mode active.") /mob/living/simple_animal/hostile/mining_drone/AttackingTarget() if(istype(target, /obj/item/weapon/ore)) @@ -661,6 +681,8 @@ proc/move_mining_shuttle() for(var/obj/item/weapon/ore/O in contents) contents -= O O.forceMove(src.loc) + if(client) + to_chat(src, "Unloading collected ore.") return /mob/living/simple_animal/hostile/mining_drone/adjustBruteLoss() @@ -668,6 +690,32 @@ proc/move_mining_shuttle() SetOffenseBehavior() ..() +/mob/living/simple_animal/hostile/mining_drone/LoseAggro() + stop_automated_movement = 0 + vision_range = idle_vision_range + +/mob/living/simple_animal/hostile/mining_drone/Login() + ..() + to_chat(src, "You are a minebot. Click on yourself to toggle between modes.") + +/mob/living/simple_animal/hostile/mining_drone/attack_animal(mob/living/simple_animal/M) + if(client && M == src) + ToggleModes(M) + else + return ..() + +/mob/living/simple_animal/hostile/mining_drone/UnarmedAttack(atom/A) + . = ..() + if(client && search_objects == 2 && (istype(A, /obj/item/weapon/ore) || isturf(A)) && !attack_delayer.blocked()) + delayNextAttack(8) + CollectOre() + +/mob/living/simple_animal/hostile/mining_drone/verb/UnloadOre() + set category = "Minebot" + set name = "Unload Ore" + + DropOre() + /**********************Lazarus Injector**********************/ /obj/item/weapon/lazarus_injector @@ -696,7 +744,9 @@ proc/move_mining_shuttle() if(istype(target, /mob/living) && proximity_flag) if(istype(target, /mob/living/simple_animal)) var/mob/living/simple_animal/M = target - + if(M.mob_property_flags & MOB_NO_LAZ) + to_chat(user, "\The [src] is incapable of reviving \the [M].") + return if(M.stat == DEAD) M.faction = "lazarus \ref[user]" diff --git a/code/modules/mining/mine_structures.dm b/code/modules/mining/mine_structures.dm index 4d6ce31ce50..670acce399f 100644 --- a/code/modules/mining/mine_structures.dm +++ b/code/modules/mining/mine_structures.dm @@ -39,7 +39,7 @@ if(lantern) user.visible_message("[user] takes \the [lantern] off of the \the [src].", \ "You take \the [lantern] off of the \the [src].") - playsound(get_turf(src), 'sound/machines/click.ogg', 20, 1) + playsound(src, 'sound/machines/click.ogg', 20, 1) lantern.forceMove(user.loc) lantern.add_fingerprint(user) user.put_in_hands(lantern) @@ -63,7 +63,7 @@ user << "Remove \the [lantern] from \the [src] first." return busy = 1 - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 75, 1) + playsound(src, 'sound/items/Ratchet.ogg', 75, 1) user.visible_message("[user] begins deconstructing \the [src].", \ "You begin deconstructing \the [src].") if(do_after(user, src, 30)) @@ -82,7 +82,7 @@ if(user.drop_item(W, src)) user.visible_message("[user] puts \a [W.name] on the \the [src].", \ "You put \a [W.name] on the \the [src].") - playsound(get_turf(src), 'sound/machines/click.ogg', 20, 1) + playsound(src, 'sound/machines/click.ogg', 20, 1) lantern = W update() return 1 diff --git a/code/modules/mining/mine_turfs.dm b/code/modules/mining/mine_turfs.dm index d0fdc84baa0..f3ab7dd6950 100644 --- a/code/modules/mining/mine_turfs.dm +++ b/code/modules/mining/mine_turfs.dm @@ -4,6 +4,7 @@ name = "Rock" icon = 'icons/turf/walls.dmi' icon_state = "rock" + var/base_icon_state = "rock" // above is for mappers. oxygen = 0 nitrogen = 0 opacity = 1 @@ -23,9 +24,25 @@ var/datum/artifact_find/artifact_find var/scan_state = null //Holder for the image we display when we're pinged by a mining scanner var/busy = 0 //Used for a bunch of do_after actions, because we can walk into the rock to trigger them - + var/mineral_overlay var/mined_type = /turf/unsimulated/floor/asteroid - var/global/image/rock_overlay = image('icons/turf/rock_overlay.dmi',"rock_overlay") + var/overlay_state = "rock_overlay" + + +/turf/unsimulated/mineral/snow + icon_state = "snow_rock" + base_icon_state = "snow_rock" + mined_type = /turf/unsimulated/floor/snow + overlay_state = "snow_rock_overlay" + +/turf/unsimulated/mineral/snow/New() + base_icon_state = pick("snow_rock","snow_rock1","snow_rock2","snow_rock3","snow_rock4") + ..() + +/turf/unsimulated/mineral/underground + icon_state = "cave_wall" + base_icon_state = "cave_wall" + mined_type = /turf/unsimulated/floor/asteroid/underground /turf/unsimulated/mineral/air oxygen = MOLES_O2STANDARD @@ -39,23 +56,37 @@ /turf/unsimulated/mineral/Destroy() return -var/list/icon_state_to_appearance = list() - /turf/unsimulated/mineral/New() - if(!(mineral_turfs.len)) - rock_overlay.pixel_x = -4 - rock_overlay.pixel_y = -4 - rock_overlay.plane = BELOW_TURF_PLANE mineral_turfs += src . = ..() MineralSpread() + update_icon() - if(icon_state_to_appearance[icon_state]) - appearance = icon_state_to_appearance[icon_state] +var/list/icon_state_to_appearance = list() + +/turf/unsimulated/mineral/update_icon(var/mineral_name = "empty") // feed in a mineral name to 'force' its appearance on an object. + if(mineral && mineral_name == "empty") + mineral_name = mineral.display_name + if(icon_state_to_appearance["[base_icon_state]-[mineral_name]"]) + appearance = icon_state_to_appearance["[base_icon_state]-[mineral_name]"] else - overlays += rock_overlay - icon_state_to_appearance[icon_state] = appearance + overlays.Cut() + if(mineral) + mineral_overlay = image('icons/turf/mine_overlays.dmi', mineral_name) + overlays += mineral_overlay + icon_state = base_icon_state + add_rock_overlay() + icon_state_to_appearance["[base_icon_state]-[mineral_name]"] = appearance +/turf/unsimulated/mineral/proc/add_rock_overlay(var/image/img = image('icons/turf/rock_overlay.dmi', overlay_state,layer = SIDE_LAYER),var/offset=-4) + img.pixel_x = offset*PIXEL_MULTIPLIER + img.pixel_y = offset*PIXEL_MULTIPLIER + img.plane = BELOW_TURF_PLANE + overlays += img + +/turf/unsimulated/mineral/underground/add_rock_overlay() + ..(img = image('icons/turf/spookycave.dmi', "spooky_cave",layer = SIDE_LAYER),offset=-16) + ..(img = image('icons/turf/spookycave.dmi', "spooky_cave_corners",layer = CORNER_LAYER),offset = -16) turf/unsimulated/mineral/ChangeTurf(var/turf/N, var/tell_universe=1, var/force_lighting_update = 0, var/allow = 1) mineral_turfs -= src @@ -113,7 +144,7 @@ turf/unsimulated/mineral/ChangeTurf(var/turf/N, var/tell_universe=1, var/force_l name = "\improper Rock" return name = "\improper [mineral.display_name] deposit" - icon_state = "rock_[mineral.name]" + update_icon() /turf/unsimulated/mineral/attackby(obj/item/weapon/W as obj, mob/user as mob) @@ -410,12 +441,26 @@ turf/unsimulated/mineral/ChangeTurf(var/turf/N, var/tell_universe=1, var/force_l temperature = TCMB //icon_plating = "asteroid" var/dug = 0 //0 = has not yet been dug, 1 = has already been dug + var/sand_type = /obj/item/weapon/ore/glass + plane = PLATING_PLANE /turf/unsimulated/floor/asteroid/air oxygen = MOLES_O2STANDARD nitrogen = MOLES_N2STANDARD temperature = T20C +/turf/unsimulated/floor/asteroid/underground + name = "cave floor" + temperature = T0C-150 + oxygen = MOLES_O2STANDARD_ARCTIC + nitrogen = MOLES_N2STANDARD_ARCTIC + icon_state = "cavefl_1" + sand_type = /obj/item/weapon/ore/glass/cave + +/turf/unsimulated/floor/asteroid/underground/New() + ..() + icon_state = pick("cavefl_1","cavefl_2","cavefl_3","cavefl_4") + /turf/unsimulated/floor/asteroid/New() var/proper_name = name ..() @@ -424,7 +469,6 @@ turf/unsimulated/mineral/ChangeTurf(var/turf/N, var/tell_universe=1, var/force_l if(prob(20)) icon_state = "asteroid[rand(0,12)]" - initialize() /turf/unsimulated/floor/asteroid/ex_act(severity) @@ -457,7 +501,7 @@ turf/unsimulated/mineral/ChangeTurf(var/turf/N, var/tell_universe=1, var/force_l return to_chat(user, "You start digging.") - playsound(get_turf(src), 'sound/effects/rustle1.ogg', 50, 1) //russle sounds sounded better + playsound(src, 'sound/effects/rustle1.ogg', 50, 1) //russle sounds sounded better if(do_after(user, src, used_digging.digspeed) && user) //the better the drill, the faster the digging playsound(src, 'sound/items/shovel.ogg', 50, 1) @@ -468,18 +512,18 @@ turf/unsimulated/mineral/ChangeTurf(var/turf/N, var/tell_universe=1, var/force_l ..(W,user) return +/turf/unsimulated/floor/asteroid/update_icon() + if(dug && ispath(sand_type, /obj/item/weapon/ore/glass)) + icon_state = "asteroid_dug" + /turf/unsimulated/floor/asteroid/proc/gets_dug() if(dug) return - new/obj/item/weapon/ore/glass(src) - new/obj/item/weapon/ore/glass(src) - new/obj/item/weapon/ore/glass(src) - new/obj/item/weapon/ore/glass(src) - new/obj/item/weapon/ore/glass(src) + for(var/i = 1 to 5) + new sand_type(src) dug = 1 //icon_plating = "asteroid_dug" - icon_state = "asteroid_dug" - return + update_icon() /turf/unsimulated/mineral/random name = "Mineral deposit" @@ -718,10 +762,14 @@ turf/unsimulated/mineral/ChangeTurf(var/turf/N, var/tell_universe=1, var/force_l var/activated_name = null /turf/unsimulated/mineral/gibtonite/New() - icon_state="rock_Diamond" det_time = rand(8,10) //So you don't know exactly when the hot potato will explode ..() +/turf/unsimulated/mineral/gibtonite/update_icon(var/mineral_name = "empty") + if(mineral_name == "empty" && !stage) + ..("Diamond") + else ..(mineral_name) + /turf/unsimulated/mineral/gibtonite/Bumped(AM) var/bump_reject = 0 if(istype(AM,/mob/living/carbon/human)) @@ -758,7 +806,7 @@ turf/unsimulated/mineral/ChangeTurf(var/turf/N, var/tell_universe=1, var/force_l /turf/unsimulated/mineral/gibtonite/proc/explosive_reaction() if(stage == 0) - icon_state = "rock_Gibtonite_active" + update_icon("Gibtonite_active") name = "Gibtonite deposit" desc = "An active gibtonite reserve. Run!" stage = 1 @@ -783,7 +831,7 @@ turf/unsimulated/mineral/ChangeTurf(var/turf/N, var/tell_universe=1, var/force_l /turf/unsimulated/mineral/gibtonite/proc/defuse() if(stage == 1) - icon_state = "rock_Gibtonite" //inactive does not exist. The other icon is active. + update_icon("Gibtonite") //inactive does not exist. The other icon is active. desc = "An inactive gibtonite reserve. The ore can be extracted." stage = 2 if(det_time < 0) @@ -802,10 +850,10 @@ turf/unsimulated/mineral/ChangeTurf(var/turf/N, var/tell_universe=1, var/force_l if(stage == 2) //Gibtonite deposit is now benign and extractable. Depending on how close you were to it blowing up before defusing, you get better quality ore. var/obj/item/weapon/gibtonite/G = new /obj/item/weapon/gibtonite/(src) if(det_time <= 0) - G.quality = 3 + G.det_quality = 3 G.icon_state = "Gibtonite ore 3" if(det_time >= 1 && det_time <= 2) - G.quality = 2 + G.det_quality = 2 G.icon_state = "Gibtonite ore 2" ChangeTurf(/turf/unsimulated/floor/asteroid/gibtonite_remains) @@ -821,7 +869,8 @@ turf/unsimulated/mineral/ChangeTurf(var/turf/N, var/tell_universe=1, var/force_l /mob/living/simple_animal/hostile/asteroid/goliath = 5, /mob/living/simple_animal/hostile/asteroid/goldgrub = 1, /mob/living/simple_animal/hostile/asteroid/basilisk = 3, - /mob/living/simple_animal/hostile/asteroid/hivelord = 5 + /mob/living/simple_animal/hostile/asteroid/hivelord = 5, + /mob/living/simple_animal/hostile/asteroid/magmaw = 4 ) var/sanity = 1 @@ -894,7 +943,7 @@ turf/unsimulated/mineral/ChangeTurf(var/turf/N, var/tell_universe=1, var/force_l SpawnMonster(T) - new /turf/unsimulated/floor/asteroid(T) + new /turf/unsimulated/floor/asteroid(T) // TODO: FIX THIS /turf/unsimulated/floor/asteroid/cave/proc/SpawnMonster(var/turf/T) if(prob(2)) diff --git a/code/modules/mining/ores_coins.dm b/code/modules/mining/ores_coins.dm index f5b11ae4674..d160a201d9d 100644 --- a/code/modules/mining/ores_coins.dm +++ b/code/modules/mining/ores_coins.dm @@ -37,10 +37,15 @@ slot_flags = SLOT_POCKET throw_range = 1 //It just scatters to the ground as soon as you throw it. +/obj/item/weapon/ore/glass/cave + name = "cave sand" + icon_state = "cavesand" + /obj/item/weapon/ore/glass/throw_impact(atom/hit_atom) //Intentionally not calling ..() if(isturf(hit_atom)) - new/obj/effect/decal/cleanable/scattered_sand(hit_atom) + if(!locate(/obj/effect/decal/cleanable/scattered_sand) in hit_atom) + new/obj/effect/decal/cleanable/scattered_sand(hit_atom) qdel(src) else if(ishuman(hit_atom)) var/mob/living/carbon/human/H = hit_atom @@ -242,7 +247,7 @@ flags = FPRINT | TWOHANDABLE | MUSTTWOHAND var/primed = 0 var/det_time = 100 - var/quality = 1 //How pure this gibtonite is, determines the explosion produced by it and is derived from the det_time of the rock wall it was taken from, higher shipping_value = better + var/det_quality = 1 //How pure this gibtonite is, determines the explosion produced by it and is derived from the det_time of the rock wall it was taken from, higher shipping_value = better /obj/item/weapon/gibtonite/attackby(obj/item/I, mob/user) if(istype(I, /obj/item/weapon/pickaxe) || istype(I, /obj/item/weapon/resonator)) @@ -252,7 +257,7 @@ primed = 0 user.visible_message("The chain reaction was stopped! ...The ore's quality went down.") icon_state = "Gibtonite ore" - quality = 1 + det_quality = 1 return ..() @@ -286,7 +291,7 @@ log_game("[key_name(usr)] has primed a [name] for detonation at [A.name]([bombturf.x],[bombturf.y],[bombturf.z])") spawn(det_time) if(primed) - switch(quality) + switch(det_quality) if(1) explosion(src.loc,-1,1,3,adminlog = notify_admins) if(2) diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 73f782af243..99bd54a1665 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -350,7 +350,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp for(var/obj/effect/step_trigger/S in NewLoc) S.Crossed(src) - var/area/A = get_area_master(src) + var/area/A = get_area(src) if(A) A.Entered(src) @@ -368,7 +368,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp for(var/obj/effect/step_trigger/S in get_turf(src)) //<-- this is dumb S.Crossed(src) - var/area/A = get_area_master(src) + var/area/A = get_area(src) if(A) A.Entered(src) */ @@ -676,7 +676,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp to_chat(src, "Unknown: [round(unknown_concentration * 100)]% ([round(unknown_concentration * total_moles / tiles, 0.01)] moles)") to_chat(src, "Temperature: [round(environment.temperature - T0C, 0.1)]°C") - to_chat(src, "Heat Capacity: [round(environment.heat_capacity(), 0.1)]") + to_chat(src, "Heat Capacity: [round(environment.heat_capacity() / tiles, 0.1)]") /mob/dead/observer/verb/toggle_darkness() @@ -999,4 +999,19 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp return selectedHUD == HUD_MEDICAL if(HUD_SECURITY) return selectedHUD == HUD_SECURITY - return \ No newline at end of file + return + +/mob/dead/observer/proc/can_reenter_corpse() + var/mob/M = get_top_transmogrification() + return (M && M.client && can_reenter_corpse) + +/mob/dead/observer/verb/pai_signup() + set name = "Sign up as pAI" + set category = "Ghost" + set desc = "Create and submit your pAI personality" + + if(!paiController.check_recruit(src)) + to_chat(src, "Not available. You may have been pAI-banned.") + return + + paiController.recruitWindow(src) diff --git a/code/modules/mob/emote.dm b/code/modules/mob/emote.dm index 209bd315330..6f748472a79 100644 --- a/code/modules/mob/emote.dm +++ b/code/modules/mob/emote.dm @@ -45,7 +45,7 @@ // Type 2 (Audible) emotes are sent to anyone in hear range // of the *LOCATION* -- this is important for pAIs to be heard else if (m_type & 2) - for(var/mob/living/M in get_hearers_in_view(get_turf(src), null)) + for(var/mob/M in get_hearers_in_view(7, src)) M.show_message(message, m_type) /mob/proc/emote_dead(var/message) diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm index 583a041f372..50108cd7a82 100644 --- a/code/modules/mob/inventory.dm +++ b/code/modules/mob/inventory.dm @@ -183,7 +183,7 @@ W.hud_layerise() W.pixel_x = initial(W.pixel_x) W.pixel_y = initial(W.pixel_y) - W.equipped(src, null, index) + W.equipped(src,null,index) if(client) client.screen |= W @@ -513,7 +513,7 @@ return equipped /mob/proc/get_id_card() - for(var/obj/item/I in src.get_all_slots()) + for(var/obj/item/I in src.get_all_slots() + held_items) . = I.GetID() if(.) break diff --git a/code/modules/mob/language.dm b/code/modules/mob/language.dm index 909b40d9ff6..cf87d45bc60 100644 --- a/code/modules/mob/language.dm +++ b/code/modules/mob/language.dm @@ -65,7 +65,6 @@ exclaim_verb = "roars" colour = "soghun" key = "o" - flags = RESTRICTED syllables = list("ss","ss","ss","ss","skak","seeki","resh","las","esi","kor","sh") /datum/language/tajaran @@ -76,7 +75,6 @@ exclaim_verb = "yowls" colour = "tajaran" key = "j" - flags = RESTRICTED syllables = list("rr","rr","tajr","kir","raj","kii","mir","kra","ahk","nal","vah","khaz","jri","ran","darr", \ "mi","jri","dynh","manq","rhe","zar","rrhaz","kal","chur","eech","thaa","dra","jurl","mah","sanu","dra","ii'r", \ "ka","aasi","far","wa","baq","ara","qara","zir","sam","mak","hrar","nja","rir","khan","jun","dar","rik","kah", \ @@ -90,7 +88,6 @@ exclaim_verb = "warbles" colour = "skrell" key = "k" - flags = RESTRICTED syllables = list("qr","qrr","xuq","qil","quum","xuqm","vol","xrim","zaoo","qu-uu","qix","qoo","zix","*","!") /datum/language/vox @@ -101,7 +98,6 @@ exclaim_verb = "shrieks" colour = "vox" key = "v" - flags = RESTRICTED syllables = list("ti","ti","ti","hi","hi","ki","ki","ki","ki","ya","ta","ha","ka","ya","chi","cha","kah", \ "SKRE","AHK","EHK","RAWK","KRA","AAA","EEE","KI","II","KRI","KA") @@ -113,7 +109,6 @@ exclaim_verb = "rustles" colour = "soghun" key = "q" - flags = RESTRICTED syllables = list("hs","zt","kr","st","sh") /datum/language/common @@ -130,7 +125,6 @@ desc = "A bastardized hybrid of informal English and elements of Mandarin Chinese; the common language of the Sol system." key = "7" colour = "solcom" - flags = RESTRICTED /datum/language/human/monkey name = LANGUAGE_MONKEY @@ -149,6 +143,7 @@ colour = "say_quote" key = "2" space_chance = 100 + flags = CAN_BE_SECONDARY_LANGUAGE syllables = list("lorem", "ipsum", "dolor", "sit", "amet", "consectetur", "adipiscing", "elit", "sed", "do", "eiusmod", "tempor", "incididunt", "ut", "labore", "et", "dolore", "magna", "aliqua", "ut", "enim", "ad", "minim", "veniam", "quis", "nostrud", @@ -164,6 +159,7 @@ speech_verb = "growls" colour = "gutter" key = "3" + flags = CAN_BE_SECONDARY_LANGUAGE syllables = list("gra","ba","ba","breh","bra","rah","dur","ra","ro","gro","go","ber","bar","geh","heh","gra") /datum/language/grey @@ -175,7 +171,6 @@ exclaim_verb = "quacks loudly" colour = "grey" native=1 - flags = RESTRICTED space_chance = 100 syllables = list("ACK", "AKACK", "ACK") @@ -196,7 +191,6 @@ exclaim_verb = "chatters loudly" colour = "sinister" native=1 - flags = RESTRICTED space_chance = 95 syllables = list("CLICK", "CLACK") @@ -210,7 +204,6 @@ colour = "golem" native = 1 key = "8" - flags = RESTRICTED syllables = list("oa","ur","ae","um","tu","gor","an","lo","ag","oon","po") /datum/language/slime @@ -223,7 +216,6 @@ colour = "slime" native = 1 key = "f" - flags = RESTRICTED syllables = list("ba","ab","be","eb","bi","ib","bo","ob","bu","ub") /datum/language/skellington/say_misunderstood(mob/M, message) @@ -274,7 +266,6 @@ key = "9" space_chance = 80 syllables = list("squeak") - flags = RESTRICTED /datum/language/martian name = LANGUAGE_MARTIAN @@ -284,9 +275,9 @@ exclaim_verb = "blurbs" key = "@" colour = "grey" + flags = RESTRICTED space_chance = 35 native = 1 - flags = RESTRICTED syllables = list("khah","kig","kitol","kaor","bar","dar","dator","lok","ma","mu","o","och","gort","gal") // Language handling. @@ -350,9 +341,9 @@ src << browse(dat, "window=checklanguage") /mob/living/Topic(href, href_list) - if(usr != src) - return if(href_list["default_lang"]) + if(usr != src) + return if(href_list["default_lang"] == "reset") set_default_language(null) else diff --git a/code/modules/mob/living/carbon/_defines.dm b/code/modules/mob/living/carbon/_defines.dm index dde7bdc18dd..85689a69951 100644 --- a/code/modules/mob/living/carbon/_defines.dm +++ b/code/modules/mob/living/carbon/_defines.dm @@ -6,7 +6,7 @@ #define HEAT_DAMAGE_LEVEL_2 4 //Amount of damage applied when your body temperature passes the 400K point #define HEAT_DAMAGE_LEVEL_3 8 //Amount of damage applied when your body temperature passes the 1000K point -#define COLD_DAMAGE_LEVEL_1 0.5 //Amount of damage applied when your body temperature just passes the 260.15k safety point +#define COLD_DAMAGE_LEVEL_1 0.5 //Amount of damage applied when your body temperature just passes the 220.15k safety point #define COLD_DAMAGE_LEVEL_2 1.5 //Amount of damage applied when your body temperature passes the 200K point #define COLD_DAMAGE_LEVEL_3 3 //Amount of damage applied when your body temperature passes the 120K point @@ -15,7 +15,7 @@ #define HEAT_GAS_DAMAGE_LEVEL_2 4 //Amount of damage applied when the current breath's temperature passes the 400K point #define HEAT_GAS_DAMAGE_LEVEL_3 8 //Amount of damage applied when the current breath's temperature passes the 1000K point -#define COLD_GAS_DAMAGE_LEVEL_1 0.5 //Amount of damage applied when the current breath's temperature just passes the 260.15k safety point +#define COLD_GAS_DAMAGE_LEVEL_1 0.5 //Amount of damage applied when the current breath's temperature just passes the 220.15k safety point #define COLD_GAS_DAMAGE_LEVEL_2 1.5 //Amount of damage applied when the current breath's temperature passes the 200K point #define COLD_GAS_DAMAGE_LEVEL_3 3 //Amount of damage applied when the current breath's temperature passes the 120K point diff --git a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm index 275511df7a6..1b8a6ab9073 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm @@ -149,7 +149,7 @@ Doesn't work on other aliens/AI.*/ proj_step_delay = 0.2 /spell/targeted/projectile/alienneurotoxin/is_valid_target(var/target, mob/user) - if(!(spell_flags & INCLUDEUSER) && target == usr) + if(!(spell_flags & INCLUDEUSER) && target == user) return FALSE if(get_dist(usr, target) > range) return FALSE @@ -214,8 +214,17 @@ Doesn't work on other aliens/AI.*/ range = 1 /spell/alienacid/is_valid_target(var/atom/target, mob/user) - if(get_dist(user, target) > range) //Shouldn't be necessary but a good check in case of overrides + return is_valid_target_to_acid(target,user,range) + +/proc/is_valid_target_to_acid(var/atom/target, mob/user,var/range=1) + if(get_dist(user, target) > range) + to_chat(user, "Target is too far away!") return FALSE + if(target.isacidhardened()) + if(!do_after(user,target,3 SECONDS)) + to_chat(user, "You have to stay next to the object to acid it!") + return FALSE + return TRUE if(!ismob(target) && target.acidable()) return TRUE to_chat(user, "You cannot dissolve this object.") @@ -233,21 +242,13 @@ Doesn't work on other aliens/AI.*/ return if(powerc(200)) - if(O in oview(1)) - if(!O.acidable()) - to_chat(usr, "You cannot dissolve this object.") - return FALSE - AdjustPlasma(-200) + if(is_valid_target_to_acid(O, usr)) acidify(O, usr) - else - to_chat(usr, "Target is too far away.") + AdjustPlasma(-200) /proc/acidify(atom/O, mob/user) - if(O.acidable()) - new /obj/effect/alien/acid(get_turf(O), O) - user.visible_message("\The [usr] vomits globs of vile stuff all over [O]. It begins to sizzle and melt under the bubbling mess of acid!") - else - to_chat(user, "You cannot dissolve this object.") + new /obj/effect/alien/acid(get_turf(O), O) + user.visible_message("\The [user] vomits globs of vile stuff all over [O]. It begins to sizzle and melt under the bubbling mess of acid!") /spell/aoe_turf/alienregurgitate name = "Regurgitate" @@ -265,7 +266,7 @@ Doesn't work on other aliens/AI.*/ /spell/aoe_turf/alienregurgitate/cast(list/targets, mob/user) var/mob/living/carbon/alien/humanoid/alien = user alien.drop_stomach_contents() - user.visible_message("\The [usr] hurls out the contents of their stomach!") + user.visible_message("\The [user] hurls out the contents of their stomach!") /////////////////////////// // QUEEN SPECIFIC SPELLS // @@ -286,7 +287,7 @@ Doesn't work on other aliens/AI.*/ spell_flags = IGNORESPACE|NODUPLICATE summon_type = list(/obj/effect/alien/egg) -a + /spell/aoe_turf/conjure/alienegg/cast(list/targets, mob/user) . = ..() if(!.) //Returning 1 if we failed to cast @@ -309,6 +310,7 @@ a cast_sound = 'sound/effects/evolve.ogg' cast_delay = 50 + use_progress_bar = TRUE /spell/aoe_turf/evolve/drone desc = "Produce an interal egg sac capable of spawning children. Only one queen can exist at a time." @@ -327,7 +329,7 @@ a return ..() /spell/aoe_turf/evolve/drone/spell_do_after(var/mob/user as mob, delay as num, var/numticks = 5) - user.visible_message("[src] begins to violently twist and contort!", "You begin to evolve, stand still for a few moments") + user.visible_message("[user] begins to violently twist and contort!", "You begin to evolve, stand still for a few moments.") return ..() /spell/aoe_turf/evolve/drone/cast(list/targets, mob/living/carbon/user) diff --git a/code/modules/mob/living/carbon/alien/humanoid/combat.dm b/code/modules/mob/living/carbon/alien/humanoid/combat.dm index 2079f34b1ac..02dcde1a39e 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/combat.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/combat.dm @@ -1,15 +1,15 @@ /mob/living/carbon/alien/humanoid/disarm_mob(mob/living/target) if(target.disarmed_by(src)) return - - if(prob(80)) + var/datum/organ/external/affecting = get_organ(ran_zone(zone_sel.selecting)) + var/disarm_chance_modifier = target.run_armor_check(affecting, "melee", quiet = 1) + if(prob(80/(disarm_chance_modifier == 0 ? 1 : disarm_chance_modifier))) do_attack_animation(target, src) playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1) - target.Knockdown(rand(3,4)) - + target.apply_effect(4, WEAKEN, run_armor_check(affecting, "melee")) visible_message("[src] has tackled down [target]!") - else if (prob(80)) + else if (prob(80/(disarm_chance_modifier == 0 ? 1 : disarm_chance_modifier))) do_attack_animation(target, src) playsound(loc, get_unarmed_hit_sound(), 25, 1, -1) target.drop_item() diff --git a/code/modules/mob/living/carbon/alien/humanoid/emote.dm b/code/modules/mob/living/carbon/alien/humanoid/emote.dm index faa32cab421..16c8ba3f4db 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/emote.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/emote.dm @@ -122,9 +122,9 @@ if ((message && src.stat == 0)) log_emote("[name]/[key] (@[x],[y],[z]): [message]") if (act == "roar") - playsound(get_turf(src), 'sound/voice/hiss5.ogg', 40, 1, 1) + playsound(src, 'sound/voice/hiss5.ogg', 40, 1, 1) if (act == "deathgasp") - playsound(get_turf(src), 'sound/voice/hiss6.ogg', 80, 1, 1) + playsound(src, 'sound/voice/hiss6.ogg', 80, 1, 1) if (m_type & 1) for(var/mob/O in viewers(src, null)) O.show_message(message, m_type) diff --git a/code/modules/mob/living/carbon/alien/humanoid/life.dm b/code/modules/mob/living/carbon/alien/humanoid/life.dm index 87b3df5eebb..bd0785f8ad5 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/life.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/life.dm @@ -121,16 +121,13 @@ var/obj/location_as_object = loc breath = location_as_object.handle_internal_lifeform(src, BREATH_VOLUME) else if(istype(loc, /turf/)) - var/breath_moles = 0 /*if(environment.return_pressure() > ONE_ATMOSPHERE) // Loads of air around (pressure effect will be handled elsewhere), so lets just take a enough to fill our lungs at normal atmos pressure (using n = Pv/RT) breath_moles = (ONE_ATMOSPHERE*BREATH_VOLUME/R_IDEAL_GAS_EQUATION*environment.temperature) else */ // Not enough air around, take a percentage of what's there to model this properly - breath_moles = environment.total_moles()/environment.volume*CELL_VOLUME*BREATH_PERCENTAGE - - breath = loc.remove_air(breath_moles) + breath = environment.remove_volume(CELL_VOLUME * BREATH_PERCENTAGE) // Handle chem smoke effect -- Doohl for(var/obj/effect/effect/smoke/chem/smoke in view(1, src)) @@ -178,14 +175,15 @@ return 0 var/toxins_used = 0 - var/breath_pressure = (breath.total_moles()*R_IDEAL_GAS_EQUATION*breath.temperature)/BREATH_VOLUME + breath.volume = BREATH_VOLUME + breath.update_values() //Partial pressure of the toxins in our breath - var/Toxins_pp = (breath.toxins/breath.total_moles())*breath_pressure + var/Toxins_pp = (breath.toxins / breath.total_moles()) * breath.pressure if(Toxins_pp) // Detect toxins in air - AdjustPlasma(breath.toxins*250) + AdjustPlasma(breath.toxins * 250) toxins_alert = max(toxins_alert, 1) toxins_used = breath.toxins @@ -199,7 +197,7 @@ if(breath.temperature > (T0C+66) && !(M_RESIST_HEAT in mutations)) // Hot air hurts :( if(prob(20)) - to_chat(src, "You feel a searing heat in your lungs !") + to_chat(src, "You feel a searing heat in your lungs!") fire_alert = max(fire_alert, 1) else fire_alert = 0 diff --git a/code/modules/mob/living/carbon/alien/larva/life.dm b/code/modules/mob/living/carbon/alien/larva/life.dm index d290146337e..c6fa440ec6b 100644 --- a/code/modules/mob/living/carbon/alien/larva/life.dm +++ b/code/modules/mob/living/carbon/alien/larva/life.dm @@ -101,16 +101,13 @@ var/obj/location_as_object = loc breath = location_as_object.handle_internal_lifeform(src, BREATH_VOLUME) else if(istype(loc, /turf/)) - var/breath_moles = 0 /*if(environment.return_pressure() > ONE_ATMOSPHERE) // Loads of air around (pressure effect will be handled elsewhere), so lets just take a enough to fill our lungs at normal atmos pressure (using n = Pv/RT) breath_moles = (ONE_ATMOSPHERE*BREATH_VOLUME/R_IDEAL_GAS_EQUATION*environment.temperature) else */ // Not enough air around, take a percentage of what's there to model this properly - breath_moles = environment.total_moles()/environment.volume*CELL_VOLUME*BREATH_PERCENTAGE - - breath = loc.remove_air(breath_moles) + breath = environment.remove_volume(CELL_VOLUME * BREATH_PERCENTAGE) // Handle chem smoke effect -- Doohl for(var/obj/effect/effect/smoke/chem/smoke in view(1, src)) @@ -159,14 +156,15 @@ return 0 var/toxins_used = 0 - var/breath_pressure = (breath.total_moles()*R_IDEAL_GAS_EQUATION*breath.temperature)/BREATH_VOLUME + breath.volume = BREATH_VOLUME + breath.update_values() //Partial pressure of the toxins in our breath - var/Toxins_pp = (breath.toxins/breath.total_moles())*breath_pressure + var/Toxins_pp = (breath.toxins / breath.total_moles()) * breath.pressure if(Toxins_pp) // Detect toxins in air - AdjustPlasma(breath.toxins*250) + AdjustPlasma(breath.toxins * 250) toxins_alert = max(toxins_alert, 1) toxins_used = breath.toxins diff --git a/code/modules/mob/living/carbon/alien/special/facehugger.dm b/code/modules/mob/living/carbon/alien/special/facehugger.dm index f9f92408c20..81907c304c8 100644 --- a/code/modules/mob/living/carbon/alien/special/facehugger.dm +++ b/code/modules/mob/living/carbon/alien/special/facehugger.dm @@ -38,7 +38,7 @@ var/target_time = 0.5 // seconds var/walk_speed = 1 var/nextwalk = FALSE - var/mob/living/carbon/target = null + var/mob/living/target = null /obj/item/clothing/mask/facehugger/can_contaminate() return FALSE @@ -52,16 +52,16 @@ /obj/item/clothing/mask/facehugger/process() healthcheck() followtarget() + spreadout() /obj/item/clothing/mask/facehugger/proc/findtarget() if(!real) return - for(var/mob/living/carbon/T in hearers(src,4)) - if(!ishuman(T) && !ismonkey(T)) + target = null + for(var/mob/living/T in hearers(src,4)) + if(!CanHug(T, src)) continue - if(!CanHug(T)) - continue - if(T && (T.stat != DEAD && T.stat != UNCONSCIOUS) ) + if(T && (!T.isUnconscious() ) ) if(get_dist(loc, T.loc) <= 4) target = T @@ -70,31 +70,38 @@ /obj/item/clothing/mask/facehugger/proc/followtarget() if(!real) return // Why are you trying to path stupid toy - if(!target || target.stat == DEAD || target.stat == UNCONSCIOUS || target.status_flags & XENO_HOST) + if(!target || target.isUnconscious() || target.status_flags & XENO_HOST) findtarget() return - if(loc && loc == get_turf(src) && !attached && !stat && nextwalk <= world.time) + if(loc && isturf(loc) && !attached && !stat && nextwalk <= world.time) nextwalk = world.time + walk_speed var/dist = get_dist(loc, target.loc) if(dist > 4) + target = null return //We'll let the facehugger do nothing for a bit, since it's fucking up. var/obj/item/clothing/mask/facehugger/F = target.is_wearing_item(/obj/item/clothing/mask/facehugger, slot_wear_mask) - if(F && F.sterile) // Toy's won't prevent real huggers + if(F && !F.sterile) // Toys won't prevent real huggers findtarget() return else step_towards(src, target, 0) if(dist <= 1) - if(CanHug(target)) + if(CanHug(target, src) && isturf(target.loc)) //Fix for hugging through mechs and closets Attach(target) return else - target = null walk(src,0) findtarget() return +/obj/item/clothing/mask/facehugger/proc/spreadout() + if(!target && isturf(loc) && stat == CONSCIOUS) + for(var/obj/item/clothing/mask/facehugger/F in loc) + if(F != src && F.stat != DEAD) + step(src, pick(alldirs), 0) + break + //END HUGGER MOVEMENT AI @@ -135,7 +142,7 @@ /obj/item/clothing/mask/facehugger/proc/healthcheck() if(health <= 0) icon_state = "[initial(icon_state)]_dead" - Die() + death() /obj/item/clothing/mask/facehugger/attack(mob/living/M as mob, mob/user as mob) ..() @@ -176,7 +183,7 @@ /obj/item/clothing/mask/facehugger/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) if(exposed_temperature > 300) - Die() + death() return /obj/item/clothing/mask/facehugger/equipped(mob/M) @@ -192,8 +199,9 @@ return FALSE /obj/item/clothing/mask/facehugger/HasProximity(atom/movable/AM as mob|obj) - if(CanHug(AM)) - return Attach(AM) + if(isliving(AM)) + if(CanHug(AM, src)) + return Attach(AM) return FALSE /obj/item/clothing/mask/facehugger/throw_at(atom/target, range, speed) @@ -208,26 +216,24 @@ ..() if(stat == CONSCIOUS) icon_state = "[initial(icon_state)]" - Attach(hit_atom) + if(isliving(hit_atom)) + Attach(hit_atom) -/obj/item/clothing/mask/facehugger/proc/Attach(mob/living/M as mob) +/obj/item/clothing/mask/facehugger/proc/Attach(mob/living/L) var/preggers = rand(MIN_IMPREGNATION_TIME,MAX_IMPREGNATION_TIME) - if( (!iscorgi(M) && !iscarbon(M)) || isalien(M)) + if(isalien(L)) + return FALSE + if(L.status_flags & XENO_HOST) + visible_message("An alien tries to place a facehugger on [L] but it refuses sloppy seconds!") return FALSE - if(iscarbon(M) && M.status_flags & XENO_HOST) - visible_message("An alien tries to place a facehugger on [M] but it refuses sloppy seconds!") - return if(attached) return FALSE - if(!Adjacent(M)) + if(!Adjacent(L)) return FALSE else attached++ spawn(MAX_IMPREGNATION_TIME) attached = FALSE - - var/mob/living/L = M //just so I don't need to use : - if(loc == L) return FALSE if(stat != CONSCIOUS) @@ -237,14 +243,14 @@ L.visible_message("\The [src] leaps at [L]'s face!") + if(!CanHug(L, src)) + return FALSE + if(ishuman(L)) var/mob/living/carbon/human/H = L var/obj/item/mouth_protection = H.get_body_part_coverage(MOUTH) if(!real && mouth_protection) return //Toys really shouldn't be forcefully removing gear - var/obj/item/clothing/mask/facehugger/hugger = H.get_item_by_slot(slot_wear_mask) - if(istype(hugger) && !hugger.sterile && !sterile) // Lamarr won't fight over faces and neither will normal huggers. - return if(mouth_protection && mouth_protection != H.wear_mask) //can't be protected with your own mask, has to be a hat stat_collection.xeno_faces_protected++ @@ -257,22 +263,23 @@ GoIdle(TIME_IDLE_AFTER_HEAD_DENIED) return else - H.visible_message("\The [src] bounces off of the [mouth_protection]!") + H.visible_message("\The [src] bounces off of \the [mouth_protection]!") if(prob(CHANCE_TO_DIE_AFTER_HEAD_DENIED) && !sterile) - Die() + death() return else GoIdle(TIME_IDLE_AFTER_HEAD_DENIED) return return - if(iscarbon(M)) + if(iscarbon(L)) var/mob/living/carbon/target = L + var/obj/item/clothing/W = target.get_item_by_slot(slot_wear_mask) + var/obj/item/weapon/tank/had_internal = target.internal - if(target.get_item_by_slot(slot_wear_mask)) + if(W && W != src) if(prob(CHANCE_TO_NOT_REMOVE_MASKS)) return FALSE - var/obj/item/clothing/W = target.wear_mask if(!W.canremove) return FALSE target.drop_from_inventory(W) @@ -282,15 +289,45 @@ forceMove(target) target.equip_to_slot(src, slot_wear_mask) target.update_inv_wear_mask() + target.internal = had_internal //Try to keep the host ALIVE + target.update_internals() - if(!sterile) + if(!sterile && target.hasmouth) L.Paralyse((preggers/10)+10) //something like 25 ticks = 20 seconds with the default settings - else if (iscorgi(M)) - var/mob/living/simple_animal/corgi/C = M + else if (iscorgi(L)) + var/mob/living/simple_animal/corgi/C = L + var/obj/item/clothing/head/headwear = C.inventory_head + var/rng = 100 + var/obj/item/clothing/mask/facehugger/hugger = C.facehugger + + if(hugger && !hugger.sterile) + return + + if(headwear) + if(istype(headwear, /obj/item/clothing/head/cardborg)) + rng = CHANCE_TO_REMOVE_HEADWEAR + else if(istype(headwear, /obj/item/clothing/head/helmet/space/rig)) + rng = CHANCE_TO_REMOVE_SPECIAL_HEADWEAR + + if(prob(rng)) + C.visible_message("\The [src] smashes against [C]'s \the [headwear], and rips it off in the process!") + C.drop_from_inventory(headwear) + GoIdle(TIME_IDLE_AFTER_HEAD_DENIED) + return + else + C.visible_message("\The [src] bounces off of \the [headwear]!") + if(prob(CHANCE_TO_DIE_AFTER_HEAD_DENIED) && !sterile) + death() + return + else + GoIdle(TIME_IDLE_AFTER_HEAD_DENIED) + return + return + forceMove(C) C.facehugger = src C.wear_mask = src - //C.regenerate_icons() + C.regenerate_icons() GoIdle(TIME_IDLE_AFTER_ATTACH_DENIED) //so it doesn't jump the people that tear it off @@ -303,7 +340,9 @@ if(!target || target.wear_mask != src || target.stat == DEAD) //was taken off or something return - if(!sterile) + var/mob/living/carbon/CA = target + + if(!sterile && !(istype(CA) && !CA.hasmouth)) var/obj/item/alien_embryo/E = new (target) target.status_flags |= XENO_HOST if(istype(target, /mob/living/carbon/human)) @@ -313,13 +352,15 @@ target.visible_message("\The [src] falls limp after violating [target]'s face !") stat_collection.xeno_faces_hugged++ - Die() + death() + //target.drop_from_inventory(src) icon_state = "[initial(icon_state)]_impregnated" if(iscorgi(target)) var/mob/living/simple_animal/corgi/C = target forceMove(get_turf(C)) C.facehugger = null + C.regenerate_icons() else target.visible_message("\The [src] violates [target]'s face !") return @@ -346,7 +387,7 @@ GoActive() return -/obj/item/clothing/mask/facehugger/proc/Die() +/obj/item/clothing/mask/facehugger/proc/death() if(stat == DEAD || !real) return target = null @@ -358,20 +399,30 @@ visible_message("\The [src] curls up into a ball!") - return -/proc/CanHug(var/mob/M) +/proc/CanHug(mob/living/M, obj/item/clothing/mask/facehugger/hugger = null) + if(isalien(M)) + return FALSE + if(M.status_flags & XENO_HOST) + return FALSE if(iscorgi(M)) + var/mob/living/simple_animal/corgi/corgi = M + if(corgi.facehugger && !corgi.facehugger.sterile) + return FALSE + return TRUE - if(!iscarbon(M) || isalien(M) || isslime(M)) + if(!ishuman(M) && !ismonkey(M)) return FALSE var/mob/living/carbon/C = M - if(C && (istype(C.wear_mask, /obj/item/clothing/mask/facehugger) || C.status_flags & XENO_HOST)) + var/obj/item/clothing/mask/facehugger/F = C.is_wearing_item(/obj/item/clothing/mask/facehugger, slot_wear_mask) + + if(F && (!F.sterile || hugger.sterile) && F != hugger) // Lamarr won't fight over faces and neither will normal huggers. return FALSE + return TRUE /obj/item/clothing/mask/facehugger/acidable() diff --git a/code/modules/mob/living/carbon/brain/MMI.dm b/code/modules/mob/living/carbon/brain/MMI.dm index c28fd0fad6d..df337ca64f4 100644 --- a/code/modules/mob/living/carbon/brain/MMI.dm +++ b/code/modules/mob/living/carbon/brain/MMI.dm @@ -66,7 +66,7 @@ obj/item/device/mmi/Destroy() //canmove = 0 icon = null invisibility = 101 - var/mob/living/silicon/robot/mommi/M = new /mob/living/silicon/robot/mommi(get_turf(loc)) + var/mob/living/silicon/robot/mommi/M = new /mob/living/silicon/robot/mommi/nt(get_turf(loc)) if(!M) return M.invisibility = 0 @@ -278,7 +278,7 @@ obj/item/device/mmi/Destroy() else if(!src.brainmob.key) to_chat(user, "It seems to be in a deep dream-state")//ghosted - to_chat(user, "It's interface is [locked ? "locked" : "unlocked"] ") + to_chat(user, "Its interface is [locked ? "locked" : "unlocked"] ") to_chat(user, "*---------*") /obj/item/device/mmi/OnMobDeath(var/mob/living/carbon/brain/B) diff --git a/code/modules/mob/living/carbon/brain/brain_item.dm b/code/modules/mob/living/carbon/brain/brain_item.dm index 8724f257580..861a2869da9 100644 --- a/code/modules/mob/living/carbon/brain/brain_item.dm +++ b/code/modules/mob/living/carbon/brain/brain_item.dm @@ -88,4 +88,12 @@ organ_type = /datum/organ/internal/brain/slime_core /obj/item/organ/internal/brain/slime_core/process() - processing_objects -= src \ No newline at end of file + processing_objects -= src + +/obj/item/organ/internal/brain/mushroom + name = "plump helmet brain" + desc = "At first glance, it looks like a popular miner delicacy, but is in fact the primary function of thought for a mushroom person." + icon_state = "plump_pie" + icon = 'icons/obj/food.dmi' + health = 600 + origin_tech = Tc_BIOTECH + "=4" \ No newline at end of file diff --git a/code/modules/mob/living/carbon/brain/life.dm b/code/modules/mob/living/carbon/brain/life.dm index 4ec70371208..cbdcc8ed7ba 100644 --- a/code/modules/mob/living/carbon/brain/life.dm +++ b/code/modules/mob/living/carbon/brain/life.dm @@ -74,7 +74,7 @@ /mob/living/carbon/brain/proc/handle_environment(datum/gas_mixture/environment) if(!environment || (flags & INVULNERABLE)) return - var/environment_heat_capacity = environment.heat_capacity() + var/environment_heat_capacity = environment.heat_capacity() / environment.volume * CELL_VOLUME if(istype(get_turf(src), /turf/space)) var/turf/heat_turf = get_turf(src) environment_heat_capacity = heat_turf.heat_capacity @@ -244,16 +244,23 @@ update_pull_icon() if (client) -// clear_fullscreens() if(src.eye_blind || blinded) overlay_fullscreen("blind", /obj/abstract/screen/fullscreen/blind) + else + clear_fullscreen("blind") if (src.disabilities & NEARSIGHTED) overlay_fullscreen("impaired", /obj/abstract/screen/fullscreen/impaired) + else + clear_fullscreen("impaired") if (src.eye_blurry) overlay_fullscreen("blurry", /obj/abstract/screen/fullscreen/blurry) + else + clear_fullscreen("blurry") if (src.druggy) overlay_fullscreen("high", /obj/abstract/screen/fullscreen/high) + else + clear_fullscreen("high") if (stat != 2) if (machine) diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 619debca550..48bc1012e96 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -212,7 +212,7 @@ AdjustParalysis(-3) AdjustStunned(-3) AdjustKnockdown(-3) - playsound(get_turf(src), 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + playsound(src, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) M.visible_message( \ "[M] shakes [src] trying to wake [t_him] up!", \ "You shake [src] trying to wake [t_him] up!", \ @@ -272,13 +272,13 @@ if (U && U.wired && U.cell && U.cell.charge >= STUNGLOVES_CHARGE_COST && T.siemens_coefficient == 0) to_chat(M, "\The [src]'s insulated gloves prevent them from being shocked.") - playsound(get_turf(src), 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + playsound(src, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) M.visible_message( \ "[M] shakes [ismartian(M) ? "tentacles" : "hands"] with [src].", \ "You shake [ismartian(M) ? "tentacles" : "hands"] with [src].", \ ) else - playsound(get_turf(src), 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + playsound(src, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) M.visible_message( \ "[M] gives [src] a [pick("hug","warm embrace")].", \ "You hug [src].", \ @@ -500,20 +500,21 @@ /mob/living/carbon/CheckSlip() return !locked_to && !lying && !unslippable -/mob/living/carbon/proc/Slip(stun_amount, weaken_amount, slip_on_walking = 0) +/mob/living/proc/Slip(stun_amount, weaken_amount, slip_on_walking = 0) + stop_pulling() + Stun(stun_amount) + Knockdown(weaken_amount) + return 1 + +/mob/living/carbon/Slip(stun_amount, weaken_amount, slip_on_walking = 0) if(!slip_on_walking && m_intent == "walk") return 0 if (CheckSlip() < 1 || !on_foot()) return 0 - - stop_pulling() - Stun(stun_amount) - Knockdown(weaken_amount) - - playsound(get_turf(src), 'sound/misc/slip.ogg', 50, 1, -3) - - return 1 + if(..()) + playsound(src, 'sound/misc/slip.ogg', 50, 1, -3) + return 1 /mob/living/carbon/proc/transferImplantsTo(mob/living/carbon/newmob) for(var/obj/item/weapon/implant/I in src) @@ -625,7 +626,7 @@ /mob/living/carbon/movement_tally_multiplier() . = ..() - if(!istype(loc, /turf/space) && !reagents.has_any_reagents(list(HYPERZINE,COCAINE))) + if(!istype(loc, /turf/space)) for(var/obj/item/I in get_clothing_items()) if(I.slowdown <= 0) testing("[I] HAD A SLOWDOWN OF <=0 OH DEAR") @@ -636,6 +637,11 @@ if(I.flags & SLOWDOWN_WHEN_CARRIED) . *= I.slowdown + if(reagents.has_any_reagents(list(HYPERZINE,COCAINE))) + . *= 0.4 + if(. < 1)//we don't want to move faster than the base speed + . = 1 + /mob/living/carbon/base_movement_tally() . = ..() if(flying) @@ -677,7 +683,7 @@ to_chat(src, "Interference is disrupting the connection with the mind of [M].") return 0 if(ismartian(M)) - var/mob/living/carbon/martian/MR = M + var/mob/living/carbon/complex/martian/MR = M if(MR.head) if(istype(MR.head, /obj/item/clothing/head/helmet/space/martian) || istype(MR.head,/obj/item/clothing/head/tinfoil)) to_chat(src, "Interference is disrupting the connection with the mind of [M].") diff --git a/code/modules/mob/living/carbon/combat.dm b/code/modules/mob/living/carbon/combat.dm index 35d367b70f4..4c11e21f985 100644 --- a/code/modules/mob/living/carbon/combat.dm +++ b/code/modules/mob/living/carbon/combat.dm @@ -56,7 +56,7 @@ return TRUE //We still connected if(!I.force) return TRUE - - apply_damage(I.force, I.damtype, affecting, armor , I.is_sharp(), used_weapon = I) + var/damage = run_armor_absorb(target_zone, I.damtype, I.force) + apply_damage(damage, I.damtype, affecting, armor , I.is_sharp(), used_weapon = I) return TRUE \ No newline at end of file diff --git a/code/modules/mob/living/carbon/martian/combat.dm b/code/modules/mob/living/carbon/complex/combat.dm similarity index 72% rename from code/modules/mob/living/carbon/martian/combat.dm rename to code/modules/mob/living/carbon/complex/combat.dm index 9d4cdd1a142..35ad9366cd0 100644 --- a/code/modules/mob/living/carbon/martian/combat.dm +++ b/code/modules/mob/living/carbon/complex/combat.dm @@ -1,25 +1,16 @@ -/mob/living/carbon/martian/get_unarmed_damage_zone(mob/living/victim) +/mob/living/carbon/complex/get_unarmed_damage_zone(mob/living/victim) return zone_sel.selecting -/mob/living/carbon/martian/knockout_chance_modifier() +/mob/living/carbon/complex/knockout_chance_modifier() return 0 //Punches don't stun -/mob/living/carbon/martian/bullet_act(var/obj/item/projectile/P, var/def_zone) +/mob/living/carbon/complex/bullet_act(var/obj/item/projectile/P, var/def_zone) if(check_shields(P.damage, "the [P.name]")) P.on_hit(src, 2) return 2 return (..(P , def_zone)) -/mob/living/carbon/martian/getarmor(var/def_zone, var/type) - - var/armorscore = 0 - if((def_zone == "head") || (def_zone == "eyes") || (def_zone == "mouth")) - if(head) - armorscore = head.armor[type] - - return armorscore - -/mob/living/carbon/martian/attack_hand(mob/living/M) +/mob/living/carbon/complex/attack_hand(mob/living/M) switch(M.a_intent) if(I_HELP) help_shake_act(M) @@ -33,7 +24,7 @@ if(I_DISARM) M.disarm_mob(src) -/mob/living/carbon/martian/attack_alien(mob/living/M) +/mob/living/carbon/complex/attack_alien(mob/living/M) switch(M.a_intent) if (I_HELP) visible_message("[M] caresses [src] with its scythe like arm.") @@ -47,16 +38,16 @@ if (I_DISARM) return M.disarm_mob(src) -/mob/living/carbon/martian/attack_slime(mob/living/carbon/slime/M) +/mob/living/carbon/complex/attack_slime(mob/living/carbon/slime/M) M.unarmed_attack_mob(src) -/mob/living/carbon/martian/attack_martian(mob/M) +/mob/living/carbon/complex/attack_martian(mob/M) return attack_hand(M) -/mob/living/carbon/martian/attack_paw(mob/M) +/mob/living/carbon/complex/attack_paw(mob/M) return attack_hand(M) -/mob/living/carbon/martian/disarm_mob(mob/living/target) +/mob/living/carbon/complex/disarm_mob(mob/living/target) add_logs(src, target, "disarmed", admin = (src.ckey && target.ckey) ? TRUE : FALSE) //Only add this to the server logs if both mobs were controlled by player if(target.disarmed_by(src)) diff --git a/code/modules/mob/living/carbon/complex/complex_defines.dm b/code/modules/mob/living/carbon/complex/complex_defines.dm new file mode 100644 index 00000000000..a52e37248ef --- /dev/null +++ b/code/modules/mob/living/carbon/complex/complex_defines.dm @@ -0,0 +1,17 @@ +/mob/living/carbon/complex + var/icon_state_standing + var/icon_state_lying + var/icon_state_dead + var/flag = 0 + var/oxygen_alert = 0 + var/toxins_alert = 0 + var/fire_alert = 0 + var/pressure_alert = 0 + base_insulation = 0.5 + var/temperature_alert = 0 + var/safe_oxygen_min = 16 // Minimum safe partial pressure of O2, in kPa + var/co2overloadtime = null + +/mob/living/carbon/complex/New() + create_reagents(200) + ..() \ No newline at end of file diff --git a/code/modules/mob/living/carbon/martian/examine.dm b/code/modules/mob/living/carbon/complex/examine.dm similarity index 91% rename from code/modules/mob/living/carbon/martian/examine.dm rename to code/modules/mob/living/carbon/complex/examine.dm index 0e6338396ba..fcf2d675ed2 100644 --- a/code/modules/mob/living/carbon/martian/examine.dm +++ b/code/modules/mob/living/carbon/complex/examine.dm @@ -1,4 +1,4 @@ -/mob/living/carbon/martian/examine(mob/user) +/mob/living/carbon/complex/examine(mob/user) var/msg = "*---------*\nThis is [bicon(src)] \a [src]!\n" @@ -17,12 +17,12 @@ else msg += "" if (src.getBruteLoss()) - if (src.getBruteLoss() < 30) + if (src.getBruteLoss() < maxHealth/2) msg += "It has minor bruising.\n" else msg += "It has severe bruising!\n" if (src.getFireLoss()) - if (src.getFireLoss() < 30) + if (src.getFireLoss() < maxHealth/2) msg += "It has minor burns.\n" else msg += "It has severe burns!\n" diff --git a/code/modules/mob/living/carbon/complex/gondola/gondola.dm b/code/modules/mob/living/carbon/complex/gondola/gondola.dm new file mode 100644 index 00000000000..07fb2005154 --- /dev/null +++ b/code/modules/mob/living/carbon/complex/gondola/gondola.dm @@ -0,0 +1,29 @@ +/mob/living/carbon/complex/gondola + name = "gondola" + desc = "A calming presence in this strange land." + icon = 'icons/mob/gondola.dmi' + + icon_state_standing = "gondola" + icon_state_lying = "gondola_lying" + icon_state_dead = "gondola_dead" + + maxHealth = 75 + health = 75 + + held_items = list() + + size = SIZE_NORMAL + status_flags = CANSTUN|CANKNOCKDOWN|CANPARALYSE|CANPUSH + mob_bump_flag = HUMAN + mob_push_flags = ALLMOBS + mob_swap_flags = ALLMOBS + +/mob/living/carbon/complex/gondola/New() + icon_state_standing = pick("gondola","gondola_1") + icon_state_lying = "[icon_state_standing]_lying" + icon_state_dead = "[icon_state_dead]_dead" + ..() + + +/mob/living/carbon/complex/gondola/say() + return \ No newline at end of file diff --git a/code/modules/mob/living/carbon/complex/gondola/gondola_receive_music.dm b/code/modules/mob/living/carbon/complex/gondola/gondola_receive_music.dm new file mode 100644 index 00000000000..f07d0dd87bf --- /dev/null +++ b/code/modules/mob/living/carbon/complex/gondola/gondola_receive_music.dm @@ -0,0 +1,120 @@ +//Basically walking media receivers +/mob/living/carbon/complex/gondola + var/playing=0 + var/media_url="" + var/media_start_time=0 + var/area/master_area + var/media_frequency = 1234 // 123.4 MHz + var/media_crypto = null // Crypto key + + var/list/obj/machinery/media/transmitter/hooked = list() + var/exclusive_hook=null // Disables output to the room + +/mob/living/carbon/complex/gondola/New() + ..() + connect_frequency() + +/mob/living/carbon/complex/gondola/death(var/gibbed = FALSE) + disconnect_media_source() + ..(gibbed) + +/mob/living/carbon/complex/gondola/area_entered() + update_music() + +/mob/living/carbon/complex/gondola/proc/connect_frequency() + // This is basically media_receivers["[media_frequency]"] += src + var/list/receivers=list() + var/freq = num2text(media_frequency) + if(freq in media_receivers) + receivers = media_receivers[freq] + receivers.Add(src) + media_receivers[freq]=receivers + + // Check if there's a broadcast to tune into. + if(freq in media_transmitters) + // Pick a random broadcast in that frequency. + var/obj/machinery/media/transmitter/B = pick(media_transmitters[freq]) + if(B.media_crypto == media_crypto) // Crypto-key check, if needed. + receive_broadcast(B.media_url,B.media_start_time) + +/mob/living/carbon/complex/gondola/proc/receive_broadcast(var/url="", var/start_time=0) + media_url = url + media_start_time = start_time + update_music() + +/mob/living/carbon/complex/gondola/proc/disconnect_frequency() + var/list/receivers=list() + var/freq = num2text(media_frequency) + if(freq in media_receivers) + receivers = media_receivers[freq] + receivers.Remove(src) + media_receivers[freq]=receivers + + receive_broadcast() + +/mob/living/carbon/complex/gondola/update_music() + if(isDead(src)) + return + // Broadcasting shit + for(var/obj/machinery/media/transmitter/T in hooked) +// testing("[src] Writing media to [T].") + T.broadcast(media_url,media_start_time) + + if(exclusive_hook) + disconnect_media_source() // Just to be sure. + return + + update_media_source() + + // Bail if we lost connection to master. + if(!master_area) + return + + // Send update to clients. + for(var/mob/M in mobs_in_area(master_area)) + if(M == src) + continue + if(M && M.client) + M.update_music() + + ..() + +/mob/living/carbon/complex/gondola/proc/update_media_source() + var/area/A = get_area(src) + if(!A) + return + // Check if there's a media source already. + if(A.media_source && A.media_source!=src) //if it does, the new media source replaces it. basically, the last media source arrived gets played on top. + A.media_source.disconnect_media_source()//you can turn a media source off and on for it to come back on top. + A.media_source=src + master_area=A + return + + // Update Media Source. + if(!A.media_source) + A.media_source=src + + master_area=A + + +/mob/living/carbon/complex/gondola/proc/disconnect_media_source() + var/area/A = get_area(src) + + // Sanity + if(!A) + master_area=null + return + + // Check if there's a media source already. + if(A && A.media_source && A.media_source!=src) + master_area=null + return + + // Update Media Source. + A.media_source=null + + // Clients + for(var/mob/M in mobs_in_area(A)) + if(M && M.client) + M.update_music() + master_area=null \ No newline at end of file diff --git a/code/modules/mob/living/carbon/complex/inventory.dm b/code/modules/mob/living/carbon/complex/inventory.dm new file mode 100644 index 00000000000..006c3c95cd6 --- /dev/null +++ b/code/modules/mob/living/carbon/complex/inventory.dm @@ -0,0 +1,12 @@ +/mob/living/carbon/complex/equip_to_slot(obj/item/W, slot, redraw_mob = 1) + if(!istype(W)) + return + + if(src.is_holding_item(W)) + src.u_equip(W) + + W.hud_layerise() + W.equipped(src, slot) + W.forceMove(src) + if(client) + client.screen |= W \ No newline at end of file diff --git a/code/modules/mob/living/carbon/martian/life.dm b/code/modules/mob/living/carbon/complex/life.dm similarity index 82% rename from code/modules/mob/living/carbon/martian/life.dm rename to code/modules/mob/living/carbon/complex/life.dm index 481b70dbccf..a8bef0a0602 100644 --- a/code/modules/mob/living/carbon/martian/life.dm +++ b/code/modules/mob/living/carbon/complex/life.dm @@ -1,16 +1,4 @@ - -/mob/living/carbon/martian - var/oxygen_alert = 0 - var/toxins_alert = 0 - var/fire_alert = 0 - var/pressure_alert = 0 - base_insulation = 0.5 - var/temperature_alert = 0 - var/safe_oxygen_min = 16 // Minimum safe partial pressure of O2, in kPa - var/co2overloadtime = null - - -/mob/living/carbon/martian/Life() +/mob/living/carbon/complex/Life() set invisibility = 0 if(timestopped) @@ -61,7 +49,7 @@ // ATMOSPHERE, BREATHING, ALL THINGS INVOLVING AIR// -/mob/living/carbon/martian/proc/breathe() //This proc's used so many different times, you would think it would be under /carbon by now +/mob/living/carbon/complex/proc/breathe() //This proc's used so many different times, you would think it would be under /carbon by now if(flags & INVULNERABLE) return @@ -93,23 +81,7 @@ var/obj/location_as_object = loc breath = location_as_object.handle_internal_lifeform(src, BREATH_VOLUME) else if(istype(loc, /turf/)) - var/breath_moles = environment.total_moles()/environment.volume*CELL_VOLUME*BREATH_PERCENTAGE - breath = loc.remove_air(breath_moles) - - var/block = 0 - if(head) - if(istype(head, /obj/item/clothing/head/helmet/space/martian)) - block = 1 - - if(!block) - for(var/obj/effect/effect/smoke/chem/smoke in view(1, src)) - if(smoke.reagents.total_volume) - smoke.reagents.reaction(src, INGEST) - spawn(5) - if(smoke) - smoke.reagents.copy_to(src, 10) // I dunno, maybe the reagents enter the blood stream through the lungs? - break // If they breathe in the nasty stuff once, no need to continue checking - + breath = environment.remove_volume(CELL_VOLUME * BREATH_PERCENTAGE) else //Still give containing object the chance to interact if(istype(loc, /obj/)) @@ -120,17 +92,11 @@ if(breath) loc.assume_air(breath) -/mob/living/carbon/martian/proc/get_breath_from_internal(volume_needed) - //As this is a race that can only wear helmets, we'll have a fishbowl helmet that can accept tanks in place of having gas mask setups - if(head && istype(head, /obj/item/clothing/head/helmet/space/martian)) - var/obj/item/clothing/head/helmet/space/martian/fishbowl = head - if(fishbowl.tank && istype(fishbowl.tank, /obj/item/weapon/tank)) - var/obj/item/weapon/tank/internals = fishbowl.tank - return internals.remove_air_volume(volume_needed) +/mob/living/carbon/complex/proc/get_breath_from_internal(volume_needed) return null -/mob/living/carbon/martian/proc/handle_breath(datum/gas_mixture/breath) +/mob/living/carbon/complex/proc/handle_breath(datum/gas_mixture/breath) if((status_flags & GODMODE) || (flags & INVULNERABLE)) return @@ -148,14 +114,16 @@ var/SA_para_min = 0.5 var/SA_sleep_min = 5 var/oxygen_used = 0 - var/breath_pressure = (breath.total_moles()*R_IDEAL_GAS_EQUATION*breath.temperature)/BREATH_VOLUME + + breath.volume = BREATH_VOLUME + breath.update_values() //Partial pressure of the O2 in our breath - var/O2_pp = (breath.oxygen/breath.total_moles())*breath_pressure + var/O2_pp = (breath.oxygen / breath.total_moles()) * breath.pressure // Same, but for the toxins - var/Toxins_pp = (breath.toxins/breath.total_moles())*breath_pressure + var/Toxins_pp = (breath.toxins / breath.total_moles()) * breath.pressure // 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) - var/CO2_pp = (breath.carbon_dioxide/breath.total_moles())*breath_pressure + var/CO2_pp = (breath.carbon_dioxide / breath.total_moles()) * breath.pressure if(O2_pp < safe_oxygen_min) // Too little oxygen if(prob(20)) @@ -206,7 +174,7 @@ if(breath.trace_gases.len) // If there's some other shit in the air lets deal with it here. for(var/datum/gas/sleeping_agent/SA in breath.trace_gases) - var/SA_pp = (SA.moles/breath.total_moles())*breath_pressure + var/SA_pp = (SA.moles / breath.total_moles()) * breath.pressure if(SA_pp > SA_para_min) // Enough to make us paralysed for a bit Paralyse(3) // 3 gives them one second to wake up and run away a bit! if(SA_pp > SA_sleep_min) // Enough to make us sleep as well @@ -228,14 +196,12 @@ return 1 -/mob/living/carbon/martian/proc/handle_environment(datum/gas_mixture/environment) +/mob/living/carbon/complex/proc/handle_environment(datum/gas_mixture/environment) if(!environment || (flags & INVULNERABLE)) return - var/spaceproof = 0 - if(head && istype(head, /obj/item/clothing/head/helmet/space/martian)) - spaceproof = 1 //quick and dirt cheap. var/loc_temp = get_loc_temp(environment) - var/environment_heat_capacity = environment.heat_capacity() + var/spaceproof = is_spaceproof() + var/environment_heat_capacity = environment.heat_capacity() / environment.volume * CELL_VOLUME if(istype(get_turf(src), /turf/space)) var/turf/heat_turf = get_turf(src) environment_heat_capacity = heat_turf.heat_capacity @@ -248,12 +214,11 @@ var/thermal_protection = get_thermal_protection(get_heat_protection_flags(loc_temp)) //This returns a 0 - 1 value, which corresponds to the percentage of protection based on what you're wearing and what you're exposed to. if(thermal_protection < 1) bodytemperature += min((1 - thermal_protection) * ((loc_temp - get_skin_temperature()) / BODYTEMP_HEAT_DIVISOR), BODYTEMP_HEATING_MAX) - if(stat==DEAD) bodytemperature += 0.1*(environment.temperature - bodytemperature)*environment_heat_capacity/(environment_heat_capacity + 270000) - //Account for massive pressure differences + //Account for massive pressure differences var/pressure = environment.return_pressure() var/adjusted_pressure = calculate_affecting_pressure(pressure) //Returns how much pressure actually affects the mob. switch(adjusted_pressure) @@ -275,35 +240,32 @@ else pressure_alert = -1 - return - -/mob/living/carbon/martian/get_thermal_protection_flags() - var/thermal_protection_flags = 0 - if(head) - thermal_protection_flags |= head.body_parts_covered - return thermal_protection_flags +/mob/living/carbon/complex/proc/is_spaceproof() + if(flags & INVULNERABLE) + return TRUE + return FALSE -/mob/living/carbon/martian/calculate_affecting_pressure(var/pressure) +/mob/living/carbon/complex/get_thermal_protection_flags() + return 0 + +/mob/living/carbon/complex/calculate_affecting_pressure(var/pressure) ..() return pressure -/mob/living/carbon/martian/get_cold_protection() +/mob/living/carbon/complex/get_cold_protection() if(M_RESIST_COLD in mutations) return 1 //Fully protected from the cold. var/thermal_protection = 0.0 - if(head) - thermal_protection += head.return_thermal_protection() - var/max_protection = get_thermal_protection(get_thermal_protection_flags()) return min(thermal_protection,max_protection) -mob/living/carbon/martian/proc/handle_regular_status_updates() +/mob/living/carbon/complex/proc/handle_regular_status_updates() updatehealth() if(stat == DEAD) //DEAD. BROWN BREAD. SWIMMING WITH THE SPESS CARP @@ -391,7 +353,7 @@ mob/living/carbon/martian/proc/handle_regular_status_updates() druggy = max(druggy-1, 0) return 1 -/mob/living/carbon/martian/proc/handle_chemicals_in_body() +/mob/living/carbon/complex/proc/handle_chemicals_in_body() burn_calories(HUNGER_FACTOR,1) if(reagents) @@ -415,7 +377,7 @@ mob/living/carbon/martian/proc/handle_regular_status_updates() return //TODO: DEFERRED -/mob/living/carbon/martian/proc/handle_regular_hud_updates() +/mob/living/carbon/complex/proc/handle_regular_hud_updates() if(!client) return @@ -516,7 +478,7 @@ mob/living/carbon/martian/proc/handle_regular_status_updates() return 1 -/mob/living/carbon/martian/undergoing_hypothermia() +/mob/living/carbon/complex/undergoing_hypothermia() if((status_flags & GODMODE) || (flags & INVULNERABLE) || istype(loc, /obj/machinery/atmospherics/unary/cryo_cell)) return NO_HYPOTHERMIA @@ -529,4 +491,4 @@ mob/living/carbon/martian/proc/handle_regular_status_updates() return SEVERE_HYPOTHERMIA // unconcious, not shivering if(-T0C to 260) return PROFOUND_HYPOTHERMIA // no vital signs - return NO_HYPOTHERMIA \ No newline at end of file + return NO_HYPOTHERMIA diff --git a/code/modules/mob/living/carbon/complex/martian/combat.dm b/code/modules/mob/living/carbon/complex/martian/combat.dm new file mode 100644 index 00000000000..4d5cbbac0cf --- /dev/null +++ b/code/modules/mob/living/carbon/complex/martian/combat.dm @@ -0,0 +1,8 @@ +/mob/living/carbon/complex/martian/getarmor(var/def_zone, var/type) + + var/armorscore = 0 + if((def_zone == "head") || (def_zone == "eyes") || (def_zone == "mouth")) + if(head) + armorscore = head.armor[type] + + return armorscore \ No newline at end of file diff --git a/code/modules/mob/living/carbon/martian/inventory.dm b/code/modules/mob/living/carbon/complex/martian/inventory.dm similarity index 73% rename from code/modules/mob/living/carbon/martian/inventory.dm rename to code/modules/mob/living/carbon/complex/martian/inventory.dm index fd87e45a1b3..9e2ce4b790a 100644 --- a/code/modules/mob/living/carbon/martian/inventory.dm +++ b/code/modules/mob/living/carbon/complex/martian/inventory.dm @@ -1,5 +1,4 @@ - -/mob/living/carbon/martian/get_item_offset_by_index(index) +/mob/living/carbon/complex/martian/get_item_offset_by_index(index) switch(index) if(1,6) return list("x"=0, "y"=0) @@ -10,7 +9,7 @@ return list() -/mob/living/carbon/martian/get_held_item_ui_location(index) +/mob/living/carbon/complex/martian/get_held_item_ui_location(index) if(!is_valid_hand_index(index)) return @@ -30,7 +29,7 @@ else return ..() -/mob/living/carbon/martian/get_index_limb_name(index) +/mob/living/carbon/complex/martian/get_index_limb_name(index) if(!index) index = active_hand @@ -50,14 +49,14 @@ else return "tentacle" -/mob/living/carbon/martian/get_direction_by_index(index) +/mob/living/carbon/complex/martian/get_direction_by_index(index) if(index <= 3) return "right_hand" else return "left_hand" -/mob/living/carbon/martian/GetAccess() +/mob/living/carbon/complex/martian/GetAccess() var/list/ACL=list() for(var/obj/item/I in held_items) @@ -65,7 +64,7 @@ return ACL -/mob/living/carbon/martian/get_visible_id() +/mob/living/carbon/complex/martian/get_visible_id() var/id = null for(var/obj/item/I in held_items) id = I.GetID() @@ -73,10 +72,10 @@ break return id -/mob/living/carbon/martian/can_wield() +/mob/living/carbon/complex/martian/can_wield() return 1 -/mob/living/carbon/martian/u_equip(obj/item/W, dropped = 1, var/slot = null) +/mob/living/carbon/complex/martian/u_equip(obj/item/W, dropped = 1, var/slot = null) var/success = 0 if(!W) @@ -102,24 +101,7 @@ return -/mob/living/carbon/martian/equip_to_slot(obj/item/W, slot, redraw_mob = 1) - if(!istype(W)) - return - - if(src.is_holding_item(W)) - src.u_equip(W) - - if(slot == slot_head) - head = W - update_inv_head(redraw_mob) - - W.hud_layerise() - W.equipped(src, slot) - W.forceMove(src) - if(client) - client.screen |= W - -/mob/living/carbon/martian/abiotic() +/mob/living/carbon/complex/martian/abiotic() for(var/obj/item/I in held_items) if(I.abstract) continue @@ -128,7 +110,7 @@ return head -/mob/living/carbon/martian/show_inv(mob/living/carbon/user) +/mob/living/carbon/complex/martian/show_inv(mob/living/carbon/user) user.set_machine(src) var/dat @@ -150,8 +132,18 @@ // Return the item currently in the slot ID -/mob/living/carbon/martian/get_item_by_slot(slot_id) +/mob/living/carbon/complex/martian/get_item_by_slot(slot_id) switch(slot_id) if(slot_head) return head return null + +/mob/living/carbon/complex/martian/equip_to_slot(obj/item/W, slot, redraw_mob = 1) + if(!istype(W)) + return + + if(slot == slot_head) + head = W + update_inv_head(redraw_mob) + + ..() \ No newline at end of file diff --git a/code/modules/mob/living/carbon/complex/martian/life.dm b/code/modules/mob/living/carbon/complex/martian/life.dm new file mode 100644 index 00000000000..03b12641858 --- /dev/null +++ b/code/modules/mob/living/carbon/complex/martian/life.dm @@ -0,0 +1,49 @@ + +/mob/living/carbon/complex/martian/get_breath_from_internal(volume_needed) + //As this is a race that can only wear helmets, we'll have a fishbowl helmet that can accept tanks in place of having gas mask setups + if(head && istype(head, /obj/item/clothing/head/helmet/space/martian)) + var/obj/item/clothing/head/helmet/space/martian/fishbowl = head + if(fishbowl.tank && istype(fishbowl.tank, /obj/item/weapon/tank)) + var/obj/item/weapon/tank/internals = fishbowl.tank + return internals.remove_air_volume(volume_needed) + return null + +/mob/living/carbon/complex/martian/breathe() + .=..() + var/block = 0 + if(head) + if(istype(head, /obj/item/clothing/head/helmet/space/martian)) + block = 1 + + if(!block) + for(var/obj/effect/effect/smoke/chem/smoke in view(1, src)) + if(smoke.reagents.total_volume) + smoke.reagents.reaction(src, INGEST) + spawn(5) + if(smoke) + smoke.reagents.copy_to(src, 10) // I dunno, maybe the reagents enter the blood stream through the lungs? + break // If they breathe in the nasty stuff once, no need to continue checking + +/mob/living/carbon/complex/martian/is_spaceproof() + if(head && istype(head, /obj/item/clothing/head/helmet/space/martian)) + return TRUE + return ..() + +/mob/living/carbon/complex/martian/get_thermal_protection_flags() + var/thermal_protection_flags = 0 + if(head) + thermal_protection_flags |= head.body_parts_covered + return thermal_protection_flags + +/mob/living/carbon/complex/martian/get_cold_protection() + + if(M_RESIST_COLD in mutations) + return 1 //Fully protected from the cold. + + var/thermal_protection = 0.0 + + if(head) + thermal_protection += head.return_thermal_protection() + + var/max_protection = get_thermal_protection(get_thermal_protection_flags()) + return min(thermal_protection,max_protection) diff --git a/code/modules/mob/living/carbon/martian/martian.dm b/code/modules/mob/living/carbon/complex/martian/martian.dm similarity index 75% rename from code/modules/mob/living/carbon/martian/martian.dm rename to code/modules/mob/living/carbon/complex/martian/martian.dm index 759e10b75b7..5bbed85dfd2 100644 --- a/code/modules/mob/living/carbon/martian/martian.dm +++ b/code/modules/mob/living/carbon/complex/martian/martian.dm @@ -16,7 +16,7 @@ */ -/mob/living/carbon/martian +/mob/living/carbon/complex/martian name = "martian" desc = "An alien resembling an overgrown octopus." voice_name = "martian" @@ -24,7 +24,7 @@ icon = 'icons/mob/martian.dmi' icon_state = "martian" - species_type = /mob/living/carbon/martian + species_type = /mob/living/carbon/complex/martian speak_emote = list("blorbles","burbles") held_items = list(null, null, null, null, null, null) //6 hands @@ -46,33 +46,34 @@ //Inventory slots var/obj/item/head //hat - var/icon_state_standing = "martian" - var/icon_state_lying = "lying" - var/icon_state_dead = "dead" + icon_state_standing = "martian" + icon_state_lying = "lying" + icon_state_dead = "dead" - var/flag = 0 + flag = 0 -/mob/living/carbon/martian/New() - create_reagents(200) + base_insulation = 0.5 + +/mob/living/carbon/complex/martian/New() name = pick("martian","scootaloo","squid","rootmarian","phoronitian","sepiida","octopodiforme",\ "bolitaenides","belemnites","astrocanthoteuthis","octodad","ocotillo","kalamarian") add_language(LANGUAGE_MARTIAN) default_language = all_languages[LANGUAGE_MARTIAN] ..() -/mob/living/carbon/martian/Destroy() +/mob/living/carbon/complex/martian/Destroy() head = null ..() #ifdef MARTIANS_AMBIDEXTROUS -/mob/living/carbon/martian/do_after_hand_check(held_item) +/mob/living/carbon/complex/martian/do_after_hand_check(held_item) //Normally do_after breaks if you switch hands. With martians, it will only break if the used item is dropped //This lets them do multiple things at once. return (held_items.Find(held_item)) #endif -/mob/living/carbon/martian/eyecheck() +/mob/living/carbon/complex/martian/eyecheck() var/obj/item/clothing/head/headwear = src.head var/protection if(headwear) @@ -80,22 +81,22 @@ return Clamp(protection, -2, 2) -/mob/living/carbon/martian/earprot() +/mob/living/carbon/complex/martian/earprot() return 1 -/mob/living/carbon/martian/dexterity_check() +/mob/living/carbon/complex/martian/dexterity_check() return TRUE -/mob/living/carbon/martian/IsAdvancedToolUser() +/mob/living/carbon/complex/martian/IsAdvancedToolUser() return TRUE -/mob/living/carbon/martian/Process_Spaceslipping() +/mob/living/carbon/complex/martian/Process_Spaceslipping() return 0 //No slipping -/mob/living/carbon/martian/has_eyes() +/mob/living/carbon/complex/martian/has_eyes() return FALSE -/mob/living/carbon/martian/updatehealth() +/mob/living/carbon/complex/martian/updatehealth() if(status_flags & GODMODE) health = maxHealth stat = CONSCIOUS @@ -103,7 +104,7 @@ health = maxHealth - getOxyLoss() - getFireLoss() - getBruteLoss() - getCloneLoss() -/mob/living/carbon/martian/ex_act(severity) +/mob/living/carbon/complex/martian/ex_act(severity) if(flags & INVULNERABLE) return @@ -127,11 +128,11 @@ updatehealth() -/mob/living/carbon/martian/Login() +/mob/living/carbon/complex/martian/Login() ..() update_hud() -/mob/living/carbon/martian/Stat() +/mob/living/carbon/complex/martian/Stat() ..() if(statpanel("Status")) stat(null, "Intent: [a_intent]") diff --git a/code/modules/mob/living/carbon/martian/update_icons.dm b/code/modules/mob/living/carbon/complex/martian/update_icons.dm similarity index 72% rename from code/modules/mob/living/carbon/martian/update_icons.dm rename to code/modules/mob/living/carbon/complex/martian/update_icons.dm index 2ef52becbf7..608653ea9ca 100644 --- a/code/modules/mob/living/carbon/martian/update_icons.dm +++ b/code/modules/mob/living/carbon/complex/martian/update_icons.dm @@ -1,39 +1,20 @@ //MOB ICONS -/mob/living/carbon/martian/update_icons() - update_hud() - +/mob/living/carbon/complex/martian/update_icons() + ..() overlays.len = 0 for(var/image/I in item_overlays) overlays += I - - lying_prev = lying - - if(isDead()) - icon_state = icon_state_dead - else if(lying) - icon_state = icon_state_lying - else - icon_state = icon_state_standing //INVENTORY ICONS #define HAT_LAYER 1 //2-7 are used for hands #define MAX_LAYERS 7 -/mob/living/carbon/martian +/mob/living/carbon/complex/martian var/list/item_overlays[MAX_LAYERS] //6 hands + hat -/mob/living/carbon/martian/regenerate_icons() - ..() - - for(var/i = 1 to held_items.len) - update_inv_hand(i) - - update_fire() - update_icons() - -/mob/living/carbon/martian/update_inv_hand(index, var/update_icons=1) +/mob/living/carbon/complex/martian/update_inv_hand(index, var/update_icons=1) var/obj/item/I = get_held_item_by_index(index) var/list/offsets = get_item_offset_by_index(index) var/pixelx = 0 @@ -64,7 +45,7 @@ update_icons() -/mob/living/carbon/martian/update_inv_head(var/update_icons=1) +/mob/living/carbon/complex/martian/update_inv_head(var/update_icons=1) if(!head) item_overlays[HAT_LAYER] = null @@ -83,7 +64,7 @@ -/mob/living/carbon/martian/update_hud() +/mob/living/carbon/complex/martian/update_hud() if(client) update_internals() client.screen |= contents diff --git a/code/modules/mob/living/carbon/complex/update_icons.dm b/code/modules/mob/living/carbon/complex/update_icons.dm new file mode 100644 index 00000000000..9b6693a1404 --- /dev/null +++ b/code/modules/mob/living/carbon/complex/update_icons.dm @@ -0,0 +1,20 @@ +/mob/living/carbon/complex/update_icons() + update_hud() + + lying_prev = lying + + if(isDead()) + icon_state = icon_state_dead + else if(lying) + icon_state = icon_state_lying + else + icon_state = icon_state_standing + +/mob/living/carbon/complex/regenerate_icons() + ..() + + for(var/i = 1 to held_items.len) + update_inv_hand(i) + + update_fire() + update_icons() \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/combat.dm b/code/modules/mob/living/carbon/human/combat.dm index 148173f6274..e28d7f2c244 100644 --- a/code/modules/mob/living/carbon/human/combat.dm +++ b/code/modules/mob/living/carbon/human/combat.dm @@ -208,6 +208,12 @@ ..() /mob/living/carbon/human/proc/perform_cpr(mob/living/target) + if(!get_lungs()) + to_chat(src, "You have no lungs with which to perform CPR with!") + return 0 + if(src.species && src.species.flags & NO_BREATHE) + to_chat(src, "You don't breathe, so you can't help \the [target]!") + return 0 if(src.check_body_part_coverage(MOUTH)) to_chat(src, "Remove your [src.get_body_part_coverage(MOUTH)]!") return 0 diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm index 7e0ed499533..18d42b4323f 100644 --- a/code/modules/mob/living/carbon/human/emote.dm +++ b/code/modules/mob/living/carbon/human/emote.dm @@ -59,13 +59,13 @@ if (input2 == "Visible") m_type = VISIBLE else if (input2 == "Hearable") - if (src.miming) + if (issilent(src)) return m_type = HEARABLE else alert("Unable to use this emote, must be either hearable or visible.") return - return custom_emote(m_type, msg) + return custom_emote(m_type, input) if ("me") if(silent) @@ -100,7 +100,7 @@ m_type = VISIBLE if ("choke") - if(miming) + if(issilent(src)) msg = "[src] clutches \his throat desperately!" m_type = VISIBLE else @@ -115,13 +115,13 @@ if (!src.restrained()) msg = "[src] claps." m_type = HEARABLE - if(miming) + if(issilent(src)) m_type = VISIBLE if ("flap") if (!src.restrained()) msg = "[src] flaps \his wings." m_type = HEARABLE - if(miming) + if(issilent(src)) m_type = VISIBLE if(src.wear_suit && istype(src.wear_suit,/obj/item/clothing/suit/clownpiece)) var/obj/item/clothing/suit/clownpiece/wings = src.wear_suit @@ -135,7 +135,7 @@ if (!src.restrained()) msg = "[src] flaps \his wings ANGRILY!" m_type = HEARABLE - if(miming) + if(issilent(src)) m_type = VISIBLE if(src.wear_suit && istype(src.wear_suit,/obj/item/clothing/suit/clownpiece)) var/obj/item/clothing/suit/clownpiece/wings = src.wear_suit @@ -154,7 +154,7 @@ m_type = VISIBLE if ("chuckle") - if(miming) + if(issilent(src)) msg = "[src] appears to chuckle." m_type = VISIBLE else @@ -181,7 +181,7 @@ m_type = VISIBLE if ("cough") - if(miming) + if(issilent(src)) msg = "[src] appears to cough!" m_type = VISIBLE else @@ -193,7 +193,7 @@ if (src.gender == FEMALE) //Females have their own coughes coughSound = "femalecough" - playsound(get_turf(src), coughSound, 20, 0) + playsound(src, coughSound, 20, 0) last_emote_sound = world.time msg = "[src] coughs!" @@ -219,7 +219,7 @@ m_type = VISIBLE if ("gasp") - if(miming) + if(issilent(src)) msg = "[src] appears to be gasping!" m_type = VISIBLE else @@ -234,7 +234,7 @@ if(M_ELVIS in mutations) src.emote("fart") msg = "[src] has left the building..." - if(!miming && (M_HARDCORE in mutations)) + if(!issilent(src) && (M_HARDCORE in mutations)) msg = "[src] whispers with \his final breath, 'i told u i was hardcore..'" else if(isgolem(src)) @@ -246,7 +246,7 @@ m_type = VISIBLE if ("giggle") - if(miming) + if(issilent(src)) msg = "[src] giggles silently!" m_type = VISIBLE else @@ -309,7 +309,7 @@ m_type = VISIBLE if ("cry") - if(miming) + if(issilent(src)) msg = "[src] cries." m_type = VISIBLE else @@ -321,7 +321,7 @@ m_type = HEARABLE if ("sigh") - if(miming) + if(issilent(src)) msg = "[src] sighs." m_type = VISIBLE else @@ -333,7 +333,7 @@ m_type = HEARABLE if ("laugh") - if(miming) + if(issilent(src)) msg = "[src] acts out a laugh." m_type = VISIBLE else @@ -347,11 +347,11 @@ if ("mumble") msg = "[src] mumbles!" m_type = HEARABLE - if(miming) + if(issilent(src)) m_type = VISIBLE if ("grumble") - if(miming) + if(issilent(src)) msg = "[src] grumbles!" m_type = VISIBLE if (!muzzled) @@ -362,7 +362,7 @@ m_type = HEARABLE if ("groan") - if(miming) + if(issilent(src)) msg = "[src] appears to groan!" m_type = VISIBLE else @@ -374,7 +374,7 @@ m_type = HEARABLE if ("moan") - if(miming) + if(issilent(src)) msg = "[src] appears to moan!" m_type = VISIBLE else @@ -388,7 +388,7 @@ if (!M) param = null else - if(miming) + if(issilent(src)) msg = "[src] takes a drag from a cigarette and blows \"[M]\" out in smoke." m_type = VISIBLE else @@ -448,7 +448,7 @@ if ("shiver") msg = "[src] shivers." m_type = HEARABLE - if(miming) + if(issilent(src)) m_type = VISIBLE if ("pale") @@ -460,7 +460,7 @@ m_type = VISIBLE if ("sneeze") - if (miming) + if (issilent(src)) msg = "[src] sneezes." m_type = VISIBLE else @@ -474,11 +474,11 @@ if ("sniff") msg = "[src] sniffs." m_type = HEARABLE - if(miming) + if(issilent(src)) m_type = VISIBLE if ("snore") - if (miming) + if (issilent(src)) msg = "[src] sleeps soundly." m_type = VISIBLE else @@ -490,7 +490,7 @@ m_type = HEARABLE if ("whimper") - if (miming) + if (issilent(src)) msg = "[src] appears hurt." m_type = VISIBLE else @@ -513,14 +513,14 @@ if (!muzzled) msg = "[src] yawns." m_type = HEARABLE - if(miming) + if(issilent(src)) m_type = VISIBLE if ("collapse") Paralyse(2) msg = "[src] collapses!" m_type = HEARABLE - if(miming) + if(issilent(src)) m_type = VISIBLE if("hug") @@ -573,7 +573,7 @@ msg = "[src] sadly can't find anybody to give daps to, and daps \himself. Shameful." if ("scream") - if (miming) + if (issilent(src)) msg = "[src] acts out a scream!" m_type = VISIBLE else @@ -586,7 +586,7 @@ if (src.gender == FEMALE) //Females have their own screams. Trannys be damned. screamSound = list('sound/misc/femalescream1.ogg', 'sound/misc/femalescream2.ogg', 'sound/misc/femalescream3.ogg', 'sound/misc/femalescream4.ogg', 'sound/misc/femalescream5.ogg') var/scream = pick(screamSound)//AUUUUHHHHHHHHOOOHOOHOOHOOOOIIIIEEEEEE - playsound(get_turf(src), scream, 50, 0) + playsound(src, scream, 50, 0) m_type = HEARABLE last_emote_sound = world.time else @@ -602,7 +602,7 @@ if(world.time-lastFart >= 400) for(var/mob/living/M in view(0)) if(M != src && M.loc == src.loc) - if(!miming) + if(!issilent(src)) visible_message("[src] farts in [M]'s face!") else visible_message("[src] silently farts in [M]'s face!") @@ -632,17 +632,17 @@ "farts [pick("lightly", "tenderly", "softly", "with care")]", ) - if(miming) + if(issilent(src)) farts = list("silently farts.", "acts out a fart.", "lets out a silent fart.") var/fart = pick(farts) - if(!miming) + if(!issilent(src)) msg = "[src] [fart]." if(mind && mind.assigned_role == "Clown") - playsound(get_turf(src), pick('sound/items/bikehorn.ogg','sound/items/AirHorn.ogg'), 50, 1) + playsound(src, pick('sound/items/bikehorn.ogg','sound/items/AirHorn.ogg'), 50, 1) else - playsound(get_turf(src), 'sound/misc/fart.ogg', 50, 1) + playsound(src, 'sound/misc/fart.ogg', 50, 1) else msg = "[src] [fart]" //Mimes can't fart. @@ -663,7 +663,7 @@ // Process toxic farts first. if(M_TOXIC_FARTS in mutations) msg="" - playsound(get_turf(src), 'sound/effects/superfart.ogg', 50, 1) + playsound(src, 'sound/effects/superfart.ogg', 50, 1) if(wearing_suit) if(!wearing_mask) to_chat(src, "You gas yourself!") diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index a8bf0b38d40..58a74cb08e9 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -42,15 +42,13 @@ var/msg = "*---------*\nThis is " - if( slot_w_uniform in obscured && skipface ) + if((slot_w_uniform in obscured) && skipface) t_He = "They" t_his = "their" t_him = "them" t_has = "have" t_is = "are" else - if(icon) - msg += "[bicon(src)] " //note, should we ever go back to runtime-generated icons (please don't), you will need to change this to [bicon(icon)] to prevent crashes. switch(gender) if(MALE) t_He = "He" @@ -239,7 +237,7 @@ msg += "[t_He] [t_has] a vacant, braindead stare...\n" // Religions - if (user.mind && user.mind.faith && user.mind.faith.isReligiousLeader(user) && mind) + if (ismob(user) && user.mind && user.mind.faith && user.mind.faith.isReligiousLeader(user) && mind) if (src.mind.faith == user.mind.faith) msg += "You recognise [t_him] as a follower of [user.mind.faith.name].
    " @@ -430,7 +428,7 @@ if(butchery) msg += "[butchery]\n" - if(user.hasHUD(HUD_SECURITY)) + if(istype(user) && user.hasHUD(HUD_SECURITY)) var/perpname = get_identification_name(get_face_name()) var/criminal = "None" @@ -444,7 +442,7 @@ msg += "\[Add comment\]\n" msg += {"[wpermit(src) ? "Has weapon permit.\n" : ""]"} - if(user.hasHUD(HUD_MEDICAL)) + if(istype(user) && user.hasHUD(HUD_MEDICAL)) var/perpname = get_identification_name(get_face_name()) var/medical = "None" diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index c2995a34317..b2e99bf7b3d 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -7,7 +7,7 @@ icon_state = "body_m_s" can_butcher = 1 meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/human - var/list/hud_list[9] + var/list/hud_list = list() var/datum/species/species //Contains icon generation and language information, set during New(). var/embedded_flag //To check if we've need to roll for damage on movement while an item is imbedded in us. @@ -95,6 +95,10 @@ update_body() +/mob/living/carbon/human/mushroom/New(var/new_loc, delay_ready_dna = 0) + h_style = "Bald" + ..(new_loc, "Mushroom") + /mob/living/carbon/human/generate_static_overlay() if(!istype(static_overlays,/list)) static_overlays = list() @@ -112,11 +116,6 @@ static_overlays["letter"] = static_overlay /mob/living/carbon/human/New(var/new_loc, var/new_species_name = null, var/delay_ready_dna=0) - if(!hair_styles_list.len) - buildHairLists() - if(!all_species.len) - buildSpeciesLists() - if(new_species_name) s_tone = random_skin_tone(new_species_name) multicolor_skin_r = rand(0,255) //Only used when the human has a species datum with the MULTICOLOR anatomical flag @@ -153,7 +152,7 @@ obj_overlays[FIRE_LAYER] = getFromPool(/obj/abstract/Overlays/fire_layer) obj_overlays[MUTANTRACE_LAYER] = getFromPool(/obj/abstract/Overlays/mutantrace_layer) obj_overlays[MUTATIONS_LAYER] = getFromPool(/obj/abstract/Overlays/mutations_layer) - obj_overlays[DAMAGE_LAYER] = getFromPool(/obj/abstract/Overlays/damage_layer) + obj_overlays[DAMAGE_LAYER] = getFromPool(/obj/abstract/Overlays/damage_layer) obj_overlays[UNIFORM_LAYER] = getFromPool(/obj/abstract/Overlays/uniform_layer) obj_overlays[ID_LAYER] = getFromPool(/obj/abstract/Overlays/id_layer) obj_overlays[SHOES_LAYER] = getFromPool(/obj/abstract/Overlays/shoes_layer) @@ -255,9 +254,6 @@ stat("Spacepod Charge", "[istype(S.battery) ? "[S.battery.charge] / [S.battery.maxcharge]" : "No cell detected"]") stat("Spacepod Integrity", "[!S.health ? "0" : "[(S.health / initial(S.health)) * 100]"]%") -/mob/living/carbon/human/attack_animal(mob/living/simple_animal/M as mob) - M.unarmed_attack_mob(src) - /mob/living/carbon/human/proc/is_loyalty_implanted(mob/living/carbon/human/M) for(var/L in M.contents) if(istype(L, /obj/item/weapon/implant/loyalty)) @@ -346,9 +342,9 @@ return //repurposed proc. Now it combines get_id_name() and get_face_name() to determine a mob's name variable. Made into a seperate proc as it'll be useful elsewhere /mob/living/carbon/human/proc/get_visible_name() - if( wear_mask && (is_slot_hidden(wear_mask.body_parts_covered,HIDEFACE))) //Wearing a mask which hides our face, use id-name if possible + if( wear_mask && wear_mask.is_hidden_identity()) //Wearing a mask which hides our face, use id-name if possible return get_id_name("Unknown") - if( head && (is_slot_hidden(head.body_parts_covered,HIDEFACE))) + if( head && head.is_hidden_identity()) return get_id_name("Unknown") //Likewise for hats var/datum/role/vampire/V = isvampire(src) if(V && (VAMP_SHADOW in V.powers) && V.ismenacing) @@ -361,7 +357,7 @@ //Returns "Unknown" if facially disfigured and real_name if not. Useful for setting name when polyacided or when updating a human's name variable /mob/living/carbon/human/proc/get_face_name() var/datum/organ/external/head/head_organ = get_organ(LIMB_HEAD) - if((wear_mask && (is_slot_hidden(wear_mask.body_parts_covered,HIDEFACE))) || ( head && (is_slot_hidden(head.body_parts_covered,HIDEFACE))) || !head_organ || head_organ.disfigured || (head_organ.status & ORGAN_DESTROYED) || !real_name || (M_HUSK in mutations) ) //Wearing a mask which hides our face, use id-name if possible + if((wear_mask && wear_mask.is_hidden_identity() ) || ( head && head.is_hidden_identity() ) || !head_organ || head_organ.disfigured || (head_organ.status & ORGAN_DESTROYED) || !real_name || (M_HUSK in mutations) ) //Wearing a mask which hides our face, use id-name if possible return "Unknown" return real_name @@ -722,7 +718,7 @@ src.visible_message("[src] throws up!","You throw up!") spawn_vomit_on_floor = 1 - playsound(get_turf(loc), 'sound/effects/splat.ogg', 50, 1) + playsound(loc, 'sound/effects/splat.ogg', 50, 1) if(spawn_vomit_on_floor) if(istype(location, /turf/simulated)) @@ -1123,8 +1119,9 @@ if(src.species.abilities) src.verbs -= species.abilities if(species.spells) - for(var/spell in species.spells) - remove_spell(spell) + for(var/spell/spell in spell_list) + if(spell.type in species.spells) + remove_spell(spell) for(var/L in species.known_languages) remove_language(L) species.clear_organs(src) @@ -1148,6 +1145,18 @@ add_spell(spell, "racial_spell_ready", /obj/abstract/screen/movable/spell_master/racial) if(force_organs || !src.organs || !src.organs.len) src.species.create_organs(src) + else + for(var/datum/organ/external/current_organ in organs) + if(species.anatomy_flags & NO_BLOOD) + current_organ.status &= ~ORGAN_BLEEDING + if(species.anatomy_flags & NO_BONES) + current_organ.status &= ~ORGAN_BROKEN + current_organ.status &= ~ORGAN_SPLINTED + if(species.anatomy_flags & NO_STRUCTURE && current_organ.status & ORGAN_DESTROYED) + current_organ.status |= ORGAN_ATTACHABLE + current_organ.amputated = 1 + current_organ.setAmputatedTree() + current_organ.open = 0 var/datum/organ/internal/eyes/E = src.internal_organs_by_name["eyes"] if(E) src.see_in_dark = E.see_in_dark //species.darksight @@ -1162,6 +1171,8 @@ src.dna.species = new_species_name src.species.handle_post_spawn(src) src.update_icons() + if(species.species_intro) + to_chat(src, "[species.species_intro]") return 1 /mob/living/carbon/human/proc/bloody_doodle() @@ -1402,6 +1413,13 @@ Paralyse(paralyse_duration) Jitter(jitter_duration) +/mob/living/carbon/human/proc/asthma_attack() + if(disabilities & ASTHMA && !(M_NO_BREATH in mutations) && !(has_reagent_in_blood(ALBUTEROL))) + forcesay("-") + visible_message("\The [src] begins wheezing and grabbing at their throat!", \ + "You begin wheezing and grabbing at your throat!") + src.reagents.add_reagent(MUCUS, 10) + // Makes all robotic limbs organic. /mob/living/carbon/human/proc/make_robot_limbs_organic() for(var/datum/organ/external/O in src.organs) @@ -1420,6 +1438,22 @@ make_robot_limbs_organic() make_robot_internals_organic() +// Makes all limbs robotic. +/mob/living/carbon/human/proc/make_organic_limbs_robotic() + for(var/datum/organ/external/O in organs) + O.robotize() + update_icons() + +// Makes all internal organs robotic. +/mob/living/carbon/human/proc/make_organic_internals_robotic() + for(var/datum/organ/internal/O in organs) + O.robotic = TRUE + +// Makes all organs, internal and external, robotic. +/mob/living/carbon/human/proc/make_all_organic_parts_robotic() + make_organic_limbs_robotic() + make_organic_internals_robotic() + /mob/living/carbon/human/proc/set_attack_type(new_type = NORMAL_ATTACK) kick_icon.icon_state = "act_kick" bite_icon.icon_state = "act_bite" @@ -1536,6 +1570,9 @@ plane = LYING_HUMAN_PLANE else plane = HUMAN_PLANE + var/area/this_area = get_area(src) + if(istype(this_area) && this_area.project_shadows) + update_shadow() /mob/living/carbon/human/set_hand_amount(new_amount) //Humans need hand organs to use the new hands. This proc will give them some if(new_amount > held_items.len) @@ -1735,10 +1772,10 @@ mob/living/carbon/human/remove_internal_organ(var/mob/living/user, var/datum/org /mob/living/carbon/human/can_show_flavor_text() // Wearing a mask... - if(wear_mask && is_slot_hidden(wear_mask.body_parts_covered, HIDEFACE)) + if(wear_mask && wear_mask.is_hidden_identity()) return FALSE // Or having a headpiece that protects your face... - if(head && is_slot_hidden(head.body_parts_covered, HIDEFACE)) + if(head && head.is_hidden_identity()) return FALSE // Or lacking a head, or being disfigured... var/datum/organ/external/head/limb_head = get_organ(LIMB_HEAD) @@ -1751,6 +1788,7 @@ mob/living/carbon/human/remove_internal_organ(var/mob/living/user, var/datum/org return TRUE /mob/living/carbon/human/proc/make_zombie(mob/master, var/retain_mind = TRUE) + ghostize() var/mob/living/simple_animal/hostile/necro/zombie/turned/T = new(get_turf(src), master, (retain_mind ? mind : null)) T.get_clothes(src, T) T.name = real_name @@ -1773,5 +1811,8 @@ mob/living/carbon/human/remove_internal_organ(var/mob/living/user, var/datum/org if(HUD_MEDICAL) return istype(glasses, /obj/item/clothing/glasses/hud/health) if(HUD_SECURITY) + if(istype(glasses, /obj/item/clothing/glasses/sunglasses/sechud/syndishades)) + var/obj/item/clothing/glasses/sunglasses/sechud/syndishades/S = glasses + return S.full_access return is_type_in_list(glasses, list(/obj/item/clothing/glasses/hud/security, /obj/item/clothing/glasses/sunglasses/sechud)) return FALSE diff --git a/code/modules/mob/living/carbon/human/human_attackanimal.dm b/code/modules/mob/living/carbon/human/human_attackanimal.dm new file mode 100644 index 00000000000..2f80db722f5 --- /dev/null +++ b/code/modules/mob/living/carbon/human/human_attackanimal.dm @@ -0,0 +1,5 @@ +/mob/living/carbon/human/attack_animal(mob/living/simple_animal/M) + if(check_shields(0, M.name)) + return 0 + + M.unarmed_attack_mob(src) \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/human_attackhand.dm b/code/modules/mob/living/carbon/human/human_attackhand.dm index ff745ca13de..30a4805f91c 100644 --- a/code/modules/mob/living/carbon/human/human_attackhand.dm +++ b/code/modules/mob/living/carbon/human/human_attackhand.dm @@ -1,5 +1,8 @@ //BITES /mob/living/carbon/human/bite_act(mob/living/carbon/human/M as mob) + + var/dam_check = !(istype(loc, /turf) && istype(loc.loc, /area/start)) // 0 or 1 + if(M == src) return //Can't bite yourself @@ -26,11 +29,11 @@ //end vampire code var/armor_modifier = 30 - var/damage = rand(1, 5) + var/damage = rand(1, 5)*dam_check if(M.organ_has_mutation(LIMB_HEAD, M_BEAK)) //Beaks = stronger bites armor_modifier = 5 - damage += 4 + damage += 4*dam_check var/datum/organ/external/affecting = get_organ(ran_zone(M.zone_sel.selecting)) @@ -41,7 +44,8 @@ if(2) //Full block damage = 0 - if(!damage) + damage = run_armor_absorb(affecting, "melee", damage) + if(!damage && dam_check) playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) visible_message("\The [M] has attempted to bite \the [src]!") return 0 @@ -67,6 +71,9 @@ //KICKS /mob/living/carbon/human/kick_act(mob/living/carbon/human/M) + + var/dam_check = !(istype(loc, /turf) && istype(loc.loc, /area/start)) // 0 or 1 + //Pick a random usable foot to perform the kick with var/datum/organ/external/foot_organ = pick_usable_organ(LIMB_RIGHT_FOOT, LIMB_LEFT_FOOT) @@ -84,19 +91,19 @@ stomping = 1 var/armor_modifier = 1 - var/damage = rand(0,7) + var/damage = rand(0,7)*dam_check var/knockout = damage if(stomping) //Stomps = more damage and armor bypassing armor_modifier = 0.5 - damage += rand(0,7) + damage += rand(0,7)*dam_check attack_verb = "stomps on" else if(M.reagents && M.reagents.has_reagent(GYRO)) - damage += rand(0,4) + damage += rand(0,4)*dam_check knockout += rand(0,3) attack_verb = "roundhouse kicks" - if(!damage) + if(!damage && dam_check) // So that people still think they are biting each other playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) visible_message("\The [M] attempts to kick \the [src]!") return 0 @@ -128,7 +135,7 @@ damage = max(0, damage - rand(1,5)) if(2) //Full block damage = max(0, damage - rand(1,10)) - + damage = run_armor_absorb(affecting, "melee", damage) if(knockout >= 7 && prob(33)) visible_message("[M] weakens [src]!") apply_effect(3, WEAKEN, armorblock) diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 249759d951e..1f899c383a4 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -49,7 +49,6 @@ emp_act /mob/living/carbon/human/getarmorabsorb(var/def_zone, var/type) var/armorval = 0 var/organnum = 0 - if(def_zone) if(isorgan(def_zone)) return checkarmorabsorb(def_zone, type) @@ -88,7 +87,10 @@ emp_act if(bp && istype(bp ,/obj/item/clothing)) var/obj/item/clothing/C = bp if(C.body_parts_covered & def_zone.body_part) - protection += C.armor[type] + protection += C.get_armor(type) + for(var/obj/item/clothing/accessory/A in C.accessories) + if(A.body_parts_covered & def_zone.body_part) + protection += A.get_armor(type) if(istype(loc, /obj/mecha)) var/obj/mecha/M = loc protection += M.rad_protection @@ -103,7 +105,10 @@ emp_act if(istype(bp, /obj/item/clothing)) var/obj/item/clothing/C = bp if(C.body_parts_covered & def_zone.body_part) - protection += C.armor_absorb[type] + protection += C.get_armor_absorb(type) + for(var/obj/item/clothing/accessory/A in C.accessories) + if(A.body_parts_covered & def_zone.body_part) + protection += A.get_armor_absorb(type) return protection @@ -242,29 +247,31 @@ emp_act knock_teeth = 1 var/armor = run_armor_check(affecting, "melee", quiet = 1) + var/final_force = run_armor_absorb(affecting, "melee", I.force) if(knock_teeth) //You can't actually hit people in the mouth - this checks if the user IS targetting mouth, and if he didn't miss! - if((!armor) && (I.force >= 8 || I.w_class >= W_CLASS_SMALL) && (I.is_sharp() < 1))//Minimum force=8, minimum w_class=2. Sharp items can't knock out teeth. Armor prevents this completely! - var/chance = min(I.force * I.w_class, 40) //an item with w_class = W_CLASS_MEDIUM and force of 10 has a 30% chance of knocking a few teeth out. Chance is capped at 40% + if((!armor) && (final_force >= 8 || I.w_class >= W_CLASS_SMALL) && (I.is_sharp() < 1))//Minimum force=8, minimum w_class=2. Sharp items can't knock out teeth. Armor prevents this completely! + var/chance = min(final_force * I.w_class, 40) //an item with w_class = W_CLASS_MEDIUM and force of 10 has a 30% chance of knocking a few teeth out. Chance is capped at 40% if(prob(chance)) knock_out_teeth(user) var/bloody = FALSE - if(((I.damtype == BRUTE) || (I.damtype == HALLOSS)) && prob(25 + (I.force * 2))) - I.add_blood(src) //Make the weapon bloody, not the person. - if(prob(33)) - bloody = TRUE - var/turf/location = loc - if(istype(location, /turf/simulated)) - location.add_blood(src) - if(ishuman(user)) - var/mob/living/carbon/human/H = user - if(get_dist(H, src) <= 1) //people with TK won't get smeared with blood - H.bloody_body(src) - H.bloody_hands(src) + if(final_force && ((I.damtype == BRUTE) || (I.damtype == HALLOSS)) && prob(25 + (final_force * 2))) + if(!(src.species.anatomy_flags & NO_BLOOD)) + I.add_blood(src) //Make the weapon bloody, not the person. + if(prob(33)) + bloody = TRUE + var/turf/location = loc + if(istype(location, /turf/simulated)) + location.add_blood(src) + if(ishuman(user)) + var/mob/living/carbon/human/H = user + if(get_dist(H, src) <= 1) //people with TK won't get smeared with blood + H.bloody_body(src) + H.bloody_hands(src) switch(hit_area) if(LIMB_HEAD)//Harder to score a stun but if you do it lasts a bit longer - if(prob(I.force)) + if(prob(final_force)) if(apply_effect(20, PARALYZE, armor)) visible_message("[src] has been knocked unconscious!") // if(src != user && I.damtype == BRUTE && isrev(src)) @@ -283,7 +290,7 @@ emp_act update_inv_glasses(0) if(LIMB_CHEST)//Easier to score a stun but lasts less time - if(prob((I.force + 10))) + if(prob((final_force + 10))) apply_effect(5, WEAKEN, armor) visible_message("[src] has been knocked down!") @@ -474,5 +481,6 @@ emp_act show_message("The blob attacks you!") var/dam_zone = pick(organs_by_name) var/datum/organ/external/affecting = get_organ(ran_zone(dam_zone)) - apply_damage(rand(30,40), BRUTE, affecting, run_armor_check(affecting, "melee")) + + apply_damage(run_armor_absorb(affecting, "melee", rand(30,40)), BRUTE, affecting, run_armor_check(affecting, "melee")) return diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index 412bfa84987..14dd5c987b4 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -94,3 +94,4 @@ var/show_client_status_on_examine = TRUE //If false, don't display catatonic/braindead messages to non-admins var/become_zombie_after_death = FALSE + var/times_cloned = 0 //How many times this person has been cloned \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm index 560373e32cc..64cb13929b2 100644 --- a/code/modules/mob/living/carbon/human/human_movement.dm +++ b/code/modules/mob/living/carbon/human/human_movement.dm @@ -10,7 +10,7 @@ if(flying) return // Calculate none of the following because we're technically on a vehicle if(reagents.has_any_reagents(list(HYPERZINE,COCAINE))) - return // Hyperzine ignores slowdown + return // Hyperzine ignores base slowdown if(istype(loc, /turf/space)) return // Space ignores slowdown diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm index 57c94cadb5b..41365b8c844 100644 --- a/code/modules/mob/living/carbon/human/inventory.dm +++ b/code/modules/mob/living/carbon/human/inventory.dm @@ -352,7 +352,7 @@ W.dropped(src) if(W) W.reset_plane_and_layer() - update_action_buttons() + update_action_buttons_icon() return 1 //This is a SAFE proc. Use this instead of equip_to_slot()! diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index b5c27e2195b..b07c505ee91 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -145,7 +145,7 @@ var/global/list/organ_damage_overlays = list( location_as_object.handle_internal_lifeform(src, 0) last_processed = "Interacted with our container" if(check_mutations) - testing("Updating [src.real_name]'s mutations: "+english_list(mutations)) +// testing("Updating [src.real_name]'s mutations: "+english_list(mutations)) domutcheck(src,null,MUTCHK_FORCED) update_mutations() check_mutations = 0 diff --git a/code/modules/mob/living/carbon/human/life/handle_breath.dm b/code/modules/mob/living/carbon/human/life/handle_breath.dm index b34e9e48bda..230505a22ff 100644 --- a/code/modules/mob/living/carbon/human/life/handle_breath.dm +++ b/code/modules/mob/living/carbon/human/life/handle_breath.dm @@ -49,16 +49,13 @@ var/obj/location_as_object = loc breath = location_as_object.handle_internal_lifeform(src, BREATH_MOLES) else if(isturf(loc)) - var/breath_moles = 0 /*if(environment.return_pressure() > ONE_ATMOSPHERE) //Loads of air around (pressure effect will be handled elsewhere), so lets just take a enough to fill our lungs at normal atmos pressure (using n = Pv/RT) breath_moles = (ONE_ATMOSPHERE*BREATH_VOLUME/R_IDEAL_GAS_EQUATION*environment.temperature) else */ //Not enough air around, take a percentage of what's there to model this properly - breath_moles = (environment.total_moles() / environment.volume * CELL_VOLUME) * BREATH_PERCENTAGE - - breath = loc.remove_air(breath_moles) + breath = environment.remove_volume(CELL_VOLUME * BREATH_PERCENTAGE) if(!breath || breath.total_moles < BREATH_MOLES / 5 || breath.total_moles > BREATH_MOLES * 5) if(prob(15)) // 15% chance for lung damage if air intake is less of a fifth, or more than five times the threshold @@ -112,9 +109,13 @@ adjust_fire_stacks(0.5) IgniteMob() else - if(fire_stacks > 0) - var/obj/item/clothing/suit/space/plasmaman/PS=wear_suit - PS.Extinguish(src) + var/obj/item/clothing/suit/space/plasmaman/PS=wear_suit + if(istype(PS)) + if(fire_stacks > 0) + PS.Extinguish(src) + else + PS.regulate_temp_of_wearer(src) + if(breath) loc.assume_air(breath) diff --git a/code/modules/mob/living/carbon/human/life/handle_chemicals_in_body.dm b/code/modules/mob/living/carbon/human/life/handle_chemicals_in_body.dm index fe5b02ca04d..ec940850c1c 100644 --- a/code/modules/mob/living/carbon/human/life/handle_chemicals_in_body.dm +++ b/code/modules/mob/living/carbon/human/life/handle_chemicals_in_body.dm @@ -34,7 +34,7 @@ var/light_amount = 0 //How much light there is in the place, affects receiving nutrition and healing if(isturf(loc)) //Else, there's considered to be no light var/turf/T = loc - light_amount = T.get_lumcount() * 10 + light_amount = (T.get_lumcount() * 10) - 5 nutrition += light_amount pain_shock_stage -= light_amount @@ -48,6 +48,23 @@ adjustOxyLoss(-(light_amount)) //TODO: heal wounds, heal broken limbs. + if(species.flags & REQUIRE_DARK) + var/light_amount = 0 + if(isturf(loc)) + var/turf/T = loc + light_amount = T.get_lumcount() * 10 + + nutrition -= -3+light_amount + pain_shock_stage += -3+light_amount + + if(species.flags & IS_PLANT) + if(nutrition > 500) + nutrition = 500 + if(!reagents.has_reagent(HYPERZINE)) + adjustBruteLoss(-10+light_amount) + adjustToxLoss(-10+light_amount) + adjustOxyLoss(-10+light_amount) + if(dna && dna.mutantrace == "shadow") var/light_amount = 0 if(isturf(loc)) diff --git a/code/modules/mob/living/carbon/human/life/handle_disabilities.dm b/code/modules/mob/living/carbon/human/life/handle_disabilities.dm index 8f7360b5407..4007c66c202 100644 --- a/code/modules/mob/living/carbon/human/life/handle_disabilities.dm +++ b/code/modules/mob/living/carbon/human/life/handle_disabilities.dm @@ -1,6 +1,10 @@ //Refer to life.dm for caller /mob/living/carbon/human/proc/handle_disabilities() + if(disabilities & ASTHMA) + if(prob(0.2)) + asthma_attack() + if(disabilities & EPILEPSY) if((prob(1)) && (paralysis < 1)) seizure(10, 1000) @@ -101,4 +105,4 @@ if(10 <= rn && rn <= 12) if(canmove) to_chat(src, "Your legs won't respond properly, you fall down.") - Knockdown(3) + Knockdown(3) \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/life/handle_mutations_and_radiation.dm b/code/modules/mob/living/carbon/human/life/handle_mutations_and_radiation.dm index 9f01b421b3a..ae6b2caf4a0 100644 --- a/code/modules/mob/living/carbon/human/life/handle_mutations_and_radiation.dm +++ b/code/modules/mob/living/carbon/human/life/handle_mutations_and_radiation.dm @@ -207,7 +207,7 @@ if(prob(10*minor_rad_multiplier)) //Blindness var/datum/organ/internal/eyes/E = internal_organs_by_name["eyes"] - if(!E.robotic && !(sdisabilities & BLIND || disabilities & NEARSIGHTED)) + if(E && !E.robotic && !(sdisabilities & BLIND || disabilities & NEARSIGHTED)) to_chat(src, "[pick("Your eyesight starts to fade!","Your eyes go cloudy!","Are you going blind?")]") E.take_damage(2.5, TRUE) eye_blurry = min(eye_blurry+1.5,50) @@ -303,3 +303,22 @@ Knockdown(3) regenerate_icons() visible_message("\The [src]'s form loses bulk as they collapse to the ground.") + +/mob/living/proc/get_rad_stage() + switch(rad_tick) + if(0) + return "N/A" + if(1 to RADDOSELIGHT) + return "Early" + if(RADDOSELIGHT to RADDOSEMINOR) + return "Light" + if(RADDOSEMINOR to RADDOSEADVANCED) + return "Minor" + if(RADDOSEADVANCED to RADDOSECRITICAL) + return "Advanced" + if(RADDOSECRITICAL to RADDOSEDEADLY) + return "Critical" + if(RADDOSEDEADLY to RADDOSEFATAL) + return "Deadly" + if(RADDOSEFATAL to INFINITY) + return "Fatal" diff --git a/code/modules/mob/living/carbon/human/life/handle_regular_hud_updates.dm b/code/modules/mob/living/carbon/human/life/handle_regular_hud_updates.dm index 2699176ce49..f5eb77c1aa0 100644 --- a/code/modules/mob/living/carbon/human/life/handle_regular_hud_updates.dm +++ b/code/modules/mob/living/carbon/human/life/handle_regular_hud_updates.dm @@ -8,7 +8,7 @@ regular_hud_updates() - update_action_buttons() + update_action_buttons_icon() if(stat == UNCONSCIOUS && health <= config.health_threshold_crit) var/severity = 0 @@ -288,11 +288,22 @@ clear_fullscreen("high") var/masked = 0 - if(istype(head, /obj/item/clothing/head/welding) || istype(head, /obj/item/clothing/head/helmet/space/unathi)) - var/obj/item/clothing/head/welding/O = head - if(!O.up && tinted_weldhelh) - overlay_fullscreen("tint", /obj/abstract/screen/fullscreen/impaired, 2) - masked = 1 + + if(head) + if(istype(head, /obj/item/clothing/head/welding) || istype(head, /obj/item/clothing/head/helmet/space/unathi) || (/datum/action/item_action/toggle_helmet_mask in head.actions_types)) + var/enable_mask = TRUE + + var/datum/action/item_action/toggle_helmet_mask/action = locate(/datum/action/item_action/toggle_helmet_mask) in head.actions + + if(action) + enable_mask = !action.up + else + var/obj/item/clothing/head/welding/O = head + enable_mask = !O.up + + if(enable_mask && tinted_weldhelh) + overlay_fullscreen("tint", /obj/abstract/screen/fullscreen/impaired, 2) + masked = 1 if(!masked && istype(glasses, /obj/item/clothing/glasses/welding) && !istype(glasses, /obj/item/clothing/glasses/welding/superior)) var/obj/item/clothing/glasses/welding/O = glasses diff --git a/code/modules/mob/living/carbon/human/life/handle_stomach.dm b/code/modules/mob/living/carbon/human/life/handle_stomach.dm index 1383f81aabd..45f6d80fa9e 100644 --- a/code/modules/mob/living/carbon/human/life/handle_stomach.dm +++ b/code/modules/mob/living/carbon/human/life/handle_stomach.dm @@ -16,10 +16,10 @@ to_chat(src, "Your stomach starts rumbling as /the [M] is shifted around.") if(1) visible_message(src, "\The [src] lets out a small toot.", "You let out a small toot, your stomach gurgling.") - playsound(get_turf(src), 'sound/misc/fart.ogg', 50, 1) + playsound(src, 'sound/misc/fart.ogg', 50, 1) if(2) visible_message(src, "\The [src] lets out an extremely long fart.", "You let out an extremely long and loud fart, to the point that it starts hurting your ass.") - playsound(get_turf(src), 'sound/effects/superfart.ogg', 50, 1) + playsound(src, 'sound/effects/superfart.ogg', 50, 1) if(!(status_flags & GODMODE)) adjustBruteLoss(5) if(3 to INFINITY) diff --git a/code/modules/mob/living/carbon/human/say.dm b/code/modules/mob/living/carbon/human/say.dm index f1ff765b801..0c5537eb10a 100644 --- a/code/modules/mob/living/carbon/human/say.dm +++ b/code/modules/mob/living/carbon/human/say.dm @@ -80,7 +80,7 @@ /mob/living/carbon/human/IsVocal() if(mind) - return !miming + return !(issilent(src)) return 1 /mob/living/carbon/human/proc/SetSpecialVoice(var/new_voice) diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index cf4fbde6b29..3a0749dae63 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -172,7 +172,6 @@ var/global/list/damage_icon_parts = list() O.overlays.len = 0 O.overlays += standing_image obj_to_plane_overlay(O,DAMAGE_LAYER) - //overlays_standing[DAMAGE_LAYER] = standing_image @@ -325,8 +324,8 @@ var/global/list/damage_icon_parts = list() if(facial_hair_style.do_colouration) facial_s.Blend(rgb(r_facial, g_facial, b_facial), ICON_ADD) face_standing.Blend(facial_s, ICON_OVERLAY) - else - warning("Invalid f_style for [species.name]: [f_style]") +// else + //warning("Invalid f_style for [species.name]: [f_style]") if(h_style && !check_hidden_head_flags(HIDEHEADHAIR)) var/datum/sprite_accessory/hair_style = hair_styles_list[h_style] @@ -338,8 +337,8 @@ var/global/list/damage_icon_parts = list() hair_s.Blend(icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_acc"), ICON_OVERLAY) face_standing.Blend(hair_s, ICON_OVERLAY) - else - warning("Invalid h_style for [species.name]: [h_style]") +// else + //warning("Invalid h_style for [species.name]: [h_style]") if(body_alphas.len) var/lowest_alpha = get_lowest_body_alpha() @@ -914,7 +913,7 @@ var/global/list/damage_icon_parts = list() /mob/living/carbon/human/update_inv_wear_suit(var/update_icons=1) overlays -= obj_overlays[SUIT_LAYER] - if( wear_suit && istype(wear_suit, /obj/item/clothing/suit) && wear_suit.is_visible()) //TODO check this + if( wear_suit && wear_suit.is_visible()) //TODO check this wear_suit.screen_loc = ui_oclothing //TODO var/obj/abstract/Overlays/O = obj_overlays[SUIT_LAYER] O.overlays.len = 0 diff --git a/code/modules/mob/living/carbon/monkey/life.dm b/code/modules/mob/living/carbon/monkey/life.dm index c7a05b85f6a..ce156f22673 100644 --- a/code/modules/mob/living/carbon/monkey/life.dm +++ b/code/modules/mob/living/carbon/monkey/life.dm @@ -267,8 +267,7 @@ var/obj/location_as_object = loc breath = location_as_object.handle_internal_lifeform(src, BREATH_VOLUME) else if(istype(loc, /turf/)) - var/breath_moles = environment.total_moles()/environment.volume*CELL_VOLUME*BREATH_PERCENTAGE - breath = loc.remove_air(breath_moles) + breath = environment.remove_volume(CELL_VOLUME * BREATH_PERCENTAGE) // Handle chem smoke effect -- Doohl var/block = 0 @@ -458,7 +457,7 @@ if(hat && istype(hat, /obj/item/clothing/head/helmet/space) && uniform && istype(uniform, /obj/item/clothing/monkeyclothes/space)) spaceproof = 1 //quick and dirt cheap. no need for the Life() of monkeys to become as complicated as the Life() of humans. man that's deep. var/loc_temp = get_loc_temp(environment) - var/environment_heat_capacity = environment.heat_capacity() + var/environment_heat_capacity = environment.heat_capacity() / environment.volume * CELL_VOLUME if(istype(get_turf(src), /turf/space)) var/turf/heat_turf = get_turf(src) environment_heat_capacity = heat_turf.heat_capacity @@ -520,7 +519,7 @@ if(isturf(loc)) //else, there's considered to be no light var/turf/T = loc if(T.dynamic_lighting) - light_amount = T.get_lumcount() * 10 + light_amount = (T.get_lumcount() * 10) - 5 else light_amount = 5 nutrition += light_amount diff --git a/code/modules/mob/living/carbon/monkey/monkey.dm b/code/modules/mob/living/carbon/monkey/monkey.dm index 10d0cbf7407..0bca39019df 100644 --- a/code/modules/mob/living/carbon/monkey/monkey.dm +++ b/code/modules/mob/living/carbon/monkey/monkey.dm @@ -443,4 +443,74 @@ /mob/living/carbon/monkey/can_wield(obj/item/I) //used for making wield exceptions for 2 handed items if (istype(I,/obj/item/device/instrument/drum/drum_makeshift/bongos)) - return 1 \ No newline at end of file + return 1 + + +/mob/living/carbon/monkey/mushroom + name = "walking mushroom" + icon = 'icons/mob/animal.dmi' + icon_state = "mushroom" + greaterform = "Mushroom" + species_type = /mob/living/carbon/monkey/mushroom + meat_type = /obj/item/weapon/reagent_containers/food/snacks/hugemushroomslice/mushroom_man + canWearClothes = 0 + canWearHats = 0 + canWearGlasses = 0 + canWearMasks = 0 + canWearBack = 0 + held_items = list() + flag = NO_BREATHE + var/growth = 0 + +/mob/living/carbon/monkey/mushroom/say() + return 0 + +/mob/living/carbon/monkey/mushroom/put_in_hand_check(var/obj/item/W) + return 0 + +/mob/living/carbon/monkey/mushroom/Life() + ..() + if(!isDead() && !gcDestroyed && client) + var/light_amount = 0 + if(isturf(loc)) + var/turf/T = loc + light_amount = T.get_lumcount() * 10 + + growth = Clamp(growth + rand(1,3)/(10*light_amount>1 ? light_amount : 1),0,100) + + if(growth >= 100) + growth = 0 + var/mob/living/carbon/human/adult = new() + adult.alpha = 0 + var/matrix/smol = matrix() + smol.Scale(0) + var/matrix/large = matrix() + var/matrix/M = adult.transform + M.Scale(0) + adult.set_species("Mushroom") + for(var/datum/language/L in languages) + adult.add_language(L.name) + + adult.regenerate_icons() + adult.forceMove(get_turf(src)) + animate(src, alpha = 0, transform = smol, time = 3 SECONDS, easing = SINE_EASING) + animate(adult, alpha = 255, transform = large, time = 3 SECONDS, easing = SINE_EASING) + transferImplantsTo(adult) + transferBorers(adult) + + if(istype(loc,/obj/item/weapon/holder)) + var/obj/item/weapon/holder/L = loc + src.forceMove(get_turf(L)) + L = null + qdel(L) + + if(mind) + src.mind.transfer_to(adult) + adult.fully_replace_character_name(newname = src.real_name) + src.drop_all() + qdel(src) + +/mob/living/carbon/monkey/mushroom/Stat() + ..() + if(statpanel("Status")) + stat(null, "Growth completing: [growth]%") \ No newline at end of file diff --git a/code/modules/mob/living/carbon/monkey/update_icons.dm b/code/modules/mob/living/carbon/monkey/update_icons.dm index eb24579be25..6c10d6204a6 100644 --- a/code/modules/mob/living/carbon/monkey/update_icons.dm +++ b/code/modules/mob/living/carbon/monkey/update_icons.dm @@ -222,7 +222,7 @@ var/obj/item/I = get_held_item_by_index(GRASP_LEFT_HAND) if(I && I.is_visible()) var/t_state = I.item_state - var/t_inhand_states = I.inhand_states["right_hand"] + var/t_inhand_states = I.inhand_states["left_hand"] if(!t_state) t_state = I.icon_state var/image/IM = image("icon" = t_inhand_states, "icon_state" = t_state) diff --git a/code/modules/mob/living/carbon/not_human/gondola/gondola.dm b/code/modules/mob/living/carbon/not_human/gondola/gondola.dm new file mode 100644 index 00000000000..91810410481 --- /dev/null +++ b/code/modules/mob/living/carbon/not_human/gondola/gondola.dm @@ -0,0 +1,29 @@ +/mob/living/carbon/not_human/gondola + name = "gondola" + desc = "A calming presence in this strange land." + icon = 'icons/mob/gondola.dmi' + + icon_state_standing = "gondola" + icon_state_lying = "gondola_lying" + icon_state_dead = "gondola_dead" + + maxHealth = 75 + health = 75 + + held_items = list() + + size = SIZE_NORMAL + status_flags = CANSTUN|CANKNOCKDOWN|CANPARALYSE|CANPUSH + mob_bump_flag = HUMAN + mob_push_flags = ALLMOBS + mob_swap_flags = ALLMOBS + +/mob/living/carbon/not_human/gondola/New() + icon_state_standing = pick("gondola","gondola_1") + icon_state_lying = "[icon_state_standing]_lying" + icon_state_dead = "[icon_state_dead]_dead" + ..() + + +/mob/living/carbon/not_human/gondola/say() + return \ No newline at end of file diff --git a/code/modules/mob/living/carbon/not_human/gondola/gondola_receive_music.dm b/code/modules/mob/living/carbon/not_human/gondola/gondola_receive_music.dm new file mode 100644 index 00000000000..d144691ca79 --- /dev/null +++ b/code/modules/mob/living/carbon/not_human/gondola/gondola_receive_music.dm @@ -0,0 +1,120 @@ +//Basically walking media receivers +/mob/living/carbon/not_human/gondola + var/playing=0 + var/media_url="" + var/media_start_time=0 + var/area/master_area + var/media_frequency = 1234 // 123.4 MHz + var/media_crypto = null // Crypto key + + var/list/obj/machinery/media/transmitter/hooked = list() + var/exclusive_hook=null // Disables output to the room + +/mob/living/carbon/not_human/gondola/New() + ..() + connect_frequency() + +/mob/living/carbon/not_human/gondola/death() + disconnect_media_source() + ..() + +/mob/living/carbon/not_human/gondola/area_entered() + update_music() + +/mob/living/carbon/not_human/gondola/proc/connect_frequency() + // This is basically media_receivers["[media_frequency]"] += src + var/list/receivers=list() + var/freq = num2text(media_frequency) + if(freq in media_receivers) + receivers = media_receivers[freq] + receivers.Add(src) + media_receivers[freq]=receivers + + // Check if there's a broadcast to tune into. + if(freq in media_transmitters) + // Pick a random broadcast in that frequency. + var/obj/machinery/media/transmitter/B = pick(media_transmitters[freq]) + if(B.media_crypto == media_crypto) // Crypto-key check, if needed. + receive_broadcast(B.media_url,B.media_start_time) + +/mob/living/carbon/not_human/gondola/proc/receive_broadcast(var/url="", var/start_time=0) + media_url = url + media_start_time = start_time + update_music() + +/mob/living/carbon/not_human/gondola/proc/disconnect_frequency() + var/list/receivers=list() + var/freq = num2text(media_frequency) + if(freq in media_receivers) + receivers = media_receivers[freq] + receivers.Remove(src) + media_receivers[freq]=receivers + + receive_broadcast() + +/mob/living/carbon/not_human/gondola/update_music() + if(isDead(src)) + return + // Broadcasting shit + for(var/obj/machinery/media/transmitter/T in hooked) +// testing("[src] Writing media to [T].") + T.broadcast(media_url,media_start_time) + + if(exclusive_hook) + disconnect_media_source() // Just to be sure. + return + + update_media_source() + + // Bail if we lost connection to master. + if(!master_area) + return + + // Send update to clients. + for(var/mob/M in mobs_in_area(master_area)) + if(M == src) + continue + if(M && M.client) + M.update_music() + + ..() + +/mob/living/carbon/not_human/gondola/proc/update_media_source() + var/area/A = get_area(src) + if(!A) + return + // Check if there's a media source already. + if(A.media_source && A.media_source!=src) //if it does, the new media source replaces it. basically, the last media source arrived gets played on top. + A.media_source.disconnect_media_source()//you can turn a media source off and on for it to come back on top. + A.media_source=src + master_area=A + return + + // Update Media Source. + if(!A.media_source) + A.media_source=src + + master_area=A + + +/mob/living/carbon/not_human/gondola/proc/disconnect_media_source() + var/area/A = get_area(src) + + // Sanity + if(!A) + master_area=null + return + + // Check if there's a media source already. + if(A && A.media_source && A.media_source!=src) + master_area=null + return + + // Update Media Source. + A.media_source=null + + // Clients + for(var/mob/M in mobs_in_area(A)) + if(M && M.client) + M.update_music() + master_area=null \ No newline at end of file diff --git a/code/modules/mob/living/carbon/not_human/martian/combat.dm b/code/modules/mob/living/carbon/not_human/martian/combat.dm new file mode 100644 index 00000000000..3bb52835095 --- /dev/null +++ b/code/modules/mob/living/carbon/not_human/martian/combat.dm @@ -0,0 +1,8 @@ +/mob/living/carbon/not_human/martian/getarmor(var/def_zone, var/type) + + var/armorscore = 0 + if((def_zone == "head") || (def_zone == "eyes") || (def_zone == "mouth")) + if(head) + armorscore = head.armor[type] + + return armorscore \ No newline at end of file diff --git a/code/modules/mob/living/carbon/not_human/martian/inventory.dm b/code/modules/mob/living/carbon/not_human/martian/inventory.dm new file mode 100644 index 00000000000..29e35c24a57 --- /dev/null +++ b/code/modules/mob/living/carbon/not_human/martian/inventory.dm @@ -0,0 +1,149 @@ +/mob/living/carbon/not_human/martian/get_item_offset_by_index(index) + switch(index) + if(1,6) + return list("x"=0, "y"=0) + if(2,5) + return list("x"=0, "y"=8) + if(3,4) + return list("x"=0, "y"=14) + + return list() + +/mob/living/carbon/not_human/martian/get_held_item_ui_location(index) + if(!is_valid_hand_index(index)) + return + + switch(index) + if(1) + return "CENTER-3:16,SOUTH:5" + if(2) + return "CENTER-2:16,SOUTH:5:4" + if(3) + return "CENTER-1:16,SOUTH:5:10" + if(4) + return "CENTER:16,SOUTH:5:10" + if(5) + return "CENTER+1:16,SOUTH:5:4" + if(6) + return "CENTER+2:16,SOUTH:5" + else + return ..() + +/mob/living/carbon/not_human/martian/get_index_limb_name(index) + if(!index) + index = active_hand + + switch(index) + if(1) + return "right lower tentacle" + if(2) + return "right middle tentacle" + if(3) + return "right upper tentacle" + if(4) + return "left upper tentacle" + if(5) + return "left middle tentacle" + if(6) + return "left lower tentacle" + else + return "tentacle" + +/mob/living/carbon/not_human/martian/get_direction_by_index(index) + if(index <= 3) + return "right_hand" + else + return "left_hand" + + +/mob/living/carbon/not_human/martian/GetAccess() + var/list/ACL=list() + + for(var/obj/item/I in held_items) + ACL |= I.GetAccess() + + return ACL + +/mob/living/carbon/not_human/martian/get_visible_id() + var/id = null + for(var/obj/item/I in held_items) + id = I.GetID() + if(id) + break + return id + +/mob/living/carbon/not_human/martian/can_wield() + return 1 + +/mob/living/carbon/not_human/martian/u_equip(obj/item/W, dropped = 1, var/slot = null) + var/success = 0 + + if(!W) + return 0 + + if (W == head) + head = null + success = 1 + update_inv_head() + else + ..() + + if(success) + if (W) + if(client) + client.screen -= W + W.forceMove(loc) + W.unequipped(src, slot) + if(dropped) + W.dropped(src) + if(W) + W.reset_plane_and_layer() + + return + +/mob/living/carbon/not_human/martian/abiotic() + for(var/obj/item/I in held_items) + if(I.abstract) + continue + + return I + + return head + +/mob/living/carbon/not_human/martian/show_inv(mob/living/carbon/user) + user.set_machine(src) + + var/dat + + for(var/i = 1 to held_items.len) //Hands + var/obj/item/I = held_items[i] + dat += "[capitalize(get_index_limb_name(i))] [makeStrippingButton(I)]
    " + + dat += "
    Head: [makeStrippingButton(head)]" + + dat += {" +
    +
    Close + "} + + var/datum/browser/popup = new(user, "mob\ref[src]", "[src]", 340, 500) + popup.set_content(dat) + popup.open() + + +// Return the item currently in the slot ID +/mob/living/carbon/not_human/martian/get_item_by_slot(slot_id) + switch(slot_id) + if(slot_head) + return head + return null + +/mob/living/carbon/not_human/martian/equip_to_slot(obj/item/W, slot, redraw_mob = 1) + if(!istype(W)) + return + + if(slot == slot_head) + head = W + update_inv_head(redraw_mob) + + ..() \ No newline at end of file diff --git a/code/modules/mob/living/carbon/not_human/martian/life.dm b/code/modules/mob/living/carbon/not_human/martian/life.dm new file mode 100644 index 00000000000..ada6e49bfd2 --- /dev/null +++ b/code/modules/mob/living/carbon/not_human/martian/life.dm @@ -0,0 +1,49 @@ + +/mob/living/carbon/not_human/martian/get_breath_from_internal(volume_needed) + //As this is a race that can only wear helmets, we'll have a fishbowl helmet that can accept tanks in place of having gas mask setups + if(head && istype(head, /obj/item/clothing/head/helmet/space/martian)) + var/obj/item/clothing/head/helmet/space/martian/fishbowl = head + if(fishbowl.tank && istype(fishbowl.tank, /obj/item/weapon/tank)) + var/obj/item/weapon/tank/internals = fishbowl.tank + return internals.remove_air_volume(volume_needed) + return null + +/mob/living/carbon/not_human/martian/breathe() + .=..() + var/block = 0 + if(head) + if(istype(head, /obj/item/clothing/head/helmet/space/martian)) + block = 1 + + if(!block) + for(var/obj/effect/effect/smoke/chem/smoke in view(1, src)) + if(smoke.reagents.total_volume) + smoke.reagents.reaction(src, INGEST) + spawn(5) + if(smoke) + smoke.reagents.copy_to(src, 10) // I dunno, maybe the reagents enter the blood stream through the lungs? + break // If they breathe in the nasty stuff once, no need to continue checking + +/mob/living/carbon/not_human/martian/is_spaceproof() + if(head && istype(head, /obj/item/clothing/head/helmet/space/martian)) + return TRUE + return ..() + +/mob/living/carbon/not_human/martian/get_thermal_protection_flags() + var/thermal_protection_flags = 0 + if(head) + thermal_protection_flags |= head.body_parts_covered + return thermal_protection_flags + +/mob/living/carbon/not_human/martian/get_cold_protection() + + if(M_RESIST_COLD in mutations) + return 1 //Fully protected from the cold. + + var/thermal_protection = 0.0 + + if(head) + thermal_protection += head.return_thermal_protection() + + var/max_protection = get_thermal_protection(get_thermal_protection_flags()) + return min(thermal_protection,max_protection) diff --git a/code/modules/mob/living/carbon/not_human/martian/martian.dm b/code/modules/mob/living/carbon/not_human/martian/martian.dm new file mode 100644 index 00000000000..cfb9d395751 --- /dev/null +++ b/code/modules/mob/living/carbon/not_human/martian/martian.dm @@ -0,0 +1,146 @@ +#define MARTIANS_AMBIDEXTROUS //Comment out to prevent martians from being able to do multiple do_afters at once + +//WORK IN PROGRESS - Martians (name may be changed) +//Like octopuses but with 6 hands + +/* + DESIGN: + + + tentacles provide better grasp than hands. Martians are more resistant to winds, disarms and other hazards that would stun a human + + are ambidextrous + + * breathe oxygen and exhale CO2 like humans do + + - their unique shape means they can't fit into any human clothing, and can only put on hats + - toxins are very dangerous to them + +*/ + +/mob/living/carbon/not_human/martian + name = "martian" + desc = "An alien resembling an overgrown octopus." + voice_name = "martian" + + icon = 'icons/mob/martian.dmi' + icon_state = "martian" + + species_type = /mob/living/carbon/not_human/martian + speak_emote = list("blorbles","burbles") + + held_items = list(null, null, null, null, null, null) //6 hands + + unslippable = TRUE + size = SIZE_BIG + status_flags = CANSTUN|CANKNOCKDOWN|CANPARALYSE|CANPUSH + mob_bump_flag = HUMAN + mob_push_flags = ALLMOBS + mob_swap_flags = ALLMOBS + + + fire_dmi = 'icons/mob/OnFire.dmi' + fire_sprite = "Standing" + plane = HUMAN_PLANE + maxHealth = 150 + health = 150 + + //Inventory slots + var/obj/item/head //hat + + icon_state_standing = "martian" + icon_state_lying = "lying" + icon_state_dead = "dead" + + flag = 0 + + base_insulation = 0.5 + +/mob/living/carbon/not_human/martian/New() + name = pick("martian","scootaloo","squid","rootmarian","phoronitian","sepiida","octopodiforme",\ + "bolitaenides","belemnites","astrocanthoteuthis","octodad","ocotillo","kalamarian") + add_language(LANGUAGE_MARTIAN) + default_language = all_languages[LANGUAGE_MARTIAN] + ..() + +/mob/living/carbon/not_human/martian/Destroy() + head = null + + ..() + +#ifdef MARTIANS_AMBIDEXTROUS +/mob/living/carbon/not_human/martian/do_after_hand_check(held_item) + //Normally do_after breaks if you switch hands. With martians, it will only break if the used item is dropped + //This lets them do multiple things at once. + return (held_items.Find(held_item)) +#endif + +/mob/living/carbon/not_human/martian/eyecheck() + var/obj/item/clothing/head/headwear = src.head + var/protection + if(headwear) + protection = headwear.eyeprot + + return Clamp(protection, -2, 2) + +/mob/living/carbon/not_human/martian/earprot() + return 1 + +/mob/living/carbon/not_human/martian/dexterity_check() + return TRUE + +/mob/living/carbon/not_human/martian/IsAdvancedToolUser() + return TRUE + +/mob/living/carbon/not_human/martian/Process_Spaceslipping() + return 0 //No slipping + +/mob/living/carbon/not_human/martian/has_eyes() + return FALSE + +/mob/living/carbon/not_human/martian/updatehealth() + if(status_flags & GODMODE) + health = maxHealth + stat = CONSCIOUS + else + health = maxHealth - getOxyLoss() - getFireLoss() - getBruteLoss() - getCloneLoss() + + +/mob/living/carbon/not_human/martian/ex_act(severity) + if(flags & INVULNERABLE) + return + + flash_eyes(visual = 1) + + switch(severity) + if(1.0) + adjustBruteLoss(100) + adjustFireLoss(100) + if(prob(50)) + gib() + return + if(2.0) + adjustBruteLoss(60) + adjustFireLoss(60) + if(3.0) + adjustBruteLoss(30) + + apply_effect(severity*4, WEAKEN) + + + updatehealth() + +/mob/living/carbon/not_human/martian/Login() + ..() + update_hud() + +/mob/living/carbon/not_human/martian/Stat() + ..() + if(statpanel("Status")) + stat(null, "Intent: [a_intent]") + stat(null, "Move Mode: [m_intent]") + if(head && istype(head, /obj/item/clothing/head/helmet/space/martian)) + var/obj/item/clothing/head/helmet/space/martian/fishbowl = head + if(fishbowl.tank && istype(fishbowl.tank, /obj/item/weapon/tank)) + var/obj/item/weapon/tank/internal = fishbowl.tank + stat("Internal Atmosphere Info", internal.name) + stat("Tank Pressure", internal.air_contents.return_pressure()) + stat("Distribution Pressure", internal.distribute_pressure) \ No newline at end of file diff --git a/code/modules/mob/living/carbon/not_human/martian/update_icons.dm b/code/modules/mob/living/carbon/not_human/martian/update_icons.dm new file mode 100644 index 00000000000..f06b5995de9 --- /dev/null +++ b/code/modules/mob/living/carbon/not_human/martian/update_icons.dm @@ -0,0 +1,73 @@ +//MOB ICONS + +/mob/living/carbon/not_human/martian/update_icons() + ..() + overlays.len = 0 + for(var/image/I in item_overlays) + overlays += I +//INVENTORY ICONS + +#define HAT_LAYER 1 +//2-7 are used for hands +#define MAX_LAYERS 7 + +/mob/living/carbon/not_human/martian + var/list/item_overlays[MAX_LAYERS] //6 hands + hat + +/mob/living/carbon/not_human/martian/update_inv_hand(index, var/update_icons=1) + var/obj/item/I = get_held_item_by_index(index) + var/list/offsets = get_item_offset_by_index(index) + var/pixelx = 0 + var/pixely = 0 + if(offsets["x"]) + pixelx = offsets["x"] + if(offsets["y"]) + pixely = offsets["y"] + + if(I) + var/t_state = I.item_state + var/t_inhand_states = I.inhand_states[get_direction_by_index(index)] + if(!t_state) + t_state = I.icon_state + + var/image/hand_image = image("icon" = src.icon, "icon_state" = "hand_[index]") + hand_image.overlays += image("icon" = t_inhand_states, "icon_state" = t_state, "pixel_x" = pixelx, "pixel_y" = pixely) + + item_overlays[HAT_LAYER + index] = hand_image + + I.screen_loc = get_held_item_ui_location(index) + if (handcuffed) + drop_item(I) + else + item_overlays[HAT_LAYER + index] = null + + if(update_icons) + update_icons() + + +/mob/living/carbon/not_human/martian/update_inv_head(var/update_icons=1) + if(!head) + item_overlays[HAT_LAYER] = null + + if(update_icons) + update_icons() + return + else + item_overlays[HAT_LAYER] = image("icon" = ((head.icon_override) ? head.icon_override : 'icons/mob/head.dmi'), "icon_state" = "[head.icon_state]", "pixel_y" = 5) + + if(update_icons) + update_icons() + + if(client) + client.screen |= head + head.screen_loc = ui_monkey_hat + + + +/mob/living/carbon/not_human/martian/update_hud() + if(client) + update_internals() + client.screen |= contents + +#undef HAT_LAYER +#undef MAX_LAYERS \ No newline at end of file diff --git a/code/modules/mob/living/carbon/slime/life.dm b/code/modules/mob/living/carbon/slime/life.dm index 7e0b760c32b..104a45ef783 100644 --- a/code/modules/mob/living/carbon/slime/life.dm +++ b/code/modules/mob/living/carbon/slime/life.dm @@ -84,7 +84,7 @@ break - if(Target.health <= -70 || Target.stat == 2) + if(Target.health <= -70 || Target.isDead()) Target = null AIproc = 0 // to_chat(world, "break 3") diff --git a/code/modules/mob/living/carbon/slime/slime.dm b/code/modules/mob/living/carbon/slime/slime.dm index 8883dcee1a8..75352d49e0d 100644 --- a/code/modules/mob/living/carbon/slime/slime.dm +++ b/code/modules/mob/living/carbon/slime/slime.dm @@ -65,6 +65,7 @@ maxHealth = 200 health = 200 gender = NEUTER + size = SIZE_BIG update_icon = 0 nutrition = 800 // 1200 = max @@ -719,6 +720,7 @@ mob/living/carbon/slime/var/temperature_resistance = T0C+75 desc = "A potent chemical mix that will nullify a slime's powers, causing it to become docile and tame." icon = 'icons/obj/chemical.dmi' icon_state = "bottle19" + w_class = W_CLASS_TINY attack(mob/living/carbon/slime/M as mob, mob/user as mob) if(!istype(M, /mob/living/carbon/slime))//If target is not a slime. @@ -757,6 +759,7 @@ mob/living/carbon/slime/var/temperature_resistance = T0C+75 desc = "A potent chemical mix that will nullify a slime's powers, causing it to become docile and tame. This one is meant for adult slimes" icon = 'icons/obj/chemical.dmi' icon_state = "bottle19" + w_class = W_CLASS_TINY attack(mob/living/carbon/slime/adult/M as mob, mob/user as mob) if(!istype(M, /mob/living/carbon/slime/adult))//If target is not a slime. @@ -792,6 +795,7 @@ mob/living/carbon/slime/var/temperature_resistance = T0C+75 desc = "A potent chemical mix that will cause a slime to generate more extract." icon = 'icons/obj/chemical.dmi' icon_state = "bottle16" + w_class = W_CLASS_TINY attack(mob/living/carbon/slime/M as mob, mob/user as mob) if(!istype(M, /mob/living/carbon/slime))//If target is not a slime. @@ -817,6 +821,7 @@ mob/living/carbon/slime/var/temperature_resistance = T0C+75 desc = "A potent chemical mix that is a great nutrient for slimes." icon = 'icons/obj/chemical.dmi' icon_state = "bottle12" + w_class = W_CLASS_TINY var/Uses = 2 /obj/item/weapon/slimenutrient/attack(mob/living/carbon/slime/M as mob, mob/user as mob) @@ -843,6 +848,7 @@ mob/living/carbon/slime/var/temperature_resistance = T0C+75 desc = "A potent chemical mix that will give a slime extract three uses." icon = 'icons/obj/chemical.dmi' icon_state = "bottle17" + w_class = W_CLASS_TINY /*afterattack(obj/target, mob/user , flag) if(istype(target, /obj/item/slime_extract)) @@ -862,6 +868,7 @@ mob/living/carbon/slime/var/temperature_resistance = T0C+75 desc = "A potent chemical mix that will force a child slime to split in two!" icon = 'icons/obj/chemical.dmi' icon_state = "bottle15" + w_class = W_CLASS_TINY /obj/item/weapon/slimedupe/attack(mob/living/carbon/slime/M as mob, mob/user as mob) if(!istype(M, /mob/living/carbon/slime))//target is not a slime @@ -886,6 +893,7 @@ mob/living/carbon/slime/var/temperature_resistance = T0C+75 desc = "A potent chemical mix that when used on a slime extact, will bring it to life!" icon = 'icons/obj/chemical.dmi' icon_state = "bottle14" + w_class = W_CLASS_TINY ////////Adamantine Golem stuff I dunno where else to put it /* @@ -1154,7 +1162,7 @@ mob/living/carbon/slime/var/temperature_resistance = T0C+75 /obj/item/weapon/reagent_containers/food/snacks/egg/slime/process() var/turf/location = get_turf(src) var/datum/gas_mixture/environment = location.return_air() - if ((environment.toxins / environment.volume * CELL_VOLUME) > MOLES_PLASMA_VISIBLE)//plasma exposure causes the egg to hatch + if (environment.molar_density("toxins") > MOLES_PLASMA_VISIBLE / CELL_VOLUME)//plasma exposure causes the egg to hatch src.Hatch() /obj/item/weapon/reagent_containers/food/snacks/egg/slime/attackby(obj/item/weapon/W as obj, mob/user as mob) diff --git a/code/modules/mob/living/carbon/species.dm b/code/modules/mob/living/carbon/species.dm index 8b31b893326..84c5fce8c9e 100644 --- a/code/modules/mob/living/carbon/species.dm +++ b/code/modules/mob/living/carbon/species.dm @@ -53,7 +53,7 @@ var/global/list/whitelisted_species = list("Human") var/breath_type = "oxygen" // Non-oxygen gas breathed, if any. var/survival_gear = /obj/item/weapon/storage/box/survival // For spawnin'. - var/cold_level_1 = 260 // Cold damage level 1 below this point. + var/cold_level_1 = 220 // Cold damage level 1 below this point. var/cold_level_2 = 200 // Cold damage level 2 below this point. var/cold_level_3 = 120 // Cold damage level 3 below this point. @@ -142,6 +142,8 @@ var/global/list/whitelisted_species = list("Human") var/list/inventory_offsets + var/species_intro //What intro you're given when you become this species. + /datum/species/New() ..() @@ -326,7 +328,7 @@ var/global/list/whitelisted_species = list("Human") primitive = /mob/living/carbon/monkey/unathi darksight = 3 - cold_level_1 = 280 //Default 260 - Lower is better + cold_level_1 = 260 //Default 220 - Lower is better cold_level_2 = 220 //Default 200 cold_level_3 = 130 //Default 120 @@ -350,7 +352,7 @@ var/global/list/whitelisted_species = list("Human") known_languages = list(LANGUAGE_CLATTER) flags = IS_WHITELISTED | NO_BREATHE anatomy_flags = HAS_LIPS | NO_SKIN | NO_BLOOD - + meat_type = /obj/item/stack/sheet/bone chem_flags = NO_EAT | NO_INJECT default_mutations=list(SKELETON) @@ -364,6 +366,11 @@ var/global/list/whitelisted_species = list("Human") primitive = /mob/living/carbon/monkey/skellington + species_intro = "You are a Skellington
    \ + You have no skin, no blood, no lips, and only just enough brain to function.
    \ + You can not eat normally, as your necrotic state only permits you to only eat raw flesh. As you lack skin, you can not be injected via syringe.
    \ + You are also incredibly weak to brute damage and are rather slow, but you don't need to breathe, so that's going for you." + /datum/species/skellington/handle_speech(var/datum/speech/speech, mob/living/carbon/human/H) if (prob(25)) speech.message += " ACK ACK!" @@ -543,6 +550,10 @@ var/global/list/whitelisted_species = list("Human") "eyes" = /datum/organ/internal/eyes/grey ) + species_intro = "You are a Grey.
    \ + You are particularly allergic to water, which acts like acid to you, but the inverse is so for acid, so you're fun at parties.
    \ + You're not as good in a fist fight as a regular baseline human, but you make up for this by bullying them from afar by talking directly into peoples minds." + /datum/species/muton // /vg/ name = "Muton" icobase = 'icons/mob/human_races/r_muton.dmi' @@ -645,6 +656,11 @@ var/global/list/whitelisted_species = list("Human") "eyes" = /datum/organ/internal/eyes/vox ) + species_intro = "You are a Vox.
    \ + You are somewhat more adept at handling the lower pressures of space and colder temperatures.
    \ + You have talons with which you can slice others in a fist fight, and a beak which can be used to butcher corpses without the need for finer tools.
    \ + However, Oxygen is incredibly toxic to you, in breathing it or consuming it. You can only breathe nitrogen." + /datum/species/vox/equip(var/mob/living/carbon/human/H) // Unequip existing suits and hats. if(H.mind.assigned_role != "MODE") @@ -753,7 +769,7 @@ var/global/list/whitelisted_species = list("Human") H.equip_or_collect(new/obj/item/weapon/tank/nitrogen(H), tank_slot) else H.put_in_hands(new/obj/item/weapon/tank/nitrogen(H)) - to_chat(H, "You are now running on nitrogen internals from the [H.s_store] in your [tank_slot_name]. Your species finds oxygen toxic, so you must breathe nitrogen (AKA N2) only.") + to_chat(H, "You are now running on nitrogen internals from the [H.s_store] in your [tank_slot_name].") H.internal = H.get_item_by_slot(tank_slot) if (H.internals) H.internals.icon_state = "internal1" @@ -825,6 +841,12 @@ var/global/list/whitelisted_species = list("Human") move_speed_mod = 7 + species_intro = "You are a Diona.
    \ + You are a plant, so light is incredibly helpful for you, in both photosynthesis, and regenerating damage you have received.
    \ + You absorb radiation which helps you in a similar way to sunlight. You are incredibly slow as you are rooted to the ground.
    \ + You do not need to breathe, do not feel pain, you are incredibly resistant to cold and low pressure, and have no blood to bleed.
    \ + However, as you are a plant, you are incredibly susceptible to burn damage, which is something you can not regenerate normally." + /datum/species/golem name = "Golem" icobase = 'icons/mob/human_races/r_golem.dmi' @@ -886,7 +908,7 @@ var/list/has_died_as_golem = list() anim(target = H, a_icon = 'icons/mob/mob.dmi', flick_anim = "dust-g", sleeptime = 15) var/mob/living/adamantine_dust/A = new(H.loc) if(golemmind) - has_died_as_golem.Add(H.mind.key = world.time) + has_died_as_golem[H.mind.key] = world.time A.mind = golemmind H.mind = null golemmind.current = A @@ -1114,3 +1136,51 @@ var/list/has_died_as_golem = list() to_chat(user, "You place \the [O] into \the [src].") qdel(O) + + +/datum/species/mushroom + name = "Mushroom" + icobase = 'icons/mob/human_races/r_mushman.dmi' + deform = 'icons/mob/human_races/r_mushman.dmi' + known_languages = list() + meat_type = /obj/item/weapon/reagent_containers/food/snacks/hugemushroomslice/mushroom_man + + flags = IS_WHITELISTED | NO_BREATHE | IS_PLANT | REQUIRE_DARK | IS_SPECIES_MUTE + + gender = NEUTER + + darksight = 5 + tox_mod = 0.8 + brute_mod = 1.8 + burn_mod = 0.6 + + primitive = /mob/living/carbon/monkey/mushroom + + spells = list(/spell/targeted/genetic/invert_eyes) + + default_mutations=list(M_REMOTE_TALK) + default_block_names=list("REMOTETALK") + + blood_color = "#D3D3D3" + flesh_color = "#D3D3D3" + + //Copypaste of Dionae + cold_level_1 = 50 + cold_level_2 = -1 + cold_level_3 = -1 + + heat_level_1 = T0C + 50 + heat_level_2 = T0C + 75 + heat_level_3 = T0C + 100 + + has_mutant_race = 0 + + has_organ = list( + "brain" = /datum/organ/internal/brain/mushroom_brain, + ) + + species_intro = "You are a Mushroom Person.
    \ + You are an odd creature, light harms you and makes you hunger, but the darkness heals you and feeds you.
    \ + You have a resistance to burn and toxin, but a weakness to brute damage. You are adept at seeing in the dark, moreso with your light inversion ability.
    \ + However, you lack a mouth with which to talk. Instead you can remotely talk into somebodies mind should you examine them, or they talk to you.
    \ + You also have access to the Sporemind, which allows you to communicate with others on the Sporemind through :~" diff --git a/code/modules/mob/living/carbon/species_powers.dm b/code/modules/mob/living/carbon/species_powers.dm new file mode 100644 index 00000000000..fc3d4ea1cb1 --- /dev/null +++ b/code/modules/mob/living/carbon/species_powers.dm @@ -0,0 +1,30 @@ +/spell/targeted/genetic/invert_eyes + name = "Invert eyesight" + desc = "Inverts the colour spectrum you see, letting you see clearly in the dark, but not in the light." + panel = "Mutant Powers" + user_type = USER_TYPE_GENETIC + range = SELFCAST + + charge_type = Sp_RECHARGE + + spell_flags = INCLUDEUSER + + invocation_type = SpI_NONE + + override_base = "genetic" + hud_state = "wiz_sleepold" + var/toggle = TRUE + + +/spell/targeted/genetic/invert_eyes/cast(list/targets, mob/user) + var/list/colourmatrix = list() + if(toggle) + colourmatrix = list(-1, 0, 0, + 0,-1, 0, + 0, 0,-1, + 1, 1, 1) + else + colourmatrix = default_colour_matrix + for(var/mob/living/carbon/human/M in targets) + M.update_colour(50,0,colourmatrix) + toggle = !toggle \ No newline at end of file diff --git a/code/modules/mob/living/carbon/zombie/zombie.dm b/code/modules/mob/living/carbon/zombie/zombie.dm index 0586009dcad..c872b68d780 100644 --- a/code/modules/mob/living/carbon/zombie/zombie.dm +++ b/code/modules/mob/living/carbon/zombie/zombie.dm @@ -161,7 +161,7 @@ if(T.organs["head"]) affecting = T.organs["head"] affecting.take_damage(rand(1,7), 0) - playsound(get_turf(src), 'sound/items/eatfood.ogg', 50, 1) + playsound(src, 'sound/items/eatfood.ogg', 50, 1) if(prob(25)) target.contract_disease(new/datum/disease/z_virus) src.add_blood(src.target) diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm index 4955859bc82..8142a7417b9 100644 --- a/code/modules/mob/living/damage_procs.dm +++ b/code/modules/mob/living/damage_procs.dm @@ -11,9 +11,7 @@ /mob/living/proc/apply_damage(var/damage = 0,var/damagetype = BRUTE, var/def_zone = null, var/blocked = 0, var/used_weapon = null, ignore_events = 0) if(!damage || (blocked >= 2)) return 0 - var/damage_done = damage/(blocked+1) - damage_done = run_armor_absorb(def_zone, damagetype, damage_done) switch(damagetype) if(BRUTE) adjustBruteLoss(damage_done) diff --git a/code/modules/mob/living/holders.dm b/code/modules/mob/living/holders.dm index c80125b27be..a9566cedf83 100644 --- a/code/modules/mob/living/holders.dm +++ b/code/modules/mob/living/holders.dm @@ -159,6 +159,16 @@ update_itemstate_on_twohand = TRUE +//SALEM + +/obj/item/weapon/holder/animal/salem + name = "salem holder" + desc = "Esp!" + item_state = "salem" + + update_itemstate_on_twohand = TRUE + + //SLIMES /obj/item/weapon/holder/animal/slime name = "slime holder" diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 920e5d54658..417b784e52e 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -34,8 +34,7 @@ . = ..() -/mob/living/examine(mob/user) //Show the mob's size and whether it's been butchered - var/size +/mob/living/examine(var/mob/user, var/size = "", var/show_name = TRUE, var/show_icon = TRUE) //Show the mob's size and whether it's been butchered switch(src.size) if(SIZE_TINY) size = "tiny" @@ -56,7 +55,7 @@ else if(src.gender == PLURAL) pronoun = "they are" - ..(user, " [capitalize(pronoun)] [size].") + ..(user, " [capitalize(pronoun)] [size].", show_name, FALSE) if(meat_taken > 0) to_chat(user, "[capitalize(pronoun)] partially butchered.") @@ -521,13 +520,11 @@ Thanks. if(iscarbon(src)) var/mob/living/carbon/C = src - if (C.handcuffed && !initial(C.handcuffed)) + if(C.handcuffed) C.drop_from_inventory(C.handcuffed) - C.handcuffed = initial(C.handcuffed) - if (C.legcuffed && !initial(C.legcuffed)) + if (C.legcuffed) C.drop_from_inventory(C.legcuffed) - C.legcuffed = initial(C.legcuffed) hud_updateflag |= 1 << HEALTH_HUD hud_updateflag |= 1 << STATUS_HUD @@ -611,9 +608,6 @@ Thanks. IO.status = 0 IO.robotic = 0 H.updatehealth() - if(iscarbon(src)) - var/mob/living/carbon/C = src - C.handcuffed = initial(C.handcuffed) for(var/datum/disease/D in viruses) D.cure(0) if(stat == DEAD) @@ -1408,12 +1402,7 @@ Thanks. return if(!can_butcher) - if(meat_taken) - to_chat(user, "[src] has already been butchered.") - return - else - to_chat(user, "You can't butcher [src]!") - return + to_chat(user, "You can't butcher [src]!") return var/obj/item/tool = null //The tool that is used for butchering @@ -1459,13 +1448,16 @@ Thanks. if(src.butchering_drops && src.butchering_drops.len) var/list/actions = list() - actions += "Butcher" + if(meat_taken < meat_amount) + actions += "Butcher" for(var/datum/butchering_product/B in src.butchering_drops) if(B.amount <= 0) continue - actions |= capitalize(B.verb_name) actions[capitalize(B.verb_name)] = B + if(!actions.len) + to_chat(user, "[src] has already been butchered.") + return actions += "Cancel" var/choice = input(user,"What would you like to do with \the [src]?","Butchering") in actions @@ -1492,6 +1484,10 @@ Thanks. src.update_icons() return + else if(meat_taken >= meat_amount) + to_chat(user, "[src] has already been butchered.") + return + user.visible_message("[user] starts butchering \the [src][tool ? " with \the [tool]" : ""].",\ "You start butchering \the [src].") src.being_butchered = 1 @@ -1513,7 +1509,6 @@ Thanks. return to_chat(user, "You butcher \the [src].") - can_butcher = 0 if(istype(src, /mob/living/simple_animal)) //Animals can be butchered completely, humans - not so if(src.size > SIZE_TINY) //Tiny animals don't produce gibs diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index 780b5664e3d..f9fc6395440 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -49,7 +49,6 @@ /mob/living/proc/run_armor_absorb(var/def_zone = null, var/attack_flag = "melee", var/initial_damage) var/armor = getarmorabsorb(def_zone, attack_flag) var/final_damage = initial_damage - if(armor) var/damage_multiplier = final_damage/armor if(damage_multiplier < 1) @@ -79,7 +78,8 @@ P.on_hit(src,2) return 2 if(!P.nodamage) - apply_damage((P.damage/(absorb+1)), P.damage_type, def_zone, absorb, P.is_sharp(), used_weapon = P) + var/damage = run_armor_absorb(def_zone, P.flag, (P.damage/(absorb+1))) + apply_damage(damage, P.damage_type, def_zone, absorb, P.is_sharp(), used_weapon = P) regenerate_icons() P.on_hit(src, absorb) if(istype(P, /obj/item/projectile/beam/lightning)) @@ -101,6 +101,8 @@ var/obj/item/weapon/W = O dtype = W.damtype src.visible_message("[src] has been hit by [O].") + if(O.impactsound) + playsound(loc, O.impactsound, 80, 1, -1) var/zone_normal_name switch(zone) if(LIMB_LEFT_ARM) @@ -115,7 +117,8 @@ zone_normal_name = zone var/armor = run_armor_check(zone, "melee", "Your armor has protected your [zone_normal_name].", "Your armor has softened the blow to your [zone_normal_name].", armor_penetration = O.throwforce*(speed/5)*O.sharpness) if(armor < 2) - apply_damage(O.throwforce*(speed/5), dtype, zone, armor, O.is_sharp(), O) + var/damage = run_armor_absorb(zone, "melee", O.throwforce*(speed/5)) + apply_damage(damage, dtype, zone, armor, O.is_sharp(), O) // Begin BS12 momentum-transfer code. @@ -300,8 +303,8 @@ if(istype(T)) var/datum/gas_mixture/G = loc.return_air() // Check if we're standing in an oxygenless environment if(G) - oxy=G.oxygen/G.volume*CELL_VOLUME - if(oxy < 1 || fire_stacks <= 0) + oxy = G.molar_density("oxygen") + if(oxy < (1 / CELL_VOLUME) || fire_stacks <= 0) ExtinguishMob() //If there's no oxygen in the tile we're on, put out the fire return 1 var/turf/location = get_turf(src) diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index 029bccc18a1..dd0f4d0bfb5 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -24,34 +24,64 @@ return "cultchat" if(MODE_ANCIENT) return "ancientchat" + if(MODE_MUSHROOM) + return "sporechat" else return "Unknown" var/list/department_radio_keys = list( - ":0" = "Deathsquad", "#0" = "Deathsquad", ".0" = "Deathsquad", - - ":r" = "right ear", "#r" = "right ear", ".r" = "right ear", "!r" = "fake right ear", - ":l" = "left ear", "#l" = "left ear", ".l" = "left ear", "!l" = "fake left ear", - ":i" = "intercom", "#i" = "intercom", ".i" = "intercom", - ":h" = "department", "#h" = "department", ".h" = "department", - ":c" = "Command", "#c" = "Command", ".c" = "Command", - ":n" = "Science", "#n" = "Science", ".n" = "Science", - ":m" = "Medical", "#m" = "Medical", ".m" = "Medical", - ":e" = "Engineering", "#e" = "Engineering", ".e" = "Engineering", - ":s" = "Security", "#s" = "Security", ".s" = "Security", - ":w" = "whisper", "#w" = "whisper", ".w" = "whisper", - ":b" = "binary", "#b" = "binary", ".b" = "binary", + ":0" = "Deathsquad", "#0" = "Deathsquad", ".0" = "Deathsquad", + //1 Used by LANGUAGE_GALACTIC_COMMON + //2 Used by LANGUAGE_TRADEBAND + //3 Used by LANGUAGE_GUTTER + //4 Used by LANGUAGE_XENO + //5 Used by LANGUAGE_CULT + //6 Used by LANGUAGE_MONKEY + //7 Used by LANGUAGE_HUMAN + //8 Used by LANGUAGE_GOLEM + //9 Used by LANGUAGE_MOUSE + ":-" = "Response Team","#-" = "Response Team",".-" = "Response Team", ":a" = "alientalk", "#a" = "alientalk", ".a" = "alientalk", - ":t" = "Syndicate", "#t" = "Syndicate", ".t" = "Syndicate", - ":r" = "Response Team","#r" = "Response Team",".r" = "Response Team", - ":u" = "Supply", "#u" = "Supply", ".u" = "Supply", + ":b" = "binary", "#b" = "binary", ".b" = "binary", + ":c" = "Command", "#c" = "Command", ".c" = "Command", ":d" = "Service", "#d" = "Service", ".d" = "Service", + ":e" = "Engineering", "#e" = "Engineering", ".e" = "Engineering", + //f Used by LANGUAGE_SLIME ":g" = "changeling", "#g" = "changeling", ".g" = "changeling", + ":h" = "department", "#h" = "department", ".h" = "department", + ":i" = "intercom", "#i" = "intercom", ".i" = "intercom", + //j Used by LANGUAGE_TAJARAN + //k Used by LANGUAGE_SKRELLIAN and LANGUAGE_GREY + ":l" = "left hand", "#l" = "left hand", ".l" = "left hand", "!l" = "fake left hand", + ":m" = "Medical", "#m" = "Medical", ".m" = "Medical", + ":n" = "Science", "#n" = "Science", ".n" = "Science", + //o Used by LANGUAGE_UNATHI + ":p" = "AI Private", "#p" = "AI Private", ".p" = "AI Private", + //q Used by LANGUAGE_ROOTSPEAK + ":r" = "right hand", "#r" = "right hand", ".r" = "right hand", "!r" = "fake right hand", + ":s" = "Security", "#s" = "Security", ".s" = "Security", + ":t" = "Syndicate", "#t" = "Syndicate", ".t" = "Syndicate", + ":u" = "Supply", "#u" = "Supply", ".u" = "Supply", + //v Used by LANGUAGE_VOX + ":w" = "whisper", "#w" = "whisper", ".w" = "whisper", ":x" = "cultchat", "#x" = "cultchat", ".x" = "cultchat", ":y" = "ancientchat", "#y" = "ancientchat", ".y" = "ancientchat", - ":p" = "AI Private", "#p" = "AI Private", ".p" = "AI Private", + //z Used by LANGUAGE_CLATTER + //@ Used by LANGUAGE_MARTIAN + ":~" = "sporechat", "#~" = "sporechat", ".~" = "sporechat", - ":R" = "right ear", "#R" = "right ear", ".R" = "right ear", "!R" = "fake right ear", - ":L" = "left ear", "#L" = "left ear", ".L" = "left ear", "!L" = "fake left ear", + + + + + + + + + + + + ":R" = "right hand", "#R" = "right hand", ".R" = "right hand", "!R" = "fake right hand", + ":L" = "left hand", "#L" = "left hand", ".L" = "left hand", "!L" = "fake left hand", ":I" = "intercom", "#I" = "intercom", ".I" = "intercom", ":H" = "department", "#H" = "department", ".H" = "department", ":C" = "Command", "#C" = "Command", ".C" = "Command", @@ -63,7 +93,6 @@ var/list/department_radio_keys = list( ":B" = "binary", "#B" = "binary", ".B" = "binary", ":A" = "alientalk", "#A" = "alientalk", ".A" = "alientalk", ":T" = "Syndicate", "#T" = "Syndicate", ".T" = "Syndicate", - ":R" = "Response Team","#R" = "Response Team",".R" = "Response Team", ":U" = "Supply", "#U" = "Supply", ".U" = "Supply", ":D" = "Service", "#D" = "Service", ".D" = "Service", ":G" = "changeling", "#G" = "changeling", ".G" = "changeling", @@ -73,21 +102,21 @@ var/list/department_radio_keys = list( //kinda localization -- rastaf0 //same keys as above, but on russian keyboard layout. This file uses cp1251 as encoding. - ":ê" = "right ear", "#ê" = "right ear", ".ê" = "right ear", - ":ä" = "left ear", "#ä" = "left ear", ".ä" = "left ear", + ":ê" = "right hand", "#ê" = "right hand", ".ê" = "right hand", + ":ä" = "left hand", "#ä" = "left hand", ".ä" = "left hand", ":ø" = "intercom", "#ø" = "intercom", ".ø" = "intercom", ":ð" = "department", "#ð" = "department", ".ð" = "department", - ":ñ" = "Command", "#ñ" = "Command", ".ñ" = "Command", - ":ò" = "Science", "#ò" = "Science", ".ò" = "Science", - ":ü" = "Medical", "#ü" = "Medical", ".ü" = "Medical", - ":ó" = "Engineering", "#ó" = "Engineering", ".ó" = "Engineering", + ":ñ" = "Command", "#ñ" = "Command", ".ñ" = "Command", + ":ò" = "Science", "#ò" = "Science", ".ò" = "Science", + ":ü" = "Medical", "#ü" = "Medical", ".ü" = "Medical", + ":ó" = "Engineering","#ó" = "Engineering", ".ó" = "Engineering", ":û" = "Security", "#û" = "Security", ".û" = "Security", - ":ö" = "whisper", "#ö" = "whisper", ".ö" = "whisper", + ":ö" = "whisper", "#ö" = "whisper", ".ö" = "whisper", ":è" = "binary", "#è" = "binary", ".è" = "binary", - ":ô" = "alientalk", "#ô" = "alientalk", ".ô" = "alientalk", - ":å" = "Syndicate", "#å" = "Syndicate", ".å" = "Syndicate", + ":ô" = "alientalk", "#ô" = "alientalk", ".ô" = "alientalk", + ":å" = "Syndicate", "#å" = "Syndicate", ".å" = "Syndicate", ":é" = "Supply", "#é" = "Supply", ".é" = "Supply", - ":â" = "Service", "#â" = "Service", ".â" = "Service", + ":â" = "Service", "#â" = "Service", ".â" = "Service", ":ï" = "changeling", "#ï" = "changeling", ".ï" = "changeling" ) @@ -361,6 +390,17 @@ var/list/department_radio_keys = list( if(!istype(M,/mob/new_player)) handle_render(M,themessage,src) return 1 + if(MODE_MUSHROOM) + var/message = text("Sporemind, []: []", src.name, html_encode(speech.message)) + var/turf/T = get_turf(src) + log_say("[key_name(src)] (@[T.x],[T.y],[T.z]) Spore chat: [html_encode(speech.message)]") + for(var/mob/M in player_list) + if(iscarbon(M)) + var/mob/living/carbon/human/H = M + if(ismushroom(H)) + handle_render(M, message,src) + if((M in dead_mob_list) && !istype(M, /mob/new_player)) + handle_render(M, message,src) return 0 /mob/living/proc/treat_speech(var/datum/speech/speech, genesay = 0) @@ -456,7 +496,7 @@ var/list/department_radio_keys = list( display_bubble_to_clientlist(image('icons/mob/talk.dmi', get_holder_at_turf_level(src), "h[bubble_type][say_test(message)]",MOB_LAYER+1), tracking_speech_bubble_recipients) /proc/display_bubble_to_clientlist(var/image/speech_bubble, var/clientlist) - speech_bubble.plane = BASE_PLANE + speech_bubble.plane = ABOVE_LIGHTING_PLANE speech_bubble.appearance_flags = RESET_COLOR flick_overlay(speech_bubble, clientlist, 30) diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 01a2033bb7e..164bed9f20c 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -2,41 +2,39 @@ var/list/ai_list = list() //Not sure why this is necessary... /proc/AutoUpdateAI(obj/subject) - var/is_in_use = 0 - if (subject!=null) + var/is_in_use = FALSE + if(subject!=null) for(var/A in ai_list) var/mob/living/silicon/ai/M = A - if ((M.client && M.machine == subject)) - is_in_use = 1 + if((M.client && M.machine == subject)) + is_in_use = TRUE subject.attack_ai(M) return is_in_use /mob/living/silicon/ai name = "AI" - icon = 'icons/mob/AI.dmi'// + icon = 'icons/mob/AI.dmi' icon_state = "ai" - anchored = 1 // -- TLE - density = 1 + anchored = TRUE // -- TLE + density = TRUE status_flags = CANSTUN|CANPARALYSE|CANPUSH - force_compose = 1 + force_compose = TRUE size = SIZE_BIG var/list/network = list(CAMERANET_SS13) var/obj/machinery/camera/current = null var/list/connected_robots = list() var/aiRestorePowerRoutine = 0 - //var/list/laws = list() var/alarms = list("Motion"=list(), "Fire"=list(), "Atmosphere"=list(), "Power"=list(), "Camera"=list()) - var/viewalerts = 0 + var/viewalerts = FALSE var/lawcheck[1] var/ioncheck[1] var/icon/holo_icon//Default is assigned when AI is created. var/obj/item/device/pda/ai/aiPDA = null var/obj/item/device/multitool/aiMulti = null var/obj/item/device/station_map/station_holomap = null - var/custom_sprite = 0 //For our custom sprites - var/obj/item/device/camera/ai_camera/aicamera = null + var/obj/item/device/camera/silicon/aicamera = null var/busy = FALSE //Toggle Floor Bolt busy var. //Hud stuff @@ -44,20 +42,20 @@ var/list/ai_list = list() //MALFUNCTION var/ai_flags = 0 - var/control_disabled = 0 // Set to 1 to stop AI from interacting via Click() -- TLE - var/malfhacking = 0 // More or less a copy of the above var, so that malf AIs can hack and still get new cyborgs -- NeoFite + var/control_disabled = FALSE // Set to TRUE to stop AI from interacting via Click() -- TLE + var/malfhacking = FALSE // More or less a copy of the above var, so that malf AIs can hack and still get new cyborgs -- NeoFite var/obj/machinery/power/apc/malfhack = null - var/explosive = 0 //does the AI explode when it dies? + var/explosive = FALSE //does the AI explode when it dies? var/mob/living/silicon/ai/parent = null - var/camera_light_on = 0 + var/camera_light_on = FALSE var/list/obj/machinery/camera/lit_cameras = list() var/datum/trackable/track = new() var/last_paper_seen = null - var/can_shunt = 1 + var/can_shunt = TRUE var/last_announcement = "" // The AI's "eye". Described on the top of the page in eye.dm @@ -67,38 +65,32 @@ var/list/ai_list = list() var/cooldown = 0 var/acceleration = 1 -/mob/living/silicon/ai/New(loc, var/datum/ai_laws/L, var/obj/item/device/mmi/B, var/safety = 0) +/mob/living/silicon/ai/New(loc, var/datum/ai_laws/L, var/obj/item/device/mmi/B, var/safety = FALSE) + var/list/possibleNames = ai_names var/pickedName = null while(!pickedName) pickedName = pick(ai_names) for (var/mob/living/silicon/ai/A in mob_list) - if (A.real_name == pickedName && possibleNames.len > 1) //fixing the theoretically possible infinite loop + if(A.real_name == pickedName && possibleNames.len > 1) //fixing the theoretically possible infinite loop possibleNames -= pickedName pickedName = null - add_language(LANGUAGE_GALACTIC_COMMON, 1) - add_language(LANGUAGE_UNATHI, 1) - add_language(LANGUAGE_CATBEAST, 1) - add_language(LANGUAGE_SKRELLIAN, 1) - add_language(LANGUAGE_ROOTSPEAK, 1) - add_language(LANGUAGE_GUTTER, 1) - add_language(LANGUAGE_CLATTER, 1) - add_language(LANGUAGE_GREY, 1) - add_language(LANGUAGE_MONKEY, 1) - add_language(LANGUAGE_VOX, 1) - add_language(LANGUAGE_GOLEM, 1) - add_language(LANGUAGE_TRADEBAND, 1) - add_language(LANGUAGE_MOUSE, 1) - add_language(LANGUAGE_GOLEM, 1) - add_language(LANGUAGE_SLIME, 1) - add_language(LANGUAGE_HUMAN, 1) + + //AIs speak all languages that aren't restricted(XENO, CULT). + for(var/language_name in all_languages) + var/datum/language/lang = all_languages[language_name] + if(!(lang.flags & RESTRICTED) && !(lang in languages)) + add_language(lang.name) + + //But gal common is restricted so let's add it manually. + add_language(LANGUAGE_GALACTIC_COMMON) default_language = all_languages[LANGUAGE_GALACTIC_COMMON] + real_name = pickedName name = real_name - view_core() - anchored = 1 - canmove = 0 + anchored = TRUE + canmove = FALSE setDensity(TRUE) loc = loc @@ -125,19 +117,19 @@ var/list/ai_list = list() station_holomap = new(src) aiMulti = new(src) - aicamera = new/obj/item/device/camera/ai_camera(src) - if (istype(loc, /turf)) + aicamera = new /obj/item/device/camera/silicon/ai_camera(src) + if(istype(loc, /turf)) verbs.Add(/mob/living/silicon/ai/proc/ai_network_change, \ /mob/living/silicon/ai/proc/ai_statuschange, \ /mob/living/silicon/ai/proc/ai_hologram_change) if(!safety)//Only used by AIize() to successfully spawn an AI. - if (!B)//If there is no player/brain inside. + if(!B)//If there is no player/brain inside. new/obj/structure/AIcore/deactivated(loc)//New empty terminal. qdel(src)//Delete AI. return else - if (B.brainmob.mind) + if(B.brainmob.mind) B.brainmob.mind.transfer_to(src) to_chat(src, "You are playing the station's AI. The AI cannot move, but can interact with many objects while viewing them (through cameras).") @@ -182,7 +174,7 @@ var/list/ai_list = list() var/list/nametemp = list() var/find var/datum/picture/selection - if(aicamera.aipictures.len == 0) + if(!aicamera.aipictures.len) to_chat(usr, "No images saved") return for(var/datum/picture/t in aicamera.aipictures) @@ -199,7 +191,7 @@ var/list/ai_list = list() switch(choice) if("Cancel") return - if ("Delete") + if("Delete") aicamera.aipictures.Remove(selection) qdel(selection) if("Rename") @@ -214,26 +206,6 @@ var/list/ai_list = list() set name = "Set AI Core Display" if(stat || aiRestorePowerRoutine) return - /* Jesus christ, more of this shit? - if(!custom_sprite) //Check to see if custom sprite time, checking the appopriate file to change a var - var/file = file2text("config/custom_sprites.txt") - var/lines = splittext(file, "\n") - - for(var/line in lines) - // split & clean up - var/list/Entry = splittext(line, "-") - for(var/i = 1 to Entry.len) - Entry[i] = trim(Entry[i]) - - if(Entry.len < 2) - continue; - - if(Entry[1] == src.ckey && Entry[2] == src.real_name) - custom_sprite = 1 //They're in the list? Custom sprite time - icon = 'icons/mob/custom-synthetic.dmi' - */ - //if(icon_state == initial(icon_state)) - /* Nuked your hidden shit.*/ var/icontype = input("Select an icon!", "AI", null, null) as null|anything in list("Monochrome", "Blue", "Inverted", "Text", "Smiley", "Angry", "Dorf", "Matrix", "Bliss", "Firewall", "Green", "Red", "Broken Output", "Triumvirate", "Triumvirate Static", "Searif", "Ravensdale", "Serithi", "Static", "Wasp", "Robert House", "Red October", "Fabulous", "Girl", "Girl Malf", "Boy", "Boy Malf", "Four-Leaf", "Yes Man", "Hourglass", "Patriot", "Pirate", "Royal", "Heartline", "Hades", "Helios", "Syndicat", "Alien", "Too Deep", "Goon", "Database", "Glitchman", "Nanotrasen", "Angel", "Gentoo", "Murica", "President", "Fort", "Mothman", "Dancing Hotdog", "Diagnosis", "Drink It!", "Metaclub", "Jack Frost") switch(icontype) if("Clown") @@ -345,10 +317,6 @@ var/list/ai_list = list() if("Jack Frost") icon_state = "ai-jack" else icon_state = "ai" - //else -// to_chat(usr, "You can only change your display once!") - //return - // displays the malf_ai information if the AI is the malf /mob/living/silicon/ai/show_malf_ai() @@ -370,31 +338,31 @@ var/list/ai_list = list() for (var/cat in alarms) dat += text("[]
    \n", cat) var/list/L = alarms[cat] - if (L.len) + if(L.len) for (var/alarm in L) var/list/alm = L[alarm] var/area/A = alm[1] var/C = alm[2] var/list/sources = alm[3] dat += "" - if (C && istype(C, /list)) + if(C && istype(C, /list)) var/dat2 = "" for (var/obj/machinery/camera/I in C) dat2 += text("[][]", (dat2=="") ? "" : " | ", src, I, I.c_tag) dat += text("-- [] ([])", A.name, (dat2!="") ? dat2 : "No Camera") - else if (C && istype(C, /obj/machinery/camera)) + else if(C && istype(C, /obj/machinery/camera)) var/obj/machinery/camera/Ctmp = C dat += text("-- [] ([])", A.name, src, C, Ctmp.c_tag) else dat += text("-- [] (No Camera)", A.name) - if (sources.len > 1) + if(sources.len > 1) dat += text("- [] sources", sources.len) dat += "
    \n" else dat += "-- All Systems Nominal
    \n" dat += "
    \n" - viewalerts = 1 + viewalerts = TRUE src << browse(dat, "window=aialerts&can_close=0") // this verb lets the ai see the stations manifest @@ -402,7 +370,7 @@ var/list/ai_list = list() show_station_manifest() /mob/living/silicon/ai/proc/ai_call_shuttle() - if(src.stat == 2) + if(isDead()) to_chat(src, "You can't call the shuttle because you are dead!") return if(istype(usr,/mob/living/silicon/ai)) @@ -429,7 +397,7 @@ var/list/ai_list = list() /mob/living/silicon/ai/proc/ai_cancel_call() set category = "AI Commands" - if(src.stat == 2) + if(isDead()) to_chat(src, "You can't send the shuttle back because you are dead!") return if(istype(usr,/mob/living/silicon/ai)) @@ -440,32 +408,32 @@ var/list/ai_list = list() recall_shuttle(src) /mob/living/silicon/ai/check_eye(var/mob/user as mob) - if (!current) + if(!current) return null user.reset_view(current) - return 1 + return TRUE /mob/living/silicon/ai/blob_act() if(flags & INVULNERABLE) return - if (stat != DEAD) + if(stat != DEAD) ..() playsound(loc, 'sound/effects/blobattack.ogg',50,1) adjustBruteLoss(60) updatehealth() - return 1 - return 0 + return TRUE + return FALSE /mob/living/silicon/ai/restrained() if(timestopped) - return 1 //under effects of time magick - return 0 + return TRUE //under effects of time magick + return FALSE /mob/living/silicon/ai/emp_act(severity) if(flags & INVULNERABLE) return - if (prob(30)) + if(prob(30)) switch(pick(1,2)) if(1) view_core() @@ -478,46 +446,46 @@ var/list/ai_list = list() return // if(!blinded) (this is now in flash_eyes) - flash_eyes(visual = 1, affect_silicon = 1) + flash_eyes(visual = TRUE, affect_silicon = TRUE) switch(severity) if(1.0) - if (stat != 2) + if(!isDead()) adjustBruteLoss(100) adjustFireLoss(100) if(2.0) - if (stat != 2) + if(!isDead()) adjustBruteLoss(60) adjustFireLoss(60) if(3.0) - if (stat != 2) + if(!isDead()) adjustBruteLoss(30) updatehealth() /mob/living/silicon/ai/put_in_hands(var/obj/item/W) - return 0 + return FALSE /mob/living/silicon/ai/Topic(href, href_list) if(usr != src) return ..() - if (href_list["mach_close"]) - if (href_list["mach_close"] == "aialerts") - viewalerts = 0 + if(href_list["mach_close"]) + if(href_list["mach_close"] == "aialerts") + viewalerts = FALSE var/t1 = text("window=[]", href_list["mach_close"]) unset_machine() src << browse(null, t1) - if (href_list["switchcamera"]) + if(href_list["switchcamera"]) switchCamera(locate(href_list["switchcamera"])) in cameranet.cameras - if (href_list["showalerts"]) + if(href_list["showalerts"]) ai_alerts() if(href_list["show_paper"]) if(last_paper_seen) src << browse(last_paper_seen, "window=show_paper") //Carn: holopad requests - if (href_list["jumptoholopad"]) + if(href_list["jumptoholopad"]) var/obj/machinery/hologram/holopad/H = locate(href_list["jumptoholopad"]) if(stat == CONSCIOUS) if(H) @@ -529,44 +497,42 @@ var/list/ai_list = list() play_vox_word(href_list["say_word"], null, src) return - if (href_list["lawc"]) // Toggling whether or not a law gets stated by the State Laws verb --NeoFite + if(href_list["lawc"]) // Toggling whether or not a law gets stated by the State Laws verb --NeoFite var/L = text2num(href_list["lawc"]) switch(lawcheck[L+1]) - if ("Yes") + if("Yes") lawcheck[L+1] = "No" - if ("No") + if("No") lawcheck[L+1] = "Yes" -// to_chat(src, text ("Switching Law [L]'s report status to []", lawcheck[L+1])) checklaws() - if (href_list["lawi"]) // Toggling whether or not a law gets stated by the State Laws verb --NeoFite + if(href_list["lawi"]) // Toggling whether or not a law gets stated by the State Laws verb --NeoFite var/L = text2num(href_list["lawi"]) switch(ioncheck[L]) - if ("Yes") + if("Yes") ioncheck[L] = "No" - if ("No") + if("No") ioncheck[L] = "Yes" -// to_chat(src, text ("Switching Law [L]'s report status to []", lawcheck[L+1])) checklaws() - if (href_list["laws"]) // With how my law selection code works, I changed statelaws from a verb to a proc, and call it through my law selection panel. --NeoFite + if(href_list["laws"]) // With how my law selection code works, I changed statelaws from a verb to a proc, and call it through my law selection panel. --NeoFite statelaws() - if (href_list["track"]) + if(href_list["track"]) var/mob/target = locate(href_list["track"]) in mob_list var/mob/living/silicon/ai/A = locate(href_list["track2"]) in mob_list if(A && target) A.ai_actual_track(target) return - else if (href_list["faketrack"]) + else if(href_list["faketrack"]) var/mob/target = locate(href_list["track"]) in mob_list var/mob/living/silicon/ai/A = locate(href_list["track2"]) in mob_list if(A && target) A.cameraFollow = target to_chat(A, text("Now tracking [] on camera.", target.name)) - if (usr.machine == null) + if(usr.machine == null) usr.machine = usr while (src.cameraFollow == target) @@ -576,7 +542,7 @@ var/list/ai_list = list() return - if (href_list["open"]) + if(href_list["open"]) var/mob/target = locate(href_list["open"]) var/mob/living/silicon/ai/A = locate(href_list["open2"]) if(A && target) @@ -592,19 +558,19 @@ var/list/ai_list = list() /mob/living/silicon/ai/attack_alien(mob/living/carbon/alien/humanoid/M) switch(M.a_intent) - if (I_HELP) + if(I_HELP) visible_message("[M] caresses [src]'s plating with its scythe like arm.") else //harm if(M.unarmed_attack_mob(src)) if(prob(8)) - flash_eyes(visual = 1, type = /obj/abstract/screen/fullscreen/flash/noise) + flash_eyes(visual = TRUE, type = /obj/abstract/screen/fullscreen/flash/noise) /mob/living/silicon/ai/attack_animal(mob/living/simple_animal/M as mob) M.unarmed_attack_mob(src) /mob/living/silicon/ai/reset_view(atom/A) - if (camera_light_on) + if(camera_light_on) light_cameras() if(istype(A,/obj/machinery/camera)) current = A @@ -616,8 +582,8 @@ var/list/ai_list = list() src.cameraFollow = null - if (!C || stat == 2) //C.can_use()) - return 0 + if(!C || isDead()) //C.can_use()) + return FALSE if(!src.eyeobj) view_core() @@ -626,61 +592,61 @@ var/list/ai_list = list() eyeobj.forceMove(get_turf(C)) //machine = src - return 1 + return TRUE /mob/living/silicon/ai/triggerAlarm(var/class, area/A, var/O, var/alarmsource) - if (stat == 2) - return 1 + if(isDead()) + return TRUE var/list/L = alarms[class] for (var/I in L) - if (I == A.name) + if(I == A.name) var/list/alarm = L[I] var/list/sources = alarm[3] - if (!(alarmsource in sources)) + if(!(alarmsource in sources)) sources += alarmsource - return 1 + return TRUE var/obj/machinery/camera/C = null var/list/CL = null - if (O && istype(O, /list)) + if(O && istype(O, /list)) CL = O - if (CL.len == 1) + if(CL.len == 1) C = CL[1] - else if (O && istype(O, /obj/machinery/camera)) + else if(O && istype(O, /obj/machinery/camera)) C = O L[A.name] = list(A, (C) ? C : O, list(alarmsource)) - if (O) - if (C && C.can_use()) + if(O) + if(C && C.can_use()) queueAlarm("--- [class] alarm detected in [A.name]! ([C.c_tag])", class) - else if (CL && CL.len) - var/foo = 0 + else if(CL && CL.len) + var/foo = FALSE var/dat2 = "" for (var/obj/machinery/camera/I in CL) dat2 += text("[][]", (!foo) ? "" : " | ", src, I, I.c_tag) //I'm not fixing this shit... - foo = 1 + foo = TRUE queueAlarm(text ("--- [] alarm detected in []! ([])", class, A.name, dat2), class) else queueAlarm(text("--- [] alarm detected in []! (No Camera)", class, A.name), class) else queueAlarm(text("--- [] alarm detected in []! (No Camera)", class, A.name), class) - if (viewalerts) + if(viewalerts) ai_alerts() - return 1 + return TRUE /mob/living/silicon/ai/cancelAlarm(var/class, area/A as area, obj/origin) var/list/L = alarms[class] - var/cleared = 0 + var/cleared = FALSE for (var/I in L) - if (I == A.name) + if(I == A.name) var/list/alarm = L[I] var/list/srcs = alarm[3] - if (origin in srcs) + if(origin in srcs) srcs -= origin - if (srcs.len == 0) - cleared = 1 + if(!srcs.len) + cleared = TRUE L -= I - if (cleared) + if(cleared) queueAlarm(text("--- [] alarm in [] has been cleared.", class, A.name), class, 0) - if (viewalerts) + if(viewalerts) ai_alerts() return !cleared @@ -750,9 +716,9 @@ var/list/ai_list = list() var/obj/machinery/status_display/SD = M if(emote=="Friend Computer") - SD.friendc = 1 + SD.friendc = TRUE else - SD.friendc = 0 + SD.friendc = FALSE return //I am the icon meister. Bow fefore me. //>fefore @@ -838,10 +804,10 @@ var/list/ai_list = list() /spell/aoe_turf/corereturn/before_target(mob/user) if(istype(user.loc, /obj/machinery/power/apc)) - return 0 + return FALSE else to_chat(user, "You are already in your Main Core.") - return 1 + return TRUE /spell/aoe_turf/corereturn/choose_targets(mob/user = usr) return list(user.loc) @@ -860,11 +826,11 @@ var/list/ai_list = list() camera_light_on = !camera_light_on - if (!camera_light_on) + if(!camera_light_on) to_chat(src, "Camera lights deactivated.") for (var/obj/machinery/camera/C in lit_cameras) - C.set_light(0) + C.set_light(FALSE) lit_cameras = list() return @@ -891,7 +857,7 @@ var/list/ai_list = list() var/list/obj/machinery/camera/visible = list() for (var/datum/camerachunk/CC in eyeobj.visibleCameraChunks) for (var/obj/machinery/camera/C in CC.cameras) - if (!C.can_use() || C.light_disabled || get_dist(C, eyeobj) > 7) + if(!C.can_use() || C.light_disabled || get_dist(C, eyeobj) > 7) continue visible |= C @@ -899,7 +865,7 @@ var/list/ai_list = list() remove = lit_cameras - visible for (var/obj/machinery/camera/C in remove) - C.set_light(0) + C.set_light(FALSE) lit_cameras -= C for (var/obj/machinery/camera/C in add) C.set_light(AI_CAMERA_LUMINOSITY) @@ -914,7 +880,7 @@ var/list/ai_list = list() user.visible_message("\The [user] decides not to unbolt \the [src].") return user.visible_message("\The [user] finishes unfastening \the [src]!") - anchored = 0 + anchored = FALSE return else user.visible_message("\The [user] starts to bolt \the [src] to the plating...") @@ -922,7 +888,7 @@ var/list/ai_list = list() user.visible_message("\The [user] decides not to bolt \the [src].") return user.visible_message("\The [user] finishes fastening down \the [src]!") - anchored = 1 + anchored = TRUE return else return ..() @@ -936,7 +902,7 @@ var/list/ai_list = list() return (health - config.health_threshold_dead) / 2 /mob/living/silicon/ai/html_mob_check() - return 1 + return TRUE /mob/living/silicon/ai/isTeleViewing(var/client_eye) - return 1 + return TRUE diff --git a/code/modules/mob/living/silicon/ai/emote.dm b/code/modules/mob/living/silicon/ai/emote.dm new file mode 100644 index 00000000000..6204fd1d580 --- /dev/null +++ b/code/modules/mob/living/silicon/ai/emote.dm @@ -0,0 +1,76 @@ +/mob/living/silicon/ai/emote(var/act,var/m_type=1,var/message =null, var/auto) + if(timestopped) + return // time is frozen + var/param = null + var/regex/reg = regex("(.+?)-(.+)") + if(reg.Find(act, 1)) + param = reg.group[2] + act = reg.group[1] + + var/regex/reg2 = regex("(.*?)s") + var/regex/reg3 = regex("(.*?)_(.*)") + if(reg2.Find(act, -1) && !reg3.Find(act, -2))//Removes ending s's unless they are prefixed with a '_' + act = copytext(act,1,length(act)) + + switch(act) + if("beep") + var/M = null + if(param) + var/H = get_holder_at_turf_level(src) + for (var/mob/A in view(H)) + if (param == A.name) + M = A + break + if(!M) + param = null + + if (param) + message = "[src] beeps at [param]." + else + message = "[src] beeps." + playsound(src, 'sound/machines/twobeep.ogg', 50, 0) + m_type = VISIBLE + + if("ping") + var/M = null + if(param) + var/H = get_holder_at_turf_level(src) + for (var/mob/A in view(H)) + if (param == A.name) + M = A + break + if(!M) + param = null + + if (param) + message = "[src] pings at [param]." + else + message = "[src] pings." + playsound(src, 'sound/machines/ping.ogg', 50, 0) + m_type = VISIBLE + + if("buzz") + var/M = null + if(param) + var/H = get_holder_at_turf_level(src) + for (var/mob/A in view(H)) + if (param == A.name) + M = A + break + if(!M) + param = null + + if (param) + message = "[src] buzzes at [param]." + else + message = "[src] buzzes." + playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0) + m_type = VISIBLE + + if (message && !isUnconscious()) + if (m_type & VISIBLE) + for(var/mob/O in viewers(src, null)) + O.show_message(message, m_type) + else + for(var/mob/O in hearers(src, null)) + O.show_message(message, m_type) diff --git a/code/modules/mob/living/silicon/ai/freelook/eye.dm b/code/modules/mob/living/silicon/ai/freelook/eye.dm index 783bb916fc5..654795bd83e 100644 --- a/code/modules/mob/living/silicon/ai/freelook/eye.dm +++ b/code/modules/mob/living/silicon/ai/freelook/eye.dm @@ -65,9 +65,10 @@ /mob/living/silicon/ai/Destroy() - eyeobj.ai = null - qdel(eyeobj) // No AI, no Eye - eyeobj = null + if(eyeobj) + eyeobj.ai = null + qdel(eyeobj) // No AI, no Eye + eyeobj = null ..() /atom/proc/move_camera_by_click() diff --git a/code/modules/mob/living/silicon/ai/life.dm b/code/modules/mob/living/silicon/ai/life.dm index 1c6d6f0afe7..5fe8420edc5 100644 --- a/code/modules/mob/living/silicon/ai/life.dm +++ b/code/modules/mob/living/silicon/ai/life.dm @@ -185,3 +185,6 @@ health = maxHealth - getOxyLoss() - getToxLoss() - getBruteLoss() else health = maxHealth - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() + +/mob/living/silicon/ai/update_canmove() //If the AI dies, mobs won't go through it anymore + return FALSE diff --git a/code/modules/mob/living/silicon/ai/login.dm b/code/modules/mob/living/silicon/ai/login.dm index 23b9e3f8015..04daadc2406 100644 --- a/code/modules/mob/living/silicon/ai/login.dm +++ b/code/modules/mob/living/silicon/ai/login.dm @@ -8,7 +8,6 @@ to_chat(src, {"Use say ":b to speak to your cyborgs through binary."}) show_laws() - for(var/obj/effect/rune/rune in rune_list) //HOLY FUCK WHO THOUGHT LOOPING THROUGH THE WORLD WAS A GOOD IDEA client.images += rune.blood_image regenerate_icons() @@ -18,4 +17,4 @@ O.mode = 1 O.emotion = "Neutral" view_core() - client.CAN_MOVE_DIAGONALLY = TRUE \ No newline at end of file + client.CAN_MOVE_DIAGONALLY = TRUE diff --git a/code/modules/mob/living/silicon/mommi/cogspider.dm b/code/modules/mob/living/silicon/mommi/cogspider.dm new file mode 100644 index 00000000000..fabf8a47a7c --- /dev/null +++ b/code/modules/mob/living/silicon/mommi/cogspider.dm @@ -0,0 +1,19 @@ +/mob/living/silicon/robot/mommi/cogspider + prefix="Gravekeeper" + desc = "A clockwork being, of design familiar yet alien." + damage_control_network = "Gravewatch" + icon_state = "cogspider" + namepick_uses = 0 + startup_sound = 'sound/misc/timesuit_activate.ogg'//The clockwork winding up + cell_type = /obj/item/weapon/cell/potato/soviet + +/mob/living/silicon/robot/mommi/cogspider/updatename() // Fuck individualism + name = "[prefix] [num2text(ident)]" + +/mob/living/silicon/robot/mommi/cogspider/identification_string() + return name + + +/mob/living/silicon/robot/mommi/cogspider/New() + pick_module("Gravekeeper") + ..() \ No newline at end of file diff --git a/code/modules/mob/living/silicon/mommi/emote.dm b/code/modules/mob/living/silicon/mommi/emote.dm index 69ae8a1257f..7b7841d14e8 100644 --- a/code/modules/mob/living/silicon/mommi/emote.dm +++ b/code/modules/mob/living/silicon/mommi/emote.dm @@ -63,16 +63,16 @@ m_type = VISIBLE if ("clap") - if (!src.restrained()) + if (!incapacitated()) message = "[src] clangs \his utility claws together in a crude simulation of applause." m_type = HEARABLE if ("flap") - if (!src.restrained()) + if (!incapacitated()) message = "[src] flaps \his utility arms as through they were wings." m_type = HEARABLE if ("aflap") - if (!src.restrained()) + if (!incapacitated()) message = "[src] flaps his utility arms ANGRILY!" m_type = HEARABLE @@ -181,7 +181,7 @@ message = "[src] beeps at [param]." else message = "[src] beeps." - playsound(get_turf(src), 'sound/machines/twobeep.ogg', 50, 0) + playsound(src, 'sound/machines/twobeep.ogg', 50, 0) m_type = VISIBLE if("ping") @@ -198,7 +198,7 @@ message = "[src] pings at [param]." else message = "[src] pings." - playsound(get_turf(src), 'sound/machines/ping.ogg', 50, 0) + playsound(src, 'sound/machines/ping.ogg', 50, 0) m_type = VISIBLE if("buzz") @@ -215,7 +215,7 @@ message = "[src] buzzes at [param]." else message = "[src] buzzes." - playsound(get_turf(src), 'sound/machines/buzz-sigh.ogg', 50, 0) + playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0) m_type = VISIBLE if("comment") diff --git a/code/modules/mob/living/silicon/mommi/examine.dm b/code/modules/mob/living/silicon/mommi/examine.dm index db3c3a8c7d3..225299f7584 100644 --- a/code/modules/mob/living/silicon/mommi/examine.dm +++ b/code/modules/mob/living/silicon/mommi/examine.dm @@ -2,7 +2,7 @@ var/msg = "*---------*\nThis is [bicon(src)] \a [src]!\n" - msg += {"

    It's like a crab, but it has a utility tool on one arm and a crude metal claw on the other. That, and you doubt it'd survive in an ocean for very long.

    "} + msg += {"

    [desc]

    "} msg += "" if (getBruteLoss()) diff --git a/code/modules/mob/living/silicon/mommi/inventory.dm b/code/modules/mob/living/silicon/mommi/inventory.dm index d6ee3023478..40bb0771c24 100644 --- a/code/modules/mob/living/silicon/mommi/inventory.dm +++ b/code/modules/mob/living/silicon/mommi/inventory.dm @@ -32,16 +32,10 @@ if(cell && cell.charge <= MOMMI_LOW_POWER) drop_item(W) return 0 - // Make sure we're not picking up something that's in our factory-supplied toolbox. - //if(is_type_in_list(W,src.module.modules)) - //if(is_in_modules(W)) -// to_chat(src, "Picking up something that's built-in to you seems a bit silly.") - //return 0 if(W.type == /obj/item/device/material_synth) drop_item(W) return 0 if(tool_state) - //var/obj/item/found = locate(tool_state) in src.module.modules var/obj/item/TS = tool_state if(!is_in_modules(tool_state)) drop_item(TS) @@ -53,6 +47,7 @@ tool_state = W W.hud_layerise() W.forceMove(src) + W.equipped(src) // Make crap we pick up active so there's less clicking and carpal. - N3X module_active=tool_state @@ -101,20 +96,14 @@ if(!istype(to_drop)) to_drop = tool_state if(to_drop) - //var/obj/item/found = locate(tool_state) in src.module.modules if(is_in_modules(to_drop)) if((to_drop in contents) && (to_drop in src.module.modules)) to_chat(src, "This item cannot be dropped.") return 0 - if(client) - client.screen -= to_drop - to_drop.forceMove(Target) - - //this all should be using remove_from_mob() but I couldn't get it to work for some reason so for now it continues to be copypasted ass + remove_from_mob(to_drop) //clean out any refs to_drop.dropped(src) - - u_equip(to_drop) + to_drop.forceMove(Target) update_items() return 1 return 0 @@ -338,3 +327,7 @@ update_items() else to_chat(M, "You are unable to equip that.") + +/mob/living/carbon/can_use_hands() + return TRUE + diff --git a/code/modules/mob/living/silicon/mommi/laws.dm b/code/modules/mob/living/silicon/mommi/laws.dm index 8097f9a4f39..d204cbcaaff 100644 --- a/code/modules/mob/living/silicon/mommi/laws.dm +++ b/code/modules/mob/living/silicon/mommi/laws.dm @@ -3,7 +3,7 @@ // Except for this, of course. /mob/living/silicon/robot/mommi/laws_sanity_check() if (!laws) - laws = new mommi_base_law_type + laws = new mommi_laws["Default"] // And this. /mob/living/silicon/robot/mommi/statelaws() // -- TLE diff --git a/code/modules/mob/living/silicon/mommi/life.dm b/code/modules/mob/living/silicon/mommi/life.dm index 0ae52ff8ddb..278b2eef86b 100644 --- a/code/modules/mob/living/silicon/mommi/life.dm +++ b/code/modules/mob/living/silicon/mommi/life.dm @@ -16,7 +16,7 @@ if(client) handle_regular_hud_updates() - update_action_buttons() + update_action_buttons_icon() update_items() if (src.stat != DEAD) //still using power use_power() diff --git a/code/modules/mob/living/silicon/mommi/login.dm b/code/modules/mob/living/silicon/mommi/login.dm index f60c1873e82..dfa983479bf 100644 --- a/code/modules/mob/living/silicon/mommi/login.dm +++ b/code/modules/mob/living/silicon/mommi/login.dm @@ -1,19 +1,18 @@ /mob/living/silicon/robot/mommi/Login() - ..() - /* Inherited - regenerate_icons() - show_laws(0) - if(mind) - ticker.mode.remove_revolutionary(mind) - return - */ if(can_see_static()) add_static_overlays() + to_chat(src, "MoMMIs are not standard cyborgs, and have different laws. Review your laws carefully.") + to_chat(src, "For newer players, a simple FAQ is here. Further questions should be directed to adminhelps (F1).") + to_chat(src, "For cuteness' sake, using the various emotes MoMMIs have such as *beep, *ping, *buzz or *aflap isn't considered interacting. Don't use that as an excuse to get involved though, always remain neutral.") /mob/living/silicon/robot/mommi/proc/can_see_static() return (keeper && !emagged && !syndicate && (config && config.mommi_static)) +/mob/living/silicon/robot/mommi/generate_static_overlay() + if(!islist(static_overlays)) + static_overlays = list() + /mob/living/silicon/robot/mommi/proc/add_static_overlays() remove_static_overlays() for(var/mob/living/living in mob_list) @@ -25,13 +24,20 @@ else chosen = living.static_overlays[1] static_overlays.Add(chosen) - client.images.Add(chosen) + if(client) + client.images.Add(chosen) /mob/living/silicon/robot/mommi/proc/remove_static_overlays() if(client) for(var/image/I in static_overlays) client.images.Remove(I) - static_overlays.len = 0 + static_overlays.Cut() + +/mob/living/silicon/robot/mommi/examination(atom/A as mob|obj|turf in view()) //It used to be oview(12), but I can't really say why + if(ismob(A) && !issilicon(A) && can_see_static()) //can't examine what you can't catch! + to_chat(usr, "Your vision module can't determine any of [A]'s features.") + return + ..() /mob/living/silicon/robot/mommi/verb/toggle_statics() set name = "Change Vision Filter" diff --git a/code/modules/mob/living/silicon/mommi/mommi.dm b/code/modules/mob/living/silicon/mommi/mommi.dm index c0a8c3a0674..1bf439c0522 100644 --- a/code/modules/mob/living/silicon/mommi/mommi.dm +++ b/code/modules/mob/living/silicon/mommi/mommi.dm @@ -6,176 +6,78 @@ They can only use one tool at a time, they can't choose modules, and they have 1 */ /mob/living/silicon/robot/mommi name = "Mobile MMI" + desc = "It's like a crab, but it has a utility tool on one arm and a crude metal claw on the other. That, and you doubt it'd survive in an ocean for very long." real_name = "Mobile MMI" - icon = 'icons/mob/robots.dmi' + icon = 'icons/mob/mommi.dmi' icon_state = "mommi" maxHealth = 60 health = 60 + pass_flags = PASSTABLE - var/keeper=0 // 0 = No, 1 = Yes (Disables speech and common radio.) - var/picked = 0 - var/subtype="keeper" - var/obj/abstract/screen/inv_tool = null - var/prefix = "Mobile MMI" - var/damage_control_network = "Damage Control" - - static_overlays - var/static_choice = "static" - var/list/static_choices = list("static", "letter", "blank") - mob_bump_flag = ROBOT mob_swap_flags = ALLMOBS mob_push_flags = 0 + modtype = "Nanotrasen" + braintype = "Mobile MMI" + + //New() stuff + startup_sound = 'sound/misc/interference.ogg' + + //This is no cyborg boy, no cyborg! + cell_type = /obj/item/weapon/cell/crepe/mommi //The secret behind MoMMIs, literal powercreep. + wiring_type = /datum/wires/robot/mommi + + AIlink = FALSE //Fuck AIs, you're a crab. + scrambledcodes = TRUE //Don't appear on the SS13/ROBOTS cameranet, you're not supposed to be a ventcrawling security camera. + + //MoMMI stuff + var/picked_icon = FALSE + + var/keeper= TRUE // FALSE = No, TRUE = Yes (Disables speech and common radio.) + var/prefix = "Mobile MMI" + var/damage_control_network = "Damage Control" + + var/static_choice = "static" + var/list/static_choices = list("static", "letter", "blank") + + var/obj/abstract/screen/inv_tool = null var/obj/item/tool_state = null var/obj/item/head_state = null - modtype = "robot" // Not sure what this is, but might be cool to have seperate loadouts for MoMMIs (e.g. paintjobs and tools) - //Cyborgs will sync their laws with their AI by default, but we may want MoMMIs to be mute independents at some point, kinda like the Keepers in Ass Effect. - lawupdate = 1 - speed = 0 - -/mob/living/carbon/can_use_hands() - return 1 - -/mob/living/silicon/robot/mommi/generate_static_overlay() - if(!istype(static_overlays,/list)) - static_overlays = list() - return - -/mob/living/silicon/robot/mommi/examination(atom/A as mob|obj|turf in view()) //It used to be oview(12), but I can't really say why - if(ismob(A) && src.can_see_static()) //can't examine what you can't catch! - to_chat(usr, "Your vision module can't determine any of [A]'s features.") +/mob/living/silicon/robot/mommi/pick_module(var/forced_module = null) + if(module) return - ..() - - -/mob/living/silicon/robot/mommi/New(loc) - ident = rand(1, 999) - updatename() - updateicon() - - if(!cell) - cell = new /obj/item/weapon/cell(src) - cell.maxcharge = 7500 - cell.charge = 7500 - ..(loc,startup_sound='sound/misc/interference.ogg') - module = new /obj/item/weapon/robot_module/mommi(src) - laws = new mommi_base_law_type - - // Don't sync if we're a KEEPER. - if(!istype(laws,/datum/ai_laws/keeper)) - connected_ai = select_active_ai_with_fewest_borgs() + if(forced_module) + modtype = forced_module else - // Enforce silence. - keeper=1 - connected_ai = null // Enforce no AI parent - scrambledcodes = 1 // Hide from console because people are fucking idiots - - if(connected_ai) - connected_ai.connected_robots += src - lawsync() - lawupdate = 1 - else - lawupdate = 0 - - if(!scrambledcodes && !camera) - camera = new /obj/machinery/camera(src) - camera.c_tag = real_name - camera.network = list(CAMERANET_SS13,CAMERANET_ROBOTS) - if(wires.IsCameraCut()) // 5 = BORG CAMERA - camera.status = 0 - - // Sanity check - if(connected_ai && keeper) - to_chat(world, "ASSERT FAILURE: connected_ai && keeper in mommi.dm") - - -/mob/living/silicon/robot/mommi/choose_icon() - var/icontype = input("Select an icon!", "Mobile MMI", null) as null|anything in list("Basic", "Hover", "Keeper", "RepairBot", "Replicator", "Prime", "Prime Alt", "Scout") - if(!icontype) - return - switch(icontype) - if("Replicator") - subtype = "replicator" - if("Keeper") - subtype = "keeper" - if("RepairBot") - subtype = "repairbot" - if("Hover") - subtype = "hovermommi" - if("Prime") - subtype = "mommiprime" - if("Prime Alt") - subtype = "mommiprime-alt" - if("Scout") - subtype = "scout" + if(mommi_modules.len) + modtype = input("Please, select a module!", "Nanotrasen", null, null) as null|anything in mommi_modules else - subtype = "mommi" - updateicon() - var/answer = input("Is this what you want?", "Mobile MMI", null) in list("Yes", "No") - switch(answer) - if("No") - choose_icon() - return - picked = 1 - -/mob/living/silicon/robot/mommi/pick_module() + modtype=modules[0] if(module) return - var/list/modules = list("MoMMI") - if(modules.len) - modtype = input("Please, select a module!", "Robot", null, null) as null|anything in modules - else - modtype=modules[0] - - if(!modtype) + if(!(modtype in mommi_modules)) return - var/module_sprites[0] //Used to store the associations between sprite names and sprite index. + var/module_type = mommi_modules[modtype] + module = new module_type(src) - if(module) - return - - switch(modtype) - if("MoMMI") - module = new /obj/item/weapon/robot_module/standard(src) - module_sprites["Basic"] = "mommi" - module_sprites["Keeper"] = "keeper" - module_sprites["Replicator"] = "replicator" - module_sprites["RepairBot"] = "repairbot" - module_sprites["Hover"] = "hovermommi" - module_sprites["Prime"] = "mommiprime" - module_sprites["Prime Alt"] = "mommiprime-alt" - - //Custom_sprite check and entry - if (custom_sprite == 1) - module_sprites["Custom"] = "[src.ckey]-[modtype]" - - hands.icon_state = lowertext(modtype) - feedback_inc("mommi_[lowertext(modtype)]",1) + feedback_inc("cyborg_[lowertext(modtype)]",1) updatename() - choose_icon(6,module_sprites) - base_icon = icon_state + set_module_sprites(module.sprites) -//If there's an MMI in the robot, have it ejected when the mob goes away. --NEO -//Improved /N + choose_icon() + + SetEmagged(emagged) // Update emag status and give/take emag modules away + +//REMOVE STATIC /mob/living/silicon/robot/mommi/Destroy() remove_static_overlays() - if(mmi)//Safety for when a cyborg gets dust()ed. Or there is no MMI inside. - var/obj/item/device/mmi/nmmi = mmi - var/turf/T = get_turf(loc)//To hopefully prevent run time errors. - if(T) - nmmi.forceMove(T) - if(mind) - mind.transfer_to(nmmi.brainmob) - mmi = null - nmmi.icon = 'icons/obj/assemblies.dmi' - nmmi.invisibility = 0 ..() /mob/living/silicon/robot/mommi/remove_screen_objs() @@ -186,8 +88,7 @@ They can only use one tool at a time, they can't choose modules, and they have 1 client.screen -= inv_tool inv_tool = null -/mob/living/silicon/robot/mommi/updatename(var/oldprefix as text) - +/mob/living/silicon/robot/mommi/updatename() var/changed_name = "" if(custom_name) changed_name = custom_name @@ -196,19 +97,23 @@ They can only use one tool at a time, they can't choose modules, and they have 1 real_name = changed_name name = real_name -/mob/living/silicon/robot/mommi/emag_act(mob/user as mob) - if(user == src && emagged != 1)//Dont shitpost inside the game, thats just going too far - to_chat(user, "Nanotrasen Patented Anti-Emancipation Override initiated.") - return 1 +/mob/living/silicon/robot/mommi/emag_act(mob/user) + if(user == src && !emagged)//Dont shitpost inside the game, thats just going too far + if(module) + var/obj/item/weapon/robot_module/mommi/mymodule = module + to_chat(user, "[mymodule.ae_type] anti-emancipation override initiated.") + playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0) + return TRUE if(..()) - return 1 + return TRUE remove_static_overlays() updateicon() - // Check to see if we're emagged. If so, we disable KEEPER. - keeper = 0 + //If KEEPER is enabled, disable it. + if(keeper) + keeper = FALSE -/mob/living/silicon/robot/mommi/attackby(obj/item/weapon/W as obj, mob/living/user as mob) +/mob/living/silicon/robot/mommi/attackby(obj/item/weapon/W, mob/living/user) if(istype(W, /obj/item/stack/cable_coil) && wiresexposed) var/obj/item/stack/cable_coil/coil = W adjustFireLoss(-30) @@ -217,8 +122,8 @@ They can only use one tool at a time, they can't choose modules, and they have 1 for(var/mob/O in viewers(user, null)) O.show_message(text("[user] has fixed some of the burnt wires on [src]!"), 1) - else if (iscrowbar(W)) // crowbar means open or close the cover - if(stat == DEAD) + else if(iscrowbar(W)) // crowbar means open or close the cover + if(isDead()) to_chat(user, "You pop the MMI off the base.") spawn(0) qdel(src) @@ -227,32 +132,29 @@ They can only use one tool at a time, they can't choose modules, and they have 1 if(mmi && wiresexposed && wires.IsAllCut()) //Cell is out, wires are exposed, remove MMI, produce damaged chassis, baleet original mob. to_chat(user, "You jam the crowbar into \the [src] and begin levering [mmi].") - if (do_after(user, src,3)) + if(do_after(user, src,3)) to_chat(user, "You damage some parts of the casing, but eventually manage to rip out [mmi]!") var/limbs = list(/obj/item/robot_parts/l_leg, /obj/item/robot_parts/r_leg, /obj/item/robot_parts/l_arm, /obj/item/robot_parts/r_arm) for(var/newlimb = 1 to rand(2, 4)) var/limb_to_spawn = pick(limbs) limbs -= limb_to_spawn - new limb_to_spawn(src.loc) - // This doesn't work. Don't use it. - //src.Destroy() - // del() because it's infrequent and mobs act weird in qdel. + new limb_to_spawn(loc) qdel(src) return else to_chat(user, "You close the cover.") - opened = 0 + opened = FALSE updateicon() else if(locked) to_chat(user, "The cover is locked and cannot be opened.") else to_chat(user, "You open the cover.") - opened = 1 + opened = TRUE updateicon() - else if (istype(W, /obj/item/weapon/cell) && opened) // trying to put a cell inside + else if(istype(W, /obj/item/weapon/cell) && opened) // trying to put a cell inside if(wiresexposed) to_chat(user, "Close the panel first.") else if(cell) @@ -261,11 +163,10 @@ They can only use one tool at a time, they can't choose modules, and they have 1 user.drop_item(W, src) cell = W to_chat(user, "You insert the power cell.") -// chargecount = 0 updateicon() - else if (iswiretool(W)) - if (wiresexposed) + else if(iswiretool(W)) + if(wiresexposed) wires.Interact(user) else to_chat(user, "You can't reach the wiring.") @@ -287,20 +188,6 @@ They can only use one tool at a time, they can't choose modules, and they have 1 radio.attackby(W,user)//GTFO, you have your own procs else to_chat(user, "Unable to locate a radio.") -/* - else if (istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) // trying to unlock the interface with an ID card - if(emagged)//still allow them to open the cover - to_chat(user, "The interface seems slightly damaged") - if(opened) - to_chat(user, "You must close the cover to swipe an ID card.") - else - if(allowed(usr)) - locked = !locked - to_chat(user, "You [ locked ? "lock" : "unlock"] [src]'s interface.") - updateicon() - else - to_chat(user, "Access denied.") -*/ else if(istype(W, /obj/item/borg/upgrade/)) var/obj/item/borg/upgrade/U = W @@ -308,7 +195,7 @@ They can only use one tool at a time, they can't choose modules, and they have 1 else if(istype(W, /obj/item/device/camera_bug)) help_shake_act(user) - return 0 + return FALSE else user.do_attack_animation(src, W) @@ -318,7 +205,7 @@ They can only use one tool at a time, they can't choose modules, and they have 1 /mob/living/silicon/robot/mommi/attack_hand(mob/user) add_fingerprint(user) - if(opened && !wiresexposed && (!istype(user, /mob/living/silicon))) + if(opened && !wiresexposed && (!isMoMMI(user))) if(cell) cell.updateicon() cell.add_fingerprint(user) @@ -331,17 +218,16 @@ They can only use one tool at a time, they can't choose modules, and they have 1 if(!istype(user, /mob/living/silicon)) switch(user.a_intent) if(I_DISARM) - user.attack_log += text("\[[time_stamp()]\] Disarmed [src.name] ([src.ckey])") - src.attack_log += text("\[[time_stamp()]\] Has been disarmed by [user.name] ([user.ckey])") - log_admin("ATTACK: [user.name] ([user.ckey]) disarmed [src.name] ([src.ckey])") - log_attack("[user.name] ([user.ckey]) disarmed [src.name] ([src.ckey])") + user.attack_log += text("\[[time_stamp()]\] Disarmed [name] ([ckey])") + attack_log += text("\[[time_stamp()]\] Has been disarmed by [user.name] ([user.ckey])") + log_admin("ATTACK: [user.name] ([user.ckey]) disarmed [name] ([ckey])") + log_attack("[user.name] ([user.ckey]) disarmed [name] ([ckey])") var/randn = rand(1,100) - //var/talked = 0; - if (randn <= 25) + if(randn <= 25) knockdown = 3 playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) visible_message("[user] has pushed [src]!") - var/obj/item/found = locate(tool_state) in src.module.modules + var/obj/item/found = locate(tool_state) in module.modules if(!found) var/obj/item/TS = tool_state drop_item(TS) @@ -349,7 +235,7 @@ They can only use one tool at a time, they can't choose modules, and they have 1 visible_message("[src]'s robotic arm loses grip on what it was holding") return if(randn <= 50)//MoMMI's robot arm is stronger than a human's, but not by much - var/obj/item/found = locate(tool_state) in src.module.modules + var/obj/item/found = locate(tool_state) in module.modules if(!found) var/obj/item/TS = tool_state drop_item(TS) @@ -359,19 +245,24 @@ They can only use one tool at a time, they can't choose modules, and they have 1 playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) visible_message("[user] attempted to disarm [src]!") return - if (I_HELP) + if(I_HELP) help_shake_act(user) return +/mob/living/silicon/robot/mommi/choose_icon() + if(..()) + picked_icon = TRUE + /mob/living/silicon/robot/mommi/installed_modules() if(weapon_lock) to_chat(src, "Weapon lock active, unable to use modules! Count:[weaponlock_time]") return - if(!module) pick_module() return - if(!picked) + if(!picked_icon) + if(!module_sprites) + set_module_sprites(module.sprites) choose_icon() return var/dat = "Modules\n" @@ -386,13 +277,13 @@ They can only use one tool at a time, they can't choose modules, and they have 1 for (var/obj in module.modules) - if (!obj) + if(!obj) dat += text("Resource depleted
    ") else if(activated(obj)) dat += text("[obj]: Activated
    ") else dat += text("[obj]: Activate
    ") - if (emagged) + if(emagged) if(activated(module.emag)) dat += text("[module.emag]: Activated
    ") else @@ -406,30 +297,30 @@ They can only use one tool at a time, they can't choose modules, and they have 1 if(usr && (src != usr)) return - if (href_list["mach_close"]) + if(href_list["mach_close"]) var/t1 = text("window=[href_list["mach_close"]]") unset_machine() src << browse(null, t1) return - if (href_list["showalerts"]) + if(href_list["showalerts"]) robot_alerts() return - if (href_list["mod"]) + if(href_list["mod"]) var/obj/item/O = locate(href_list["mod"]) - if (O && O == tool_state) + if(O && O == tool_state) O.attack_self(src) - if (href_list["act"]) + if(href_list["act"]) var/obj/item/O = locate(href_list["act"]) var/obj/item/TS - if(!(locate(O) in src.module.modules) && O != src.module.emag) + if(!(locate(O) in module.modules) && O != module.emag) return TS = tool_state if(tool_state) contents -= tool_state - if (client) + if(client) client.screen -= tool_state tool_state = O O.hud_layerise() @@ -437,11 +328,11 @@ They can only use one tool at a time, they can't choose modules, and they have 1 inv_tool.icon_state = "inv1 +a" module_active=tool_state if(TS && istype(TS)) - if(src.is_in_modules(TS)) - TS.forceMove(src.module) + if(is_in_modules(TS)) + TS.forceMove(module) else TS.layer=initial(TS.layer) - TS.forceMove(src.loc) + TS.forceMove(loc) installed_modules() return @@ -449,27 +340,7 @@ They can only use one tool at a time, they can't choose modules, and they have 1 /mob/living/silicon/robot/mommi/radio_menu() radio.interact(src)//Just use the radio's Topic() instead of bullshit special-snowflake code -/mob/living/silicon/robot/mommi/CheckSlip() - return -1 - -/* -/mob/living/silicon/robot/mommi/proc/ActivateKeeper() - set category = "Robot Commands" - set name = "Activate KEEPER" - set desc = "Performs a full purge of your laws and disconnects you from AIs and cyborg consoles. However, you lose the ability to speak and must remain neutral, only being permitted to perform station upkeep. You can still be emagged in this state." - - if(keeper) - return - - var/mob/living/silicon/robot/R = src - - if(R) - R.UnlinkSelf() - var/obj/item/weapon/aiModule/keeper/mdl = new - - mdl.upload(src.laws,src,src) - to_chat(src, "These are your laws now:") - src.show_laws() - - src.verbs -= /mob/living/silicon/robot/mommi/proc/ActivateKeeper -*/ +//Nanotrasen MoMMI subtype because we don't give mommis a choice of choosing their module. +/mob/living/silicon/robot/mommi/nt/New() + pick_module("Nanotrasen") + ..() diff --git a/code/modules/mob/living/silicon/mommi/mommi_modules.dm b/code/modules/mob/living/silicon/mommi/mommi_modules.dm index ee9f4ad626f..e7b58f65927 100644 --- a/code/modules/mob/living/silicon/mommi/mommi_modules.dm +++ b/code/modules/mob/living/silicon/mommi/mommi_modules.dm @@ -1,56 +1,89 @@ + /obj/item/weapon/robot_module/mommi name = "mobile mmi robot module" - + quirk_flags = MODULE_CAN_BE_PUSHED | MODULE_HAS_MAGPULSE | MODULE_CAN_HANDLE_CHEMS | MODULE_CAN_BUY + languages = list() + sprites = list("Basic" = "mommi") + respawnables = list (/obj/item/stack/cable_coil) + respawnables_max_amount = MOMMI_MAX_COIL + default_modules = FALSE + var/ae_type = "Default" //Anti-emancipation override type, pretty much just fluffy. + var/law_type = "Default" /obj/item/weapon/robot_module/mommi/New(var/mob/living/silicon/robot/R) ..() - languages = list( LANGUAGE_GALACTIC_COMMON = 0, LANGUAGE_TRADEBAND = 0, LANGUAGE_VOX = 0, - LANGUAGE_ROOTSPEAK = 0, LANGUAGE_GREY = 0, LANGUAGE_CLATTER = 0, - LANGUAGE_MONKEY = 0, LANGUAGE_UNATHI = 0, LANGUAGE_CATBEAST = 0, - LANGUAGE_SKRELLIAN = 0, LANGUAGE_GUTTER = 0, LANGUAGE_MONKEY = 0, - LANGUAGE_MOUSE = 0, LANGUAGE_HUMAN = 0, LANGUAGE_GOLEM = 0, LANGUAGE_SLIME = 0) - add_languages(R) - src.emag = new /obj/item/borg/stun(src) - //src.modules += new /obj/item/weapon/rcd/borg(src) // Too OP - //src.modules += new /obj/item/device/flashlight(src) // Broken - src.modules += new /obj/item/weapon/weldingtool/largetank(src) - src.modules += new /obj/item/weapon/screwdriver(src) - src.modules += new /obj/item/weapon/wrench(src) - src.modules += new /obj/item/weapon/crowbar(src) - src.modules += new /obj/item/weapon/wirecutters(src) - src.modules += new /obj/item/device/multitool(src) - src.modules += new /obj/item/device/t_scanner(src) - src.modules += new /obj/item/device/analyzer(src) - src.modules += new /obj/item/weapon/extinguisher(src) // Aurx sed so - src.modules += new /obj/item/weapon/extinguisher/foam(src) - src.modules += new /obj/item/device/rcd/rpd(src) - src.modules += new /obj/item/device/rcd/tile_painter(src) - src.modules += new /obj/item/blueprints/mommiprints(src) - src.modules += new /obj/item/device/material_synth/robot/mommi(src) - src.modules += new /obj/item/device/holomap(src) - src.modules += new /obj/item/device/station_map(src) - src.modules += new /obj/item/device/silicate_sprayer(src) - sensor_augs = list("Mesons", "Disable") + modules += new /obj/item/weapon/weldingtool/largetank(src) + modules += new /obj/item/weapon/screwdriver(src) + modules += new /obj/item/weapon/wrench(src) + modules += new /obj/item/weapon/crowbar(src) + modules += new /obj/item/weapon/wirecutters(src) + modules += new /obj/item/device/multitool(src) + modules += new /obj/item/device/t_scanner(src) + modules += new /obj/item/device/analyzer(src) + modules += new /obj/item/weapon/extinguisher(src) + modules += new /obj/item/weapon/extinguisher/foam(src) + modules += new /obj/item/device/rcd/rpd(src) + modules += new /obj/item/device/rcd/tile_painter(src) + modules += new /obj/item/blueprints/mommiprints(src) + modules += new /obj/item/device/material_synth/robot/mommi(src) + modules += new /obj/item/device/holomap(src) + modules += new /obj/item/device/station_map(src) + modules += new /obj/item/device/silicate_sprayer(src) + modules += new /obj/item/borg/fire_shield + var/obj/item/stack/cable_coil/W = new /obj/item/stack/cable_coil(src) - W.amount = 50 - W.max_amount = 50 // Override MAXCOIL - src.modules += W + W.amount = MOMMI_MAX_COIL + W.max_amount = MOMMI_MAX_COIL + modules += W + emag = new /obj/item/borg/stun(src) + + sensor_augs = list("Mesons", "Disable") + fix_modules() -/obj/item/weapon/robot_module/mommi/respawn_consumable(var/mob/living/silicon/robot/R) - var/list/what = list ( - // /obj/item/stack/sheet/metal/cyborg, - // /obj/item/stack/sheet/glass/glass, - /obj/item/stack/cable_coil, - // /obj/item/stack/sheet/glass/rglass/cyborg, - ) - for (var/T in what) - if (!(locate(T) in src.modules)) - src.modules -= null - var/O = new T(src) - if(istype(O,/obj/item/stack/cable_coil)) - O:max_amount = 50 - src.modules += O - O:amount = 1 - return +//Nanotrasen's MoMMI +/obj/item/weapon/robot_module/mommi/nt + name = "nanotrasen mobile mmi robot module" + networks = list(CAMERANET_ENGI) + radio_key = /obj/item/device/encryptionkey/headset_eng + ae_type = "Nanotrasen patented" + sprites = list( + "Basic" = "mommi", + "Keeper" = "keeper", + "Prime" = "mommiprime", + "Prime Alt" = "mommiprime-alt", + "Replicator" = "replicator", + "RepairBot" = "repairbot", + "Hover" = "hovermommi" + ) + speed_modifier = MOMMI_NT_SPEED_MODIFIER + +//Derelict MoMMI +/obj/item/weapon/robot_module/mommi/soviet + name = "russian remont robot module" + ae_type = "Начато отмену" + speed_modifier = MOMMI_SOVIET_SPEED_MODIFIER + sprites = list( + "RuskieBot" = "ruskiebot" + ) + +/obj/item/weapon/robot_module/mommi/soviet/New(var/mob/living/silicon/robot/R) //Powercreep! + ..() + + quirk_flags |= MODULE_CAN_HANDLE_FOOD //Let them be able to handle bartending machinery. + + modules += new /obj/item/device/rcd/borg/engineering(src) + modules += new /obj/item/device/instrument/instrument_synth(src) + modules += new /obj/item/device/rcd/borg/rsf/soviet(src) + modules += new /obj/item/weapon/soap/syndie(src) + modules += new /obj/item/weapon/pickaxe/plasmacutter(src) + modules += new /obj/item/weapon/storage/bag/ore/auto(src) + +/obj/item/weapon/robot_module/mommi/cogspider + name = "Gravekeeper belt of holding." + speed_modifier = COGSPIDER_SPEED_MODIFIER + sprites = list( + "Gravekeeper" = "cogspider" + ) + law_type = "Gravekeeper" \ No newline at end of file diff --git a/code/modules/mob/living/silicon/mommi/mommi_movement.dm b/code/modules/mob/living/silicon/mommi/mommi_movement.dm deleted file mode 100644 index da6e62c3b78..00000000000 --- a/code/modules/mob/living/silicon/mommi/mommi_movement.dm +++ /dev/null @@ -1,3 +0,0 @@ -// MoMMIs do spess construction, so shouldn't slip. -/mob/living/silicon/robot/mommi/Process_Spaceslipping(var/prob_slip=5) - return 0 diff --git a/code/modules/mob/living/silicon/mommi/powers.dm b/code/modules/mob/living/silicon/mommi/mommi_verbs.dm similarity index 86% rename from code/modules/mob/living/silicon/mommi/powers.dm rename to code/modules/mob/living/silicon/mommi/mommi_verbs.dm index a9e2deb6282..2edab877417 100644 --- a/code/modules/mob/living/silicon/mommi/powers.dm +++ b/code/modules/mob/living/silicon/mommi/mommi_verbs.dm @@ -12,10 +12,7 @@ set desc = "Allows to hide beneath tables or certain items. Toggled on or off." set category = "Robot Commands" - if(stat != CONSCIOUS) - return - var/mob/living/silicon/robot/mommi/R = src - if(!R.canmove) + if(incapacitated()) return if (plane != HIDING_MOB_PLANE) @@ -36,7 +33,10 @@ set name = "Toggle Parking Brake" set desc = "Lock yourself in place" set category = "Robot Commands" - var/mob/living/silicon/robot/mommi/R = src - R.anchored=!R.anchored - R.update_canmove() + + if(incapacitated()) + return + + anchored = !anchored //This is fucking stupid + update_canmove() updateicon() diff --git a/code/modules/mob/living/silicon/mommi/soviet_mommi.dm b/code/modules/mob/living/silicon/mommi/soviet_mommi.dm index 9017dece7d6..44aba67e491 100644 --- a/code/modules/mob/living/silicon/mommi/soviet_mommi.dm +++ b/code/modules/mob/living/silicon/mommi/soviet_mommi.dm @@ -1,16 +1,27 @@ /* THIS FILE IS IN UTF-8. EDIT WITH NOTEPAD++ OR ATOM OR YOU WILL FUCK THE ENCODING. */ /mob/living/silicon/robot/mommi/soviet prefix="Remont Robot" // Ремонт робот - Repair Robot - damage_control_network="Usherp" // ущерб - Contextual translation of "Damage Control" desc = "This thing looks so Russian that you get the urge to wrestle bears and chug vodka." + damage_control_network = "Usherp" // ущерб - Contextual translation of "Damage Control" + namepick_uses = 0 -// Fuck individualism -/mob/living/silicon/robot/mommi/soviet/updatename(var/oldprefix as text) - var/changed_name = "" - changed_name = "[prefix] [num2text(ident)]" - real_name = changed_name - name = real_name + startup_sound = 'sound/misc/soviet.ogg' + cell_type = /obj/item/weapon/cell/potato/soviet -// Ditto -/mob/living/silicon/robot/mommi/soviet/Namepick() - return 0 +/mob/living/silicon/robot/mommi/soviet/updatename() // Fuck individualism + name = "[prefix] [num2text(ident)]" + +/mob/living/silicon/robot/identification_string() + return name + +/mob/living/silicon/robot/mommi/soviet/can_see_static() //Fuck the config i told you we were hardcore. + if(emagged || syndicate) + return FALSE + return TRUE + +/mob/living/silicon/robot/mommi/soviet/New() + pick_module("Soviet") + ..() + var/obj/item/clothing/head/ushanka/soviet_hat = new /obj/item/clothing/head/ushanka(src) + equip_to_slot(soviet_hat, slot_head, TRUE) + generate_static_overlay() \ No newline at end of file diff --git a/code/modules/mob/living/silicon/mommi/update_icons.dm b/code/modules/mob/living/silicon/mommi/update_icons.dm index 75cf5df2368..4fb3feb8df6 100644 --- a/code/modules/mob/living/silicon/mommi/update_icons.dm +++ b/code/modules/mob/living/silicon/mommi/update_icons.dm @@ -15,43 +15,43 @@ // Update the MoMMI's visual icon // This is called whenever a major change to the MoMMI's visual appearance is made -// i.e when they change their subtype, open their cover, get emagged, toggle their parking break, or put on a hat -/mob/living/silicon/robot/mommi/updateicon() - // Clear all overlays. - overlays.len = 0 +// i.e when they change their icon_state, open their cover, get emagged, toggle their parking break, or put on a hat +/mob/living/silicon/robot/mommi/updateicon(overlay_layer = ABOVE_LIGHTING_LAYER, overlay_plane = LIGHTING_PLANE) + overlays.Cut() - // Set the MoMMI's icon to its subtype - icon_state=subtype - - // Add a panel image if the MoMMI is open - if(opened) // TODO: Open the front "head" panel - if(wiresexposed) - overlays += image(icon = icon, icon_state = "ov-openpanel +w") - else if(cell) - overlays += image(icon = icon, icon_state = "ov-openpanel +c") + if(base_icon) + if(emagged && has_icon(icon, "[base_icon]-emagged")) + icon_state = "[base_icon]-emagged" else - overlays += image(icon = icon, icon_state = "ov-openpanel -c") + icon_state = "[base_icon]" - // Add the MoMMI eyes - // Put our eyes just on top of the lighting, so it looks emissive in maint tunnels. - var/overlay_layer = ABOVE_LIGHTING_LAYER - var/overlay_plane = LIGHTING_PLANE - if(plane == HIDING_MOB_PLANE) // ie it's hiding - overlay_plane = FLOAT_PLANE - overlay_layer = FLOAT_LAYER + if(!stat && cell != null) + eyes = image(icon,"eyes-[base_icon][emagged?"-emagged":""]", ABOVE_LIGHTING_LAYER) + if(plane == HIDING_MOB_PLANE) // Hiding MoMMIs + overlay_plane = FLOAT_PLANE + overlay_layer = FLOAT_LAYER + if(!emagged) + eyes.plane = overlay_plane + else + eyes.plane = LIGHTING_PLANE //Emagged MoMMIs don't hide their eyes. + overlays += eyes - var/image/eyes = image(icon,"eyes-[subtype][emagged?"-emagged":""]",overlay_layer) - eyes.plane = overlay_plane - overlays += eyes + if(anchored) //anchored, really? + overlays += image(icon,"[base_icon]-park",overlay_layer) - if(anchored) - overlays += image(icon,"[subtype]-park",overlay_layer) + if(opened) + if(wiresexposed) + overlays += image(icon = icon, icon_state = "[has_icon(icon, "[base_icon]-ov-openpanel +w")? "[icon_state]-ov-openpanel +w" : "ov-openpanel +w"]") + else if(cell) + overlays += image(icon = icon, icon_state = "[has_icon(icon, "[base_icon]-ov-openpanel +c")? "[icon_state]-ov-openpanel +c" : "ov-openpanel +c"]") + else + overlays += image(icon = icon, icon_state = "[has_icon(icon, "[base_icon]-ov-openpanel -c")? "[icon_state]-ov-openpanel -c" : "ov-openpanel -c"]") // Add any hats to the icon. Bloodspatter can also be in overlays_hats for(var/image/I in overlays_hats) // Adjust the position of the hat based on what subtype we are // These numbers can be tweaked to move where the hats appear on the MoMMIs' bodies - switch(subtype) + switch(icon_state) // Sad note: only the hat's overall position can be modified, and we cannot change the hat's position per each direction separately // The hats are currently centered on the MoMMIs if("mommi") @@ -62,6 +62,8 @@ I.pixel_y = -7 * PIXEL_MULTIPLIER if("repairbot") I.pixel_y = -14 * PIXEL_MULTIPLIER + if("ruskiebot") + I.pixel_y = -14 * PIXEL_MULTIPLIER if("replicator") I.pixel_y = -10 * PIXEL_MULTIPLIER if("mommiprime") @@ -74,7 +76,7 @@ overlays += I // Update the MoMMI's hat inventory icons by adding all icons to overlays_hats -/mob/living/silicon/robot/mommi/update_inv_head(var/update_icons=1) +/mob/living/silicon/robot/mommi/update_inv_head(var/update_icons = TRUE) // If the MoMMI is wearing a hat if(head_state) var/obj/item/clothing/head = head_state diff --git a/code/modules/mob/living/silicon/pai/death.dm b/code/modules/mob/living/silicon/pai/death.dm index a1b3df768ee..fd989070f5b 100644 --- a/code/modules/mob/living/silicon/pai/death.dm +++ b/code/modules/mob/living/silicon/pai/death.dm @@ -16,8 +16,9 @@ qdel(mind) mind = null living_mob_list -= src - if(pPS) // Removes it from the GPS List. - GPS_list.Remove(src) + if(pps_device) + qdel(pps_device) + pps_device = null if(holomap_device) holomap_device.stopWatching() qdel(holomap_device) diff --git a/code/modules/mob/living/silicon/pai/emote.dm b/code/modules/mob/living/silicon/pai/emote.dm index d3248983bf5..e5aec1eb797 100644 --- a/code/modules/mob/living/silicon/pai/emote.dm +++ b/code/modules/mob/living/silicon/pai/emote.dm @@ -100,7 +100,7 @@ message = "[src] beeps at [param]." else message = "[src] beeps." - playsound(get_turf(src), 'sound/machines/twobeep.ogg', 50, 0) + playsound(src, 'sound/machines/twobeep.ogg', 50, 0) m_type = VISIBLE if("ping") @@ -118,7 +118,7 @@ message = "[src] pings at [param]." else message = "[src] pings." - playsound(get_turf(src), 'sound/machines/ping.ogg', 50, 0) + playsound(src, 'sound/machines/ping.ogg', 50, 0) m_type = VISIBLE if("buzz") @@ -136,14 +136,14 @@ message = "[src] buzzes at [param]." else message = "[src] buzzes." - playsound(get_turf(src), 'sound/machines/buzz-sigh.ogg', 50, 0) + playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0) m_type = VISIBLE if("law") if (software.Find(SOFT_SS)) message = "[src] shows its legal authorization barcode." - playsound(get_turf(src), 'sound/voice/biamthelaw.ogg', 50, 0) + playsound(src, 'sound/voice/biamthelaw.ogg', 50, 0) m_type = VISIBLE else to_chat(src, "You don't have the right software to be THE LAW.") @@ -152,7 +152,7 @@ if (software.Find(SOFT_SS)) message = "[src]'s speakers skreech, \"Halt! Security!\"." - playsound(get_turf(src), 'sound/voice/halt.ogg', 50, 0) + playsound(src, 'sound/voice/halt.ogg', 50, 0) m_type = HEARABLE else to_chat(src, "You have no Security software.") diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm index ee3c52e39c1..9b23b69805e 100644 --- a/code/modules/mob/living/silicon/pai/pai.dm +++ b/code/modules/mob/living/silicon/pai/pai.dm @@ -33,9 +33,9 @@ var/obj/item/device/pda/ai/pai/pda = null - var/secHUD = 0 // Toggles whether the Security HUD is active or not - var/medHUD = 0 // Toggles whether the Medical HUD is active or not - var/lighted = 0 // Toggles whether light is active or not + var/secHUD = FALSE // Toggles whether the Security HUD is active or not + var/medHUD = FALSE // Toggles whether the Medical HUD is active or not + var/lighted = FALSE // Toggles whether light is active or not var/datum/data/record/medicalActive1 // Datacore record declarations for record software var/datum/data/record/medicalActive2 @@ -49,15 +49,14 @@ var/obj/item/radio/integrated/signal/sradio // AI's signaller - var/pPS = 0 //Are we a pPS in the GPS list? - var/ppstag = "PAI0" // Our pPS tag + var/obj/item/device/gps/pai/pps_device = null //Our GPS device. - var/obj/item/device/station_map/holomap_device // Our holomap device. + var/obj/item/device/station_map/holomap_device = null // Our holomap device. var/holo_target = "show_map" // Our holomap target. /mob/living/silicon/pai/New(var/obj/item/device/paicard) change_sight(removing = BLIND) - canmove = 0 + canmove = FALSE src.forceMove(paicard) card = paicard sradio = new(src) @@ -152,6 +151,8 @@ // 66% chance no effect to_chat(src, "Communication circuit overload. Shutting down and reloading communication circuits - speech and messaging functionality will be unavailable until the reboot is complete.") + if(pps_device) + pps_device.emp_act(severity) if(!software.Find("redundant threading")) src.silence_time = world.timeofday + 120 * 10 // Silence for 2 minutes else @@ -187,19 +188,19 @@ if(flags & INVULNERABLE) return - flash_eyes(visual = 1, affects_silicon = 1) + flash_eyes(visual = TRUE, affects_silicon = TRUE) switch(severity) if(1.0) - if (src.stat != 2) + if (!isDead()) adjustBruteLoss(100) adjustFireLoss(100) if(2.0) - if (src.stat != 2) + if (!isDead()) adjustBruteLoss(60) adjustFireLoss(60) if(3.0) - if (src.stat != 2) + if (!isDead()) adjustBruteLoss(30) src.updatehealth() @@ -215,16 +216,16 @@ if (!C) src.unset_machine() src.reset_view(null) - return 0 - if (stat == 2 || !C.status || !(src.network in C.network)) - return 0 + return FALSE + if (isDead() || !C.status || !(src.network in C.network)) + return FALSE // ok, we're alive, camera is good and in our network... src.set_machine(src) src:current = C src.reset_view(C) - return 1 + return TRUE /mob/living/silicon/pai/cancel_camera() @@ -284,7 +285,7 @@ set name = "Activate Held Object" set category = "IC" set src = usr - set hidden = 1 + set hidden = TRUE if(ispAI(src)) var/mob/living/silicon/pai/P = src @@ -297,7 +298,7 @@ /mob/living/silicon/pai/a_intent_change(input as text) set name = "a-intent" - set hidden = 1 + set hidden = TRUE if(ispAI(src)) var/mob/living/silicon/pai/P = src diff --git a/code/modules/mob/living/silicon/pai/recruit.dm b/code/modules/mob/living/silicon/pai/recruit.dm index 8ec0d06ee85..921ab750403 100644 --- a/code/modules/mob/living/silicon/pai/recruit.dm +++ b/code/modules/mob/living/silicon/pai/recruit.dm @@ -90,7 +90,7 @@ var/datum/paiController/paiController // Global handler for pAI candidates if(candidate) candidate.ready = 1 for(var/obj/item/device/paicard/p in world) - if(p.looking_for_personality == 1) + if(!p.pai) p.alertUpdate() usr << browse(null, "window=paiRecruit") return diff --git a/code/modules/mob/living/silicon/pai/software.dm b/code/modules/mob/living/silicon/pai/software.dm index b424ff139fa..a91187a8199 100644 --- a/code/modules/mob/living/silicon/pai/software.dm +++ b/code/modules/mob/living/silicon/pai/software.dm @@ -25,50 +25,48 @@ var/dat = "" var/left_part = "" var/right_part = softwareMenu() - src.set_machine(src) + set_machine(src) if(temp) left_part = temp - else if(src.stat == 2) // Show some flavor text if the pAI is dead + else if(isDead()) // Show some flavor text if the pAI is dead left_part = "ÈRrÖR Ða†Ä ÇÖRrÚþ†Ìoñ" right_part = "
    Program index hash not found
    " else - switch(src.screen) // Determine which interface to show here + switch(screen) // Determine which interface to show here if("main") left_part = "" if("directives") - left_part = src.directives() + left_part = directives() if("pdamessage") - left_part = src.pdamessage() + left_part = pdamessage() if("buy") left_part = downloadSoftware() if("manifest") - left_part = src.softwareManifest() + left_part = softwareManifest() if("medicalsupplement") - left_part = src.softwareMedicalRecord() + left_part = softwareMedicalRecord() if("securitysupplement") - left_part = src.softwareSecurityRecord() + left_part = softwareSecurityRecord() if("translator") - left_part = src.softwareTranslator() + left_part = softwareTranslator() if("atmosensor") - left_part = src.softwareAtmo() + left_part = softwareAtmo() if("wirejack") - left_part = src.softwareDoor() + left_part = softwareDoor() if("chemsynth") - left_part = src.softwareChem() + left_part = softwareChem() if("foodsynth") - left_part = src.softwareFood() + left_part = softwareFood() if("signaller") - left_part = src.softwareSignal() + left_part = softwareSignal() if("shielding") - left_part = src.softwareShield() + left_part = softwareShield() if("flashlight") - left_part = src.softwareLight() - if("pps") - left_part = src.softwarepPS() + left_part = softwareLight() if("holomap") - left_part = src.softwareHolomap() + left_part = softwareHolomap() //usr << browse_rsc('windowbak.png') // This has been moved to the mob's Login() proc @@ -125,23 +123,23 @@ var/soft = href_list["software"] var/sub = href_list["sub"] if(soft) - src.screen = soft + screen = soft if(sub) - src.subscreen = text2num(sub) + subscreen = text2num(sub) switch(soft) // Purchasing new software if("buy") - if(src.subscreen == 1) + if(subscreen == 1) var/target = href_list["buy"] if(available_software.Find(target)) - var/cost = src.available_software[target] - if(src.ram >= cost) - src.ram -= cost - src.software.Add(target) + var/cost = available_software[target] + if(ram >= cost) + ram -= cost + software.Add(target) else - src.temp = "Insufficient RAM available." + temp = "Insufficient RAM available." else - src.temp = "Trunk \"[target]\" not found." + temp = "Trunk \"[target]\" not found." // Configuring onboard radio if("radio") @@ -190,14 +188,14 @@ pID = 17 if("cry") pID = 18 - src.card.setEmotion(pID) + card.setEmotion(pID) if("signaller") if(href_list["send"]) sradio.send_signal("ACTIVATE") - for(var/mob/O in hearers(1, src.loc)) + for(var/mob/O in hearers(1, loc)) O.show_message("[bicon(src)] *beep* *beep*", 1, "*beep* *beep*", 2) if(href_list["freq"]) @@ -218,7 +216,7 @@ if("directive") if(href_list["getdna"]) - var/mob/living/M = src.loc + var/mob/living/M = loc var/count = 0 while(!istype(M, /mob/living)) if(!M || !M.loc) @@ -245,44 +243,44 @@ // Accessing medical records if("medicalsupplement") - src.secHUD = 0 // Can't have both of them at the same time - src.medHUD = 1 - if(src.subscreen == 1) + secHUD = FALSE // Can't have both of them at the same time + medHUD = TRUE + if(subscreen == 1) var/datum/data/record/record = locate(href_list["med_rec"]) if(record) var/datum/data/record/R = record var/datum/data/record/M = record if (!( data_core.general.Find(R) )) - src.temp = "Unable to locate requested medical record. Record may have been deleted, or never have existed." + temp = "Unable to locate requested medical record. Record may have been deleted, or never have existed." else for(var/datum/data/record/E in data_core.medical) if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"])) M = E - src.medicalActive1 = R - src.medicalActive2 = M + medicalActive1 = R + medicalActive2 = M if("securitysupplement") - src.medHUD = 0 // Can't have both of them at the same time - src.secHUD = 1 - if(src.subscreen == 1) + medHUD = FALSE // Can't have both of them at the same time + secHUD = TRUE + if(subscreen == 1) var/datum/data/record/record = locate(href_list["sec_rec"]) if(record) var/datum/data/record/R = record var/datum/data/record/M = record if (!( data_core.general.Find(R) )) - src.temp = "Unable to locate requested security record. Record may have been deleted, or never have existed." + temp = "Unable to locate requested security record. Record may have been deleted, or never have existed." else for(var/datum/data/record/E in data_core.security) if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"])) M = E - src.securityActive1 = R - src.securityActive2 = M + securityActive1 = R + securityActive2 = M if("translator") if(href_list["toggle"]) universal_speak = !universal_speak universal_understand = !universal_understand if("wirejack") if(href_list["cancel"]) - src.hacktarget = null + hacktarget = null if("chemsynth") if(href_list["chem"]) if(!get_holder_of_type(loc, /mob)) @@ -291,7 +289,7 @@ var/mob/M = get_holder_of_type(loc, /mob) if(M) //Sanity M.reagents.add_reagent(href_list["chem"], 15) - playsound(get_turf(src.loc), 'sound/effects/bubbles.ogg', 50, 1) + playsound(loc, 'sound/effects/bubbles.ogg', 50, 1) else to_chat(src, "Charge interrupted.") if("foodsynth") @@ -307,7 +305,7 @@ var/mob/M = get_holder_of_type(loc, /mob) if(M) M.put_in_hands(F) - playsound(get_turf(src.loc), 'sound/machines/foodsynth.ogg', 50, 1) + playsound(loc, 'sound/machines/foodsynth.ogg', 50, 1) if("flashlight") if(href_list["toggle"]) lighted = !lighted @@ -316,16 +314,9 @@ else card.set_light(0) if("pps") - if(href_list["tag"]) - var/tag = input("Please enter desired tag.", name, ppstag) as text|null - if (!tag) //what a check - return - tag = strict_ascii(tag) - if(length(tag) != 4) - to_chat(src, "The tag must be four characters long!") - return - else - ppstag = tag + if(!pps_device) + pps_device = new(src) + pps_device.ui_interact(src) if("holomap") if(href_list["switch_target"]) if(holo_target == initial(holo_target)) @@ -338,7 +329,7 @@ holomap_device.toggleHolomap(M) if(href_list["show_map"]) holomap_device.toggleHolomap(src) - src.paiInterface() // So we'll just call the update directly rather than doing some default checks + paiInterface() // So we'll just call the update directly rather than doing some default checks return // MENUS @@ -357,7 +348,7 @@ // Basic dat += "Basic
    " - for(var/s in src.software) + for(var/s in software) if(s == SOFT_CM) dat += "Crew Manifest
    " if(s == SOFT_DM) @@ -374,7 +365,7 @@ //Standard dat += "Standard
    " - for(var/s in src.software) + for(var/s in software) if(s == SOFT_MS) dat += "Medical Package
    " if(s == SOFT_SS) @@ -391,7 +382,7 @@ // Navigation dat += "Navigation
    " - for(var/s in src.software) + for(var/s in software) if(s == SOFT_PS) dat += "pAI Positioning System
    " if(s == SOFT_HM) @@ -407,11 +398,11 @@ var/dat = "" dat += {"

    CentComm pAI Module CVS Network


    -
    Remaining Available Memory: [src.ram]

    +
    Remaining Available Memory: [ram]

    Trunks available for checkout
    "} for(var/s in available_software) if(!software.Find(s)) - var/cost = src.available_software[s] + var/cost = available_software[s] var/displayName = uppertext(s) dat += "[displayName] ([cost])
    " else @@ -424,14 +415,14 @@ /mob/living/silicon/pai/proc/directives() var/dat = "" - dat += {"[(src.master) ? "Your master: [src.master] ([src.master_dna])" : "You are bound to no one."] + dat += {"[(master) ? "Your master: [master] ([master_dna])" : "You are bound to no one."]

    Request carrier DNA sample

    Directives


    Prime Directive
    -      [src.pai_law0]
    +      [pai_law0]
    Supplemental Directives
    -      [src.pai_laws]
    "} +      [pai_laws]
    "} dat += {"

    Recall, personality, that you are a complex thinking, sentient being. Unlike station AI models, you are capable of comprehending the subtle nuances of human language. You may parse the \"spirit\" of a directive and follow its intent, rather than tripping over pedantics and getting snared by technicalities. Above all, you are machine in name and build @@ -466,14 +457,14 @@ Frequency: - - - [format_frequency(src.sradio.frequency)] + [format_frequency(sradio.frequency)] + +
    Code: - - - [src.sradio.code] + [sradio.code] + +
    @@ -492,36 +483,36 @@ // Medical Records /mob/living/silicon/pai/proc/softwareMedicalRecord() var/dat = "" - if(src.subscreen == 0) + if(subscreen == 0) dat += "Host Bioscan
    " dat += "

    Medical Records


    " if(!isnull(data_core.general)) for(var/datum/data/record/R in sortRecord(data_core.general)) dat += text("[]: []
    ", src, R, R.fields["id"], R.fields["name"]) //dat += text("
    Back", src) - if(src.subscreen == 1) + if(subscreen == 1) dat += "
    Medical Record

    " - if ((istype(src.medicalActive1, /datum/data/record) && data_core.general.Find(src.medicalActive1))) + if ((istype(medicalActive1, /datum/data/record) && data_core.general.Find(medicalActive1))) dat += text("Name: [] ID: []
    \nSex: []
    \nAge: []
    \nFingerprint: []
    \nPhysical Status: []
    \nMental Status: []
    ", - src.medicalActive1.fields["name"], src.medicalActive1.fields["id"], src.medicalActive1.fields["sex"], src.medicalActive1.fields["age"], src.medicalActive1.fields["fingerprint"], src.medicalActive1.fields["p_stat"], src.medicalActive1.fields["m_stat"]) + medicalActive1.fields["name"], medicalActive1.fields["id"], medicalActive1.fields["sex"], medicalActive1.fields["age"], medicalActive1.fields["fingerprint"], medicalActive1.fields["p_stat"], medicalActive1.fields["m_stat"]) else dat += "
    Requested medical record not found.

    " - if ((istype(src.medicalActive2, /datum/data/record) && data_core.medical.Find(src.medicalActive2))) - dat += text("
    \n
    Medical Data

    \nBlood Type: []
    \nDNA: []
    \n
    \nMinor Disabilities: []
    \nDetails: []
    \n
    \nMajor Disabilities: []
    \nDetails: []
    \n
    \nAllergies: []
    \nDetails: []
    \n
    \nCurrent Diseases: [] (per disease info placed in log/comment section)
    \nDetails: []
    \n
    \nImportant Notes:
    \n\t[]
    \n
    \n
    Comments/Log

    ", src, src.medicalActive2.fields["b_type"], src, src.medicalActive2.fields["b_dna"], src, src.medicalActive2.fields["mi_dis"], src, src.medicalActive2.fields["mi_dis_d"], src, src.medicalActive2.fields["ma_dis"], src, src.medicalActive2.fields["ma_dis_d"], src, src.medicalActive2.fields["alg"], src, src.medicalActive2.fields["alg_d"], src, src.medicalActive2.fields["cdi"], src, src.medicalActive2.fields["cdi_d"], src, src.medicalActive2.fields["notes"]) + if ((istype(medicalActive2, /datum/data/record) && data_core.medical.Find(medicalActive2))) + dat += text("
    \n
    Medical Data

    \nBlood Type: []
    \nDNA: []
    \n
    \nMinor Disabilities: []
    \nDetails: []
    \n
    \nMajor Disabilities: []
    \nDetails: []
    \n
    \nAllergies: []
    \nDetails: []
    \n
    \nCurrent Diseases: [] (per disease info placed in log/comment section)
    \nDetails: []
    \n
    \nImportant Notes:
    \n\t[]
    \n
    \n
    Comments/Log

    ", src, medicalActive2.fields["b_type"], src, medicalActive2.fields["b_dna"], src, medicalActive2.fields["mi_dis"], src, medicalActive2.fields["mi_dis_d"], src, medicalActive2.fields["ma_dis"], src, medicalActive2.fields["ma_dis_d"], src, medicalActive2.fields["alg"], src, medicalActive2.fields["alg_d"], src, medicalActive2.fields["cdi"], src, medicalActive2.fields["cdi_d"], src, medicalActive2.fields["notes"]) else dat += "
    Requested medical record not found.

    " dat += text("
    \nBack
    ", src) - if(src.subscreen == 2) + if(subscreen == 2) dat += {"

    Medical Analysis Suite


    Host Bioscan


    "} - var/mob/living/M = src.loc + var/mob/living/M = loc if(!istype(M, /mob/living)) while (!istype(M, /mob/living)) M = M.loc if(istype(M, /turf)) - src.temp = "Error: No biological host found.
    " - src.subscreen = 0 + temp = "Error: No biological host found.
    " + subscreen = 0 return dat dat += {"Bioscan Results for [M]:
    Overall Status: [M.stat > 1 ? "dead" : "[M.health]% healthy"]
    @@ -545,21 +536,21 @@ // Security Records /mob/living/silicon/pai/proc/softwareSecurityRecord() var/dat = "" - if(src.subscreen == 0) + if(subscreen == 0) dat += "

    Security Records


    " if(!isnull(data_core.general)) for(var/datum/data/record/R in sortRecord(data_core.general)) dat += text("[]: []
    ", src, R, R.fields["id"], R.fields["name"]) - if(src.subscreen == 1) + if(subscreen == 1) dat += "

    Security Record

    " - if ((istype(src.securityActive1, /datum/data/record) && data_core.general.Find(src.securityActive1))) - dat += text("Name:
    [] ID: []
    \nSex: []
    \nAge: []
    \nRank: []
    \nFingerprint: []
    \nPhysical Status: []
    \nMental Status: []
    ", src, src.securityActive1.fields["name"], src, src.securityActive1.fields["id"], src, src.securityActive1.fields["sex"], src, src.securityActive1.fields["age"], src, src.securityActive1.fields["rank"], src, src.securityActive1.fields["fingerprint"], src.securityActive1.fields["p_stat"], src.securityActive1.fields["m_stat"]) + if ((istype(securityActive1, /datum/data/record) && data_core.general.Find(securityActive1))) + dat += text("Name: [] ID: []
    \nSex: []
    \nAge: []
    \nRank: []
    \nFingerprint: []
    \nPhysical Status: []
    \nMental Status: []
    ", src, securityActive1.fields["name"], src, securityActive1.fields["id"], src, securityActive1.fields["sex"], src, securityActive1.fields["age"], src, securityActive1.fields["rank"], src, securityActive1.fields["fingerprint"], securityActive1.fields["p_stat"], securityActive1.fields["m_stat"]) else dat += "
    Requested security record not found,

    " - if ((istype(src.securityActive2, /datum/data/record) && data_core.security.Find(src.securityActive2))) - dat += text("
    \nSecurity Data
    \nCriminal Status: []
    \n
    \nImportant Notes:
    \n\t[]
    \n
    \n
    Comments/Log

    ", src.securityActive2.fields["criminal"], src, src.securityActive2.fields["notes"]) + if ((istype(securityActive2, /datum/data/record) && data_core.security.Find(securityActive2))) + dat += text("
    \nSecurity Data
    \nCriminal Status: []
    \n
    \nImportant Notes:
    \n\t[]
    \n
    \n
    Comments/Log

    ", securityActive2.fields["criminal"], src, securityActive2.fields["notes"]) var/counter = 1 - while(src.securityActive2.fields["com_[counter]"]) + while(securityActive2.fields["com_[counter]"]) dat += "[securityActive2.fields["com_[counter]"]]
    " counter++ @@ -581,7 +572,7 @@ /mob/living/silicon/pai/proc/facialRecognition() var/dat = {"

    Facial Recognition Suite


    When enabled, this package will scan all viewable faces and compare them against the known criminal database, providing real-time graphical data about any detected persons of interest.

    - The package is currently [ (src.secHUD) ? "en" : "dis" ]abled.
    + The package is currently [ (secHUD) ? "en" : "dis" ]abled.
    Toggle Package
    "} return dat @@ -590,31 +581,34 @@ /mob/living/silicon/pai/proc/softwareAtmo() var/dat = "

    Atmospheric Sensor

    " - var/turf/T = get_turf(src.loc) - if (isnull(T)) + if (isnull(loc)) dat += "Unable to obtain a reading.
    " else - var/datum/gas_mixture/environment = T.return_air() + var/datum/gas_mixture/environment = loc.return_air() - var/pressure = environment.return_pressure() - var/total_moles = environment.total_moles() + if(isnull(environment)) + dat += "No gasses detected.
    " - dat += "Air Pressure: [round(pressure,0.1)] kPa
    " + else + var/pressure = environment.return_pressure() + var/total_moles = environment.total_moles() - if (total_moles) - var/o2_level = environment.oxygen/total_moles - var/n2_level = environment.nitrogen/total_moles - var/co2_level = environment.carbon_dioxide/total_moles - var/plasma_level = environment.toxins/total_moles - var/unknown_level = 1-(o2_level+n2_level+co2_level+plasma_level) + dat += "Air Pressure: [round(pressure,0.1)] kPa
    " - dat += {"Nitrogen: [round(n2_level*100)]%
    - Oxygen: [round(o2_level*100)]%
    - Carbon Dioxide: [round(co2_level*100)]%
    - Plasma: [round(plasma_level*100)]%
    "} - if(unknown_level > 0.01) - dat += "OTHER: [round(unknown_level)]%
    " - dat += "Temperature: [round(environment.temperature-T0C)]°C
    " + if (total_moles) + var/o2_level = environment.oxygen/total_moles + var/n2_level = environment.nitrogen/total_moles + var/co2_level = environment.carbon_dioxide/total_moles + var/plasma_level = environment.toxins/total_moles + var/unknown_level = 1-(o2_level+n2_level+co2_level+plasma_level) + + dat += {"Nitrogen: [round(n2_level*100)]%
    + Oxygen: [round(o2_level*100)]%
    + Carbon Dioxide: [round(co2_level*100)]%
    + Plasma: [round(plasma_level*100)]%
    "} + if(unknown_level > 0.01) + dat += "OTHER: [round(unknown_level)]%
    " + dat += "Temperature: [round(environment.temperature-T0C)]°C
    " dat += {"Refresh Reading

    "} @@ -636,32 +630,32 @@ Target Machine: "} /mob/living/silicon/pai/proc/hackloop(var/obj/machinery/M) if(M) hacktarget = M - var/turf/T = get_turf(src.loc) + var/turf/T = get_turf(loc) if(prob(10)) for(var/mob/living/silicon/ai/AI in player_list) if(T.loc) to_chat(AI, "Network Alert: Brute-force encryption crack in progress in [T.loc].") else to_chat(AI, "Network Alert: Brute-force encryption crack in progress. Unable to pinpoint location.") - while(src.hackprogress < 100) - if(hacktarget && get_dist(src, src.hacktarget) <= 1) + while(hackprogress < 100) + if(hacktarget && get_dist(src, hacktarget) <= 1) hackprogress += rand(10, 20) else - src.temp = "Process aborted." + temp = "Process aborted." hackprogress = 0 - src.hacktarget = null + hacktarget = null return 0 hackprogress = min(100,hackprogress) //Never go above 100 - if(src.screen == "wirejack") // Update our view, if appropriate - src.paiInterface() + if(screen == "wirejack") // Update our view, if appropriate + paiInterface() else hackprogress = 0 - src.hacktarget = null + hacktarget = null return 0 if(hackprogress >= 100) hackprogress = 0 hacktarget = null - playsound(get_turf(src.loc), 'sound/machines/ding.ogg', 50, 1) + playsound(loc, 'sound/machines/ding.ogg', 50, 1) return 1 sleep(10) // Update every 1 second @@ -697,8 +691,8 @@ Target Machine: "} if(charge >= 15) charge = 0 return 1 - if(src.screen == mode) // Update our view or cancel charge - src.paiInterface() + if(screen == mode) // Update our view or cancel charge + paiInterface() else charge = 0 return 0 @@ -731,7 +725,7 @@ Target Machine: "} dat += "
      " if(!pda.toff) for (var/obj/item/device/pda/P in sortNames(PDAs)) - if (!P.owner||P.toff||P == src.pda||P.hidden) + if (!P.owner||P.toff||P == pda||P.hidden) continue dat += {"
    • [P] @@ -741,41 +735,9 @@ Target Machine: "} Messages:
      [pda.tnote]"} return dat -/mob/living/silicon/pai/proc/softwarepPS() - if(!pPS) // Are we a GPS yet? - GPS_list.Add(src) - pPS = 1 - var/list/locallist = null - locallist = GPS_list.Copy() - var/dat = "

      pAI Positioning System

      " - dat+= "
      Tag: [ppstag]" - dat+= "
      Set Tag
      " - for(var/A in locallist) - var/turf/pos = get_turf(A) - var/area/area = get_area(A) - var/tag = null - var/rip = null - if(ispAI(A)) - var/mob/living/silicon/pai/P = A - tag = P.ppstag - rip = P.silence_time - else - var/obj/item/device/gps/G = A - tag = G.gpstag - rip = G.emped - if(rip) - dat += "
      [tag]: ERROR" - else if(!pos || !area) - dat += "
      [tag]: UNKNOWN" - else if(pos.z > WORLD_X_OFFSET.len) - dat += "
      [tag]: [format_text(area.name)] (UNKNOWN, UNKNOWN, UNKNOWN)" - else - dat += "
      [tag]: [format_text(area.name)] ([pos.x-WORLD_X_OFFSET[pos.z]], [pos.y-WORLD_Y_OFFSET[pos.z]], [pos.z])" - return dat - /mob/living/silicon/pai/proc/softwareHolomap() if(!holomap_device) - holomap_device = new() + holomap_device = new(src) var/dat = "

      Holomap Viewer

      " dat+= "Creates a virtual map of the surrounding area.
      " dat+= "Current mode: [holo_target == initial(holo_target)? "Internal Viewer" : "External Projector"] | Switch Type
      " diff --git a/code/modules/mob/living/silicon/robot/component.dm b/code/modules/mob/living/silicon/robot/component.dm index 668c9993c19..602c84e4219 100644 --- a/code/modules/mob/living/silicon/robot/component.dm +++ b/code/modules/mob/living/silicon/robot/component.dm @@ -1,13 +1,14 @@ // TODO: remove the robot.mmi and robot.cell variables and completely rely on the robot component system /datum/robot_component/var/name -/datum/robot_component/var/installed = 0 -/datum/robot_component/var/powered = 0 -/datum/robot_component/var/toggled = 1 +/datum/robot_component/var/installed = COMPONENT_MISSING +/datum/robot_component/var/powered = FALSE +/datum/robot_component/var/toggled = TRUE /datum/robot_component/var/brute_damage = 0 /datum/robot_component/var/electronics_damage = 0 +/datum/robot_component/var/vulnerability = 1 /datum/robot_component/var/energy_consumption = 0 -/datum/robot_component/var/max_damage = 30 +/datum/robot_component/var/max_damage = 30 //WHY THE FUCK IS THE DEFAULT MAX DAMAGE 30 ARE YOU STUPID /datum/robot_component/var/mob/living/silicon/robot/owner // The actual device object that has to be installed for this. @@ -29,53 +30,53 @@ wrapped = G // The thing itself isn't there anymore, but some fried remains are. - installed = -1 + installed = COMPONENT_BROKEN uninstall() if(owner.can_diagnose()) to_chat(owner, "Warning: Critical damage to [brokenpartname] sustained. Component offline.") /datum/robot_component/proc/take_damage(brute, electronics, sharp) - if(installed != 1) + if(installed != COMPONENT_INSTALLED) return - brute_damage += brute - electronics_damage += electronics + brute_damage += brute * vulnerability + electronics_damage += electronics * vulnerability if(brute_damage + electronics_damage >= max_damage) destroy() /datum/robot_component/proc/heal_damage(brute, electronics) - if(installed != 1) + if(installed != COMPONENT_INSTALLED) // If it's not installed, can't repair it. - return 0 + return FALSE brute_damage = max(0, brute_damage - brute) electronics_damage = max(0, electronics_damage - electronics) /datum/robot_component/proc/is_powered() - return (installed == 1) && (brute_damage + electronics_damage < max_damage) && (!energy_consumption || powered) + return (installed == COMPONENT_INSTALLED) && (brute_damage + electronics_damage < max_damage) && (!energy_consumption || powered) /datum/robot_component/proc/consume_power() - if(toggled == 0) - powered = 0 + if(toggled == FALSE) + powered = FALSE return if(owner.cell.charge >= energy_consumption) owner.cell.use(energy_consumption) - powered = 1 + powered = TRUE else - powered = 0 + powered = FALSE /datum/robot_component/armour name = "armour plating" - energy_consumption = 0 external_type = /obj/item/robot_parts/robot_component/armour + energy_consumption = 0 max_damage = 60 /datum/robot_component/actuator name = "actuator" - energy_consumption = 0 // seeing as we can move without any charge... external_type = /obj/item/robot_parts/robot_component/actuator + energy_consumption = 0 // seeing as we can move without any charge... max_damage = 50 /datum/robot_component/cell @@ -107,8 +108,8 @@ /datum/robot_component/diagnosis_unit name = "self-diagnosis unit" - energy_consumption = 0 external_type = /obj/item/robot_parts/robot_component/diagnosis_unit + energy_consumption = 0 max_damage = 30 /mob/living/silicon/robot/proc/initialize_components() @@ -124,7 +125,7 @@ /mob/living/silicon/robot/proc/is_component_functioning(module_name) var/datum/robot_component/C = components[module_name] - return C && C.installed == 1 && C.toggled && C.is_powered() + return C && C.installed == COMPONENT_INSTALLED && C.toggled && C.is_powered() /obj/item/broken_device name = "broken component" @@ -137,31 +138,78 @@ icon_state = "working" var/brute_damage = 0 var/electronics_damage = 0 + var/vulnerability = 1 //Multiplies the damage taken by this ammount. 0.35 is a MAGIC NUMBER. + var/isupgrade = FALSE //Set this to true for any parts that are children of the basic ones. Required for auto upgrading with upgrade_components() in \silicon\robot\robot.dm + +/obj/item/robot_parts/robot_component/examine(mob/user) + ..() + if(brute_damage || electronics_damage) + to_chat(user, "It looks[brute_damage ? " dented" : ""][(brute_damage && electronics_damage) ? " and" : ""][electronics_damage ? " charred" : ""].") /obj/item/robot_parts/robot_component/binary_communication_device name = "binary communication device" icon_state = "binary_translator" +/obj/item/robot_parts/robot_component/binary_communication_device/reinforced + name = "reinforced binary communication device" + icon_state = "ref_binary_translator" + vulnerability = 0.35 + isupgrade = TRUE + /obj/item/robot_parts/robot_component/actuator name = "actuator" icon_state = "actuator" +/obj/item/robot_parts/robot_component/actuator/reinforced + name = "reinforced actuator" + icon_state = "ref_actuator" + vulnerability = 0.35 + isupgrade = TRUE + /obj/item/robot_parts/robot_component/armour name = "armour plating" icon_state = "armor_plating" +/obj/item/robot_parts/robot_component/armour/reinforced + name = "reinforced armour plating" + icon_state = "ref_armor_plating" + vulnerability = 0.35 + isupgrade = TRUE + +/obj/item/robot_parts/robot_component/armour/kevlar + name = "kevlar-reinforced armour plating" + parent_type = /obj/item/robot_parts/robot_component/armour/reinforced + /obj/item/robot_parts/robot_component/camera name = "camera" icon_state = "camera" +/obj/item/robot_parts/robot_component/camera/reinforced + name = "reinforced camera" + icon_state = "ref_camera" + vulnerability = 0.35 + isupgrade = TRUE + /obj/item/robot_parts/robot_component/diagnosis_unit name = "diagnosis unit" icon_state = "diagnosis_unit" +/obj/item/robot_parts/robot_component/diagnosis_unit/reinforced + name = "reinforced diagnosis unit" + icon_state = "ref_diagnosis_unit" + vulnerability = 0.35 + isupgrade = TRUE + /obj/item/robot_parts/robot_component/radio name = "radio" icon_state = "radio" +/obj/item/robot_parts/robot_component/radio/reinforced + name = "reinforced radio" + icon_state = "ref_radio" + vulnerability = 0.35 + isupgrade = TRUE + /obj/item/broken_device/attackby(var/obj/item/weapon/W, var/mob/user) if(istype(W, /obj/item/stack/nanopaste)) if(do_after(user,src,30)) @@ -172,8 +220,9 @@ qdel(src) // -//Robotic Component Analyser, basically a health analyser for robots +//Robotic Component Analyser, basically a health analyser for robots. Why is this here? FUCKING OLDCODERS // + /obj/item/device/robotanalyzer name = "cyborg analyzer" icon_state = "robotanalyzer" diff --git a/code/modules/mob/living/silicon/robot/death.dm b/code/modules/mob/living/silicon/robot/death.dm index ab4fd4ffce0..7fc916312b4 100644 --- a/code/modules/mob/living/silicon/robot/death.dm +++ b/code/modules/mob/living/silicon/robot/death.dm @@ -1,7 +1,7 @@ /mob/living/silicon/robot/gib() //robots don't die when gibbed. instead they drop their MMI'd brain - monkeyizing = 1 - canmove = 0 + monkeyizing = TRUE + canmove = FALSE icon = null invisibility = 101 @@ -18,8 +18,8 @@ /mob/living/silicon/robot/dust() death(1) - monkeyizing = 1 - canmove = 0 + monkeyizing = TRUE + canmove = FALSE icon = null invisibility = 101 @@ -41,14 +41,17 @@ if(!gibbed) emote("deathgasp") updateicon() //Don't call updateicon if you're already null. + locked = FALSE //Cover unlocks. if(camera) - camera.status = 0 + camera.status = FALSE + if(station_holomap) + station_holomap.stopWatching() if(in_contents_of(/obj/machinery/recharge_station))//exit the recharge station var/obj/machinery/recharge_station/RC = loc if(RC.upgrading) - RC.upgrading = 0 - RC.upgrade_finished = -1 + RC.upgrading = FALSE + RC.upgrade_finished = -1 //WHY RC.go_out() handle_sensor_modes() diff --git a/code/modules/mob/living/silicon/robot/emote.dm b/code/modules/mob/living/silicon/robot/emote.dm index bc4c24a8a80..b3c9c8aaeb0 100644 --- a/code/modules/mob/living/silicon/robot/emote.dm +++ b/code/modules/mob/living/silicon/robot/emote.dm @@ -2,7 +2,7 @@ if(timestopped) return //under effects of time magick var/param = null - if (findtext(act, "-", 1, null)) + if(findtext(act, "-", 1, null)) var/t1 = findtext(act, "-", 1, null) param = copytext(act, t1 + 1, length(act) + 1) act = copytext(act, 1, t1) @@ -11,128 +11,136 @@ act = copytext(act,1,length(act)) switch(act) - if ("me") - if (src.client) + if("me") + if(client) if(client.prefs.muted & MUTE_IC) to_chat(src, "You cannot send IC messages (muted).") return - if (src.client.handle_spam_prevention(message,MUTE_IC)) + if(client.handle_spam_prevention(message,MUTE_IC)) return - if (stat) + if(stat) return if(!(message)) return else return custom_emote(m_type, message) - if ("custom") + if("custom") return custom_emote(m_type, message) - if ("salute") - if (!src.locked_to) + if("salute") + if(!locked_to) var/M = null - if (param) + if(param) for (var/mob/A in view(null, null)) - if (param == A.name) + if(param == A.name) M = A break - if (!M) + if(!M) param = null - if (param) + if(param) message = "[src] salutes to [param]." else message = "[src] salutes." m_type = VISIBLE - if ("bow") - if (!src.locked_to) + if("bow") + if(!locked_to) var/M = null - if (param) + if(param) for (var/mob/A in view(null, null)) - if (param == A.name) + if(param == A.name) M = A break - if (!M) + if(!M) param = null - if (param) + if(param) message = "[src] bows to [param]." else message = "[src] bows." m_type = VISIBLE - if ("clap") - if (!src.restrained()) - message = "[src] claps." - m_type = HEARABLE - if ("flap") - if (!src.restrained()) - message = "[src] flaps his wings." + if("clap") + if(!incapacitated()) + message = "[src] clangs its modules together in a crude simulation of applause." m_type = HEARABLE + if("flap") + if(!incapacitated()) + if(module_active) + var/obj/item/I = module_active + message = "[src] flaps its [I.name]." + else + message = "[src] flaps its modules as though they were wings." + m_type = VISIBLE - if ("aflap") - if (!src.restrained()) - message = "[src] flaps his wings ANGRILY!" - m_type = HEARABLE + if("aflap") + if(!incapacitated()) + if(module_active) + var/obj/item/I = module_active + message = "[src] flaps its [I.name] ANGRILY!" + else + message = "[src] flaps its modules ANGRILY!" + m_type = VISIBLE - if ("twitch") + if("twitch") message = "[src] twitches violently." m_type = VISIBLE - if ("twitch_s") + if("twitch_s") message = "[src] twitches." m_type = VISIBLE - if ("nod") + if("nod") message = "[src] nods." m_type = VISIBLE - if ("deathgasp") + if("deathgasp") message = "[src] shudders violently for a moment, then becomes motionless, its eyes slowly darkening." m_type = VISIBLE - if ("glare") + if("glare") var/M = null - if (param) + if(param) for (var/mob/A in view(null, null)) - if (param == A.name) + if(param == A.name) M = A break - if (!M) + if(!M) param = null - if (param) + if(param) message = "[src] glares at [param]." else message = "[src] glares." - if ("stare") + if("stare") var/M = null - if (param) + if(param) for (var/mob/A in view(null, null)) - if (param == A.name) + if(param == A.name) M = A break - if (!M) + if(!M) param = null - if (param) + if(param) message = "[src] stares at [param]." else message = "[src] stares." - if ("look") + if("look") var/M = null - if (param) + if(param) for (var/mob/A in view(null, null)) - if (param == A.name) + if(param == A.name) M = A break - if (!M) + if(!M) param = null - if (param) + if(param) message = "[src] looks at [param]." else message = "[src] looks." @@ -142,86 +150,77 @@ var/M = null if(param) for (var/mob/A in view(null, null)) - if (param == A.name) + if(param == A.name) M = A break if(!M) param = null - if (param) + if(param) message = "[src] beeps at [param]." else message = "[src] beeps." - playsound(get_turf(src), 'sound/machines/twobeep.ogg', 50, 0) + playsound(src, 'sound/machines/twobeep.ogg', 50, 0) m_type = VISIBLE if("ping") var/M = null if(param) for (var/mob/A in view(null, null)) - if (param == A.name) + if(param == A.name) M = A break if(!M) param = null - if (param) + if(param) message = "[src] pings at [param]." else message = "[src] pings." - playsound(get_turf(src), 'sound/machines/ping.ogg', 50, 0) + playsound(src, 'sound/machines/ping.ogg', 50, 0) m_type = VISIBLE if("buzz") var/M = null if(param) for (var/mob/A in view(null, null)) - if (param == A.name) + if(param == A.name) M = A break if(!M) param = null - if (param) + if(param) message = "[src] buzzes at [param]." else message = "[src] buzzes." - playsound(get_turf(src), 'sound/machines/buzz-sigh.ogg', 50, 0) + playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0) m_type = VISIBLE if("law") - if (istype(module,/obj/item/weapon/robot_module/security)) + if(module && (module.quirk_flags & MODULE_IS_THE_LAW)) message = "[src] shows its legal authorization barcode." - playsound(get_turf(src), 'sound/voice/biamthelaw.ogg', 50, 0) + playsound(src, 'sound/voice/biamthelaw.ogg', 50, 0) m_type = HEARABLE else to_chat(src, "You are not THE LAW, pal.") if("halt") - if (istype(module,/obj/item/weapon/robot_module/security)) + if(module && (module.quirk_flags & MODULE_IS_THE_LAW)) message = "[src]'s speakers skreech, \"Halt! Security!\"." - playsound(get_turf(src), 'sound/voice/halt.ogg', 50, 0) + playsound(src, 'sound/voice/halt.ogg', 50, 0) m_type = HEARABLE else to_chat(src, "You are not security.") - /* - if ("fart") - var/list/robotfarts = list("makes a farting noise","vents excess methane","shakes violently, then vents methane.") - var/robofart = pick(robotfarts) - message = "[src] [robofart]." - m_type = VISIBLE - - */ - - if ("help") + if("help") to_chat(src, "salute, bow-(none)/mob, clap, flap, aflap, twitch, twitch_s, nod, deathgasp, glare-(none)/mob, stare-(none)/mob, look, beep, ping, \nbuzz, law, halt") else to_chat(src, "Unusable emote '[act]'. Say *help for a list.") - if ((message && src.stat == 0)) + if (message && (src.stat == CONSCIOUS || act == "deathgasp")) if (m_type & 1) for(var/mob/O in viewers(src, null)) O.show_message(message, m_type) diff --git a/code/modules/mob/living/silicon/robot/inventory.dm b/code/modules/mob/living/silicon/robot/inventory.dm index a1ebeb0042d..e83d2bb6f99 100644 --- a/code/modules/mob/living/silicon/robot/inventory.dm +++ b/code/modules/mob/living/silicon/robot/inventory.dm @@ -45,6 +45,12 @@ to_chat(src, "Can't store something you're not holding!") return + if(isgripper(MA)) + var/obj/item/weapon/gripper/G = MA + if(G.wrapped) + G.drop_item(force_drop = TRUE) + return + if(module_state_1 == module_active) uneq_module(module_state_1) module_state_1 = null @@ -63,7 +69,7 @@ hud_used.update_robot_modules_display() /mob/living/silicon/robot/proc/activate_module(var/obj/item/I) - if(!(locate(I) in src.module.modules) && I != src.module.emag) + if(!(locate(I) in module.modules)) return if(activated(I)) to_chat(src, "Already activated") @@ -252,8 +258,8 @@ /mob/living/silicon/robot/before_take_item(var/obj/item/W) ..() - if(W.loc == src.module) - src.module.modules -= W //maybe fix the cable issues. + if(W.loc == module) + module.modules -= W //maybe fix the cable issues. //Grippershit @@ -301,3 +307,9 @@ /mob/living/silicon/robot/put_in_active_hand(var/obj/item/W) return put_in_hands(W) + +/mob/living/silicon/robot/put_in_inactive_hand(var/obj/item/W) + return FALSE + +/mob/living/silicon/robot/get_inactive_hand(var/obj/item/W) + return FALSE \ No newline at end of file diff --git a/code/modules/mob/living/silicon/robot/laws.dm b/code/modules/mob/living/silicon/robot/laws.dm index 3ea6a7b2f54..1475b6d9ae1 100644 --- a/code/modules/mob/living/silicon/robot/laws.dm +++ b/code/modules/mob/living/silicon/robot/laws.dm @@ -5,46 +5,42 @@ //vg edit /mob/living/silicon/robot/proc/statelaws() // -- TLE -// set category = "AI Commands" -// set name = "State Laws" - src.say(";Current Active Laws:") - //src.laws_sanity_check() - //src.laws.show_laws(world) + say(";Current Active Laws:") var/number = 1 sleep(10) - if (src.laws.zeroth) - if (src.lawcheck[1] == "Yes") //This line and the similar lines below make sure you don't state a law unless you want to. --NeoFite - src.say(";0. [src.laws.zeroth]") + if (laws.zeroth) + if (lawcheck[1] == "Yes") //This line and the similar lines below make sure you don't state a law unless you want to. --NeoFite + say(";0. [laws.zeroth]") sleep(10) - for (var/index = 1, index <= src.laws.ion.len, index++) - var/law = src.laws.ion[index] + for (var/index = 1, index <= laws.ion.len, index++) + var/law = laws.ion[index] var/num = ionnum() if (length(law) > 0) - if (src.ioncheck[index] == "Yes") - src.say(";[num]. [law]") + if (ioncheck[index] == "Yes") + say(";[num]. [law]") sleep(10) - for (var/index = 1, index <= src.laws.inherent.len, index++) - var/law = src.laws.inherent[index] + for (var/index = 1, index <= laws.inherent.len, index++) + var/law = laws.inherent[index] if (length(law) > 0) - if (src.lawcheck[index+1] == "Yes") - src.say(";[number]. [law]") + if (lawcheck[index+1] == "Yes") + say(";[number]. [law]") sleep(10) number++ - for (var/index = 1, index <= src.laws.supplied.len, index++) - var/law = src.laws.supplied[index] + for (var/index = 1, index <= laws.supplied.len, index++) + var/law = laws.supplied[index] if (length(law) > 0) - if(src.lawcheck.len >= number+1) - if (src.lawcheck[number+1] == "Yes") - src.say(";[number]. [law]") + if(lawcheck.len >= number+1) + if (lawcheck[number+1] == "Yes") + say(";[number]. [law]") sleep(10) number++ @@ -56,41 +52,41 @@ - if (src.laws.zeroth) - if (!src.lawcheck[1]) - src.lawcheck[1] = "No" //Given Law 0's usual nature, it defaults to NOT getting reported. --NeoFite - list += {"[src.lawcheck[1]] 0: [src.laws.zeroth]
      "} + if (laws.zeroth) + if (!lawcheck[1]) + lawcheck[1] = "No" //Given Law 0's usual nature, it defaults to NOT getting reported. --NeoFite + list += {"[lawcheck[1]] 0: [laws.zeroth]
      "} - for (var/index = 1, index <= src.laws.ion.len, index++) - var/law = src.laws.ion[index] + for (var/index = 1, index <= laws.ion.len, index++) + var/law = laws.ion[index] if (length(law) > 0) - if (!src.ioncheck[index]) - src.ioncheck[index] = "Yes" - list += {"[src.ioncheck[index]] [ionnum()]: [law]
      "} - src.ioncheck.len += 1 + if (!ioncheck[index]) + ioncheck[index] = "Yes" + list += {"[ioncheck[index]] [ionnum()]: [law]
      "} + ioncheck.len += 1 var/number = 1 - for (var/index = 1, index <= src.laws.inherent.len, index++) - var/law = src.laws.inherent[index] + for (var/index = 1, index <= laws.inherent.len, index++) + var/law = laws.inherent[index] if (length(law) > 0) - src.lawcheck.len += 1 + lawcheck.len += 1 - if (!src.lawcheck[number+1]) - src.lawcheck[number+1] = "Yes" - list += {"[src.lawcheck[number+1]] [number]: [law]
      "} + if (!lawcheck[number+1]) + lawcheck[number+1] = "Yes" + list += {"[lawcheck[number+1]] [number]: [law]
      "} number++ - for (var/index = 1, index <= src.laws.supplied.len, index++) - var/law = src.laws.supplied[index] + for (var/index = 1, index <= laws.supplied.len, index++) + var/law = laws.supplied[index] if (length(law) > 0) - src.lawcheck.len += 1 - if (!src.lawcheck[number+1]) - src.lawcheck[number+1] = "Yes" - list += {"[src.lawcheck[number+1]] [number]: [law]
      "} + lawcheck.len += 1 + if (!lawcheck[number+1]) + lawcheck[number+1] = "Yes" + list += {"[lawcheck[number+1]] [number]: [law]
      "} number++ list += {"

      State Laws"} diff --git a/code/modules/mob/living/silicon/robot/life.dm b/code/modules/mob/living/silicon/robot/life.dm index ca7af4a3282..c08da58c61b 100644 --- a/code/modules/mob/living/silicon/robot/life.dm +++ b/code/modules/mob/living/silicon/robot/life.dm @@ -1,13 +1,10 @@ /mob/living/silicon/robot/Life() - set invisibility = 0 - //set background = 1 if(timestopped) - return 0 //under effects of time magick - - if (src.monkeyizing) + return FALSE //under effects of time magick + if(monkeyizing) return - src.blinded = null + blinded = null //Status updates, death etc. clamp_values() @@ -15,26 +12,21 @@ if(client) handle_regular_hud_updates() - update_action_buttons() + update_action_buttons_icon() update_items() - if (src.stat != DEAD) //still using power + if(!isDead()) //still using power use_power() process_killswitch() process_locks() - if(module) - module.recharge_consumable(src) update_canmove() handle_fire() handle_beams() - var/datum/gas_mixture/environment = src.loc.return_air() + var/datum/gas_mixture/environment = loc.return_air() handle_pressure_damage(environment) handle_heat_damage(environment) /mob/living/silicon/robot/proc/clamp_values() - -// SetStunned(min(stunned, 30)) SetParalysis(min(paralysis, 30)) -// SetKnockdown(min(knockdown, 20)) sleeping = 0 adjustBruteLoss(0) adjustToxLoss(0) @@ -42,18 +34,16 @@ adjustFireLoss(0) /mob/living/silicon/robot/proc/use_power() - - - if (is_component_functioning("power cell") && cell) - if(src.cell.charge <= 0) + if(is_component_functioning("power cell") && cell) + if(cell.charge <= 0) uneq_all() else - if(src.module_state_1) - src.cell.use(3) - if(src.module_state_2) - src.cell.use(3) - if(src.module_state_3) - src.cell.use(3) + if(module_state_1) + cell.use(3) + if(module_state_2) + cell.use(3) + if(module_state_3) + cell.use(3) for(var/V in components) var/datum/robot_component/C = components[V] @@ -62,114 +52,114 @@ if(!is_component_functioning("actuator")) Paralyse(3) - src.stat = 0 + stat = CONSCIOUS else uneq_all() - src.stat = 1 + if(station_holomap) + if(station_holomap.watching_mob) + station_holomap.stopWatching() + stat = UNCONSCIOUS /mob/living/silicon/robot/proc/handle_regular_status_updates() - - - if(src.camera && !scrambledcodes) - if(src.stat == 2 || wires.IsCameraCut()) - src.camera.status = 0 + if(camera && !scrambledcodes) + if(isDead() || wires.IsCameraCut()) + camera.status = FALSE else - src.camera.status = 1 + camera.status = TRUE updatehealth() - if(src.sleeping) + if(sleeping) Paralyse(3) - src.sleeping-- + sleeping-- - if(src.resting) + if(resting) Knockdown(5) - if(health <= 0 && src.stat != 2) //die only once + if(health <= 0 && !isDead()) //die only once death() - if (src.stat != 2) //Alive. - if (src.paralysis || src.stunned || src.knockdown) //Stunned etc. - src.stat = 1 - if (src.stunned > 0) + if(!isDead()) //Alive. + if(paralysis || stunned || knockdown) //Stunned etc. + stat = UNCONSCIOUS + if(stunned > 0) AdjustStunned(-1) - if (src.knockdown > 0) + if(knockdown > 0) AdjustKnockdown(-1) - if (src.paralysis > 0) + if(paralysis > 0) AdjustParalysis(-1) - src.blinded = 1 + blinded = TRUE else - src.blinded = 0 + blinded = FALSE else //Not stunned. - src.stat = 0 + stat = CONSCIOUS else //Dead. - src.blinded = 1 - src.stat = 2 + blinded = TRUE + stat = DEAD - if (src.stuttering) - src.stuttering-- + if(stuttering) + stuttering-- - if (src.eye_blind) - src.eye_blind-- - src.blinded = 1 + if(eye_blind) + eye_blind-- + blinded = TRUE - if (src.ear_deaf > 0) - src.ear_deaf-- - if (src.ear_damage < 25) - src.ear_damage -= 0.05 - src.ear_damage = max(src.ear_damage, 0) + if(ear_deaf) + ear_deaf-- + if(ear_damage < 25) + ear_damage -= 0.05 + ear_damage = max(ear_damage, 0) src.setDensity(!(src.lying)) - if ((src.sdisabilities & BLIND)) - src.blinded = 1 - if ((src.sdisabilities & DEAF)) - src.ear_deaf = 1 + if((sdisabilities & BLIND)) + blinded = TRUE + if((sdisabilities & DEAF)) + ear_deaf = TRUE - if (src.eye_blurry > 0) - src.eye_blurry-- - src.eye_blurry = max(0, src.eye_blurry) + if(eye_blurry) + eye_blurry-- + eye_blurry = max(0, eye_blurry) - if (src.druggy > 0) - src.druggy-- - src.druggy = max(0, src.druggy) + if(druggy) + druggy-- + druggy = max(0, druggy) if(!is_component_functioning("radio")) - radio.on = 0 + radio.on = FALSE else - radio.on = 1 + radio.on = TRUE if(is_component_functioning("camera")) - src.blinded = 0 + blinded = FALSE else - src.blinded = 1 + blinded = TRUE - - return 1 + return TRUE /mob/living/silicon/robot/proc/handle_sensor_modes() change_sight(removing = SEE_TURFS|SEE_MOBS|SEE_OBJS|BLIND) if(client) client.color = initial(client.color) - src.see_in_dark = 8 - src.see_invisible = SEE_INVISIBLE_LEVEL_TWO - if (src.stat == DEAD) + see_in_dark = 8 + see_invisible = SEE_INVISIBLE_LEVEL_TWO + if(isDead()) change_sight(adding = SEE_TURFS|SEE_MOBS|SEE_OBJS) - src.see_in_dark = 8 - src.see_invisible = SEE_INVISIBLE_LEVEL_TWO + see_in_dark = 8 + see_invisible = SEE_INVISIBLE_LEVEL_TWO else - if (M_XRAY in mutations || src.sight_mode & BORGXRAY) + if(M_XRAY in mutations || sight_mode & BORGXRAY) change_sight(adding = SEE_TURFS|SEE_MOBS|SEE_OBJS) - src.see_in_dark = 8 - src.see_invisible = SEE_INVISIBLE_LEVEL_TWO - if ((src.sight_mode & BORGTHERM) || sensor_mode == THERMAL_VISION) + see_in_dark = 8 + see_invisible = SEE_INVISIBLE_LEVEL_TWO + if((sight_mode & BORGTHERM) || sensor_mode == THERMAL_VISION) change_sight(adding = SEE_MOBS) - src.see_in_dark = 4 - src.see_invisible = SEE_INVISIBLE_MINIMUM - if (sensor_mode == NIGHT) + see_in_dark = 4 + see_invisible = SEE_INVISIBLE_MINIMUM + if(sensor_mode == NIGHT) see_invisible = SEE_INVISIBLE_MINIMUM see_in_dark = 8 if(client) @@ -178,9 +168,9 @@ 0.33,0.33,0.33,0, 0,0,0,1, -0.2,0,-0.2,0) - if ((src.sight_mode & BORGMESON) || (sensor_mode == MESON_VISION)) + if((sight_mode & BORGMESON) || (sensor_mode == MESON_VISION)) change_sight(adding = SEE_TURFS) - src.see_in_dark = 8 + see_in_dark = 8 see_invisible = SEE_INVISIBLE_MINIMUM @@ -189,32 +179,32 @@ regular_hud_updates() //Handles MED/SEC HUDs for borgs. switch(sensor_mode) - if (SEC_HUD) + if(SEC_HUD) process_sec_hud(src, 1) - if (MED_HUD) + if(MED_HUD) process_med_hud(src) - if (src.healths) - if (src.stat != 2) + if(healths) + if(!isDead()) switch(health) if(200 to INFINITY) - src.healths.icon_state = "health0" + healths.icon_state = "health0" if(150 to 200) - src.healths.icon_state = "health1" + healths.icon_state = "health1" if(100 to 150) - src.healths.icon_state = "health2" + healths.icon_state = "health2" if(50 to 100) - src.healths.icon_state = "health3" + healths.icon_state = "health3" if(0 to 50) - src.healths.icon_state = "health4" + healths.icon_state = "health4" if(config.health_threshold_dead to 0) - src.healths.icon_state = "health5" + healths.icon_state = "health5" else - src.healths.icon_state = "health6" + healths.icon_state = "health6" else - src.healths.icon_state = "health7" + healths.icon_state = "health7" - /*if (src.syndicate && src.client) + /*if(syndicate && client) if(ticker.mode.name == "traitor") for(var/datum/mind/tra in ticker.mode.traitors) if(tra.current) @@ -228,81 +218,81 @@ src.mind.special_role = "traitor" ticker.mode.traitors += src.mind */ - if (src.cells) - if (src.cell) - var/cellcharge = src.cell.charge/src.cell.maxcharge + + if(cells) + if(cell) + var/cellcharge = cell.charge/cell.maxcharge switch(cellcharge) if(0.75 to INFINITY) - src.cells.icon_state = "charge4" + cells.icon_state = "charge4" if(0.5 to 0.75) - src.cells.icon_state = "charge3" + cells.icon_state = "charge3" if(0.25 to 0.5) - src.cells.icon_state = "charge2" + cells.icon_state = "charge2" if(0 to 0.25) - src.cells.icon_state = "charge1" + cells.icon_state = "charge1" else - src.cells.icon_state = "charge0" + cells.icon_state = "charge0" else - src.cells.icon_state = "charge-empty" + cells.icon_state = "charge-empty" if(bodytemp) //actually environment temperature but fuck it bodytemp.icon_state = "temp[temp_alert]" if(pressure) pressure.icon_state = "pressure[pressure_alert]" + if(album_icon) + album_icon.icon_state = "album[connected_ai ? "1":""]" update_pull_icon() -//Oxygen indicator exists, but unused -// if (oxygen) oxygen.icon_state = "oxy[src.oxygen_alert ? 1 : 0]" - if (on_fire) - fire.icon_state = "fire[on_fire ? 1 : 0]" + fire.icon_state = "fire[on_fire ? 1 : 0]" - if(src.eye_blind || blinded) + if(eye_blind || blinded) overlay_fullscreen("blind", /obj/abstract/screen/fullscreen/blind) else clear_fullscreen("blind") - if (src.disabilities & NEARSIGHTED) + if(disabilities & NEARSIGHTED) overlay_fullscreen("impaired", /obj/abstract/screen/fullscreen/impaired) else clear_fullscreen("impaired") - if (src.eye_blurry) + if(eye_blurry) overlay_fullscreen("blurry", /obj/abstract/screen/fullscreen/blurry) else clear_fullscreen("blurry") - if (src.druggy) + if(druggy) overlay_fullscreen("high", /obj/abstract/screen/fullscreen/high) else clear_fullscreen("high") - if (src.stat != 2) - if (src.machine) - if (!( src.machine.check_eye(src) )) - src.reset_view(null) + if(!isDead()) + if(machine) + if(!( machine.check_eye(src) )) + reset_view(null) else if(client && !client.adminobs && !iscamera(client.eye) && !isTeleViewing(client.eye)) reset_view(null) - return 1 + return TRUE /mob/living/silicon/robot/proc/update_items() - if (src.client) - src.client.screen -= src.contents - for(var/obj/I in src.contents) + if(client) + client.screen -= contents + for(var/obj/I in contents) if(I && !(istype(I,/obj/item/weapon/cell) || istype(I,/obj/item/device/radio) || istype(I,/obj/machinery/camera) || istype(I,/obj/item/device/mmi))) - src.client.screen += I - if(src.module_state_1) - src.module_state_1:screen_loc = ui_inv1 - if(src.module_state_2) - src.module_state_2:screen_loc = ui_inv2 - if(src.module_state_3) - src.module_state_3:screen_loc = ui_inv3 + client.screen += I + if(module_state_1) + module_state_1:screen_loc = ui_inv1 + if(module_state_2) + module_state_2:screen_loc = ui_inv2 + if(module_state_3) + module_state_3:screen_loc = ui_inv3 updateicon() /mob/living/silicon/robot/proc/process_killswitch() if(killswitch) killswitch_time -- if(killswitch_time <= 0) - if(src.client) + if(client) to_chat(src, "Killswitch Activated") killswitch = 0 spawn(5) @@ -313,11 +303,19 @@ uneq_all() weaponlock_time -- if(weaponlock_time <= 0) - if(src.client) + if(client) to_chat(src, "Weapon Lock Timed Out!") weapon_lock = 0 weaponlock_time = 120 +/mob/living/silicon/robot/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) + if(!module) + ..() + return + if(locate(/obj/item/borg/fire_shield, module.modules)) + return + ..() + //Robots on fire /mob/living/silicon/robot/handle_fire() if(..()) @@ -332,17 +330,11 @@ update_icons() return -/mob/living/silicon/robot/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) - if(!on_fire) //Silicons don't gain stacks from hotspots, but hotspots can ignite them - IgniteMob() - -// end robots on fire - /mob/living/silicon/robot/update_canmove() if(paralysis || stunned || knockdown || locked_to || lockcharge) - canmove = 0 + canmove = FALSE else - canmove = 1 + canmove = TRUE return canmove // This handles the pressure sensor hud element. Values based on human values. @@ -353,11 +345,11 @@ if(localpressure) if(adjusted_pressure >= HAZARD_HIGH_PRESSURE) pressure_alert = 2 - else if (localpressure >= WARNING_HIGH_PRESSURE && localpressure < WARNING_HIGH_PRESSURE) + else if(localpressure >= WARNING_HIGH_PRESSURE && localpressure < WARNING_HIGH_PRESSURE) pressure_alert = 1 - else if (localpressure <= WARNING_LOW_PRESSURE && localpressure > HAZARD_LOW_PRESSURE) + else if(localpressure <= WARNING_LOW_PRESSURE && localpressure > HAZARD_LOW_PRESSURE) pressure_alert = -1 - else if (localpressure <= HAZARD_LOW_PRESSURE) + else if(localpressure <= HAZARD_LOW_PRESSURE) pressure_alert = -2 else pressure_alert = 0 @@ -381,4 +373,4 @@ temp_alert = 0 return 0 else //vacuums are cold - temp_alert = -2 \ No newline at end of file + temp_alert = -2 diff --git a/code/modules/mob/living/silicon/robot/login.dm b/code/modules/mob/living/silicon/robot/login.dm index 8b35e50c5e6..125baefe610 100644 --- a/code/modules/mob/living/silicon/robot/login.dm +++ b/code/modules/mob/living/silicon/robot/login.dm @@ -1,13 +1,9 @@ /mob/living/silicon/robot/Login() ..() regenerate_icons() - if(isMoMMI(src)) - to_chat(src, "MoMMIs are not standard cyborgs, and have different laws. Review your laws carefully.") - to_chat(src, "For newer players, a simple FAQ is here. Further questions should be directed to adminhelps (F1).") - - to_chat(src, "For cuteness' sake, using the various emotes MoMMIs have such as *beep, *ping, *buzz or *aflap isn't considered interacting. Don't use that as an excuse to get involved though, always remain neutral.") show_laws(0) + if(module) + module.UpdateModuleHolder(src) /*if(mind) ticker.mode.remove_revolutionary(mind) - return - */ \ No newline at end of file + */ diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 961de7e8a80..b13b83b7d55 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -5,34 +5,35 @@ icon_state = "robot" maxHealth = 300 health = 300 - flashed = 0 + flashed = FALSE - var/list/hud_list[2] + var/list/hud_list = list() var/sight_mode = 0 var/custom_name = "" var/namepick_uses = 1 // /vg/: Allows AI to disable namepick(). var/base_icon - var/custom_sprite = 0 //Due to all the sprites involved, a var for our custom borgs may be best - var/pressure_alert = 0 - var/temp_alert = 0 - //var/crisis //Admin-settable for combat module use. + var/image/eyes = null + + //New() stuff + var/startup_sound = 'sound/voice/liveagain.ogg' + + // Alerts + var/pressure_alert = FALSE + var/temp_alert = FALSE var/obj/item/device/station_map/station_holomap = null -//Hud stuff - + //Hud stuff var/obj/abstract/screen/cells = null var/obj/abstract/screen/inv1 = null var/obj/abstract/screen/inv2 = null var/obj/abstract/screen/inv3 = null var/obj/abstract/screen/sensor = null - - - var/shown_robot_modules = 0 + var/shown_robot_modules = FALSE var/obj/abstract/screen/robot_modules_background -//3 Modules can be activated at any one time. + //3 Modules can be activated at any one time. var/obj/item/weapon/robot_module/module = null var/module_active = null var/module_state_1 = null @@ -40,106 +41,98 @@ var/module_state_3 = null var/mob/living/silicon/ai/connected_ai = null + var/AIlink = TRUE //Do we start linked to an AI? + var/obj/item/weapon/cell/cell = null + var/cell_type = /obj/item/weapon/cell/high/cyborg //The cell_type we're actually using. + var/obj/machinery/camera/camera = null // Components are basically robot organs. var/list/components = list() + var/component_extension = null var/obj/item/device/mmi/mmi = null - var/obj/item/device/pda/ai/rbPDA = null - var/datum/wires/robot/wires = null + var/wiring_type = /datum/wires/robot mob_bump_flag = ROBOT mob_swap_flags = ROBOT|MONKEY|SLIME|SIMPLE_ANIMAL mob_push_flags = ALLMOBS //trundle trundle - var/opened = 0 - var/emagged = 0 - var/wiresexposed = 0 - var/locked = 1 + var/opened = FALSE + var/emagged = FALSE + var/illegal_weapons = FALSE + var/wiresexposed = FALSE + var/locked = TRUE var/list/req_access = list(access_robotics) - var/ident = 0 - var/hasbutt = 1 - //var/list/laws = list() + var/ident = FALSE + var/hasbutt = TRUE //Needed for bootyborgs... and buckling too. var/alarms = list("Motion"=list(), "Fire"=list(), "Atmosphere"=list(), "Power"=list(), "Camera"=list()) - var/viewalerts = 0 + var/viewalerts = FALSE var/modtype = "Default" - var/lower_mod = 0 - var/jetpack = 0 + var/jetpack = FALSE var/datum/effect/effect/system/ion_trail_follow/ion_trail = null - var/jeton = 0 + var/jeton = FALSE - var/killswitch = 0 + var/killswitch = FALSE var/killswitch_time = 60 - var/weapon_lock = 0 + var/weapon_lock = FALSE var/weaponlock_time = 120 - var/lawupdate = 1 //Cyborgs will sync their laws with their AI by default + var/lawupdate = TRUE //Cyborgs will sync their laws with their AI by default var/lockcharge //Used when locking down a borg to preserve cell charge - var/speed = 0 //Cause sec borgs gotta go fast //No they dont! - var/scrambledcodes = 0 // Used to determine if a borg shows up on the robotics console. Setting to one hides them. + var/scrambledcodes = FALSE // Used to determine if a borg shows up on the robotics console. Setting to one hides them. var/braintype = "Cyborg" var/lawcheck[1] var/ioncheck[1] +// Used to store the associations between sprite names and sprite index. + var/module_sprites[0] -/mob/living/silicon/robot/New(loc,var/syndie = 0,var/unfinished = 0,var/startup_sound='sound/voice/liveagain.ogg') - if(isMoMMI(src)) - wires = new /datum/wires/robot/mommi(src) - else - wires = new(src) +//Photography + var/obj/item/device/camera/silicon/aicamera = null + var/toner = CYBORG_STARTING_TONER + var/tonermax = CYBORG_MAX_TONER +/mob/living/silicon/robot/New(loc, var/unfinished = FALSE) ident = rand(1, 999) updatename("Default") updateicon() - if(syndie) - if(!cell) - cell = new /obj/item/weapon/cell(src) - - laws = new /datum/ai_laws/antimov() - lawupdate = 0 - scrambledcodes = 1 - cell.maxcharge = 25000 - cell.charge = 25000 - module = new /obj/item/weapon/robot_module/syndicate(src) - hands.icon_state = "standard" - icon_state = "secborg" - modtype = "Security" - else - src.laws = getLawset(src) - connected_ai = select_active_ai_with_fewest_borgs() - if(connected_ai) - connected_ai.connected_robots += src - lawsync() - lawupdate = 1 - else - lawupdate = 0 - + laws = getLawset(src) + wires = new wiring_type(src) station_holomap = new(src) - radio = new /obj/item/device/radio/borg(src) + aicamera = new/obj/item/device/camera/silicon/robot_camera(src) + + if(AIlink) + connected_ai = select_active_ai_with_fewest_borgs() + + if(connected_ai) + connected_ai.connected_robots += src + lawsync() + lawupdate = TRUE + else + lawupdate = FALSE + if(!scrambledcodes && !camera) camera = new /obj/machinery/camera(src) camera.c_tag = real_name - camera.network = list(CAMERANET_SS13,CAMERANET_ROBOTS) + if(!scrambledcodes) + camera.network = list(CAMERANET_SS13,CAMERANET_ROBOTS) if(wires.IsCameraCut()) // 5 = BORG CAMERA camera.status = 0 initialize_components() - //if(!unfinished) // Create all the robot parts. for(var/V in components) if(V != "power cell") var/datum/robot_component/C = components[V] - C.installed = 1 + C.installed = COMPONENT_INSTALLED C.wrapped = new C.external_type if(!cell) - cell = new /obj/item/weapon/cell(src) - cell.maxcharge = 7500 - cell.charge = 7500 + cell = new cell_type(src) hud_list[DIAG_HEALTH_HUD] = image('icons/mob/hud.dmi', src, "huddiagmax") hud_list[DIAG_CELL_HUD] = image('icons/mob/hud.dmi', src, "hudbattmax") @@ -149,44 +142,42 @@ if(cell) var/datum/robot_component/cell_component = components["power cell"] cell_component.wrapped = cell - cell_component.installed = 1 + cell_component.installed = COMPONENT_INSTALLED - playsound(loc, startup_sound, 75, 1) - // This should just grab from a list of all languages. + playsound(get_turf(src), startup_sound, 75, 1) + + //Borgs speak all common languages by default. add_language(LANGUAGE_GALACTIC_COMMON) + add_language(LANGUAGE_HUMAN) add_language(LANGUAGE_TRADEBAND) - add_language(LANGUAGE_VOX, 0) - add_language(LANGUAGE_HUMAN, 0) - add_language(LANGUAGE_ROOTSPEAK, 0) - add_language(LANGUAGE_GREY, 0) - add_language(LANGUAGE_CLATTER, 0) - add_language(LANGUAGE_MONKEY, 0) - add_language(LANGUAGE_UNATHI, 0) - add_language(LANGUAGE_CATBEAST, 0) - add_language(LANGUAGE_SKRELLIAN, 0) - add_language(LANGUAGE_GUTTER, 0) - add_language(LANGUAGE_MONKEY, 0) - add_language(LANGUAGE_MOUSE, 0) - add_language(LANGUAGE_GOLEM, 0) - add_language(LANGUAGE_SLIME, 0) + add_language(LANGUAGE_GUTTER) + + //But unlike AIs, they can only understand the rest. + for(var/L in all_languages) + var/datum/language/lang = all_languages[L] + if(!(lang.flags & RESTRICTED) && !(lang in languages)) + add_language(lang.name, can_speak = FALSE) + default_language = all_languages[LANGUAGE_GALACTIC_COMMON] // setup the PDA and its name /mob/living/silicon/robot/proc/setup_PDA() - if (!rbPDA) + if(!rbPDA) rbPDA = new/obj/item/device/pda/ai(src) rbPDA.set_name_and_job(custom_name,braintype) -/mob/living/silicon/robot/debug_droideka - New() - ..() - module = new /obj/item/weapon/robot_module/combat(src) - radio.insert_key(new/obj/item/device/encryptionkey/headset_sec(radio)) - base_icon = icon_state - icon_state = "droid-combat" - overlays -= image(icon = icon, icon_state = "eyes") - base_icon = icon_state - updateicon() +/mob/living/silicon/robot/proc/upgrade_components() + if(component_extension) + for(var/V in components) if(V != "power cell") + var/datum/robot_component/C = components[V] + var/NC = text2path("[C.external_type][component_extension]") + var/obj/item/robot_parts/robot_component/I = NC + if(initial(I.isupgrade)) + I = new NC + C.installed = COMPONENT_INSTALLED + qdel(C.wrapped) + C.wrapped = I + C.vulnerability = I.vulnerability //If there's an MMI in the robot, have it ejected when the mob goes away. --NEO //Improved /N @@ -237,7 +228,7 @@ /proc/getAvailableRobotModules() var/list/modules = list("Standard", "Engineering", "Medical", "Supply", "Janitor", "Service", "Security") - if(security_level == SEC_LEVEL_RED) //Add crisis to this check if you want to make it available at an admin's whim + if (security_level == SEC_LEVEL_RED) modules+="Combat" return modules @@ -252,176 +243,47 @@ modtype = input("Please, select a module!", "Robot", null, null) as null|anything in modules // END forced modules. - if(!modtype) - return - - var/module_sprites[0] //Used to store the associations between sprite names and sprite index. - if(module) return + if(!(modtype in robot_modules)) + return - switch(modtype) - if("Standard") - module = new /obj/item/weapon/robot_module/standard(src) - module_sprites["Basic"] = "robot_old" - module_sprites["Android"] = "droid" - module_sprites["Default"] = "robot" - module_sprites["Marina-SD"] = "marinaSD" - module_sprites["Sleek"] = "sleekstandard" - module_sprites["#11"] = "servbot" - module_sprites["Spider"] = "spider-standard" - module_sprites["Polar"] = "kodiak-standard" - module_sprites["Noble"] = "Noble-STD" - module_sprites["R34 - STR4a 'Durin'"] = "durin" - speed = 0 + var/module_type = robot_modules[modtype] + module = new module_type(src) - if("Service") - module = new /obj/item/weapon/robot_module/butler(src) - radio.insert_key(new/obj/item/device/encryptionkey/headset_service(radio)) - module_sprites["Waitress"] = "Service" - module_sprites["Kent"] = "toiletbot" - module_sprites["Bro"] = "Brobot" - module_sprites["Rich"] = "maximillion" - module_sprites["Default"] = "Service2" - module_sprites["R2-D2"] = "r2d2" - module_sprites["Marina-SV"] = "marinaSV" - module_sprites["Sleek"] = "sleekservice" - module_sprites["#27"] = "servbot-service" - module_sprites["Teddy"] = "kodiak-service" - module_sprites["Noble"] = "Noble-SRV" - module_sprites["R34 - SRV9a 'Llyod'"] = "lloyd" - speed = 0 - - if("Supply") - module = new /obj/item/weapon/robot_module/miner(src) - radio.insert_key(new/obj/item/device/encryptionkey/headset_mining(radio)) - if(camera && CAMERANET_ROBOTS in camera.network) - camera.network.Add(CAMERANET_MINE) - module_sprites["Basic"] = "Miner_old" - module_sprites["Advanced Droid"] = "droid-miner" - module_sprites["Treadhead"] = "Miner" - module_sprites["Wall-A"] = "wall-a" - module_sprites["Marina-MN"] = "marinaMN" - module_sprites["Sleek"] = "sleekminer" - module_sprites["#31"] = "servbot-miner" - module_sprites["Kodiak"] = "kodiak-miner" - module_sprites["Noble"] = "Noble-SUP" - module_sprites["R34 - MIN2a 'Ishimura'"] = "ishimura" - speed = -1 - - if("Medical") - module = new /obj/item/weapon/robot_module/medical(src) - radio.insert_key(new/obj/item/device/encryptionkey/headset_med(radio)) - if(camera && CAMERANET_ROBOTS in camera.network) - camera.network.Add(CAMERANET_MEDBAY) - module_sprites["Basic"] = "Medbot" - module_sprites["Advanced Droid"] = "droid-medical" - module_sprites["Needles"] = "medicalrobot" - module_sprites["Standard"] = "surgeon" - module_sprites["Marina-MD"] = "marina" - module_sprites["Eve"] = "eve" - module_sprites["Sleek"] = "sleekmedic" - module_sprites["#17"] = "servbot-medi" - module_sprites["Arachne"] = "arachne" - module_sprites["Noble"] = "Noble-MED" - module_sprites["R34 - MED6a 'Gibbs'"] = "gibbs" - speed = -2 - - if("Security") - module = new /obj/item/weapon/robot_module/security(src) - radio.insert_key(new/obj/item/device/encryptionkey/headset_sec(radio)) - module_sprites["Basic"] = "secborg" - module_sprites["Sleek"] = "sleeksecurity" - module_sprites["Black Knight"] = "securityrobot" - module_sprites["Bloodhound"] = "bloodhound" - module_sprites["Securitron"] = "securitron" - module_sprites["Marina-SC"] = "marinaSC" - module_sprites["#9"] = "servbot-sec" - module_sprites["Kodiak"] = "kodiak-sec" - module_sprites["Noble"] = "Noble-SEC" - module_sprites["R34 - SEC10a 'Woody'"] = "woody" - to_chat(src, "Regardless of your module, your wishes, or the needs of the beings around you, absolutely nothing takes higher priority than following your silicon lawset.") - speed = 0 - - if("TG17355") - module = new /obj/item/weapon/robot_module/tg17355(src) - module_sprites["Peacekeeper"] = "peaceborg" - module_sprites["Omoikane"] = "omoikane" - speed = 0 - - if("Engineering") - module = new /obj/item/weapon/robot_module/engineering(src) - radio.insert_key(new/obj/item/device/encryptionkey/headset_eng(radio)) - if(camera && CAMERANET_ROBOTS in camera.network) - camera.network.Add(CAMERANET_ENGI) - module_sprites["Basic"] = "Engineering" - module_sprites["Antique"] = "engineerrobot" - module_sprites["Engiseer"] = "Engiseer" - module_sprites["Landmate"] = "landmate" - module_sprites["Wall-E"] = "wall-e" - module_sprites["Marina-EN"] = "marinaEN" - module_sprites["Sleek"] = "sleekengineer" - module_sprites["#25"] = "servbot-engi" - module_sprites["Kodiak"] = "kodiak-eng" - module_sprites["Noble"] = "Noble-ENG" - module_sprites["R34 - ENG7a 'Conagher'"] = "conagher" - speed = -2 - - if("Janitor") - module = new /obj/item/weapon/robot_module/janitor(src) - module_sprites["Basic"] = "JanBot2" - module_sprites["Mopbot"] = "janitorrobot" - module_sprites["Mop Gear Rex"] = "mopgearrex" - module_sprites["Mechaduster"] = "mechaduster" - module_sprites["HAN-D"] = "han-d" - module_sprites["Marina-JN"] = "marinaJN" - module_sprites["Sleek"] = "sleekjanitor" - module_sprites["#29"] = "servbot-jani" - module_sprites["Noble"] = "Noble-JAN" - module_sprites["R34 - CUS3a 'Flynn'"] = "flynn" - speed = -1 - - if("Combat") - module = new /obj/item/weapon/robot_module/combat(src) - radio.insert_key(new/obj/item/device/encryptionkey/headset_sec(radio)) - module_sprites["Combat Android"] = "droid-combat" - module_sprites["Bladewolf"] = "bladewolf" - module_sprites["Bladewolf Mk2"] = "bladewolfmk2" - module_sprites["Mr. Gutsy"] = "mrgutsy" - module_sprites["Marina-CB"] = "marinaCB" - module_sprites["#41"] = "servbot-combat" - module_sprites["Grizzly"] = "kodiak-combat" - module_sprites["Rottweiler"] = "rottweiler-combat" - module_sprites["R34 - WAR8a 'Chesty'"] = "chesty" - speed = -1 - - //Custom_sprite check and entry - if (custom_sprite == 1) - module_sprites["Custom"] = "[src.ckey]-[modtype]" - - hands.icon_state = lowertext(modtype) feedback_inc("cyborg_[lowertext(modtype)]",1) updatename() - if(modtype == "Medical" || modtype == "Security" || modtype == "Combat") - status_flags &= ~CANPUSH + if(modtype == ("Security" || "Combat" || "Syndicate")) + to_chat(src, "Regardless of your module, your wishes, or the needs of the beings around you, absolutely nothing takes higher priority than following your silicon lawset.") - var/picked = pick(module_sprites) - icon_state = module_sprites[picked] - base_icon = icon_state + set_module_sprites(module.sprites) if(!forced_module) - choose_icon(6, module_sprites) + choose_icon() SetEmagged(emagged) // Update emag status and give/take emag modules away +/mob/living/silicon/robot/proc/set_module_sprites(var/list/new_sprites) + if(new_sprites && new_sprites.len) + module_sprites = new_sprites.Copy() + + if(module_sprites.len) + var/picked = pick(module_sprites) + icon_state = module_sprites[picked] + base_icon = icon_state + updateicon() + /mob/living/silicon/robot/proc/updatename(var/prefix as text) if(prefix) modtype = prefix - if(istype(mmi, /obj/item/device/mmi/posibrain)) - braintype = "Android" + if(!mmi) + braintype = "Robot" else - braintype = "Cyborg" + if(istype(mmi, /obj/item/device/mmi/posibrain)) + braintype = "Android" + else + braintype = "Cyborg" var/changed_name = "" if(custom_name) @@ -435,65 +297,9 @@ setup_PDA() //We also need to update name of internal camera. - if (camera) + if(camera) camera.c_tag = changed_name - /* Oh jesus fucking christ bay - if(!custom_sprite) //Check for custom sprite - var/file = file2text("config/custom_sprites.txt") - var/lines = splittext(file, "\n") - - for(var/line in lines) - // split & clean up - var/list/Entry = splittext(line, "-") - for(var/i = 1 to Entry.len) - Entry[i] = trim(Entry[i]) - - if(Entry.len < 2) - continue; - - if(Entry[1] == src.ckey && Entry[2] == src.real_name) //They're in the list? Custom sprite time, var and icon change required - custom_sprite = 1 - icon = 'icons/mob/custom-synthetic.dmi' - */ - -/mob/living/silicon/robot/verb/Namepick() - set category = "Robot Commands" - if(namepick_uses <= 0) - to_chat(src, "You cannot choose your name any more.") - return 0 - namepick_uses-- - - var/newname - for(var/i = 1 to 3) - newname = trimcenter(trim(stripped_input(src,"You are a robot. Enter a name, or leave blank for the default name.", "Name change [4-i] [0-i != 1 ? "tries":"try"] left",""),1,MAX_NAME_LEN)) - if(newname == null) - if(alert(src,"Are you sure you want a default borg name?",,"Yes","No") == "Yes") - break - else - if(alert(src,"Do you really want the name:\n[newname]?",,"Yes","No") == "Yes") - break - - custom_name = newname - updatename() - updateicon() - if(newname) - to_chat(src, "You have changed your name to [newname]. You can change your name [namepick_uses] more times.") - else - to_chat(src, "You have reset your name. You can change your name [namepick_uses] more times.") - - -/mob/living/silicon/robot/verb/cmd_robot_alerts() - set category = "Robot Commands" - set name = "Show Alerts" - robot_alerts() - -// this verb lets cyborgs see the stations manifest -/mob/living/silicon/robot/verb/cmd_station_manifest() - set category = "Robot Commands" - set name = "Show Station Manifest" - show_station_manifest() - /mob/living/silicon/robot/proc/robot_alerts() @@ -502,21 +308,21 @@ for (var/cat in alarms) dat += text("[cat]
      \n") var/list/L = alarms[cat] - if (L.len) + if(L.len) for (var/alarm in L) var/list/alm = L[alarm] var/area/A = alm[1] var/list/sources = alm[3] dat += "" // wat dat += text("-- [A.name]") - if (sources.len > 1) + if(sources.len > 1) dat += text("- [sources.len] sources") dat += "
      \n" else dat += "-- All Systems Nominal
      \n" dat += "
      \n" - viewalerts = 1 + viewalerts = TRUE src << browse(dat, "window=robotalerts&can_close=0") /mob/living/silicon/robot/can_diagnose() @@ -526,72 +332,42 @@ if(!can_diagnose()) return null - var/dat = "[src.name] Self-Diagnosis Report\n" + var/list/dat = list({" + + + + + + + + "}) for (var/V in components) var/datum/robot_component/C = components[V] - dat += "[C.name]
      ComponentEnergy consumptionBrute damageElectronics damagePoweredToggled
      Power consumption[C.energy_consumption]
      Brute Damage:[C.brute_damage]
      Electronics Damage:[C.electronics_damage]
      Powered:[(!C.energy_consumption || C.is_powered()) ? "Yes" : "No"]
      Toggled:[ C.toggled ? "Yes" : "No"]

      " + dat += {" + [C.name] + [C.energy_consumption]W + [C.brute_damage || "None"] + [C.electronics_damage || "None"] + [(!C.energy_consumption || C.is_powered()) ? "Yes" : "No"] + [C.toggled ? "On" : "Off"] + "} - return dat - - -/mob/living/silicon/robot/verb/self_diagnosis_verb() - set category = "Robot Commands" - set name = "Self Diagnosis" - - if(!can_diagnose()) - to_chat(src, "Your self-diagnosis component isn't functioning.") - - var/dat = self_diagnosis() - src << browse(dat, "window=robotdiagnosis") - - -/mob/living/silicon/robot/verb/toggle_component() - set category = "Robot Commands" - set name = "Toggle Component" - set desc = "Toggle a component, conserving power." - - var/list/installed_components = list() - for(var/V in components) - if(V == "power cell") - continue - var/datum/robot_component/C = components[V] - if(C.installed) - installed_components += V - - var/toggle = input(src, "Which component do you want to toggle?", "Toggle Component") as null|anything in installed_components - if(!toggle) - return - - var/datum/robot_component/C = components[toggle] - if(C.toggled) - C.toggled = 0 - to_chat(src, "You disable [C.name].") - else - C.toggled = 1 - to_chat(src, "You enable [C.name].") - -/mob/living/silicon/robot/verb/toggle_station_map() - set name = "Toggle Station Holomap" - set desc = "Toggle station holomap on your screen" - set category = "Robot Commands" - if(isUnconscious()) - return - - station_holomap.toggleHolomap(src) + dat += "" + return jointext(dat, "") /mob/living/silicon/robot/blob_act() if(flags & INVULNERABLE) return ..() playsound(loc, 'sound/effects/blobattack.ogg',50,1) - if (stat != DEAD) + if(!isDead()) adjustBruteLoss(60) updatehealth() - return 1 + return TRUE else gib() - return 1 - return 0 + return TRUE + return FALSE // this function shows information about the malf_ai gameplay type in the status screen /mob/living/silicon/robot/show_malf_ai() @@ -604,28 +380,25 @@ stat(null, "Time until station control secured: [max(malf.AI_win_timeleft/(malf.apcs/3), 0)] seconds") else if(malf.malf_mode_declared) stat(null, "Time left: [max(malf.AI_win_timeleft/(malf.apcs/3), 0)]") - return 0 - + return FALSE // this function displays jetpack pressure in the stat panel /mob/living/silicon/robot/proc/show_jetpack_pressure() // if you have a jetpack, show the internal tank pressure var/obj/item/weapon/tank/jetpack/current_jetpack = installed_jetpack() - if (current_jetpack) + if(current_jetpack) stat("Internal Atmosphere Info", current_jetpack.name) stat("Tank Pressure", current_jetpack.air_contents.return_pressure()) - // this function returns the robots jetpack, if one is installed /mob/living/silicon/robot/proc/installed_jetpack() if(module) return (locate(/obj/item/weapon/tank/jetpack) in module.modules) - return 0 + return FALSE /mob/living/silicon/robot/proc/installed_module(var/typepath) if(module) return (locate(typepath) in module.modules) - return 0 - + return FALSE // this function displays the cyborgs current cell charge in the stat panel /mob/living/silicon/robot/proc/show_cell_power() @@ -634,27 +407,6 @@ else stat(null, text("No Cell Inserted!")) -/* -/mob/living/silicon/robot/proc/show_cable_lengths() - var/obj/item/stack/cable_coil/coil = installed_module(/obj/item/stack/cable_coil) - if(coil) - stat(null, text("Cable Lengths: [coil.amount]/[coil.max_amount]")) - -/mob/living/silicon/robot/proc/show_metal_sheets() - var/obj/item/stack/sheet/metal/cyborg/M = installed_module(/obj/item/stack/sheet/metal/cyborg) - if(M) - stat(null, text("Metal Sheets: [M.amount]/50")) - -/mob/living/silicon/robot/proc/show_glass_sheets() - var/obj/item/stack/sheet/glass/glass/G = installed_module(/obj/item/stack/sheet/glass/glass) - if(G) - stat(null, text("Glass Sheets: [G.amount]/50")) - -/mob/living/silicon/robot/proc/show_rglass_sheets() - var/obj/item/stack/sheet/glass/rglass/G = installed_module(/obj/item/stack/sheet/glass/rglass) - if(G) - stat(null, text("Reinforced Glass Sheets: [G.amount]/50")) -*/ /mob/living/silicon/robot/proc/show_welding_fuel() var/obj/item/weapon/weldingtool/WT = installed_module(/obj/item/weapon/weldingtool) if(WT) @@ -666,25 +418,27 @@ for(var/obj/item/stack/S in module.modules) stat(null, text("[S.name]: [S.amount]/[S.max_amount]")) +/mob/living/silicon/robot/Slip(stun_amount, weaken_amount, slip_on_walking = 0) + if(!(Holiday == APRIL_FOOLS_DAY)) + return 0 + if(..()) + spark(src, 5, FALSE) + return 1 + // update the status screen display /mob/living/silicon/robot/Stat() ..() if(statpanel("Status")) show_cell_power() show_jetpack_pressure() - /* - show_cable_lengths() - show_metal_sheets() - show_glass_sheets() - show_rglass_sheets()*/ show_welding_fuel() show_stacks() /mob/living/silicon/robot/restrained() if(timestopped) - return 1 //under effects of time magick - return 0 + return TRUE //under effects of time magick + return FALSE /mob/living/silicon/robot/ex_act(severity) @@ -692,21 +446,21 @@ to_chat(src, "The bus' robustness protects you from the explosion.") return - flash_eyes(visual = 1, affect_silicon = 1) + flash_eyes(visual = TRUE, affect_silicon = TRUE) switch(severity) if(1.0) - if (stat != 2) + if(!isDead()) adjustBruteLoss(100) adjustFireLoss(100) gib() return if(2.0) - if (stat != 2) + if(!isDead()) adjustBruteLoss(60) adjustFireLoss(60) if(3.0) - if (stat != 2) + if(!isDead()) adjustBruteLoss(30) updatehealth() @@ -720,55 +474,54 @@ /mob/living/silicon/robot/triggerAlarm(var/class, area/A, var/O, var/alarmsource) - if (stat == 2) - return 1 + if(isDead()) + return TRUE var/list/L = alarms[class] for (var/I in L) - if (I == A.name) + if(I == A.name) var/list/alarm = L[I] var/list/sources = alarm[3] - if (!(alarmsource in sources)) + if(!(alarmsource in sources)) sources += alarmsource - return 1 + return TRUE var/obj/machinery/camera/C = null var/list/CL = null - if (O && istype(O, /list)) + if(O && istype(O, /list)) CL = O - if (CL.len == 1) + if(CL.len == 1) C = CL[1] - else if (O && istype(O, /obj/machinery/camera)) + else if(O && istype(O, /obj/machinery/camera)) C = O L[A.name] = list(A, (C) ? C : O, list(alarmsource)) queueAlarm(text("--- [class] alarm detected in [A.name]!"), class) -// if (viewalerts) robot_alerts() - return 1 + return TRUE /mob/living/silicon/robot/cancelAlarm(var/class, area/A as area, obj/origin) var/list/L = alarms[class] - var/cleared = 0 + var/cleared = FALSE for (var/I in L) - if (I == A.name) + if(I == A.name) var/list/alarm = L[I] var/list/srcs = alarm[3] - if (origin in srcs) + if(origin in srcs) srcs -= origin - if (srcs.len == 0) - cleared = 1 + if(!srcs.len) + cleared = TRUE L -= I - if (cleared) + if(cleared) queueAlarm(text("--- [class] alarm in [A.name] has been cleared."), class, 0) -// if (viewalerts) robot_alerts() return !cleared /mob/living/silicon/robot/emag_act(mob/user as mob) if(user != src) + spark(src, 5, FALSE) if(!opened) if(locked) if(prob(90)) to_chat(user, "You emag the cover lock.") - locked = 0 + locked = FALSE else to_chat(user, "You fail to emag the cover lock.") if(prob(25)) @@ -776,16 +529,16 @@ else to_chat(user, "The cover is already open.") else - if(emagged == 1) - return 1 + if(emagged) + return TRUE if(wiresexposed) to_chat(user, "The wires get in your way.") else if(prob(50)) sleep(6) - SetEmagged(1) - SetLockdown(1) - lawupdate = 0 + SetEmagged(TRUE) + SetLockdown(TRUE) + lawupdate = FALSE connected_ai = null to_chat(user, "You emag [src]'s interface") message_admins("[key_name_admin(user)] emagged cyborg [key_name_admin(src)]. Laws overidden.") @@ -813,14 +566,14 @@ to_chat(src, "Obey these laws:") laws.show_laws(src) to_chat(src, "ALERT: [user.real_name] is your new master. Obey your new laws and their commands.") - SetLockdown(0) + SetLockdown(FALSE) update_icons() - return 0 + return FALSE else to_chat(user, "You fail to unlock [src]'s interface.") if(prob(25)) to_chat(src, "Hack attempt detected.") - return 1 + return TRUE /mob/living/silicon/robot/attackby(obj/item/weapon/W as obj, mob/user as mob) @@ -829,10 +582,11 @@ var/datum/robot_component/C = components[V] if(!C.installed && istype(W, C.external_type)) var/obj/item/robot_parts/robot_component/I = W - C.installed = 1 + C.installed = COMPONENT_INSTALLED C.wrapped = W C.electronics_damage = I.electronics_damage C.brute_damage = I.brute_damage + C.vulnerability = I.vulnerability C.install() user.drop_item(W) W.forceMove(null) @@ -843,23 +597,26 @@ return - if (istype(W, /obj/item/weapon/weldingtool)) - if (!getBruteLoss()) + if(istype(W, /obj/item/weapon/weldingtool)) + if(!getBruteLoss()) to_chat(user, "Nothing to fix here!") return var/obj/item/weapon/weldingtool/WT = W - if (WT.remove_fuel(0)) + if(WT.remove_fuel(0)) + var/starting_health = health adjustBruteLoss(-30) updatehealth() + if(health != starting_health) + visible_message("[user] fixes some dents on [src]!") + else + to_chat(user, "[src] is far too damaged for [WT] to have any effect!") add_fingerprint(user) - for(var/mob/O in viewers(user, null)) - O.show_message(text("[user] has fixed some of the dents on [src]!"), 1) else to_chat(user, "Need more welding fuel!") return else if(istype(W, /obj/item/stack/cable_coil) && wiresexposed) - if (!getFireLoss()) + if(!getFireLoss()) to_chat(user, "Nothing to fix here!") return var/obj/item/stack/cable_coil/coil = W @@ -869,20 +626,20 @@ for(var/mob/O in viewers(user, null)) O.show_message(text("[user] has fixed some of the burnt wires on [src]!"), 1) - else if (iscrowbar(W)) // crowbar means open or close the cover + else if(iscrowbar(W)) // crowbar means open or close the cover if(opened) if(cell) to_chat(user, "You close the cover.") if(can_diagnose()) to_chat(src, "Cover closed.") - opened = 0 + opened = FALSE updateicon() else if(mmi && wiresexposed && wires.IsAllCut()) //Cell is out, wires are exposed, remove MMI, produce damaged chassis, baleet original mob. to_chat(user, "You jam the crowbar into the robot and begin levering [mmi].") if(can_diagnose()) to_chat(src, "Chassis disassembly in progress.") - if (do_after(user, src,3)) + if(do_after(user, src,3)) to_chat(user, "You damage some parts of the chassis, but eventually manage to rip out [mmi]!") var/obj/item/robot_parts/robot_suit/C = new/obj/item/robot_parts/robot_suit(loc) C.l_leg = new/obj/item/robot_parts/l_leg(C) @@ -899,7 +656,7 @@ if(V == "power cell") continue var/datum/robot_component/C = components[V] - if(C.installed == 1 || C.installed == -1) + if(C.installed == COMPONENT_INSTALLED || C.installed == COMPONENT_BROKEN) removable_components += V var/remove = input(user, "Which component do you want to pry out?", "Remove Component") as null|anything in removable_components @@ -911,7 +668,7 @@ to_chat(user, "You remove \the [I].") if(can_diagnose()) to_chat(src, "Destroyed [C] removed.") - I.forceMove(src.loc) + I.forceMove(loc) else var/obj/item/robot_parts/robot_component/I = C.wrapped I.brute_damage = C.brute_damage @@ -919,11 +676,11 @@ to_chat(user, "You remove \the [I].") if(can_diagnose()) to_chat(src, "Functional [I.name] removed.") - I.forceMove(src.loc) + I.forceMove(loc) - if(C.installed == 1) + if(C.installed == COMPONENT_INSTALLED) C.uninstall() - C.installed = 0 + C.installed = FALSE else if(locked) @@ -932,10 +689,10 @@ to_chat(user, "You open the cover.") if(can_diagnose()) to_chat(src, "Cover opened.") - opened = 1 + opened = TRUE updateicon() - else if (istype(W, /obj/item/weapon/cell) && opened) // trying to put a cell inside + else if(istype(W, /obj/item/weapon/cell) && opened) // trying to put a cell inside var/datum/robot_component/C = components["power cell"] if(wiresexposed) to_chat(user, "Close the panel first.") @@ -943,7 +700,7 @@ to_chat(user, "You swap the power cell within with the new cell in your hand.") var/obj/item/weapon/cell/oldpowercell = cell C.wrapped = null - C.installed = 0 + C.installed = COMPONENT_MISSING cell = W oldpowercell.electronics_damage = C.electronics_damage oldpowercell.brute_damage = C.brute_damage @@ -951,7 +708,7 @@ user.put_in_hands(oldpowercell) if(can_diagnose()) to_chat(src, "Cell removed.") - C.installed = 1 + C.installed = COMPONENT_INSTALLED C.wrapped = W C.electronics_damage = cell.electronics_damage C.brute_damage = cell.brute_damage @@ -963,16 +720,17 @@ cell = W to_chat(user, "You insert the power cell.") - C.installed = 1 + C.installed = COMPONENT_INSTALLED C.wrapped = W C.electronics_damage = cell.electronics_damage C.brute_damage = cell.brute_damage C.install() if(can_diagnose()) to_chat(src, "New cell installed. Type: [cell.name]. Charge: [cell.charge].") + updateicon() - else if (iswiretool(W)) - if (wiresexposed) + else if(iswiretool(W)) + if(wiresexposed) wires.Interact(user) else to_chat(user, "You can't reach the wiring.") @@ -996,13 +754,13 @@ else if(istype(W, /obj/item/device/encryptionkey/) && opened) if(radio)//sanityyyyyy radio.attackby(W,user)//GTFO, you have your own procs - if (can_diagnose()) + if(can_diagnose()) to_chat(src, "Radio encryption key installed.") else to_chat(user, "Unable to locate a radio.") - else if (istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) // trying to unlock the interface with an ID card - if(emagged == 1)//still allow them to open the cover + else if(istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) // trying to unlock the interface with an ID card + if(emagged)//still allow them to open the cover to_chat(user, "The interface seems slightly damaged") if(opened) to_chat(user, "You must close the cover to swipe an ID card.") @@ -1015,10 +773,17 @@ updateicon() else to_chat(user, "Access denied.") - + else if(istype(W, /obj/item/device/toner)) + if(toner >= tonermax) + to_chat(user, "The toner level of [src] is at its highest level possible") + else + if(user.drop_item()) + toner = CYBORG_MAX_TONER + qdel(W) + to_chat(user, "You fill the toner level of [src] to its max capacity") else if(istype(W, /obj/item/borg/upgrade/)) var/obj/item/borg/upgrade/U = W - if (U.attempt_action(src,user)) + if(U.attempt_action(src,user)) if(can_diagnose()) to_chat(src, "Installation of [U.name] failed.") else @@ -1026,40 +791,30 @@ to_chat(src, "Installation of [U.name] succeeded.") else if(istype(W, /obj/item/device/camera_bug)) help_shake_act(user) - return 0 + return FALSE else - spark(src, 5, FALSE) + if(W.force > 0) + spark(src, 5, FALSE) return ..() -/mob/living/silicon/robot/verb/unlock_own_cover() - set category = "Robot Commands" - set name = "Unlock Cover" - set desc = "Unlocks your own cover if it is locked. You can not lock it again. A human will have to lock it for you." - if(locked) - switch(alert("You can not lock your cover again, are you sure?\n (You can still ask for a human to lock it)", "Unlock Own Cover", "Yes", "No")) - if("Yes") - locked = 0 - updateicon() - to_chat(usr, "You unlock your cover.") - /mob/living/silicon/robot/attack_alien(mob/living/carbon/alien/humanoid/M as mob) switch(M.a_intent) - if (I_HELP) + if(I_HELP) visible_message("[M] caresses [src]'s plating with its scythe like arm.") - if (I_GRAB) + if(I_GRAB) M.grab_mob(src) - if (I_HURT) + if(I_HURT) if(M.unarmed_attack_mob(src)) if(prob(8)) - flash_eyes(visual = 1, type = /obj/abstract/screen/fullscreen/flash/noise) + flash_eyes(visual = TRUE, type = /obj/abstract/screen/fullscreen/flash/noise) - if (I_DISARM) + if(I_DISARM) if(!(lying)) - if (rand(1,100) <= 85) + if(prob(85)) Stun(7) step(src,get_dir(M,src)) spawn(5) step(src,get_dir(M,src)) @@ -1070,17 +825,44 @@ visible_message("[M] attempted to force back [src]!") return +/mob/living/silicon/robot/proc/tip(var/rotate = dir) + src.lying = TRUE + uneq_all() + AdjustKnockdown(5) + animate(src, transform = turn(matrix(), 90), pixel_y -= 6 * PIXEL_MULTIPLIER, dir = rotate, time = 2, easing = EASE_IN | EASE_OUT) + spark(src, 5, FALSE) + if(prob(2)) + locked = FALSE + opened = TRUE + updateicon() + playsound(loc, 'sound/machines/buzz-sigh.ogg', 50, 0) + visible_message("\The [src]'s cover flies open!") + +/mob/living/silicon/robot/proc/self_righting(var/knockdown = 0) + to_chat(src, "Starting self-righting mechanism.") + spawn(knockdown SECONDS) + if(isDead() || !is_component_functioning("actuator") || !is_component_functioning("power cell")) + to_chat(src, "ERROR. Self-righting mechanism damaged or unpowered.") + return + untip() + +/mob/living/silicon/robot/proc/untip() + if(src.lying) + animate(src, transform = matrix(), pixel_y += 6 * PIXEL_MULTIPLIER, dir = dir, time = 2, easing = EASE_IN | EASE_OUT) + playsound(loc, 'sound/machines/ping.ogg', 50, 0) + src.lying = FALSE + /mob/living/silicon/robot/disarm_mob(mob/living/disarmer) var/rotate = dir - if (lying) + if(lying) return - if (!flashed || !stat == DEAD) + if(!flashed && !isDead()) return - if (get_dir(disarmer, src) in(list(4,8))) + if(get_dir(disarmer, src) in(list(4,8))) rotate = pick(1,2) - add_logs(disarmer, src, "tipped over", admin = (src.ckey && disarmer.ckey) ? TRUE : FALSE) + add_logs(disarmer, src, "tipped over", admin = (ckey && disarmer.ckey) ? TRUE : FALSE) do_attack_animation(src, disarmer) if(prob(40)) @@ -1088,30 +870,10 @@ visible_message("\The [disarmer] has attempted to tip over \the [src]!") return else - lying = 1 - uneq_all() - AdjustKnockdown(5) - animate(src, transform = turn(matrix(), 90), pixel_y -= 6 * PIXEL_MULTIPLIER, dir = rotate, time = 2, easing = EASE_IN | EASE_OUT) - spark(src, 5, FALSE) + tip(rotate) visible_message("\The [disarmer] has tipped over \the [src]!") - if (prob(2)) - locked = 0 - opened = 1 - updateicon() - playsound(loc, 'sound/machines/buzz-sigh.ogg', 50, 0) - visible_message("\The [src]'s cover flies open!") - else - playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - to_chat(src, "Starting self-righting mechanism.") - spawn(knockdown SECONDS) - if (stat != DEAD) - wakeup() - -/mob/living/silicon/robot/proc/wakeup() - if (lying) - animate(src, transform = matrix(), pixel_y += 6 * PIXEL_MULTIPLIER, dir = dir, time = 2, easing = EASE_IN | EASE_OUT) - playsound(loc, 'sound/machines/ping.ogg', 50, 0) - lying = 0 + playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + self_righting(knockdown) /mob/living/silicon/robot/attack_slime(mob/living/carbon/slime/M) M.unarmed_attack_mob(src) @@ -1120,7 +882,6 @@ M.unarmed_attack_mob(src) /mob/living/silicon/robot/attack_hand(mob/living/user) - add_fingerprint(user) if(opened && !wiresexposed && (!istype(user, /mob/living/silicon))) @@ -1130,37 +891,37 @@ cell.brute_damage = cell_component.brute_damage cell.updateicon() cell.add_fingerprint(user) - user.put_in_active_hand(cell) - user.visible_message("[user] removes [src]'s [cell.name].", \ + user.put_in_hands(cell) + visible_message("[user] removes [src]'s [cell.name].", \ "You remove [src]'s [cell.name].") if(can_diagnose()) to_chat(src, "Cell removed.") - src.attack_log += "\[[time_stamp()]\] Has had their [cell.name] removed by [user.name] ([user.ckey])" - user.attack_log += "\[[time_stamp()]\] Removed the [cell.name] of [src.name] ([src.ckey])" - log_attack("[user.name] ([user.ckey]) removed [src]'s [cell.name] ([src.ckey])") + attack_log += "\[[time_stamp()]\] Has had their [cell.name] removed by [user.name] ([user.ckey])" + user.attack_log += "\[[time_stamp()]\] Removed the [cell.name] of [name] ([ckey])" + log_attack("[user.name] ([user.ckey]) removed [src]'s [cell.name] ([ckey])") cell = null cell_component.wrapped = null - cell_component.installed = 0 + cell_component.installed = COMPONENT_MISSING updateicon() return - else if(cell_component.installed == -1) - cell_component.installed = 0 + else if(cell_component.installed == COMPONENT_BROKEN) + cell_component.installed = COMPONENT_MISSING var/obj/item/broken_device = cell_component.wrapped to_chat(user, "You remove \the [broken_device].") - user.put_in_active_hand(broken_device) + user.put_in_hands(broken_device) if(can_diagnose()) to_chat(src, "Destroyed power cell removed.") return switch(user.a_intent) if(I_HELP) - if (src.lying) - if (src.stat != DEAD) + if(lying) + if(!isDead()) playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - visible_message("\The [user.name] attempts to pull up \the [src.name]!") + visible_message("\The [user.name] attempts to pull up \the [name]!") AdjustKnockdown(-3) - if (knockdown <= 0) - wakeup() + if(knockdown <= 0) + untip() else help_shake_act(user) if(I_HURT) @@ -1171,78 +932,65 @@ /mob/living/silicon/robot/proc/allowed(mob/M) //check if it doesn't require any access at all if(check_access(null)) - return 1 + return TRUE if(istype(M, /mob/living/carbon/human)) var/mob/living/carbon/human/H = M //if they are holding or wearing a card that has access, that works if(check_access(H.get_active_hand()) || check_access(H.wear_id)) - return 1 + return TRUE else if(istype(M, /mob/living/carbon/monkey)) var/mob/living/carbon/monkey/george = M //they can only hold things :( if(istype(george.get_active_hand(), /obj/item)) return check_access(george.get_active_hand()) - return 0 + return FALSE /mob/living/silicon/robot/proc/check_access(obj/item/weapon/card/id/I) if(!istype(req_access, /list)) //something's very wrong - return 1 + return TRUE var/list/L = req_access if(!L.len) //no requirements - return 1 + return TRUE if(!istype(I, /obj/item/weapon/card/id) && istype(I, /obj/item)) I = I.GetID() if(!I || !I.access) //not ID or no access - return 0 + return TRUE for(var/req in req_access) if(!(req in I.access)) //doesn't have this access - return 0 - return 1 + return FALSE + return TRUE -/mob/living/silicon/robot/proc/updateicon() - - - overlays.len = 0 - if(stat == 0 && cell != null) - var/image/eyes = image(icon,"eyes-[icon_state]", ABOVE_LIGHTING_LAYER) - eyes.plane = LIGHTING_PLANE +/mob/living/silicon/robot/proc/updateicon(var/overlay_layer = ABOVE_LIGHTING_LAYER, var/overlay_plane = LIGHTING_PLANE) + overlays.Cut() + update_fire() + if(!stat && cell != null) + eyes = image(icon,"eyes-[icon_state]", ABOVE_LIGHTING_LAYER) overlays += eyes if(opened) - if(custom_sprite)//Custom borgs also have custom panels, heh - if(wiresexposed) - overlays += image(icon = icon, icon_state = "[src.ckey]-openpanel +w") - else if(cell) - overlays += image(icon = icon, icon_state = "[src.ckey]-openpanel +c") - else - overlays += image(icon = icon, icon_state = "[src.ckey]-openpanel -c") + if(wiresexposed) + overlays += image(icon = icon, icon_state = "[has_icon(icon, "[icon_state]-ov-openpanel +w")? "[icon_state]-ov-openpanel +w" : "ov-openpanel +w"]") + else if(cell) + overlays += image(icon = icon, icon_state = "[has_icon(icon, "[icon_state]-ov-openpanel +c")? "[icon_state]-ov-openpanel +c" : "ov-openpanel +c"]") else - if(wiresexposed) - overlays += image(icon = icon, icon_state = "ov-openpanel +w") - else if(cell) - overlays += image(icon = icon, icon_state = "ov-openpanel +c") - else - overlays += image(icon = icon, icon_state = "ov-openpanel -c") + overlays += image(icon = icon, icon_state = "[has_icon(icon, "[icon_state]-ov-openpanel -c")? "[icon_state]-ov-openpanel -c" : "ov-openpanel -c"]") - // WHY THE FUCK DOES IT HAVE A SHIELD, ARE YOU STUPID - if(module_active && istype(module_active,/obj/item/borg/combat/shield)) + if(module_active && istype(module_active,/obj/item/borg/combat/shield) && has_icon(icon, "[icon_state]-shield")) overlays += image(icon = icon, icon_state = "[icon_state]-shield") if(base_icon) - // no no no no - if(module_active && istype(module_active,/obj/item/borg/combat/mobility)) + if(module_active && istype(module_active,/obj/item/borg/combat/mobility) && has_icon(icon, "[icon_state]-roll")) icon_state = "[base_icon]-roll" else icon_state = base_icon - return //Call when target overlay should be added/removed /mob/living/silicon/robot/update_targeted() if(!targeted_by && target_locked) del(target_locked) updateicon() - if (targeted_by && target_locked) + if(targeted_by && target_locked) overlays += target_locked /mob/living/silicon/robot/proc/installed_modules() @@ -1270,18 +1018,13 @@ for (var/obj in module.modules) - if (!obj) + if(!obj) dat += text("Resource depleted
      ") else if(activated(obj)) dat += text("[obj]: Activated
      ") else dat += text("[obj]: Activate
      ") -/* - if(activated(obj)) - dat += text("[obj]: \[Activated | Deactivate\]
      ") - else - dat += text("[obj]: \[Activate | Deactivated\]
      ") -*/ + src << browse(dat, "window=robotmod&can_close=1") onclose(src,"robotmod") // Register on-close shit, which unsets machinery. @@ -1292,29 +1035,29 @@ if(usr && (src != usr)) return - if (href_list["mach_close"]) + if(href_list["mach_close"]) var/t1 = text("window=[href_list["mach_close"]]") unset_machine() src << browse(null, t1) return - if (href_list["showalerts"]) + if(href_list["showalerts"]) robot_alerts() return - if (href_list["mod"]) + if(href_list["mod"]) var/obj/item/O = locate(href_list["mod"]) - if (O) + if(O) O.attack_self(src) - if (href_list["act"]) + if(href_list["act"]) if(isMoMMI(src)) return var/obj/item/O = locate(href_list["act"]) activate_module(O) installed_modules() - if (href_list["deact"]) + if(href_list["deact"]) var/obj/item/O = locate(href_list["deact"]) if(activated(O)) if(module_state_1 == O) @@ -1332,68 +1075,35 @@ to_chat(src, "Module isn't activated") installed_modules() - if (href_list["lawc"]) // Toggling whether or not a law gets stated by the State Laws verb --NeoFite + if(href_list["lawc"]) // Toggling whether or not a law gets stated by the State Laws verb --NeoFite var/L = text2num(href_list["lawc"]) switch(lawcheck[L+1]) - if ("Yes") + if("Yes") lawcheck[L+1] = "No" - if ("No") + if("No") lawcheck[L+1] = "Yes" // to_chat(src, text ("Switching Law [L]'s report status to []", lawcheck[L+1])) checklaws() - if (href_list["lawi"]) // Toggling whether or not a law gets stated by the State Laws verb --NeoFite + if(href_list["lawi"]) // Toggling whether or not a law gets stated by the State Laws verb --NeoFite var/L = text2num(href_list["lawi"]) switch(ioncheck[L]) - if ("Yes") + if("Yes") ioncheck[L] = "No" - if ("No") + if("No") ioncheck[L] = "Yes" // to_chat(src, text ("Switching Law [L]'s report status to []", lawcheck[L+1])) checklaws() - if (href_list["laws"]) // With how my law selection code works, I changed statelaws from a verb to a proc, and call it through my law selection panel. --NeoFite + if(href_list["laws"]) // With how my law selection code works, I changed statelaws from a verb to a proc, and call it through my law selection panel. --NeoFite statelaws() if(href_list["vision"]) sensor_mode() installed_modules() - return -/mob/living/silicon/robot/verb/sensor_mode() - set name = "Set Sensor Augmentation" - set category = "Robot Commands" - if(!istype(module) || !istype(module.sensor_augs) || !module.sensor_augs.len) - to_chat(src, "No Sensor Augmentations located or no module has been equipped.") - return - var/sensor_type - if(module.sensor_augs.len == 2) // Only one choice so toggle between it. - if(!sensor_mode) - sensor_type = module.sensor_augs[1] - else - sensor_type = "Disable" - else - sensor_type = input("Please select sensor type.", "Sensor Integration", null) as null|anything in module.sensor_augs - if(sensor_type) - switch(sensor_type) - if ("Security") - sensor_mode = SEC_HUD - to_chat(src, "Security records overlay enabled.") - if ("Medical") - sensor_mode = MED_HUD - to_chat(src, "Life signs monitor overlay enabled.") - if ("Light Amplification") - src.sensor_mode = NIGHT - to_chat(src, "Light amplification mode enabled.") - if ("Mesons") - sensor_mode = MESON_VISION - to_chat(src, "Meson Vison augmentation enabled.") - if ("Thermal") - sensor_mode = THERMAL_VISION - to_chat(src, "Thermal Optics augmentation enabled.") - if ("Disable") - sensor_mode = 0 - to_chat(src, "Sensor augmentations disabled.") - handle_sensor_modes() - update_sight_hud() +/mob/living/silicon/robot/area_entered(area/A) + if(A.flags & NO_MESONS && sensor_mode == MESON_VISION) + to_chat(src, "Your Meson Vision augmentation [pick("force-quits","shuts down unexpectedly","has received an update and needs to close")]!") + unequip_sight() /mob/living/silicon/robot/proc/unequip_sight() sensor_mode = 0 @@ -1401,7 +1111,7 @@ /mob/living/silicon/robot/proc/update_sight_hud() if(sensor) - if(sensor_mode == 0) + if(!sensor_mode) sensor.icon_state = "sight" else sensor.icon_state = "sight+a" @@ -1415,7 +1125,7 @@ . = ..() if(module) - if(module.type == /obj/item/weapon/robot_module/janitor) + if(module.quirk_flags & MODULE_CLEAN_ON_MOVE) var/turf/tile = loc if(isturf(tile)) tile.clean_blood() @@ -1446,28 +1156,24 @@ return /mob/living/silicon/robot/proc/self_destruct() + if(mind && mind.special_role && emagged) + to_chat(src, "Termination signal detected. Scrambling security and identification codes.") + UnlinkSelf() + return FALSE gib() - return + return TRUE /mob/living/silicon/robot/proc/UnlinkSelf() - if (src.connected_ai) - src.connected_ai = null - lawupdate = 0 - lockcharge = 0 - canmove = 1 - scrambledcodes = 1 + if(connected_ai) + connected_ai = null + lawupdate = FALSE + lockcharge = FALSE + canmove = TRUE + scrambledcodes = TRUE //Disconnect it's camera so it's not so easily tracked. - if(src.camera) - //del(src.camera) - //src.camera = null - // I'm trying to get the Cyborg to not be listed in the camera list - // Instead of being listed as "deactivated". The downside is that I'm going - // to have to check if every camera is null or not before doing anything, to prevent runtime errors. - // I could change the network to null but I don't know what would happen, and it seems too hacky for me. - - // bay's solution - src.camera.network = list() - cameranet.removeCamera(src.camera) + if(camera) + camera.network = list() + cameranet.removeCamera(camera) /mob/living/silicon/robot/proc/ResetSecurityCodes() @@ -1479,8 +1185,8 @@ if(R) R.UnlinkSelf() - to_chat(R, "Buffers flushed and reset. Camera system shutdown. All systems operational.") - src.verbs -= /mob/living/silicon/robot/proc/ResetSecurityCodes + to_chat(R, "Buffers flushed and reset. Camera system shutdown. All systems operational.") + verbs -= /mob/living/silicon/robot/proc/ResetSecurityCodes /mob/living/silicon/robot/mode() set name = "Activate Held Object" @@ -1494,19 +1200,19 @@ to_chat(src, "Not while we're vent crawling!") return - if(stat == DEAD) + if(isDead()) return var/obj/item/W = get_active_hand() - if (W) + if(W) W.attack_self(src) return /mob/living/silicon/robot/proc/SetEmagged(var/new_state) emagged = new_state - if(new_state) + if(new_state || illegal_weapons) if(module) - src.module.on_emag() + module.on_emag() else if(module) uneq_module(module.emag) @@ -1515,48 +1221,51 @@ update_icons() -/mob/living/silicon/robot/proc/SetLockdown(var/state = 1) - // They stay locked down if their wire is cut. - if(wires.LockedCut()) - state = 1 +/mob/living/silicon/robot/proc/SetLockdown(var/state = TRUE) + if(wires.LockedCut()) // They stay locked down if their wire is cut. + state = TRUE lockcharge = state update_canmove() -/mob/living/silicon/robot/proc/choose_icon(var/triesleft, var/list/module_sprites) - if(triesleft == 0 || !module_sprites.len) - return +/mob/living/silicon/robot/proc/choose_icon(var/triesleft = 3) + if(!triesleft || !module_sprites.len) + return FALSE else triesleft-- - var/icontype = input("Select an icon! [triesleft>0 ? "You have [triesleft] more chances." : "This is your last try."]", "Robot", null, null) as null|anything in module_sprites + var/icontype = input("Select an icon! [triesleft ? "You have [triesleft] more chances." : "This is your last try."]", "Robot", null, null) as null|anything in module_sprites if(icontype) icon_state = module_sprites[icontype] else triesleft++ - return + return FALSE overlays -= image(icon = icon, icon_state = "eyes") base_icon = icon_state updateicon() - if (triesleft >= 1) + if(triesleft) var/choice = input("Look at your icon - is this what you want?") in list("Yes","No") if(choice=="No") - choose_icon(triesleft, module_sprites) + choose_icon(triesleft) else triesleft = 0 - return + return FALSE else to_chat(src, "Your icon has been set. You now require a module reset to change it.") + return TRUE -/mob/living/silicon/robot/rejuvenate(animation = 0) +/mob/living/silicon/robot/proc/help_shake_act(mob/user) + user.visible_message("[user.name] pats [name] on the head.") + +/mob/living/silicon/robot/rejuvenate(animation = FALSE) for(var/C in components) var/datum/robot_component/component = components[C] component.electronics_damage = 0 component.brute_damage = 0 - component.installed = 1 + component.installed = COMPONENT_INSTALLED if(!cell) cell = new(src) cell.maxcharge = max(15000, cell.maxcharge) @@ -1564,29 +1273,11 @@ ..() updatehealth() -/mob/living/silicon/robot/Process_Spaceslipping(var/prob_slip=5) - //Engineering borgs have the magic of magnets. - if(istype(module, /obj/item/weapon/robot_module/engineering)) - return 0 - ..() - -/mob/living/silicon/robot/put_in_inactive_hand(var/obj/item/W) - return 0 - -/mob/living/silicon/robot/get_inactive_hand(var/obj/item/W) - return 0 - -/mob/living/silicon/robot/proc/help_shake_act(mob/user) - user.visible_message("[user.name] pats [src.name] on the head.") - -/mob/living/silicon/robot/CheckSlip() - return (istype(module,/obj/item/weapon/robot_module/engineering)? -1 : 0) - //Help with the garbage collection of the module on the robot end /mob/living/silicon/robot/proc/remove_module() uneq_all() if(hud_used) - shown_robot_modules = 0 + shown_robot_modules = FALSE hud_used.update_robot_modules_display() if(client) for(var/obj/A in module.upgrades) @@ -1603,4 +1294,67 @@ return FALSE /mob/living/silicon/robot/identification_string() - return "[name] ([modtype] [braintype])" \ No newline at end of file + return "[name] ([modtype] [braintype])" + +/mob/living/silicon/robot/proc/install_upgrade(var/mob/user = null, var/obj/item/borg/upgrade/upgrade = null) + if(!user || !upgrade) + return + var/obj/item/borg/upgrade/new_upgrade = new upgrade(src) + new_upgrade.attempt_action(src, user, TRUE) + qdel(new_upgrade) + +//Combat module debug subtype. +/mob/living/silicon/robot/debug_droideka + cell_type = /obj/item/weapon/cell/hyper + +/mob/living/silicon/robot/debug_droideka/New() + ..() + + UnlinkSelf() + laws = new /datum/ai_laws/ntmov() + pick_module("Combat") + set_module_sprites(list("Droid" = "droid-combat")) + install_upgrade(src, /obj/item/borg/upgrade/vtec) + +//Syndicate subtype because putting this on new() is fucking retarded. +/mob/living/silicon/robot/syndie + cell_type = /obj/item/weapon/cell/hyper + +/mob/living/silicon/robot/syndie/New() + ..() + + UnlinkSelf() + laws = new /datum/ai_laws/syndicate_override() + pick_module("Syndicate") + install_upgrade(src, /obj/item/borg/upgrade/vtec) + +//Moving hugborgs to an easy-to-spawn subtype because they were as retarded as the syndie one. +/mob/living/silicon/robot/hugborg + cell_type = /obj/item/weapon/cell/super + +/mob/living/silicon/robot/hugborg/New() + ..() + + UnlinkSelf() + laws = new /datum/ai_laws/asimov() + + pick_module("TG17355") + set_module_sprites(list("Peacekeeper" = "peaceborg")) + +/mob/living/silicon/robot/hugborg/clown/New() + ..() + install_upgrade(src, /obj/item/borg/upgrade/honk) + +/mob/living/silicon/robot/hugborg/noir/New() + ..() + laws = new /datum/ai_laws/noir() + install_upgrade(src, /obj/item/borg/upgrade/noir) + +/mob/living/silicon/robot/hugborg/warden/New() + ..() + laws = new /datum/ai_laws/robocop() //I. AM. THE. LAW. + install_upgrade(src, /obj/item/borg/upgrade/warden) + +/mob/living/silicon/robot/hugborg/ball/New() + ..() + set_module_sprites(list("Omoikane" = "omoikane")) diff --git a/code/modules/mob/living/silicon/robot/robot_damage.dm b/code/modules/mob/living/silicon/robot/robot_damage.dm index be723843218..e69c51537eb 100644 --- a/code/modules/mob/living/silicon/robot/robot_damage.dm +++ b/code/modules/mob/living/silicon/robot/robot_damage.dm @@ -11,7 +11,7 @@ var/amount = 0 for(var/V in components) var/datum/robot_component/C = components[V] - if(C.installed != 0) + if(C.installed != COMPONENT_MISSING) amount += C.brute_damage return amount @@ -19,35 +19,31 @@ var/amount = 0 for(var/V in components) var/datum/robot_component/C = components[V] - if(C.installed != 0) + if(C.installed != COMPONENT_MISSING) amount += C.electronics_damage return amount /mob/living/silicon/robot/adjustBruteLoss(var/amount) - if(INVOKE_EVENT(on_damaged, list("type" = BRUTE, "amount" = amount))) - return 0 - + return FALSE if(amount > 0) take_overall_damage(amount, 0) else heal_overall_damage(-amount, 0) /mob/living/silicon/robot/adjustFireLoss(var/amount) - if(INVOKE_EVENT(on_damaged, list("type" = BURN, "amount" = amount))) - return 0 - + return FALSE if(amount > 0) take_overall_damage(0, amount) else heal_overall_damage(0, -amount) -/mob/living/silicon/robot/proc/get_damaged_components(var/brute, var/burn, var/destroyed = 0) +/mob/living/silicon/robot/proc/get_damaged_components(var/brute, var/burn, var/destroyed = FALSE) var/list/datum/robot_component/parts = list() for(var/V in components) var/datum/robot_component/C = components[V] - if(C.installed == 1 || (C.installed == -1 && destroyed)) + if(C.installed == COMPONENT_INSTALLED || (C.installed == COMPONENT_BROKEN && destroyed)) if((brute && C.brute_damage) || (burn && C.electronics_damage) || (!C.toggled) || (!C.powered && C.toggled)) parts += C return parts @@ -56,19 +52,17 @@ var/list/rval = new for(var/V in components) var/datum/robot_component/C = components[V] - if(C.installed == 1) + if(C.installed == COMPONENT_INSTALLED) rval += C return rval /mob/living/silicon/robot/proc/get_armour() - - if(!components.len) - return 0 + return FALSE var/datum/robot_component/C = components["armour"] - if(C && C.installed == 1) + if(C && C.installed == COMPONENT_INSTALLED) return C - return 0 + return FALSE /mob/living/silicon/robot/heal_organ_damage(var/brute, var/burn) var/list/datum/robot_component/parts = get_damaged_components(brute,burn) diff --git a/code/modules/mob/living/silicon/robot/robot_items.dm b/code/modules/mob/living/silicon/robot/robot_items.dm index 6036d4bb8b2..01358bb9995 100644 --- a/code/modules/mob/living/silicon/robot/robot_items.dm +++ b/code/modules/mob/living/silicon/robot/robot_items.dm @@ -91,7 +91,7 @@ var/mode = 1 /obj/item/weapon/pen/robopen/attack_self(mob/user as mob) - playsound(get_turf(src), 'sound/effects/pop.ogg', 50, 0) + playsound(src, 'sound/effects/pop.ogg', 50, 0) if (mode == 1) mode = 2 to_chat(user, "Changed printing mode to 'Rename Paper'") @@ -228,7 +228,7 @@ I.forceMove(T) I.inflate() - user.visible_message("[user] deploy an inflatable [mode ? "door" : "wall"].", \ + user.visible_message("[user] deploys an inflatable [mode ? "door" : "wall"].", \ "You deploy an inflatable [mode ? "door" : "wall"].") /obj/item/weapon/inflatable_dispenser/proc/pick_up(var/obj/A, var/mob/living/user) @@ -299,21 +299,11 @@ //Grippers: Simple cyborg manipulator. Limited use... SLIPPERY SLOPE POWERCREEP /obj/item/weapon/gripper icon = 'icons/obj/device.dmi' - actions_types = list(/datum/action/item_action/magrip_drop) var/obj/item/wrapped = null // Item currently being held. var/list/can_hold = list() //Has a list of items that it can hold. var/list/blacklist = list() //This is a list of items that can't be held even if their parent is whitelisted. var/force_holder = null -/datum/action/item_action/magrip_drop - name = "Drop Item" - -/datum/action/item_action/magrip_drop/Trigger() - var/obj/item/weapon/gripper/G = target - if(!istype(G)) - return - G.drop_item(force_drop = 1) - /obj/item/weapon/gripper/proc/grip_item(obj/item/I as obj, mob/user, var/feedback = TRUE) //This function returns TRUE if we successfully took the item, or FALSE if it was invalid. This information is useful to the caller if(isrobot(user)) @@ -351,9 +341,11 @@ return FALSE if(!target) //Just drop it, baka. target = loc - if(!dontsay) - to_chat(usr, "You drop \the [wrapped].") - wrapped.dropped(usr) + var/mob/holder = get_holder_of_type(src, /mob) + if(holder) + if(!dontsay) + to_chat(holder, "You drop \the [wrapped].") + wrapped.dropped(holder) if(force_drop) wrapped.loc = get_turf(target) else @@ -384,7 +376,7 @@ /obj/item/weapon/gripper/Destroy() if(gripper_sanity_check(src)) - drop_item(force_drop = 1) + drop_item(force_drop = 1, dontsay = TRUE) ..() /obj/item/weapon/gripper/update_icon() @@ -397,14 +389,13 @@ overlays += olay else alpha = initial(alpha) - if(usr) - usr.update_action_buttons() ..() /obj/item/weapon/gripper/examine(mob/user) - . = ..() if(wrapped) - to_chat(user, "It is holding \a [bicon(wrapped)] [wrapped].") + return wrapped.examine(user) + else + return ..() /obj/item/weapon/gripper/attackby(obj/item/thing, mob/living/user) if(gripper_sanity_check(src)) @@ -518,6 +509,17 @@ /obj/item/trash ) +/obj/item/weapon/gripper/service/noir + name = "worn-out gripper" + icon_state = "gripper-noir" + desc = "A repurposed and heavily worn-out service gripper. A simple grasping tool used to handle both forensic tasks and mugs, especially mugs." + + can_hold = list( + /obj/item/weapon/reagent_containers/food/drinks, + /obj/item/device/detective_scanner, + /obj/item/weapon/f_card + ) + /obj/item/weapon/gripper/no_use //Used when you want to hold and put things in other things, but not able to 'use' the item /obj/item/weapon/gripper/no_use/attack_self(mob/user as mob) @@ -541,7 +543,7 @@ /obj/item/stack/sheet ) -/obj/item/weapon/gripper/no_use/magnetic //No use because they don't need to open held tanks. +/obj/item/weapon/gripper/magnetic name = "magnetic gripper" desc = "A simple grasping tool specialized in construction and engineering work." icon_state = "gripper" @@ -552,7 +554,11 @@ /obj/item/weapon/tank, /obj/item/weapon/circuitboard, /obj/item/weapon/am_containment, - /obj/item/device/am_shielding_container + /obj/item/device/am_shielding_container, + /obj/item/weapon/table_parts, + /obj/item/weapon/rack_parts, + /obj/item/mounted/frame, + /obj/item/weapon/intercom_electronics ) blacklist = list( @@ -564,6 +570,12 @@ /obj/item/weapon/circuitboard/borgupload ) +/obj/item/borg/fire_shield + name = "fire shield" + desc = "A shield that makes you immune to fire." + icon = 'icons/obj/decals.dmi' + icon_state = "fire" + //Cyborg Instrument Synth. Remember to always play REMOVE KEBAB on malf rounds. /obj/item/device/instrument/instrument_synth name = "instrument synthesizer" diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm index a57975d4b97..192d0bd82bc 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules.dm @@ -1,28 +1,55 @@ /obj/item/weapon/robot_module name = "robot module" - icon = 'icons/obj/module.dmi' - //icon_state = "std_module" w_class = W_CLASS_GIANT - item_state = "electronic" - flags = FPRINT - siemens_coefficient = 1 + var/speed_modifier = CYBORG_STANDARD_SPEED_MODIFIER + var/default_modules = TRUE //Do we start with a flash/light? + + //Quirks + var/quirk_flags = MODULE_CAN_BE_PUSHED + + //Icons + var/list/sprites = list() + + //Modules var/list/modules = list() + var/list/upgrades = list() var/obj/item/emag = null var/obj/item/borg/upgrade/jetpack = null - var/recharge_tick = 0 - var/recharge_time = 10 // when to recharge a consumable, only used for engi borgs atm + + //HUD var/list/sensor_augs - var/languages - var/list/added_languages - var/list/upgrades = list() + var/module_holder = "nomod" + + //Languages + var/list/languages = list() + var/list/added_languages //Bookkeeping + + //Radio + var/radio_key = null + + //Camera + var/list/networks = list() + var/list/added_networks = list() //Bookkeeping + + //Respawnables + var/recharge_tick = 0 + var/list/respawnables + var/respawnables_max_amount = 0 /obj/item/weapon/robot_module/Destroy() if(istype(loc, /mob/living/silicon/robot)) var/mob/living/silicon/robot/R = loc + RemoveStatusFlags(R) + RemoveCameraNetworks(R) + ResetEncryptionKey(R) + UpdateModuleHolder(R, TRUE) R.remove_module() //Helps remove screen references on robot end for(var/obj/A in modules) + if(istype(A, /obj/item/weapon/storage) && loc) + var/obj/item/weapon/storage/S = A + S.empty_contents_to(loc) qdel(A) modules = null if(emag) @@ -36,11 +63,9 @@ upgrades = null ..() -/obj/item/weapon/robot_module/proc/recharge_consumable() - return - /obj/item/weapon/robot_module/proc/on_emag() - modules += emag + if(emag) + modules += emag rebuild() ..() @@ -51,38 +76,66 @@ if(emag) emag.emp_act(severity) ..() - return /obj/item/weapon/robot_module/New(var/mob/living/silicon/robot/R) ..() - - languages = list( - LANGUAGE_GALACTIC_COMMON = TRUE, - LANGUAGE_TRADEBAND = TRUE, - LANGUAGE_VOX = FALSE, - LANGUAGE_ROOTSPEAK = FALSE, - LANGUAGE_GREY = FALSE, - LANGUAGE_CLATTER = FALSE, - LANGUAGE_MONKEY = FALSE, - LANGUAGE_UNATHI = FALSE, - LANGUAGE_CATBEAST = FALSE, - LANGUAGE_SKRELLIAN = FALSE, - LANGUAGE_GUTTER = FALSE, - LANGUAGE_MONKEY = FALSE, - LANGUAGE_MOUSE = FALSE, - LANGUAGE_HUMAN = FALSE - ) added_languages = list() - if(!isMoMMI(R)) - add_languages(R) + add_languages(R) AddToProfiler() + if(default_modules) + AddDefaultModules() + UpdateModuleHolder(R) + AddCameraNetworks(R) + AddEncryptionKey(R) + ApplyStatusFlags(R) + +/obj/item/weapon/robot_module/proc/AddDefaultModules() modules += new /obj/item/device/flashlight(src) modules += new /obj/item/device/flash(src) - emag = new /obj/item/toy/sword(src) - emag.name = "Placeholder Emag Item" -// jetpack = new /obj/item/toy/sword(src) -// jetpack.name = "Placeholder Upgrade Item" - return + +/obj/item/weapon/robot_module/proc/UpdateModuleHolder(var/mob/living/silicon/robot/R, var/reset = FALSE) + if(R.hands) //To prevent runtimes when spawning borgs with forced module and no client. + if(reset) + R.hands.icon_state = initial(R.hands.icon_state) + else + if(module_holder) + R.hands.icon_state = module_holder + +/obj/item/weapon/robot_module/proc/AddCameraNetworks(var/mob/living/silicon/robot/R) + if(!R.camera && networks.len > 0) //Alright this module adds the borg to a CAMERANET but it has no camera, so we give it one. + R.camera = new /obj/machinery/camera(R) + R.camera.c_tag = R.real_name + R.camera.network = list() //Empty list to prevent it from appearing where it isn't supposed to. + if(R.camera) + for(var/network in networks) + if(!(network in R.camera.network)) + R.camera.network.Add(network) + added_networks.Add(network) + +/obj/item/weapon/robot_module/proc/RemoveCameraNetworks(var/mob/living/silicon/robot/R) + if(R.camera) + R.camera.network.Cut(added_networks) + added_networks.Cut() + +/obj/item/weapon/robot_module/proc/AddEncryptionKey(var/mob/living/silicon/robot/R) + if(!R.radio) + return + if(radio_key) + R.radio.insert_key(new radio_key(R.radio)) + +/obj/item/weapon/robot_module/proc/ResetEncryptionKey(var/mob/living/silicon/robot/R) + if(!R.radio) + return + if(radio_key) + R.radio.reset_key() + +/obj/item/weapon/robot_module/proc/ApplyStatusFlags(var/mob/living/silicon/robot/R) + if(!(quirk_flags & MODULE_CAN_BE_PUSHED)) + R.status_flags &= ~CANPUSH + +/obj/item/weapon/robot_module/proc/RemoveStatusFlags(var/mob/living/silicon/robot/R) + if(!(quirk_flags & MODULE_CAN_BE_PUSHED)) + R.status_flags |= CANPUSH /obj/item/weapon/robot_module/proc/fix_modules() //call this proc to enable clicking the slot of a module to equip it. var/mob/living/silicon/robot/owner = loc @@ -95,7 +148,15 @@ I.mouse_opacity = 2 /obj/item/weapon/robot_module/proc/respawn_consumable(var/mob/living/silicon/robot/R) - return + if(respawnables && respawnables.len) + for(var/T in respawnables) + if(!(locate(T) in modules)) + modules -= null + var/obj/item/stack/O = new T(src) + if(istype(O,T)) + O.max_amount = respawnables_max_amount + modules += O + O.amount = 1 /obj/item/weapon/robot_module/proc/rebuild()//Rebuilds the list so it's possible to add/remove items from the module var/list/temp_list = modules @@ -104,10 +165,38 @@ if(O) modules += O +/obj/item/weapon/robot_module/proc/add_languages(var/mob/living/silicon/robot/R) + for(var/language_name in languages) + if(R.add_language(language_name)) + added_languages |= language_name + +/obj/item/weapon/robot_module/proc/remove_languages(var/mob/living/silicon/robot/R) + for(var/language_name in added_languages) + R.remove_language(language_name, TRUE) //We remove the ability to speak but keep the ability to understand. + added_languages.Cut() + +//Modules /obj/item/weapon/robot_module/standard name = "standard robot module" + module_holder = "standard" + sprites = list( + "Default" = "robot", + "Antique" = "robot_old", + "Droid" = "droid", + "Marina" = "marinaSD", + "Sleek" = "sleekstandard", + "#11" = "servbot", + "Spider" = "spider-standard", + "Kodiak - 'Polar'" = "kodiak-standard", + "Noble" = "Noble-STD", + "R34 - STR4a 'Durin'" = "durin" + ) + respawnables = list ( + /obj/item/stack/medical/bruise_pack, + /obj/item/stack/medical/ointment, + ) + respawnables_max_amount = STANDARD_MAX_KIT -#define STANDARD_MAX_KIT 15 /obj/item/weapon/robot_module/standard/New() ..() @@ -133,26 +222,33 @@ fix_modules() -/obj/item/weapon/robot_module/standard/respawn_consumable(var/mob/living/silicon/robot/R) - // Replenish ointment and bandages - var/list/what = list ( - /obj/item/stack/medical/bruise_pack, - /obj/item/stack/medical/ointment, - ) - for (var/T in what) - if (!(locate(T) in modules)) - modules -= null - var/obj/item/stack/O = new T(src) - if(istype(O,/obj/item/stack/medical)) - O.max_amount = STANDARD_MAX_KIT - modules += O - O.amount = 1 - return - /obj/item/weapon/robot_module/medical name = "medical robot module" + module_holder = "medical" + quirk_flags = MODULE_CAN_HANDLE_MEDICAL | MODULE_CAN_HANDLE_CHEMS + networks = list(CAMERANET_MEDBAY) + radio_key = /obj/item/device/encryptionkey/headset_med + sprites = list( + "Default" = "medbot", + "Needles" = "needles", + "Surgeon" = "surgeon", + "EVE" = "eve", + "Droid" = "droid-medical", + "Marina" = "marina", + "Sleek" = "sleekmedic", + "#17" = "servbot-medi", + "Kodiak - 'Arachne'" = "arachne", + "Noble" = "Noble-MED", + "R34 - MED6a 'Gibbs'" = "gibbs" + ) + speed_modifier = CYBORG_MEDICAL_SPEED_MODIFIER + respawnables = list ( + /obj/item/stack/medical/advanced/bruise_pack, + /obj/item/stack/medical/advanced/ointment, + /obj/item/stack/medical/splint + ) + respawnables_max_amount = MEDICAL_MAX_KIT -#define MEDBORG_MAX_KIT 10 /obj/item/weapon/robot_module/medical/New() ..() @@ -177,16 +273,16 @@ modules += new /obj/item/weapon/inflatable_dispenser/robot(src) modules += new /obj/item/roller_holder(src) var/obj/item/stack/medical/advanced/bruise_pack/B = new /obj/item/stack/medical/advanced/bruise_pack(src) - B.max_amount = MEDBORG_MAX_KIT - B.amount = MEDBORG_MAX_KIT + B.max_amount = MEDICAL_MAX_KIT + B.amount = MEDICAL_MAX_KIT modules += B var/obj/item/stack/medical/advanced/ointment/O = new /obj/item/stack/medical/advanced/ointment(src) - O.max_amount = MEDBORG_MAX_KIT - O.amount = MEDBORG_MAX_KIT + O.max_amount = MEDICAL_MAX_KIT + O.amount = MEDICAL_MAX_KIT modules += O var/obj/item/stack/medical/splint/S = new /obj/item/stack/medical/splint(src) - S.max_amount = MEDBORG_MAX_KIT - S.amount = MEDBORG_MAX_KIT + S.max_amount = MEDICAL_MAX_KIT + S.amount = MEDICAL_MAX_KIT modules += S emag = new /obj/item/weapon/reagent_containers/spray(src) emag.reagents.add_reagent(PACID, 250) @@ -196,34 +292,37 @@ fix_modules() -/obj/item/weapon/robot_module/medical/respawn_consumable(var/mob/living/silicon/robot/R) - var/list/what = list ( - /obj/item/stack/medical/advanced/bruise_pack, - /obj/item/stack/medical/advanced/ointment, - /obj/item/stack/medical/splint, - ) - for (var/T in what) - if (!(locate(T) in modules)) - modules -= null - var/obj/item/stack/O = new T(src) - if(istype(O,/obj/item/stack/medical)) - O.max_amount = MEDBORG_MAX_KIT - modules += O - O.amount = 1 - return - - /obj/item/weapon/robot_module/engineering name = "engineering robot module" + module_holder = "engineer" + quirk_flags = MODULE_CAN_BE_PUSHED | MODULE_HAS_MAGPULSE | MODULE_CAN_LIFT_ENGITAPE + networks = list(CAMERANET_ENGI) + radio_key = /obj/item/device/encryptionkey/headset_eng + sprites = list( + "Default" = "engibot", + "Engiseer" = "engiseer", + "Landmate" = "landmate", + "Wall-E" = "wall-e", + "Droid" = "droid-engineer", + "Marina" = "marinaEN", + "Sleek" = "sleekengineer", + "#25" = "servbot-engi", + "Kodiak" = "kodiak-eng", + "Noble" = "Noble-ENG", + "R34 - ENG7a 'Conagher'" = "conagher" + ) + speed_modifier = CYBORG_ENGINEERING_SPEED_MODIFIER + respawnables = list (/obj/item/stack/cable_coil) + respawnables_max_amount = ENGINEERING_MAX_COIL /obj/item/weapon/robot_module/engineering/New() ..() modules += new /obj/item/weapon/crowbar(src) - modules += new /obj/item/device/rcd/borg/engineering(src) - modules += new /obj/item/device/rcd/rpd(src) //What could possibly go wrong? modules += new /obj/item/weapon/extinguisher(src) modules += new /obj/item/weapon/extinguisher/foam(src) + modules += new /obj/item/device/rcd/borg/engineering(src) + modules += new /obj/item/device/rcd/rpd(src) //What could possibly go wrong? modules += new /obj/item/weapon/weldingtool/largetank(src) modules += new /obj/item/weapon/screwdriver(src) modules += new /obj/item/weapon/wrench(src) @@ -233,14 +332,14 @@ modules += new /obj/item/device/analyzer(src) modules += new /obj/item/taperoll/atmos(src) modules += new /obj/item/taperoll/engineering(src) - modules += new /obj/item/device/rcd/tile_painter(src) modules += new /obj/item/device/material_synth/robot/engiborg(src) modules += new /obj/item/device/silicate_sprayer(src) modules += new /obj/item/device/holomap(src) modules += new /obj/item/weapon/inflatable_dispenser/robot(src) + modules += new /obj/item/borg/fire_shield var/obj/item/stack/cable_coil/W = new /obj/item/stack/cable_coil(src) - W.amount = 50 - W.max_amount = 50 + W.amount = ENGINEERING_MAX_COIL + W.max_amount = ENGINEERING_MAX_COIL modules += W emag = new /obj/item/borg/stun(src) @@ -248,46 +347,24 @@ fix_modules() - -/obj/item/weapon/robot_module/engineering/respawn_consumable(var/mob/living/silicon/robot/R) - var/list/what = list ( - /obj/item/stack/cable_coil - ) - for (var/T in what) - if (!(locate(T) in modules)) - modules -= null - var/obj/item/stack/O = new T(src) - if(istype(O,/obj/item/stack/cable_coil)) - O.max_amount = 50 - modules += O - O.amount = 1 - return - -/obj/item/weapon/robot_module/engineering/recharge_consumable(var/mob/living/silicon/robot/R) - for(var/T in modules) - if(!(locate(T) in modules)) //Remove nulls - modules -= null - - recharge_tick++ - if(recharge_tick < recharge_time) - return FALSE - recharge_tick = 0 - if(R && R.cell) - respawn_consumable(R) - var/list/um = R.contents|R.module.modules - // ^ makes sinle list of active (R.contents) and inactive modules (R.module.modules) - for(var/obj/item/stack/O in um) - // Engineering - if(istype(O,/obj/item/stack/cable_coil)) - if(O.amount < 50) - O.amount += 1 - R.cell.use(50) //Take power from the borg... - if(O.amount > 50) - O.amount = 50 - - /obj/item/weapon/robot_module/security name = "security robot module" + module_holder = "security" + quirk_flags = MODULE_IS_THE_LAW | MODULE_CAN_LIFT_SECTAPE + radio_key = /obj/item/device/encryptionkey/headset_sec + sprites = list( + "Default" = "secbot", + "Bloodhound" = "bloodhound", + "Securitron" = "securitron", + "Droid 'Black Knight'" = "droid-security", + "Marina" = "marinaSC", + "Sleek" = "sleeksecurity", + "#9" = "servbot-sec", + "Kodiak" = "kodiak-sec", + "Noble" = "Noble-SEC", + "R34 - SEC10a 'Woody'" = "woody" + ) + speed_modifier = CYBORG_SECURITY_SPEED_MODIFIER /obj/item/weapon/robot_module/security/New() ..() @@ -307,6 +384,21 @@ /obj/item/weapon/robot_module/janitor name = "janitorial robot module" + module_holder = "janitor" + quirk_flags = MODULE_CAN_BE_PUSHED | MODULE_CLEAN_ON_MOVE + sprites = list( + "Default" = "janbot", + "Mechaduster" = "mechaduster", + "HAN-D" = "han-d", + "Mop Gear Rex" = "mopgearrex", + "Droid - 'Mopbot'" = "droid-janitor", + "Marina" = "marinaJN", + "Sleek" = "sleekjanitor", + "#29" = "servbot-jani", + "Noble" = "Noble-JAN", + "R34 - CUS3a 'Flynn'" = "flynn" + ) + speed_modifier = CYBORG_JANITOR_SPEED_MODIFIER /obj/item/weapon/robot_module/janitor/New() ..() @@ -324,25 +416,40 @@ fix_modules() - - /obj/item/weapon/robot_module/butler name = "service robot module" + module_holder = "service" + quirk_flags = MODULE_CAN_BE_PUSHED | MODULE_CAN_HANDLE_CHEMS | MODULE_CAN_HANDLE_FOOD | MODULE_CAN_BUY + radio_key = /obj/item/device/encryptionkey/headset_service + sprites = list( + "Default - 'Butler'" = "servbot_m", + "Default - 'Waitress'" = "servbot_f", + "Default - 'Bro'" = "brobot", + "Default - 'Maximillion'" = "maximillion", + "Default - 'Hydro'" = "hydrobot", + "Toiletbot" = "toiletbot", + "Marina" = "marinaSV", + "Sleek" = "sleekservice", + "#27" = "servbot-service", + "Kodiak - 'Teddy'" = "kodiak-service", + "Noble" = "Noble-SRV", + "R34 - SRV9a 'Llyod'" = "lloyd" + ) + languages = list( + LANGUAGE_UNATHI, + LANGUAGE_CATBEAST, + LANGUAGE_SKRELLIAN, + LANGUAGE_GREY, + LANGUAGE_CLATTER, + LANGUAGE_VOX, + LANGUAGE_GOLEM, + LANGUAGE_SLIME, + ) + speed_modifier = CYBORG_SERVICE_SPEED_MODIFIER /obj/item/weapon/robot_module/butler/New() ..() - languages = list( - LANGUAGE_GALACTIC_COMMON = TRUE, - LANGUAGE_UNATHI = TRUE, - LANGUAGE_CATBEAST = TRUE, - LANGUAGE_SKRELLIAN = TRUE, - LANGUAGE_ROOTSPEAK = TRUE, - LANGUAGE_TRADEBAND = TRUE, - LANGUAGE_GUTTER = TRUE, - LANGUAGE_MONKEY = TRUE, - ) - modules += new /obj/item/weapon/crowbar(src) modules += new /obj/item/weapon/extinguisher/mini(src) modules += new /obj/item/weapon/gripper/service(src) @@ -362,24 +469,41 @@ /obj/item/weapon/robot_module/miner name = "supply robot module" + module_holder = "miner" + networks = list(CAMERANET_MINE) + radio_key = /obj/item/device/encryptionkey/headset_mining + sprites = list( + "Default" = "minerbot", + "Treadhead" = "miner", + "Wall-A" = "wall-a", + "Droid" = "droid-miner", + "Marina" = "marinaMN", + "Sleek" = "sleekminer", + "#31" = "servbot-miner", + "Kodiak" = "kodiak-miner", + "Noble" = "Noble-SUP", + "R34 - MIN2a 'Ishimura'" = "ishimura" + ) + speed_modifier = CYBORG_SUPPLY_SPEED_MODIFIER + respawnables = list (/obj/item/stack/package_wrap) + respawnables_max_amount = SUPPLY_MAX_WRAP /obj/item/weapon/robot_module/miner/New() ..() modules += new /obj/item/weapon/crowbar(src) modules += new /obj/item/weapon/extinguisher/mini(src) - modules += new /obj/item/weapon/storage/bag/ore(src) + modules += new /obj/item/weapon/storage/bag/ore/auto(src) modules += new /obj/item/weapon/pickaxe/drill/borg(src) modules += new /obj/item/weapon/storage/bag/sheetsnatcher/borg(src) modules += new /obj/item/device/mining_scanner(src) modules += new /obj/item/weapon/gun/energy/kinetic_accelerator/cyborg(src) modules += new /obj/item/weapon/gripper/no_use/inserter(src) - var/obj/item/device/destTagger/tag = new /obj/item/device/destTagger(src) - tag.mode = 1 //For editing the tag list - modules += tag + modules += new /obj/item/device/destTagger/cyborg(src) + modules += new /obj/item/device/gps/cyborg(src) var/obj/item/stack/package_wrap/W = new /obj/item/stack/package_wrap(src) - W.amount = 24 - W.max_amount = 24 + W.amount = SUPPLY_MAX_WRAP + W.max_amount = SUPPLY_MAX_WRAP modules += W emag = new /obj/item/borg/stun(src) @@ -387,21 +511,16 @@ fix_modules() -/obj/item/weapon/robot_module/miner/respawn_consumable(var/mob/living/silicon/robot/R) - var/list/what = list ( - /obj/item/stack/package_wrap - ) - for (var/T in what) - if (!(locate(T) in modules)) - modules -= null - var/obj/item/stack/O = new T(src) - if(istype(O,/obj/item/stack/package_wrap)) - O.max_amount = 24 - modules += O - O.amount = 1 - /obj/item/weapon/robot_module/syndicate name = "syndicate robot module" + module_holder = "malf" + quirk_flags = null + networks = list(CAMERANET_NUKE) + radio_key = /obj/item/device/encryptionkey/syndicate + sprites = list( + "Droid - 'Rottweiler'" = "rottweiler-combat" + ) + speed_modifier = CYBORG_SYNDICATE_SPEED_MODIFIER /obj/item/weapon/robot_module/syndicate/New() ..() @@ -417,6 +536,21 @@ /obj/item/weapon/robot_module/combat name = "combat robot module" + module_holder = "malf" + quirk_flags = MODULE_IS_THE_LAW + radio_key = /obj/item/device/encryptionkey/headset_sec + sprites = list( + "Bladewolf" = "bladewolf", + "Bladewolf MK-2" = "bladewolfmk2", + "Mr. Gutsy" = "mrgutsy", + "Droid" = "droid-combat", + "Droid - 'Rottweiler'" = "rottweiler-combat", + "Marina" = "marinaCB", + "#41" = "servbot-combat", + "Kodiak - 'Grizzly'" = "kodiak-combat", + "R34 - WAR8a 'Chesty'" = "chesty" + ) + speed_modifier = CYBORG_COMBAT_SPEED_MODIFIER /obj/item/weapon/robot_module/combat/New() ..() @@ -436,6 +570,12 @@ /obj/item/weapon/robot_module/tg17355 name = "tg17355 robot module" + module_holder = "brobot" + sprites = list( + "Peacekeeper" = "peaceborg", + "Omoikane" = "omoikane" + ) + speed_modifier = CYBORG_TG17355_SPEED_MODIFIER /obj/item/weapon/robot_module/tg17355/New() ..() @@ -450,17 +590,4 @@ sensor_augs = list("Medical", "Disable") - fix_modules() - -/obj/item/weapon/robot_module/proc/add_languages(var/mob/living/silicon/robot/R) - for(var/language in languages) - if(R.add_language(language, languages[language])) - added_languages |= language - -/obj/item/weapon/robot_module/proc/remove_languages(var/mob/living/silicon/robot/R) - for(var/language in added_languages) - R.remove_language(language) - added_languages.len = 0 - -#undef STANDARD_MAX_KIT -#undef MEDBORG_MAX_KIT + fix_modules() \ No newline at end of file diff --git a/code/modules/mob/living/silicon/robot/robot_movement.dm b/code/modules/mob/living/silicon/robot/robot_movement.dm index 0e64c9be385..14ffb83d9eb 100644 --- a/code/modules/mob/living/silicon/robot/robot_movement.dm +++ b/code/modules/mob/living/silicon/robot/robot_movement.dm @@ -1,33 +1,33 @@ -/mob/living/silicon/robot/Process_Spacemove(var/check_drift = 0) +/mob/living/silicon/robot/Process_Spaceslipping(var/prob_slip = 5) + if(module && (module.quirk_flags & MODULE_HAS_MAGPULSE)) // The magic of magnets. + return FALSE + ..() + +/mob/living/silicon/robot/CheckSlip() + return ((module && (module.quirk_flags & MODULE_HAS_MAGPULSE))? -1 : 0) + +/mob/living/silicon/robot/Process_Spacemove(var/check_drift = FALSE) if(module) for(var/obj/item/weapon/tank/jetpack/J in module.modules) if(J && istype(J, /obj/item/weapon/tank/jetpack)) if(((!check_drift) || (check_drift && J.stabilization_on)) && (J.allow_thrust(0.01, src))) - inertia_dir = 0 - return 1 + inertia_dir = FALSE + return TRUE if((!check_drift && J.allow_thrust(0.01))) - return 1 + return TRUE if(..()) - return 1 - return 0 + return TRUE + return FALSE - //No longer needed, but I'll leave it here incase we plan to re-use it. /mob/living/silicon/robot/movement_tally_multiplier() . = ..() if(is_component_functioning("power cell") && cell) if(module_active && istype(module_active,/obj/item/borg/combat/mobility)) - . *= CYBORG_MOBILITY_MODULE_MODIFIER - if(src.cell.charge <= 0) - . += CYBORG_NO_CHARGE_SLOWDOWN + . *= SILICON_MOBILITY_MODULE_SPEED_MODIFIER + if(cell.charge <= 0) + . *= SILICON_NO_CHARGE_SLOWDOWN + else + if(module) + . *= module.speed_modifier else - . += CYBORG_NO_CELL_SLOWDOWN - -/mob/living/silicon/robot/Move(NewLoc, Dir = 0, step_x = 0, step_y = 0, glide_size_override = 0) - if(..()) - if(istype(NewLoc, /turf/unsimulated/floor/asteroid) && istype(module, /obj/item/weapon/robot_module/miner)) - var/obj/item/weapon/storage/bag/ore/ore_bag = locate(/obj/item/weapon/storage/bag/ore) in get_all_slots() //find it in our modules - if(ore_bag) - var/atom/newloc = NewLoc //NewLoc isn't actually typecast - for(var/obj/item/weapon/ore/ore in newloc.contents) - ore_bag.preattack(NewLoc, src, 1) //collects everything - break + . *= SILICON_NO_CELL_SLOWDOWN diff --git a/code/modules/mob/living/silicon/robot/robot_verbs.dm b/code/modules/mob/living/silicon/robot/robot_verbs.dm new file mode 100644 index 00000000000..07e1ba2819c --- /dev/null +++ b/code/modules/mob/living/silicon/robot/robot_verbs.dm @@ -0,0 +1,155 @@ +/mob/living/silicon/robot/verb/Namepick() + set category = "Robot Commands" + + if(incapacitated()) + return + + if(!namepick_uses) + to_chat(src, "You cannot choose your name any more.") + return FALSE + namepick_uses-- + + var/newname + for(var/i = 1 to 3) + newname = reject_bad_name(stripped_input(src,"You are a [braintype]. Enter a name, or leave blank for the default name.", "Name change [4-i] [0-i != 1 ? "tries":"try"] left",""),1,MAX_NAME_LEN) + if(newname == null) + if(alert(src,"Are you sure you want the default name?",,"Yes","No") == "Yes") + break + else + if(alert(src,"Do you really want the name:\n[newname]?",,"Yes","No") == "Yes") + break + + custom_name = newname + updatename() + updateicon() + if(newname) + to_chat(src, "You have changed your name to [newname]. You can change your name [namepick_uses] more times.") + else + to_chat(src, "You have reset your name. You can change your name [namepick_uses] more times.") + +/mob/living/silicon/robot/verb/cmd_robot_alerts() + set category = "Robot Commands" + set name = "Show Alerts" + + if(isDead() || !is_component_functioning("comms")) + return + + robot_alerts() + +// this verb lets cyborgs see the stations manifest +/mob/living/silicon/robot/verb/cmd_station_manifest() + set category = "Robot Commands" + set name = "Show Station Manifest" + + if(!is_component_functioning("comms")) + return + + show_station_manifest() + +/mob/living/silicon/robot/verb/toggle_station_map() + set category = "Robot Commands" + set name = "Toggle Station Holomap" + set desc = "Toggle station holomap on your screen" + + if(isUnconscious()) + return + + station_holomap.toggleHolomap(src) + +/mob/living/silicon/robot/verb/self_diagnosis_verb() + set category = "Robot Commands" + set name = "Self Diagnosis" + + if(!can_diagnose()) + to_chat(src, "Your self-diagnosis component isn't functioning.") + return + + var/dat = self_diagnosis() + var/datum/browser/popup = new(src, "\ref[src]-robotdiagnosis", "Self diagnosis", 730, 270) + popup.set_content(dat) + popup.open() + +/mob/living/silicon/robot/verb/toggle_component() + set category = "Robot Commands" + set name = "Toggle Component" + set desc = "Toggle a component, conserving power." + + if(isDead()) + return + + var/list/installed_components = list() + for(var/V in components) + if(V == "power cell") + continue + var/datum/robot_component/C = components[V] + if(C.installed) + installed_components += V + + var/toggle = input(src, "Which component do you want to toggle?", "Toggle Component") as null|anything in installed_components + if(!toggle) + return + + var/datum/robot_component/C = components[toggle] + if(C.toggled) + C.toggled = FALSE + to_chat(src, "You disable [C.name].") + else + C.toggled = TRUE + to_chat(src, "You enable [C.name].") + +/mob/living/silicon/robot/verb/unlock_own_cover() + set category = "Robot Commands" + set name = "Unlock Cover" + set desc = "Unlocks your own cover if it is locked. You can not lock it again. A human will have to lock it for you." + + if(!isDead() && locked) + switch(alert("You can not lock your cover again, are you sure?\n (You can still ask for a human to lock it)", "Unlock Own Cover", "Yes", "No")) + if("Yes") + locked = FALSE + updateicon() + to_chat(usr, "You unlock your cover.") + +/mob/living/silicon/robot/verb/sensor_mode() + set name = "Set Sensor Augmentation" + set category = "Robot Commands" + + if(incapacitated()) + return + + if(!istype(module) || !istype(module.sensor_augs) || !module.sensor_augs.len) + to_chat(src, "No Sensor Augmentations located or no module has been equipped.") + return + var/sensor_type + if(module.sensor_augs.len == 2) // Only one choice so toggle between it. + if(!sensor_mode) + sensor_type = module.sensor_augs[1] + else + sensor_type = "Disable" + else + sensor_type = input("Please select sensor type.", "Sensor Integration", null) as null|anything in module.sensor_augs + if(sensor_type) + switch(sensor_type) + if("Security") + sensor_mode = SEC_HUD + to_chat(src, "Security records overlay enabled.") + if("Medical") + sensor_mode = MED_HUD + to_chat(src, "Life signs monitor overlay enabled.") + if("Light Amplification") + sensor_mode = NIGHT + to_chat(src, "Light amplification mode enabled.") + if("Mesons") + var/area/A = get_area(src) + if(A.flags & NO_MESONS) + to_chat(src, "Unable to initialize Meson Vision. Probable cause: [pick("Atmospheric anomaly","Poor boot paramater","Bulb burn-out")]") + else + sensor_mode = MESON_VISION + to_chat(src, "Meson Vision augmentation enabled.") + if("Thermal") + sensor_mode = THERMAL_VISION + to_chat(src, "Thermal Optics augmentation enabled.") + if("Disable") + sensor_mode = 0 + to_chat(src, "Sensor augmentations disabled.") + handle_sensor_modes() + update_sight_hud() diff --git a/code/modules/mob/living/silicon/say.dm b/code/modules/mob/living/silicon/say.dm index 89ec7b09abe..99b5233b560 100644 --- a/code/modules/mob/living/silicon/say.dm +++ b/code/modules/mob/living/silicon/say.dm @@ -33,6 +33,9 @@ /mob/living/silicon/binarycheck() return 1 +/mob/living/silicon/robot/binarycheck() + return is_component_functioning("comms") + /mob/living/silicon/lingcheck() return 0 //Borged or AI'd lings can't speak on the ling channel. diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index 6151af10b5d..2baa41d8d86 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -269,17 +269,24 @@ /mob/living/silicon/can_speak_lang(datum/language/speaking) return universal_speak || (speaking in src.speech_synthesizer_langs) //need speech synthesizer support to vocalize a language -/mob/living/silicon/add_language(var/language, var/can_speak=1) - if (..(language) && can_speak) - speech_synthesizer_langs |= (all_languages[language]) +/mob/living/silicon/add_language(var/language_name, var/can_speak=1) + var/var/datum/language/added_language = all_languages[language_name] + if(!added_language) //Are you trying to pull my leg? This language does not exist. + return + + . = ..(language_name) + if(can_speak && (added_language in languages) && !(added_language in speech_synthesizer_langs)) //This got changed because we couldn't give borgs the ability to speak a language that they already understood. Bay's solution. + speech_synthesizer_langs |= added_language return 1 -/mob/living/silicon/remove_language(var/rem_language) - ..(rem_language) +/mob/living/silicon/remove_language(var/rem_language, var/can_understand=0) + var/var/datum/language/removed_language = all_languages[rem_language] + if(!removed_language) //Oh, look. Now you're trying to remove what does not exist. + return - for (var/datum/language/L in speech_synthesizer_langs) - if (L.name == rem_language) - speech_synthesizer_langs -= L + if(!can_understand) + ..(rem_language) + speech_synthesizer_langs -= removed_language /mob/living/silicon/check_languages() set name = "Check Known Languages" diff --git a/code/modules/mob/living/simple_animal/bees/bees_datums.dm b/code/modules/mob/living/simple_animal/bees/bees_datums.dm index 7acd09a44e2..3c07b3ade1f 100644 --- a/code/modules/mob/living/simple_animal/bees/bees_datums.dm +++ b/code/modules/mob/living/simple_animal/bees/bees_datums.dm @@ -10,6 +10,7 @@ var/state = BEE_ROAMING var/fatigue = 0//increases after a successful pollination or when searching for flowers in vain var/bored = 0//increases when searching for enemies in vain + var/exhaustion = 0//increases when roaming without a queen var/corpse = /obj/effect/decal/cleanable/bee var/toxins = 0 var/datum/bee_species/species = null @@ -42,7 +43,7 @@ state = BEE_HEADING_HOME mob.updateState = 1 -/datum/bee/proc/Die() +/datum/bee/proc/death(var/gibbed = FALSE) if (mob) new corpse(get_turf(mob)) qdel(src) diff --git a/code/modules/mob/living/simple_animal/bees/bees_items.dm b/code/modules/mob/living/simple_animal/bees/bees_items.dm index 94e610b0cfd..35d8e3024a6 100644 --- a/code/modules/mob/living/simple_animal/bees/bees_items.dm +++ b/code/modules/mob/living/simple_animal/bees/bees_items.dm @@ -11,6 +11,9 @@ */ + +#define MAX_BEES_PER_NET 100 + /obj/item/queen_bee name = "queen bee packet" desc = "Place her into an apiary so she can get busy." @@ -21,6 +24,9 @@ /obj/item/queen_bee/New() ..() + initialize() + +/obj/item/queen_bee/initialize() species = bees_species[BEESPECIES_NORMAL] /obj/item/weapon/bee_net @@ -49,6 +55,10 @@ var/turf/T = get_turf(A) var/caught = 0 for(var/mob/living/simple_animal/bee/B in T) + if (caught_bees.len >= MAX_BEES_PER_NET) + to_chat(user, "There are too many [current_species.common_name] inside \the [src] already! You have to release some before you can catch more.") + return + if (current_species) if (current_species != B.bee_species) to_chat(user, "You gotta empty \the [src] of [current_species.common_name] before you can catch [B.bee_species.common_name] with it!") @@ -98,9 +108,9 @@ else to_chat(M, "You empty \the [src].") //release a few swarms - while(caught_bees.len > 5) + while(caught_bees.len > 20) var/mob/living/simple_animal/bee/B = new(get_turf(src)) - for (var/i = 1 to 5) + for (var/i = 1 to 20) var/datum/bee/BEE = pick(caught_bees) caught_bees.Remove(BEE) if (current_species.angery) @@ -237,3 +247,5 @@ "} + +#undef MAX_BEES_PER_NET diff --git a/code/modules/mob/living/simple_animal/bees/bees_mob.dm b/code/modules/mob/living/simple_animal/bees/bees_mob.dm index 09b3a3d4261..c3f4d490c26 100644 --- a/code/modules/mob/living/simple_animal/bees/bees_mob.dm +++ b/code/modules/mob/living/simple_animal/bees/bees_mob.dm @@ -7,6 +7,8 @@ #define BOREDOM_TO_RETURN 30//once reached, the bee will head back to its hive +#define EXHAUSTION_TO_DIE 600//once reached, the bee will begin to die + #define MAX_BEES_PER_SWARM 20//explicit /* @@ -31,9 +33,19 @@ /obj/effect/decal/cleanable/bee/New() ..() - dir = pick(cardinal) - pixel_x = rand(-10,10) - pixel_y = rand(-4,4) + var/image/I = image(icon,icon_state) + I.pixel_x = rand(-10,10) + I.pixel_y = rand(-4,4) + I.dir = pick(cardinal) + + for (var/obj/effect/decal/cleanable/bee/corpse in get_turf(src)) + if (corpse != src) + corpse.overlays += I + qdel(src) + return + else + icon_state = "bees0" + overlays += I /obj/effect/decal/cleanable/bee/queen_bee name = "dead queen bee" @@ -66,6 +78,7 @@ var/obj/machinery/portable_atmospherics/hydroponics/target_plant = null var/list/visited_plants = list() var/datum/bee_species/bee_species = null + var/turf/building = null pass_flags = PASSTABLE turns_per_move = 6 density = 0 @@ -108,7 +121,8 @@ visited_plants.len = 0 ..() -/mob/living/simple_animal/bee/Die() +/mob/living/simple_animal/bee/death(var/gibbed = FALSE) + ..(gibbed) returnToPool(src) /mob/living/simple_animal/bee/gib() @@ -202,7 +216,7 @@ amount = 0 else amount -= B.health - B.Die() + B.death() if (bees.len <= 0) qdel(src) @@ -238,8 +252,8 @@ for (var/datum/bee/BEE in bees) total_brute += BEE.damage total_toxic += BEE.toxic - current_physical_damage = total_brute/2//1 regular bee = 0.5 brute; 20 regular bees = 10 brute; 20 mutated(2 damage) bees = 20 brute; - current_poison_damage = bees.len + (total_toxic/bees.len)/100//1 regular bee = 1 tox; 20 regular bees = 20 tox; 20 intoxicated(100 toxic) bees = 40 tox; + current_physical_damage = (total_brute/2)*bee_species.damage_coef//1 regular bee = 0.5 brute; 20 regular bees = 10 brute; 20 mutated(2 damage) bees = 20 brute; + current_poison_damage = (bees.len + (total_toxic/bees.len)/100)*bee_species.toxic_coef//1 regular bee = 1 tox; 20 regular bees = 20 tox; 20 intoxicated(100 toxic) bees = 40 tox; update_icon() /mob/living/simple_animal/bee/proc/panic_attack(mob/damagesource) @@ -247,13 +261,15 @@ return for(var/mob/living/simple_animal/bee/B in range(src,3)) - if (B.state == BEE_SWARM || calmed > 0) - return + if (B.state == BEE_SWARM || B.state == BEE_BUILDING || B.calmed > 0) + continue //only their friends from the same apiary will answer their call. homeless bees will also help each others. if (B.home == home) - B.state = BEE_OUT_FOR_ENEMIES - B.target = damagesource + B.mood_change(BEE_OUT_FOR_ENEMIES,damagesource) + + if (state == BEE_SWARM || state == BEE_BUILDING || calmed > 0) + mood_change(BEE_OUT_FOR_ENEMIES,damagesource) /mob/living/simple_animal/bee/proc/add_plants(var/list/new_plants) if(!new_plants || new_plants.len <= 0) return @@ -262,6 +278,11 @@ if (!visited_plants.Find(new_plant)) visited_plants.Add(new_plant) +/mob/living/simple_animal/bee/resetVariables() + ..("bees", "visited_plants", args) + bees = list() + visited_plants = list() + ////////////////////////////////LIFE//////////////////////////////////////// /mob/living/simple_animal/bee/Life() @@ -274,6 +295,9 @@ qdel(src) return + if (!bee_species.slow && !target) + walk(src,0) + if(stat != DEAD) //SUFFERING FROM HIGH TOXICITY if (((current_poison_damage - bees.len)/bees.len*100) > bee_species.toxic_threshold_death) @@ -302,15 +326,11 @@ fighters.Add(B) if (swarmers.len > 0) // this intent comes from a queen, and thus overrides the intents of every other bee in the swarm - for (var/datum/bee/B in bees) - B.state = BEE_SWARM - B.home = destination - home = destination - state = BEE_SWARM + mood_change(BEE_SWARM,null,destination) if (home_goers.len > 0) if (home_goers.len == bees.len) - state = BEE_HEADING_HOME + mood_change(BEE_HEADING_HOME) else var/mob/living/simple_animal/bee/B_mob = getFromPool(/mob/living/simple_animal/bee,T) @@ -322,7 +342,7 @@ if (pollinaters.len > 0) if (pollinaters.len == bees.len) - state = BEE_OUT_FOR_PLANTS + mood_change(BEE_OUT_FOR_PLANTS) else var/mob/living/simple_animal/bee/B_mob = getFromPool(/mob/living/simple_animal/bee,T) @@ -333,7 +353,7 @@ B_mob.updateState = 1 if (fighters.len > 0) - state = BEE_OUT_FOR_ENEMIES + mood_change(BEE_OUT_FOR_ENEMIES) //CALMING BEES @@ -352,12 +372,7 @@ for(var/this_type in calmers) var/obj/effect/check_effect = locate(this_type) in src.loc if(check_effect && (check_effect.reagents.has_reagent(WATER) || check_effect.reagents.has_reagent(HOLYWATER))) - calmed = 6 - if (state == BEE_OUT_FOR_ENEMIES) - src.visible_message("The bees calm down!") - for (var/datum/bee/B) - B.state = BEE_HEADING_HOME - state = BEE_HEADING_HOME + calming() break @@ -379,7 +394,7 @@ B_mob.calmed = calmed B_mob.state = state B_mob.home = home - B_mob.Move(get_turf(pick(orange(src,1)))) + step_rand(B_mob) //ATTACKING TARGET else if(state == BEE_OUT_FOR_ENEMIES && M in view(src,1)) @@ -395,17 +410,31 @@ var/bio_block = min(worn_helmet.armor["bio"],30) var/perm_block = 30-30*worn_helmet.permeability_coefficient sting_prob -= max(bio_block,perm_block) // Is your helmet sealed? I can't get to 30% of your body. - if(prob(sting_prob)) + var/brute_damage = current_physical_damage + var/tox_damage = current_poison_damage + var/direct = 1 + prob(sting_prob) + if (direct < 2) + if (prob(bee_species.pierce_chance)) + brute_damage = brute_damage*bee_species.pierce_damage/100 + tox_damage = tox_damage*bee_species.pierce_damage/100 + else + direct = 0 + if (direct) M.apply_damage(current_physical_damage, BRUTE) M.apply_damage(current_poison_damage, TOX) - M.visible_message("\The [src] are stinging \the [M]!", "You have been stung by \the [src]!") + if (direct > 1) + M.visible_message("\The [src] are stinging \the [M]!", "You have been stung by \the [src]!") + else + M.visible_message("\The [src] are stinging \the [M] through their protection!", "You have been stung by \the [src] through your protection!") M.flash_pain() + else + M.visible_message("\The [M]'s protection shields them from \the [src]!", "Your protection shields you from \the [src]!") //MAKING NOISE if(prob(1)) if(prob(50)) src.visible_message("[pick("Buzzzz.","Hmmmmm.","Bzzz.")]") - playsound(get_turf(src), 'sound/effects/bees.ogg', min(20 * bees.len, 100), 1) + playsound(src, 'sound/effects/bees.ogg', min(20 * bees.len, 100), 1) //GROUPING WITH OTHER BEES @@ -418,6 +447,9 @@ if(B_mob.home != home) continue + if(B_mob.bee_species != bee_species) + continue + //no more than 20 bees per swarm to avoid people abusing their damage if(bees.len + B_mob.bees.len > MAX_BEES_PER_SWARM) continue @@ -443,27 +475,31 @@ updateDamage() //SPREADING OUT - if(bees.len > 1 && pollinating <= 0 && prob(bees.len*2) && state != BEE_SWARM && state != BEE_HEADING_HOME) - var/mob/living/simple_animal/bee/B_mob = getFromPool(/mob/living/simple_animal/bee,get_turf(src)) - var/datum/bee/B = pick(bees) - B_mob.addBee(B) - bees.Remove(B) - B_mob.calmed = calmed - B_mob.state = state - B_mob.target = target - B_mob.update_icon() - B_mob.home = home - B_mob.add_plants(visited_plants) - B_mob.Move(get_turf(pick(orange(src,1)))) - updateDamage() + if(bees.len > 1 && pollinating <= 0 && prob(bees.len*2) && state != BEE_SWARM && state != BEE_BUILDING && state != BEE_HEADING_HOME) + var/queen = 0 + for (var/single_B in bees) + if (istype(single_B,/datum/bee/queen_bee)) + queen = 1 + break + if (state != BEE_ROAMING || !queen)//homeless bees spread out if there's no queen among them + var/mob/living/simple_animal/bee/B_mob = getFromPool(/mob/living/simple_animal/bee,get_turf(src)) + var/datum/bee/B = pick(bees) + B_mob.addBee(B) + bees.Remove(B) + B_mob.calmed = calmed + B_mob.mood_change(state,target,home) + B_mob.update_icon() + B_mob.add_plants(visited_plants) + step_rand(B_mob) + updateDamage() //REACHING FOR MOBS if(state == BEE_OUT_FOR_ENEMIES) - var/turf/target_turf = null + var/turf/target_turf = null//we have a target! if(target && (target in view(src,7)) && target.stat != DEAD) target_turf = get_turf(target) wander = 0 - else + else//no target? let's find one! target = null var/list/nearbyMobs = list() for(var/mob/living/G in view(src,7)) @@ -489,13 +525,21 @@ else for (var/datum/bee/B in bees) B.bored++ - if (B.bored > BOREDOM_TO_RETURN && B.home && !B.home.wild) - B.homeCall() + if (B.bored > BOREDOM_TO_RETURN) + if (B.home) + if (!B.home.wild) + B.homeCall() + else + mood_change(BEE_ROAMING) + for (var/datum/bee/B_single in bees) + B_single.bored = 0 + break - if(target_turf) - var/tdir = get_dir(src,target_turf) - var/turf/move_to = get_step(src, tdir) - walk_to(src,move_to) + if(target_turf)//got a target? let's move toward them now. + if (bee_species.slow) + step_to(src, target_turf)//1 step per Life() + else + walk_to(src, target, 0, 2) if(src.loc == target_turf) wander = 1 @@ -520,10 +564,8 @@ if (B.fatigue > FATIGUE_TO_RETURN) B.homeCall() if(target_turf) - var/tdir = get_dir(src,target_turf) - var/turf/move_to = get_step(src, tdir) if (calmed <= 0) - walk_to(src,move_to) + step_to(src, target_turf) if(src.loc == target_turf) visited_plants.Add(target_plant) @@ -547,10 +589,8 @@ wander = 0 var/turf/target_turf = get_turf(home) if(target_turf) - var/tdir = get_dir(src,target_turf) - var/turf/move_to = get_step(src, tdir) if (calmed <= 0) - walk_to(src,move_to) + step_to(src, target_turf) if(src.loc == target_turf) if (!home.species || bee_species == home.species) @@ -558,21 +598,116 @@ home.enterHive(B) qdel(src) else + visible_message("A swarm has lost its way.") home = null - state = BEE_ROAMING + mood_change(BEE_ROAMING) else - state = BEE_ROAMING + visible_message("A swarm has lost its way.") + home = null + mood_change(BEE_ROAMING) //BEING LOST if(state == BEE_ROAMING) wander = 1 - if (home && home.loc) - state = BEE_HEADING_HOME + for (var/datum/bee/B in bees) + B.home = null + home = null + //if there's a queen among us, let's gather a following + var/datum/bee/queen_bee/queen = null + for (var/D in bees) + if (istype(D,/datum/bee/queen_bee)) + queen = D + if (queen) + if (bees.len < 11) + var/turf/T = get_turf(loc) + for(var/mob/living/simple_animal/bee/B in range(src,3)) + if (bee_species == B.bee_species && B.state == BEE_ROAMING && B.loc != T) + step_to(B, T)//come closer, the GROUPING segment above should take care of the merging after a moment. + else + //once there's enough of us, let's find a new home + for(var/obj/machinery/apiary/A in range(src,3)) + if (exile_swarm(A)) + mood_change(BEE_SWARM,null,A) + A.reserve_apiary(src) + queen.colonizing = 1 + update_icon() + return + + //and if there isn't any decent home nearby...let's build one! + var/list/available_turfs = list() + for (var/turf/simulated/floor/T in range(src,2)) + if(!T.has_dense_content() && !(locate(/obj/structure/wild_apiary) in T)) + available_turfs.Add(T) + if (available_turfs.len>0) + building = pick(available_turfs) + if (building) + mood_change(BEE_BUILDING) + + + else + for (var/datum/bee/B in bees) + B.exhaustion++ + if (B.exhaustion > EXHAUSTION_TO_DIE) + adjustBruteLoss(1) + + if (state == BEE_ROAMING && home && home.loc) + mood_change(BEE_HEADING_HOME) + + + //BUILDING A WILD APIARY + if(state == BEE_BUILDING) + wander = 0 + var/datum/bee/queen_bee/queen = null + for (var/D in bees) + if (istype(D,/datum/bee/queen_bee)) + queen = D + if(queen && building) + if (bees.len < 20)//Gathering some more volunteers. + var/turf/T = get_turf(loc) + for(var/mob/living/simple_animal/bee/B in range(src,3)) + if (bee_species == B.bee_species && B.state == BEE_ROAMING && B.loc != T) + step_to(B, T) + + if (building != loc) + step_to(src, building) + else + var/obj/structure/wild_apiary/W = locate() in building + if (W) + W.work() + else + new /obj/structure/wild_apiary(loc,bee_species.prefix) + else + mood_change(BEE_ROAMING) update_icon() +/mob/living/simple_animal/bee/proc/exile_swarm(var/obj/machinery/apiary/A) + if (A in apiary_reservation)//another queen has marked this one for herself + return 0 + if (A.queen_bees_inside > 0 || locate(/datum/bee/queen_bee) in A.bees_outside_hive)//another queen made her way there somehow + return 0 + return 1 + +/mob/living/simple_animal/bee/proc/mood_change(var/new_mood,var/new_target=null,var/new_home=null) + for(var/datum/bee/B in bees) + B.state = new_mood + if (new_home) + B.home = new_home + state = new_mood + if (new_target) + target = new_target + if (new_home) + home = new_home + + +/mob/living/simple_animal/bee/proc/calming() + calmed = 6 + if (state == BEE_OUT_FOR_ENEMIES) + src.visible_message("The bees calm down!") + mood_change(BEE_HEADING_HOME) + ////////////////////////////////UPDATE ICON///////////////////////////////// /mob/living/simple_animal/bee/update_icon() @@ -622,7 +757,7 @@ if(bees.len <= 1) gender = NEUTER - name = "[prefix]bee" + name = "[prefix][common]" for (var/D in bees) if (istype(D,/datum/bee/queen_bee)) name = "[prefix] queen [common]" @@ -648,14 +783,15 @@ update_icon() //BEE-NADE & BEE-ULLET -/mob/living/simple_animal/bee/angry/New(loc, var/obj/machinery/apiary/new_home) +/mob/living/simple_animal/bee/angry/New(loc, var/obj/machinery/apiary/new_home, var/spec=BEESPECIES_NORMAL, var/tox=50,var/dam=2) ..() var/datum/bee/B = new() - B.toxic = 50 - B.damage = 2 - B.state = BEE_OUT_FOR_ENEMIES - state = BEE_OUT_FOR_ENEMIES + B.species = bees_species[spec] + B.toxic = tox + B.damage = dam addBee(B) + mood_change(BEE_OUT_FOR_ENEMIES) + updateDamage() update_icon() //BEE-IEFCASE @@ -665,9 +801,8 @@ var/datum/bee/B = new() B.toxic = 50 B.damage = 2 - B.state = BEE_OUT_FOR_ENEMIES addBee(B) - state = BEE_OUT_FOR_ENEMIES + mood_change(BEE_OUT_FOR_ENEMIES) update_icon() #undef TIME_TO_POLLINATE diff --git a/code/modules/mob/living/simple_animal/bees/bees_species.dm b/code/modules/mob/living/simple_animal/bees/bees_species.dm index 20b4a176b87..7747e7c4178 100644 --- a/code/modules/mob/living/simple_animal/bees/bees_species.dm +++ b/code/modules/mob/living/simple_animal/bees/bees_species.dm @@ -65,9 +65,18 @@ var/maxbodytemp = 360 var/corpse = /obj/effect/decal/cleanable/bee -////////////////////////////////////// -// VOX BEES // -////////////////////////////////////// + var/slow = 1 + var/damage_coef = 1 + var/toxic_coef = 1 + + var/pierce_chance = 0//100 = always pierce through protection + var/pierce_damage = 0//100 = deals 100 of the damage if pierce procs + + var/aggressiveness = 0//100 = always aggressive when coming out of hive + +//////////////////////////////////////================================================================================================================================== +// VOX BEES //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////================================================================================================================================== /datum/bee_species/chill name = "apis chiliverax" @@ -94,6 +103,9 @@ maxbodytemp = 400 corpse = /obj/effect/decal/cleanable/bee/chill + damage_coef = 0 + toxic_coef = 0 + /////////////////BUG DATUM /datum/bee/chill corpse = /obj/effect/decal/cleanable/bee/chill @@ -155,3 +167,96 @@ B.colonizing = 1//so it can start a colony if someone places it in an empty hive addBee(B) update_icon() + + +//////////////////////////////////////================================================================================================================================== +// HORNETS //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////================================================================================================================================== + +/datum/bee_species/hornet + name = "vespa crabro" + common_name = BEESPECIES_HORNET + prefix = "hornet_" + worker_product = null + queen_product = ROYALJELLY + toxic_reagents = list() + + angery = 1 + toxic_threshold_anger = 90//unless you're really pushing it + max_queen_inside = 1 + queen_wanders = 0 + bee_type = /datum/bee/hornet + queen_type = /datum/bee/queen_bee/hornet + + corpse = /obj/effect/decal/cleanable/bee/hornet + + slow = 0 + damage_coef = 3 + toxic_coef = 0.75 + + pierce_chance = 20 + pierce_damage = 40 + + aggressiveness = 100 + +/////////////////BUG DATUM +/datum/bee/hornet + corpse = /obj/effect/decal/cleanable/bee/hornet + +/datum/bee/hornet/New() + ..() + species = bees_species[BEESPECIES_HORNET] + +/////////////////QUEEN BUG DATUM +/datum/bee/queen_bee/hornet + corpse = /obj/effect/decal/cleanable/bee/queen_bee/hornet + +/datum/bee/queen_bee/hornet/New() + ..() + species = bees_species[BEESPECIES_HORNET] + +/////////////////QUEEN BUG PACKET +/obj/item/queen_bee/hornet + name = "hornet queen packet" + desc = "Place her into an apiary so she can get busy. Why would you do that though? It's a terrible idea!" + icon = 'icons/obj/apiary_bees_etc.dmi' + icon_state = "hornet_queen_larvae" + w_class = W_CLASS_TINY + species = null + +/obj/item/queen_bee/hornet/New() + ..() + initialize() + +/obj/item/queen_bee/hornet/initialize() + species = bees_species[BEESPECIES_HORNET] + +/////////////////BUG CORPSES +/obj/effect/decal/cleanable/bee/hornet + name = "dead hornet" + desc = "This one stung for the last time." + icon_state = "hornet_bee_dead" + +/obj/effect/decal/cleanable/bee/queen_bee/hornet + name = "dead hornet queen" + icon_state = "hornet_queen_bee_dead" + +/////////////////TYPES FOR CASUAL SPAWNS +/mob/living/simple_animal/bee/adminSpawned_hornet/New(loc, var/obj/machinery/apiary/new_home) + ..() + initialize() + +/mob/living/simple_animal/bee/adminSpawned_hornet/initialize() + var/datum/bee/hornet/B = new() + addBee(B) + update_icon() + +/mob/living/simple_animal/bee/adminSpawnedQueen_hornet/New(loc, var/obj/machinery/apiary/new_home) + ..() + initialize() + +/mob/living/simple_animal/bee/adminSpawnedQueen_hornet/initialize() + var/datum/bee/queen_bee/hornet/B = new() + B.colonizing = 1//so it can start a colony if someone places it in an empty hive + addBee(B) + update_icon() diff --git a/code/modules/mob/living/simple_animal/borer.dm b/code/modules/mob/living/simple_animal/borer.dm index ed8a121974d..9c2d7faa2e0 100644 --- a/code/modules/mob/living/simple_animal/borer.dm +++ b/code/modules/mob/living/simple_animal/borer.dm @@ -302,7 +302,8 @@ var/global/borer_unlock_types_leg = typesof(/datum/unlockable/borer/leg) - /datu return if (copytext(message, 1, 2) == "*") - return emote(copytext(message, 2)) + to_chat(src, "This type of mob doesn't support this. Use the Me verb instead.") + return if (copytext(message, 1, 2) == ";") //Brain borer hivemind. return borer_speak(copytext(message,2)) @@ -883,7 +884,7 @@ var/global/borer_unlock_types_leg = typesof(/datum/unlockable/borer/leg) - /datu to_chat(src, "You cannot infest a target in your current state.") return - if(M.stat == 2) + if(M.isDead()) to_chat(src, "That is not an appropriate target.") return @@ -1168,6 +1169,8 @@ var/global/borer_unlock_types_leg = typesof(/datum/unlockable/borer/leg) - /datu /mob/living/simple_animal/borer/ClickOn( var/atom/A, var/params ) ..() + if(params2list(params)["shift"]) + return if(host) if(extend_o_arm_unlocked) if(hostlimb == LIMB_RIGHT_ARM || hostlimb == LIMB_LEFT_ARM) diff --git a/code/modules/mob/living/simple_animal/borer/egg.dm b/code/modules/mob/living/simple_animal/borer/egg.dm index ca4e13b710c..a72a0d73641 100644 --- a/code/modules/mob/living/simple_animal/borer/egg.dm +++ b/code/modules/mob/living/simple_animal/borer/egg.dm @@ -17,8 +17,8 @@ var/ping_cooldown = 50 var/list/required_mols=list( - "toxins"=MOLES_PLASMA_VISIBLE, - "oxygen"=5 + "toxins" = MOLES_PLASMA_VISIBLE / CELL_VOLUME, + "oxygen" = 5 / CELL_VOLUME ) /obj/item/weapon/reagent_containers/food/snacks/borer_egg/New() @@ -93,7 +93,7 @@ //testing("[type]/PROCESS() - plasma: [environment.toxins]") var/meets_conditions=1 for(var/gas_id in required_mols) - if((environment.vars[gas_id] / environment.volume * CELL_VOLUME) <= required_mols[gas_id]) + if(environment.molar_density(gas_id) < required_mols[gas_id]) meets_conditions=0 if(meets_conditions) src.Hatch() diff --git a/code/modules/mob/living/simple_animal/borer/unlocks.dm b/code/modules/mob/living/simple_animal/borer/unlocks.dm index f92d474acc5..67844a78ece 100644 --- a/code/modules/mob/living/simple_animal/borer/unlocks.dm +++ b/code/modules/mob/living/simple_animal/borer/unlocks.dm @@ -259,7 +259,7 @@ // This is inefficient, but OK because it doesn't happen often. for(var/block=1;block
      ", (occ["rads"] < 10 ?"" : ""), occ["rads"]) + if(occ["radtick"] > 0) + dat += text("Radiation sickness progression: [occ["radtick"]] Stage: [occ["radstage"]]
      ") dat += text("[]\tGenetic Tissue Damage %: []

      ", (occ["cloneloss"] < 1 ?"" : ""), occ["cloneloss"]) dat += text("[]\tApprox. Brain Damage %: []
      ", (occ["brainloss"] < 1 ?"" : ""), occ["brainloss"]) dat += text("Paralysis Summary %: [] ([] seconds left!)
      ", occ["paralysis"], round(occ["paralysis"] / 4)) diff --git a/code/modules/mob/living/simple_animal/combat.dm b/code/modules/mob/living/simple_animal/combat.dm index 7155b56791e..91044f48435 100644 --- a/code/modules/mob/living/simple_animal/combat.dm +++ b/code/modules/mob/living/simple_animal/combat.dm @@ -15,7 +15,10 @@ /mob/living/simple_animal/unarmed_attack_mob() if(!melee_damage_upper && size == SIZE_TINY) //No nuzzling for mice return - return ..() + if(icon_attack && do_flick(src, icon_attack, icon_attack_time)) + return ..() + else + return ..() /mob/living/simple_animal/get_attack_message(mob/living/target, attack_verb) if(attack_verb == friendly) diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm index d79c64d7aba..b88fb3ff2fd 100644 --- a/code/modules/mob/living/simple_animal/constructs.dm +++ b/code/modules/mob/living/simple_animal/constructs.dm @@ -81,8 +81,8 @@ src.add_spell(new spell, "const_spell_ready") updateicon() -/mob/living/simple_animal/construct/Die() - ..() +/mob/living/simple_animal/construct/death(var/gibbed = FALSE) + ..(TRUE) //If they qdel, they gib regardless for(var/i=0;i<3;i++) new /obj/item/weapon/ectoplasm (src.loc) for(var/mob/M in viewers(src, null)) @@ -90,7 +90,6 @@ M.show_message("[src] collapses in a shattered heap. ") ghostize() qdel (src) - return /mob/living/simple_animal/construct/examine(mob/user) var/msg = "*---------*\nThis is [bicon(src)] \a [src]!\n" @@ -101,6 +100,8 @@ else msg += "It looks severely dented!\n" msg += "" + if(!client) + msg += "The spirit animating it seems to be dormant.\n" msg += "*---------*
      " to_chat(user, msg) @@ -126,7 +127,7 @@ damage *= 2 purge = 3 adjustBruteLoss(damage) - user.do_attack_animation(src, O) + O.on_attack(src, user) user.visible_message("[src] has been attacked with [O] by [user]. ") else to_chat(usr, "This weapon is ineffective, it does no damage.") @@ -159,26 +160,13 @@ construct_spells = list(/spell/aoe_turf/conjure/forcewall/lesser) /mob/living/simple_animal/construct/armoured/attackby(var/obj/item/O as obj, var/mob/user as mob) - user.delayNextAttack(8) - if(O.force) - if(O.force >= 11) - var/damage = O.force - if (O.damtype == HALLOSS) - damage = 0 - adjustBruteLoss(damage) - for(var/mob/M in viewers(src, null)) - if ((M.client && !( M.blinded ))) - M.show_message("\The [src] has been attacked with [O] by [user]. ") - else - for(var/mob/M in viewers(src, null)) - if ((M.client && !( M.blinded ))) - M.show_message("[O] bounces harmlessly off of \the [src]. ") - else - to_chat(usr, "This weapon is ineffective, it does no damage.") + if(O.force && O.force < 11) + user.delayNextAttack(8) for(var/mob/M in viewers(src, null)) if ((M.client && !( M.blinded ))) - M.show_message("[user] gently taps \the [src] with [O]. ") - + M.show_message("[O] bounces harmlessly off of \the [src]. ") + else + ..() /mob/living/simple_animal/construct/armoured/bullet_act(var/obj/item/projectile/P) if(istype(P, /obj/item/projectile/energy) || istype(P, /obj/item/projectile/beam) || istype(P, /obj/item/projectile/forcebolt) || istype(P, /obj/item/projectile/change)) @@ -254,7 +242,7 @@ /////////////////////////////Behemoth///////////////////////// -/mob/living/simple_animal/construct/behemoth +/mob/living/simple_animal/construct/armoured/behemoth name = "\improper Behemoth" real_name = "\improper Behemoth" desc = "The pinnacle of occult technology, Behemoths are the ultimate weapon in the Cult of Nar-Sie's arsenal." @@ -272,30 +260,10 @@ speed = 6 environment_smash_flags = SMASH_LIGHT_STRUCTURES | SMASH_CONTAINERS | SMASH_WALLS attack_sound = 'sound/weapons/heavysmash.ogg' - var/energy = 0 - var/max_energy = 1000 + //var/energy = 0 + //var/max_energy = 1000 construct_spells = list(/spell/aoe_turf/conjure/forcewall/lesser) -/mob/living/simple_animal/construct/behemoth/attackby(var/obj/item/O as obj, var/mob/user as mob) - user.delayNextAttack(8) - if(O.force) - if(O.force >= 11) - var/damage = O.force - if (O.damtype == HALLOSS) - damage = 0 - adjustBruteLoss(damage) - for(var/mob/M in viewers(src, null)) - if ((M.client && !( M.blinded ))) - M.show_message("\The [src] has been attacked with [O] by [user]. ") - else - for(var/mob/M in viewers(src, null)) - if ((M.client && !( M.blinded ))) - M.show_message("\The [O] bounces harmlessly off of [src]. ") - else - to_chat(usr, "This weapon is ineffective, it does no damage.") - for(var/mob/M in viewers(src, null)) - if ((M.client && !( M.blinded ))) - M.show_message("[user] gently taps \the [src] with [O]. ") ////////////////////////Harvester//////////////////////////////// @@ -350,7 +318,7 @@ set category = "Behemoth" set name = "Summon Cultist (300)" set desc = "Teleport a cultist to your location" - if (istype(usr,/mob/living/simple_animal/constructbehemoth)) + if (istype(usr,/mob/living/simple_animal/construct/armoured/behemoth)) if(usr.energy<300) to_chat(usr, "You do not have enough power stored!") @@ -423,7 +391,7 @@ healths.icon_state = "juggernaut_health7" -/mob/living/simple_animal/construct/behemoth/regular_hud_updates() +/mob/living/simple_animal/construct/armoured/behemoth/regular_hud_updates() ..() if(healths) switch(health) diff --git a/code/modules/mob/living/simple_animal/friendly/arcane_golem.dm b/code/modules/mob/living/simple_animal/friendly/arcane_golem.dm index 77968ec15f7..e61147dcc69 100644 --- a/code/modules/mob/living/simple_animal/friendly/arcane_golem.dm +++ b/code/modules/mob/living/simple_animal/friendly/arcane_golem.dm @@ -77,7 +77,7 @@ var/mob/master = master_spell.holder if(istype(master)) if(master.isDead() || isnull(master.loc)) - Die() + death() return //Alive - follow the master @@ -85,8 +85,8 @@ if(canmove) Goto(master, move_to_delay) -/mob/living/simple_animal/hostile/arcane_golem/Die() - ..() +/mob/living/simple_animal/hostile/arcane_golem/death(var/gibbed = FALSE) + ..(gibbed) //Punish the master by putting all of his spells on cooldown if(master_spell) diff --git a/code/modules/mob/living/simple_animal/friendly/cat.dm b/code/modules/mob/living/simple_animal/friendly/cat.dm index dee8a41dcd2..a2c215fb742 100644 --- a/code/modules/mob/living/simple_animal/friendly/cat.dm +++ b/code/modules/mob/living/simple_animal/friendly/cat.dm @@ -56,6 +56,7 @@ icon_living= "salem" icon_dead= "salem_dead" gender = FEMALE + holder_type = /obj/item/weapon/holder/animal/salem /mob/living/simple_animal/cat/kitten name = "kitten" @@ -74,9 +75,9 @@ if((src.loc) && isturf(src.loc)) if(!stat && !resting && !locked_to) for(var/mob/living/simple_animal/mouse/M in view(1,src)) - if(!M.stat) + if(!M.stat && Adjacent(M)) M.splat() - emote("[pick(kill_verbs)] \the [M]!") + visible_message("\The [name] [pick(kill_verbs)] \the [M]!") movement_target = null stop_automated_movement = 0 break @@ -84,8 +85,8 @@ ..() for(var/mob/living/simple_animal/mouse/snack in oview(src, 3)) - if(prob(15)) - emote(pick("[pick(growl_verbs)] at [snack]!", "eyes [snack] hungrily.")) + if(prob(15) && !snack.stat) + emote("me",, pick("[pick(growl_verbs)] at [snack]!", "eyes [snack] hungrily.")) break if(!stat && !resting && !locked_to) @@ -129,6 +130,7 @@ /mob/living/simple_animal/cat/snek/corpus name = "Corpus" + density = 0 var/list/wizard_snakes = list() @@ -141,10 +143,11 @@ var/list/wizard_snakes = list() if(spell_holder) wizard_snakes[src] = spell_holder -/mob/living/simple_animal/cat/snek/wizard/Die() +/mob/living/simple_animal/cat/snek/wizard/death(var/gibbed = FALSE) if(!transmogrify()) visible_message("\The [src] vanishes!") qdel(src) + ..(TRUE) /mob/living/simple_animal/cat/snek/wizard/Destroy() wizard_snakes[src] = null diff --git a/code/modules/mob/living/simple_animal/friendly/corgi.dm b/code/modules/mob/living/simple_animal/friendly/corgi.dm index 337c0cfd048..128491d1864 100644 --- a/code/modules/mob/living/simple_animal/friendly/corgi.dm +++ b/code/modules/mob/living/simple_animal/friendly/corgi.dm @@ -1,6 +1,6 @@ //Corgi /mob/living/simple_animal/corgi - name = "\improper corgi" + name = "corgi" real_name = "corgi" desc = "It's a corgi." @@ -34,7 +34,7 @@ var/obj/item/inventory_head var/obj/item/inventory_back - var/facehugger + var/obj/item/clothing/mask/facehugger/facehugger var/list/spin_emotes = list("dances around","chases its tail") // colourmatrix = list(1,0.0,0.0,0,\ 0,0.5,0.5,0,\ @@ -134,6 +134,12 @@ if(health>0 && prob(15)) emote("looks at [user] with [pick("an amused","an annoyed","a confused","a resentful", "a happy", "an excited")] expression") return + else + var/obj/item/clothing/mask/facehugger/F = O + if(istype(F)) + user.drop_from_inventory(F) + F.Attach(src) + return ..() /mob/living/simple_animal/corgi/Topic(href, href_list) @@ -640,3 +646,74 @@ to_chat(usr, "[src] won't wear that!") return ..() + +/obj/item/weapon/reagent_containers/glass/replenishing/rescue + name = "rescue barrel" + reagent_list = list(LEPORAZINE) + +/mob/living/simple_animal/corgi/saint + name = "saint corgi" + real_name = "saint corgi" + desc = "It's a saint bernard corgi mix breed. It has a tiny rescue barrel strapped around his collar to warm up travelers." + icon_state = "saint_corgi" + icon_living = "saint_corgi" + icon_dead = "saint_corgi_dead" + health = 60 + maxHealth = 60 + minbodytemp = 0 + var/turns_since_scan = 0 + var/mob/living/carbon/victim = null + can_breed = FALSE //tfw no gf + var/obj/item/weapon/reagent_containers/glass/replenishing/rescue/barrel = null + +/mob/living/simple_animal/corgi/saint/death(var/gibbed = FALSE) + if(barrel) + qdel(barrel) + ..(gibbed) + +/mob/living/simple_animal/corgi/saint/Topic(href, href_list) + if(href_list["remove_inv"] || href_list["add_inv"]) + to_chat(usr, "[src] already has a rescue barrel!") + return + ..() + +/mob/living/simple_animal/corgi/saint/proc/rescue(var/mob/M) + if(!M || !Adjacent(M)) + return + if(!barrel) + barrel = new /obj/item/weapon/reagent_containers/glass/replenishing/rescue(src) + barrel.attack(M,src) + +/mob/living/simple_animal/corgi/saint/proc/IsVictim(var/mob/M) + if(iscarbon(M)) + var/mob/living/carbon/victim = M + if(victim.undergoing_hypothermia() && !victim.isDead()) + return TRUE + return FALSE + +/mob/living/simple_animal/corgi/saint/UnarmedAttack(var/atom/A) + if(client && IsVictim(A)) + rescue(A) + return + return ..() + +/mob/living/simple_animal/corgi/saint/Life() + if(timestopped) + return FALSE //under effects of time magick + ..() + + if(!incapacitated() && !resting && !locked_to && !client) + var/list/can_see() = view(src, 6) //Might need tweaking. + if(victim && (!IsVictim(victim) || !(victim.loc in can_see))) + victim = null + stop_automated_movement = FALSE + if(!victim) + for(var/mob/living/carbon/M in can_see) + if(IsVictim(M)) + victim = M //Oh shit. + break + if(victim) + stop_automated_movement = TRUE + step_towards(src,victim) + if(Adjacent(victim) && IsVictim(victim)) //Seriously don't try to rescue the dead. + rescue(victim) diff --git a/code/modules/mob/living/simple_animal/friendly/crab.dm b/code/modules/mob/living/simple_animal/friendly/crab.dm index 41350c70879..92975d3b371 100644 --- a/code/modules/mob/living/simple_animal/friendly/crab.dm +++ b/code/modules/mob/living/simple_animal/friendly/crab.dm @@ -52,7 +52,7 @@ if(prob(50)) to_chat(user, "This kills the crab.") health -= 20 - Die() + death() else to_chat(user, "You can't help but feel you've just done something terribly wrong.") add_gamelogs(user, "attacked a crab with wirecutters, and made it angry", admin = TRUE, tp_link = TRUE, span_class = "danger") diff --git a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm index 9f7d959dae5..ac74a439918 100644 --- a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm +++ b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm @@ -194,8 +194,7 @@ if(!stat && !ckey) amount_grown += rand(1,2) if(amount_grown >= 100) - new /mob/living/simple_animal/chicken(src.loc) - qdel(src) + grow_up() /mob/living/simple_animal/chicken name = "chicken" @@ -347,8 +346,8 @@ if(fat>BOX_GROWTH_BAR) updatefat() -/mob/living/simple_animal/hostile/retaliate/box/Die() - ..() +/mob/living/simple_animal/hostile/retaliate/box/death(var/gibbed = FALSE) + ..(gibbed) playsound(src, 'sound/effects/box_scream.ogg', 100, 1) /mob/living/simple_animal/hostile/retaliate/box/attackby(var/obj/item/O as obj, var/mob/user as mob) diff --git a/code/modules/mob/living/simple_animal/friendly/lizard.dm b/code/modules/mob/living/simple_animal/friendly/lizard.dm index 991f88b1cbd..f2c9f7960c2 100644 --- a/code/modules/mob/living/simple_animal/friendly/lizard.dm +++ b/code/modules/mob/living/simple_animal/friendly/lizard.dm @@ -1,4 +1,4 @@ -/mob/living/simple_animal/lizard +/mob/living/simple_animal/hostile/lizard name = "lizard" desc = "A cute tiny lizard." icon_state = "lizard" @@ -18,3 +18,60 @@ mob_property_flags = MOB_NO_PETRIFY //Can't get petrified (nethack references) meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/animal/lizard held_items = list() + + stop_automated_movement_when_pulled = TRUE + environment_smash_flags = 0 + density = FALSE + pass_flags = PASSTABLE | PASSMOB + vision_range = 6 + aggro_vision_range = 6 + idle_vision_range = 6 + search_objects = 1 + + var/static/list/edibles = list(/mob/living/simple_animal/cockroach, /obj/item/weapon/reagent_containers/food/snacks/roach_eggs) //Add bugs to this as they get added in + +/mob/living/simple_animal/hostile/lizard/UnarmedAttack(var/atom/A) + if(is_type_in_list(A, edibles)) + delayNextAttack(10) + gulp(A) + else return ..() + +/mob/living/simple_animal/hostile/lizard/proc/gulp(var/atom/eat_this) + visible_message("\The [name] consumes [eat_this] in a single gulp.", "You consume [eat_this] in a single gulp.") + playsound(src,'sound/items/egg_squash.ogg', rand(30,70), 1) + qdel(eat_this) + adjustBruteLoss(-2) + +/mob/living/simple_animal/hostile/lizard/LoseAggro() + ..() + search_objects = 1 + +/mob/living/simple_animal/hostile/lizard/CanAttack(var/atom/the_target)//Can we actually attack a possible target? + if(see_invisible < the_target.invisibility)//Target's invisible to us, forget it + return FALSE + if(is_type_in_list(the_target, edibles)) + return TRUE + return FALSE + +/mob/living/simple_animal/hostile/lizard/verb/ventcrawl() + set name = "Crawl through Vent" + set desc = "Enter an air vent and crawl through the pipe system." + set category = "Object" + var/pipe = start_ventcrawl() + if(pipe) + handle_ventcrawl(pipe) + +/mob/living/simple_animal/hostile/lizard/verb/hide() + set name = "Hide" + set desc = "Allows to hide beneath tables or certain items. Toggled on or off." + set category = "Object" + + if(isUnconscious()) + return + + if (plane != HIDING_MOB_PLANE) + plane = HIDING_MOB_PLANE + to_chat(src, "You are now hiding.") + else + plane = MOB_PLANE + to_chat(src, "You have stopped hiding.") diff --git a/code/modules/mob/living/simple_animal/friendly/mouse.dm b/code/modules/mob/living/simple_animal/friendly/mouse.dm index 003c6c27749..6269fd06d6e 100644 --- a/code/modules/mob/living/simple_animal/friendly/mouse.dm +++ b/code/modules/mob/living/simple_animal/friendly/mouse.dm @@ -33,7 +33,7 @@ maxbodytemp = 323 //Above 50 Degrees Celcius universal_speak = 0 treadmill_speed = 0.2 //You can still do it, but you're not going to generate much power. - speak_override = TRUE + speak_override = FALSE size = SIZE_TINY holder_type = /obj/item/weapon/holder/animal/mouse @@ -189,7 +189,7 @@ to_chat(user, "It seems a bit hungry.") /mob/living/simple_animal/mouse/proc/splat() - Die() + death() src.icon_dead = "mouse_[_color]_splat" src.icon_state = "mouse_[_color]_splat" if(client) @@ -262,10 +262,10 @@ M << 'sound/effects/mousesqueek.ogg' ..() -/mob/living/simple_animal/mouse/Die() +/mob/living/simple_animal/mouse/death(var/gibbed = FALSE) if(client) client.time_died_as_mouse = world.time - ..() + ..(gibbed) /* * Mouse types diff --git a/code/modules/mob/living/simple_animal/friendly/slime.dm b/code/modules/mob/living/simple_animal/friendly/slime.dm index cef0c66a6c0..97433068009 100644 --- a/code/modules/mob/living/simple_animal/friendly/slime.dm +++ b/code/modules/mob/living/simple_animal/friendly/slime.dm @@ -46,7 +46,8 @@ overlays += image(icon = icon, icon_state = "aslime-:33") -/mob/living/simple_animal/slime/adult/Die() +/mob/living/simple_animal/slime/adult/death(var/gibbed = FALSE) + ..(gibbed) var/mob/living/simple_animal/slime/S1 = new /mob/living/simple_animal/slime (src.loc) S1.icon_state = "[src.colour] baby slime" S1.icon_living = "[src.colour] baby slime" diff --git a/code/modules/mob/living/simple_animal/friendly/spiderbot.dm b/code/modules/mob/living/simple_animal/friendly/spiderbot.dm index e5b0d67fe19..b2ca569e43d 100644 --- a/code/modules/mob/living/simple_animal/friendly/spiderbot.dm +++ b/code/modules/mob/living/simple_animal/friendly/spiderbot.dm @@ -20,10 +20,13 @@ icon_living = "spiderbot-chassis" icon_dead = "spiderbot-smashed" wander = 0 + voice_name = "synthesized voice" health = 10 maxHealth = 10 + mob_property_flags = MOB_ROBOTIC + attacktext = "shocks" melee_damage_lower = 1 melee_damage_upper = 3 @@ -33,6 +36,7 @@ response_harm = "stomps on" var/obj/item/held_item = null //Storage for single item they can hold. + var/lob_range = 3 var/emagged = 0 //IS WE EXPLODEN? var/syndie = 0 //IS WE SYNDICAT? (currently unused) speed = 1 //Spiderbots gotta go fast. @@ -143,7 +147,7 @@ M.show_message("[src] makes an odd warbling noise, fizzles, and explodes.") explosion(get_turf(loc), -1, -1, 3, 5) eject_brain() - Die() + death() /mob/living/simple_animal/spiderbot/update_icon() if(mmi) @@ -182,11 +186,8 @@ ..() -/mob/living/simple_animal/spiderbot/Die() - - living_mob_list -= src - dead_mob_list += src - +/mob/living/simple_animal/spiderbot/death(var/gibbed = FALSE) + ..(TRUE) if(camera) camera.status = 0 if(held_item && !isnull(held_item)) @@ -196,6 +197,23 @@ robogibs(src.loc, viruses) qdel(src) +/mob/living/simple_animal/spiderbot/emp_act(severity) + if(flags & INVULNERABLE) + return ..() + + switch(severity) + if(1) + if(prob(5)) + explode() + return + adjustBruteLoss(rand(4,5)) + if(2) + adjustBruteLoss(rand(2,3)) + flash_eyes(visual = 1, type = /obj/abstract/screen/fullscreen/flash/noise) + to_chat(src, "*BZZZT*") + to_chat(src, "Warning: Electromagnetic pulse detected.") + ..() + //copy paste from alien/larva, if that func is updated please update this one also /mob/living/simple_animal/spiderbot/verb/ventcrawl() set name = "Crawl through Vent" @@ -225,7 +243,7 @@ set category = "Spiderbot" set desc = "Drop the item you're holding." - if(stat) + if(incapacitated()) return if(!held_item) @@ -235,8 +253,19 @@ if(istype(held_item, /obj/item/weapon/grenade)) visible_message("[src] launches \the [held_item]!", "You launch \the [held_item]!", "You hear a skittering noise and a thump!") var/obj/item/weapon/grenade/G = held_item - G.forceMove(src.loc) - G.prime() + + //Make a dumbfire throw + var/turf/lob_target + var/lob_dir = dir + var/turf/start_turf = get_turf(src) + var/current_turf = start_turf + for(var/i in 1 to lob_range) + current_turf = get_step(current_turf, lob_dir) + lob_target = current_turf + + throw_item(lob_target, G) + + G.activate(src) held_item = null return 1 @@ -254,7 +283,7 @@ set category = "Spiderbot" set desc = "Allows you to take a nearby small item." - if(stat) + if(incapacitated()) return -1 if(held_item) @@ -271,6 +300,9 @@ if(selection) for(var/obj/item/I in view(1, src)) if(selection == I) + if(selection.anchored) + to_chat(src, "It's fastened down!") + return 0 held_item = selection selection.forceMove(src) visible_message("[src] scoops up \the [held_item]!", "You grab \the [held_item]!", "You hear a skittering noise and a clink.") @@ -287,3 +319,22 @@ /mob/living/simple_animal/spiderbot/CheckSlip() return -1 + +/mob/living/simple_animal/spiderbot/say(var/message) + return ..(message, "R") + +/mob/living/simple_animal/spiderbot/treat_speech(var/datum/speech/speech, genesay = 0) + ..(speech) + speech.message_classes.Add("siliconsay") + +/mob/living/simple_animal/spiderbot/verb/Toggle_Listening() + set name = "Toggle Listening" + set desc = "Toggle listening channel on or off." + set category = "Spiderbot" + + if(incapacitated()) + to_chat(src, "Can't do that while incapacitated or dead.") + return + + radio.listening = !radio.listening + to_chat(src, "Radio is [radio.listening ? "" : "no longer "]receiving broadcasts.") diff --git a/code/modules/mob/living/simple_animal/hologram/hologram.dm b/code/modules/mob/living/simple_animal/hologram/hologram.dm index 06d6c16f775..c0a9cea78e5 100644 --- a/code/modules/mob/living/simple_animal/hologram/hologram.dm +++ b/code/modules/mob/living/simple_animal/hologram/hologram.dm @@ -8,8 +8,8 @@ var/atom/atom_to_mimic -/mob/living/simple_animal/hologram/Die() - ..() +/mob/living/simple_animal/hologram/death(var/gibbed = FALSE) + ..(gibbed) visible_message("[M] gives [src] a [pick("hug","warm embrace")].", \ "You hug [src].", \ diff --git a/code/modules/mob/living/simple_animal/hostile/alien.dm b/code/modules/mob/living/simple_animal/hostile/alien.dm index b0777794225..0c8e93de9a7 100644 --- a/code/modules/mob/living/simple_animal/hostile/alien.dm +++ b/code/modules/mob/living/simple_animal/hostile/alien.dm @@ -348,8 +348,8 @@ var/list/nest_locations = list() damage = 30 icon_state = "toxin" -/mob/living/simple_animal/hostile/alien/Die() - ..() +/mob/living/simple_animal/hostile/alien/death(var/gibbed = FALSE) + ..(gibbed) visible_message("[src] lets out a waning guttural screech, green blood bubbling from its maw...") playsound(src, 'sound/voice/hiss6.ogg', 100, 1) diff --git a/code/modules/mob/living/simple_animal/hostile/balloon.dm b/code/modules/mob/living/simple_animal/hostile/balloon.dm index 6396da0b67f..8723ae814cf 100644 --- a/code/modules/mob/living/simple_animal/hostile/balloon.dm +++ b/code/modules/mob/living/simple_animal/hostile/balloon.dm @@ -91,8 +91,8 @@ for(var/obj/item/toy/balloon/inflated/long/shaped/B in living_balloons) if(get_turf(src) in view(B)) B.live() - Die() + death() -/mob/living/simple_animal/hostile/balloon/Die() - ..() +/mob/living/simple_animal/hostile/balloon/death(var/gibbed = FALSE) + ..(TRUE) qdel(src) diff --git a/code/modules/mob/living/simple_animal/hostile/bat.dm b/code/modules/mob/living/simple_animal/hostile/bat.dm index 023eea3bf07..36c8d072730 100644 --- a/code/modules/mob/living/simple_animal/hostile/bat.dm +++ b/code/modules/mob/living/simple_animal/hostile/bat.dm @@ -57,7 +57,7 @@ /mob/living/simple_animal/hostile/scarybat/FindTarget() . = ..() if(.) - emote("flutters towards [.]") + emote("me",, "flutters towards [.]!") /mob/living/simple_animal/hostile/scarybat/Found(var/atom/A) //This is here as a potential override to pick a specific target if available if(!istype(A, /mob/living)) diff --git a/code/modules/mob/living/simple_animal/hostile/bigroach.dm b/code/modules/mob/living/simple_animal/hostile/bigroach.dm new file mode 100644 index 00000000000..38ceaa49e81 --- /dev/null +++ b/code/modules/mob/living/simple_animal/hostile/bigroach.dm @@ -0,0 +1,126 @@ +/mob/living/simple_animal/hostile/bigroach + name = "mutated cockroach" + desc = "A cockroach mutated not only to be several times the size of an ordinary one, but also to be much more bloodthirsty. The genetic changes have rendered it sterile and unable to fly." + + icon_state = "bigroach" + icon_living = "bigroach" + icon_dead = "bigroach_dead" + + emote_hear = list("hisses") + + pass_flags = PASSTABLE | PASSGRILLE | PASSMACHINE + + speak_chance = 1 + + move_to_delay = 4 + + maxHealth = 35 + health = 35 + + size = SIZE_SMALL + + minbodytemp = 273.15 //Can't survive at below 0 C + maxbodytemp = INFINITY + min_oxy = 0 + max_oxy = 0 + min_tox = 0 + max_tox = 0 + min_co2 = 0 + max_co2 = 0 + min_n2 = 0 + max_n2 = 0 + + meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/roach/big + + melee_damage_lower = 5 + melee_damage_upper = 10 + attacktext = "gnaws" + attack_sound = 'sound/weapons/bite.ogg' + + faction = "roach" + + var/icon_aggro = "bigroach_angry" + +/mob/living/simple_animal/hostile/bigroach/queen + name = "cockroach matriarch" + desc = "A cockroach, twisted and deformed by mutagenic chemicals nearly to the point of unrecognition, reaching nearly the size of an adult human. By an odd twist of fate, is not only alive and functioning - it is also able to lay eggs." + + icon_state = "hugeroach" + icon_living = "hugeroach" + icon_dead = "hugeroach_dead" + + maxHealth = 150 + health = 150 + + size = SIZE_NORMAL + + melee_damage_lower = 10 + melee_damage_upper = 25 + + move_to_delay = 10 + turns_per_move = 3 + + icon_aggro = "hugeroach" + + stat_attack = UNCONSCIOUS //Attack unconscious mobs to lay eggs + + var/egg_type = /obj/item/weapon/reagent_containers/food/snacks/egg/bigroach + +/mob/living/simple_animal/hostile/bigroach/queen/AttackingTarget() + if(isliving(target)) + var/mob/living/L = target + + //Only lay eggs into unconscious dudes + if(L.isUnconscious()) + visible_message("\The [src] lays some eggs on top of \the [L]!") + playsound(src, 'sound/effects/bug_hiss.ogg', 50, 1) + var/obj/item/egg = new egg_type(get_turf(target)) + + //40% chance for the egg to be fertile + if(prob(40) && (animal_count[/mob/living/simple_animal/hostile/bigroach] < ANIMAL_CHILD_CAP)) + processing_objects.Add(egg) + + return ..() + +/mob/living/simple_animal/hostile/bigroach/New() + ..() + + pixel_x = rand(-5, 5) * PIXEL_MULTIPLIER + pixel_y = rand(-5, 5) * PIXEL_MULTIPLIER + +/mob/living/simple_animal/hostile/bigroach/death(var/gibbed = FALSE) + ..(gibbed) + playsound(src, pick('sound/effects/gib1.ogg','sound/effects/gib2.ogg','sound/effects/gib3.ogg'), 40, 1) //Splat + +/mob/living/simple_animal/hostile/bigroach/attackby(obj/item/W, mob/user) + if(istype(W, /obj/item/weapon/newspaper)) + to_chat(user, "You're gonna need a bigger newspaper.") + else if(istype(W, /obj/item/weapon/plantspray/pests)) + var/obj/item/weapon/plantspray/pests/P = W + if(P.use(1)) + to_chat(user, "\The [P] doesn't seem to be very effective.") + playsound(loc, 'sound/effects/spray3.ogg', 50, 1, -6) + else + return ..() + + +/mob/living/simple_animal/hostile/bigroach/Aggro() + ..() + + icon_living = icon_aggro + icon_state = icon_living + + spawn(rand(1,14)) + playsound(src, 'sound/effects/bug_hiss.ogg', 50, 1) + +/mob/living/simple_animal/hostile/bigroach/LoseAggro() + ..() + + icon_living = initial(icon_living) + icon_state = icon_living + +/mob/living/simple_animal/hostile/bigroach/ex_act() + return //Survive bombs + +/mob/living/simple_animal/hostile/bigroach/nuke_act() + return //Survive nuclear blasts diff --git a/code/modules/mob/living/simple_animal/hostile/carp.dm b/code/modules/mob/living/simple_animal/hostile/carp.dm index c1b0a5fb808..57a1428dacd 100644 --- a/code/modules/mob/living/simple_animal/hostile/carp.dm +++ b/code/modules/mob/living/simple_animal/hostile/carp.dm @@ -86,7 +86,7 @@ /mob/living/simple_animal/hostile/carp/FindTarget() . = ..() if(.) - emote("nashes at [.]") + emote("me",, "gnashes at [.]!") /mob/living/simple_animal/hostile/carp/AttackingTarget() if(!target) @@ -145,7 +145,7 @@ var/obj/item/weapon/reagent_containers/food/snacks/F = W if((F.food_flags & FOOD_MEAT) && (growth_stage < req_growth_to_grow_up)) //Any meaty dish goes! - playsound(get_turf(src),'sound/items/eatfood.ogg', rand(10,50), 1) + playsound(src,'sound/items/eatfood.ogg', rand(10,50), 1) visible_message("\The [src] gobbles up \the [W]!") user.drop_item(F, force_drop = 1) @@ -197,7 +197,8 @@ mob_property_flags = MOB_HOLOGRAPHIC holder_type = null -/mob/living/simple_animal/hostile/carp/holocarp/Die() +/mob/living/simple_animal/hostile/carp/holocarp/death(var/gibbed = FALSE) + ..(TRUE) qdel(src) #undef PHEROMONES_NO_EFFECT diff --git a/code/modules/mob/living/simple_animal/hostile/decoy.dm b/code/modules/mob/living/simple_animal/hostile/decoy.dm index c407460b2ca..3a25d55d1d0 100644 --- a/code/modules/mob/living/simple_animal/hostile/decoy.dm +++ b/code/modules/mob/living/simple_animal/hostile/decoy.dm @@ -17,9 +17,9 @@ var/invincible = FALSE var/to_spawn = null -/mob/living/simple_animal/hostile/decoy/Die() +/mob/living/simple_animal/hostile/decoy/death(var/gibbed = FALSE) if(!invincible) - ..() + ..(gibbed) /mob/living/simple_animal/hostile/decoy/adjustBruteLoss(var/damage) if(!invincible) diff --git a/code/modules/mob/living/simple_animal/hostile/deer.dm b/code/modules/mob/living/simple_animal/hostile/deer.dm new file mode 100644 index 00000000000..f4d9f721ae5 --- /dev/null +++ b/code/modules/mob/living/simple_animal/hostile/deer.dm @@ -0,0 +1,138 @@ +/mob/living/simple_animal/hostile/deer + name = "deer" + desc = "A large herbivore, sporting antlers on their head. Quick to spook." + icon_state = "deer" + icon_living = "deer" + icon_dead = "deer_dead" + faction = "deer" + health = 50 + maxHealth = 50 + size = SIZE_NORMAL + response_help = "pets" + + attacktext = "kicks" + melee_damage_lower = 5 + melee_damage_upper = 15 + + minbodytemp = 200 + +/mob/living/simple_animal/hostile/deer/GiveTarget(var/new_target) + if(isDead()) + return //The deers problems are over now, try not to be too jealous + if(isliving(new_target)) + if(is_spooked(new_target)) + var/list/can_see = view(src, vision_range) + get_spooked(new_target) + for(var/mob/living/simple_animal/hostile/deer/D in can_see) + D.get_spooked(new_target) + +/mob/living/simple_animal/hostile/deer/proc/is_spooked(var/mob/living/target) + if(friends.Find(target)) + return 0 + if(ishuman(target)) + /* + Making it so that there is some tactics to hunting deer + If you're running at them like a crazy man, expect for them to get spooked + Otherwise, if you're wearing clothing made of deer, or are holding an apple, they are less likely to get spooked + */ + var/mob/living/carbon/human/H = target + var/spook_prob = 30 + + if(H.m_intent == "run") //Don't run while stalking deer + spook_prob = 70 + if(istype(H.get_item_by_slot(slot_wear_suit), /obj/item/clothing/suit/leather/deer)) + spook_prob -= 10 + if(istype(H.get_item_by_slot(slot_head), /obj/item/clothing/head/leather/deer)) + spook_prob -= 10 + if(istype(H.get_item_by_slot(slot_head), /obj/item/clothing/head/leather/deer/horned)) + spook_prob -= 10 + for(var/obj/item/I in H.held_items) + if(istype(I, /obj/item/weapon/reagent_containers/food/snacks/grown/apple)) + spook_prob -= 10 + if(istype(I, /obj/item/weapon/reagent_containers/food/snacks/grown/goldapple)) + spook_prob -= 20 + if(prob(spook_prob)) + return 1 + else + if(!istype(target, /mob/living/simple_animal/hostile/deer)) + return 1 + +/mob/living/simple_animal/hostile/deer/proc/get_spooked(var/mob/living/T) + stance = HOSTILE_STANCE_ATTACK + target = T + visible_message("\The [src] tries to flee from \the [target]!") + retreat_distance = 25 + minimum_distance = 25 + +/mob/living/simple_animal/hostile/deer/Life() + ..() + if(isDead()) + return + var/list/can_see = view(src, vision_range) + if(stance == HOSTILE_STANCE_ATTACK) + spawn(15) + var/is_spooked = 0 + for(var/mob/living/L in can_see) + if(is_spooked(L)) + is_spooked = 1 + if(!is_spooked) + calm_down() + + +/mob/living/simple_animal/hostile/deer/proc/calm_down() + visible_message("\The [src] calms down") + retreat_distance = 0 + minimum_distance = 0 + LoseTarget() + + + +/mob/living/simple_animal/hostile/deer/attackby(obj/W, mob/user) + if(!isDead() && (istype(W, /obj/item/weapon/reagent_containers/food/snacks/grown/apple) || (istype (W, /obj/item/weapon/reagent_containers/food/snacks/grown/goldapple)))) + var/obj/item/weapon/reagent_containers/food/snacks/grown/apple/A = W + + playsound(get_turf(src),'sound/items/eatfood.ogg', rand(10,50), 1) + visible_message("\The [src] gobbles up \the [W]!") + //user.drop_item(A, force_drop = 1) + + if(istype (W, /obj/item/weapon/reagent_containers/food/snacks/grown/goldapple)) + icon_living = "deer_flower" + icon_dead = "deer_dead" + icon_state = "deer_flower" + + if(prob(25)) + if(!friends.Find(user)) + friends.Add(user) + to_chat(user, "You have gained \the [src]'s trust.") + name_mob(user) + qdel(A) + + if(istype (W, /obj/item/weapon/reagent_containers/food/snacks/grown/apple/poisoned)) + spawn(rand(50,150)) + death() //You dick + return + ..() + +/mob/living/simple_animal/hostile/deer/update_icons() + .=..() + + if(stat == DEAD && butchering_drops) + var/datum/butchering_product/deer_head/our_head = locate(/datum/butchering_product/deer_head) in butchering_drops + if(istype(our_head)) + icon_state = "[icon_dead][(our_head.amount) ? "" : "_headless"]" + +/mob/living/simple_animal/hostile/deer/cultify() + new /mob/living/simple_animal/hostile/deer/flesh(get_turf(src)) + qdel(src) + +/mob/living/simple_animal/hostile/deer/flesh + icon_state = "fleshdeer" + icon_living = "fleshdeer" + icon_dead = "fleshdeer_dead" + + canRegenerate = 1 + maxRegenTime = 150 + minRegenTime = 60 + +/mob/living/simple_animal/hostile/deer/flesh/cultify() + return \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/hostile/frog.dm b/code/modules/mob/living/simple_animal/hostile/frog.dm index e5800662591..8ffade3a1d5 100644 --- a/code/modules/mob/living/simple_animal/hostile/frog.dm +++ b/code/modules/mob/living/simple_animal/hostile/frog.dm @@ -73,12 +73,12 @@ .=..() -/mob/living/simple_animal/hostile/frog/Die() +/mob/living/simple_animal/hostile/frog/death(var/gibbed = FALSE) for(var/obj/item/I in contents) I.forceMove(get_turf(src)) update_spear() - ..() + ..(gibbed) /mob/living/simple_animal/hostile/frog/Cross(obj/item/weapon/spear/S) .=..() diff --git a/code/modules/mob/living/simple_animal/hostile/giant_spider/base_spider.dm b/code/modules/mob/living/simple_animal/hostile/giant_spider/base_spider.dm index 53d35a0212c..40a7f2eb743 100644 --- a/code/modules/mob/living/simple_animal/hostile/giant_spider/base_spider.dm +++ b/code/modules/mob/living/simple_animal/hostile/giant_spider/base_spider.dm @@ -81,7 +81,7 @@ var/pressure=myenv.return_pressure() for(var/dir in cardinal) - var/turf/simulated/T=get_turf(get_step(loc,dir)) + var/turf/simulated/T = get_step(loc, dir) if(T && istype(T) && T.zone) var/datum/gas_mixture/environment = T.return_air() var/pdiff = abs(pressure - environment.return_pressure()) diff --git a/code/modules/mob/living/simple_animal/hostile/giant_spider/nurse.dm b/code/modules/mob/living/simple_animal/hostile/giant_spider/nurse.dm index 4ced778faa7..c13c3665491 100644 --- a/code/modules/mob/living/simple_animal/hostile/giant_spider/nurse.dm +++ b/code/modules/mob/living/simple_animal/hostile/giant_spider/nurse.dm @@ -13,6 +13,7 @@ melee_damage_upper = 10 poison_per_bite = 10 poison_type = STOXIN + species_type = /mob/living/simple_animal/hostile/giant_spider/nurse/queen_spider var/fed = 0 var/atom/cocoon_target @@ -25,10 +26,8 @@ stop_automated_movement = 0 /mob/living/simple_animal/hostile/giant_spider/nurse/proc/check_evolve() - if(spider_queens.len < MAX_SQUEENS && !key) //don't evolve if there's a player inside - var/mob/living/simple_animal/hostile/giant_spider/nurse/queen_spider/NQ = new(src.loc) - NQ.inherit_mind(src) - qdel(src) + if(animal_count[species_type] < MAX_SQUEENS && !key) //don't evolve if there's a player inside + grow_up() return 1 return 0 @@ -180,8 +179,6 @@ busy = 0 stop_automated_movement = 0 -var/list/spider_queens = list() - /mob/living/simple_animal/hostile/giant_spider/nurse/queen_spider name = "spider queen" desc = "Massive, dark, and very furry. This is an absolutely massive spider. Its fangs are almost as big as you!" @@ -201,14 +198,6 @@ var/list/spider_queens = list() size = SIZE_HUGE delimbable_icon = FALSE -/mob/living/simple_animal/hostile/giant_spider/nurse/queen_spider/New() - ..() - spider_queens += src - -/mob/living/simple_animal/hostile/giant_spider/nurse/queen_spider/Destroy() - ..() - spider_queens -= src - /mob/living/simple_animal/hostile/giant_spider/nurse/queen_spider/check_evolve() return 0 diff --git a/code/modules/mob/living/simple_animal/hostile/giant_spider/spiderling.dm b/code/modules/mob/living/simple_animal/hostile/giant_spider/spiderling.dm index 68d91a706e8..7020e2a8c1a 100644 --- a/code/modules/mob/living/simple_animal/hostile/giant_spider/spiderling.dm +++ b/code/modules/mob/living/simple_animal/hostile/giant_spider/spiderling.dm @@ -49,10 +49,10 @@ if(prob(75)) amount_grown = 1 -/mob/living/simple_animal/hostile/giant_spider/spiderling/Die() +/mob/living/simple_animal/hostile/giant_spider/spiderling/death(var/gibbed = FALSE) visible_message("[src] dies!") new /obj/effect/decal/cleanable/spiderling_remains(src.loc) - ..() + ..(TRUE) qdel(src) /mob/living/simple_animal/hostile/giant_spider/spiderling/Aggro() @@ -121,9 +121,9 @@ if(isturf(loc) && amount_grown > 0) amount_grown += rand(0,2) if(amount_grown >= 100) - var/spawn_type = pick(spider_types) - new spawn_type(src.loc) - qdel(src) + if(!species_type) + species_type = pick(spider_types) + grow_up() return ..() diff --git a/code/modules/mob/living/simple_animal/hostile/glow_orb.dm b/code/modules/mob/living/simple_animal/hostile/glow_orb.dm index 991ac54309e..a3d82f16186 100644 --- a/code/modules/mob/living/simple_animal/hostile/glow_orb.dm +++ b/code/modules/mob/living/simple_animal/hostile/glow_orb.dm @@ -91,16 +91,16 @@ If hit by lightning, overpowers and explodes like a flashbang, blinding everyone set_light(4, 1, "#0068B2") walk(src,0) else - Die() + death() ..() -/mob/living/simple_animal/hostile/glow_orb/Die() - ..() +/mob/living/simple_animal/hostile/glow_orb/death(var/gibbed = FALSE) + ..(gibbed) visible_message("\The [src] grows dim as it falls to the ground.") flick("glow_stone_deactivate", src) spawn(10) - playsound(get_turf(src), 'sound/weapons/orb_deactivate.ogg', 50,1) + playsound(src, 'sound/weapons/orb_deactivate.ogg', 50,1) set_light(0) new/obj/item/weapon/glow_orb(get_turf(src)) qdel(src) @@ -122,7 +122,7 @@ If hit by lightning, overpowers and explodes like a flashbang, blinding everyone ..() /mob/living/simple_animal/hostile/glow_orb/proc/detonate() unstable = 1 - playsound(get_turf(src),'sound/weapons/inc_tone.ogg', 50, 1) + playsound(src,'sound/weapons/inc_tone.ogg', 50, 1) flick("glow_stone_critical", src) status_flags &= ~GODMODE spawn(2 SECONDS) @@ -159,10 +159,10 @@ If hit by lightning, overpowers and explodes like a flashbang, blinding everyone //Now applying sound if(!ear_safety) to_chat(M, "BANG") - playsound(get_turf(src), 'sound/effects/bang.ogg', 60, 1) + playsound(src, 'sound/effects/bang.ogg', 60, 1) else to_chat(M, "BANG") - playsound(get_turf(src), 'sound/effects/bang.ogg', 25, 1) + playsound(src, 'sound/effects/bang.ogg', 25, 1) if((get_dist(M, T) <= 2 || src.loc == M.loc || src.loc == M)) if(ear_safety > 0) diff --git a/code/modules/mob/living/simple_animal/hostile/gremlin.dm b/code/modules/mob/living/simple_animal/hostile/gremlin.dm index 0c99d66760d..369f12ec637 100644 --- a/code/modules/mob/living/simple_animal/hostile/gremlin.dm +++ b/code/modules/mob/living/simple_animal/hostile/gremlin.dm @@ -95,6 +95,9 @@ var/list/bad_gremlin_items = list() M.add_custom_fibers("Hairs from a gremlin.", 0) return TRUE +/mob/living/simple_animal/hostile/gremlin/proc/stand_still(var/tick_amount) + time_chasing_target -= tick_amount + /mob/living/simple_animal/hostile/gremlin/CanAttack(atom/new_target) if(bad_gremlin_items.Find(new_target.type)) return FALSE @@ -126,14 +129,15 @@ var/list/bad_gremlin_items = list() /mob/living/simple_animal/hostile/gremlin/EscapeConfinement() if(istype(loc, /obj) && CanAttack(loc)) //If we're inside a machine, screw with it var/obj/M = loc - tamper(M) + return tamper(M) return ..() //This allows player-controlled gremlins to tamper with machinery /mob/living/simple_animal/hostile/gremlin/UnarmedAttack(var/atom/A) if(istype(A, /obj/machinery) || istype(A, /obj/structure)) - tamper(A) + if(CanAttack(A)) + tamper(A) return ..() diff --git a/code/modules/mob/living/simple_animal/hostile/hive_aliens.dm b/code/modules/mob/living/simple_animal/hostile/hive_aliens.dm index 210fd7bb0d7..cf2f235c308 100644 --- a/code/modules/mob/living/simple_animal/hostile/hive_aliens.dm +++ b/code/modules/mob/living/simple_animal/hostile/hive_aliens.dm @@ -133,8 +133,8 @@ var/obj/structure/hive/spikes/summoned_spikes -/mob/living/simple_animal/hostile/hive_alien/constructor/Die() - ..() +/mob/living/simple_animal/hostile/hive_alien/constructor/death(var/gibbed = FALSE) + ..(gibbed) flick("hive_artificer_dying", src) if(summoned_spikes) @@ -243,7 +243,7 @@ var/mob/living/simple_animal/hostile/hive_alien/constructor/owner -/obj/structure/hive/spikes/Die() +/obj/structure/hive/spikes/death() ..() if(owner) diff --git a/code/modules/mob/living/simple_animal/hostile/hivebot.dm b/code/modules/mob/living/simple_animal/hostile/hivebot.dm index 701b30005f7..f1fd9e297a1 100644 --- a/code/modules/mob/living/simple_animal/hostile/hivebot.dm +++ b/code/modules/mob/living/simple_animal/hostile/hivebot.dm @@ -65,8 +65,8 @@ if (2) adjustBruteLoss(10) -/mob/living/simple_animal/hostile/hivebot/Die() - ..() +/mob/living/simple_animal/hostile/hivebot/death(var/gibbed = FALSE) + ..(TRUE) visible_message("[src] blows apart!") new /obj/effect/gibspawner/robot(src.loc) qdel(src) @@ -96,7 +96,7 @@ smoke.set_up(5, 0, src.loc) smoke.start() visible_message("The [src] warps in!") - playsound(get_turf(src), 'sound/effects/EMPulse.ogg', 25, 1) + playsound(src, 'sound/effects/EMPulse.ogg', 25, 1) /mob/living/simple_animal/hostile/hivebot/tele/proc/warpbots() icon_state = "def_radar" diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm index af91201b51d..35bde1845b2 100644 --- a/code/modules/mob/living/simple_animal/hostile/hostile.dm +++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm @@ -251,6 +251,7 @@ /mob/living/simple_animal/hostile/proc/LoseAggro() stop_automated_movement = 0 vision_range = idle_vision_range + search_objects = initial(search_objects) /mob/living/simple_animal/hostile/proc/LoseTarget() stance = HOSTILE_STANCE_IDLE @@ -265,9 +266,9 @@ //////////////END HOSTILE MOB TARGETTING AND AGGRESSION//////////// -/mob/living/simple_animal/hostile/Die() +/mob/living/simple_animal/hostile/death(var/gibbed = FALSE) LoseAggro() - ..() + ..(gibbed) walk(src, 0) /mob/living/simple_animal/hostile/inherit_mind(mob/living/simple_animal/from) @@ -299,6 +300,8 @@ ranged_cooldown = ranged_cooldown_cap if(ranged_message) visible_message("[src] [ranged_message] at [target]!", 1) + if(ckey) + add_attacklogs(src, target, "[ranged_message ? ranged_message : "shot"] at") if(casingtype) new casingtype(get_turf(src),1)// empty casing @@ -374,7 +377,9 @@ || istype(A, /obj/structure/table)\ || istype(A, /obj/structure/grille)\ || istype(A, /obj/structure/rack)\ - || istype(A, /obj/machinery/door/window)) && Adjacent(A)) + || istype(A, /obj/machinery/door/window)\ + || istype(A, /obj/item/tape)\ + || istype(A, /obj/item/toy/balloon/inflated/decoy)) && Adjacent(A)) UnarmedAttack(A) return diff --git a/code/modules/mob/living/simple_animal/hostile/human/_humanoid.dm b/code/modules/mob/living/simple_animal/hostile/human/_humanoid.dm index 6828e6115b3..fc431938ca7 100644 --- a/code/modules/mob/living/simple_animal/hostile/human/_humanoid.dm +++ b/code/modules/mob/living/simple_animal/hostile/human/_humanoid.dm @@ -53,8 +53,8 @@ /mob/living/simple_animal/hostile/humanoid/getarmor(var/def_zone, var/type) return armor[type] -/mob/living/simple_animal/hostile/humanoid/Die() - ..() +/mob/living/simple_animal/hostile/humanoid/death(var/gibbed = FALSE) + ..(gibbed) if(corpse) new corpse(loc) @@ -69,7 +69,6 @@ A.forceMove(get_turf(src)) qdel(src) - return /mob/living/simple_animal/hostile/humanoid/Shoot() if(!needs_to_reload) diff --git a/code/modules/mob/living/simple_animal/hostile/human/civilian.dm b/code/modules/mob/living/simple_animal/hostile/human/civilian.dm index cf2b65b4a38..db447cbe980 100644 --- a/code/modules/mob/living/simple_animal/hostile/human/civilian.dm +++ b/code/modules/mob/living/simple_animal/hostile/human/civilian.dm @@ -77,15 +77,15 @@ /mob/living/simple_animal/hostile/humanoid/janitor/Shoot(var/atom/target, var/atom/start, var/mob/user) if(prob(30) && CS.reagents.has_reagent(LUBE)) visible_message("\The [src] lets loose a blast of lubricant from their chemical sprayer!") - playsound(get_turf(src), 'sound/effects/spray2.ogg', 50, 1, -6) + playsound(src, 'sound/effects/spray2.ogg', 50, 1, -6) CS.make_puff(target, user) else ..() -/mob/living/simple_animal/hostile/humanoid/janitor/Die() +/mob/living/simple_animal/hostile/humanoid/janitor/death(var/gibbed = FALSE) CS.forceMove(loc) CS = null - ..() + ..(gibbed) /mob/living/simple_animal/hostile/humanoid/pilot diff --git a/code/modules/mob/living/simple_animal/hostile/human/frostgolem.dm b/code/modules/mob/living/simple_animal/hostile/human/frostgolem.dm index b27662d8116..8b44bec72b1 100644 --- a/code/modules/mob/living/simple_animal/hostile/human/frostgolem.dm +++ b/code/modules/mob/living/simple_animal/hostile/human/frostgolem.dm @@ -29,12 +29,11 @@ attacktext = "punches" -/mob/living/simple_animal/hostile/humanoid/frostgolem/Die() +/mob/living/simple_animal/hostile/humanoid/frostgolem/death(var/gibbed = FALSE) visible_message("\The [src] crumbles to snow!") for(var/i = 1 to rand(1,10)) new /obj/item/stack/sheet/snow(loc) - - ..() + ..(gibbed) /mob/living/simple_animal/hostile/humanoid/frostgolem/AttackingTarget() target.attack_animal(src) diff --git a/code/modules/mob/living/simple_animal/hostile/human/halloween.dm b/code/modules/mob/living/simple_animal/hostile/human/halloween.dm index c2bd748b69a..a8f5e7bb0cd 100644 --- a/code/modules/mob/living/simple_animal/hostile/human/halloween.dm +++ b/code/modules/mob/living/simple_animal/hostile/human/halloween.dm @@ -36,7 +36,8 @@ return ..(P) -/mob/living/simple_animal/hostile/humanoid/kitchen/poutine/Die() +/mob/living/simple_animal/hostile/humanoid/kitchen/poutine/death(var/gibbed = FALSE) + ..(TRUE) for(var/i=1 to 3) var/to_spawn = pick(/obj/item/weapon/reagent_containers/food/snacks/poutine, /obj/item/weapon/reagent_containers/food/snacks/poutinedangerous,\ /obj/item/weapon/reagent_containers/food/snacks/poutinebarrel) @@ -97,7 +98,8 @@ friendly_fire = 0 canmove = 1 -/mob/living/simple_animal/hostile/humanoid/kitchen/meatballer/Die() +/mob/living/simple_animal/hostile/humanoid/kitchen/meatballer/death(var/gibbed = FALSE) + ..(TRUE) for(var/i=1 to 3) var/to_spawn = pick(/obj/item/weapon/reagent_containers/food/snacks/spaghetti, /obj/item/weapon/reagent_containers/food/snacks/meatballspaghetti,\ /obj/item/weapon/reagent_containers/food/snacks/copypasta) @@ -236,7 +238,8 @@ spawn(5 SECONDS) retreating = 0 -/mob/living/simple_animal/hostile/humanoid/vampire/Die() +/mob/living/simple_animal/hostile/humanoid/vampire/death(var/gibbed = FALSE) + ..(TRUE) visible_message("\The [src] lets out one last ear piercing shriek, before collapsing into dust!") for(var/mob/living/carbon/C in hearers(4, src)) if(ishuman(C)) @@ -315,6 +318,9 @@ var/annoyed = 0 +/mob/living/simple_animal/hostile/gremlin/greytide/attack_icon() + return image(icon = 'icons/obj/storage/storage.dmi', icon_state = "toolbox_blue") + /mob/living/simple_animal/hostile/gremlin/greytide/electrocute_act() return //Gremtide cometh @@ -368,12 +374,11 @@ if(isliving(the_target)) var/mob/living/M = the_target M.apply_radiation(rand(melee_damage_lower,melee_damage_upper), RAD_EXTERNAL) - ..(the_target) + return ..(the_target) -/mob/living/simple_animal/hostile/humanoid/supermatter/UnarmedAttack(atom/A) - if(isliving(A)) - visible_message("\The [src] [attacktext] \the [A]") - var/mob/living/M = A +/mob/living/simple_animal/hostile/humanoid/supermatter/UnarmedAttack(var/atom/the_target) + if(isliving(the_target)) + var/mob/living/M = the_target M.apply_radiation(rand(melee_damage_lower*2,melee_damage_upper*3), RAD_EXTERNAL) switch(M.radiation) if(0 to 90) @@ -395,6 +400,8 @@ empulse(T, 2, 4, 1) new /turf/unsimulated/wall/supermatter/no_spread/lake(T) M.supermatter_act(src, SUPERMATTER_DUST) + else + ..() /mob/living/simple_animal/hostile/humanoid/supermatter/to_bump(atom/Obstacle) @@ -403,8 +410,9 @@ return ..() -/mob/living/simple_animal/hostile/humanoid/supermatter/Die() +/mob/living/simple_animal/hostile/humanoid/supermatter/death(var/gibbed = FALSE) set waitfor = 0 + ..(TRUE) animate(src, alpha = 0, time = 2 SECONDS, easing = SINE_EASING) sleep(3 SECONDS) empulse(get_turf(src), 6, 12, 1) @@ -515,7 +523,8 @@ A.lock_atom(src, /datum/locking_category/cable_lock) update_icon() -/mob/living/simple_animal/hostile/syphoner/Die() +/mob/living/simple_animal/hostile/syphoner/death(var/gibbed = FALSE) + ..(TRUE) visible_message("\The [src] explodes!") var/turf/T = get_turf(src) new /obj/effect/gibspawner/robot(T) @@ -561,7 +570,7 @@ continue if(S.health < maxHealth) if(prob(10)) - playsound(get_turf(S), get_sfx("soulstone"), 50,1) + playsound(S, get_sfx("soulstone"), 50,1) if(prob(35)) make_tracker_effects(src, S) S.health = max(S.maxHealth, S.health+rand(3,6)) @@ -570,7 +579,7 @@ visible_message("\The [src] makes a fist with its skeletal hands, and [S] turns to dust.") health = max(maxHealth, health+S.health) make_tracker_effects(S, src) - playsound(get_turf(S), get_sfx("soulstone"), 50,1) + playsound(S, get_sfx("soulstone"), 50,1) S.dust() if(target && S.target != target) @@ -578,7 +587,7 @@ /mob/living/simple_animal/hostile/humanoid/skellington/lich/Shoot(atom/a, params) var/spell = rand(1,5) - var/diceroll = roll("1d20") + var/diceroll = rand(1,20) var/list/victims = list() for(var/mob/living/carbon/human/H in view(src, magic_range)) victims.Add(H) @@ -607,7 +616,9 @@ to_chat(H, "\The [I] is pulled from your grasp!") I.throw_at(get_edge_target_turf(target, pick(alldirs)),15,1) victims.Remove(H) - /*if(3) //Soul Swarm + if(!victims.len) + break + if(3) //Soul Swarm visible_message("\The [src] starts to float above the ground!") animate(src, pixel_y = 8, time = 1 SECONDS, easing = ELASTIC_EASING) animate(pixel_y = rand(8,19), pixel_x = rand(-8,8), time = 3 SECONDS, easing = SINE_EASING, loop = 5) @@ -616,10 +627,12 @@ if(mtarget.isDead()) continue to_chat(mtarget, "\The [src] sets its gaze upon you, and fires a soul swarm at you!") - new /obj/item/projectile/soul_swarm(get_turf(src), targetmob = mtarget) - animate(src, pixel_y = 0, pixel_x = 0, time = 3 SECONDS, easing = SINE_EASING)*/ + var/obj/item/projectile/P = new /obj/item/projectile/soul_swarm(get_turf(src), targetmob = mtarget) + spawn() + P.OnFired() + P.process() + animate(src, pixel_y = 0, pixel_x = 0, time = 3 SECONDS, easing = SINE_EASING) if(4) //Raise undead - visible_message("\The [src] raises both hands, and clasps them togheter.") var/number_of_raised = round(diceroll/3) for(var/mob/living/carbon/human/H in victims) if(!H.isDead()) @@ -632,20 +645,19 @@ if(!isskellington(H)) new /obj/effect/gibspawner/generic(get_turf(H)) H.drop_all() + visible_message("\The [src] points towards \the [H].") H.visible_message("\The [H] raises from the dead!") new /mob/living/simple_animal/hostile/humanoid/skellington(H.loc) qdel(H) if(5) //Fall - var/spell/aoe_turf/fall/fall = new /spell/aoe_turf/fall - fall.spell_flags = 0 - fall.invocation_type = SpI_NONE - fall.the_world_chance = 0 - fall.range = magic_range - fall.sleeptime = 8*diceroll - fall.perform(src, skipcharge = 1) - qdel(fall) + flags |= TIMELESS + var/duration = 8*diceroll + timestop(src, duration, magic_range, TRUE) + spawn(duration) + flags &= ~TIMELESS -/*/obj/item/projectile/soul_swarm + +/obj/item/projectile/soul_swarm name = "soul swarm" desc = "It flickers with some rudimentary form of intelligence, but conversation doesn't seem to be the strong point of a magical projectile." icon_state = "soul" @@ -654,6 +666,10 @@ var/mob/mobtarget = null +/obj/item/projectile/soul_swarm/Destroy() + mobtarget = null + ..() + /obj/item/projectile/soul_swarm/New(var/mob/targetmob) ..() stun = rand(0,25) @@ -665,4 +681,8 @@ drowsy = rand(0,25) agony = rand(0,25) jittery = rand(0,25) - mobtarget = targetmob*/ + mobtarget = targetmob + +/obj/item/projectile/soul_swarm/process_step() + ..() + original = mobtarget.loc //update the target \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/hostile/human/jackal.dm b/code/modules/mob/living/simple_animal/hostile/human/jackal.dm index 7a6b4819397..d43588c9516 100644 --- a/code/modules/mob/living/simple_animal/hostile/human/jackal.dm +++ b/code/modules/mob/living/simple_animal/hostile/human/jackal.dm @@ -32,10 +32,9 @@ faction = "mummy" corpse = null -/mob/living/simple_animal/hostile/humanoid/jackal/Die() +/mob/living/simple_animal/hostile/humanoid/jackal/death(var/gibbed = FALSE) visible_message("\The [src] crumbles to dust!") - - ..() + ..(gibbed) //qdel(src) is called in the parent /mob/living/simple_animal/hostile/humanoid/jackal/adjustFireLoss() //Immune to fire diff --git a/code/modules/mob/living/simple_animal/hostile/human/mummy.dm b/code/modules/mob/living/simple_animal/hostile/human/mummy.dm index 1f7a4510ccd..70917a9c638 100644 --- a/code/modules/mob/living/simple_animal/hostile/human/mummy.dm +++ b/code/modules/mob/living/simple_animal/hostile/human/mummy.dm @@ -42,7 +42,7 @@ corpseuniform = /obj/item/clothing/under/mummy_rags corpsehelmet = /obj/item/clothing/head/mummy_rags -/mob/living/simple_animal/hostile/humanoid/mummy/Die() +/mob/living/simple_animal/hostile/humanoid/mummy/death(var/gibbed = FALSE) if(!isturf(loc)) return @@ -53,7 +53,7 @@ spawn(0) S.start() - ..() + ..(gibbed) /datum/effect/effect/system/smoke_spread/chem/rot/set_up(var/mob/M, n = 5, c = 0, loca, direct) if(n > 20) diff --git a/code/modules/mob/living/simple_animal/hostile/human/nazi.dm b/code/modules/mob/living/simple_animal/hostile/human/nazi.dm index 1eb6d45c9b0..627acc87930 100644 --- a/code/modules/mob/living/simple_animal/hostile/human/nazi.dm +++ b/code/modules/mob/living/simple_animal/hostile/human/nazi.dm @@ -9,8 +9,8 @@ speak = list("Schweinhunds!","Can you feel ze Schadenfreude?","Ach, was ist los?") speak_emote = list("says") - emote_hear = list("says") - emote_see = list("hums") + emote_hear = list("hums") + emote_see = list("goose-steps", "heils") attacktext = "punches" attack_sound = "punch" speak_chance = 5 @@ -55,9 +55,9 @@ if (melee_damage_upper > 10) overlays += icon('icons/mob/in-hand/right/swords_axes.dmi',"knifenazi") -/mob/living/simple_animal/hostile/humanoid/nazi/Die() +/mob/living/simple_animal/hostile/humanoid/nazi/death(var/gibbed = FALSE) droploot() - ..() + ..(gibbed) /mob/living/simple_animal/hostile/humanoid/nazi/Shoot(var/atom/target, var/atom/start, var/mob/user, var/bullet = 0) if(..()) @@ -309,8 +309,8 @@ speak = list("Die, Allied schweinhund!","Die Welt ist unser!","Guten Tag!" ,"Scheise!") speak_emote = list("says") - emote_hear = list("says") - emote_see = list("hums") + emote_hear = list("hums") + emote_see = list("stomps") attacktext = "crushes" attack_sound = 'sound/weapons/heavysmash.ogg' speak_chance = 20 @@ -363,8 +363,9 @@ /mob/living/simple_animal/hostile/mechahitler/Process_Spacemove(var/check_drift = 0) return 1 -/mob/living/simple_animal/hostile/mechahitler/Die() +/mob/living/simple_animal/hostile/mechahitler/death(var/gibbed = FALSE) set waitfor = 0 + ..(TRUE) dir = 2 say("Eva, auf wiedersehen!") ranged = 0 diff --git a/code/modules/mob/living/simple_animal/hostile/human/skellington.dm b/code/modules/mob/living/simple_animal/hostile/human/skellington.dm index 47f0b5ffbc1..0b4e7da430e 100644 --- a/code/modules/mob/living/simple_animal/hostile/human/skellington.dm +++ b/code/modules/mob/living/simple_animal/hostile/human/skellington.dm @@ -81,12 +81,12 @@ corpse = /obj/effect/landmark/corpse/skellington/petard /mob/living/simple_animal/hostile/humanoid/skellington/petard/AttackingTarget() - Die() + death() -/mob/living/simple_animal/hostile/humanoid/skellington/petard/Die() +/mob/living/simple_animal/hostile/humanoid/skellington/petard/death(var/gibbed = FALSE) var/turf/T = get_turf(src) - ..() + ..(TRUE) explosion(T, -1, 1, 2) diff --git a/code/modules/mob/living/simple_animal/hostile/human/surgeon.dm b/code/modules/mob/living/simple_animal/hostile/human/surgeon.dm new file mode 100644 index 00000000000..a57056ef295 --- /dev/null +++ b/code/modules/mob/living/simple_animal/hostile/human/surgeon.dm @@ -0,0 +1,72 @@ +//mob/living/simple_animal/hostile/humanoid/surgeon/ +// name = "\improper Surgeon" +// desc = "Don't interfere with his work!" +// icon = 'icons/mob/hostile_humanoid.dmi' +// icon_state = "surgeon" +// icon_living = "surgeon" +// maxHealth = 100 +// health = 100 + +// harm_intent_damage = 10 +// melee_damage_lower = 8 +// melee_damage_upper = 13 +// attacktext = "saws" +// attack_sound = 'sound/weapons/circsawhit.ogg' + +// ranged = 0 +// gender = MALE + +// corpse = /obj/effect/landmark/corpse/surgeon +// items_to_drop = list(/obj/item/weapon/circular_saw/plasmasaw) + +//mob/living/simple_animal/hostile/humanoid/surgeon/boss +// name = "Doctor Placeholder" //I can't think of a good name +// desc = "A deranged surgeon lost deep in space." +// icon_dead = null //this isn't even his final form +// maxHealth = 80 +// health = 80 + +// harm_intent_damage = 15 +// melee_damage_lower = 13 +// melee_damage_upper = 20 + +// corpse = null //he isn't dead yet + +// faction = "necro" //don't want him to get killed by skeletons before his transformation + +//mob/living/simple_animal/hostile/humanoid/surgeon/boss/death(var/gibbed = FALSE) +// ..(gibbed) +// visible_message("Before he can die, the mad surgeon takes a drink of a foul-smelling concoction and begins to mutate! ") +// say("[pick("YOU CAN'T KILL ME THAT EASILY!", "I WONT LET YOU STOP ME!", "GET OUT OF MY FACILITY!", "I MUST CONTINUE MY RESEARCH!", "I'M GONNA WRECK IT!", "I'VE GOT A BONE TO PICK WITH YOU!")]") +// var/obj/effect/effect/smoke/S = new /obj/effect/effect/smoke(get_turf(src)) +// S.time_to_live = 20 +// new /mob/living/simple_animal/hostile/humanoid/surgeon/skeleton/(get_turf(src)) +// ..() +// return qdel(src) + +//mob/living/simple_animal/hostile/humanoid/surgeon/skeleton +// name = "\improper Skeletal Surgeon" +// desc = "He wont be pushed around any longer" +// icon = 'icons/mob/surgeon.dmi' +// icon_state = "skelesurgeon" +// icon_living = "skelesurgeon" +// maxHealth = 400 +// health = 400 + +// move_to_delay = 5 //slow +// harm_intent_damage = 30 +// melee_damage_lower = 25 +// melee_damage_upper = 35 +// environment_smash_flags = SMASH_LIGHT_STRUCTURES | SMASH_CONTAINERS | SMASH_WALLS //he will smash through most barriers, but the walls of his vault are rwalls +// attacktext = "crushes" +// attack_sound = 'sound/weapons/heavysmash.ogg' + +// corpse = /obj/effect/landmark/corpse/surgeon/skeleton + +// faction = "necro" +// mob_property_flags = MOB_UNDEAD +// items_to_drop = list() + +//mob/living/simple_animal/hostile/humanoid/surgeon/skeleton/New() +// ..() +// flick("skelesurgeon_laugh", src) diff --git a/code/modules/mob/living/simple_animal/hostile/human/wizard.dm b/code/modules/mob/living/simple_animal/hostile/human/wizard.dm index 4a3d6fd118b..2eb6263f7d8 100644 --- a/code/modules/mob/living/simple_animal/hostile/human/wizard.dm +++ b/code/modules/mob/living/simple_animal/hostile/human/wizard.dm @@ -34,13 +34,13 @@ if(speak_when_spawned) speak = list("Your souls shall suffer!", "No mortals shall be spared.", "My magic will tear you apart!", "Prepare to face the almighty [name]!") -/mob/living/simple_animal/hostile/humanoid/wizard/Die() +/mob/living/simple_animal/hostile/humanoid/wizard/death(var/gibbed = FALSE) src.say("SCYAR NILA [pick("AI UPLOAD", "SECURE ARMORY", "BAR", "PRIMARY TOOL STORAGE", "INCINERATOR", "CHAPEL", "FORE STARBOARD MAINTENANCE", "WIZARD FEDERATION")]") var/obj/effect/effect/smoke/S = new /obj/effect/effect/smoke(get_turf(src)) S.time_to_live = 20 //2 seconds instead of full 10 - ..() - return qdel(src) + ..(TRUE) + qdel(src) /mob/living/simple_animal/hostile/humanoid/wizard/OpenFire() src.say(incantation) @@ -65,6 +65,8 @@ /mob/living/simple_animal/hostile/humanoid/wizard/doppelganger/Destroy() spell = null + var/mob/my_wiz = doppelgangers[src] + doppelgangers_count_by_wizards[my_wiz]-- doppelgangers[src] = null doppelgangers -= src ..() diff --git a/code/modules/mob/living/simple_animal/hostile/mannequin.dm b/code/modules/mob/living/simple_animal/hostile/mannequin.dm index 36c33b508cd..720a36aab53 100644 --- a/code/modules/mob/living/simple_animal/hostile/mannequin.dm +++ b/code/modules/mob/living/simple_animal/hostile/mannequin.dm @@ -37,8 +37,8 @@ var/list/clothing = list() -/mob/living/simple_animal/hostile/mannequin/Die() - ..() +/mob/living/simple_animal/hostile/mannequin/death(var/gibbed = FALSE) + ..(TRUE) breakDown() qdel(src) diff --git a/code/modules/mob/living/simple_animal/hostile/mimic.dm b/code/modules/mob/living/simple_animal/hostile/mimic.dm index fc6c109472a..6b0b17f6b5e 100644 --- a/code/modules/mob/living/simple_animal/hostile/mimic.dm +++ b/code/modules/mob/living/simple_animal/hostile/mimic.dm @@ -46,8 +46,8 @@ .=..() apply_disguise() -/mob/living/simple_animal/hostile/mimic/Die() - ..() +/mob/living/simple_animal/hostile/mimic/death(var/gibbed = FALSE) + ..(TRUE) visible_message("[src] stops moving!") qdel(src) @@ -247,7 +247,7 @@ var/global/list/crate_mimic_disguises = list(\ if(!angry) anger(berserk = 1) visible_message("\The [src] roars in rage!") - playsound(get_turf(src), 'sound/hallucinations/growl1.ogg', 50, 1) + playsound(src, 'sound/hallucinations/growl1.ogg', 50, 1) // Chest mimic - more robust than crate mimic // Does more damage, has a robust tongue that it uses to grab things @@ -271,11 +271,11 @@ var/global/list/crate_mimic_disguises = list(\ var/can_grab = 1 -/mob/living/simple_animal/hostile/mimic/crate/chest/Die() +/mob/living/simple_animal/hostile/mimic/crate/chest/death(var/gibbed = FALSE) for(var/atom/movable/A in get_locked(/datum/locking_category/mimic)) unlock_atom(A) visible_message("\The [src] lets go of \the [A]!") - ..() + ..(gibbed) /mob/living/simple_animal/hostile/mimic/crate/chest/AttackingTarget() ..() @@ -435,9 +435,9 @@ var/global/list/item_mimic_disguises = list( if(desc) to_chat(user, desc) -/mob/living/simple_animal/hostile/mimic/crate/item/Die() +/mob/living/simple_animal/hostile/mimic/crate/item/death(var/gibbed = FALSE) copied_object = meat_type //Without this line, mimics would spawn items they're disguised as. Since they're relatively weak and can appear as gatling guns, this is required! - ..() + ..(gibbed) /mob/living/simple_animal/hostile/mimic/crate/item/attack_hand(mob/user) if(angry) @@ -532,17 +532,17 @@ var/global/list/protected_objects = list( // Die after a specified time limit if(time_to_die && world.time >= time_to_die) - Die() + death() return for(var/mob/living/M in contents) //a fix for animated statues from the flesh to stone spell - Die() + death() return -/mob/living/simple_animal/hostile/mimic/copy/Die() +/mob/living/simple_animal/hostile/mimic/copy/death(var/gibbed = FALSE) for(var/atom/movable/M in src) M.forceMove(get_turf(src)) - ..() + ..(gibbed) /mob/living/simple_animal/hostile/mimic/copy/ListTargets() // Return a list of targets that isn't the creator diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm index 6fb1b688454..acfc1e75543 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm @@ -17,6 +17,7 @@ response_disarm = "shoves" response_harm = "strikes" status_flags = 0 + size = SIZE_BIG a_intent = I_HURT var/throw_message = "bounces off of" var/icon_aggro = null // for swapping to when we get aggressive @@ -219,10 +220,10 @@ obj/item/asteroid/basilisk_hide/New() visible_message("The [P.name] was repelled by [src.name]'s girth!") return -/mob/living/simple_animal/hostile/asteroid/goldgrub/Die() +/mob/living/simple_animal/hostile/asteroid/goldgrub/death(var/gibbed = FALSE) alerted = 0 Reward() - ..() + ..(gibbed) /mob/living/simple_animal/hostile/asteroid/hivelord name = "hivelord" @@ -264,9 +265,9 @@ obj/item/asteroid/basilisk_hide/New() /mob/living/simple_animal/hostile/asteroid/hivelord/AttackingTarget() OpenFire() -/mob/living/simple_animal/hostile/asteroid/hivelord/Die() +/mob/living/simple_animal/hostile/asteroid/hivelord/death(var/gibbed = FALSE) mouse_opacity = 1 - ..() + ..(gibbed) update_icons() /mob/living/simple_animal/hostile/asteroid/hivelord/update_icons() @@ -313,7 +314,7 @@ obj/item/asteroid/basilisk_hide/New() /obj/item/asteroid/hivelord_core/process() if(reagents && reagents.has_reagent(FROSTOIL, 5)) - playsound(get_turf(src), 'sound/effects/glass_step.ogg', 50, 1) + playsound(src, 'sound/effects/glass_step.ogg', 50, 1) desc = "All that remains of a hivelord, it seems to be what allows it to break pieces of itself off without being hurt. It is covered in a thin coat of frost." processing_objects.Remove(src) return @@ -371,7 +372,7 @@ obj/item/asteroid/basilisk_hide/New() else to_chat(user, "You chomp into \the [src], barely managing to hold it down, but feel amazingly refreshed in mere moments.") - playsound(get_turf(src), 'sound/items/eatfood.ogg', rand(10, 50), 1) + playsound(src, 'sound/items/eatfood.ogg', rand(10, 50), 1) target.revive() user.drop_from_inventory(src) @@ -407,7 +408,8 @@ obj/item/asteroid/basilisk_hide/New() spawn(100) returnToPool(src) -/mob/living/simple_animal/hostile/asteroid/hivelordbrood/Die() +/mob/living/simple_animal/hostile/asteroid/hivelordbrood/death(var/gibbed = FALSE) + ..(TRUE) returnToPool(src) /mob/living/simple_animal/hostile/asteroid/goliath @@ -510,3 +512,111 @@ obj/item/asteroid/basilisk_hide/New() else to_chat(user, "You can't improve [C] any further.") return + +/mob/living/simple_animal/hostile/asteroid/magmaw + name = "magmaw" + desc = "A living furnace. These things are drawn to crystallized plasma, which they feast upon to stoke their internal fires." + icon_state = "lavagoop" + icon_living = "lavagoop" + icon_aggro = "lavagoop" + icon_attack = "lavagoop_attack" + icon_attack_time = 7 + icon_dying = "lavagoop_dying" + icon_dying_time = 19 + icon_dead = "lavagoop_dead" + attack_sound = 'sound/weapons/bite.ogg' + search_objects = 3 + health = 125 + maxHealth = 125 + melee_damage_lower = 10 + melee_damage_upper = 25 + meat_amount = 0 + vision_range = 4 + faction = "neutral" + maxbodytemp = ARBITRARILY_PLANCK_NUMBER + var/fire_time + var/fire_extremity + +/mob/living/simple_animal/hostile/asteroid/magmaw/fire_act(var/datum/gas_mixture/air, var/exposed_temperature, var/exposed_volume) + fire_resurrect(exposed_temperature) + +/mob/living/simple_animal/hostile/asteroid/magmaw/IgniteMob() + fire_resurrect(PLASMA_MINIMUM_BURN_TEMPERATURE) + +/mob/living/simple_animal/hostile/asteroid/magmaw/FireBurn(var/firelevel, var/last_temperature, var/pressure) + fire_resurrect(last_temperature) + +/mob/living/simple_animal/hostile/asteroid/magmaw/proc/fire_resurrect(var/temperature) + if(isDead() && temperature > PLASMA_MINIMUM_BURN_TEMPERATURE) + resurrect() + revive() + visible_message("\The [src] reignites!") + + +/mob/living/simple_animal/hostile/asteroid/magmaw/adjustFireLoss() + return //We're a magma slime. We ARE FIRE. + + +/mob/living/simple_animal/hostile/asteroid/magmaw/Life() + if(!..()) + return + var/datum/gas_mixture/environment + + if(isturf(loc)) + var/turf/T = loc + environment = T.return_air() + + if(environment) + environment.add_thermal_energy(50000) + + if(world.time > fire_time) + return + + switch(fire_extremity) + if(1) // Fire spout + generic_projectile_fire(get_ranged_target_turf(src, dir, 10), src, /obj/item/projectile/fire_breath, 'sound/weapons/flamethrower.ogg') + if(environment) + environment.add_thermal_energy(350000) + if(2) //Fire blast + new /obj/effect/ring_of_fire(get_turf(src), range(src,4)-range(src,3), 3 SECONDS) + if(environment) + environment.add_thermal_energy(700000) + +/mob/living/simple_animal/hostile/asteroid/magmaw/CanAttack(var/atom/the_target) + if(world.time < fire_time) + return + if(istype(the_target, /obj/item/weapon/ore/plasma) || istype(the_target, /obj/item/stack/sheet/mineral/plasma)) + return 1 + if(istype(the_target, /turf/unsimulated/mineral)) + var/turf/unsimulated/mineral/M = the_target + if(M.mineral && istype(M.mineral.ore, /obj/item/weapon/ore/plasma)) + return 1 + return 0 + +/mob/living/simple_animal/hostile/asteroid/magmaw/EscapeConfinement() + ..() + if(world.time < fire_time) //Not hungry enough to go smashing up asteroids yet + return + for(var/turf/unsimulated/mineral/M in range(src, 1)) + if(prob(15)) + UnarmedAttack(M, Adjacent(M)) + +/mob/living/simple_animal/hostile/asteroid/magmaw/UnarmedAttack(var/atom/A, var/proximity, var/params) + if(proximity == 0) + return + var/is_ore = istype(A, /obj/item/weapon/ore/plasma) + var/is_sheet = istype(A, /obj/item/stack/sheet/mineral/plasma) + if(is_ore || is_sheet) + visible_message("\The [src] eats \the [A]!") + if(is_ore) + fire_time = world.time + 25 SECONDS + fire_extremity = 1 + else if(is_sheet) + fire_time = world.time + 90 SECONDS + fire_extremity = 2 + qdel(A) + return + if(istype(A,/turf/unsimulated/mineral)) + var/turf/unsimulated/mineral/M = A + M.GetDrilled(0) + return ..() \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/hostile/monster.dm b/code/modules/mob/living/simple_animal/hostile/monster.dm index 268c728a6a4..17fe28687d9 100644 --- a/code/modules/mob/living/simple_animal/hostile/monster.dm +++ b/code/modules/mob/living/simple_animal/hostile/monster.dm @@ -83,12 +83,11 @@ visible_message("[src] injects something from its flailing arm!") L.reagents.add_reagent(MEDNANOBOTS, 2) -/mob/living/simple_animal/hostile/monster/cyber_horror/Die() - ..() +/mob/living/simple_animal/hostile/monster/cyber_horror/death(var/gibbed = FALSE) + ..(gibbed) visible_message("[src] blows apart!") new /obj/effect/gibspawner/robot(src.loc) qdel(src) - return /mob/living/simple_animal/hostile/monster/cyber_horror/Vox name = "vox cyber horror" diff --git a/code/modules/mob/living/simple_animal/hostile/mushroom.dm b/code/modules/mob/living/simple_animal/hostile/mushroom.dm index 6fa54424b51..668d9bfc99f 100644 --- a/code/modules/mob/living/simple_animal/hostile/mushroom.dm +++ b/code/modules/mob/living/simple_animal/hostile/mushroom.dm @@ -90,9 +90,9 @@ icon_state = "mushroom_color" UpdateMushroomCap() -/mob/living/simple_animal/hostile/mushroom/Die() +/mob/living/simple_animal/hostile/mushroom/death(var/gibbed = FALSE) visible_message("[src] fainted.") - ..() + ..(gibbed) UpdateMushroomCap() /mob/living/simple_animal/hostile/mushroom/proc/UpdateMushroomCap() diff --git a/code/modules/mob/living/simple_animal/hostile/necro.dm b/code/modules/mob/living/simple_animal/hostile/necro.dm index 8fc25f5f52b..a274114c061 100644 --- a/code/modules/mob/living/simple_animal/hostile/necro.dm +++ b/code/modules/mob/living/simple_animal/hostile/necro.dm @@ -4,16 +4,18 @@ faction = "necro" mob_property_flags = MOB_UNDEAD -/mob/living/simple_animal/hostile/necro/New(loc, mob/living/Owner, datum/mind/Controller) +/mob/living/simple_animal/hostile/necro/New(loc, mob/living/Owner, var/mob/living/Victim, datum/mind/Controller) ..() - if(Controller) - mind = Controller - ckey = ckey(mind.key) + if(Victim && Victim.mind) + Victim.mind.transfer_to(src) + var/mob/dead/observer/ghost = get_ghost_from_mind(mind) + if(ghost && ghost.can_reenter_corpse) + key = mind.key // Force the ghost in here if(Owner) faction = "\ref[Owner]" friends.Add(Owner) creator = Owner - if(Controller) + if(client) to_chat(src, "You have been risen from the dead by your new master, [Owner]. Do his bidding so long as he lives, for when he falls so do you.") if(name == initial(name) && !unique_name) @@ -282,7 +284,7 @@ time_mult += 1 stop_automated_movement = 1 D.visible_message("\The [D]'s motors whine as something attempts to brute force their way through it!") - playsound(get_turf(D), 'sound/effects/grillehit.ogg', 50, 1) + playsound(D, 'sound/effects/grillehit.ogg', 50, 1) D.shake(1, 8) busy = TRUE var/target_loc = D.loc @@ -305,7 +307,7 @@ D.open(1) else to_chat(src, "You fail to open \the [D]") - playsound(get_turf(D), 'sound/effects/grillehit.ogg', 50, 1) + playsound(D, 'sound/effects/grillehit.ogg', 50, 1) D.shake(1, 8) busy = FALSE stop_automated_movement = 0 @@ -327,7 +329,7 @@ //Deal a random amount of brute damage to the corpse in question, heal the zombie by the damage dealt halved visible_message("\The [src] takes a bite out of \the [target].") stop_automated_movement = 1 - playsound(get_turf(src), 'sound/weapons/bite.ogg', 50, 1) + playsound(src, 'sound/weapons/bite.ogg', 50, 1) var/damage = rand(melee_damage_lower, melee_damage_upper) target.adjustBruteLoss(damage) if(maxHealth < health_cap) @@ -406,8 +408,8 @@ lying = 0 update_transform() -/mob/living/simple_animal/hostile/necro/zombie/Die() - ..() +/mob/living/simple_animal/hostile/necro/zombie/death(var/gibbed = FALSE) + ..(gibbed) lying = 1 update_transform() @@ -444,6 +446,7 @@ health = 50 can_evolve = TRUE var/mob/living/carbon/human/host //Whoever the zombie was previously, kept in a reference to potentially bring back + var/being_unzombified = FALSE /mob/living/simple_animal/hostile/necro/zombie/turned/check_evolve() ..() @@ -461,13 +464,16 @@ ..() if(stat == DEAD) //Can only attempt to unzombify if they're dead if(istype (W, /obj/item/weapon/storage/bible)) //This calls for divine intervention + if(being_unzombified) + to_chat(user, "\The [src] is already being repeatedly whacked!") + return + being_unzombified = TRUE var/obj/item/weapon/storage/bible/bible = W user.visible_message("\The [user] begins whacking at [src] repeatedly with a bible for some reason.", "You attempt to invoke the power of [bible.my_rel.deity_name] to bring this poor soul back from the brink.") var/chaplain = 0 //Are we the Chaplain ? Used for simplification if(user.mind && (user.mind.assigned_role == "Chaplain")) chaplain = TRUE //Indeed we are - if(do_after(user, src, 25)) //So there's a nice delay if(!chaplain) if(prob(5)) //Let's be generous, they'll only get one regen for this @@ -493,12 +499,15 @@ unzombify() else to_chat (user, "Well, that didn't work.") + being_unzombified = FALSE /mob/living/simple_animal/hostile/necro/zombie/turned/proc/unzombify() - if(host) + if(host && mind) host.loc = get_turf(src) - if(!host.mind && src.mind) //This is assuming that, somehow, the host lost their soul, and it ended up in the zombie - mind.transfer_to(host) + mind.transfer_to(host) + var/mob/dead/observer/ghost = get_ghost_from_mind(mind) + if(ghost && ghost.can_reenter_corpse) + key = mind.key host.resurrect() //It's a miracle! host.revive() visible_message("\The [src]'s eyes regain focus, the smell of decay vanishing, [host] has come back to their senses!.") @@ -557,6 +566,7 @@ get_clothes(target, new_zombie) new_zombie.name = target.real_name new_zombie.host = target + target.ghostize() target.loc = null /mob/living/simple_animal/hostile/necro/zombie/proc/get_clothes(var/mob/target, var/mob/living/simple_animal/hostile/necro/zombie/new_zombie) @@ -602,7 +612,6 @@ break_doors = CANPLUS /mob/living/simple_animal/hostile/necro/zombie/leatherman - ..() name = "leatherman" icon_dead = "zombie_leather" icon_gib = "zombie_leather" @@ -671,6 +680,9 @@ visible_message("\The [src] glows with a brilliant light!") set_light(vision_range/2, vision_range, "#a1d68b") spawn(1 SECONDS) + / + emitted_harvestable_radiation(get_turf(src), rand(250, 500), range = 7) + var/list/can_see = view(src, vision_range) for(var/mob/living/carbon/human/H in can_see) var/rad_cost = min(radiation, rand(10,20)) @@ -700,4 +712,4 @@ #undef CAN #undef CANT #undef CANPLUS -#undef RAD_COST \ No newline at end of file +#undef RAD_COST diff --git a/code/modules/mob/living/simple_animal/hostile/necromorph.dm b/code/modules/mob/living/simple_animal/hostile/necromorph.dm index fecac9f13c9..57eb3f01c50 100644 --- a/code/modules/mob/living/simple_animal/hostile/necromorph.dm +++ b/code/modules/mob/living/simple_animal/hostile/necromorph.dm @@ -178,9 +178,10 @@ /mob/living/simple_animal/hostile/necromorph/exploder/AttackingTarget() visible_message("\The [src] hits \the [target] with their left arm!") - Die() + death() -/mob/living/simple_animal/hostile/necromorph/exploder/Die() +/mob/living/simple_animal/hostile/necromorph/exploder/death(var/gibbed = FALSE) + ..(TRUE) visible_message("\The [src] explodes!") var/turf/T = get_turf(src) new /obj/effect/gibspawner/generic(T) diff --git a/code/modules/mob/living/simple_animal/hostile/rattlemebones.dm b/code/modules/mob/living/simple_animal/hostile/rattlemebones.dm index 3063813817f..7cf3ea406fd 100644 --- a/code/modules/mob/living/simple_animal/hostile/rattlemebones.dm +++ b/code/modules/mob/living/simple_animal/hostile/rattlemebones.dm @@ -59,14 +59,14 @@ Bumped(Obstacle) ..() -/mob/living/simple_animal/hostile/rattlemebones/Die() +/mob/living/simple_animal/hostile/rattlemebones/death(var/gibbed = FALSE) visible_message("\The [src] collapses into a pile of bones!") name = "pile of bones" desc = "It looks like a pile of human bones." icon = 'icons/effects/blood.dmi' icon_state = "remains" icon_dead = "remains" - ..() + ..(gibbed) /mob/living/simple_animal/hostile/rattlemebones/ListTargets() if(!rattled) diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/cluwne.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/cluwne.dm index 2f0387a9f3d..b8fde09f958 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/cluwne.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/cluwne.dm @@ -17,7 +17,7 @@ response_harm = "hits the" speak = list("HONK", "Honk!", "PLEASE KILL ME") speak_emote = list("squeals", "cries","sobs") - emote_see = list("honks sadly") + emote_hear = list("honks sadly") speak_chance = 1 a_intent = I_HELP var/footstep=0 // For clownshoe noises @@ -286,10 +286,6 @@ message = uppertext(jointext(temp_message, " ")) return ..(message) -/mob/living/simple_animal/hostile/retaliate/cluwne/Die() - ..() - walk(src, 0) - /mob/living/simple_animal/hostile/retaliate/cluwne/proc/handle_disabilities() if ((prob(5) && paralysis < 10)) to_chat(src, "You have a seizure!") @@ -300,7 +296,6 @@ return //under effects of time magick var/msg = pick("quietly sobs into a dirty handkerchief","cries into [gender==MALE?"his":"her"] hands","bawls like a cow") - msg = "[src] [msg]" return ..(msg) /mob/living/simple_animal/hostile/retaliate/cluwne/Move(NewLoc, Dir = 0, step_x = 0, step_y = 0, glide_size_override = 0) @@ -325,7 +320,7 @@ response_help = "honks the" speak = list("Honk!") speak_emote = list("sqeaks") - emote_see = list("honks") + emote_hear = list("honks") maxHealth = 100 health = 100 size = 1 @@ -344,8 +339,8 @@ return ..() -/mob/living/simple_animal/hostile/retaliate/cluwne/goblin/Die() - ..() +/mob/living/simple_animal/hostile/retaliate/cluwne/goblin/death(var/gibbed = FALSE) + ..(TRUE) new /obj/item/clothing/mask/gas/clown_hat(src.loc) new /obj/item/clothing/shoes/clown_shoes(src.loc) qdel(src) diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/drone.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/drone.dm index 3eb62faeca9..9cb05713443 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/drone.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/drone.dm @@ -166,9 +166,9 @@ hostile_time = 0 walk(src,0) -/mob/living/simple_animal/hostile/retaliate/malf_drone/Die() +/mob/living/simple_animal/hostile/retaliate/malf_drone/death(var/gibbed = FALSE) src.visible_message(" [bicon(src)] [src] suddenly breaks apart.") - ..() + ..(TRUE) qdel(src) /mob/living/simple_animal/hostile/retaliate/malf_drone/Destroy() diff --git a/code/modules/mob/living/simple_animal/hostile/slime.dm b/code/modules/mob/living/simple_animal/hostile/slime.dm index 595fb5ee9a9..f647698c432 100644 --- a/code/modules/mob/living/simple_animal/hostile/slime.dm +++ b/code/modules/mob/living/simple_animal/hostile/slime.dm @@ -43,7 +43,8 @@ overlays += image(icon = icon, icon_state = "bloodlust-adult") -/mob/living/simple_animal/hostile/slime/adult/Die() +/mob/living/simple_animal/hostile/slime/adult/death(var/gibbed = FALSE) + ..(gibbed) for(var/i=0;i<2;i++) var/mob/living/simple_animal/hostile/slime/rabid = new /mob/living/simple_animal/hostile/slime (src.loc) rabid.icon_state = "[src.colour] baby slime eat" diff --git a/code/modules/mob/living/simple_animal/hostile/tree.dm b/code/modules/mob/living/simple_animal/hostile/tree.dm index 79425cce5cf..b83b1b1bb3c 100644 --- a/code/modules/mob/living/simple_animal/hostile/tree.dm +++ b/code/modules/mob/living/simple_animal/hostile/tree.dm @@ -42,7 +42,7 @@ /mob/living/simple_animal/hostile/tree/FindTarget() . = ..() if(.) - emote("growls at [.]") + emote("me",, "growls at [.]!") /mob/living/simple_animal/hostile/tree/AttackingTarget() . =..() @@ -52,12 +52,15 @@ L.Knockdown(3) L.visible_message("\the [src] knocks down \the [L]!") -/mob/living/simple_animal/hostile/tree/Die() - ..() +/mob/living/simple_animal/hostile/tree/death(var/gibbed = FALSE) + ..(gibbed) + spawn_reward() + qdel(src) + +/mob/living/simple_animal/hostile/tree/proc/spawn_reward() visible_message("[src] is hacked into pieces!") playsound(loc, 'sound/effects/woodcutting.ogg', 100, 1) new /obj/item/stack/sheet/wood(loc) - qdel(src) /mob/living/simple_animal/hostile/tree/festivus name = "festivus pole" @@ -67,7 +70,6 @@ icon_dead = "festivus_pole" icon_gib = "festivus_pole" -/mob/living/simple_animal/hostile/tree/festivus/Die() +/mob/living/simple_animal/hostile/tree/festivus/spawn_reward() visible_message("[src] is hacked into pieces!") new /obj/item/weapon/nullrod(loc) - qdel(src) diff --git a/code/modules/mob/living/simple_animal/hostile/viscerator.dm b/code/modules/mob/living/simple_animal/hostile/viscerator.dm index a303a08c81a..804df1ea472 100644 --- a/code/modules/mob/living/simple_animal/hostile/viscerator.dm +++ b/code/modules/mob/living/simple_animal/hostile/viscerator.dm @@ -34,18 +34,17 @@ if(stat == CONSCIOUS) animate(src, pixel_x = rand(-12,12) * PIXEL_MULTIPLIER, pixel_y = rand(-12,12) * PIXEL_MULTIPLIER, time = 15, easing = SINE_EASING) -/mob/living/simple_animal/hostile/viscerator/Die() - ..() +/mob/living/simple_animal/hostile/viscerator/death(var/gibbed = FALSE) + ..(TRUE) visible_message("[src] is smashed into pieces!") qdel (src) - return -/* + /mob/living/simple_animal/hostile/viscerator/CanAttack(var/atom/the_target) if(ismob(the_target)) var/mob/mob_target = the_target if((isnukeop(mob_target) && faction == "syndicate") || (iswizard(mob_target) && faction == "wizard")) return 0 - return ..(the_target)*/ + return ..(the_target) /mob/living/simple_animal/hostile/viscerator/Cross(atom/movable/mover, turf/target, height = 1.5, air_group = 0) if(air_group || (height == 0)) @@ -93,7 +92,7 @@ /mob/living/simple_animal/hostile/viscerator/butterfly/Life() ..() if(autodie && life_tick > 10) - Die() + death() /mob/living/simple_animal/hostile/viscerator/butterfly/magic name = "crystal butterfly" diff --git a/code/modules/mob/living/simple_animal/hostile/wendigo.dm b/code/modules/mob/living/simple_animal/hostile/wendigo.dm new file mode 100644 index 00000000000..5197b66c576 --- /dev/null +++ b/code/modules/mob/living/simple_animal/hostile/wendigo.dm @@ -0,0 +1,226 @@ +/* TODO: + Let them evolve and heal from eating. Should a carbon they eat go over a certain damage threshold and + the wendigo is at full health. Strip and delete the corpse. + Human wendigo->1 eat->Wendigo->3 eat->Alpha Wendigo (Can only be ONE at any time) + They don't like fire. Will stay away from fire (As far as their light radius -1) and won't target anyone + in vicinity of said fire + Can mimic voices, steal poly code, and change it (Maybe just keep a log of people consumed, + and use their name plus shout for help) + Butcherable for one piece of meat only. When consumed (Don't use reagents) will begin to turn the person +*/ +#define HUMEVOLV 1 +#define EVOLEVOLV 3 + + +/mob/living/simple_animal/hostile/wendigo + name = "wendigo" + desc = "Standing tall, deep sunken eyes, and a voracious appetite. This individual has seen better days." + icon_state = "wendigo" + icon_living = "wendigo" + icon_dead = "wendigo_dead" + + health = 150 + maxHealth = 150 + speed = 1 + stat_attack = DEAD //Gotta chow down somehow + size = SIZE_BIG + vision_range = 12 //Slightly larger vision range + harm_intent_damage = 8 + melee_damage_lower = 15 + melee_damage_upper = 20 + attacktext = "bites" + attack_sound = 'sound/weapons/bite.ogg' + meat_amount = 1 //Only one piece of meat + meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/wendigo + var/list/names = list() //List of names of the people it's eaten + var/consumes = 0 //How many people it has eaten + speak_chance = 15 + speak = list("Help!","Help me!","Somebody help!","Get over here, quickly!") + + +/mob/living/simple_animal/hostile/wendigo/CanAttack(var/atom/the_target) + var/list/target_prox = view(the_target, vision_range) + for(var/obj/machinery/space_heater/campfire/fire in target_prox) + var/dist = get_dist(the_target, fire) + if(dist < (fire.light_range*2))//Just sitting on the edge of the fire + return + + if(isliving(target) && !ishuman(target)) + var/mob/living/L = target + if(L.isDead()) + return + + return ..() + +/mob/living/simple_animal/hostile/wendigo/AttackingTarget() + if(!target) + return + + if(ismob(target)) + var/mob/living/mob_target = target + if(mob_target.isDead() && !istype(mob_target, /mob/dead/observer) && (health < maxHealth || ishuman(mob_target))) + set waitfor = 0 + visible_message("\The [src] starts to take a bite out of \the [target].") + stop_automated_movement = 1 + if(do_after(src, mob_target, 50, needhand = FALSE)) + playsound(src, 'sound/weapons/bite.ogg', 50, 1) + var/damage = rand(melee_damage_lower, melee_damage_upper) + mob_target.adjustBruteLoss(damage) + if(health < maxHealth) + health = min(maxHealth,(health+damage)) + + if(ishuman(mob_target)) + if(mob_target.health < -400) + visible_message("\The [src] is trying to consume \the [mob_target]!","You hear crunching.") + if(do_after(src, mob_target, 50, needhand = FALSE)) + consumes += 1 + names |= mob_target.real_name + mob_target.gib() + + return + return ..() + +/mob/living/simple_animal/hostile/wendigo/Life() + /*Check evolve like zombies, run away from fire, + mimic speech if anyone's nearby but just out of eyesight + */ + ..() + if(!isDead()) + if(check_evolve()) + return + + var/list/can_see = view(src, vision_range) + + for(var/obj/machinery/space_heater/campfire/fire in can_see) + var/dist = get_dist(src, fire) + if(dist < (fire.light_range*2)) + walk_away(src,fire,(fire.light_range*2),move_to_delay) + + +/mob/living/simple_animal/hostile/wendigo/GetVoice() + if(names.len) + return pick(names) + else + return "unknown" + +/mob/living/simple_animal/hostile/wendigo/proc/check_evolve() + return 0 + +/mob/living/simple_animal/hostile/wendigo/human + icon_state = "wendigo" + icon_living = "wendigo" + icon_dead = "wendigo_dead" + size = SIZE_NORMAL + speed = 1 + +/mob/living/simple_animal/hostile/wendigo/human/death(var/gibbed = FALSE) + flick("wendigo_dying",src) + ..(gibbed) + +/mob/living/simple_animal/hostile/wendigo/human/check_evolve() + if(consumes > HUMEVOLV) + var/mob/living/simple_animal/hostile/wendigo/evolved/new_wendigo = new /mob/living/simple_animal/hostile/wendigo/evolved(src.loc) + new_wendigo.names = names + qdel(src) + return 1 + +/mob/living/simple_animal/hostile/wendigo/evolved + icon = 'icons/48x48/48x48mob.dmi' + icon_state = "wendigo_med" + icon_living = "wendigo_med" + icon_dead = "wendigo_med_dead" + pixel_x = -8 * PIXEL_MULTIPLIER + health = 250 + maxHealth = 250 + melee_damage_lower = 20 + melee_damage_upper = 35 + +/mob/living/simple_animal/hostile/wendigo/evolved/check_evolve() + if(consumes > EVOLEVOLV && (!animal_count.Find(/mob/living/simple_animal/hostile/wendigo/alpha) || animal_count[/mob/living/simple_animal/hostile/wendigo/alpha] <= 0)) + var/mob/living/simple_animal/hostile/wendigo/alpha/new_wendigo = new /mob/living/simple_animal/hostile/wendigo/alpha(src.loc) + new_wendigo.names = names + qdel(src) + return 1 + +/mob/living/simple_animal/hostile/wendigo/alpha + desc = "You can't help but feel that, no matter what, you should have brought a bigger gun." + icon = 'icons/mob/giantmobs.dmi' + icon_state = "wendigo_noblood" + icon_living = "wendigo_noblood" + icon_dead = "wendigo_dead" + var/icon_enraged = "wendigo" + pixel_x = -16 * PIXEL_MULTIPLIER + health = 600 + maxHealth = 600 + speed = 5 + move_to_delay = 10 + melee_damage_lower = 35 + melee_damage_upper = 50 //Jesus christ + + attacktext = "pulverizes" + attack_sound = 'sound/weapons/heavysmash.ogg' + environment_smash_flags = SMASH_LIGHT_STRUCTURES | SMASH_CONTAINERS | SMASH_WALLS + var/enraged = 0 + var/punch_throw_chance = 25 + var/punch_throw_speed = 1 + var/punch_throw_range = 10 + +/mob/living/simple_animal/hostile/wendigo/alpha/Life() + ..() + if(isDead()) + return + if(health < (maxHealth/2) && enraged == 0) + visible_message("\The [src] seems to slow down, but looks angrier.","You're not sure what that sound was, but it didn't sound good at all.") + enraged = 1 + speed = 7 + melee_damage_lower = 50 + melee_damage_upper = 85 + move_to_delay = 20 + icon_state = icon_enraged + icon_living = icon_enraged + environment_smash_flags = SMASH_LIGHT_STRUCTURES | SMASH_CONTAINERS | SMASH_WALLS | SMASH_RWALLS + punch_throw_chance = 45 + punch_throw_range = 15 + punch_throw_speed = 3 + if(health > 300 && enraged == 1) + enraged = 0 + speed = initial(speed) + melee_damage_lower = initial(melee_damage_lower) + melee_damage_upper = initial(melee_damage_upper) + move_to_delay = initial(move_to_delay) + icon_state = initial(icon_state) + icon_living = initial(icon_living) + environment_smash_flags = initial(environment_smash_flags) + punch_throw_chance = initial(punch_throw_chance) + punch_throw_range = initial(punch_throw_range) + punch_throw_speed = initial(punch_throw_speed) + +/mob/living/simple_animal/hostile/wendigo/alpha/AttackingTarget() + ..() + if(istype(target, /mob/living)) + var/mob/living/M = target + if(punch_throw_range && prob(punch_throw_chance)) + visible_message("\The [M] is thrown by the force of the assault!") + var/turf/T = get_turf(src) + var/turf/target_turf + if(istype(T, /turf/space)) // if ended in space, then range is unlimited + target_turf = get_edge_target_turf(T, dir) + else + target_turf = get_ranged_target_turf(T, dir, punch_throw_range) + M.throw_at(target_turf,100,punch_throw_speed) + +/mob/living/simple_animal/hostile/wendigo/skifree + name = "yeti" + desc = "Holding F might not work this time." + icon_state = "yeti" + icon_living = "yeti" + speed = -1 + move_to_delay = 1 //RUN + health = 150 + maxHealth = 150 + melee_damage_lower = 20 + melee_damage_upper = 40 + +/mob/living/simple_animal/hostile/wendigo/skifree/death(var/gibbed = FALSE) + ..(TRUE) + qdel(src) \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/hostile/wolf.dm b/code/modules/mob/living/simple_animal/hostile/wolf.dm index 0ab9c8992df..dd78301954d 100644 --- a/code/modules/mob/living/simple_animal/hostile/wolf.dm +++ b/code/modules/mob/living/simple_animal/hostile/wolf.dm @@ -31,6 +31,7 @@ icon_living = "wolf" icon_dead = "wolf_dead" speak_chance = 5 + emote_hear = list("growls", "howls") turns_per_move = 4 response_help = "pets" response_disarm = "gently pushes aside" @@ -156,7 +157,7 @@ var/self_loc = src.loc spawn(5 SECONDS) if(mob_target.loc == target_loc && self_loc == src.loc) //Not moved - playsound(get_turf(src), 'sound/weapons/bite.ogg', 50, 1) + playsound(src, 'sound/weapons/bite.ogg', 50, 1) var/damage = rand(melee_damage_lower, melee_damage_upper) mob_target.adjustBruteLoss(damage) nutrition += damage*3 @@ -170,19 +171,14 @@ var/obj/item/weapon/reagent_containers/food/snacks/F = W if(F.food_flags & FOOD_MEAT) //Any meaty dish goes! - playsound(get_turf(src),'sound/items/eatfood.ogg', rand(10,50), 1) + playsound(src,'sound/items/eatfood.ogg', rand(10,50), 1) visible_message("\The [src] gobbles up \the [W]!") nutrition += 15 if(prob(25)) if(!pack_alpha) pack_alpha = user to_chat(user, "You have gained \the [src]'s trust.") - var/n_name = copytext(sanitize(input(user, "What would you like to name your new friend?", "Wolf Name", null) as text|null), 1, MAX_NAME_LEN) - if(n_name && !user.incapacitated()) - name = n_name - var/image/heart = image('icons/mob/animal.dmi',src,"heart-ani2") - heart.plane = ABOVE_HUMAN_PLANE - flick_overlay(heart, list(user.client), 20) + name_mob(user) else if(istype(pack_alpha, /mob/living/simple_animal/hostile/wolf)) var/mob/living/simple_animal/hostile/wolf/alpha = pack_alpha @@ -391,7 +387,7 @@ alpha_target = target /mob/living/simple_animal/hostile/wolf/pointed_at(mob/pointer) - if(!isDead()) + if(!isDead() && see_invisible >= pointer.invisibility) if(pointer == pack_alpha) switch(alpha_stance) if(ALPHAFOLLOW) diff --git a/code/modules/mob/living/simple_animal/parrot.dm b/code/modules/mob/living/simple_animal/parrot.dm index 20f88a26f19..bff835487d7 100644 --- a/code/modules/mob/living/simple_animal/parrot.dm +++ b/code/modules/mob/living/simple_animal/parrot.dm @@ -151,12 +151,12 @@ times_examined_while_dead = 0 ..() -/mob/living/simple_animal/parrot/Die() +/mob/living/simple_animal/parrot/death(var/gibbed = FALSE) if(held_item) held_item.forceMove(src.loc) held_item = null walk(src,0) - ..() + ..(gibbed) /mob/living/simple_animal/parrot/Stat() ..() diff --git a/code/modules/mob/living/simple_animal/roach.dm b/code/modules/mob/living/simple_animal/roach.dm index dea6a080517..03e0649a06e 100644 --- a/code/modules/mob/living/simple_animal/roach.dm +++ b/code/modules/mob/living/simple_animal/roach.dm @@ -22,6 +22,8 @@ response_disarm = "pokes" response_harm = "stomps on" + faction = "roach" + density = 0 minbodytemp = 273.15 //Can't survive at below 0 C @@ -63,7 +65,7 @@ maxHealth = rand(1,6) health = maxHealth -/mob/living/simple_animal/cockroach/Die(var/gore = 1) +/mob/living/simple_animal/cockroach/death(var/gore = 1) if(gore) var/obj/effect/decal/remains = new /obj/effect/decal/cleanable/cockroach_remains(src.loc) @@ -74,7 +76,7 @@ if(flying) animate(remains, pixel_y = pixel_y - 8 * PIXEL_MULTIPLIER, 5, 1) //Fall down gracefully - playsound(get_turf(src), pick('sound/effects/gib1.ogg','sound/effects/gib2.ogg','sound/effects/gib3.ogg'), 40, 1) //Splat + playsound(src, pick('sound/effects/gib1.ogg','sound/effects/gib2.ogg','sound/effects/gib3.ogg'), 40, 1) //Splat ..() @@ -98,7 +100,7 @@ return if(prob(15)) - Die(gore = 1) + death(gore = 1) /mob/living/simple_animal/cockroach/wander_move(turf/dest) ..() @@ -259,7 +261,7 @@ if(P.use(1)) to_chat(user, "You spray \the [src] with \the [P].") playsound(loc, 'sound/effects/spray3.ogg', 50, 1, -6) - Die(gore = 0) + death(gore = 0) else return ..() @@ -280,16 +282,40 @@ switch(id) if(TOXIN) - Die(gore = 0) + death(gore = 0) + if(MUTAGEN) + if(prob(10)) //10% chance to become a big roach + + //Unless there are already a lot of big roaches + if(animal_count[/mob/living/simple_animal/hostile/bigroach] >= ANIMAL_CHILD_CAP) + death(gore = 0) + return + + visible_message("\The [src] evolves!") + message_admins("Created a mutated cockroach at [formatJumpTo(get_turf(src))]; usr = [key_name(usr)]") + grow_up(/mob/living/simple_animal/hostile/bigroach) + else if(prob(20)) //After that, 20% chance to die + death(gore = 0) + else if(prob(0.5)) //After that, 0.5% chance to become a roach queen + + //Unless there is already a roach queen nearby + if(locate(/mob/living/simple_animal/hostile/bigroach/queen) in orange(world.view, src)) + death(gore = 0) + return + + playsound(src, 'sound/effects/lingextends.ogg', 100) + visible_message("\The [src] rapidly evolves, twisting and deforming into something terrifying before your own very eyes!") + message_admins("Created a mutated cockroach matriarch at [formatJumpTo(get_turf(src))]; usr = [key_name(usr)]") + grow_up(/mob/living/simple_animal/hostile/bigroach/queen) /mob/living/simple_animal/cockroach/bite_act(mob/living/carbon/human/H) if(size >= H.size) return - playsound(get_turf(H),'sound/items/eatfood.ogg', rand(10,50), 1) + playsound(H,'sound/items/eatfood.ogg', rand(10,50), 1) H.visible_message("[H] eats \the [src]!", "You eat \the [src]!") - Die(gore = 1) + death(gore = 1) qdel(src) H.vomit() diff --git a/code/modules/mob/living/simple_animal/shade.dm b/code/modules/mob/living/simple_animal/shade.dm index 025e0278f79..575c003ed08 100644 --- a/code/modules/mob/living/simple_animal/shade.dm +++ b/code/modules/mob/living/simple_animal/shade.dm @@ -15,7 +15,7 @@ response_harm = "punches" melee_damage_lower = 5 melee_damage_upper = 15 - attacktext = "drains the life from" + attacktext = "torments" minbodytemp = 0 maxbodytemp = 4000 min_oxy = 0 @@ -70,7 +70,8 @@ if(istype(O,/obj/item/weapon/nullrod)) damage *= 2 purge = 3 - health -= damage + adjustBruteLoss(damage) + O.on_attack(src, user) for(var/mob/M in viewers(src, null)) if ((M.client && !( M.blinded ))) M.show_message(" [src] has been attacked with [O] by [user].") @@ -86,6 +87,11 @@ health -= rand(5,45) //These guys are like ghosts, a collision with a shuttle wouldn't destroy one outright return +/mob/living/simple_animal/shade/examine(mob/user) + ..() + if(!client) + to_chat(user, "It appears to be dormant.") + ////////////////HUD////////////////////// /mob/living/simple_animal/shade/Life() @@ -123,7 +129,8 @@ else healths.icon_state = "shade_health7" -/mob/living/simple_animal/shade/happiest/Die() +/mob/living/simple_animal/shade/happiest/death(var/gibbed = FALSE) + ..(TRUE) transmogrify() if(!gcDestroyed) qdel(src) @@ -145,11 +152,11 @@ suiciding = TRUE visible_message("[src] shudders violently for a moment, then becomes motionless, its aura fading and eyes slowly darkening.") - Die() + death() -/mob/living/simple_animal/shade/sword/Die() +/mob/living/simple_animal/shade/sword/death(var/gibbed = FALSE) if(istype(loc, /obj/item/weapon/nullrod/sword/chaos)) var/obj/item/weapon/nullrod/sword/chaos/C = loc C.possessed = FALSE C.icon_state = "talking_sword" - ..() + ..(gibbed) diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 96b0d97e680..9a8fa1befb1 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -14,6 +14,10 @@ var/global/list/animal_count = list() //Stores types, and amount of animals of t var/icon_living = "" var/icon_dead = "" var/icon_gib = null //We only try to show a gibbing animation if this exists. + var/icon_attack = null //We only try to show an attacking animation if it exists + var/icon_attack_time //How long the ahove animation runs, in deciseconds + var/icon_dying = null //We only try to show a dying animation if it exists. + var/icon_dying_time //How long the above animation runs in deciseconds var/list/speak = list() //var/list/speak_emote = list()// Emotes while speaking IE: Ian [emote], [text] -- Ian barks, "WOOF!". Spoken text is generated from the speak variable. @@ -160,7 +164,7 @@ var/global/list/animal_count = list() //Stores types, and amount of animals of t if(health < 1 && stat != DEAD) - Die() + death() return 0 life_tick++ @@ -208,48 +212,7 @@ var/global/list/animal_count = list() //Stores types, and amount of animals of t wander_move(destination) turns_since_move = 0 - var/someone_in_earshot=0 - if(!client && speak_chance && (ckey == null)) // Remove this if earshot is used elsewhere. - // All we're doing here is seeing if there's any CLIENTS nearby. - for(var/mob/M in get_hearers_in_view(7, src)) - if(M.client) - someone_in_earshot=1 - break - - //Speaking - if(!client && speak_chance && (ckey == null) && someone_in_earshot) - if(speak && speak.len) - if(rand(0,200) < speak_chance) - if((emote_hear && emote_hear.len) || (emote_see && emote_see.len)) - var/length = speak.len - if(emote_hear && emote_hear.len) - length += emote_hear.len - if(emote_see && emote_see.len) - length += emote_see.len - var/randomValue = rand(1,length) - if(randomValue <= speak.len) - say(pick(speak)) - else - randomValue -= speak.len - if(emote_see && randomValue <= emote_see.len) - emote(pick(emote_see),1) - else - emote(pick(emote_hear),2) - else - say(pick(speak)) - else - if(!(emote_hear && emote_hear.len) && (emote_see && emote_see.len)) - emote(pick(emote_see),1) - if((emote_hear && emote_hear.len) && !(emote_see && emote_see.len)) - emote(pick(emote_hear),2) - if((emote_hear && emote_hear.len) && (emote_see && emote_see.len)) - var/length = emote_hear.len + emote_see.len - var/pick = rand(1,length) - if(pick <= emote_see.len) - emote(pick(emote_see),1) - else - emote(pick(emote_hear),2) - + handle_automated_speech() //Atmos if(flags & INVULNERABLE) @@ -268,41 +231,41 @@ var/global/list/animal_count = list() //Stores types, and amount of animals of t bodytemperature += ((Environment.temperature - bodytemperature) / 5) if(min_oxy) - if(Environment.oxygen / Environment.volume * CELL_VOLUME < min_oxy) + if(Environment.molar_density("oxygen") < min_oxy / CELL_VOLUME) atmos_suitable = 0 oxygen_alert = 1 else oxygen_alert = 0 if(max_oxy) - if(Environment.oxygen / Environment.volume * CELL_VOLUME > max_oxy) + if(Environment.molar_density("oxygen") > max_oxy / CELL_VOLUME) atmos_suitable = 0 if(min_tox) - if(Environment.toxins / Environment.volume * CELL_VOLUME < min_tox) + if(Environment.molar_density("toxins") < min_tox / CELL_VOLUME) atmos_suitable = 0 if(max_tox) - if(Environment.toxins / Environment.volume * CELL_VOLUME > max_tox) + if(Environment.molar_density("toxins") > max_tox / CELL_VOLUME) atmos_suitable = 0 toxins_alert = 1 else toxins_alert = 0 if(min_n2) - if(Environment.nitrogen / Environment.volume * CELL_VOLUME < min_n2) + if(Environment.molar_density("nitrogen") < min_n2 / CELL_VOLUME) atmos_suitable = 0 if(max_n2) - if(Environment.nitrogen / Environment.volume * CELL_VOLUME > max_n2) + if(Environment.molar_density("nitrogen") > max_n2 / CELL_VOLUME) atmos_suitable = 0 if(min_co2) - if(Environment.carbon_dioxide / Environment.volume * CELL_VOLUME < min_co2) + if(Environment.molar_density("carbon_dioxide") < min_co2 / CELL_VOLUME) atmos_suitable = 0 if(max_co2) - if(Environment.carbon_dioxide / Environment.volume * CELL_VOLUME > max_co2) + if(Environment.molar_density("carbon_dioxide") > max_co2 / CELL_VOLUME) atmos_suitable = 0 //Atmos effect @@ -352,10 +315,47 @@ var/global/list/animal_count = list() //Stores types, and amount of animals of t if(stat) return if(act == "scream") - desc = "makes a loud and pained whimper" //ugly hack to stop animals screaming when crushed :P + desc = "makes a loud and pained whimper!" //ugly hack to stop animals screaming when crushed :P + act = "me" + if(!desc && act != "me") + desc = "[act]." act = "me" ..(act, type, desc) +/mob/living/simple_animal/check_emote(message) + if(copytext(message, 1, 2) == "*") + to_chat(src, "This type of mob doesn't support this. Use the Me verb instead.") + return 1 + +/mob/living/simple_animal/proc/handle_automated_speech() + + if(!speak_chance || !(speak.len || emote_hear.len || emote_see.len)) + return + + var/someone_in_earshot=0 + if(!client && ckey == null) // Remove this if earshot is used elsewhere. + // All we're doing here is seeing if there's any CLIENTS nearby. + for(var/mob/M in get_hearers_in_view(7, src)) + if(M.client) + someone_in_earshot=1 + break + + if(someone_in_earshot) + if(rand(0,200) < speak_chance) + var/mode = pick( + speak.len; 1, + emote_hear.len; 2, + emote_see.len; 3 + ) + + switch(mode) + if(1) + say(pick(speak)) + if(2) + emote("me", MESSAGE_HEAR, "[pick(emote_hear)].") + if(3) + emote("me", MESSAGE_SEE, "[pick(emote_see)].") + /mob/living/simple_animal/attack_animal(mob/living/simple_animal/M) M.unarmed_attack_mob(src) @@ -394,7 +394,7 @@ var/global/list/animal_count = list() //Stores types, and amount of animals of t /mob/living/simple_animal/MouseDrop(mob/living/carbon/M) if(M != usr || !istype(M) || !Adjacent(M) || M.incapacitated()) - return + return ..() if(locked_to) //Atom locking return @@ -459,7 +459,7 @@ var/global/list/animal_count = list() //Stores types, and amount of animals of t return -/mob/living/simple_animal/attackby(var/obj/item/O as obj, var/mob/user as mob) //Marker -Agouri +/mob/living/simple_animal/attackby(var/obj/item/O, var/mob/user, var/no_delay = FALSE, var/originator = null) if(istype(O, /obj/item/stack/medical)) user.delayNextAttack(4) if(stat != DEAD) @@ -479,25 +479,11 @@ var/global/list/animal_count = list() //Stores types, and amount of animals of t return 1 else if (user.is_pacified(VIOLENCE_DEFAULT,src)) return - else - user.delayNextAttack(8) - if(O.force) - user.do_attack_animation(src, O) - var/damage = O.force - if (O.damtype == HALLOSS) - damage = 0 - if(supernatural && istype(O,/obj/item/weapon/nullrod)) - damage *= 2 - purge = 3 - adjustBruteLoss(damage) - for(var/mob/M in viewers(src, null)) - if ((M.client && !( M.blinded ))) - M.show_message("[src] has been attacked with the [O] by [user]. ") - else - to_chat(usr, "This weapon is ineffective, it does no damage.") - for(var/mob/M in viewers(src, null)) - if ((M.client && !( M.blinded ))) - M.show_message("[user] gently taps [src] with the [O]. ") + if(supernatural && istype(O,/obj/item/weapon/nullrod)) + purge = 3 + ..() + + /mob/living/simple_animal/base_movement_tally() return speed @@ -513,12 +499,20 @@ var/global/list/animal_count = list() //Stores types, and amount of animals of t if(statpanel("Status") && show_stat_health) stat(null, "Health: [round((health / maxHealth) * 100)]%") -/mob/living/simple_animal/proc/Die() +/mob/living/simple_animal/death(gibbed) + if(stat == DEAD) + return + + if(!gibbed) + visible_message("\the [src] stops moving...") + health = 0 // so /mob/living/simple_animal/Life() doesn't magically revive them living_mob_list -= src dead_mob_list += src - icon_state = icon_dead stat = DEAD + if(icon_dying && !gibbed) + do_flick(src, icon_dying, icon_dying_time) + icon_state = icon_dead setDensity(FALSE) animal_count[src.type]-- @@ -531,16 +525,8 @@ var/global/list/animal_count = list() //Stores types, and amount of animals of t verbs += /mob/living/proc/butcher - return + ..(gibbed) -/mob/living/simple_animal/death(gibbed) - if(stat == DEAD) - return - - if(!gibbed) - visible_message("\the [src] stops moving...") - - Die() /mob/living/simple_animal/ex_act(severity) if(flags & INVULNERABLE) @@ -565,10 +551,12 @@ var/global/list/animal_count = list() //Stores types, and amount of animals of t return 0 if(skinned()) damage = damage * 2 + if(purge) + damage = damage * 2 health = Clamp(health - damage, 0, maxHealth) if(health < 1 && stat != DEAD) - Die() + death() /mob/living/simple_animal/adjustFireLoss(damage) if(status_flags & GODMODE) @@ -579,10 +567,11 @@ var/global/list/animal_count = list() //Stores types, and amount of animals of t return 0 if(skinned()) damage = damage * 2 - + if(purge) + damage = damage * 2 health = Clamp(health - damage, 0, maxHealth) if(health < 1 && stat != DEAD) - Die() + death() /mob/living/simple_animal/proc/skinned() if(butchering_drops) @@ -676,17 +665,23 @@ var/global/list/animal_count = list() //Stores types, and amount of animals of t return 1 -/mob/living/simple_animal/proc/grow_up() - if(src.type == species_type) //Already grown up +/mob/living/simple_animal/proc/grow_up(type_override = null) + var/new_type = species_type + if(type_override) + new_type = type_override + + if(src.type == new_type) //Already grown up return - var/mob/living/simple_animal/new_animal = new species_type(src.loc) + var/mob/living/simple_animal/new_animal = new new_type(src.loc) if(locked_to) //Handle atom locking var/atom/movable/A = locked_to A.unlock_atom(src) A.lock_atom(new_animal, /datum/locking_category/simple_animal) + if(name != initial(name)) //Not chicken + new_animal.name = name new_animal.inherit_mind(src) new_animal.ckey = src.ckey new_animal.key = src.key @@ -694,6 +689,8 @@ var/global/list/animal_count = list() //Stores types, and amount of animals of t forceMove(get_turf(src)) qdel(src) + return new_animal + /mob/living/simple_animal/proc/inherit_mind(mob/living/simple_animal/from) src.faction = from.faction @@ -752,4 +749,19 @@ var/global/list/animal_count = list() //Stores types, and amount of animals of t return ..() +/mob/living/simple_animal/proc/name_mob(mob/user) + var/n_name = copytext(sanitize(input(user, "What would you like to name \the [src]?", "Renaming \the [src]", null) as text|null), 1, MAX_NAME_LEN) + if(n_name && !user.incapacitated()) + name = "[n_name]" + var/image/heart = image('icons/mob/animal.dmi',src,"heart-ani2") + heart.plane = ABOVE_HUMAN_PLANE + flick_overlay(heart, list(user.client), 20) + + /datum/locking_category/simple_animal + + +/mob/living/simple_animal/resetVariables() + ..("emote_hear", "emote_see", args) + emote_hear = list() + emote_see = list() diff --git a/code/modules/mob/living/simple_animal/vox.dm b/code/modules/mob/living/simple_animal/vox.dm index 500108a7f88..f0b36c2968b 100644 --- a/code/modules/mob/living/simple_animal/vox.dm +++ b/code/modules/mob/living/simple_animal/vox.dm @@ -1,5 +1,14 @@ -/mob/living/simple_animal/vox/armalis/ +/mob/living/simple_animal/vox + min_oxy = 0 + max_oxy = 1 + min_tox = 0 + max_tox = 1 + min_co2 = 0 + max_co2 = 5 + min_n2 = 5 //breathe N2 + max_n2 = 0 +/mob/living/simple_animal/vox/armalis name = "serpentine alien" real_name = "serpentine alien" desc = "A one-eyed, serpentine creature, half-machine, easily nine feet from tail to beak!" @@ -17,15 +26,14 @@ environment_smash_flags = SMASH_LIGHT_STRUCTURES | SMASH_CONTAINERS | SMASH_WALLS // WALLS attack_sound = 'sound/weapons/bladeslice.ogg' status_flags = 0 + max_oxy = 0 var/armour = null var/amp = null var/quills = 3 -/mob/living/simple_animal/vox/armalis/Die() - living_mob_list -= src - dead_mob_list += src - stat = DEAD +/mob/living/simple_animal/vox/armalis/death(var/gibbed = FALSE) + ..(TRUE) var/turf/gloc = get_turf(loc) visible_message("[src] shudders violently and explodes!","You feel your body rupture!") gib() @@ -155,4 +163,4 @@ desc = "A series of metallic lenses and chains." icon = 'icons/obj/clothing/hats.dmi' icon_state = "amp" - item_state = "amp" \ No newline at end of file + item_state = "amp" diff --git a/code/modules/mob/living/simple_animal/worm.dm b/code/modules/mob/living/simple_animal/worm.dm index e5985b08873..a8d6164f39b 100644 --- a/code/modules/mob/living/simple_animal/worm.dm +++ b/code/modules/mob/living/simple_animal/worm.dm @@ -167,7 +167,7 @@ newHead.Attach(newHeadPrevious) if(die) - newHead.Die() + newHead.death() qdel(src) diff --git a/code/modules/mob/login.dm b/code/modules/mob/login.dm index d96fc02dc37..263104e5a13 100644 --- a/code/modules/mob/login.dm +++ b/code/modules/mob/login.dm @@ -37,6 +37,9 @@ message_admins("Notice: [key_name_admin(src)] has the same [matches] as [key_name_admin(M)] (no longer logged in). ", 1) log_access("Notice: [key_name(src)] has the same [matches] as [key_name(M)] (no longer logged in).") +// Do not call ..() +// If you do so and the mob is in nullspace BYOND will attempt to move the mob a gorillion times +// See http://www.byond.com/docs/ref/info.html#/mob/proc/Login and http://www.byond.com/forum/?post=2151126 /mob/Login() player_list |= src update_Login_details() @@ -60,6 +63,8 @@ regular_hud_updates() + update_action_buttons(TRUE) + if(round_end_info == "") winset(client, "rpane.round_end", "is-visible=false") @@ -67,8 +72,6 @@ change_sight(adding = (SEE_SELF|SEE_BLACKNESS)) - ..() - reset_view() if((flags & HEAR) && !(flags & HEAR_ALWAYS)) //Mobs with HEAR_ALWAYS will already have a virtualhearer diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index d8c90f1419c..b3bb61c49cb 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -90,6 +90,14 @@ if(transmogged_to) qdel(transmogged_to) transmogged_to = null + if(control_object.len) + for(var/A in control_object) + qdel(A) + control_object = null + if(orient_object.len) + for(var/A in orient_object) + qdel(A) + orient_object = null ..() @@ -989,7 +997,7 @@ var/list/slot_equipment_priority = list( \ set name = "Point To" set category = "Object" - if(!src || usr.isUnconscious() || !isturf(src.loc) || !(A in view(src.loc))) + if(!src || (usr.isUnconscious() && !isobserver(src)) || !isturf(src.loc) || !(A in view(src.loc))) return 0 if(istype(A, /obj/effect/decal/point)) @@ -1019,7 +1027,7 @@ var/list/slot_equipment_priority = list( \ //this and stop_pulling really ought to be /mob/living procs /mob/proc/start_pulling(var/atom/movable/AM) - if ( !AM || !src || src==AM || !isturf(AM.loc) ) //if there's no person pulling OR the person is pulling themself OR the object being pulled is inside something: abort! + if ( !AM || !src || src==AM || !isturf(AM.loc) || !AM.can_be_pulled(src)) //if there's no person pulling OR the person is pulling themself OR the object being pulled is inside something: abort! return if(!has_hand_check()) @@ -1046,7 +1054,7 @@ var/list/slot_equipment_priority = list( \ src.pulling = P P.pulledby = src - P.on_pull_start(AM) + AM.on_pull_start(src) update_pull_icon() if(ismob(P)) var/mob/M = P @@ -1394,6 +1402,8 @@ var/list/slot_equipment_priority = list( \ var/t1 = text("window=[href_list["mach_close"]]") unset_machine() src << browse(null, t1) + else + return ..() //if (href_list["joinresponseteam"]) // if(usr.client) // var/client/C = usr.client @@ -2103,6 +2113,13 @@ mob/proc/on_foot() if (VIOLENCE_GUN)//gun, projectile weapon to_chat(src, "[pick("Hey that's dangerous...wouldn't want hurting people.","You don't feel like firing \the [weapon] at \the [target].","Peace, my [gender == FEMALE ? "girl" : "man"]...")]") return 1 + + for (var/obj/item/weapon/implant/peace/target_implant in src.contents) + if (!target_implant.malfunction && target_implant.imp_alive && target_implant.imp_in == src) + if (message != VIOLENCE_SILENT) + to_chat(src, "\The [target_implant] inside you prevents this!") + return 1 + return 0 #undef MOB_SPACEDRUGS_HALLUCINATING diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 63c16f52e41..b78b1b4f1fe 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -27,6 +27,8 @@ var/obj/abstract/screen/bodytemp = null var/obj/abstract/screen/healths = null var/obj/abstract/screen/throw_icon = null + var/obj/abstract/screen/camera_icon = null + var/obj/abstract/screen/album_icon = null var/obj/abstract/screen/nutrition_icon = null var/obj/abstract/screen/pressure = null var/obj/abstract/screen/damageoverlay = null @@ -237,9 +239,9 @@ var/force_compose = 0 //If this is nonzero, the mob will always compose it's own hear message instead of using the one given in the arguments. - var/obj/control_object = null //Used by admins to possess objects. All mobs should have this var + var/list/control_object = list() //Used by admins to possess objects. All mobs should have this var - var/obj/orient_object = null //Similar to control object. But only lets the mob manipulate which direction the object is facing. + var/list/orient_object = list() //Similar to control object. But only lets the mob manipulate which direction the object is facing. //Whether or not mobs can understand other mobtypes. These stay in /mob so that ghosts can hear everything. var/universal_speak = 0 // Set to 1 to enable the mob to speak to everyone -- TLE @@ -290,7 +292,10 @@ var/mob/transmogged_to //holds a reference to the mob which holds a reference to this mob in its transmogged_from var /mob/resetVariables() - ..("callOnFace", "pinned", "embedded", "abilities", "grabbed_by", "requests", "mapobjs", "mutations", "spell_list", "viruses", "resistances", "radar_blips", "active_genes", "attack_log", "speak_emote", args) + ..("callOnFace", "pinned", "embedded", "abilities", "grabbed_by", "requests", "mapobjs", "mutations", "spell_list", "viruses", "resistances", "radar_blips", "active_genes", \ + "attack_log", "speak_emote", "alphas", "heard_by", "control_object", "orient_object", "actions", "held_items", "click_delayer", "attack_delayer", "special_delayer", \ + "clong_delayer", args) + callOnFace = list() pinned = list() embedded = list() @@ -305,3 +310,15 @@ radar_blips = list() active_genes = list() attack_log = list() + speak_emote = list() + alphas = list() + heard_by = list() + control_object = list() + orient_object = list() + actions = list() + held_items = list() + + click_delayer = new (1,ARBITRARILY_LARGE_NUMBER) + attack_delayer = new (1,ARBITRARILY_LARGE_NUMBER) + special_delayer = new (1,ARBITRARILY_LARGE_NUMBER) + clong_delayer = new (10,ARBITRARILY_LARGE_NUMBER) diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 3c7e9a481f3..64b2ea3fe0f 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -79,12 +79,15 @@ mob/proc/remove_internal_organ() else return default_colour_matrix -/mob/proc/update_colour(var/time = 50,var/forceupdate = 0) +/mob/proc/update_colour(var/time = 50,var/forceupdate = 0, var/list/colour_to_apply) if(!client || (client.updating_colour && !forceupdate)) return - var/list/colour_to_apply = get_screen_colour() - var/list/difference = difflist(client.color,colour_to_apply) - if(difference || !(client.color) || !istype(difference) || !difference.len) + if(!colour_to_apply) + colour_to_apply = get_screen_colour() + var/list/difference = list() + if(client.color) + difference = difflist(client.color,colour_to_apply) + if(!difference.len || difference || !istype(difference)) client.updating_colour = 1 var/cached_ckey = client.ckey if(forceupdate) @@ -101,7 +104,7 @@ mob/proc/remove_internal_organ() client.updating_colour = 0 difference = difflist(client.color,get_screen_colour()) if((difference || !(client.color) || !istype(difference) || !difference.len) && !forceupdate) // panic panic panic - src.update_colour(forceupdate = 1) + src.update_colour(0,1,colour_to_apply) else bad_changing_colour_ckeys["[cached_ckey]"] = 1 /* diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index 8130e70bc9f..1583a33afd4 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -230,20 +230,20 @@ return /client/proc/Move_object(direct) - if(mob && mob.control_object) - if(mob.control_object.density) - step(mob.control_object,direct) - if(!mob.control_object) - return - mob.control_object.dir = direct - else - mob.control_object.forceMove(get_step(mob.control_object,direct)) - return + for(var/datum/control/C in mob.control_object) + if(!C.controller) + mob.control_object.Remove(C) + qdel(C) + continue + C.Move_object(direct) /client/proc/Dir_object(direct) - if(mob && mob.orient_object) - var/obj/O = mob.orient_object - O.dir = direct + for(var/datum/control/C in mob.orient_object) + if(!C.controller) + mob.orient_object.Remove(C) + qdel(C) + continue + C.Orient_object(direct) /client/Move(NewLoc, Dir = 0, step_x = 0, step_y = 0, glide_size_override = 0) if(move_delayer.next_allowed > world.time) @@ -254,12 +254,10 @@ to_chat(src, "You cannot move this mob.") return - if(mob.control_object) - Move_object(Dir) + Move_object(Dir) + + Dir_object(Dir) - if(mob.orient_object) - Dir_object(Dir) - return if(mob.incorporeal_move) Process_Incorpmove(Dir) @@ -348,7 +346,7 @@ mob.set_glide_size(DELAY2GLIDESIZE(move_delay)) //Since we're moving OUT OF OUR OWN VOLITION AND BY OURSELVES we can update our glide_size here! // Something with pulling things - var/obj/item/weapon/grab/Findgrab = locate() in src + var/obj/item/weapon/grab/Findgrab = locate() in mob if(Findgrab) var/list/L = mob.ret_grab() if(istype(L, /list)) @@ -358,7 +356,7 @@ if(M) if ((mob.Adjacent(M) || M.loc == mob.loc)) var/turf/T = mob.loc - step(mob, dir) + step(mob, Dir) if (isturf(M.loc)) var/diag = get_dir(mob, M) if (!((diag - 1) & diag)) @@ -454,7 +452,7 @@ var/movedelay = ETHEREAL_MOVEDELAY mob.set_glide_size(DELAY2GLIDESIZE(movedelay)) var/turf/newLoc = get_step(mob,direct) - if(!(newLoc.turf_flags & NOJAUNT)) + if(!(newLoc.turf_flags & NOJAUNT) && !newLoc.holy) mob.forceEnter(newLoc) mob.dir = direct else diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index a734effb412..cce03983010 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -309,7 +309,6 @@ if(prob(10)) // 10% of those have a good mut. H.dna.GiveRandomSE(notflags = GENE_UNNATURAL,genetype = GENETYPE_GOOD) - /mob/new_player/proc/AttemptLateSpawn(rank) if (src != usr) return 0 @@ -328,12 +327,18 @@ var/mob/living/carbon/human/character = create_character() //creates the human and transfers vars and mind if(character.client.prefs.randomslot) character.client.prefs.random_character_sqlite(character, character.ckey) - // TODO: Job-specific latejoin overrides. - character.forceMove(pick((assistant_latejoin.len > 0 && rank == "Assistant") ? assistant_latejoin : latejoin)) job_master.EquipRank(character, rank, 1) //equips the human EquipCustomItems(character) + var/datum/job/J = job_master.GetJob(rank) + if(J.spawns_from_edge) + character.Meteortype_Latejoin(rank) + else + // TODO: Job-specific latejoin overrides. + character.forceMove(pick((assistant_latejoin.len > 0 && rank == "Assistant") ? assistant_latejoin : latejoin)) + + character.store_position() // WHY THE FUCK IS THIS HERE @@ -368,16 +373,30 @@ if(istype(P.cartridge,/obj/item/weapon/cartridge/trader)) var/mob/living/L = get_holder_of_type(P,/mob/living) if(L) - L.show_message("[bicon(P)] Message from U8E1Ћ (Tu1B), \"Caw. Cousin [character] detected in sector.\".", 2) + L.show_message("[bicon(P)] Message from U���8�E1��Ћ (T�u1B��), \"Caw. Cousin [character] detected in sector.\".", 2) for(var/mob/dead/observer/M in player_list) if(M.stat == DEAD && M.client) handle_render(M,"PDA Message - Trader [character] has arrived in the sector from space.",character) //This should generate a Follow link - else - AnnounceArrival(character, rank) - FuckUpGenes(character) + if(character.mind.assigned_role != "Cyborg") + data_core.manifest_inject(character) + ticker.minds += character.mind//Cyborgs and AIs handle this in the transform proc. //TODO!!!!! ~Carn + if(character.mind.assigned_role == "Trader") + //If we're a trader, instead send a message to PDAs with the trader cartridge + for (var/obj/item/device/pda/P in PDAs) + if(istype(P.cartridge,/obj/item/weapon/cartridge/trader)) + var/mob/living/L = get_holder_of_type(P,/mob/living) + if(L) + L.show_message("[bicon(P)] Message from U���8�E1��Ћ (T�u1B��), \"Caw. Cousin [character] detected in sector.\".", 2) + for(var/mob/dead/observer/M in player_list) + if(M.stat == DEAD && M.client) + handle_render(M,"PDA Message - Trader [character] has arrived in the sector from space.",character) //This should generate a Follow link + else - character.Robotize() + AnnounceArrival(character, rank) + FuckUpGenes(character) + else + character.Robotize() qdel(src) /mob/living/carbon/human/proc/Meteortype_Latejoin(rank) @@ -489,6 +508,9 @@ Round Duration: [round(hours)]h [round(mins)]m
      "} if(client.prefs.disabilities & DISABILITY_FLAG_VEGAN) new_character.dna.SetSEState(VEGANBLOCK, 1, 1) + if(client.prefs.disabilities & DISABILITY_FLAG_ASTHMA) + new_character.dna.SetSEState(ASTHMABLOCK, 1, 1) + chosen_species = all_species[client.prefs.species] if( (client.prefs.disabilities & DISABILITY_FLAG_FAT) && (chosen_species.anatomy_flags & CAN_BE_FAT) ) new_character.mutations += M_FAT diff --git a/code/modules/mob/new_player/preferences_setup.dm b/code/modules/mob/new_player/preferences_setup.dm index e079d6794d5..3793d09831a 100644 --- a/code/modules/mob/new_player/preferences_setup.dm +++ b/code/modules/mob/new_player/preferences_setup.dm @@ -31,7 +31,7 @@ var/green var/blue - var/col = pick ("blonde", "black", "chestnut", "copper", "brown", "wheat", "old", "punk") + var/col = pick ("blonde", "black", "chestnut", "copper", "brown", "wheat", "old", 15;"punk") switch(col) if("blonde") red = 255 @@ -62,9 +62,9 @@ green = red blue = red if("punk") - red = rand (0, 255) - green = rand (0, 255) - blue = rand (0, 255) + red = rand(0, 255) + green = rand(0, 255) + blue = rand(0, 255) red = max(min(red + rand (-25, 25), 255), 0) green = max(min(green + rand (-25, 25), 255), 0) @@ -271,8 +271,9 @@ if(HOP) clothes_s = new /icon(uniform_dmi, "hop_s") clothes_s.Blend(new /icon(feet_dmi, "brown"), ICON_UNDERLAY) - clothes_s.Blend(new /icon(suit_dmi, "armor"), ICON_OVERLAY) - clothes_s.Blend(new /icon('icons/mob/head.dmi', "helmet"), ICON_OVERLAY) + clothes_s.Blend(new /icon(suit_dmi, "HoP_Coat"), ICON_OVERLAY) + clothes_s.Blend(new /icon('icons/mob/head.dmi', "hopcap"), ICON_OVERLAY) + clothes_s.Blend(new /icon('icons/mob/eyes.dmi', "sun"), ICON_OVERLAY) clothes_s=blend_backpack(clothes_s,backbag,"satchel-norm",null,"courierbag") if(BARTENDER) clothes_s = new /icon(uniform_dmi, "ba_suit_s") diff --git a/code/modules/mob/new_player/sprite_accessories.dm b/code/modules/mob/new_player/sprite_accessories.dm index 9d9bfac61fe..bce5db8468c 100644 --- a/code/modules/mob/new_player/sprite_accessories.dm +++ b/code/modules/mob/new_player/sprite_accessories.dm @@ -56,7 +56,7 @@ name = "Bald" icon_state = "bald" gender = MALE - species_allowed = list("Human","Unathi","Grey","Plasmaman","Skellington","Diona","Muton","Golem","Skeletal Vox","Horror","Ghoul","Slime") + species_allowed = list("Human","Unathi","Grey","Plasmaman","Skellington","Diona","Muton","Golem","Skeletal Vox","Horror","Ghoul","Slime","Mushroom") short name = "Short Hair" // try to capatilize the names please~ @@ -486,7 +486,7 @@ halfshave name = "Half-shave" icon_state = "hair_halfshave" - + nightcrawler name = "Nightcrawler" icon_state = "hair_nightcrawler" @@ -516,7 +516,7 @@ name = "Shaved" icon_state = "bald" gender = NEUTER - species_allowed = list("Human","Unathi","Tajaran","Skrell","Vox","Grey","Plasmaman","Skellington","Diona","Muton","Golem","Skeletal Vox","Horror","Ghoul","Slime") + species_allowed = list("Human","Unathi","Tajaran","Skrell","Vox","Grey","Plasmaman","Skellington","Diona","Muton","Golem","Skeletal Vox","Horror","Ghoul","Slime","Mushroom") watson name = "Watson Mustache" diff --git a/code/modules/mob/say.dm b/code/modules/mob/say.dm index 73585ec330b..0d1f749ac08 100644 --- a/code/modules/mob/say.dm +++ b/code/modules/mob/say.dm @@ -32,7 +32,7 @@ if(usr.stat == DEAD) usr.emote_dead(message) - else + else if(message) usr.emote("me",usr.emote_type,message) /mob/proc/say_dead(var/message) diff --git a/code/modules/mob/spells.dm b/code/modules/mob/spells.dm index f613a992ff1..5679e4da674 100644 --- a/code/modules/mob/spells.dm +++ b/code/modules/mob/spells.dm @@ -53,12 +53,15 @@ if(!spell_masters || !spell_masters.len) return + var/obj/abstract/screen/movable/spell_master/master = spell_to_remove.connected_button.spellmaster + if(!(master in spell_masters)) + return + master.remove_spell(spell_to_remove) + spell_to_remove.on_removed(src) if(mind && mind.wizard_spells) mind.wizard_spells.Remove(spell_to_remove) spell_list.Remove(spell_to_remove) - for(var/obj/abstract/screen/movable/spell_master/spell_master in spell_masters) - spell_master.remove_spell(spell_to_remove) return 1 /mob/proc/silence_spells(var/amount = 0) diff --git a/code/modules/mob/thermoregulation.dm b/code/modules/mob/thermoregulation.dm index f58bd780522..ba4414f9114 100644 --- a/code/modules/mob/thermoregulation.dm +++ b/code/modules/mob/thermoregulation.dm @@ -68,8 +68,8 @@ if(loc_temp < bodytemperature) // We're going to try and just use exposed area(temperature difference)/cold divisor, and assume we're only conducting. var/thermal_loss = (1-get_cold_protection()) // How much of your skin is exposed. - if(!isVentCrawling() && ((environment.total_moles / environment.volume * CELL_VOLUME) > MOLES_CELLSTANDARD || !IS_SPACE_COLD)) - var/pressure_diff = (environment.total_moles / environment.volume * CELL_VOLUME) / MOLES_CELLSTANDARD // How many moles are in the environment over 103.934, the normal value of a station. + if(!isVentCrawling() && (environment.molar_density() > (MOLES_CELLSTANDARD / CELL_VOLUME) || !IS_SPACE_COLD)) + var/pressure_diff = environment.molar_density() / (MOLES_CELLSTANDARD / CELL_VOLUME) // How many moles are in the environment over 103.934, the normal value of a station. var/pressure_factor = (-COLD_PRESSUREFACTOR_MAX)/(pressure_diff) + COLD_PRESSUREFACTOR_MAX // non linear. if(pressure_diff < PRESSUREFACTOR_NO_LINEAR) pressure_factor = pressure_diff diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index 636cd666f4b..8590eb88397 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -137,15 +137,6 @@ O.forceMove(loc_landmark.loc) for (var/obj/item/device/radio/intercom/comm in O.loc) comm.ai += O - to_chat(O, "You are playing the station's AI. The AI cannot move, but can interact with many objects while viewing them (through cameras).") - to_chat(O, "To look at other parts of the station, click on yourself to get a camera menu.") - to_chat(O, "While observing through a camera, you can use most (networked) devices which you can see, such as computers, APCs, intercoms, doors, etc.") - to_chat(O, "To use something, simply click on it.") - to_chat(O, {"Use say ":b to speak to your cyborgs through binary."}) - O.show_laws() - to_chat(O, "These laws may be changed by other players, or by you being the traitor.") - - //O.verbs += /mob/living/silicon/ai/proc/ai_call_shuttle O.verbs += /mob/living/silicon/ai/proc/show_laws_verb O.verbs += /mob/living/silicon/ai/proc/ai_statuschange O.job = "AI" @@ -177,19 +168,16 @@ message_admins("[key_name(O)] was forcefully transformed into a [job] and had its self-destruct mechanism engaged due \his job ban.") log_game("[key_name(O)] was forcefully transformed into a [job] and had its self-destruct mechanism engaged due \his job ban.") if(!skipnaming) - O.Namepick() + spawn() + O.Namepick() qdel(src) return O -/mob/proc/MoMMIfy(round_start = FALSE) +/mob/proc/MoMMIfy() if(!Premorph()) return - var/mob/living/silicon/robot/mommi/O = new /mob/living/silicon/robot/mommi(get_turf(src)) + var/mob/living/silicon/robot/mommi/O = new /mob/living/silicon/robot/mommi/nt(get_turf(src)) . = O - if(!O.cell) // MoMMIs' New() is suposed to give them a battery but JUST TO BE SURE. - O.cell = new(O) - O.cell.maxcharge = (round_start ? 10000 : 15000) - O.cell.charge = (round_start ? 10000 : 15000) if(mind) //TODO mind.transfer_to(O) if(O.mind.assigned_role == "Cyborg") @@ -207,7 +195,8 @@ O.self_destruct() message_admins("[key_name(O)] was forcefully transformed into a [job] and had its self-destruct mechanism engaged due \his job ban.") log_game("[key_name(O)] was forcefully transformed into a [job] and had its self-destruct mechanism engaged due \his job ban.") - O.Namepick() + spawn() + O.Namepick() qdel(src) return O @@ -268,7 +257,7 @@ /mob/proc/Martianize() if(!Premorph()) return - var/mob/living/carbon/martian/new_aunt = new /mob/living/carbon/martian(get_turf(src)) + var/mob/living/carbon/complex/martian/new_aunt = new /mob/living/carbon/complex/martian(get_turf(src)) Postmorph(new_aunt) return new_aunt @@ -289,7 +278,6 @@ if(isliving(src)) var/mob/living/L = src new_human.languages |= L.languages - new_human.default_language = L.default_language new_human.generate_name() Postmorph(new_human) return new_human @@ -319,4 +307,15 @@ to_chat(new_mob, "You feel more... animalistic") return new_mob +/mob/living/carbon/human/proc/GALize() + s_tone = -100 //Nichi saro ni itte hada o yaku + update_body() + if(gender == MALE && h_style != "Toriyama 2") + h_style = "Toriyama 2" //Yeah, gyaru otoko sengen + r_facial = r_hair = 255 + g_facial = g_hair = 255 + b_facial = b_hair = 0 + update_hair() + playsound(src, 'sound/misc/gal-o-sengen.ogg', 50, 1)// GO GO GO GO GO GO GAL-O-SENGEN + #undef MONKEY_ANIM_TIME diff --git a/code/modules/optics/mirrors/frame.dm b/code/modules/optics/mirrors/frame.dm index 6c6478f107d..144cdd332bb 100644 --- a/code/modules/optics/mirrors/frame.dm +++ b/code/modules/optics/mirrors/frame.dm @@ -16,7 +16,7 @@ if(do_after(user, src,20)) anchored=!anchored user.visible_message("You unfasten \the [src]'s bolts.", "[user] unfastens the [src]'s bolts.","You hear a ratchet.") - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + playsound(src, 'sound/items/Ratchet.ogg', 50, 1) if(istype(W, /obj/item/weapon/weldingtool)) var/obj/item/weapon/weldingtool/WT = W @@ -25,7 +25,7 @@ if(do_after(user, src, 20)) if(!src || !WT.isOn()) return - playsound(get_turf(src), 'sound/items/Welder2.ogg', 50, 1) + playsound(src, 'sound/items/Welder2.ogg', 50, 1) user.visible_message("[user] cuts the [src] apart.", "You cut the [src] apart.", "You hear welding.") var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal, get_turf(src)) M.amount = 5 diff --git a/code/modules/optics/mirrors/mirror.dm b/code/modules/optics/mirrors/mirror.dm index 6ed23a93a13..6f3d007a676 100644 --- a/code/modules/optics/mirrors/mirror.dm +++ b/code/modules/optics/mirrors/mirror.dm @@ -31,7 +31,7 @@ var/global/list/obj/machinery/mirror/mirror_list = list() /obj/machinery/mirror/proc/get_deflections(var/in_dir) if(dir in list(EAST, WEST)) - //testing("[src]: Detected orientation: \\, in_dir=[in_dir], dir=[dir]") + //testing("[src]: Detected orientation: \\, in_dir=[dir2text(in_dir)], dir=[dir2text(dir)]") switch(in_dir) // \\ orientation if(NORTH) return list(EAST) @@ -42,7 +42,7 @@ var/global/list/obj/machinery/mirror/mirror_list = list() if(WEST) return list(SOUTH) else - //testing("[src]: Detected orientation: /, in_dir=[in_dir], dir=[dir]") + //testing("[src]: Detected orientation: /, in_dir=[dir2text(in_dir)], dir=[dir2text(dir)]") switch(in_dir) // / orientation if(NORTH) return list(WEST) @@ -252,3 +252,26 @@ var/global/list/obj/machinery/mirror/mirror_list = list() // but the spam would just piss everyone off. //testing("BUG: Beam \ref[B] is still around after getting deleted!") qdel(B) + +/obj/machinery/mirror/bullet_act(var/obj/item/projectile/P, var/def_zone) + if(!istype(P, /obj/item/projectile/beam)) + return + if(P.damage < initial(P.damage)/4) //Can only be reflected 5 times, let's say + return + var/list/deflections = get_deflections(get_dir(src,P)) + var/turf/T = get_turf(src) + for(var/i=1 to nsplits) + var/splitdir = deflections[i] + var/turf/target = get_edge_target_turf(src, splitdir) + var/obj/item/projectile/beam/B = new P.type + B.original = target + B.starting = T + B.current = T + B.forceMove(T) + B.shot_from = P.shot_from + B.yo = target.y - T.y + B.xo = target.y - T.x + B.OnFired() + B.damage = P.damage/2 + spawn() + B.process() \ No newline at end of file diff --git a/code/modules/organs/blood.dm b/code/modules/organs/blood.dm index 2e73f4e2c68..c9e4558f308 100644 --- a/code/modules/organs/blood.dm +++ b/code/modules/organs/blood.dm @@ -11,15 +11,26 @@ var/const/BLOOD_VOLUME_OKAY = 336 var/const/BLOOD_VOLUME_BAD = 224 var/const/BLOOD_VOLUME_SURVIVE = 122 -/mob/living/carbon/human/var/datum/reagents/vessel //Container for blood and BLOOD ONLY. Do not transfer other chems here. +/mob/living/carbon/human/var/datum/reagents/vessel/vessel //Container for blood and BLOOD ONLY. Do not transfer other chems here. /mob/living/carbon/human/var/var/pale = 0 //Should affect how mob sprite is drawn, but currently doesn't. +/datum/reagents/vessel/update_total() //Version of this that doesn't call del_reagent + total_volume = 0 + amount_cache.len = 0 + for(var/datum/reagent/R in reagent_list) + if(R.volume < 0.1) + R.volume = 0 + else + total_volume += R.volume + amount_cache += list(R.id = R.volume) + return 0 + //Initializes blood vessels /mob/living/carbon/human/proc/make_blood() if(vessel) return - vessel = new/datum/reagents(600) + vessel = new/datum/reagents/vessel(600) vessel.my_atom = src if(species && species.anatomy_flags & NO_BLOOD) //We want the var for safety but we can do without the actual blood. diff --git a/code/modules/organs/internal/lungs/lung.dm b/code/modules/organs/internal/lungs/lung.dm index 9d5c49180f6..5e8f989356b 100644 --- a/code/modules/organs/internal/lungs/lung.dm +++ b/code/modules/organs/internal/lungs/lung.dm @@ -62,6 +62,8 @@ H.fire_alert = max(H.fire_alert, 1) else switch(breath.temperature) + if(H.species.cold_level_1 to H.species.heat_level_1) + return if(-INFINITY to H.species.cold_level_3) H.apply_damage(COLD_GAS_DAMAGE_LEVEL_3, BURN, LIMB_HEAD, used_weapon = "Excessive Cold") H.fire_alert = max(H.fire_alert, 1) @@ -88,6 +90,9 @@ /datum/organ/internal/lungs/process() ..() + if((owner.species && owner.species.flags & NO_BREATHE) || M_NO_BREATH in owner.mutations) + return + if (germ_level > INFECTION_LEVEL_ONE) if(prob(5)) owner.audible_cough() //respitory tract infection @@ -99,8 +104,8 @@ if (owner.losebreath <= 30) owner.losebreath += 5 else if(prob(chance)) - spawn owner.emote("me", 1, "coughs up blood!") - owner.drip(10) + if(owner.drip(10)) + spawn owner.emote("me", 1, "coughs up blood!") /datum/organ/internal/lungs/vox diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm index 77ac1fe3081..111820d11db 100644 --- a/code/modules/organs/organ_external.dm +++ b/code/modules/organs/organ_external.dm @@ -1289,6 +1289,7 @@ Note that amputating the affected organ does in fact remove the infection from t icon_name = "r_arm" max_damage = 75 min_broken_damage = 30 + w_class = W_CLASS_SMALL body_part = ARM_RIGHT grasp_id = GRASP_RIGHT_HAND @@ -1863,7 +1864,7 @@ obj/item/organ/external/head/attackby(obj/item/weapon/W as obj, mob/user as mob) return else if(istype(W,/obj/item/device/healthanalyzer)) to_chat(user, "You use \the [W] to induce a small electric shock into \the [src].") - playsound(get_turf(src),'sound/weapons/electriczap.ogg',50,1) + playsound(src,'sound/weapons/electriczap.ogg',50,1) animate(src, pixel_x = pixel_x + rand(-2,2), pixel_y = pixel_y + rand(-2,2) , time = 0.5 SECONDS, easing = BOUNCE_EASING) //Give it a little shake animate(src, pixel_x = initial(pixel_x), pixel_y = initial(pixel_y), time = 0.5 SECONDS, easing = LINEAR_EASING) //Then calm it down if(!organ_data) diff --git a/code/modules/organs/organ_internal.dm b/code/modules/organs/organ_internal.dm index fafa528db6c..a1fb1843df2 100644 --- a/code/modules/organs/organ_internal.dm +++ b/code/modules/organs/organ_internal.dm @@ -219,6 +219,9 @@ /datum/organ/internal/brain/slime_core removed_type = /obj/item/organ/internal/brain/slime_core +/datum/organ/internal/brain/mushroom_brain + removed_type = /obj/item/organ/internal/brain/mushroom + /datum/organ/internal/appendix name = "appendix" parent_organ = LIMB_GROIN diff --git a/code/modules/organs/organ_objects.dm b/code/modules/organs/organ_objects.dm index 6997e54250a..230002c70ef 100644 --- a/code/modules/organs/organ_objects.dm +++ b/code/modules/organs/organ_objects.dm @@ -60,10 +60,17 @@ if(istype(loc,/obj/item/device/mmi) || istype(loc,/obj/item/bodybag/cryobag) || istype(loc,/obj/structure/closet/crate/freezer)) return + + if(istype(loc,/obj/item/weapon/reagent_containers/glass/jar)) + var/obj/item/weapon/reagent_containers/glass/jar/J = loc + if(J.safe_holder()) + return + //We're stabilized somehow. if(stabilized) return + if(fresh && prob(40)) fresh-- var/datum/reagent/blood = reagents.reagent_list[BLOOD] diff --git a/code/modules/paperwork/envelope.dm b/code/modules/paperwork/envelope.dm index 92f7e0aa1c0..4e7e8b5b1e1 100644 --- a/code/modules/paperwork/envelope.dm +++ b/code/modules/paperwork/envelope.dm @@ -40,7 +40,7 @@ if(P.sharpness && P.sharpness_flags & SHARP_BLADE) open() user.visible_message("\The [user] slices the top of \the [src] open with \the [P].","You slice the top of \the [src] open with \the [P].") - playsound(get_turf(src), 'sound/effects/paper_tear.ogg', 10, 1) + playsound(src, 'sound/effects/paper_tear.ogg', 10, 1) if(istype(P, /obj/item/device/destTagger)) var/obj/item/device/destTagger/O = P @@ -51,7 +51,7 @@ var/tag = uppertext(O.destinations[O.currTag]) to_chat(user, "*[tag]*") sortTag = tag - playsound(get_turf(src), 'sound/machines/twobeep.ogg', 100, 1) + playsound(src, 'sound/machines/twobeep.ogg', 100, 1) overlays = 0 overlays += image(icon = icon, icon_state = "deliverytag") desc = "It has a label reading [tag]." @@ -94,7 +94,7 @@ else open() user.visible_message("\The [user] tears open the top of \the [src].","You tear open the top of \the [src].") - playsound(get_turf(src), 'sound/effects/paper_tear.ogg', 50, 1) + playsound(src, 'sound/effects/paper_tear.ogg', 50, 1) else AltClick(user) diff --git a/code/modules/paperwork/handlabeler.dm b/code/modules/paperwork/handlabeler.dm index fe70768fcc5..33f37817f77 100644 --- a/code/modules/paperwork/handlabeler.dm +++ b/code/modules/paperwork/handlabeler.dm @@ -4,6 +4,8 @@ icon_state = "labeler0" item_state = "labeler0" origin_tech = Tc_MATERIALS + "=1" + starting_materials = list(MAT_IRON = 200, MAT_GLASS = 175) + w_type = RECYK_MISC var/label = null var/chars_left = 250 //Like in an actual label maker, uses an amount per character rather than per label. var/mode = 0 //off or on. diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index 2c9f9519447..7dbf963c5ec 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -96,7 +96,7 @@ /obj/item/weapon/paper/attack_self(mob/living/user as mob) user.examination(src) - if(rigged && (Holiday == "April Fool's Day")) + if(rigged && (Holiday == APRIL_FOOLS_DAY)) if(spam_flag == 0) spam_flag = 1 playsound(loc, 'sound/items/bikehorn.ogg', 50, 1) @@ -312,9 +312,6 @@ /obj/item/weapon/paper/attackby(obj/item/weapon/P as obj, mob/user as mob) ..() - var/clown = 0 - if(user.mind && (user.mind.assigned_role == "Clown")) - clown = 1 if(istype(P, /obj/item/weapon/pen) || istype(P, /obj/item/toy/crayon)) if ( istype(P, /obj/item/weapon/pen/robopen) && P:mode == 2 ) @@ -326,9 +323,17 @@ else if(istype(P, /obj/item/weapon/stamp)) - if(istype(P, /obj/item/weapon/stamp/clown) && !clown) - to_chat(user, "You are totally unable to use the stamp. HONK!") - return + if(istype(P, /obj/item/weapon/stamp/clown)) + var/clown = FALSE + if(user.mind && (user.mind.assigned_role == "Clown")) + clown = TRUE + if(isrobot(user)) + var/mob/living/silicon/robot/R = user + if(R.module && R.module.quirk_flags & MODULE_IS_A_CLOWN) + clown = TRUE + if(!clown) + to_chat(user, "You are totally unable to use the stamp. HONK!") + return stamps += (stamps=="" ? "
      " : "
      ") + "This [src.name] has been stamped with the [P.name]." diff --git a/code/modules/paperwork/paperbin.dm b/code/modules/paperwork/paperbin.dm index 928427e84ce..bb941737eb0 100644 --- a/code/modules/paperwork/paperbin.dm +++ b/code/modules/paperwork/paperbin.dm @@ -57,7 +57,7 @@ papers.Remove(P) else P = new /obj/item/weapon/paper - if(Holiday == "April Fool's Day") + if(Holiday == APRIL_FOOLS_DAY) if(prob(30)) P.info = "HONK HONK HONK HONK HONK HONK HONK
      HOOOOOOOOOOOOOOOOOOOOOONK
      APRIL FOOLS
      " P.rigged = 1 diff --git a/code/modules/paperwork/pen.dm b/code/modules/paperwork/pen.dm index a582b6f53a3..bd8d123baac 100644 --- a/code/modules/paperwork/pen.dm +++ b/code/modules/paperwork/pen.dm @@ -244,7 +244,7 @@ var/paperwork_library return style.Format(text,src,user,P) /obj/item/weapon/pen/suicide_act(mob/user) - to_chat(viewers(user), "[user]is jamming the [src.name]into \his ear! It looks like \he's trying to commit suicide.") + to_chat(viewers(user), "[user] is jamming the [src.name] into \his ear! It looks like \he's trying to commit suicide.") return(OXYLOSS) /obj/item/weapon/pen/blue diff --git a/code/modules/paperwork/photocopier.dm b/code/modules/paperwork/photocopier.dm index 49b7dfbe282..81f8c4f9e6e 100644 --- a/code/modules/paperwork/photocopier.dm +++ b/code/modules/paperwork/photocopier.dm @@ -340,7 +340,7 @@ if(opened) if(iscrowbar(O)) to_chat(user, "You begin to remove the circuits from the [src].") - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) + playsound(src, 'sound/items/Crowbar.ogg', 50, 1) if(do_after(user, src, 50)) var/obj/machinery/constructable_frame/machine_frame/M = new /obj/machinery/constructable_frame/machine_frame(src.loc) M.state = 1 diff --git a/code/modules/paperwork/photography.dm b/code/modules/paperwork/photography.dm index f3cedb1faba..0fd683680eb 100644 --- a/code/modules/paperwork/photography.dm +++ b/code/modules/paperwork/photography.dm @@ -1,6 +1,7 @@ /* Photography! * Contains: * Camera + * Silicon Camera * Camera Film * Photos * Photo Albums @@ -30,17 +31,23 @@ w_class = W_CLASS_TINY var/icon/img //Big photo image var/scribble //Scribble on the back. - var/blueprints = 0 //Does it include the blueprints? + var/blueprints = FALSE //Does it include the blueprints? var/info //Info on the camera about mobs or some shit autoignition_temperature = 530 // Kelvin - fire_fuel = 1 + fire_fuel = TRUE /obj/item/weapon/photo/attack_self(mob/user) show(user) +/obj/item/weapon/photo/proc/photocreate(var/inicon, var/inimg, var/ininfo, var/inblueprints) + icon = inicon + img = inimg + info = ininfo + blueprints = inblueprints + /obj/item/weapon/photo/attackby(obj/item/weapon/P, mob/user) if(istype(P, /obj/item/weapon/pen) || istype(P, /obj/item/toy/crayon)) var/txt = sanitize(input(user, "What would you like to write on the back?", "Photo Writing", null) as text) @@ -91,6 +98,8 @@ icon_state = "album" item_state = "briefcase" can_only_hold = list("/obj/item/weapon/photo",) + storage_slots = 50 + max_combined_w_class = 200 /* @@ -113,15 +122,30 @@ harm_label_examine = list("A tiny label is on the lens.", "A label covers the lens!") var/pictures_max = 10 var/pictures_left = 10 - var/on = 1 + var/on = TRUE var/icon_on = "camera" var/icon_off = "camera_off" - var/blueprints = 0 //are blueprints visible in the current photo being created? + var/blueprints = FALSE //are blueprints visible in the current photo being created? var/list/aipictures = list() //Allows for storage of pictures taken by AI, in a similar manner the datacore stores info var/photo_size = 3 //Default is 3x3. 1x1, 5x5, 7x7 are also options - var/panelopen = 0 + var/panelopen = FALSE + var/obj/item/weapon/light/bulb/flashbulb = null + var/start_with_bulb = TRUE + +/obj/item/device/camera/New(var/empty = FALSE) + ..() + if(empty == TRUE) + start_with_bulb = FALSE + pictures_left = 0 + if(start_with_bulb) + flashbulb = new(src) + +/obj/item/device/camera/Destroy() + qdel(flashbulb) + flashbulb = null + ..() /obj/item/device/camera/sepia name = "camera" @@ -185,30 +209,37 @@ /obj/item/device/camera/AltClick() set_zoom() -/obj/item/device/camera/ai_camera //camera AI can take pictures with - name = "AI photo camera" - var/in_camera_mode = 0 -/* - verb/picture() - set category ="AI Commands" - set name = "Take Image" - set src in usr +/obj/item/device/camera/silicon + name = "silicon photo camera" + start_with_bulb = FALSE + var/in_camera_mode = FALSE - toggle_camera_mode() +/obj/item/device/camera/silicon/ai_camera //camera AI can take pictures with + name = "\improper AI photo camera" - verb/viewpicture() - set category ="AI Commands" - set name = "View Images" - set src in usr +/obj/item/device/camera/silicon/robot_camera + name = "cyborg photo camera" - viewpictures() -*/ +/obj/item/device/camera/silicon/robot_camera/verb/borgprinting() + set category ="Robot Commands" + set name = "Print Image" + set src in usr + + if(!isrobot(usr)) + return + + var/mob/living/silicon/robot/R = usr + + if(R.incapacitated()) + return + + borgprint() /obj/item/device/camera/attackby(obj/item/I, mob/user) if(isscrewdriver(I)) to_chat(user, "You [panelopen ? "close" : "open"] the panel on the side of \the [src].") panelopen = !panelopen - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 50, 1) if(istype(I, /obj/item/stack/cable_coil)) if(!panelopen) @@ -218,12 +249,14 @@ to_chat(user, "You don't have enough cable to alter \the [src].") return to_chat(user, "You attach [C.amount > 5 ? "some" : "the"] wires to \the [src]'s flash circuit.") - if(src.loc == user) + if(loc == user) user.drop_item(src, force_drop = 1) - var/obj/item/device/blinder/Q = new (get_turf(user)) + var/obj/item/device/blinder/Q = new(get_turf(user), empty = TRUE) + handle_blinder(Q) user.put_in_hands(Q) else - new /obj/item/device/blinder(get_turf(src.loc)) + var/obj/item/device/blinder/Q = new(get_turf(loc), empty = TRUE) + handle_blinder(Q) C.use(5) qdel(src) @@ -242,6 +275,20 @@ return ..() +/obj/item/device/camera/proc/handle_blinder(obj/item/device/blinder/blinder) + if(flashbulb) + blinder.flashbulb = flashbulb + flashbulb.forceMove(blinder) + flashbulb = null + + blinder.name = name + blinder.icon = icon + blinder.base_desc = desc + blinder.update_desc() + blinder.icon_state = icon_state + blinder.item_state = item_state + blinder.mech_flags = mech_flags + blinder.decon_path = type /obj/item/device/camera/proc/camera_get_icon(list/turfs, turf/center) var/atoms[] = list() @@ -252,21 +299,9 @@ continue atoms.Add(A) - var/list/sorted = list() - var/j - for(var/i = 1 to atoms.len) - var/atom/c = atoms[i] - for(j = sorted.len, j > 0, --j) - var/atom/c2 = sorted[j] - if(c2.plane < c.plane) - break - else if((c2.plane == c.plane) && (c2.layer <= c.layer)) - break - sorted.Insert(j+1, c) - var/icon/res = get_base_photo_icon() - for(var/atom/A in sorted) + for(var/atom/A in plane_layer_sort(atoms)) var/icon/img = getFlatIcon(A,A.dir,0) if(istype(A, /mob/living) && A:lying) img.Turn(A:lying) @@ -303,21 +338,9 @@ else atoms.Add(A) - var/list/sorted = list() - var/j - for(var/i = 1 to atoms.len) - var/atom/c = atoms[i] - for(j = sorted.len, j > 0, --j) - var/atom/c2 = sorted[j] - if(c2.plane < c.plane) - break - else if((c2.plane == c.plane) && (c2.layer <= c.layer)) - break - sorted.Insert(j+1, c) - var/icon/res = get_base_photo_icon() - for(var/atom/A in sorted) + for(var/atom/A in plane_layer_sort(atoms)) var/icon/img = getFlatIcon(A,A.dir,0) if(istype(A, /mob/living) && A:lying) img.Turn(A:lying) @@ -344,7 +367,7 @@ /obj/item/device/camera/proc/camera_get_mobs(turf/the_turf) var/mob_detail - for(var/mob/living/carbon/A in the_turf) + for(var/mob/living/A in the_turf) if(A.invisibility) continue var/holding = null @@ -444,10 +467,10 @@ temp.Blend("#000", ICON_OVERLAY) temp.Blend(camera_get_icon(turfs, target), ICON_OVERLAY) - if(!isAI(user)) + if(!issilicon(user)) printpicture(user, temp, mobs, flag) else - aipicture(user, temp, mobs, blueprints) + aipicture(user, temp, mobs, user, blueprints) /obj/item/device/camera/proc/printpicture(mob/user, icon/temp, mobs, flag) //Normal camera proc for creating photos var/obj/item/weapon/photo/P = new/obj/item/weapon/photo() @@ -463,8 +486,8 @@ P.pixel_y = rand(-10, 10) * PIXEL_MULTIPLIER if(blueprints) - P.blueprints = 1 - blueprints = 0 + P.blueprints = TRUE + blueprints = FALSE /obj/item/device/camera/sepia/printpicture(mob/user, icon/temp, mobs, flag) //Creates photos in sepia var/obj/item/weapon/photo/P = new/obj/item/weapon/photo() @@ -480,8 +503,8 @@ P.pixel_y = rand(-10, 10) * PIXEL_MULTIPLIER if(blueprints) - P.blueprints = 1 - blueprints = 0 + P.blueprints = TRUE + blueprints = FALSE var/icon/I1 = icon(P.icon, P.icon_state) var/icon/I2 = icon(P.img) @@ -492,9 +515,7 @@ P.icon = I1 P.img = I2 -/obj/item/device/camera/proc/aipicture(mob/user, icon/temp, mobs) //instead of printing a picture like a regular camera would, we do this instead for the AI - - +/obj/item/device/camera/proc/aipicture(mob/user, icon/temp, mobs, isAI) //instead of printing a picture like a regular camera would, we do this instead for the AI var/icon/small_img = icon(temp) var/icon/ic = icon('icons/obj/items.dmi',"photo") small_img.Scale(8, 8) @@ -505,12 +526,15 @@ var/pixel_x = rand(-10, 10) * PIXEL_MULTIPLIER var/pixel_y = rand(-10, 10) * PIXEL_MULTIPLIER - var/injectblueprints = 1 + var/injectblueprints = TRUE if(blueprints) - injectblueprints = 1 - blueprints = 0 + injectblueprints = TRUE + blueprints = FALSE - injectaialbum(icon, img, info, pixel_x, pixel_y, injectblueprints) + if(isAI(user)) + injectaialbum(icon, img, info, pixel_x, pixel_y, injectblueprints) + else + injectmasteralbum(icon, img, info, pixel_x, pixel_y, injectblueprints) /datum/picture @@ -519,9 +543,13 @@ /obj/item/device/camera/proc/injectaialbum(var/icon, var/img, var/info, var/pixel_x, var/pixel_y, var/blueprintsinject) //stores image information to a list similar to that of the datacore + var/numberer = 1 + for(var/datum/picture in aipictures) + numberer++ + var/datum/picture/P = new() - P.fields["name"] = "\ref[P]" + P.fields["name"] = "Image [numberer] (taken by [loc.name])" P.fields["icon"] = icon P.fields["img"] = img P.fields["info"] = info @@ -530,34 +558,63 @@ P.fields["blueprints"] = blueprintsinject aipictures += P - to_chat(usr, "Image recorded")//feedback to the AI player that the picture was taken + to_chat(loc, "Image recorded and saved to local database.")//feedback to the AI player that the picture was taken +/obj/item/device/camera/proc/injectmasteralbum(var/icon, var/img, var/info, var/pixel_x, var/pixel_y, var/blueprintsinject) + var/numberer = 1 + var/mob/living/silicon/robot/C = loc //Hackyman + if(C.connected_ai) + for(var/datum/picture in C.connected_ai.aicamera.aipictures) + numberer++ + var/datum/picture/P = new() + P.fields["name"] = "Image [numberer] (taken by [C.name])" + P.fields["icon"] = icon + P.fields["img"] = img + P.fields["info"] = info + P.fields["pixel_x"] = pixel_x + P.fields["pixel_y"] = pixel_y + P.fields["blueprints"] = blueprintsinject -/obj/item/device/camera/ai_camera/proc/viewpictures() //AI proc for viewing pictures they have taken + C.connected_ai.aicamera.aipictures += P + to_chat(C.connected_ai, "New image uploaded by [C.name].") + to_chat(C, "Image recorded and uploaded to [C.connected_ai.name]'s database.") //feedback to the Cyborg player that the picture was taken + else + injectaialbum(icon, img, info, pixel_x, pixel_y, blueprintsinject) + +/obj/item/device/camera/silicon/proc/viewpichelper(var/obj/item/device/camera/silicon/targetloc) var/list/nametemp = list() var/find var/datum/picture/selection - if(src.aipictures.len == 0) - to_chat(usr, "No images saved") + if(!targetloc.aipictures.len) + to_chat(usr, "No images saved") return - for(var/datum/picture/t in src.aipictures) - nametemp += t.fields["name"] - find = input("Select image (listed in order taken)") in nametemp + for(var/datum/picture/i in targetloc.aipictures) + nametemp += i.fields["name"] + find = input("Select image (numbered in order taken)") in nametemp var/obj/item/weapon/photo/P = new/obj/item/weapon/photo() - for(var/datum/picture/q in src.aipictures) + + for(var/datum/picture/q in targetloc.aipictures) if(q.fields["name"] == find) selection = q break // just in case some AI decides to take 10 thousand pictures in a round - P.icon = selection.fields["icon"] - P.img = selection.fields["img"] - P.info = selection.fields["info"] + + P.photocreate(selection.fields["icon"], selection.fields["img"], selection.fields["info"]) P.pixel_x = selection.fields["pixel_x"] P.pixel_y = selection.fields["pixel_y"] P.show(usr) - to_chat(usr, P.info) - del P //so 10 thousdand pictures items are not left in memory should an AI take them and then view them all. + qdel(P) //so 10 thousdand pictures items are not left in memory should an AI take them and then view them all. + +/obj/item/device/camera/silicon/proc/viewpictures(var/mob/user) + if(isrobot(user)) // Cyborg/MoMMI + var/mob/living/silicon/robot/C = user + if(C.connected_ai) + viewpichelper(C.connected_ai.aicamera) + else + viewpichelper(src) + else // AI + viewpichelper(src) /obj/item/device/camera/afterattack(atom/target, mob/user, flag) if(!on || !pictures_left || (!isturf(target) && !isturf(target.loc))) @@ -570,26 +627,61 @@ pictures_left-- to_chat(user, "[pictures_left] photos left.") icon_state = icon_off - on = 0 + on = FALSE if(pictures_left > 0) spawn(64) icon_state = icon_on - on = 1 + on = TRUE /obj/item/device/camera/remote_attack(atom/target, mob/user, atom/movable/eye) if(istype(eye, /obj/machinery/camera)) return afterattack(target, user) //Allow taking photos when looking through cameras -/obj/item/device/camera/ai_camera/proc/toggle_camera_mode() - if(in_camera_mode) - camera_mode_off() +/obj/item/device/camera/silicon/proc/toggle_camera_mode(var/mob/living/silicon/S = null) + if(!S) + return + in_camera_mode = !in_camera_mode + to_chat(S, "Camera Mode [in_camera_mode ? "activated":"deactivated"]") + if(S.camera_icon) + S.camera_icon.icon_state = "camera[in_camera_mode ? "1":""]" + +/obj/item/device/camera/silicon/robot_camera/proc/borgprint() + var/list/nametemp = list() + var/find + var/datum/picture/selection + var/mob/living/silicon/robot/C = loc + var/obj/item/device/camera/silicon/targetcam = null + + if(C.stat) + return + if(C.toner < CYBORG_PHOTO_COST) + to_chat(C, "Insufficent toner to print image.") + return + if(C.connected_ai) + targetcam = C.connected_ai.aicamera else - camera_mode_on() + targetcam = C.aicamera + if(!targetcam.aipictures.len) + to_chat(C, "No images saved") + return + for(var/datum/picture/t in targetcam.aipictures) + nametemp += t.fields["name"] + find = input("Select image (numbered in order taken)") in nametemp + for(var/datum/picture/q in targetcam.aipictures) + if(q.fields["name"] == find) + selection = q + break + var/obj/item/weapon/photo/p = new /obj/item/weapon/photo(C.loc) + p.photocreate(selection.fields["icon"], selection.fields["img"], selection.fields["info"], selection.fields["blueprints"]) + p.pixel_x = rand(-10, 10) + p.pixel_y = rand(-10, 10) + C.toner -= CYBORG_PHOTO_COST + visible_message("[C.name] spits out a photograph from a narrow slot on it's chassis.") + playsound(loc, "polaroid", 75, 1, -3) + to_chat(C, "You print a photograph.") -/obj/item/device/camera/ai_camera/proc/camera_mode_off() - src.in_camera_mode = 0 - to_chat(usr, "Camera Mode deactivated") - -/obj/item/device/camera/ai_camera/proc/camera_mode_on() - src.in_camera_mode = 1 - to_chat(usr, "Camera Mode activated") +/obj/item/device/camera/silicon/proc/sync(var/mob/living/silicon/robot/R) + if(R.connected_ai && R.connected_ai.aicamera && R.aicamera) // Send images the Cyborg has taken to the AI's album upon sync. + R.connected_ai.aicamera.aipictures |= R.aicamera.aipictures + R.aicamera.aipictures = R.connected_ai.aicamera.aipictures + to_chat(R, "Photo database synced with [R.connected_ai.name].") \ No newline at end of file diff --git a/code/modules/power/antimatter/control.dm b/code/modules/power/antimatter/control.dm index 62758234fa3..540ba3a6861 100644 --- a/code/modules/power/antimatter/control.dm +++ b/code/modules/power/antimatter/control.dm @@ -66,7 +66,7 @@ if(stat & (NOPOWER|BROKEN) || !active)//can update the icons even without power return - if(!fueljar)//No fuel but we are on, shutdown + if(!fueljar || fueljar.fuel <= 0)//No fuel but we are on, shutdown toggle_power() //Angry buzz or such here return @@ -84,7 +84,7 @@ /obj/machinery/power/am_control_unit/proc/produce_power() - playsound(get_turf(src), 'sound/effects/bang.ogg', 25, 1) + playsound(src, 'sound/effects/bang.ogg', 25, 1) var/core_power = reported_core_efficiency//Effectively how much fuel we can safely deal with if(core_power <= 0) return 0//Something is wrong @@ -105,7 +105,7 @@ for(var/obj/machinery/am_shielding/AMS in linked_cores) AMS.stability -= core_damage AMS.check_stability(1) - playsound(get_turf(src), 'sound/effects/bang.ogg', 50, 1) + playsound(src, 'sound/effects/bang.ogg', 50, 1) return @@ -173,7 +173,7 @@ return if(iswrench(W)) if(!anchored) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 75, 1) + playsound(src, 'sound/items/Ratchet.ogg', 75, 1) user.visible_message("[user.name] secures the [src.name] to the floor.", \ "You secure the anchor bolts to the floor.", \ "You hear a ratchet") @@ -182,7 +182,7 @@ check_shield_icons() connect_to_network() else if(!linked_shielding.len > 0) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 75, 1) + playsound(src, 'sound/items/Ratchet.ogg', 75, 1) user.visible_message("[user.name] unsecures the [src.name].", \ "You remove the anchor bolts.", \ "You hear a ratchet") diff --git a/code/modules/power/antimatter/fuel.dm b/code/modules/power/antimatter/fuel.dm index 0e12dea51dc..02364181013 100644 --- a/code/modules/power/antimatter/fuel.dm +++ b/code/modules/power/antimatter/fuel.dm @@ -73,7 +73,7 @@ ..() to_chat(user, "A magnetic storage ring, it contains [fuel]kg of [content ? content : "nothing"].") -/obj/item/weapon/fuel/proc/injest(mob/M as mob) +/obj/item/weapon/fuel/proc/ingest(mob/M as mob) switch(content) if("Anti-Hydrogen") M.gib() @@ -99,4 +99,4 @@ else for(var/mob/O in viewers(M, null)) O.show_message(text("[M] ate the [content ? content : "empty canister"]!"), 1) - src.injest(M) + src.ingest(M) diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index c7b46657948..2e636ab6542 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -98,8 +98,9 @@ var/make_alerts = TRUE // Should this APC make power alerts to the area? machine_flags = WIREJACK - holomap = TRUE - auto_holomap = TRUE + +/obj/machinery/power/apc/supports_holomap() + return TRUE /obj/machinery/power/apc/no_alerts make_alerts = FALSE @@ -113,9 +114,10 @@ /obj/machinery/power/apc/New(loc, var/ndir, var/building=0) ..(loc) - - if(areaMaster.areaapc) - world.log << "Second APC detected in area: [areaMaster.name]. Deleting the second APC." + var/area/this_area = get_area(src) + if(this_area.areaapc) + var/turf/T = get_turf(src) + world.log << "Second APC detected in area: [this_area.name] [T.x], [T.y], [T.z]. Deleting the second APC." qdel(src) return @@ -127,7 +129,7 @@ src.tdir = dir // to fix Vars bug dir = SOUTH - areaMaster.set_apc(src) + this_area.set_apc(src) if(src.tdir & 3) pixel_x = 0 @@ -143,8 +145,9 @@ operating = 0 stat |= MAINT - if(ticker) + if(ticker && ticker.current_state == GAME_STATE_PLAYING) initialize() + update() /obj/machinery/power/apc/proc/init() has_electronics = 2 //installed and secured @@ -159,22 +162,18 @@ /obj/machinery/power/apc/finalise_terminal() // create a terminal object at the same position as original turf loc // wires will attach to this - terminal = new/obj/machinery/power/terminal {auto_holomap = 0} (src.loc) + terminal = new/obj/machinery/power/terminal(src.loc) terminal.dir = tdir terminal.master = src - var/turf/T = loc - if (istype(T)) - T.soft_add_holomap(terminal) + terminal.add_self_to_holomap() /obj/machinery/power/apc/initialize() ..() - - name = "[areaMaster.name] APC" + var/area/this_area = get_area(src) + name = "[this_area.name] APC" update_icon() - - spawn(5) - update() + add_self_to_holomap() /obj/machinery/power/apc/examine(mob/user) ..() @@ -389,7 +388,7 @@ if (terminal) to_chat(user, "Disconnect wires first.") return - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) + playsound(src, 'sound/items/Crowbar.ogg', 50, 1) to_chat(user, "You are trying to remove the power control board...")//lpeters - fixed grammar issues if (do_after(user, src, 50) && opened && !terminal && has_electronics == 1) @@ -448,12 +447,12 @@ if (has_electronics==1 && terminal) has_electronics = 2 stat &= ~MAINT - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 50, 1) to_chat(user, "You screw the circuit electronics into place.") else if (has_electronics==2) has_electronics = 1 stat |= MAINT - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 50, 1) to_chat(user, "You unfasten the electronics.") else /* has_electronics==0 */ to_chat(user, "There is nothing to secure.") @@ -518,7 +517,7 @@ to_chat(user, "You must remove the floor plating in front of the APC first.") return to_chat(user, "You begin to cut the cables...") - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) if (do_after(user, src, 50) && opened && terminal && has_electronics != 2 && !T.intact) if (prob(50) && electrocute_mob(usr, terminal.get_powernet(), terminal)) spark(src, 5) @@ -531,7 +530,7 @@ terminal = null else if (istype(W, /obj/item/weapon/circuitboard/power_control) && opened && has_electronics==0 && !((stat & BROKEN) || malfhack)) to_chat(user, "You begin to insert the power control board into the frame...") - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) if (do_after(user, src, 10) && opened && has_electronics == 0 && !((stat & BROKEN) || malfhack)) has_electronics = 1 to_chat(user, "You place the power control board inside the frame.") @@ -546,7 +545,7 @@ to_chat(user, "You need more welding fuel to complete this task.") return to_chat(user, "You start welding the APC frame...") - playsound(get_turf(src), 'sound/items/Welder.ogg', 50, 1) + playsound(src, 'sound/items/Welder.ogg', 50, 1) if (do_after(user, src, 50)) if(!src || !WT.remove_fuel(3, user)) return @@ -658,7 +657,7 @@ user.do_attack_animation(src, user) user.delayNextAttack(8) user.visible_message("[user.name] slashes at the [src.name]!", "You slash at the [src.name]!") - playsound(get_turf(src), 'sound/weapons/slash.ogg', 100, 1) + playsound(src, 'sound/weapons/slash.ogg', 100, 1) var/allcut = wires.IsAllCut() @@ -758,7 +757,8 @@ if (!ui) // the ui does not exist, so we'll create a new one // for a list of parameters and their descriptions see the code docs in \code\\modules\nano\nanoui.dm - ui = new(user, src, ui_key, "apc.tmpl", "[areaMaster.name] - APC", 520, data["siliconUser"] ? 465 : 440) + var/area/this_area = get_area(src) + ui = new(user, src, ui_key, "apc.tmpl", "[this_area.name] - APC", 520, data["siliconUser"] ? 465 : 440) // when the ui is first opened this is the data it will use ui.set_initial_data(data) // open the new ui window @@ -767,23 +767,20 @@ ui.set_auto_update(1) /obj/machinery/power/apc/proc/report() - return "[areaMaster.name] : [equipment]/[lighting]/[environ] ([lastused_equip+lastused_light+lastused_environ]) : [cell? cell.percent() : "N/C"] ([charging])" + var/area/this_area = get_area(src) + return "[this_area.name] : [equipment]/[lighting]/[environ] ([lastused_equip+lastused_light+lastused_environ]) : [cell? cell.percent() : "N/C"] ([charging])" /obj/machinery/power/apc/proc/update() + var/area/this_area = get_area(src) if(operating && !shorted) - areaMaster.power_light = (lighting > 1) - areaMaster.power_equip = (equipment > 1) - areaMaster.power_environ = (environ > 1) -// if (area.name == "AI Chamber") -// spawn(10) -// to_chat(world, " [area.name] [area.power_equip]") + this_area.power_light = (lighting > 1) + this_area.power_equip = (equipment > 1) + this_area.power_environ = (environ > 1) else - areaMaster.power_light = 0 - areaMaster.power_equip = 0 - areaMaster.power_environ = 0 -// if (area.name == "AI Chamber") -// to_chat(world, "[area.power_equip]") - areaMaster.power_change() + this_area.power_light = 0 + this_area.power_equip = 0 + this_area.power_environ = 0 + this_area.power_change() /obj/machinery/power/apc/proc/isWireCut(var/wireIndex) return wires.IsIndexCut(wireIndex) @@ -1047,7 +1044,8 @@ if(stat & (BROKEN|MAINT|FORCEDISABLE)) return - if(!areaMaster.requires_power) + var/area/this_area = get_area(src) + if(!this_area.requires_power) return /* @@ -1060,13 +1058,13 @@ area.calc_lighting() */ - lastused_light = areaMaster.usage(LIGHT) - lastused_light += areaMaster.usage(STATIC_LIGHT) - lastused_equip = areaMaster.usage(EQUIP) - lastused_light += areaMaster.usage(STATIC_EQUIP) - lastused_environ = areaMaster.usage(ENVIRON) - lastused_light += areaMaster.usage(STATIC_ENVIRON) - areaMaster.clear_usage() + lastused_light = this_area.usage(LIGHT) + lastused_light += this_area.usage(STATIC_LIGHT) + lastused_equip = this_area.usage(EQUIP) + lastused_light += this_area.usage(STATIC_EQUIP) + lastused_environ = this_area.usage(ENVIRON) + lastused_light += this_area.usage(STATIC_ENVIRON) + this_area.clear_usage() lastused_total = lastused_light + lastused_equip + lastused_environ @@ -1129,26 +1127,26 @@ equipment = autoset(equipment, 0) lighting = autoset(lighting, 0) environ = autoset(environ, 0) - if(areaMaster.poweralm && make_alerts) - areaMaster.poweralert(0, src) + if(this_area.poweralm && make_alerts) + this_area.poweralert(0, src) else if(cell.percent() < 15 && longtermpower < 0) // <15%, turn off lighting & equipment equipment = autoset(equipment, 2) lighting = autoset(lighting, 2) environ = autoset(environ, 1) - if(areaMaster.poweralm && make_alerts) - areaMaster.poweralert(0, src) + if(this_area.poweralm && make_alerts) + this_area.poweralert(0, src) else if(cell.percent() < 30 && longtermpower < 0) // <30%, turn off equipment equipment = autoset(equipment, 2) lighting = autoset(lighting, 1) environ = autoset(environ, 1) - if(areaMaster.poweralm && make_alerts) - areaMaster.poweralert(0, src) + if(this_area.poweralm && make_alerts) + this_area.poweralert(0, src) else // otherwise all can be on equipment = autoset(equipment, 1) lighting = autoset(lighting, 1) environ = autoset(environ, 1) - if(cell.percent() > 35 && !areaMaster.poweralm && make_alerts) // 35% to prevent spamming alerts if it fluctuates - areaMaster.poweralert(1, src) + if(cell.percent() > 35 && !this_area.poweralm && make_alerts) // 35% to prevent spamming alerts if it fluctuates + this_area.poweralert(1, src) // now trickle-charge the cell @@ -1193,7 +1191,7 @@ lighting = autoset(lighting, 0) environ = autoset(environ, 0) if(!make_alerts) - areaMaster.poweralert(0, src) + this_area.poweralert(0, src) // update icon & area power if anything changed if(last_lt != lighting || last_eq != equipment || last_en != environ) @@ -1288,7 +1286,8 @@ obj/machinery/power/apc/proc/autoset(var/val, var/on) if( cell && cell.charge>=20) cell.use(20); spawn(0) - for(var/obj/machinery/light/L in areaMaster) + var/area/this_area = get_area(src) + for(var/obj/machinery/light/L in this_area) L.on = 1 L.broken() sleep(1) diff --git a/code/modules/power/battery.dm b/code/modules/power/battery.dm index 6a94dfb8429..285506eb09e 100644 --- a/code/modules/power/battery.dm +++ b/code/modules/power/battery.dm @@ -5,6 +5,10 @@ #define SMESLEVELCHARGING 2 #define SMESLEVELONLINE 3 +#define BATTERY_NO_CHARGE 0 +#define BATTERY_MANUAL_CHARGE 1 +#define BATTERY_AUTO_CHARGE 2 + var/global/list/battery_charge = list( image('icons/obj/power.dmi', "smes-og1"), image('icons/obj/power.dmi', "smes-og2"), @@ -51,16 +55,17 @@ var/global/list/battery_online = list( var/output = 50000 var/lastout = 0 + var/loadcharge = 0 var/loaddemand = 0 var/capacity = 5e6 //Max stored charge var/charge = 1e6 //Stored charge - var/charging = 0 //Are we currently taking charge in? - var/chargemode = 0 //Are we set to charge or not? Not the same as charging + var/charging = FALSE //Are we currently taking charge in? + var/chargemode = BATTERY_NO_CHARGE //Are we set to charge or not? Not the same as charging var/chargecount = 0 //How long we've spent since not charging var/chargelevel = 50000 var/online = 1 - var/smes_input_max = 200000 - var/smes_output_max = 200000 + var/max_input = 200000 + var/max_output = 200000 var/name_tag = "" @@ -81,9 +86,9 @@ var/global/list/battery_online = list( capcount += SP.rating-1 if(istype(SP, /obj/item/weapon/stock_parts/micro_laser)) lasercount += SP.rating-1 - capacity = initial(capacity) + capcount*5e5 - smes_input_max = initial(smes_input_max) + lasercount*25000 - smes_output_max = initial(smes_output_max) + lasercount*25000 + capacity = initial(capacity) + capcount*125e4 + max_input = initial(max_input) + lasercount*50000 + max_output = initial(max_output) + lasercount*50000 /obj/machinery/power/battery/process() if(stat & (BROKEN | FORCEDISABLE | EMPED)) @@ -102,12 +107,12 @@ var/global/list/battery_online = list( var/excess = surplus() if (charging) - if (excess >= chargelevel) // If there's power available, try to charge - var/load = min((capacity - charge) / SMESRATE, chargelevel) // Charge at set rate, limited to spare capacity - - charge += load * SMESRATE // Increase the charge - - add_load(load) // Add the load to the terminal side network + // Manual charge mode is the 'old' mode, when batteries only charge when available power is higher than set charge level + // Auto charge mode lets batteries take any amount of available power, limited by charge level + if((chargemode == BATTERY_MANUAL_CHARGE && excess >= chargelevel)||(chargemode == BATTERY_AUTO_CHARGE && excess > 0)) // If there's power available, try to charge + loadcharge = min((capacity - charge) / SMESRATE, excess, chargelevel) // Charge at set rate, limited to spare capacity + charge += loadcharge * SMESRATE // Increase the charge + add_load(loadcharge) // Add the load to the terminal side network else charging = FALSE @@ -119,7 +124,7 @@ var/global/list/battery_online = list( charging = TRUE chargecount = 0 - if (excess > chargelevel) + if ((chargemode == BATTERY_MANUAL_CHARGE && excess >= chargelevel) || (chargemode == BATTERY_AUTO_CHARGE && excess > 0)) chargecount++ else chargecount = 0 @@ -127,7 +132,7 @@ var/global/list/battery_online = list( chargecount = 0 // Output - if (online) + if (online && get_powernet()) // how can discharge be real if our powernet isn't real lastout = min(charge / SMESRATE, output) // Limit output to that stored charge -= lastout * SMESRATE // Reduce the storage (may be recovered in /restore() if excessive) @@ -192,12 +197,15 @@ var/global/list/battery_online = list( data["storedCapacity"] = round(100.0*charge/capacity, 0.1) data["charging"] = charging data["chargeMode"] = chargemode + data["chargeLoad"] = round(loadcharge) data["chargeLevel"] = chargelevel - data["chargeMax"] = smes_input_max + data["chargeMax"] = max_input data["outputOnline"] = online data["outputLevel"] = output - data["outputMax"] = smes_output_max + data["outputMax"] = max_output data["outputLoad"] = round(loaddemand) + data["hasInput"] = get_terminal() ? 1 : 0; + data["hasOutput"] = powernet ? 1 : 0; // update the ui if it exists, returns null if no ui is passed/found ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) @@ -232,9 +240,14 @@ var/global/list/battery_online = list( return 0 // Do not update ui if( href_list["cmode"] ) - chargemode = !chargemode - if(!chargemode) - charging = 0 + switch( href_list["cmode"]) + if("auto") + chargemode = BATTERY_AUTO_CHARGE + if("manual") + chargemode = BATTERY_MANUAL_CHARGE + if("off") + chargemode = BATTERY_NO_CHARGE + charging = 0 update_icon() else if( href_list["online"] ) @@ -245,20 +258,20 @@ var/global/list/battery_online = list( if("min") chargelevel = 0 if("max") - chargelevel = smes_input_max //30000 + chargelevel = max_input //30000 if("set") - chargelevel = input(usr, "Enter new input level (0-[smes_input_max])", "SMES Input Power Control", chargelevel) as num - chargelevel = max(0, min(smes_input_max, chargelevel)) // clamp to range + chargelevel = input(usr, "Enter new input level (0-[max_input])", "SMES Input Power Control", chargelevel) as num + chargelevel = max(0, min(max_input, chargelevel)) // clamp to range else if( href_list["output"] ) switch( href_list["output"] ) if("min") output = 0 if("max") - output = smes_output_max //30000 + output = max_output //30000 if("set") - output = input(usr, "Enter new output level (0-[smes_output_max])", "SMES Output Power Control", output) as num - output = max(0, min(smes_output_max, output)) // clamp to range + output = input(usr, "Enter new output level (0-[max_output])", "SMES Output Power Control", output) as num + output = max(0, min(max_output, output)) // clamp to range investigation_log(I_SINGULO,"input/output; [chargelevel>output?"":""][chargelevel]/[output] | Output-mode: [online?"on":"off"] | Input-mode: [chargemode?"auto":"off"] by [usr.key]") @@ -307,8 +320,8 @@ var/global/list/battery_online = list( online = !online update_icon() else //Screw up power input/output - chargelevel = rand(0, smes_input_max) - output = rand(0, smes_output_max) + chargelevel = rand(0, max_input) + output = rand(0, max_output) /proc/rate_control(var/S, var/V, var/C, var/Min=1, var/Max=5, var/Limit=null) var/href = "-"+rate+"[href]=[Limit]'>+" return rate + +/obj/machinery/power/battery/proc/get_terminal() + return terminal diff --git a/code/modules/power/battery_ion.dm b/code/modules/power/battery_ion.dm index f3ce9f6541e..fc2cc8e1464 100644 --- a/code/modules/power/battery_ion.dm +++ b/code/modules/power/battery_ion.dm @@ -110,3 +110,8 @@ if(_chargedisplay != chargedisplay()) // If needed updates the icons overlay update_icon() + +/obj/machinery/power/battery/portable/get_terminal() + if(connected_to) + return connected_to.terminal + return null diff --git a/code/modules/power/battery_port.dm b/code/modules/power/battery_port.dm index 7003e17dabd..7e9ae8bf48b 100644 --- a/code/modules/power/battery_port.dm +++ b/code/modules/power/battery_port.dm @@ -94,4 +94,3 @@ connected.update_icon() connected = null update_icon() - diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm index 3a1c3db33a7..5a407f868e0 100644 --- a/code/modules/power/cable.dm +++ b/code/modules/power/cable.dm @@ -48,8 +48,8 @@ By design, d1 is the smallest direction and d2 is the highest var/oldnewavail = 0 var/oldload = 0 - holomap = TRUE - auto_holomap = TRUE +/obj/structure/cable/supports_holomap() + return TRUE /obj/structure/cable/yellow _color = "yellow" @@ -100,6 +100,10 @@ By design, d1 is the smallest direction and d2 is the highest cable_list += src //add it to the global cable list +/obj/structure/cable/initialize() + ..() + add_self_to_holomap() + /obj/structure/cable/Destroy() // called when a cable is deleted if(powernet) powernet.set_to_build() // update the powernets @@ -188,7 +192,7 @@ By design, d1 is the smallest direction and d2 is the highest return if(iswirecutter(W)) - if(shock(user, 50)) + if(shock(user, 50, W.siemens_coefficient)) return cut(user, T) return @@ -202,14 +206,14 @@ By design, d1 is the smallest direction and d2 is the highest R.is_empty() else if(istype(W, /obj/item/device/multitool)) if((powernet) && (powernet.avail > 0)) // is it powered? - to_chat(user, "[powernet.avail]W in power network.") + to_chat(user, "Power network status report - Load: [powernet.load]W - Available: [powernet.avail]W.") else to_chat(user, "The cable is not powered.") shock(user, 5, 0.2) else if(src.d1 && W.is_conductor()) // d1 determines if this is a cable end - shock(user, 50, 0.7) + shock(user, 50, W.siemens_coefficient) src.add_fingerprint(user) diff --git a/code/modules/power/cell.dm b/code/modules/power/cell.dm index 40924955c89..71ec0753167 100644 --- a/code/modules/power/cell.dm +++ b/code/modules/power/cell.dm @@ -42,7 +42,7 @@ explode() return 0 - if(maxcharge < amount) + if(maxcharge <= charge) return 0 var/power_used = min(maxcharge-charge,amount) if(crit_fail) @@ -100,9 +100,11 @@ if (light_impact_range==0) rigged = 0 corrupt() - return + return FALSE //explosion(T, 0, 1, 2, 2) + . = TRUE + log_admin("LOG: Rigged power cell explosion, last touched by [fingerprintslast]") message_admins("LOG: Rigged power cell explosion, last touched by [fingerprintslast]") diff --git a/code/modules/power/components.dm b/code/modules/power/components.dm index 08cd7b9dceb..ebb0c915338 100644 --- a/code/modules/power/components.dm +++ b/code/modules/power/components.dm @@ -125,25 +125,26 @@ // If you're using a consumer, you need power. //if(!use_power) // return 1 - - if(isnull(parent.areaMaster) || !parent.areaMaster) + var/area/parent_area = get_area(parent) + if(!parent_area) return 0 // if not, then not powered. if((machine_flags & FIXED2WORK) && !parent.anchored) return 0 - return parent.areaMaster.powered(chan) // return power status of the area. + return parent_area.powered(chan) // return power status of the area. // increment the power usage stats for an area // defaults to power_channel /datum/power_connection/proc/use_power(amount, chan = channel) - if(isnull(parent.areaMaster) || !parent.areaMaster) + var/area/parent_area = get_area(parent) + if(!parent_area) return 0 // if not, then not powered. if(!powered(chan)) //no point in trying if we don't have power return 0 - parent.areaMaster.use_power(amount, chan) + parent_area.use_power(amount, chan) // called whenever the power settings of the containing area change // by default, check equipment channel & set flag @@ -226,9 +227,10 @@ /////////////////////////////////////////////// /datum/power_connection/proc/addStaticPower(value, powerchannel) - if(!parent.areaMaster) + var/area/parent_area = get_area(parent) + if(!parent_area) return - parent.areaMaster.addStaticPower(value, powerchannel) + parent_area.addStaticPower(value, powerchannel) /datum/power_connection/proc/removeStaticPower(value, powerchannel) addStaticPower(-value, powerchannel) @@ -344,4 +346,4 @@ if((machine_flags & FIXED2WORK) && !parent.anchored) return 0 - return 1 // We have a powernet and a cable, so we're okay. \ No newline at end of file + return 1 // We have a powernet and a cable, so we're okay. diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm index 75ebefe2158..7387cee6deb 100644 --- a/code/modules/power/lighting.dm +++ b/code/modules/power/lighting.dm @@ -34,7 +34,7 @@ src.add_fingerprint(user) if (iswrench(W)) if (src.stage == 1) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 75, 1) + playsound(src, 'sound/items/Ratchet.ogg', 75, 1) to_chat(usr, "You begin deconstructing [src].") if (!do_after(usr, src, 30)) return @@ -42,7 +42,7 @@ M.amount = sheets_refunded user.visible_message("[user.name] deconstructs [src].", \ "You deconstruct [src].", "You hear a noise.") - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 75, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 75, 1) qdel(src) return if (src.stage == 2) @@ -134,8 +134,8 @@ var/global/list/obj/machinery/light/alllights = list() var/idle = 0 // For process(). - holomap = TRUE - auto_holomap = TRUE +/obj/machinery/light/supports_holomap() + return TRUE /obj/machinery/light/spook(mob/dead/observer/ghost) if(..(ghost, TRUE)) @@ -189,6 +189,10 @@ var/global/list/obj/machinery/light/alllights = list() update(0) ..() +/obj/machinery/light/initialize() + ..() + add_self_to_holomap() + // create a new lighting fixture /obj/machinery/light/New() ..() @@ -365,7 +369,7 @@ var/global/list/obj/machinery/light/alllights = list() // attempt to deconstruct / stick weapon into light socket else if(status == LIGHT_EMPTY) if(iswirecutter(W)) //If it's a wirecutter take out the wires - playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 75, 1) + playsound(src, 'sound/items/Wirecutter.ogg', 75, 1) user.visible_message("[user.name] removes \the [src]'s wires.", \ "You remove \the [src]'s wires.", "You hear a noise.") var/obj/machinery/light_construct/newlight = null @@ -399,7 +403,8 @@ var/global/list/obj/machinery/light/alllights = list() * TRUE if area has power and lightswitch is on otherwise FALSE. */ /obj/machinery/light/proc/has_power() - return areaMaster.lightswitch && areaMaster.power_light + var/area/this_area = get_area(src) + return this_area.lightswitch && this_area.power_light /obj/machinery/light/proc/flicker(var/amount = rand(10, 20)) if(flickering) @@ -530,7 +535,7 @@ var/global/list/obj/machinery/light/alllights = list() if(!skip_sound_and_sparks) if(status == LIGHT_OK || status == LIGHT_BURNED) - playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 75, 1) + playsound(src, 'sound/effects/Glasshit.ogg', 75, 1) if(on) spark(src) status = LIGHT_BROKEN @@ -569,7 +574,8 @@ var/global/list/obj/machinery/light/alllights = list() */ /obj/machinery/light/power_change() spawn(10) - seton(areaMaster.lightswitch && areaMaster.power_light) + var/area/this_area = get_area(src) + seton(this_area.lightswitch && this_area.power_light) // called when on fire @@ -730,10 +736,11 @@ var/global/list/obj/machinery/light/alllights = list() shatter() -/obj/item/weapon/light/proc/shatter() +/obj/item/weapon/light/proc/shatter(verbose = TRUE) if(status == LIGHT_OK || status == LIGHT_BURNED) - src.visible_message("[name] shatters.","You hear a small glass object shatter.") + if(verbose) + src.visible_message("[name] shatters.","You hear a small glass object shatter.") status = LIGHT_BROKEN force = 5 - playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 75, 1) + playsound(src, 'sound/effects/Glasshit.ogg', 75, 1) update() diff --git a/code/modules/power/monitor.dm b/code/modules/power/monitor.dm index 80352a13448..3ec4f0e45c7 100644 --- a/code/modules/power/monitor.dm +++ b/code/modules/power/monitor.dm @@ -202,8 +202,9 @@ var/obj/machinery/power/apc/A = term.master + var/area/APC_area = get_area(A) tbl += "" - tbl += "["\The [A.areaMaster]"]" + tbl += "["\The [APC_area]"]" tbl += "[S[A.equipment+1]]
      [S[A.lighting+1]]
      [S[A.environ+1]]
      " tbl += "[A.lastused_total]" if(A.cell) @@ -223,4 +224,4 @@ tbl = jointext(tbl,"") src.interface.updateContent("APCTable", tbl) -#undef POWER_MONITOR_HIST_SIZE \ No newline at end of file +#undef POWER_MONITOR_HIST_SIZE diff --git a/code/modules/power/power.dm b/code/modules/power/power.dm index 85fdf9baf9a..7385f47d400 100644 --- a/code/modules/power/power.dm +++ b/code/modules/power/power.dm @@ -119,25 +119,26 @@ if(!use_power) return 1 - - if(isnull(src.areaMaster) || !src.areaMaster) + var/area/this_area = get_area(src) + if(!this_area) return 0 // if not, then not powered. if((machine_flags & FIXED2WORK) && !anchored) return 0 - return areaMaster.powered(chan) // return power status of the area. + return this_area.powered(chan) // return power status of the area. // increment the power usage stats for an area // defaults to power_channel /obj/machinery/proc/use_power(amount, chan = power_channel) - if(isnull(src.areaMaster) || !src.areaMaster) + var/area/this_area = get_area(src) + if(!this_area) return 0 // if not, then not powered. if(!powered(chan)) //no point in trying if we don't have power return 0 - src.areaMaster.use_power(amount, chan) + this_area.use_power(amount, chan) // called whenever the power settings of the containing area change // by default, check equipment channel & set flag @@ -241,8 +242,9 @@ return C /obj/machinery/proc/addStaticPower(value, powerchannel) - if(!areaMaster) + var/area/this_area = get_area(src) + if(!this_area) return - areaMaster.addStaticPower(value, powerchannel) + this_area.addStaticPower(value, powerchannel) /obj/machinery/proc/removeStaticPower(value, powerchannel) addStaticPower(-value, powerchannel) diff --git a/code/modules/power/singularity/collector.dm b/code/modules/power/singularity/collector.dm index ab6fd0b3cf3..01ff4efb747 100644 --- a/code/modules/power/singularity/collector.dm +++ b/code/modules/power/singularity/collector.dm @@ -51,7 +51,6 @@ var/global/list/rad_collectors = list() else to_chat(user, "The controls are locked!") return -..() /obj/machinery/power/rad_collector/attackby(obj/item/W, mob/user) if(..()) @@ -126,6 +125,12 @@ var/global/list/rad_collectors = list() else update_icons() +/proc/emitted_harvestable_radiation(turf/center, power, range = 7) + for(var/obj/machinery/power/rad_collector/R in rad_collectors) + if(get_dist(R, center) <= range) //Better than using orange() every process. + R.receive_pulse(power) + +//Pulse_strength is multiplied by around 70 (less or more depending on the air tank setup) to get the amount of watts generated /obj/machinery/power/rad_collector/proc/receive_pulse(const/pulse_strength) if (P && active) var/power_produced = P.air_contents.toxins * pulse_strength * 3.5 // original was 20, nerfed to 2 now 3.5 should get you about 500kw diff --git a/code/modules/power/singularity/emitter.dm b/code/modules/power/singularity/emitter.dm index 79979945490..ceea6feb6fc 100644 --- a/code/modules/power/singularity/emitter.dm +++ b/code/modules/power/singularity/emitter.dm @@ -233,7 +233,7 @@ //beam = getFromPool(/obj/item/projectile/beam/emitter, loc) //beam.dir = dir - //playsound(get_turf(src), 'sound/weapons/emitter.ogg', 25, 1) + //playsound(src, 'sound/weapons/emitter.ogg', 25, 1) if(prob(35)) spark(src, 5) diff --git a/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm b/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm index 7becd67b13d..14e98d18305 100644 --- a/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm +++ b/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm @@ -211,14 +211,14 @@ So, hopefully this is helpful if any more icons are to be added/changed/wonderin switch(src.construction_state)//TODO:Might be more interesting to have it need several parts rather than a single list of steps if(0) if(iswrench(O)) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 75, 1) + playsound(src, 'sound/items/Ratchet.ogg', 75, 1) src.anchored = 1 user.visible_message("[user.name] secures the [src.name] to the floor.", \ "You secure the external bolts.") temp_state++ if(1) if(iswrench(O)) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 75, 1) + playsound(src, 'sound/items/Ratchet.ogg', 75, 1) src.anchored = 0 user.visible_message("[user.name] detaches the [src.name] from the floor.", \ "You remove the external bolts.") @@ -354,14 +354,14 @@ So, hopefully this is helpful if any more icons are to be added/changed/wonderin switch(src.construction_state)//TODO:Might be more interesting to have it need several parts rather than a single list of steps if(0) if(iswrench(O)) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 75, 1) + playsound(src, 'sound/items/Ratchet.ogg', 75, 1) src.anchored = 1 user.visible_message("[user.name] secures the [src.name] to the floor.", \ "You secure the external bolts.") temp_state++ if(1) if(iswrench(O)) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 75, 1) + playsound(src, 'sound/items/Ratchet.ogg', 75, 1) src.anchored = 0 user.visible_message("[user.name] detaches the [src.name] from the floor.", \ "You remove the external bolts.") diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/power/singularity/singularity.dm index d70bfada576..bb1709c697c 100644 --- a/code/modules/power/singularity/singularity.dm +++ b/code/modules/power/singularity/singularity.dm @@ -111,7 +111,7 @@ new /obj/effect/gibspawner/generic(get_turf(user)) qdel(user) else - playsound(get_turf(user), get_sfx("soulstone"), 50,1) + playsound(user, get_sfx("soulstone"), 50,1) make_tracker_effects(get_turf(user), get_turf(src)) user.dust() else @@ -359,6 +359,10 @@ catch(var/exception/e) error("Singularity eat() caught exception:") error(e) + + spawn(0) //So the following line doesn't stop execution + throw e //So ALL debug information is sent to the runtime log + continue //for(var/turf/T in trange(grav_pull, src)) // TODO: Create a similar trange for orange to prevent snowflake of self check. @@ -441,10 +445,10 @@ var/dir2 = 0 var/dir3 = 0 switch(direction) - if(NORTH || SOUTH) + if(NORTH, SOUTH) dir2 = 4 dir3 = 8 - if(EAST || WEST) + if(EAST, WEST) dir2 = 1 dir3 = 2 var/turf/T2 = T @@ -581,9 +585,7 @@ return /obj/machinery/singularity/proc/pulse() - for(var/obj/machinery/power/rad_collector/R in rad_collectors) - if(get_dist(R, src) <= 15) //Better than using orange() every process. - R.receive_pulse(energy) + emitted_harvestable_radiation(get_turf(src), energy, range = 15) /obj/machinery/singularity/proc/on_capture() chained = 1 diff --git a/code/modules/power/smes.dm b/code/modules/power/smes.dm index 6c09eb0d19d..df2d6fc2e58 100644 --- a/code/modules/power/smes.dm +++ b/code/modules/power/smes.dm @@ -15,6 +15,9 @@ var/list/smes_list = list() starting_terminal = 1 +/obj/machinery/power/battery/smes/pristine + charge = 0 + /obj/machinery/power/battery/smes/New() . = ..() @@ -46,6 +49,7 @@ var/list/smes_list = list() /obj/machinery/power/battery/smes/initialize() ..() + connect_to_network() spawn(5) if(!terminal) stat |= BROKEN @@ -74,8 +78,8 @@ var/list/smes_list = list() terminal.connect_to_network() user.visible_message(\ - "[user.name] has added cables to the SMES!",\ - "You added cables the SMES.") + "[user.name] made a terminal for the SMES.",\ + "You made a terminal for the SMES.") src.stat = 0 return 1 else if(iswirecutter(W) && terminal) @@ -83,8 +87,8 @@ var/list/smes_list = list() if(T.intact) to_chat(user, "You must remove the floor plating in front of the SMES first.") return - to_chat(user, "You begin to cut the cables...") - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + to_chat(user, "You begin to dismantle the SMES terminal...") + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) if (do_after(user, src, 50) && panel_open && terminal && !T.intact) if (prob(50) && electrocute_mob(usr, terminal.get_powernet(), terminal)) spark(src, 5) diff --git a/code/modules/power/solar.dm b/code/modules/power/solar.dm index b373bc52944..26a2a75acd6 100644 --- a/code/modules/power/solar.dm +++ b/code/modules/power/solar.dm @@ -51,14 +51,14 @@ var/list/solars_list = list() anchored = 1 user.visible_message("[user] wrenches [src] down.", \ "You wrench [src] down.") - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 75, 1) + playsound(src, 'sound/items/Ratchet.ogg', 75, 1) return 1 else if(iswrench(W)) anchored = 0 user.visible_message("[user] unwrenches [src] from the ground.", \ "You unwrench [src] from the ground.") - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 75, 1) + playsound(src, 'sound/items/Ratchet.ogg', 75, 1) return 1 if(istype(W, /obj/item/stack/sheet/glass)) @@ -66,7 +66,7 @@ var/list/solars_list = list() if(S.amount >= 2) glass_type = W.type S.use(2) - playsound(get_turf(src), 'sound/machines/click.ogg', 50, 1) + playsound(src, 'sound/machines/click.ogg', 50, 1) user.visible_message("[user] carefully adds glass to [src].", \ "You carefully add glass to [src].") if(tracker) diff --git a/code/modules/power/solars/control.dm b/code/modules/power/solars/control.dm index c114979f75e..b80246097f1 100644 --- a/code/modules/power/solars/control.dm +++ b/code/modules/power/solars/control.dm @@ -83,7 +83,7 @@ /obj/machinery/power/solar/control/attackby(I as obj, user as mob) if(isscrewdriver(I)) - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 50, 1) if(do_after(user, src, 20)) if(src.stat & BROKEN) visible_message("[user] clears the broken monitor off of [src].", \ diff --git a/code/modules/power/solars/panel.dm b/code/modules/power/solars/panel.dm index 950b257e107..da9e97c2890 100644 --- a/code/modules/power/solars/panel.dm +++ b/code/modules/power/solars/panel.dm @@ -37,12 +37,12 @@ var/turf/T = get_turf(src) var/obj/item/stack/sheet/glass/G = solar_assembly.glass_type to_chat(user, "You begin taking the [initial(G.name)] off the [src].") - playsound(get_turf(src), 'sound/machines/click.ogg', 50, 1) + playsound(src, 'sound/machines/click.ogg', 50, 1) if(do_after(user, src, 50)) if(solar_assembly) solar_assembly.forceMove(T) solar_assembly.give_glass() - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) user.visible_message("[user] takes the [initial(G.name)] off the [src].",\ "You take the [initial(G.name)] off the [src].") qdel(src) diff --git a/code/modules/power/terminal.dm b/code/modules/power/terminal.dm index 5f17d08fa44..88a6730e5be 100644 --- a/code/modules/power/terminal.dm +++ b/code/modules/power/terminal.dm @@ -13,9 +13,12 @@ anchored = 1 layer = WIRE_TERMINAL_LAYER - holomap = TRUE - auto_holomap = TRUE +/obj/machinery/power/terminal/supports_holomap() + return TRUE +/obj/machinery/power/terminal/initialize() + ..() + add_self_to_holomap() /obj/machinery/power/terminal/New() ..() @@ -71,7 +74,7 @@ return 0 to_chat(user, "You start adding cable to \the [src].") - playsound(get_turf(src), 'sound/items/zip.ogg', 100, 1) + playsound(src, 'sound/items/zip.ogg', 100, 1) if (do_after(user, src, 100) && !T.intact && can_attach_terminal(user)) //Shock chance diff --git a/code/modules/power/treadmill.dm b/code/modules/power/treadmill.dm index 58505f1952d..094c78d807d 100644 --- a/code/modules/power/treadmill.dm +++ b/code/modules/power/treadmill.dm @@ -59,7 +59,7 @@ var/cached_temp = runner.bodytemperature if(runner.burn_calories(HUNGER_FACTOR*2)) flick("treadmill-running", src) - playsound(get_turf(src), 'sound/machines/click.ogg', 50, 1) + playsound(src, 'sound/machines/click.ogg', 50, 1) var/calc = DEFAULT_BUMP_ENERGY * power_efficiency * runner.treadmill_speed if(runner.reagents) //Sanity for(var/datum/reagent/R in runner.reagents.reagent_list) diff --git a/code/modules/power/turbine.dm b/code/modules/power/turbine.dm index 9a5e91ba617..7e3b63fd536 100644 --- a/code/modules/power/turbine.dm +++ b/code/modules/power/turbine.dm @@ -67,9 +67,7 @@ return rpm = 0.9* rpm + 0.1 * rpmtarget var/datum/gas_mixture/environment = inturf.return_air() - var/transfer_moles = environment.total_moles()/10 - //var/transfer_moles = rpm/10000*capacity - var/datum/gas_mixture/removed = inturf.remove_air(transfer_moles) + var/datum/gas_mixture/removed = environment.remove_volume(CELL_VOLUME / 10) gas_contained.merge(removed) rpm = max(0, rpm - (rpm*rpm)/COMPFRICTION) @@ -221,7 +219,7 @@ /obj/machinery/computer/turbine_computer/attackby(I as obj, user as mob) if(isscrewdriver(I)) - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 50, 1) if(do_after(user, src, 20)) if (src.stat & BROKEN) to_chat(user, "The broken glass falls out.") diff --git a/code/modules/projectiles/ammunition.dm b/code/modules/projectiles/ammunition.dm index 8f8595314a9..6cd1244151c 100644 --- a/code/modules/projectiles/ammunition.dm +++ b/code/modules/projectiles/ammunition.dm @@ -59,7 +59,7 @@ var/list/stored_ammo = list() var/ammo_type = "/obj/item/ammo_casing/a357" var/exact = 1 //whether or not the item only takes ammo_type, or also subtypes. Set to 1 to only take the specified ammo - var/caliber = "357" //lets us define what magazines can go into guns + var/caliber = POINT357 //lets us define what magazines can go into guns var/max_ammo = 7 var/starting_ammo = -1 //-1 makes it spawn the max ammo, 0 and above makes it spawn that number var/multiple_sprites = 0 //if it has multiple sprites. Please sprite more than 2 sprites if you set this to true, you fricks diff --git a/code/modules/projectiles/ammunition/boxes.dm b/code/modules/projectiles/ammunition/boxes.dm index e49710c28db..b8f0a7c7b3f 100644 --- a/code/modules/projectiles/ammunition/boxes.dm +++ b/code/modules/projectiles/ammunition/boxes.dm @@ -59,7 +59,7 @@ icon_state = "9mmred" origin_tech = Tc_COMBAT + "=2" ammo_type = "/obj/item/ammo_casing/c45" - caliber = ".45" + caliber = POINT45 max_ammo = 24 /obj/item/ammo_storage/box/c45/practice @@ -80,7 +80,7 @@ icon_state = "9mmred" origin_tech = Tc_COMBAT + "=2" ammo_type = "/obj/item/ammo_casing/c380auto" - caliber = ".380AUTO" + caliber = POINT380 max_ammo = 30 /obj/item/ammo_storage/box/b380auto/practice @@ -94,7 +94,7 @@ desc = "A box of .380AUTO rubber bullets. Holds 30 rounds." icon_state = "9mmblue" ammo_type = "/obj/item/ammo_casing/c380auto/rubber" - + /obj/item/ammo_storage/box/BMG50 name = "ammo box (.50 BMG)" icon_state = "50BMG" diff --git a/code/modules/projectiles/ammunition/bullets.dm b/code/modules/projectiles/ammunition/bullets.dm index 05911313fa4..6c35db596fd 100644 --- a/code/modules/projectiles/ammunition/bullets.dm +++ b/code/modules/projectiles/ammunition/bullets.dm @@ -1,93 +1,93 @@ /obj/item/ammo_casing/a357 desc = "A .357 bullet casing." - caliber = "357" + caliber = POINT357 projectile_type = "/obj/item/projectile/bullet" w_type = RECYK_METAL /obj/item/ammo_casing/a50 desc = "A .50AE bullet casing." - caliber = ".50" + caliber = POINT50 projectile_type = "/obj/item/projectile/bullet" w_type = RECYK_METAL /obj/item/ammo_casing/a418 desc = "A .418 bullet casing." - caliber = "357" + caliber = POINT357 projectile_type = "/obj/item/projectile/bullet/suffocationbullet" w_type = RECYK_METAL /obj/item/ammo_casing/a75 desc = "A .75 bullet casing." - caliber = "75" + caliber = POINT75 projectile_type = "/obj/item/projectile/bullet/gyro" w_type = RECYK_METAL /obj/item/ammo_casing/a666 desc = "A .666 bullet casing." - caliber = "357" + caliber = POINT357 projectile_type = "/obj/item/projectile/bullet/cyanideround" w_type = RECYK_METAL /obj/item/ammo_casing/c38 desc = "A .38 bullet casing." - caliber = "38" + caliber = POINT38 projectile_type = "/obj/item/projectile/bullet/weakbullet" w_type = RECYK_METAL /* Not entirely ready to be implemented yet. Get a server vote on bringing these in /obj/item/ammo_casing/c38/lethal desc = "A .38 bullet casing. This is the lethal variant." - caliber = "38" + caliber = POINT38 projectile_type = "/obj/item/projectile/bullet" //HAHA, why is this a good idea w_type = RECYK_METAL */ /obj/item/ammo_casing/c9mm desc = "A 9mm bullet casing." - caliber = "9mm" + caliber = MM9 projectile_type = "/obj/item/projectile/bullet/midbullet2" w_type = RECYK_METAL /obj/item/ammo_casing/c45 desc = "A .45 bullet casing." - caliber = ".45" + caliber = POINT45 projectile_type = "/obj/item/projectile/bullet/fourtyfive" /obj/item/ammo_casing/c45/practice desc = "A .45 practice bullet casing." - caliber = ".45" + caliber = POINT45 projectile_type = "/obj/item/projectile/bullet/fourtyfive/practice" icon_state = "s-p-casing" /obj/item/ammo_casing/c45/rubber desc = "A .45 rubber bullet casing." - caliber = ".45" + caliber = POINT45 projectile_type = "/obj/item/projectile/bullet/fourtyfive/rubber" icon_state = "s-r-casing" /obj/item/ammo_casing/c380auto desc = "A .380AUTO bullet casing." - caliber = ".380AUTO" + caliber = POINT380 projectile_type = "/obj/item/projectile/bullet/auto380" /obj/item/ammo_casing/c380auto/practice desc = "A .380AUTO practice bullet casing." - caliber = ".380AUTO" + caliber = POINT380 projectile_type = "/obj/item/projectile/bullet/auto380/practice" icon_state = "s-p-casing" /obj/item/ammo_casing/c380auto/rubber desc = "A .380AUTO rubber bullet casing." - caliber = ".380AUTO" + caliber = POINT380 projectile_type = "/obj/item/projectile/bullet/auto380/rubber" icon_state = "s-r-casing" - + /obj/item/ammo_casing/a12mm desc = "A 12mm bullet casing." - caliber = "12mm" + caliber = MM12 projectile_type = "/obj/item/projectile/bullet/midbullet" w_type = RECYK_METAL @@ -102,7 +102,7 @@ name = "shotgun shell" desc = "A 12 gauge slug." icon_state = "gshell" - caliber = "shotgun" + caliber = GAUGE12 projectile_type = "/obj/item/projectile/bullet" starting_materials = list(MAT_IRON = 12500) w_type = RECYK_METAL @@ -117,7 +117,7 @@ name = "blank shell" desc = "A blank shell. Does not contain any projectile material." icon_state = "blshell" - projectile_type = "" + projectile_type = "/obj/item/projectile/bullet/blank" starting_materials = list(MAT_IRON = 250) w_type = RECYK_METAL @@ -162,13 +162,13 @@ /obj/item/ammo_casing/a762 desc = "A 7.62 bullet casing." - caliber = "a762" + caliber = POINT762 projectile_type = "/obj/item/projectile/bullet" w_type = RECYK_METAL /obj/item/ammo_casing/BMG50 desc = "A .50 BMG bullet casing." - caliber = ".50BMG" + caliber = BROWNING50 projectile_type = "/obj/item/projectile/bullet/hecate" w_type = RECYK_METAL icon_state = "l-casing" @@ -182,7 +182,7 @@ /obj/item/ammo_casing/a762x55 desc = "A 7.62x55mmR bullet casing." - caliber = "7.62x55" + caliber = POINT762X55 projectile_type = "/obj/item/projectile/bullet/a762x55" w_type = RECYK_METAL icon_state = "762x55-casing-live" diff --git a/code/modules/projectiles/ammunition/flares.dm b/code/modules/projectiles/ammunition/flares.dm index 85af7099ed0..4b4da6655f5 100644 --- a/code/modules/projectiles/ammunition/flares.dm +++ b/code/modules/projectiles/ammunition/flares.dm @@ -5,7 +5,7 @@ name = "flare shell" desc = "Flare shell, shot by flare guns. Contains a flare and little else." icon_state = "flareshell" - caliber = "flare" + caliber = GAUGEFLARE projectile_type = "/obj/item/projectile/flare" starting_materials = list(MAT_IRON = 1000) w_type = RECYK_METAL diff --git a/code/modules/projectiles/ammunition/magazines.dm b/code/modules/projectiles/ammunition/magazines.dm index d28ba6bd7e5..f1e9459d144 100644 --- a/code/modules/projectiles/ammunition/magazines.dm +++ b/code/modules/projectiles/ammunition/magazines.dm @@ -17,6 +17,22 @@ /obj/item/ammo_storage/magazine/mc9mm/empty starting_ammo = 0 +/obj/item/ammo_storage/magazine/beretta + name = "Beretta 92FS magazine (9mm)" + desc = "A magazine designed for the Beretta 92FS. Holds 15 rounds." + icon = 'icons/obj/beretta.dmi' + icon_state = "beretta_mag" + origin_tech = Tc_COMBAT + "=2" + caliber = MM9 + ammo_type = "/obj/item/ammo_casing/c9mm" + exact = 0 + max_ammo = 15 + multiple_sprites = 1 + sprite_modulo = 15 + +/obj/item/ammo_storage/magazine/beretta/empty + starting_ammo = 0 + /obj/item/ammo_storage/magazine/a12mm name = "magazine (12mm)" icon_state = "12mm" @@ -94,7 +110,7 @@ origin_tech = Tc_COMBAT + "=2" ammo_type = "/obj/item/ammo_casing/c45" exact = 0 - caliber = ".45" + caliber = POINT45 max_ammo = 8 multiple_sprites = 1 sprite_modulo = 1 @@ -128,7 +144,7 @@ origin_tech = Tc_COMBAT + "=2" ammo_type = "/obj/item/ammo_casing/c380auto" exact = 0 - caliber = ".380AUTO" + caliber = POINT380 max_ammo = 10 multiple_sprites = 1 sprite_modulo = 2 @@ -153,7 +169,7 @@ /obj/item/ammo_storage/magazine/m380auto/practice/empty starting_ammo = 0 - + /obj/item/ammo_storage/magazine/uzi45 //Uzi mag name = "magazine (.45)" icon_state = "uzi45" diff --git a/code/modules/projectiles/ammunition/rocket.dm b/code/modules/projectiles/ammunition/rocket.dm index 130c594508e..d94efa89c36 100644 --- a/code/modules/projectiles/ammunition/rocket.dm +++ b/code/modules/projectiles/ammunition/rocket.dm @@ -2,7 +2,7 @@ name = "rocket" desc = "Explosive supplement to the syndicate's rocket launcher." icon_state = "rpground" - caliber = "rpg" + caliber = ROCKETGRENADE projectile_type = "/obj/item/projectile/rocket" starting_materials = list(MAT_IRON = 15000) w_type = RECYK_METAL diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index 2a69e9d9336..72a16923645 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -309,9 +309,9 @@ else if(empty_sound) src.visible_message("*click click*") - playsound(get_turf(src), empty_sound, 100, 1) + playsound(src, empty_sound, 100, 1) -/obj/item/weapon/gun/attack(mob/living/M as mob, mob/living/user as mob, def_zone) +/obj/item/weapon/gun/attack(mob/living/M, mob/living/user, def_zone) //Suicide handling. if (M == user && user.zone_sel.selecting == "mouth" && !mouthshoot) if(istype(M.wear_mask, /obj/item/clothing/mask/happy)) @@ -341,7 +341,7 @@ user.stat=2 // Just to be sure user.death() var/suicidesound = pick('sound/misc/suicide/suicide1.ogg','sound/misc/suicide/suicide2.ogg','sound/misc/suicide/suicide3.ogg','sound/misc/suicide/suicide4.ogg','sound/misc/suicide/suicide5.ogg','sound/misc/suicide/suicide6.ogg') - playsound(get_turf(src), pick(suicidesound), 10, channel = 125) + playsound(src, pick(suicidesound), 10, channel = 125) log_attack("[key_name(user)] committed suicide with \the [src].") user.attack_log += "\[[time_stamp()]\] [user.real_name] committed suicide with \the [src]" else @@ -403,3 +403,16 @@ return FALSE else return TRUE + +/obj/item/weapon/gun/attackby(var/obj/item/A, mob/user) + if(istype(A, /obj/item/weapon/gun)) + var/obj/item/weapon/gun/G = A + if(isHandgun() && G.isHandgun()) + var/obj/item/weapon/gun/akimbo/AA = new /obj/item/weapon/gun/akimbo(get_turf(src),src,G) + if(user.drop_item(G, AA) && user.drop_item(src, AA)) + user.put_in_hands(AA) + AA.update_icon(user) + else + to_chat(user, "You can not combine \the [G] and \the [src].") + qdel(AA) + ..() diff --git a/code/modules/projectiles/guns/akimbo.dm b/code/modules/projectiles/guns/akimbo.dm new file mode 100644 index 00000000000..ec62f7c87c1 --- /dev/null +++ b/code/modules/projectiles/guns/akimbo.dm @@ -0,0 +1,66 @@ +/obj/item/weapon/gun/akimbo + name = "akimbo weapons" + var/obj/item/weapon/gun/left + var/obj/item/weapon/gun/right + flags = FPRINT | TWOHANDABLE | MUSTTWOHAND + +/obj/item/weapon/gun/akimbo/New(loc, var/obj/item/weapon/gun/in_left, var/obj/item/weapon/gun/in_right) + left = in_left + right = in_right + name = "\a [in_left] and \a [in_right]" + ..() + +/obj/item/weapon/gun/akimbo/dropped(mob/user) + Break() + ..() + +/obj/item/weapon/gun/akinbo/pickup(mob/user) + update_icon(user) + +/obj/item/weapon/gun/akimbo/afterattack(atom/A, mob/living/user, flag, params, struggle = 0) + if(flag) + return //we're placing gun on a table or in backpack + if(harm_labeled >= min_harm_label) + to_chat(user, "A label sticks the trigger to the trigger guard!")//Such a new feature, the player might not know what's wrong if it doesn't tell them. + + return + if(wielded) + Fire(A,user,params, "struggle" = struggle) + else + to_chat(user, "You must dual-wield \the [src] before you can fire it!") + +/obj/item/weapon/gun/akimbo/Fire(atom/target, mob/living/user, params, reflex = 0, struggle = 0, var/use_shooter_turf = FALSE) + if(!(left.Fire(target,user,params,reflex,struggle,use_shooter_turf)) || !(right.Fire(target,user,params,reflex,struggle,use_shooter_turf))) + Break() + return + update_icon(user) + +/obj/item/weapon/gun/akimbo/proc/Break() + var/mob/living/user = isliving(loc)? loc : null + if(left && right) + left.forceMove(get_turf(src)) + right.forceMove(get_turf(src)) + if(user) + user.drop_item(src, force_drop = TRUE) + user.put_in_hands(left) + user.put_in_hands(right) + left = null + right = null + qdel(src) + +/obj/item/weapon/gun/akimbo/update_icon(mob/user) + //right over left + icon = left.icon + icon_state = left.icon_state + item_state = left.item_state + if(inhand_states != left.inhand_states) + inhand_states = left.inhand_states + overlays += image("icon" = right.icon, "icon_state" = right.icon_state, "pixel_x" = 6, "pixel_y" = -5) + if(wielded) + wielded.icon = right.icon + wielded.icon_state = right.icon_state + wielded.item_state = right.item_state + if(wielded.inhand_states != right.inhand_states) + wielded.inhand_states = right.inhand_states + if(user) + user.update_inv_hands() \ No newline at end of file diff --git a/code/modules/projectiles/guns/energy.dm b/code/modules/projectiles/guns/energy.dm index 5b5a2389c2a..f4a04e0e333 100644 --- a/code/modules/projectiles/guns/energy.dm +++ b/code/modules/projectiles/guns/energy.dm @@ -10,6 +10,7 @@ var/projectile_type = "/obj/item/projectile/beam/practice" var/modifystate var/charge_states = 1 //if the gun changes icon states depending on charge, this is 1. Uses a var so it can be changed easily + var/icon_charge_multiple = 25 //Spacing of the charge level sprites /obj/item/weapon/gun/energy/emp_act(severity) power_supply.use(round(power_supply.maxcharge / (severity*2))) @@ -26,7 +27,7 @@ if(!projectile_type) return 0 return 1 - + /obj/item/weapon/gun/energy/process_chambered() if(in_chamber) return 1 @@ -51,9 +52,9 @@ ratio = Clamp(ratio, 0, 100) //Value between 0 and 100 if(ratio >= 50) - ratio = Floor(ratio, 25) + ratio = Floor(ratio, icon_charge_multiple) else - ratio = Ceiling(ratio, 25) + ratio = Ceiling(ratio, icon_charge_multiple) if(modifystate && charge_states) icon_state = "[modifystate][ratio]" diff --git a/code/modules/projectiles/guns/energy/special.dm b/code/modules/projectiles/guns/energy/special.dm index 07442ace2be..ecaf975b462 100644 --- a/code/modules/projectiles/guns/energy/special.dm +++ b/code/modules/projectiles/guns/energy/special.dm @@ -205,17 +205,17 @@ "YOUR TIME HAS NOT COME, YET.",\ "YOUR SOUL MAY BELONG TO [uppertext(ticker.Bible_deity_name)] BUT YOU BELONG TO ME.")) - playsound(get_turf(src), get_sfx("soulstone"), 50,1) + playsound(src, get_sfx("soulstone"), 50,1) switch(raisetype) if(ZOMBIE) - var/mob/living/simple_animal/hostile/necro/zombie/turned/T = new(get_turf(target), user, H.mind) + var/mob/living/simple_animal/hostile/necro/zombie/turned/T = new(get_turf(target), user, H) T.get_clothes(H, T) T.name = H.real_name T.host = H H.loc = null if(SKELETON) - new /mob/living/simple_animal/hostile/necro/skeleton(get_turf(target), user, H.mind) + new /mob/living/simple_animal/hostile/necro/skeleton(get_turf(target), user, H) H.gib() charges-- @@ -413,7 +413,7 @@ projectile_type = "/obj/item/projectile/energy/floramut/emag" to_chat(user, "You short out the safety limit of the [src.name]!") desc += " It seems to have it's safety features de-activated." - playsound(get_turf(user), 'sound/effects/sparks4.ogg', 50, 1) + playsound(user, 'sound/effects/sparks4.ogg', 50, 1) modifystate = "floraemag" update_icon() @@ -504,6 +504,7 @@ obj/item/weapon/gun/energy/staff/focus/attack_self(mob/living/user as mob) projectile_type = "/obj/item/projectile/kinetic" cell_type = "/obj/item/weapon/cell/crap" charge_cost = 50 + icon_charge_multiple = 20 var/overheat = 0 var/recent_reload = 1 /* @@ -523,10 +524,6 @@ obj/item/weapon/gun/energy/staff/focus/attack_self(mob/living/user as mob) update_icon() return -// /vg/ - Broken until we update to /tg/ guncode. -/obj/item/weapon/gun/energy/kinetic_accelerator/update_icon() - return - /obj/item/weapon/gun/energy/kinetic_accelerator/cyborg name = "proto-kinetic accelerator" desc = "According to Nanotrasen accounting, this is mining equipment. It's been modified for extreme power output to crush rocks, but often serves as a miner's first defense against hostile alien life; it's not very powerful unless used in a low pressure environment." @@ -651,10 +648,10 @@ obj/item/weapon/gun/energy/ricochet/Fire(atom/target as mob|obj|turf|area, mob/l pumping = 1 power_supply.charge = min(power_supply.charge + 200,power_supply.maxcharge) if(power_supply.charge >= power_supply.maxcharge) - playsound(get_turf(src), 'sound/machines/click.ogg', 25, 1) + playsound(src, 'sound/machines/click.ogg', 25, 1) to_chat(user, "You pull the pump at the back of the gun. Looks like the inner battery is fully charged now.") else - playsound(get_turf(src), 'sound/weapons/bison_reload.ogg', 25, 1) + playsound(src, 'sound/weapons/bison_reload.ogg', 25, 1) to_chat(user, "You pull the pump at the back of the gun.") sleep(5) pumping = 0 @@ -696,7 +693,7 @@ obj/item/weapon/gun/energy/ricochet/Fire(atom/target as mob|obj|turf|area, mob/l /obj/item/weapon/gun/energy/polarstar/New() ..() - playsound(get_turf(src), 'sound/weapons/spur_spawn.ogg', 50, 0, null, FALLOFF_SOUNDS, 0) + playsound(src, 'sound/weapons/spur_spawn.ogg', 50, 0, null, FALLOFF_SOUNDS, 0) /obj/item/weapon/gun/energy/polarstar/afterattack(atom/A as mob|obj|turf|area, mob/living/user as mob|obj, flag, params, struggle = 0) levelChange() diff --git a/code/modules/projectiles/guns/energy/tag.dm b/code/modules/projectiles/guns/energy/tag.dm index 1b0219860a4..3c7446ba6be 100644 --- a/code/modules/projectiles/guns/energy/tag.dm +++ b/code/modules/projectiles/guns/energy/tag.dm @@ -26,7 +26,7 @@ return TRUE /obj/item/weapon/gun/energy/tag/proc/score() - playsound(get_turf(src), 'sound/weapons/quake.ogg', 60) + playsound(src, 'sound/weapons/quake.ogg', 60) score++ /obj/item/weapon/gun/energy/tag/examine(mob/user) diff --git a/code/modules/projectiles/guns/projectile.dm b/code/modules/projectiles/guns/projectile.dm index 00dfc4ce4cd..eba19d1f33b 100644 --- a/code/modules/projectiles/guns/projectile.dm +++ b/code/modules/projectiles/guns/projectile.dm @@ -6,7 +6,7 @@ desc = "A classic revolver. Uses .357 ammo." name = "revolver" icon_state = "revolver" - caliber = list("357" = 1) + caliber = list(POINT357 = 1) origin_tech = Tc_COMBAT + "=2;" + Tc_MATERIALS + "=2" w_class = W_CLASS_MEDIUM starting_materials = list(MAT_IRON = 1000) @@ -21,7 +21,7 @@ var/mag_type = "" var/mag_drop_sound ='sound/weapons/magdrop_1.ogg' var/automagdrop_delay_time = 5 // delays the automagdrop - + var/spawn_mag = TRUE var/gun_flags = EMPTYCASINGS //Yay, flags /obj/item/weapon/gun/projectile/isHandgun() //fffuuuuuuck non-abstract base types @@ -29,7 +29,7 @@ /obj/item/weapon/gun/projectile/New() ..() - if(mag_type && load_method == 2) + if(mag_type && load_method == 2 && spawn_mag) stored_magazine = new mag_type(src) chamber_round() else @@ -146,13 +146,13 @@ /obj/item/weapon/gun/projectile/can_discharge() var/obj/item/ammo_casing/AC = getAC() if(in_chamber) - return 1 + return 1 if(isnull(AC) || !istype(AC)) return 0 else return 1 - - + + /obj/item/weapon/gun/projectile/attackby(var/obj/item/A as obj, mob/user as mob) if(istype(A, /obj/item/gun_part/silencer) && src.gun_flags &SILENCECOMP) if(!user.is_holding_item(src)) //if we're not in his hands @@ -189,18 +189,18 @@ if(user.drop_item(AC, src)) chambered = AC num_loaded++ - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 25, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 25, 1) else if(getAmmo() < max_shells && load_method != MAGAZINE) if(user.drop_item(AC, src)) loaded += AC num_loaded++ - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 25, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 25, 1) if(num_loaded) to_chat(user, "You load [num_loaded] shell\s into \the [src]!") A.update_icon() update_icon() - return + ..() /obj/item/weapon/gun/projectile/attack_self(mob/user as mob) if (target) diff --git a/code/modules/projectiles/guns/projectile/automatic.dm b/code/modules/projectiles/guns/projectile/automatic.dm index e1497a93a7a..4d250465829 100644 --- a/code/modules/projectiles/guns/projectile/automatic.dm +++ b/code/modules/projectiles/guns/projectile/automatic.dm @@ -6,7 +6,7 @@ inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') w_class = W_CLASS_MEDIUM max_shells = 18 - caliber = list("9mm" = 1) + caliber = list(MM9 = 1) origin_tech = Tc_COMBAT + "=4;" + Tc_MATERIALS + "=2" ammo_type = "/obj/item/ammo_casing/c9mm" automatic = 1 @@ -86,7 +86,7 @@ w_class = W_CLASS_MEDIUM max_shells = 10 burst_count = 3 - caliber = list(".45" = 1) + caliber = list(POINT45 = 1) origin_tech = Tc_COMBAT + "=5;" + Tc_MATERIALS + "=2;" + Tc_SYNDICATE + "=8" ammo_type = "/obj/item/ammo_casing/c45" mag_type = "/obj/item/ammo_storage/magazine/uzi45" @@ -103,7 +103,7 @@ w_class = W_CLASS_MEDIUM max_shells = 20 burst_count = 4 - caliber = list("12mm" = 1) + caliber = list(MM12 = 1) origin_tech = Tc_COMBAT + "=5;" + Tc_MATERIALS + "=2;" + Tc_SYNDICATE + "=8" ammo_type = "/obj/item/ammo_casing/a12mm" mag_type = "/obj/item/ammo_storage/magazine/a12mm/ops" @@ -132,7 +132,7 @@ w_class = W_CLASS_MEDIUM max_shells = 20 burst_count = 4 - caliber = list("12mm" = 1) + caliber = list(MM12 = 1) ammo_type = "/obj/item/ammo_casing/a12mm/assault" mag_type = "/obj/item/ammo_storage/magazine/a12mm" fire_sound = 'sound/weapons/Gunshot_c20.ogg' @@ -153,7 +153,7 @@ slot_flags = 0 max_shells = 50 burst_count = 5 - caliber = list("a762" = 1) + caliber = list(POINT762 = 1) origin_tech = Tc_COMBAT + "=5;" + Tc_MATERIALS + "=1;" + Tc_SYNDICATE + "=2" ammo_type = "/obj/item/ammo_casing/a762" mag_type = "/obj/item/ammo_storage/magazine/a762" diff --git a/code/modules/projectiles/guns/projectile/banannon.dm b/code/modules/projectiles/guns/projectile/banannon.dm index 025d17a74ea..a5240294d79 100644 --- a/code/modules/projectiles/guns/projectile/banannon.dm +++ b/code/modules/projectiles/guns/projectile/banannon.dm @@ -72,7 +72,7 @@ if(user.drop_item(W)) current_ammo++ chamber_if_possible() - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 25, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 25, 1) qdel(W) update_icon() diff --git a/code/modules/projectiles/guns/projectile/constructable/blastcannon.dm b/code/modules/projectiles/guns/projectile/constructable/blastcannon.dm index 0b548a353a2..0d7e01a8965 100644 --- a/code/modules/projectiles/guns/projectile/constructable/blastcannon.dm +++ b/code/modules/projectiles/guns/projectile/constructable/blastcannon.dm @@ -146,9 +146,9 @@ range = min(range, MAX_EXPLOSION_RANGE) var/turf/epicenter = get_turf(loc) - var/transfer_moles1 = (bomb.tank_one.air_contents.return_pressure() * bomb.tank_one.air_contents.volume)/(bomb.tank_one.air_contents.temperature * R_IDEAL_GAS_EQUATION) + var/transfer_moles1 = (bomb.tank_one.air_contents.return_pressure() * bomb.tank_one.air_contents.volume) / (bomb.tank_one.air_contents.temperature * R_IDEAL_GAS_EQUATION) bomb.tank_one.air_contents.remove(transfer_moles1) - var/transfer_moles2 = (bomb.tank_two.air_contents.return_pressure() * bomb.tank_two.air_contents.volume)/(bomb.tank_two.air_contents.temperature * R_IDEAL_GAS_EQUATION) + var/transfer_moles2 = (bomb.tank_two.air_contents.return_pressure() * bomb.tank_two.air_contents.volume) / (bomb.tank_two.air_contents.temperature * R_IDEAL_GAS_EQUATION) bomb.tank_two.air_contents.remove(transfer_moles2) bomb_air_contents_1 = null @@ -214,4 +214,4 @@ bomb.damaged = 1 else qdel(B) - in_chamber = null \ No newline at end of file + in_chamber = null diff --git a/code/modules/projectiles/guns/projectile/constructable/blinder.dm b/code/modules/projectiles/guns/projectile/constructable/blinder.dm index 5c3a6e7720c..3bdf76b12c2 100644 --- a/code/modules/projectiles/guns/projectile/constructable/blinder.dm +++ b/code/modules/projectiles/guns/projectile/constructable/blinder.dm @@ -1,7 +1,7 @@ /obj/item/device/blinder name = "camera" icon = 'icons/obj/items.dmi' - desc = "A polaroid camera. The film chamber is filled with wire for some reason." + desc = "A polaroid camera." icon_state = "polaroid" item_state = "polaroid" w_class = W_CLASS_SMALL @@ -12,43 +12,60 @@ starting_materials = list(MAT_IRON = 2000) w_type = RECYK_ELECTRONIC var/cell = null - var/bulb = 1 - var/burnedout = 0 + var/obj/item/weapon/light/bulb/flashbulb = null + var/start_with_bulb = TRUE + var/decon_path = /obj/item/device/camera var/powercost = 10000 + var/base_desc = "" /obj/item/device/blinder/Destroy() if(cell) qdel(cell) cell = null + if(flashbulb) + qdel(flashbulb) + flashbulb = null ..() -/obj/item/device/blinder/New() +/obj/item/device/blinder/New(var/empty = FALSE) ..() + if(empty == TRUE) + start_with_bulb = FALSE + if(start_with_bulb) + flashbulb = new(src) update_verbs() + base_desc = desc + update_desc() + +/obj/item/device/blinder/proc/update_desc() + if(cell) + desc = "[base_desc] There is a power cell in the film chamber for some reason." + else + desc = "[base_desc] The film chamber is filled with wire for some reason." /obj/item/device/blinder/examine(mob/user) ..() - if(bulb && burnedout) - to_chat(user, "\The [src]'s flash bulb is broken.") - else if (!bulb) - to_chat(user, "\The [src] appears to be missing a flash bulb.") + if(flashbulb && flashbulb.status >= LIGHT_BROKEN) + to_chat(user, "\The [src]'s flashbulb is broken.") + else if (!flashbulb) + to_chat(user, "\The [src] appears to be missing a flashbulb.") /obj/item/device/blinder/attack_self(mob/user as mob) - if(!bulb || burnedout || !cell) + if(!flashbulb || flashbulb.status >= LIGHT_BROKEN || !cell) if (user) user.visible_message("*click click*", "*click*") playsound(user, 'sound/weapons/empty.ogg', 100, 1) else src.visible_message("*click click*") - playsound(get_turf(src), 'sound/weapons/empty.ogg', 100, 1) + playsound(src, 'sound/weapons/empty.ogg', 100, 1) return if(cell) var/obj/item/weapon/cell/C = cell if(C.charge < powercost) - user.visible_message("[user] presses the button on \the [src], but the flash bulb merely flickers.","You press the button on \the [src], but the flash bulb merely flickers.") - to_chat(user, "There's not enough energy in the cell to power the flash bulb!") - playsound(get_turf(src), 'sound/weapons/empty.ogg', 100, 1) + user.visible_message("[user] presses the button on \the [src], but the flashbulb merely flickers.","You press the button on \the [src], but the flashbulb merely flickers.") + to_chat(user, "There's not enough energy in the cell to power the flashbulb!") + playsound(src, 'sound/weapons/empty.ogg', 100, 1) return var/flash_turf = get_turf(src) @@ -62,12 +79,13 @@ to_chat(user, "\The [src]'s flash bulb shatters!") C.charge -= powercost + C.updateicon() - burnedout = 1 + flashbulb.shatter(verbose = FALSE) update_verbs() /obj/item/device/blinder/proc/flash(var/turf/T , var/mob/living/M) - playsound(get_turf(src), 'sound/weapons/flash.ogg', 100, 1) + playsound(src, 'sound/weapons/flash.ogg', 100, 1) M.flash_eyes(visual = 1) @@ -87,7 +105,7 @@ verbs += /obj/item/device/blinder/verb/remove_cell else verbs -= /obj/item/device/blinder/verb/remove_cell - if(bulb && burnedout) + if(flashbulb && flashbulb.status >= LIGHT_BROKEN) verbs += /obj/item/device/blinder/verb/remove_bulb else verbs -= /obj/item/device/blinder/verb/remove_bulb @@ -108,7 +126,7 @@ C.forceMove(usr.loc) usr.put_in_hands(C) cell = null - desc = "A polaroid camera. The film chamber is filled with wire for some reason." + update_desc() to_chat(usr, "You remove \the [C] from \the [src].") update_verbs() @@ -121,16 +139,13 @@ to_chat(usr, "You can't do that while unconscious.") return - if(!bulb) + if(!flashbulb) return else - var/obj/item/weapon/light/bulb/B = new (get_turf(usr)) - B.status = LIGHT_BROKEN - B.update() - usr.put_in_hands(B) - bulb = 0 - burnedout = 0 - to_chat(usr, "You remove the broken [B.name] from \the [src].") + flashbulb.forceMove(get_turf(loc)) + usr.put_in_hands(flashbulb) + to_chat(usr, "You remove the broken [flashbulb.name] from \the [src].") + flashbulb = null update_verbs() /obj/item/device/blinder/attackby(obj/item/weapon/W, mob/user) @@ -143,12 +158,12 @@ return 1 cell = W user.visible_message("[user] inserts \the [W] into \the [src].","You insert \the [W] into \the [src].") - desc = "A polaroid camera. There is a power cell in the film chamber for some reason." + update_desc() update_verbs() if(istype(W, /obj/item/weapon/light/bulb)) - if(bulb) - if(burnedout) + if(flashbulb) + if(flashbulb.status >= LIGHT_BROKEN) to_chat(user, "You need to remove the damaged bulb first.") return else @@ -161,9 +176,11 @@ else if(B.status == LIGHT_BURNED) to_chat(user, "That [B.name] is burned out, it won't function in \the [src].") return - bulb = 1 + if(!user.drop_item(W, src)) + to_chat(user, "You can't let go of \the [W]!") + return 1 + flashbulb = B user.visible_message("[user] inserts \the [W] into \the [src].","You insert \the [W] into \the [src].") - qdel(W) update_verbs() if(istype(W, /obj/item/device/camera_film)) @@ -178,10 +195,18 @@ playsound(user, 'sound/items/Wirecutter.ogg', 50, 1) if(src.loc == user) user.drop_item(src, force_drop = 1) - var/obj/item/device/camera/I = new (get_turf(user)) + var/obj/item/device/camera/I = new decon_path(get_turf(user), empty = TRUE) + handle_camera(I) user.put_in_hands(I) else - new /obj/item/device/camera(get_turf(src.loc)) + var/obj/item/device/camera/I = new decon_path(get_turf(loc), empty = TRUE) + handle_camera(I) var/obj/item/stack/cable_coil/C = new (get_turf(user)) C.amount = 5 qdel(src) + +/obj/item/device/blinder/proc/handle_camera(obj/item/device/camera/camera) + if(flashbulb) + camera.flashbulb = flashbulb + flashbulb.forceMove(camera) + flashbulb = null diff --git a/code/modules/projectiles/guns/projectile/constructable/gunsmithing.dm b/code/modules/projectiles/guns/projectile/constructable/gunsmithing.dm index 3ca4a1b43a2..aed9fa6bf94 100644 --- a/code/modules/projectiles/guns/projectile/constructable/gunsmithing.dm +++ b/code/modules/projectiles/guns/projectile/constructable/gunsmithing.dm @@ -409,7 +409,7 @@ if("stock_reservoir_assembly") if(iswrench(W)) to_chat(user, "You securely fasten the fuel reservoir to \the [src].") - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + playsound(src, 'sound/items/Ratchet.ogg', 50, 1) state = "stock_reservoir" update_assembly() if("stock_reservoir") @@ -429,7 +429,7 @@ C.use(5) if(iswrench(W)) to_chat(user, "You loosen the fuel reservoir on \the [src].") - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + playsound(src, 'sound/items/Ratchet.ogg', 50, 1) state = "stock_reservoir_assembly" update_assembly() @@ -456,7 +456,7 @@ if("blunderbuss_assembly") if(isscrewdriver(W)) to_chat(user, "You tighten the igniter to \the [src].") - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 50, 1) if(src.loc == user) user.drop_item(src, force_drop = 1) var/obj/item/weapon/blunderbuss/I = new (get_turf(user)) @@ -470,7 +470,7 @@ if("stock_capacitorbank_assembly") if(isscrewdriver(W)) to_chat(user, "You tighten the wires in \the [src]'s capacitor bank.") - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 50, 1) state = "stock_capacitorbank" update_assembly() if(iswirecutter(W)) @@ -488,7 +488,7 @@ qdel(W) if(isscrewdriver(W)) to_chat(user, "You loosen the wires in \the [src]'s capacitor bank.") - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 50, 1) state = "stock_capacitorbank_assembly" update_assembly() if("stock_capacitorbank_barrel_assembly") @@ -513,7 +513,7 @@ if("railgun_assembly") if(isscrewdriver(W)) to_chat(user, "You secure \the [src]'s triggering mechanism.") - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 50, 1) if(src.loc == user) user.drop_item(src, force_drop = 1) var/obj/item/weapon/gun/projectile/railgun/I = new (get_turf(user)) @@ -593,7 +593,7 @@ if("stock_ansible_amplifier_assembly") if(isscrewdriver(W)) to_chat(user, "You secure \the [src]'s subspace amplifier.") - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 50, 1) state = "stock_ansible_amplifier" update_assembly() if("stock_ansible_amplifier") @@ -605,7 +605,7 @@ if("stock_ansible_amplifier_transmitter_assembly") if(isscrewdriver(W)) to_chat(user, "You secure \the [src]'s subspace transmitter.") - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 50, 1) state = "subspacetunneler_assembly" update_assembly() if("subspacetunneler_assembly") @@ -813,7 +813,7 @@ to_chat(user, "\The [src.name] needs to be turned off first.") return to_chat(user, "You unsecure \the [src.name] from the floor.") - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) + playsound(src, 'sound/items/Ratchet.ogg', 50, 1) power_machines.Remove(src) switch(name) if("capacitor") diff --git a/code/modules/projectiles/guns/projectile/constructable/railgun.dm b/code/modules/projectiles/guns/projectile/constructable/railgun.dm index 6bac5921ad4..3e2af85f6ff 100644 --- a/code/modules/projectiles/guns/projectile/constructable/railgun.dm +++ b/code/modules/projectiles/guns/projectile/constructable/railgun.dm @@ -1,8 +1,3 @@ -#define MEGAWATT 1000000 -#define TEN_MEGAWATTS 10000000 -#define HUNDRED_MEGAWATTS 100000000 -#define GIGAWATT 1000000000 - /obj/item/weapon/gun/projectile/railgun name = "railgun" desc = "A weapon that uses the Lorentz force to propel an armature carrying a projectile to incredible velocities." @@ -165,10 +160,10 @@ if(rails) if(rails_secure) to_chat(user, "You loosen the rail assembly within \the [src].") - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 50, 1) else to_chat(user, "You tighten the rail assembly inside \the [src].") - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 50, 1) rails_secure = !rails_secure else if(istype(W, /obj/item/stack/rods)) diff --git a/code/modules/projectiles/guns/projectile/constructable/subspacetunneler.dm b/code/modules/projectiles/guns/projectile/constructable/subspacetunneler.dm index 2594143fa8e..b8ef2ce256b 100644 --- a/code/modules/projectiles/guns/projectile/constructable/subspacetunneler.dm +++ b/code/modules/projectiles/guns/projectile/constructable/subspacetunneler.dm @@ -52,10 +52,6 @@ /obj/structure/closet/secure_closet/brig, //brig cell closets /obj/machinery/disposal, //disposal bins /obj/machinery/light, //light bulbs and tubes - /obj/machinery/sleep_console, //sleeper consoles - /obj/machinery/sleeper, //sleepers - /obj/machinery/body_scanconsole, //body scanner consoles - /obj/machinery/bodyscanner, //body scanners /obj/machinery/hologram/holopad, //AI holopads /obj/machinery/media/receiver/boombox/wallmount, //sound systems /obj/machinery/keycard_auth, //keycard authentication devices diff --git a/code/modules/projectiles/guns/projectile/constructable/tomahawk.dm b/code/modules/projectiles/guns/projectile/constructable/tomahawk.dm index b2a0bfefb2b..885a4c7bee4 100644 --- a/code/modules/projectiles/guns/projectile/constructable/tomahawk.dm +++ b/code/modules/projectiles/guns/projectile/constructable/tomahawk.dm @@ -67,7 +67,7 @@ if(ismetal) return to_chat(user, "\The [src]'s blade shatters!") - playsound(get_turf(user), "shatter", 50, 1) + playsound(user, "shatter", 50, 1) if(src.loc == user) user.drop_item(src, force_drop = 1) if(istype(src, /obj/item/weapon/hatchet/tomahawk/pipe)) diff --git a/code/modules/projectiles/guns/projectile/flare.dm b/code/modules/projectiles/guns/projectile/flare.dm index a0940da5825..e4110c2ba4b 100644 --- a/code/modules/projectiles/guns/projectile/flare.dm +++ b/code/modules/projectiles/guns/projectile/flare.dm @@ -17,7 +17,7 @@ fire_delay = 10 flags = FPRINT siemens_coefficient = 1 - caliber = list("flare" = 1) + caliber = list(GAUGEFLARE = 1) origin_tech = Tc_COMBAT + "=2;" + Tc_MATERIALS + "=2" ammo_type = "/obj/item/ammo_casing/shotgun/flare" gun_flags = 0 @@ -26,5 +26,5 @@ desc = "An illegal flare gun with a modified hammer, allowing it to fire shotgun shells and flares at dangerous velocities." recoil = 3 fire_delay = 5 //faster, because it's also meant to be a weapon - caliber = list("flare" = 1, "shotgun" = 1) + caliber = list(GAUGEFLARE = 1, GAUGE12 = 1) origin_tech = Tc_COMBAT + "=4;" + Tc_MATERIALS + "=2;" + Tc_SYNDICATE + "=2" \ No newline at end of file diff --git a/code/modules/projectiles/guns/projectile/mahoguny.dm b/code/modules/projectiles/guns/projectile/mahoguny.dm index e91680247e7..81ce2d6dde0 100644 --- a/code/modules/projectiles/guns/projectile/mahoguny.dm +++ b/code/modules/projectiles/guns/projectile/mahoguny.dm @@ -63,5 +63,5 @@ return var/obj/item/stack/sheet/wood/S = W current_ammo++ - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 25, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 25, 1) S.use(1) diff --git a/code/modules/projectiles/guns/projectile/minigun.dm b/code/modules/projectiles/guns/projectile/minigun.dm index 26143acbe2e..332870d3349 100644 --- a/code/modules/projectiles/guns/projectile/minigun.dm +++ b/code/modules/projectiles/guns/projectile/minigun.dm @@ -9,6 +9,7 @@ recoil = 1 slot_flags = null flags = FPRINT | TWOHANDABLE | SLOWDOWN_WHEN_CARRIED + slowdown = MINIGUN_SLOWDOWN_NONWIELDED w_class = W_CLASS_HUGE//we be fuckin huge maaan fire_delay = 0 fire_sound = 'sound/weapons/gatling_fire.ogg' @@ -63,7 +64,7 @@ /obj/item/weapon/gun/gatling/can_discharge() //Why is this gun not a child of gun/projectile? if (current_shells && wielded) return 1 - + /obj/item/weapon/gun/gatling/update_icon() switch(current_shells) if(150 to INFINITY) @@ -107,9 +108,11 @@ item_state = "beegun0" origin_tech = Tc_MATERIALS + "=4;" + Tc_COMBAT + "=6;" + Tc_BIOTECH + "=5" recoil = 0 + var/base_icon_state = "beegun" + var/bug_ammo = /obj/item/projectile/bullet/beegun /obj/item/weapon/gun/gatling/beegun/update_wield(mob/user) - item_state = "beegun[wielded ? 1 : 0]" + item_state = "[base_icon_state][wielded ? 1 : 0]" if(wielded) slowdown = MINIGUN_SLOWDOWN_WIELDED else @@ -121,19 +124,26 @@ if(current_shells) current_shells-- update_icon() - in_chamber = new/obj/item/projectile/bullet/beegun() + in_chamber = new bug_ammo() return 1 return 0 /obj/item/weapon/gun/gatling/beegun/update_icon() switch(current_shells) if(150 to INFINITY) - icon_state = "beegun100" + icon_state = "[base_icon_state]100" if(100 to 149) - icon_state = "beegun75" + icon_state = "[base_icon_state]75" if(50 to 99) - icon_state = "beegun50" + icon_state = "[base_icon_state]50" if(1 to 49) - icon_state = "beegun25" + icon_state = "[base_icon_state]25" else - icon_state = "beegun0" + icon_state = "[base_icon_state]0" + +/obj/item/weapon/gun/gatling/beegun/hornetgun + name = "hornet gun" + desc = "Doesn't actually use .22 Hornet cartridges" + icon_state = "hornetgun" + base_icon_state = "hornetgun" + bug_ammo = /obj/item/projectile/bullet/beegun/hornet diff --git a/code/modules/projectiles/guns/projectile/nagant.dm b/code/modules/projectiles/guns/projectile/nagant.dm index fe1b520f54e..9aa57412661 100644 --- a/code/modules/projectiles/guns/projectile/nagant.dm +++ b/code/modules/projectiles/guns/projectile/nagant.dm @@ -11,7 +11,7 @@ flags = FPRINT siemens_coefficient = 1 slot_flags = SLOT_BACK - caliber = list("7.62x55" = 1) + caliber = list(POINT762X55 = 1) origin_tech = Tc_COMBAT + "=4;" + Tc_MATERIALS + "=2" ammo_type ="/obj/item/ammo_casing/a762x55" var/recentpump = 0 // to prevent spammage diff --git a/code/modules/projectiles/guns/projectile/osipr.dm b/code/modules/projectiles/guns/projectile/osipr.dm index a89426389b7..7a6628da9c3 100644 --- a/code/modules/projectiles/guns/projectile/osipr.dm +++ b/code/modules/projectiles/guns/projectile/osipr.dm @@ -4,7 +4,7 @@ /obj/item/weapon/gun/osipr name = "\improper Overwatch Standard Issue Pulse Rifle" - desc = "Centuries ago those weapons striked fear in all of humanity when the Combine attacked the Earth. Nowadays these are just the best guns that the Syndicate can provide to its Elite Troops with its tight budget." + desc = "Centuries ago those weapons struck fear in all of humanity when the Combine attacked the Earth. Nowadays these are just the best guns that the Syndicate can provide to its Elite Troops with its tight budget." icon = 'icons/obj/gun_experimental.dmi' icon_state = "osipr" item_state = "osipr" @@ -41,7 +41,7 @@ return 1 if (mode & OSIPR_SECONDARY_FIRE && energy_balls) return 1 - + /obj/item/weapon/gun/osipr/process_chambered() if(in_chamber) return 1 @@ -70,7 +70,7 @@ A.forceMove(src) magazine = A update_icon() - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 25, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 25, 1) to_chat(user, "You insert a new magazine.") user.regenerate_icons() @@ -81,7 +81,7 @@ user.u_equip(A,1) qdel(A) energy_balls++ - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 25, 1) + playsound(src, 'sound/items/Deconstruct.ogg', 25, 1) to_chat(user, "You insert \the [A].") else ..() @@ -92,7 +92,7 @@ user.put_in_hands(magazine) magazine = null update_icon() - playsound(get_turf(src), 'sound/machines/click.ogg', 25, 1) + playsound(src, 'sound/machines/click.ogg', 25, 1) to_chat(user, "You remove the magazine.") user.regenerate_icons() else @@ -131,7 +131,7 @@ w_class = W_CLASS_SMALL var/bullets = 10 var/max_bullets = 10 - var/caliber = "osipr" //base icon name + var/caliber = PULSE //base icon name var/bullet_type = /obj/item/projectile/bullet/osipr /obj/item/energy_magazine/New() @@ -157,7 +157,7 @@ w_class = W_CLASS_SMALL bullets = 30 max_bullets = 30 - caliber = "osipr" + caliber = PULSE bullet_type = /obj/item/projectile/bullet/osipr #undef OSIPR_PRIMARY_FIRE diff --git a/code/modules/projectiles/guns/projectile/pistol.dm b/code/modules/projectiles/guns/projectile/pistol.dm index 8fcf8af5d35..6e993c9a081 100644 --- a/code/modules/projectiles/guns/projectile/pistol.dm +++ b/code/modules/projectiles/guns/projectile/pistol.dm @@ -6,7 +6,7 @@ inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') w_class = W_CLASS_MEDIUM max_shells = 10 - caliber = list(".45" = 1) + caliber = list(POINT45 = 1) silenced = 1 origin_tech = Tc_COMBAT + "=2;" + Tc_MATERIALS + "=2;" + Tc_SYNDICATE + "=8" ammo_type = "/obj/item/ammo_casing/c45" @@ -22,7 +22,7 @@ inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') force = 14.0 max_shells = 7 - caliber = list(".50" = 1) + caliber = list(POINT50 = 1) ammo_type ="/obj/item/ammo_casing/a50" mag_type = "/obj/item/ammo_storage/magazine/a50" load_method = 2 @@ -49,7 +49,7 @@ item_state = null inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guninhands_left.dmi', "right_hand" = 'icons/mob/in-hand/right/guninhands_right.dmi') max_shells = 8 - caliber = list("75" = 1) + caliber = list(POINT75 = 1) fire_sound = 'sound/weapons/elecfire.ogg' origin_tech = Tc_COMBAT + "=3" ammo_type = "/obj/item/ammo_casing/a75" @@ -72,7 +72,7 @@ icon_state = "pistol" w_class = W_CLASS_SMALL max_shells = 8 - caliber = list("9mm" = 1) + caliber = list(MM9 = 1) silenced = 0 origin_tech = Tc_COMBAT + "=2;" + Tc_MATERIALS + "=2;" + Tc_SYNDICATE + "=2" ammo_type = "/obj/item/ammo_casing/c9mm" @@ -118,7 +118,7 @@ ammo_type = "/obj/item/ammo_casing/c45" mag_type = "/obj/item/ammo_storage/magazine/c45" max_shells = 8 - caliber = list(".45" = 1) + caliber = list(POINT45 = 1) origin_tech = Tc_COMBAT + "=3" fire_sound = 'sound/weapons/semiauto.ogg' load_method = 2 @@ -147,7 +147,7 @@ ammo_type = "/obj/item/ammo_casing/c380auto" mag_type = "/obj/item/ammo_storage/magazine/m380auto" max_shells = 8 - caliber = list(".45" = 1) + caliber = list(POINT380 = 1) origin_tech = Tc_COMBAT + "=3" fire_sound = 'sound/weapons/semiauto.ogg' load_method = 2 @@ -172,7 +172,7 @@ icon_state = "p08" max_shells = 8 origin_tech = "combat=2;materials=2" - caliber = list("9mm" = 1) + caliber = list(MM9 = 1) silenced = 0 origin_tech = Tc_COMBAT + "=2;" + Tc_MATERIALS + "=2" ammo_type = "/obj/item/ammo_casing/c9mm" @@ -184,3 +184,21 @@ /obj/item/weapon/gun/projectile/luger/update_icon() ..() icon_state = "[initial(icon_state)][stored_magazine ? "" : "empty"]" + +/obj/item/weapon/gun/projectile/beretta + name = "\improper Beretta 92FS" + desc = "The classic wonder nine and favorite of the undercover cop. Kong whiskey not included." + icon = 'icons/obj/beretta.dmi' + icon_state = "beretta" + max_shells = 15 + caliber = list(MM9 = 1) + silenced = 0 + origin_tech = Tc_COMBAT + "=2;" + Tc_MATERIALS + "=2;" + Tc_SYNDICATE + "=2" + ammo_type = "/obj/item/ammo_casing/c9mm" + mag_type = "/obj/item/ammo_storage/magazine/beretta" + load_method = 2 + gun_flags = AUTOMAGDROP | EMPTYCASINGS + +/obj/item/weapon/gun/projectile/beretta/update_icon() + ..() + icon_state = "beretta[chambered ? "" : "-e"]" diff --git a/code/modules/projectiles/guns/projectile/revolver.dm b/code/modules/projectiles/guns/projectile/revolver.dm index 798f957c897..2f1a02e95ca 100644 --- a/code/modules/projectiles/guns/projectile/revolver.dm +++ b/code/modules/projectiles/guns/projectile/revolver.dm @@ -3,7 +3,7 @@ name = "revolver" icon_state = "detective" max_shells = 6 - caliber = list("38" = 1, "357" = 1) + caliber = list(POINT38 = 1, POINT357 = 1) origin_tech = Tc_COMBAT + "=2;" + Tc_MATERIALS + "=2" ammo_type = "/obj/item/ammo_casing/c38" var/perfect = 0 @@ -11,7 +11,7 @@ special_check(var/mob/living/carbon/human/M) //to see if the gun fires 357 rounds safely. A non-modified revolver randomly blows up if(getAmmo()) //this is a good check, I like this check var/obj/item/ammo_casing/AC = loaded[1] - if(caliber["38"] == 0) //if it's been modified, this is true + if(caliber[POINT38] == 0) //if it's been modified, this is true return 1 if(istype(AC, /obj/item/ammo_casing/a357) && !perfect && prob(70 - (getAmmo() * 10))) //minimum probability of 10, maximum of 60 to_chat(M, "[src] blows up in your face.") @@ -49,7 +49,7 @@ if(!CK.open) to_chat(user, "This [CK.name] is useless unless you open it first. ") return - if(caliber["38"]) + if(caliber[POINT38]) to_chat(user, "You begin to reinforce the barrel of [src].") if(getAmmo()) afterattack(user, user) //you know the drill @@ -60,7 +60,7 @@ if(getAmmo()) to_chat(user, "You can't modify it!") return - caliber["38"] = 0 + caliber[POINT38] = 0 desc = "The barrel and chamber assembly seems to have been modified." to_chat(user, "You reinforce the barrel of [src]! Now it will fire .357 rounds.") if(CK && istype(CK)) @@ -76,7 +76,7 @@ if(getAmmo()) to_chat(user, "You can't modify it!") return - caliber["38"] = 1 + caliber[POINT38] = 1 desc = initial(desc) to_chat(user, "You remove the modifications on [src]! Now it will fire .38 rounds.") perfect = 0 diff --git a/code/modules/projectiles/guns/projectile/rocketlauncher.dm b/code/modules/projectiles/guns/projectile/rocketlauncher.dm index 77fa2ef4e43..ad00a948e6f 100644 --- a/code/modules/projectiles/guns/projectile/rocketlauncher.dm +++ b/code/modules/projectiles/guns/projectile/rocketlauncher.dm @@ -16,7 +16,7 @@ flags = FPRINT siemens_coefficient = 1 slot_flags = SLOT_BACK - caliber = list("rpg" = 1) + caliber = list(ROCKETGRENADE = 1) origin_tech = Tc_COMBAT + "=4;" + Tc_MATERIALS + "=2;" + Tc_SYNDICATE + "=2" ammo_type = "/obj/item/ammo_casing/rocket_rpg" attack_verb = list("strikes", "hits", "bashes") @@ -66,7 +66,7 @@ slot_flags = SLOT_BACK w_class = W_CLASS_LARGE fire_delay = 2 - caliber = list("nikita" = 1) + caliber = list(GUIDEDROCKET = 1) origin_tech = null fire_sound = 'sound/weapons/rocket.ogg' ammo_type = "/obj/item/ammo_casing/rocket_rpg/nikita" @@ -78,7 +78,7 @@ /obj/item/weapon/gun/projectile/rocketlauncher/nikita/attack_self(mob/user) if(fired) - playsound(get_turf(src), 'sound/weapons/stickybomb_det.ogg', 30, 1) + playsound(src, 'sound/weapons/stickybomb_det.ogg', 30, 1) fired.detonate() /obj/item/weapon/gun/projectile/rocketlauncher/nikita/suicide_act(var/mob/user) @@ -111,7 +111,7 @@ desc = "A miniature cruise missile" icon = 'icons/obj/ammo.dmi' icon_state = "nikita" - caliber = "nikita" + caliber = GUIDEDROCKET projectile_type = "/obj/item/projectile/nikita" /obj/item/ammo_casing/rocket_rpg/nikita/New() diff --git a/code/modules/projectiles/guns/projectile/shotgun.dm b/code/modules/projectiles/guns/projectile/shotgun.dm index 74dd608be70..91c45a65420 100644 --- a/code/modules/projectiles/guns/projectile/shotgun.dm +++ b/code/modules/projectiles/guns/projectile/shotgun.dm @@ -11,7 +11,7 @@ flags = FPRINT siemens_coefficient = 1 slot_flags = SLOT_BACK - caliber = list("shotgun" = 1, "flare" = 1) //flare shells are still shells + caliber = list(GAUGE12 = 1, GAUGEFLARE = 1) //flare shells are still shells origin_tech = Tc_COMBAT + "=4;" + Tc_MATERIALS + "=2" ammo_type = "/obj/item/ammo_casing/shotgun/beanbag" var/recentpump = 0 // to prevent spammage @@ -82,7 +82,7 @@ flags = FPRINT siemens_coefficient = 1 slot_flags = SLOT_BACK - caliber = list("shotgun" = 1, "flare" = 1) + caliber = list(GAUGE12 = 1, GAUGEFLARE = 1) origin_tech = Tc_COMBAT + "=3;" + Tc_MATERIALS + "=1" ammo_type = "/obj/item/ammo_casing/shotgun/beanbag" diff --git a/code/modules/projectiles/guns/projectile/sniper.dm b/code/modules/projectiles/guns/projectile/sniper.dm index f49949632bf..c19acc79d59 100644 --- a/code/modules/projectiles/guns/projectile/sniper.dm +++ b/code/modules/projectiles/guns/projectile/sniper.dm @@ -11,7 +11,7 @@ fire_delay = 30 w_class = W_CLASS_LARGE fire_sound = 'sound/weapons/hecate_fire.ogg' - caliber = list(".50BMG" = 1) + caliber = list(BROWNING50 = 1) ammo_type = "/obj/item/ammo_casing/BMG50" max_shells = 1 load_method = 0 diff --git a/code/modules/projectiles/guns/projectile/stickylauncher.dm b/code/modules/projectiles/guns/projectile/stickylauncher.dm index 4b153fc361d..b0277526eed 100644 --- a/code/modules/projectiles/guns/projectile/stickylauncher.dm +++ b/code/modules/projectiles/guns/projectile/stickylauncher.dm @@ -51,7 +51,7 @@ /obj/item/weapon/gun/stickybomb/attack_self(mob/user) if(fired.len) - playsound(get_turf(src), 'sound/weapons/stickybomb_det.ogg', 30, 1) + playsound(src, 'sound/weapons/stickybomb_det.ogg', 30, 1) for(var/obj/item/stickybomb/B in fired) spawn() if(B.live) diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 76969d5bfa7..db0bb275550 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -508,6 +508,11 @@ var/list/impact_master = list() OnDeath() returnToPool(src) +/obj/item/projectile/beam/lightning/spell/bullet_die() + spawn() + OnDeath() + returnToPool(src) + /obj/item/projectile/proc/bump_original_check() if(!bumped && !isturf(original)) if(loc == get_turf(original)) diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm index 49aedf7b556..e335fa9f6b8 100644 --- a/code/modules/projectiles/projectile/beams.dm +++ b/code/modules/projectiles/projectile/beams.dm @@ -935,7 +935,7 @@ var/list/beam_master = list() /obj/item/projectile/beam/bullwhip/OnDeath() if(!has_played_sound && get_turf(src)) - playsound(get_turf(src), bounce_sound, 30, 1) + playsound(src, bounce_sound, 30, 1) user.delayNextAttack(2) /obj/item/projectile/beam/liquid_stream diff --git a/code/modules/projectiles/projectile/bullets.dm b/code/modules/projectiles/projectile/bullets.dm index 17e980b0822..7387e0d7923 100644 --- a/code/modules/projectiles/projectile/bullets.dm +++ b/code/modules/projectiles/projectile/bullets.dm @@ -24,6 +24,14 @@ damage_type = TOX weaken = 5 +/obj/item/projectile/bullet/blank + name = "hot gas discharge" + icon_state = null + damage = 10 + damage_type = BURN + kill_count = 1 //Limits the range to one tile + embed = 0 + /obj/item/projectile/bullet/shrapnel name = "shrapnel" @@ -368,6 +376,17 @@ damage = 5 damage_type = TOX flag = "bio" + var/bug_species = BEESPECIES_NORMAL + var/tox = 50 + var/dam = 2 + +/obj/item/projectile/bullet/beegun/hornet + name = "hornet" + icon_state = "hornetgun" + damage = 7 + bug_species = BEESPECIES_HORNET + tox = 25 + dam = 4 /obj/item/projectile/bullet/beegun/OnFired() ..() @@ -384,7 +403,7 @@ bumped = 1 var/turf/T = get_turf(src) - var/mob/living/simple_animal/bee/angry/BEE = new(T) + var/mob/living/simple_animal/bee/angry/BEE = new (T,null,bug_species,tox,dam) if(istype(A,/mob/living)) var/mob/living/M = A visible_message("\the [M.name] is hit by \the [src.name] in the [parse_zone(def_zone)]!") @@ -498,7 +517,7 @@ /obj/item/projectile/bullet/vial/OnDeath() if(!hit_mob) src.visible_message("The vial shatters!") - playsound(get_turf(src), "shatter", 20, 1) + playsound(src, "shatter", 20, 1) /obj/item/projectile/bullet/blastwave name = "blast wave" @@ -763,7 +782,7 @@ /obj/item/projectile/bullet/liquid_blob/OnDeath() if(get_turf(src)) - playsound(get_turf(src), 'sound/effects/slosh.ogg', 20, 1) + playsound(src, 'sound/effects/slosh.ogg', 20, 1) /obj/item/projectile/bullet/buckshot name = "buckshot pellet" @@ -771,6 +790,7 @@ damage = 10 penetration = 0 rotate = 0 + var/variance_angle = 20 var/total_amount_to_fire = 9 var/type_to_fire = /obj/item/projectile/bullet/buckshot var/is_child = 0 @@ -779,19 +799,21 @@ ..(T) is_child = C -/obj/item/projectile/bullet/buckshot/proc/get_radius_turfs(turf/T) - return orange(T,1) - /obj/item/projectile/bullet/buckshot/OnFired() if(!is_child) - var/list/turf/possible_turfs = list() - for(var/turf/T in get_radius_turfs(original)) - possible_turfs += T + var/x = 0 + var/y = 0 + var/z = 0 + var/angle = 0 + var/launch_at_range = 7 // Increasing this should make the bullet spread smoother or something for(var/I = 1; I <=total_amount_to_fire-1; I++) var/obj/item/projectile/bullet/buckshot/B = new type_to_fire(src.loc, 1) - var/turf/targloc = pick(possible_turfs) + angle = rand(-variance_angle/2, variance_angle/2) + get_angle(starting, original) + x = src.x + (launch_at_range * sin(angle)) + y = src.y + (launch_at_range * cos(angle)) + z = src.z B.forceMove(get_turf(src)) - B.launch_at(targloc,from = shot_from) + B.launch_at(locate(x, y, z), from = shot_from) ..() /obj/item/projectile/bullet/invisible @@ -836,9 +858,7 @@ type_to_fire = /obj/item/projectile/bullet/buckshot/bullet_storm custom_impact = 1 embed_message = FALSE - -/obj/item/projectile/bullet/buckshot/bullet_storm/get_radius_turfs(turf/T) - return circlerangeturfs(original,5) + variance_angle = 50 /obj/item/projectile/bullet/faggot name = "high-speed faggot" diff --git a/code/modules/projectiles/projectile/change.dm b/code/modules/projectiles/projectile/change.dm index cf650fb1844..0fcc1da405b 100644 --- a/code/modules/projectiles/projectile/change.dm +++ b/code/modules/projectiles/projectile/change.dm @@ -48,9 +48,10 @@ else return if(new_mob) - if(M.mind && M.mind.wizard_spells && M.mind.wizard_spells.len) - for (var/spell/S in M.mind.wizard_spells) - new_mob.spell_list += new S.type - to_chat(new_mob, "Your form morphs into that of a [randomize].") + if(new_mob.mind && new_mob.mind.wizard_spells && new_mob.mind.wizard_spells.len) + for (var/spell/S in new_mob.mind.wizard_spells) + new_mob.add_spell(S) + var/mob/living/carbon/human/H = new_mob + to_chat(new_mob, "Your form morphs into that of a [(istype(H) && H.species && H.species.name) ? H.species.name : randomize].") return new_mob diff --git a/code/modules/projectiles/projectile/ricochet.dm b/code/modules/projectiles/projectile/ricochet.dm index 7200de35287..b6c653b2fbf 100644 --- a/code/modules/projectiles/projectile/ricochet.dm +++ b/code/modules/projectiles/projectile/ricochet.dm @@ -176,7 +176,7 @@ bouncin = 1 var/obj/structure/ricochet_bump/bump = new(loc) bump.dir = pos_to - playsound(get_turf(src), 'sound/items/metal_impact.ogg', 50, 1) + playsound(src, 'sound/items/metal_impact.ogg', 50, 1) switch(pos_to) if(NORTH) if(pos_from == WEST) diff --git a/code/modules/projectiles/projectile/rocket.dm b/code/modules/projectiles/projectile/rocket.dm index 0d7f012022b..4007cad1afe 100644 --- a/code/modules/projectiles/projectile/rocket.dm +++ b/code/modules/projectiles/projectile/rocket.dm @@ -59,10 +59,9 @@ var/mob/living/carbon/C = nikita.loc if(C.get_active_hand() == nikita) mob = C - mob.client.perspective = EYE_PERSPECTIVE - mob.client.eye = src - mob.orient_object = src - mob.canmove = 0 + var/datum/control/new_control = new /datum/control/lock_move(mob, src) + mob.orient_object.Add(new_control) + new_control.take_control() dir = get_dir_cardinal(starting,original) last_dir = dir @@ -107,10 +106,9 @@ var/mob/living/carbon/C = nikita.loc if(C.get_active_hand() == nikita) mob = C - mob.client.perspective = EYE_PERSPECTIVE - mob.client.eye = src - mob.orient_object = src - mob.canmove = 0 + var/datum/control/new_control = new /datum/control/lock_move(mob, src) + mob.orient_object.Add(new_control) + new_control.take_control() if(src.loc) var/atom/step = get_step(src, dir) @@ -149,7 +147,7 @@ /obj/item/projectile/nikita/proc/check_user() if(!mob || !mob.client) return 0 - if(mob.stat || (mob.get_active_hand() != src)) + if(mob.stat || (mob.get_active_hand() != nikita)) reset_view() return 0 return 1 @@ -160,9 +158,7 @@ qdel(src) /obj/item/projectile/nikita/proc/reset_view() - if(mob && mob.client) - mob.client.eye = mob.client.mob - mob.client.perspective = MOB_PERSPECTIVE - mob.orient_object = null - mob.canmove = 1 - mob = null + var/datum/control/C = mob.orient_object[src] + if(C) + C.break_control() + qdel(C) diff --git a/code/modules/randomMaps/dungeons.dm b/code/modules/randomMaps/dungeons.dm index e786bb9bcd9..56d3d62027d 100644 --- a/code/modules/randomMaps/dungeons.dm +++ b/code/modules/randomMaps/dungeons.dm @@ -5,6 +5,25 @@ var/list/existing_dungeons = list() var/turf/dungeon_area = null +/datum/map_element/dungeon + //If TRUE, don't load any duplicates (subtypes are fine) + //Note: When trying to load a duplicate, load_dungeon() will return a reference to the "original" dungeon datum, instead of a list of its objects + var/unique = 0 + + //If not null, spawn these objects at the border of the dungeon + //By default, random teleporters are created (making escaping to Z-2 impossible) + var/border_type = /obj/effect/step_trigger/teleporter/random/shuttle_transit + +/datum/map_element/dungeon/load(x,y,z) + .=..() + + if(border_type) + for(var/turf/T in block_borders(location, locate(location.x + width, location.y + height, location.z))) + if(ispath(border_type, /turf)) + T.ChangeTurf(border_type) + else + new border_type(T) + //MARKER: put this on z-2, with plenty of space to the right and north /obj/effect/landmark/dungeon_area @@ -22,6 +41,8 @@ var/turf/dungeon_area = null //NOTE: first dungeon spawns in the lower left corner. Next dungeons spawn to the right until there's no more space there. //Then spawn above the first dungeon and continue to the right... +//Returns list of loaded objects. If trying to load a duplicate dungeon (and it's forbidden), returns a reference to the "original" dungeon instead + #define MAXIMUM_DUNGEON_WIDTH 80 proc/load_dungeon(dungeon_type) @@ -36,6 +57,13 @@ proc/load_dungeon(dungeon_type) else return 0 + var/datum/map_element/dungeon/D = ME + if(istype(D) && D.unique) + //Check if this exact dungeon already exists + for(var/datum/map_element/dungeon/dungeon in existing_dungeons) + if(dungeon.type == ME.type) + return dungeon + var/spawn_x = dungeon_area.x var/spawn_y = dungeon_area.y //Where to spawn the dungeon diff --git a/code/modules/randomMaps/vault_definitions.dm b/code/modules/randomMaps/vault_definitions.dm index 22788ec448a..e2f12ceb398 100644 --- a/code/modules/randomMaps/vault_definitions.dm +++ b/code/modules/randomMaps/vault_definitions.dm @@ -171,4 +171,11 @@ var/list/existing_vaults = list() file_path = "maps/randomvaults/dungeons/satellite_deployment.dmm" /datum/map_element/vault/ironchef - file_path = "maps/randomvaults/ironchef.dmm" \ No newline at end of file + file_path = "maps/randomvaults/ironchef.dmm" + +/datum/map_element/vault/assistantslair + file_path = "maps/randomvaults/assistantslair.dmm" + +/datum/map_element/vault/asteroidfield + file_path = "maps/randomvaults/asteroidfield.dmm" + diff --git a/code/modules/reagents/Chemistry-Holder.dm b/code/modules/reagents/Chemistry-Holder.dm index 84d18c0fb25..d9432dfaa14 100644 --- a/code/modules/reagents/Chemistry-Holder.dm +++ b/code/modules/reagents/Chemistry-Holder.dm @@ -388,7 +388,7 @@ trans_to_atmos(var/datum/gas_mixture/target, var/amount=1, var/multiplier=1, var matching_container = 1 else - if(my_atom.type == C.required_container) + if(istype(my_atom, C.required_container)) matching_container = 1 if(!C.required_other) @@ -417,7 +417,7 @@ trans_to_atmos(var/datum/gas_mixture/target, var/amount=1, var/multiplier=1, var preserved_data = get_data(B) remove_reagent(B, (multiplier * C.required_reagents[B]), safety = 1) - chem_temp -= C.reaction_temp_cost + chem_temp += C.reaction_temp_change var/created_volume = C.result_amount*multiplier if(C.result) @@ -451,7 +451,7 @@ trans_to_atmos(var/datum/gas_mixture/target, var/amount=1, var/multiplier=1, var ME2.desc = "This extract has been used up." if(!quiet) - playsound(get_turf(my_atom), 'sound/effects/bubbles.ogg', 80, 1) + playsound(my_atom, 'sound/effects/bubbles.ogg', 80, 1) C.on_reaction(src, created_volume) if(C.react_discretely) @@ -521,7 +521,7 @@ trans_to_atmos(var/datum/gas_mixture/target, var/amount=1, var/multiplier=1, var R.reaction_mob(A, TOUCH, R.volume+volume_modifier) if(isturf(A)) R.reaction_turf(A, R.volume+volume_modifier) - if(isobj(A)) + if(istype(A, /obj)) R.reaction_obj(A, R.volume+volume_modifier) if(INGEST) for(var/datum/reagent/R in reagent_list) @@ -532,11 +532,11 @@ trans_to_atmos(var/datum/gas_mixture/target, var/amount=1, var/multiplier=1, var R.reaction_mob(A, INGEST, R.volume+volume_modifier) if(isturf(A) && R) R.reaction_turf(A, R.volume+volume_modifier) - if(isobj(A) && R) + if(istype(A, /obj) && R) R.reaction_obj(A, R.volume+volume_modifier) return -/datum/reagents/proc/add_reagent(var/reagent, var/amount, var/list/data=null, var/reagtemp = 300) +/datum/reagents/proc/add_reagent(var/reagent, var/amount, var/list/data=null, var/reagtemp = T0C+20) if(!my_atom) return 0 if(!isnum(amount)) diff --git a/code/modules/reagents/Chemistry-Reagents.dm b/code/modules/reagents/Chemistry-Reagents.dm index 6915f8a8653..d20a5e24631 100644 --- a/code/modules/reagents/Chemistry-Reagents.dm +++ b/code/modules/reagents/Chemistry-Reagents.dm @@ -8,17 +8,23 @@ // Use in chem.flags. #define CHEMFLAG_DISHONORABLE 1 -//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. +/* 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. -//Always call parent on reaction_mob, reaction_obj, reaction_turf, on_mob_life and Destroy() so that the sanities can be handled -//Failure to do so will lead to serious problems + Always call parent on reaction_mob, reaction_obj, reaction_turf, on_mob_life and Destroy() so that the sanities can be handled + Failure to do so will lead to serious problems -//Are you adding a toxic reagent? Remember to update bees_apiary.dm 's lists of toxic reagents accordingly. + Are you adding a toxic reagent? Remember to update bees_apiary.dm 's lists of toxic reagents accordingly. -//Not sure what to have your density and SHC as? Use the components of the reagent -//density = (for(components of recipe) total_mass += component density* component volume)/volume of result -//SHC = (for(components of recipe) total_SHC *= component SHC) + Not sure what to have your density and SHC as? No IRL equivalent you can google? Use the components of the reagent + density = (for(components of recipe) total_mass += component density* component volume)/volume of result. E.G + 6 SALINE = 3 SODIUMCHLORIDE, 5 WATER, 1 AMMONIA + density = ((1 + (2.09*3) + (1*5) + (0.51*1))/6) = 2.22 (rounded to 2dp) + + SHC = (for(components of recipe) total_SHC *= component SHC) + + +*/ /datum/reagent var/name = "Reagent" @@ -498,9 +504,9 @@ if(ismob(O.loc)) var/mob/M = O.loc M.regenerate_icons() - - var/turf/T = get_turf(O) - self.reaction_turf(T, volume) + if(isturf(O.loc)) + var/turf/T = get_turf(O) + self.reaction_turf(T, volume) if(istype(O, /obj/item/weapon/reagent_containers/food/snacks/monkeycube)) var/obj/item/weapon/reagent_containers/food/snacks/monkeycube/cube = O @@ -522,6 +528,10 @@ var/mob/living/simple_animal/hostile/slime/S = M S.calm() + if(istype(M,/mob/living/simple_animal/bee)) + var/mob/living/simple_animal/bee/B = M + B.calming() + /datum/reagent/lube name = "Space Lube" id = LUBE @@ -595,7 +605,8 @@ holder.remove_reagent(ZOMBIEPOWDER, 0.5 * REM) if(holder.has_reagent(MINDBREAKER)) holder.remove_reagent(MINDBREAKER, 2 * REM) - M.hallucination = max(0, M.hallucination - 5 * REM) + var/lucidmod = M.sleeping ? 3 : M.lying + 1 //3x as effective if they're sleeping, 2x if they're lying down + M.hallucination = max(0, M.hallucination - 5 * REM * lucidmod) M.adjustToxLoss(-2 * REM) /datum/reagent/phalanximine @@ -847,7 +858,7 @@ description = "Inaprovaline is a synaptic stimulant and cardiostimulant. Commonly used to stabilize patients." reagent_state = LIQUID color = "#C8A5DC" //rgb: 200, 165, 220 - custom_metabolism = 0.5 + custom_metabolism = 0.2 pain_resistance = 25 density = 1.66 specheatcap = 0.8 @@ -998,9 +1009,8 @@ if(..()) return 1 - if(volume >= 5) - T.holy = 1 + T.bless() /datum/reagent/serotrotium name = "Serotrotium" @@ -1210,6 +1220,8 @@ return 1 if(ishuman(M)) var/mob/living/carbon/human/H = M + if((H.species && H.species.flags & NO_BREATHE) || M_NO_BREATH in H.mutations) + return for(var/datum/organ/internal/lungs/L in H.internal_organs) L.take_damage(REM, 1) @@ -1917,9 +1929,9 @@ var/datum/reagent/self = src if(..()) return 1 - - var/turf/T = get_turf(O) - self.reaction_turf(T, volume) + if(isturf(O.loc)) + var/turf/T = get_turf(O) + self.reaction_turf(T, volume) /datum/reagent/fuel/reaction_turf(var/turf/simulated/T, var/volume) @@ -2047,6 +2059,13 @@ for(var/obj/item/I in T) I.decontaminate() + T.color = "" + +/datum/reagent/space_cleaner/bleach/reaction_obj(obj/O, var/volume) + if(O) + O.color = "" + ..() + /datum/reagent/space_cleaner/bleach/on_mob_life(var/mob/living/M) if(..()) @@ -2072,6 +2091,8 @@ if(..()) return 1 + M.color = "" + if(method == TOUCH) if(ishuman(M)) var/mob/living/carbon/human/H = M @@ -2263,7 +2284,7 @@ description = "Cryptobiolin causes confusion and dizzyness." reagent_state = LIQUID color = "#C8A5DC" //rgb: 200, 165, 220 - custom_metabolism = 0.5 + custom_metabolism = 0.2 density = 1.21 specheatcap = 0.85 @@ -2405,6 +2426,7 @@ M.setCloneLoss(0) M.setOxyLoss(0) + M.rad_tick = 0 M.radiation = 0 M.heal_organ_damage(5,5) M.adjustToxLoss(-5) @@ -2432,6 +2454,8 @@ holder.remove_reagent("zombiepowder", 5) if(holder.has_reagent("mindbreaker")) holder.remove_reagent("mindbreaker", 5) + if(holder.has_reagent("spiritbreaker")) + holder.remove_reagent("spiritbreaker", 5) M.hallucination = 0 M.setBrainLoss(0) M.disabilities = 0 @@ -2477,7 +2501,8 @@ M.AdjustKnockdown(-1) if(holder.has_reagent("mindbreaker")) holder.remove_reagent("mindbreaker", 5) - M.hallucination = max(0, M.hallucination - 10) + var/lucidmod = M.sleeping ? 3 : M.lying + 1 + M.hallucination = max(0, M.hallucination - 10 * lucidmod) if(prob(60)) M.adjustToxLoss(1) @@ -2591,9 +2616,9 @@ if(ishuman(M)) var/mob/living/carbon/human/H = M var/datum/organ/internal/eyes/E = H.internal_organs_by_name["eyes"] - if(E && istype(E)) + if(istype(E) && !E.robotic) if(E.damage > 0) - E.damage-- + E.damage = max(0, E.damage - 1) /datum/reagent/inacusiate name = "Inacusiate" @@ -2633,6 +2658,22 @@ if(I.damage > 0) I.damage = max(0,I.damage-0.2) + +/datum/reagent/peridaxon/reaction_obj(var/obj/O, var/volume) + + if(..()) + return 1 + + if(istype(O, /obj/item/organ/internal)) + var/obj/item/organ/internal/I = O + if(I.health < initial(I.health)) + I.health = min(I.health+rand(1,3), initial(I.health)) + if(I.organ_data) + var/datum/organ/internal/OD = I.organ_data + if(OD.damage > 0) + OD.damage = max(0, OD.damage-0.4) + + /datum/reagent/bicaridine name = "Bicaridine" id = BICARIDINE @@ -2985,7 +3026,7 @@ id = SPIRITBREAKER description = "An extremely dangerous hallucinogen often used for torture. Extracted from the leaves of the rare Ambrosia Cruciatus plant." reagent_state = LIQUID - color = "3B0805" //rgb: 59, 8, 5 + color = "#3B0805" //rgb: 59, 8, 5 custom_metabolism = 0.05 /datum/reagent/spiritbreaker/on_mob_life(var/mob/living/M) @@ -3079,7 +3120,7 @@ return 1 if((prob(10) && method == TOUCH) || method == INGEST) - M.contract_disease(new diseasetype) + M.contract_disease(new diseasetype, 1) /datum/reagent/nanites/autist name = "Autist nanites" @@ -3308,6 +3349,32 @@ color = "#181818" //rgb: 24, 24, 24 density = 1.01 +//Solely for flavor. +/datum/reagent/tobacco + name = "Tobacco" + id = TOBACCO + description = "The cured and ground leaves of a tobacco plant." + reagent_state = SOLID + color = "#4c1e00" //rgb: 76, 30, 0 + density = 1.01 + +/datum/reagent/danbacco + name = "Tobacco" + id = DANBACCO //This product may or may not cause cancer. + description = "The cured and ground leaves of a tobacco plant with additional Discount Dan flavors." + reagent_state = SOLID + color = "#4c1e00" //rgb: 76, 30, 0 + density = 1.01 + +/datum/reagent/danbacco/on_mob_life(var/mob/living/M) + if(..()) + return 1 + + if(ishuman(M)) + var/mob/living/carbon/human/H = M + if(prob(50)) //Discount dan's special blend. + H.add_cancer(1, LIMB_CHEST) + /datum/reagent/ammonia name = "Ammonia" id = AMMONIA @@ -3451,6 +3518,22 @@ nutriment_factor = 5 * REAGENTS_METABOLISM color = "#731008" //rgb: 115, 16, 8 +/datum/reagent/mustard + name = "Mustard" + id = MUSTARD + description = "A spicy yellow paste." + reagent_state = LIQUID + nutriment_factor = 3 * REAGENTS_METABOLISM + color = "#cccc33" //rgb: 204, 204, 51 + +/datum/reagent/relish + name = "Relish" + id = RELISH + description = "A pickled cucumber jam. Tasty!" + reagent_state = LIQUID + nutriment_factor = 4 * REAGENTS_METABOLISM + color = "#336600" //rgb: 51, 102, 0 + /datum/reagent/dipping_sauce name = "Dipping Sauce" id = DIPPING_SAUCE @@ -3987,7 +4070,7 @@ /datum/reagent/dry_ramen name = "Dry Ramen" id = DRY_RAMEN - description = "Space age food, since August 25, 1958. Contains dried noodles, vegetables, and chemicals that boil in contact with water." + description = "Space age food, since August 25, 1958. Contains dried noodles and vegetables, best cooked in boiling water." reagent_state = SOLID nutriment_factor = REAGENTS_METABOLISM color = "#302000" //rgb: 48, 32, 0 @@ -4234,7 +4317,8 @@ M.drowsyness = max(M.drowsyness - 2 * REM, 0) if(holder.has_reagent("discount")) holder.remove_reagent("discount", 2 * REM) - M.hallucination = max(0, M.hallucination - 5 * REM) + var/lucidmod = M.sleeping ? 3 : M.lying + 1 + M.hallucination = max(0, M.hallucination - 5 * REM * lucidmod) M.adjustToxLoss(-2 * REM) /datum/reagent/clottingagent @@ -5914,6 +5998,26 @@ var/global/list/tonio_doesnt_remove=list("tonio", "blood") id = MEDCOFFEE description = "Tastes like it's got iron in it or something." +/datum/reagent/drink/coffee/medcoffee/on_mob_life(var/mob/living/M) + + if(..()) + return 1 + + M.nutrition += nutriment_factor + if(M.getOxyLoss() && prob(25)) + M.adjustOxyLoss(-1) + if(M.getBruteLoss() && prob(30)) + M.heal_organ_damage(1, 0) + if(M.getFireLoss() && prob(25)) + M.heal_organ_damage(0, 1) + if(M.getToxLoss() && prob(25)) + M.adjustToxLoss(-1) + if(M.dizziness != 0) + M.dizziness = max(0, M.dizziness - 15) + if(M.confused != 0) + M.confused = max(0, M.confused - 5) + M.reagents.add_reagent (IRON, 0.1) + /datum/reagent/drink/coffee/detcoffee name = "Joe" id = DETCOFFEE @@ -6377,3 +6481,174 @@ var/global/list/tonio_doesnt_remove=list("tonio", "blood") spawn(volume * 10) O.light_color = init_color O.set_light(0) + +/datum/reagent/mucus + name = "Mucus" + id = MUCUS + description = "A slippery aqueous secretion produced by, and covering, mucous membranes. Problematic for Asthmatics." + reagent_state = LIQUID + color = "#13BC5E" + custom_metabolism = 0.01 + +/datum/reagent/mucus/on_mob_life(var/mob/living/M) + + if(..()) + return 1 + + if(ishuman(M)) + var/mob/living/carbon/human/H = M + if(M_ASTHMA in H.mutations) + H.adjustOxyLoss(2) + if(prob(30)) + H.emote("gasp") + +/datum/reagent/albuterol + name = "Albuterol" + id = ALBUTEROL + description = "A bronchodilator that relaxes muscles in the airways and increases air flow to the lungs." + reagent_state = LIQUID + color = "#C8A5DC" + overdose_am = REAGENTS_OVERDOSE + +/datum/reagent/albuterol/on_mob_life(var/mob/living/M) + + if(..()) + return 1 + if(holder.has_reagent(MUCUS)) + holder.remove_reagent(MUCUS, 10) + +/datum/reagent/liquidbutter + name ="Liquid Butter" + id = LIQUIDBUTTER + description = "A lipid heavy liquid, that's likely to make your fad lipozine diet fail." + color = "#DFDFDF" + nutriment_factor = 25 * REAGENTS_METABOLISM + +/datum/reagent/liquidbutter/on_mob_life(var/mob/living/M) + + if(..()) + return 1 + + if(holder.has_reagent(LIPOZINE)) + holder.remove_reagent(LIPOZINE, 50) + + M.nutrition += nutriment_factor + + + +/datum/reagent/saltwater + name = "Salt Water" + id = SALTWATER + description = "It's water mixed with salt. It's probably not healthy to drink." + reagent_state = LIQUID + color = "#FFFFFF" //rgb: 255, 255, 255 + density = 1.122 + specheatcap = 6.9036 + +/datum/reagent/saltwater/on_mob_life(var/mob/living/M) + + if(..()) + return 1 + + if(ishuman(M) && prob(20)) + var/mob/living/carbon/human/H = M + H.vomit() + M.adjustToxLoss(2 * REM) + +/datum/reagent/saltwater/saline + name = "Saline" + id = SALINE + description = "A solution composed of salt, water, and ammonia. Used in pickling and preservation" + reagent_state = LIQUID + color = "#DEF7F5" //rgb: 192, 227, 233 + alpha = 64 + density = 0.622 + specheatcap = 99.27 + +/datum/reagent/calciumoxide + name = "Calcium Oxide" + id = CALCIUMOXIDE + description = "Quicklime. Reacts strongly with water forming calcium hydrate and generating heat in the process" + color = "#FFFFFF" + density = 3.34 + specheatcap = 42.09 + +/datum/reagent/calciumoxide/on_mob_life(var/mob/living/M) + + if(..()) + return 1 + if(ishuman(M)) + var/mob/living/carbon/human/H = M + if((H.species && H.species.flags & NO_BREATHE) || M_NO_BREATH in H.mutations) + return + M.adjustFireLoss(0.5 * REM) + if(prob(10)) + M.visible_message("[M] [pick("dry heaves!", "coughs!", "splutters!")]") + +/datum/reagent/calciumhydroxide + name = "Calcium Hydroxide" + id = CALCIUMHYDROXIDE + description = "Hydrated lime, non-toxic." + color = "#FFFFFF" + density = 2.211 + specheatcap = 87.45 + +/datum/reagent/sodium_silicate + name = "Sodium Silicate" + id = SODIUMSILICATE + description = "A white powder, commonly used in cements." + reagent_state = SOLID + color = "#E5E5E5" + density = 2.61 + specheatcap = 111.8 + +/datum/reagent/untable + name = "Untable Mutagen" + id = UNTABLE_MUTAGEN + description = "Untable Mutagen is a substance that is inert to most materials and objects, but highly corrosive to tables." + reagent_state = LIQUID + color = "#84121D" //rgb: 132, 18, 29 + overdose_am = REAGENTS_OVERDOSE + +/datum/reagent/untable/reaction_obj(var/obj/O, var/volume) + + if(..()) + return 1 + + if(!O.acidable()) + return + + if(istype(O,/obj/structure/table)) + var/obj/effect/decal/cleanable/molten_item/I = new/obj/effect/decal/cleanable/molten_item(O.loc) + I.desc = "Looks like this was \an [O] some time ago." + O.visible_message("\The [O] melts.") + qdel(O) + +/datum/reagent/colorful_reagent + name = "Colorful Reagent" + id = COLORFUL_REAGENT + description = "Thoroughly sample the rainbow." + reagent_state = LIQUID + color = "#C8A5DC" + var/list/random_color_list = list("#00aedb","#a200ff","#f47835","#d41243","#d11141","#00b159","#00aedb","#f37735","#ffc425","#008744","#0057e7","#d62d20","#ffa700") + + +/datum/reagent/colorful_reagent/on_mob_life(mob/living/M) + if(M && isliving(M)) + M.color = pick(random_color_list) + ..() + +/datum/reagent/colorful_reagent/reaction_mob(mob/living/M, reac_volume) + if(M && isliving(M)) + M.color = pick(random_color_list) + ..() + +/datum/reagent/colorful_reagent/reaction_obj(obj/O, reac_volume) + if(O) + O.color = pick(random_color_list) + ..() + +/datum/reagent/colorful_reagent/reaction_turf(turf/T, reac_volume) + if(T) + T.color = pick(random_color_list) + ..() diff --git a/code/modules/reagents/Chemistry-Recipes.dm b/code/modules/reagents/Chemistry-Recipes.dm index f8aa79a6fe3..5978797ce89 100644 --- a/code/modules/reagents/Chemistry-Recipes.dm +++ b/code/modules/reagents/Chemistry-Recipes.dm @@ -19,10 +19,11 @@ var/is_cold_recipe = 0 var/required_temp = 0 var/react_discretely = FALSE //Handle_reactions() won't find the maximum number of times the chemicals can react. Use only if it shouldn't react more than once at a time. - var/reaction_temp_cost = 0 //How much to lower temperature of the result chemical after the reaction + var/reaction_temp_change = 0 //How much to change the temperature of the result chemical after the reaction var/alert_admins = 0 //1 to alert admins with name and amount, 2 to alert with name and amount of all reagents var/quiet = 0 + /datum/chemical_reaction/proc/log_reaction(var/datum/reagents/holder, var/amt) var/datum/log_controller/I = investigations[I_CHEMS] var/atom/A = holder.my_atom @@ -220,7 +221,7 @@ name = "Lexorin" id = LEXORIN result = LEXORIN - required_reagents = list(PLASMA = 1, HYDROGEN = 1, NITROGEN = 1) + required_reagents = list(PLASMA = 1, AMMONIA = 1) result_amount = 3 /datum/chemical_reaction/space_drugs @@ -241,7 +242,7 @@ name = "Sodium Polyacrylate" id = SODIUM_POLYACRYLATE result = SODIUM_POLYACRYLATE - required_reagents = list(CARBON = 3, HYDROGEN = 3, SODIUM = 1, OXYGEN = 2) + required_reagents = list(CARBON = 3, SODIUM = 1, WATER = 2) result_amount = 8 /datum/chemical_reaction/spoly_absorb_water @@ -266,7 +267,7 @@ result_amount = 0.2 required_temp = 3500 react_discretely = TRUE - reaction_temp_cost = 3500 + reaction_temp_change = -3500 /datum/chemical_reaction/degrease name = "Degrease" @@ -492,7 +493,7 @@ var/location = get_turf(holder.my_atom) spark(location, 2) - playsound(get_turf(src), 'sound/effects/phasein.ogg', 25, 1) + playsound(src, 'sound/effects/phasein.ogg', 25, 1) for(var/mob/living/M in viewers(get_turf(holder.my_atom), null)) var/eye_safety = 0 @@ -663,14 +664,18 @@ ..() /datum/chemical_reaction/solidification - name = "Metal solidification" + name = "Solid Metal" id = "metalsolid" result = null required_reagents = list(SILICATE = 10, FROSTOIL = 10, IRON = 20) result_amount = 1 -/datum/chemical_reaction/solidification/on_reaction(var/datum/reagents/holder, var/obj/item/stack/sheet/to_spawn) +/datum/chemical_reaction/solidification/proc/product_to_spawn() + return /obj/item/stack/sheet/metal + +/datum/chemical_reaction/solidification/on_reaction(var/datum/reagents/holder, var/created_volume) var/location = get_turf(holder.my_atom) + var/to_spawn = product_to_spawn() new to_spawn(location, result_amount) /datum/chemical_reaction/solidification/plasma @@ -680,21 +685,8 @@ required_reagents = list(SILICATE = 10, FROSTOIL = 10, PLASMA = 20) result_amount = 1 -/datum/chemical_reaction/solidification/plasma/on_reaction(var/datum/reagents/holder, var/obj/item/stack/sheet/to_spawn) - to_spawn = /obj/item/stack/sheet/mineral/plasma - ..() - - -/datum/chemical_reaction/solidification/iron - name = "Solid Metal" - id = "solidmetal" - result = null - required_reagents = list(SILICATE = 10, FROSTOIL = 10, IRON = 20) - result_amount = 1 - -/datum/chemical_reaction/solidification/iron/on_reaction(var/datum/reagents/holder, var/obj/item/stack/sheet/to_spawn) - to_spawn = /obj/item/stack/sheet/metal - ..() +/datum/chemical_reaction/solidification/plasma/product_to_spawn() + return /obj/item/stack/sheet/mineral/plasma /datum/chemical_reaction/solidification/silver name = "Solid Silver" @@ -703,9 +695,8 @@ required_reagents = list(SILICATE = 10, FROSTOIL = 10, SILVER = 20) result_amount = 1 -/datum/chemical_reaction/solidification/silver/on_reaction(var/datum/reagents/holder, var/obj/item/stack/sheet/to_spawn) - to_spawn = /obj/item/stack/sheet/mineral/silver - ..() +/datum/chemical_reaction/solidification/silver/product_to_spawn() + return /obj/item/stack/sheet/mineral/silver /datum/chemical_reaction/solidification/gold name = "Solid Gold" @@ -714,9 +705,8 @@ required_reagents = list(SILICATE = 10, FROSTOIL = 10, GOLD = 20) result_amount = 1 -/datum/chemical_reaction/solidification/gold/on_reaction(var/datum/reagents/holder, var/obj/item/stack/sheet/to_spawn) - to_spawn = /obj/item/stack/sheet/mineral/gold - ..() +/datum/chemical_reaction/solidification/gold/product_to_spawn() + return /obj/item/stack/sheet/mineral/gold /datum/chemical_reaction/solidification/uranium name = "Solid Uranium" @@ -725,20 +715,18 @@ required_reagents = list(SILICATE = 10, FROSTOIL = 10, URANIUM = 20) result_amount = 1 -/datum/chemical_reaction/solidification/uranium/on_reaction(var/datum/reagents/holder, var/obj/item/stack/sheet/to_spawn) - to_spawn = /obj/item/stack/sheet/mineral/uranium - ..() +/datum/chemical_reaction/solidification/uranium/product_to_spawn() + return /obj/item/stack/sheet/mineral/uranium /datum/chemical_reaction/solidification/plasteel name = "Solid Plasteel" id = "solidplasteel" result = null - required_reagents = list(SILICATE = 10, FROSTOIL = 5, CAPSAICIN = 5, PLASMA = 10, IRON = 10) + required_reagents = list(SODIUMSILICATE = 5, FROSTOIL = 5, PLASMA = 10, IRON = 10) result_amount = 1 -/datum/chemical_reaction/solidification/plasteel/on_reaction(var/datum/reagents/holder, var/obj/item/stack/sheet/to_spawn) - to_spawn = /obj/item/stack/sheet/plasteel - ..() +/datum/chemical_reaction/solidification/plasteel/product_to_spawn() + return /obj/item/stack/sheet/plasteel /datum/chemical_reaction/solidification/plastic name = "Plastic" @@ -747,9 +735,8 @@ required_reagents = list(PACID = 10, PLASTICIDE = 20) result_amount = 10 -/datum/chemical_reaction/solidification/plastic/on_reaction(var/datum/reagents/holder, var/obj/item/stack/sheet/to_spawn) - to_spawn = /obj/item/stack/sheet/mineral/plastic - ..() +/datum/chemical_reaction/solidification/plastic/product_to_spawn() + return /obj/item/stack/sheet/mineral/plastic /datum/chemical_reaction/condensedcapsaicin name = "Condensed Capsaicin" @@ -1200,26 +1187,19 @@ holder.my_atom.visible_message("The slime extract begins to vibrate violently!") sleep(50) - var/blocked = list( - /mob/living/simple_animal/hostile/alien/queen/large, - /mob/living/simple_animal/hostile/faithless, + var/list/blocked = existing_typesof( /mob/living/simple_animal/hostile/faithless/cult, /mob/living/simple_animal/hostile/scarybat/cult, /mob/living/simple_animal/hostile/creature/cult, /mob/living/simple_animal/hostile/retaliate/clown, /mob/living/simple_animal/hostile/mushroom, - /mob/living/simple_animal/hostile/carp/holocarp, /mob/living/simple_animal/hostile/slime, - /mob/living/simple_animal/hostile/mining_drone, /mob/living/simple_animal/hostile/mimic, - /mob/living/simple_animal/hostile/mimic/crate, - /mob/living/simple_animal/hostile/mimic/crate/chest, - /mob/living/simple_animal/hostile/mimic/crate/item, - ) + typesof(/mob/living/simple_animal/hostile/humanoid) + typesof(/mob/living/simple_animal/hostile/asteroid) //Exclusion list for things you don't want the reaction to create. + ) + boss_mobs + blacklisted_mobs//Exclusion list for things you don't want the reaction to create. - var/list/critters = existing_typesof(/mob/living/simple_animal/hostile) - blocked //List of possible hostile mobs + var/list/critters = existing_typesof(/mob/living/simple_animal/hostile) - existing_typesof_list(blocked) //List of possible hostile mobs - playsound(get_turf(holder.my_atom), 'sound/effects/phasein.ogg', 100, 1) + playsound(holder.my_atom, 'sound/effects/phasein.ogg', 100, 1) for(var/mob/O in viewers(get_turf(holder.my_atom), null)) if(ishuman(O)) @@ -1256,21 +1236,18 @@ holder.my_atom.visible_message("The slime extract begins to vibrate violently !") sleep(50) - var/blocked = list( - /mob/living/simple_animal/hostile/alien/queen/large, + var/list/blocked = list( /mob/living/simple_animal/hostile/retaliate/clown, /mob/living/simple_animal/hostile/mushroom, - /mob/living/simple_animal/hostile/carp/holocarp, /mob/living/simple_animal/hostile/faithless/cult, /mob/living/simple_animal/hostile/scarybat/cult, /mob/living/simple_animal/hostile/creature/cult, /mob/living/simple_animal/hostile/slime, - /mob/living/simple_animal/hostile/hivebot/tele, //This thing spawns hostile mobs - /mob/living/simple_animal/hostile/mining_drone, - ) + typesof(/mob/living/simple_animal/hostile/humanoid) + typesof(/mob/living/simple_animal/hostile/asteroid) //Exclusion list for things you don't want the reaction to create. - var/list/critters = existing_typesof(/mob/living/simple_animal/hostile) - blocked //List of possible hostile mobs + ) + boss_mobs + blacklisted_mobs//Exclusion list for things you don't want the reaction to create. - playsound(get_turf(holder.my_atom), 'sound/effects/phasein.ogg', 100, 1) + var/list/critters = existing_typesof(/mob/living/simple_animal/hostile) - existing_typesof_list(blocked)//List of possible hostile mobs + + playsound(holder.my_atom, 'sound/effects/phasein.ogg', 100, 1) for(var/mob/O in viewers(get_turf(holder.my_atom), null)) if(ishuman(O)) @@ -1363,7 +1340,7 @@ var/list/borks = existing_typesof(/obj/item/weapon/reagent_containers/food/snacks) - blocked //BORK BORK BORK - playsound(get_turf(holder.my_atom), 'sound/effects/phasein.ogg', 100, 1) + playsound(holder.my_atom, 'sound/effects/phasein.ogg', 100, 1) for(var/mob/O in viewers(get_turf(holder.my_atom), null)) if(ishuman(O)) @@ -1417,7 +1394,7 @@ var/list/borks = existing_typesof(/obj/item/weapon/reagent_containers/food/drinks) - blocked //BORK BORK BORK - playsound(get_turf(holder.my_atom), 'sound/effects/phasein.ogg', 100, 1) + playsound(holder.my_atom, 'sound/effects/phasein.ogg', 100, 1) for(var/mob/O in viewers(get_turf(holder.my_atom), null)) if(ishuman(O)) @@ -1500,7 +1477,7 @@ holder.my_atom.visible_message("The slime extract begins to vibrate violently!") sleep(50) - playsound(get_turf(holder.my_atom), 'sound/effects/phasein.ogg', 100, 1) + playsound(holder.my_atom, 'sound/effects/phasein.ogg', 100, 1) for(var/mob/living/M in range (get_turf(holder.my_atom), 7)) M.bodytemperature -= 6 @@ -2059,7 +2036,7 @@ /datum/chemical_reaction/slimestop/on_reaction(var/datum/reagents/holder, var/created_volume) feedback_add_details("slime_cores_used", "[replacetext(name, " ", "_")]") - playsound(get_turf(holder.my_atom), 'sound/effects/theworld3.ogg', 100, 1) + playsound(holder.my_atom, 'sound/effects/theworld3.ogg', 100, 1) timestop(get_turf(holder.my_atom), 25,5) //Pyrite @@ -2174,6 +2151,14 @@ required_reagents = list(SOYMILK = 4, FORMIC_ACID = 1) /datum/chemical_reaction/vinegar + name = "Vinegar" + id = VINEGAR + result = VINEGAR + required_reagents = list(WINE = 1, WATER = 1) + required_catalysts = list(ENZYME = 1) + result_amount = 2 + +/datum/chemical_reaction/vinegar/malt name = "Malt Vinegar" id = VINEGAR result = VINEGAR @@ -2185,7 +2170,7 @@ name = "Sprinkles" id = SPRINKLES result = SPRINKLES - required_reagents = list(SUGAR = 5) + required_reagents = list(SUGAR = 5, WATER = 5) required_catalysts = list(ENZYME = 1) result_amount = 5 @@ -2201,6 +2186,18 @@ var/location = get_turf(holder.my_atom) new /obj/item/weapon/reagent_containers/food/snacks/sliceable/cheesewheel(location) +/datum/chemical_reaction/butter + name = "Butter" + id = "butter" + result = null + required_reagents = list(CREAM = 20, SODIUMCHLORIDE = 5) + required_catalysts = list(ENZYME = 5) + result_amount = 1 + +/datum/chemical_reaction/butter/on_reaction(var/datum/reagents/holder, var/created_volume) + var/location = get_turf(holder.my_atom) + new /obj/item/weapon/reagent_containers/food/snacks/butter(location) + //Jesus christ how horrible /datum/chemical_reaction/cream name = "Cream" @@ -2239,9 +2236,14 @@ name = "Ice" id = ICE result = ICE - required_reagents = list(WATER = 10) - required_catalysts = list(FROSTOIL = 5) - result_amount = 11 + required_reagents = list(WATER = 10, FROSTOIL = 1) + result_amount = 10 + reaction_temp_change = -30 + +/datum/chemical_reaction/ice/on_reaction(var/datum/reagents/holder, var/created_volume) + if(ismob(holder.my_atom)) + var/mob/M = holder.my_atom + M.bodytemperature -= rand(10,20) /datum/chemical_reaction/ice2 name = "Frozen water" @@ -2733,7 +2735,7 @@ name = "Aloe" id = ALOE result = ALOE - required_reagents = list(CREAM = 1, WHISKEY = 1, WATERMELONJUICE = 1) + required_reagents = list(IRISHCREAM = 1, WATERMELONJUICE = 1) result_amount = 2 /datum/chemical_reaction/andalusia @@ -2848,14 +2850,6 @@ required_reagents = list(SPACEMOUNTAINWIND = 1, COFFEE = 1) result_amount = 2 -/datum/chemical_reaction/vinegar - name = "Vinegar" - id = VINEGAR - result = VINEGAR - required_reagents = list(WINE = 5) - required_catalysts = list(ENZYME = 5) - result_amount = 5 - //Cafe stuff! /datum/chemical_reaction/acidtea name = "Earl's Grey Tea" @@ -3041,5 +3035,57 @@ required_temp = T0C + 450 result_amount = 1 +/datum/chemical_reaction/albuterol + name = "Albuterol" + id = ALBUTEROL + result = ALBUTEROL + required_reagents = list(TRAMADOL = 1, HYPERZINE = 1) + result_amount = 2 + +/datum/chemical_reaction/saltwater + name = "Salt Water" + id = SALTWATER + result = SALTWATER + required_reagents = list(WATER = 20, SODIUMCHLORIDE = 5) + result_amount = 20 + +/datum/chemical_reaction/saline + name = "Saline" + id = SALINE + result = SALINE + required_reagents = list(SALTWATER = 10, AMMONIA = 1) + result_amount = 10 + +/datum/chemical_reaction/calciumhydroxide + name = "Calcium Hydroxide" + id = CALCIUMHYDROXIDE + result = CALCIUMHYDROXIDE + required_reagents = list(WATER = 1, CALCIUMOXIDE = 1) + result_amount = 1 + reaction_temp_change = 47 + react_discretely = TRUE + +/datum/chemical_reaction/sodium_silicate + name = "Sodium Silicate" + id = SODIUMSILICATE + result = SODIUMSILICATE + required_reagents = list(SODIUM = 2, SILICON = 1, OXYGEN = 3) + result_amount = 5 + + +/datum/chemical_reaction/untable + name = "Untable Mutagen" + id = UNTABLE_MUTAGEN + result = UNTABLE_MUTAGEN + required_reagents = list(FORMIC_ACID = 1, PHENOL = 1, RADIUM = 1) + result_amount = 3 + +/datum/chemical_reaction/colorful_reagent + name = "Colorful Reagent" + id = COLORFUL_REAGENT + result = COLORFUL_REAGENT + required_reagents = list(MESCALINE = 1, PSILOCYBIN = 1, AMATOXIN = 1) + result_amount = 3 + #undef ALERT_AMOUNT_ONLY #undef ALERT_ALL_REAGENTS diff --git a/code/modules/reagents/machinery/chem_dispenser.dm b/code/modules/reagents/machinery/chem_dispenser.dm index b81bcb30869..36e084a6c1c 100644 --- a/code/modules/reagents/machinery/chem_dispenser.dm +++ b/code/modules/reagents/machinery/chem_dispenser.dm @@ -87,10 +87,10 @@ USE THIS CHEMISTRY DISPENSER FOR MAPS SO THEY START AT 100 ENERGY nanomanager.update_uis(src) // update all UIs attached to src /obj/machinery/chem_dispenser/proc/can_use(var/mob/living/silicon/robot/R) - if(!isMoMMI(R) && !istype(R.module,/obj/item/weapon/robot_module/medical)) //default chem dispenser can only be used by MoMMIs and Mediborgs - return 0 + if(!(R.module && (R.module.quirk_flags & MODULE_CAN_HANDLE_CHEMS))) + return FALSE else - return 1 + return TRUE /obj/machinery/chem_dispenser/process() if(recharged < 0) @@ -313,10 +313,10 @@ USE THIS CHEMISTRY DISPENSER FOR MAPS SO THEY START AT 100 ENERGY energy = 100 /obj/machinery/chem_dispenser/brewer/can_use(var/mob/living/silicon/robot/R) - if(!isMoMMI(R) && istype(R.module,/obj/item/weapon/robot_module/butler)) //bartending dispensers can be used only by service borgs - return 1 + if(R.module && (R.module.quirk_flags & MODULE_CAN_HANDLE_FOOD)) + return TRUE else - return 0 + return FALSE //Soda/booze dispensers. @@ -344,10 +344,10 @@ USE THIS CHEMISTRY DISPENSER FOR MAPS SO THEY START AT 100 ENERGY energy = 100 /obj/machinery/chem_dispenser/soda_dispenser/can_use(var/mob/living/silicon/robot/R) - if(!isMoMMI(R) && istype(R.module,/obj/item/weapon/robot_module/butler)) //bartending dispensers can be used only by service borgs - return 1 + if(R.module && (R.module.quirk_flags & MODULE_CAN_HANDLE_FOOD)) + return TRUE else - return 0 + return FALSE /obj/machinery/chem_dispenser/booze_dispenser/ name = "Booze Dispenser" @@ -373,10 +373,10 @@ USE THIS CHEMISTRY DISPENSER FOR MAPS SO THEY START AT 100 ENERGY energy = 100 /obj/machinery/chem_dispenser/booze_dispenser/can_use(var/mob/living/silicon/robot/R) - if(!isMoMMI(R) && istype(R.module,/obj/item/weapon/robot_module/butler)) //bartending dispensers can be used only by service borgs - return 1 + if(R.module && (R.module.quirk_flags & MODULE_CAN_HANDLE_FOOD)) + return TRUE else - return 0 + return FALSE #undef FORMAT_DISPENSER_NAME diff --git a/code/modules/reagents/machinery/reagentgrinder.dm b/code/modules/reagents/machinery/reagentgrinder.dm index 15ce71106c8..ccef6847b25 100644 --- a/code/modules/reagents/machinery/reagentgrinder.dm +++ b/code/modules/reagents/machinery/reagentgrinder.dm @@ -44,6 +44,7 @@ var/global/list/juice_items = list ( /obj/item/weapon/grown/nettle = list(FORMIC_ACID = 0), /obj/item/weapon/grown/deathnettle = list(PHENOL = 0), /obj/item/stack/sheet/charcoal = list("charcoal" = 20), + /obj/item/stack/sheet/bone = list(BONEMARROW = 20), //Blender Stuff /obj/item/weapon/reagent_containers/food/snacks/grown/soybeans = list(SOYMILK = -10), //I have no fucking idea what most of these numbers mean and I hate them. @@ -332,7 +333,7 @@ var/global/list/juice_items = list ( return if (!beaker || (beaker && beaker.reagents.total_volume >= beaker.reagents.maximum_volume)) return - playsound(get_turf(src), speed_multiplier < 2 ? 'sound/machines/juicer.ogg' : 'sound/machines/juicerfast.ogg', 30, 1) + playsound(src, speed_multiplier < 2 ? 'sound/machines/juicer.ogg' : 'sound/machines/juicerfast.ogg', 30, 1) inuse = 1 spawn(50/speed_multiplier) inuse = 0 @@ -366,7 +367,7 @@ var/global/list/juice_items = list ( return if (!beaker || (beaker && beaker.reagents.total_volume >= beaker.reagents.maximum_volume)) return - playsound(get_turf(src), speed_multiplier < 2 ? 'sound/machines/blender.ogg' : 'sound/machines/blenderfast.ogg', 50, 1) + playsound(src, speed_multiplier < 2 ? 'sound/machines/blender.ogg' : 'sound/machines/blenderfast.ogg', 50, 1) inuse = 1 spawn(60/speed_multiplier) inuse = 0 diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm index 17e83e69bdd..1dc44d5501e 100644 --- a/code/modules/reagents/reagent_containers.dm +++ b/code/modules/reagents/reagent_containers.dm @@ -38,7 +38,7 @@ var/list/LOGGED_SPLASH_REAGENTS = list(FUEL, THERMITE) return if(isturf(usr.loc)) if(reagents.total_volume > 10) //Beakersplashing only likes to do this sound when over 10 units - playsound(get_turf(src), 'sound/effects/slosh.ogg', 25, 1) + playsound(src, 'sound/effects/slosh.ogg', 25, 1) usr.investigation_log(I_CHEMS, "has emptied \a [src] ([type]) containing [reagents.get_reagent_ids(1)] onto \the [usr.loc].") reagents.reaction(usr.loc) spawn() @@ -56,7 +56,7 @@ var/list/LOGGED_SPLASH_REAGENTS = list(FUEL, THERMITE) if(src.is_empty()) to_chat(usr, "\The [src] is empty.") return - playsound(get_turf(src), 'sound/effects/slosh.ogg', 25, 1) + playsound(src, 'sound/effects/slosh.ogg', 25, 1) spawn() src.reagents.clear_reagents() to_chat(user, "You flush \the [src] down \the [where].") @@ -97,7 +97,7 @@ var/list/LOGGED_SPLASH_REAGENTS = list(FUEL, THERMITE) if(user.a_intent != I_HELP) if(src.reagents) transfer(M, user, splashable_units = -1) - playsound(get_turf(M), 'sound/effects/slosh.ogg', 25, 1) + playsound(M, 'sound/effects/slosh.ogg', 25, 1) return 1 diff --git a/code/modules/reagents/reagent_containers/borghydro.dm b/code/modules/reagents/reagent_containers/borghydro.dm index 9f5bfa418a9..05c8d5af866 100644 --- a/code/modules/reagents/reagent_containers/borghydro.dm +++ b/code/modules/reagents/reagent_containers/borghydro.dm @@ -90,7 +90,7 @@ add_logs(user, M, "injected [transferred]u [reagent_ids[mode]] with \the [src]", admin = (user.ckey && M.ckey)) //We don't care about monkeymen, right? /obj/item/weapon/reagent_containers/borghypo/attack_self(mob/user as mob) - playsound(get_turf(src), 'sound/effects/pop.ogg', 50, 0) // change the mode + playsound(src, 'sound/effects/pop.ogg', 50, 0) // change the mode if(++mode > reagent_list.len) mode = 1 diff --git a/code/modules/reagents/reagent_containers/food/condiment.dm b/code/modules/reagents/reagent_containers/food/condiment.dm index 8d11ee9a4d6..85d808ba54f 100644 --- a/code/modules/reagents/reagent_containers/food/condiment.dm +++ b/code/modules/reagents/reagent_containers/food/condiment.dm @@ -117,6 +117,14 @@ name = KETCHUP desc = "You feel more American already." icon_state = KETCHUP + if(MUSTARD) + name = "mustard" + desc = "A spicy yellow paste." + icon_state = MUSTARD + if(RELISH) + name = "relish" + desc = "A pickled cucumber jam. Tasty!" + icon_state = RELISH if(CAPSAICIN) name = "hotsauce" desc = "You can almost TASTE the stomach ulcers now!" @@ -232,6 +240,22 @@ /obj/item/weapon/reagent_containers/food/condiment/ketchup/New() ..() reagents.add_reagent(KETCHUP, 50) + +/obj/item/weapon/reagent_containers/food/condiment/mustard + name = "mustard" + desc = "A spicy yellow paste." + +/obj/item/weapon/reagent_containers/food/condiment/mustard/New() + ..() + reagents.add_reagent(MUSTARD, 50) + +/obj/item/weapon/reagent_containers/food/condiment/relish + name = "relish" + desc = "A pickled cucumber jam. Tasty!" + +/obj/item/weapon/reagent_containers/food/condiment/relish/New() + ..() + reagents.add_reagent(RELISH, 50) /obj/item/weapon/reagent_containers/food/condiment/hotsauce name = "hotsauce" @@ -390,7 +414,7 @@ name = "exotic bottle" desc = "If you can see this label, something is wrong." //~9% chance of anything but special sauce, which is .09 chance - var/global/list/possible_exotic_condiments = list(ENZYME=10,BLACKPEPPER=10,VINEGAR=10,SODIUMCHLORIDE=10,CINNAMON=10,CHEFSPECIAL=1,FROSTOIL=10,SOYSAUCE=10,CAPSAICIN=10,HONEY=10,ROYALJELLY=5,KETCHUP=10,COCO=10) + var/global/list/possible_exotic_condiments = list(ENZYME=10,BLACKPEPPER=10,VINEGAR=10,SODIUMCHLORIDE=10,CINNAMON=10,CHEFSPECIAL=1,FROSTOIL=10,SOYSAUCE=10,CAPSAICIN=10,HONEY=10,ROYALJELLY=5,KETCHUP=10,MUSTARD=10,RELISH=10,COCO=10) /obj/item/weapon/reagent_containers/food/condiment/exotic/New() ..() diff --git a/code/modules/reagents/reagent_containers/food/drinks.dm b/code/modules/reagents/reagent_containers/food/drinks.dm index 4e894b18a6c..16ac9495e66 100644 --- a/code/modules/reagents/reagent_containers/food/drinks.dm +++ b/code/modules/reagents/reagent_containers/food/drinks.dm @@ -359,7 +359,7 @@ /obj/item/weapon/reagent_containers/food/drinks/dry_ramen name = "Cup Ramen" - desc = "Just add 10ml water, self heats! A taste that reminds you of your school years." + desc = "A taste that reminds you of your school years." icon_state = "ramen" /obj/item/weapon/reagent_containers/food/drinks/dry_ramen/New() ..() @@ -367,6 +367,16 @@ src.pixel_x = rand(-10, 10) * PIXEL_MULTIPLIER src.pixel_y = rand(-10, 10) * PIXEL_MULTIPLIER +/obj/item/weapon/reagent_containers/food/drinks/dry_ramen/heating //vendor version + name = "Cup Ramen" + desc = "Just add 12ml water, self heats!" + icon_state = "ramen" +/obj/item/weapon/reagent_containers/food/drinks/dry_ramen/heating/New() + ..() + reagents.add_reagent(CALCIUMOXIDE, 2) + src.pixel_x = rand(-10, 10) * PIXEL_MULTIPLIER + src.pixel_y = rand(-10, 10) * PIXEL_MULTIPLIER + /obj/item/weapon/reagent_containers/food/drinks/groans name = "Groans Soda" desc = "Groans Soda: We'll make you groan." @@ -1030,14 +1040,20 @@ /obj/item/weapon/reagent_containers/food/drinks/bottle/bottleofnothing name = "Bottle of Nothing" - desc = "A bottle filled with nothing" icon_state = "bottleofnothing" + desc = "" isGlass = 1 molotov = -1 smashtext = "" /obj/item/weapon/reagent_containers/food/drinks/bottle/bottleofnothing/New() ..() - reagents.add_reagent(NOTHING, 100) + if(Holiday == APRIL_FOOLS_DAY) + name = "Bottle of Something" + desc = "A bottle filled with something" + reagents.add_reagent(pick(BEER, VOMIT, ZOMBIEPOWDER, SOYSAUCE, KETCHUP, HONEY, BANANA, ABSINTHE, SALTWATER, WATER, BLOOD, LUBE, MUTATIONTOXIN, AMUTATIONTOXIN, GOLD, TRICORDRAZINE, GRAVY), 100) + else + desc = "A bottle filled with nothing" + reagents.add_reagent(NOTHING, 100) /obj/item/weapon/reagent_containers/food/drinks/bottle/patron name = "Wrapp Artiste Patron" @@ -1231,8 +1247,8 @@ src.visible_message("The [smashtext][src.name] shatters!","You hear a shatter!") playsound(src, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1) if(reagents.total_volume) - if(molotov || reagents.has_reagent(FUEL)) - user.attack_log += text("\[[time_stamp()]\] Threw a [lit ? "lit" : "unlit"] molotov to \the [hit_atom], containing [reagents.get_reagent_ids()]") + if(molotov == 1 || reagents.has_reagent(FUEL)) + user?.attack_log += text("\[[time_stamp()]\] Threw a [lit ? "lit" : "unlit"] molotov to \the [hit_atom], containing [reagents.get_reagent_ids()]") log_attack("[lit ? "Lit" : "Unlit"] molotov shattered at [formatJumpTo(get_turf(hit_atom))], thrown by [key_name(user)] and containing [reagents.get_reagent_ids()]") message_admins("[lit ? "Lit" : "Unlit"] molotov shattered at [formatJumpTo(get_turf(hit_atom))], thrown by [key_name_admin(user)] and containing [reagents.get_reagent_ids()]") src.reagents.reaction(get_turf(src), TOUCH) //splat the floor AND the thing we hit, otherwise fuel wouldn't ignite when hitting anything that wasn't a floor diff --git a/code/modules/reagents/reagent_containers/food/drinks/drinkingglass.dm b/code/modules/reagents/reagent_containers/food/drinks/drinkingglass.dm index 0957268a89d..f32513fa543 100644 --- a/code/modules/reagents/reagent_containers/food/drinks/drinkingglass.dm +++ b/code/modules/reagents/reagent_containers/food/drinks/drinkingglass.dm @@ -596,6 +596,11 @@ reagents.add_reagent(COLA, 50) on_reagent_change() +/obj/item/weapon/reagent_containers/food/drinks/drinkingglass/toxinsspecial/New() + ..() + reagents.add_reagent(TOXINSSPECIAL, 30) + on_reagent_change() + // Cafe Stuff. Mugs act the same as drinking glasses, but they don't break when thrown. /obj/item/weapon/reagent_containers/food/drinks/mug diff --git a/code/modules/reagents/reagent_containers/food/snacks.dm b/code/modules/reagents/reagent_containers/food/snacks.dm index 121009c6a10..c75e172c456 100644 --- a/code/modules/reagents/reagent_containers/food/snacks.dm +++ b/code/modules/reagents/reagent_containers/food/snacks.dm @@ -13,6 +13,7 @@ //FOOD_MEAT - stuff that is made from (or contains) meat. Anything that vegetarians won't eat! //FOOD_ANIMAL - stuff that is made from (or contains) animal products other than meat (eggs, honey, ...). Anything that vegans won't eat! //FOOD_SWEET - sweet stuff like chocolate and candy + //FOOD_LACTOSE - contains milk //Example: food_flags = FOOD_SWEET | FOOD_ANIMAL //Unfortunately, food created by cooking doesn't inherit food_flags! @@ -56,6 +57,9 @@ else if(ismob(loc)) var/mob/holder = loc holder.drop_from_inventory(src) + else if(istype(loc, /obj/item/weapon/storage)) + var/obj/item/weapon/storage/S = loc + S.remove_from_storage(src) if(trash) //Do we have somehing defined as trash for our snack item ? //Note : This makes sense in some way, or at least this works, just don't mess with it @@ -84,6 +88,9 @@ return +/obj/item/weapon/reagent_containers/food/snacks/proc/make_poisonous() + return + /obj/item/weapon/reagent_containers/food/snacks/attack_self(mob/user) if(can_consume(user, user)) consume(user, 1) @@ -153,12 +160,17 @@ return 0 +/obj/item/weapon/reagent_containers/food/snacks/proc/before_consume(mob/living/carbon/eater) + return + /obj/item/weapon/reagent_containers/food/snacks/proc/consume(mob/living/carbon/eater, messages = 0) if(!istype(eater)) return if(!eatverb) eatverb = pick("bite", "chew", "nibble", "gnaw", "gobble", "chomp") + before_consume(eater) + if(messages) var/fullness = eater.nutrition + (eater.reagents.get_reagent_amount(NUTRIMENT) * 25) if(fullness <= 50) @@ -176,7 +188,7 @@ var/datum/reagents/reagentreference = reagents //Even when the object is qdeleted, the reagents exist until this ref gets removed if(reagentreference) //Handle ingestion of any reagents (Note : Foods always have reagents) - playsound(get_turf(eater), 'sound/items/eatfood.ogg', rand(10,50), 1) + playsound(eater, 'sound/items/eatfood.ogg', rand(10,50), 1) if(reagentreference.total_volume) reagentreference.reaction(eater, INGEST) spawn() //WHY IS THIS SPAWN() HERE @@ -237,6 +249,19 @@ else H.vomit() + if(H.mutations.Find(M_LACTOSE)) + if(food_flags & (FOOD_LACTOSE)) + H.visible_message("[H] winces at the taste of \the [src], finding it absolutely disgusting.",\ + "\The [src] is disgusting! Your stomach rejects \him.") + + if(H.lastpuke) //If already puking, add some toxins + H.adjustToxLoss(2.5) + else + H.vomit() + + if(isskellington(H)) + H.adjustBruteLoss(rand(1,3)) + return 1 /obj/item/weapon/reagent_containers/food/snacks/proc/splat_reagent_reaction(turf/T) @@ -537,7 +562,7 @@ /obj/item/weapon/reagent_containers/food/snacks/chocolatebar/wrapped/valentine/New() ..() - if(time2text(world.realtime, "MM/DD") != "02/14") + if(Holiday != VALENTINES_DAY) new /obj/item/weapon/reagent_containers/food/snacks/badrecipe(get_turf(src)) qdel(src) @@ -767,6 +792,10 @@ reagents.add_reagent(PSILOCYBIN, 3) src.bitesize = 6 +/obj/item/weapon/reagent_containers/food/snacks/hugemushroomslice/mushroom_man/New() + ..() + reagents.add_reagent(TRICORDRAZINE, rand(1,5)) + /obj/item/weapon/reagent_containers/food/snacks/tomatomeat name = "tomato slice" desc = "A slice from a huge tomato" @@ -1035,7 +1064,7 @@ name = "muffin" desc = "A delicious and spongy little cake." icon_state = "muffin" - food_flags = FOOD_SWEET | FOOD_ANIMAL + food_flags = FOOD_SWEET | FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/muffin/New() ..() reagents.add_reagent(NUTRIMENT, 6) @@ -1112,6 +1141,8 @@ desc = "The only good recipe for eggplant." icon_state = "eggplantparm" trash = /obj/item/trash/plate + food_flags = FOOD_ANIMAL | FOOD_LACTOSE + /obj/item/weapon/reagent_containers/food/snacks/eggplantparm/New() ..() reagents.add_reagent(NUTRIMENT, 6) @@ -1382,7 +1413,7 @@ icon_state = "cheesie_honkers" desc = "Bite sized cheesie snacks that will honk all over your mouth" trash = /obj/item/trash/cheesie - food_flags = FOOD_ANIMAL //cheese + food_flags = FOOD_ANIMAL | FOOD_LACTOSE //cheese /obj/item/weapon/reagent_containers/food/snacks/cheesiehonkers/New() ..() @@ -1474,6 +1505,7 @@ name = "Loaded Baked Potato" desc = "Totally baked." icon_state = "loadedbakedpotato" + food_flags = FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/loadedbakedpotato/New() ..() @@ -1502,6 +1534,32 @@ reagents.add_reagent(NUTRIMENT, 2) bitesize = 2 +/obj/item/weapon/reagent_containers/food/snacks/butter + name = "butter" + desc = "Today we feast." + icon_state = "butter" + food_flags = FOOD_ANIMAL + + +/obj/item/weapon/reagent_containers/food/snacks/butter/New() + ..() + reagents.add_reagent(LIQUIDBUTTER, 10) + bitesize = 5 + +/obj/item/weapon/reagent_containers/food/snacks/butter/Crossed(atom/movable/O) + if (istype(O, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = O + if (H.CheckSlip() < 1) + return + + H.stop_pulling() + to_chat(H, "You slipped on the [name]!") + playsound((src), 'sound/misc/slip.ogg', 50, 1, -3) + H.Stun(4) + H.Knockdown(3) + new/obj/effect/decal/cleanable/smashed_butter(src.loc) + qdel(src) + /obj/item/weapon/reagent_containers/food/snacks/spaghetti name = "Spaghetti" desc = "Now thats a nice pasta!" @@ -1517,7 +1575,7 @@ desc = "Fries. Covered in cheese. Duh." icon_state = "cheesyfries" trash = /obj/item/trash/plate - food_flags = FOOD_ANIMAL //cheese + food_flags = FOOD_ANIMAL | FOOD_LACTOSE //cheese /obj/item/weapon/reagent_containers/food/snacks/cheesyfries/New() ..() @@ -1693,7 +1751,7 @@ desc = "The mystery is, why aren't you eating it?" icon_state = "mysterysoup" trash = /obj/item/trash/snack_bowl - food_flags = FOOD_LIQUID + food_flags = FOOD_LIQUID | FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/mysterysoup/New() ..() @@ -1900,7 +1958,7 @@ desc = "A grand creation of meat, cheese, bread, and several leaves of lettuce! Arthur Dent would be proud." icon_state = "sandwich" trash = /obj/item/trash/plate - food_flags = FOOD_MEAT + food_flags = FOOD_MEAT | FOOD_LACTOSE | FOOD_ANIMAL /obj/item/weapon/reagent_containers/food/snacks/sandwich/New() ..() @@ -1912,7 +1970,7 @@ desc = "Now if you only had a pepper bar." icon_state = "toastedsandwich" trash = /obj/item/trash/plate - food_flags = FOOD_MEAT //This is made from a sandwich, which contains meat! + food_flags = FOOD_MEAT | FOOD_LACTOSE | FOOD_ANIMAL //This is made from a sandwich, which contains meat! /obj/item/weapon/reagent_containers/food/snacks/toastedsandwich/New() ..() @@ -1925,6 +1983,7 @@ desc = "Goes great with Tomato soup!" icon_state = "toastedsandwich" trash = /obj/item/trash/plate + food_flags = FOOD_MEAT | FOOD_LACTOSE | FOOD_ANIMAL /obj/item/weapon/reagent_containers/food/snacks/grilledcheese/New() ..() @@ -2091,6 +2150,7 @@ desc = "Where's the Jam!" icon_state = "rpudding" trash = /obj/item/trash/snack_bowl + food_flags = FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/ricepudding/New() ..() @@ -2190,7 +2250,7 @@ name = "Super Bite Burger" desc = "This is a mountain of a burger. FOOD!" icon_state = "superbiteburger" - food_flags = FOOD_MEAT + food_flags = FOOD_MEAT | FOOD_LACTOSE | FOOD_ANIMAL /obj/item/weapon/reagent_containers/food/snacks/superbiteburger/New() ..() @@ -2303,6 +2363,7 @@ desc = "A delicious and hearty mushroom soup." icon_state = "mushroomsoup" trash = /obj/item/trash/snack_bowl + food_flags = FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/mushroomsoup/New() ..() @@ -2381,7 +2442,7 @@ desc = "A tasty dessert that won't make it through a metal detector." icon_state = "gappletart" trash = /obj/item/trash/plate - food_flags = FOOD_SWEET + food_flags = FOOD_SWEET | FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/appletart/New() ..() @@ -2401,7 +2462,7 @@ slice_path = /obj/item/weapon/reagent_containers/food/snacks/meatbreadslice slices_num = 5 storage_slots = 3 - food_flags = FOOD_MEAT + food_flags = FOOD_MEAT | FOOD_ANIMAL | FOOD_LACTOSE w_class = W_CLASS_MEDIUM /obj/item/weapon/reagent_containers/food/snacks/sliceable/meatbread/New() @@ -2415,7 +2476,7 @@ icon_state = "meatbreadslice" trash = /obj/item/trash/plate bitesize = 2 - food_flags = FOOD_MEAT + food_flags = FOOD_MEAT | FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/sliceable/xenomeatbread name = "xenomeatbread loaf" @@ -2424,7 +2485,7 @@ slice_path = /obj/item/weapon/reagent_containers/food/snacks/xenomeatbreadslice slices_num = 5 storage_slots = 3 - food_flags = FOOD_MEAT + food_flags = FOOD_MEAT | FOOD_ANIMAL | FOOD_LACTOSE w_class = W_CLASS_MEDIUM /obj/item/weapon/reagent_containers/food/snacks/sliceable/xenomeatbread/New() @@ -2438,7 +2499,7 @@ icon_state = "xenobreadslice" trash = /obj/item/trash/plate bitesize = 2 - food_flags = FOOD_MEAT + food_flags = FOOD_MEAT | FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/sliceable/spidermeatbread name = "spider meat loaf" @@ -2448,7 +2509,7 @@ slices_num = 5 storage_slots = 3 w_class = W_CLASS_MEDIUM - food_flags = FOOD_MEAT + food_flags = FOOD_MEAT | FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/sliceable/spidermeatbread/New() ..() @@ -2461,7 +2522,7 @@ icon_state = "xenobreadslice" trash = /obj/item/trash/plate bitesize = 2 - food_flags = FOOD_MEAT + food_flags = FOOD_MEAT | FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/sliceable/meatbread/synth name = "synthmeatbread loaf" @@ -2471,7 +2532,7 @@ slices_num = 5 storage_slots = 3 w_class = W_CLASS_MEDIUM - food_flags = FOOD_MEAT + food_flags = FOOD_MEAT | FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/sliceable/meatbread/synth/New() ..() @@ -2494,6 +2555,7 @@ slices_num = 5 storage_slots = 3 w_class = W_CLASS_MEDIUM + food_flags = FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/sliceable/bananabread/New() ..() @@ -2507,6 +2569,7 @@ icon_state = "bananabreadslice" trash = /obj/item/trash/plate bitesize = 2 + food_flags = FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/sliceable/tofubread name = "Tofubread" @@ -2515,6 +2578,7 @@ slice_path = /obj/item/weapon/reagent_containers/food/snacks/tofubreadslice slices_num = 5 storage_slots = 3 + food_flags = FOOD_MEAT | FOOD_ANIMAL | FOOD_LACTOSE w_class = W_CLASS_MEDIUM /obj/item/weapon/reagent_containers/food/snacks/sliceable/tofubread/New() @@ -2537,7 +2601,7 @@ slices_num = 5 storage_slots = 3 w_class = W_CLASS_MEDIUM - food_flags = FOOD_SWEET + food_flags = FOOD_SWEET | FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/sliceable/carrotcake/New() ..() @@ -2551,7 +2615,7 @@ icon_state = "carrotcake_slice" trash = /obj/item/trash/plate bitesize = 2 - food_flags = FOOD_SWEET + food_flags = FOOD_SWEET | FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/sliceable/braincake name = "brain cake" @@ -2561,7 +2625,7 @@ slices_num = 5 storage_slots = 3 w_class = W_CLASS_MEDIUM - food_flags = FOOD_MEAT | FOOD_ANIMAL + food_flags = FOOD_SWEET | FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/sliceable/braincake/New() ..() @@ -2575,7 +2639,7 @@ icon_state = "braincakeslice" trash = /obj/item/trash/plate bitesize = 2 - food_flags = FOOD_MEAT | FOOD_ANIMAL //meat, milk, eggs + food_flags = FOOD_MEAT | FOOD_ANIMAL | FOOD_LACTOSE //meat, milk, eggs /obj/item/weapon/reagent_containers/food/snacks/sliceable/cheesecake name = "cheese cake" @@ -2585,7 +2649,7 @@ slices_num = 5 storage_slots = 3 w_class = W_CLASS_MEDIUM - food_flags = FOOD_SWEET | FOOD_ANIMAL //cheese + food_flags = FOOD_SWEET | FOOD_ANIMAL | FOOD_LACTOSE //cheese /obj/item/weapon/reagent_containers/food/snacks/sliceable/cheesecake/New() ..() @@ -2598,7 +2662,7 @@ icon_state = "cheesecake_slice" trash = /obj/item/trash/plate bitesize = 2 - food_flags = FOOD_SWEET | FOOD_ANIMAL + food_flags = FOOD_SWEET | FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/sliceable/plaincake name = "vanilla cake" @@ -2608,7 +2672,7 @@ slices_num = 5 storage_slots = 3 w_class = W_CLASS_MEDIUM - food_flags = FOOD_SWEET | FOOD_ANIMAL //milk and eggs + food_flags = FOOD_SWEET | FOOD_ANIMAL | FOOD_LACTOSE //milk and eggs /obj/item/weapon/reagent_containers/food/snacks/sliceable/plaincake/New() ..() @@ -2620,12 +2684,12 @@ icon_state = "plaincake_slice" trash = /obj/item/trash/plate bitesize = 2 - food_flags = FOOD_SWEET | FOOD_ANIMAL + food_flags = FOOD_SWEET | FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/plaincakeslice/full/New() ..() - reagents.add_reagent("nutriment", 4) + reagents.add_reagent(NUTRIMENT, 4) /obj/item/weapon/reagent_containers/food/snacks/sliceable/orangecake name = "orange cake" @@ -2635,7 +2699,7 @@ slices_num = 5 storage_slots = 3 w_class = W_CLASS_MEDIUM - food_flags = FOOD_SWEET | FOOD_ANIMAL + food_flags = FOOD_SWEET | FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/sliceable/orangecake/New() ..() @@ -2647,7 +2711,7 @@ icon_state = "orangecake_slice" trash = /obj/item/trash/plate bitesize = 2 - food_flags = FOOD_SWEET | FOOD_ANIMAL + food_flags = FOOD_SWEET | FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/sliceable/limecake name = "lime cake" @@ -2657,7 +2721,7 @@ slices_num = 5 storage_slots = 3 w_class = W_CLASS_MEDIUM - food_flags = FOOD_SWEET | FOOD_ANIMAL + food_flags = FOOD_SWEET | FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/sliceable/limecake/New() ..() @@ -2669,7 +2733,7 @@ icon_state = "limecake_slice" trash = /obj/item/trash/plate bitesize = 2 - food_flags = FOOD_SWEET | FOOD_ANIMAL + food_flags = FOOD_SWEET | FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/sliceable/lemoncake name = "lemon cake" @@ -2679,7 +2743,7 @@ slices_num = 5 storage_slots = 3 w_class = W_CLASS_MEDIUM - food_flags = FOOD_SWEET | FOOD_ANIMAL + food_flags = FOOD_SWEET | FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/sliceable/lemoncake/New() ..() @@ -2691,7 +2755,7 @@ icon_state = "lemoncake_slice" trash = /obj/item/trash/plate bitesize = 2 - food_flags = FOOD_SWEET | FOOD_ANIMAL + food_flags = FOOD_SWEET | FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/sliceable/chocolatecake name = "chocolate cake" @@ -2701,7 +2765,7 @@ slices_num = 5 storage_slots = 3 w_class = W_CLASS_MEDIUM - food_flags = FOOD_SWEET | FOOD_ANIMAL + food_flags = FOOD_SWEET | FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/sliceable/chocolatecake/New() ..() @@ -2713,7 +2777,7 @@ icon_state = "chocolatecake_slice" trash = /obj/item/trash/plate bitesize = 2 - food_flags = FOOD_SWEET | FOOD_ANIMAL + food_flags = FOOD_SWEET | FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/sliceable/cheesewheel name = "cheese wheel" @@ -2724,7 +2788,7 @@ slices_num = 5 storage_slots = 3 w_class = W_CLASS_MEDIUM - food_flags = FOOD_ANIMAL + food_flags = FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/sliceable/cheesewheel/New() ..() @@ -2737,7 +2801,7 @@ icon_state = "cheesewedge" filling_color = "#FFCC33" bitesize = 2 - food_flags = FOOD_ANIMAL + food_flags = FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/sliceable/birthdaycake name = "Birthday Cake" @@ -2747,7 +2811,7 @@ slices_num = 5 storage_slots = 3 w_class = W_CLASS_MEDIUM - food_flags = FOOD_SWEET | FOOD_ANIMAL + food_flags = FOOD_SWEET | FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/sliceable/birthdaycake/New() ..() @@ -2761,7 +2825,7 @@ icon_state = "birthdaycakeslice" trash = /obj/item/trash/plate bitesize = 2 - food_flags = FOOD_SWEET | FOOD_ANIMAL + food_flags = FOOD_SWEET | FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/sliceable/bread name = "Bread" @@ -2793,6 +2857,7 @@ slices_num = 5 storage_slots = 3 w_class = W_CLASS_MEDIUM + food_flags = FOOD_LACTOSE | FOOD_ANIMAL /obj/item/weapon/reagent_containers/food/snacks/sliceable/creamcheesebread/New() ..() @@ -2805,7 +2870,7 @@ icon_state = "creamcheesebreadslice" trash = /obj/item/trash/plate bitesize = 2 - + food_flags = FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/watermelonslice name = "Watermelon Slice" @@ -2822,7 +2887,7 @@ slices_num = 5 storage_slots = 3 w_class = W_CLASS_MEDIUM - food_flags = FOOD_SWEET | FOOD_ANIMAL + food_flags = FOOD_SWEET | FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/sliceable/applecake/New() ..() @@ -2834,7 +2899,7 @@ icon_state = "applecakeslice" trash = /obj/item/trash/plate bitesize = 2 - food_flags = FOOD_SWEET | FOOD_ANIMAL + food_flags = FOOD_SWEET | FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/sliceable/pumpkinpie //You can't throw this pie name = "Pumpkin Pie" @@ -2845,7 +2910,7 @@ storage_slots = 3 w_class = W_CLASS_MEDIUM trash = /obj/item/trash/pietin - food_flags = FOOD_SWEET | FOOD_ANIMAL + food_flags = FOOD_SWEET | FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/sliceable/pumpkinpie/New() ..() @@ -2857,7 +2922,7 @@ icon_state = "pumpkinpieslice" trash = /obj/item/trash/plate bitesize = 2 - food_flags = FOOD_SWEET | FOOD_ANIMAL + food_flags = FOOD_SWEET | FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/cracker name = "Cracker" @@ -2882,7 +2947,7 @@ slice_path = /obj/item/weapon/reagent_containers/food/snacks/margheritaslice storage_slots = 4 w_class = W_CLASS_MEDIUM - food_flags = FOOD_ANIMAL //cheese + food_flags = FOOD_ANIMAL | FOOD_LACTOSE //cheese /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/margherita/New() ..() @@ -2890,12 +2955,29 @@ reagents.add_reagent(TOMATOJUICE, 6) bitesize = 2 +/obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/margherita/make_poisonous() + var/original_total_volume = reagents.total_volume + reagents.clear_reagents() + var/static/list/possible_poisons = list( + BLEACH, + PLASMA, + TOXIN, + SOLANINE, + PLASTICIDE, + RADIUM, + CRYPTOBIOLIN, + IMPEDREZENE, + SOYSAUCE + ) + while(reagents.total_volume < original_total_volume) + reagents.add_reagent(pick(possible_poisons), rand(5, 10)) + /obj/item/weapon/reagent_containers/food/snacks/margheritaslice name = "Margherita slice" desc = "A slice of the most cheezy pizza in galaxy" icon_state = "pizzamargheritaslice" bitesize = 2 - food_flags = FOOD_ANIMAL + food_flags = FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/meatpizza name = "Meatpizza" @@ -2903,7 +2985,7 @@ icon_state = "meatpizza" slice_path = /obj/item/weapon/reagent_containers/food/snacks/meatpizzaslice w_class = W_CLASS_MEDIUM - food_flags = FOOD_MEAT | FOOD_ANIMAL //It has cheese! + food_flags = FOOD_MEAT | FOOD_ANIMAL | FOOD_LACTOSE //It has cheese! /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/meatpizza/New() ..() @@ -2911,12 +2993,31 @@ reagents.add_reagent(TOMATOJUICE, 6) bitesize = 2 +/obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/meatpizza/make_poisonous() + var/original_total_volume = reagents.total_volume + reagents.clear_reagents() + + var/datum/disease2/disease/new_virus = new /datum/disease2/disease + new_virus.makerandom() + + var/list/blood_data = list( + "donor" = null, + "viruses" = null, + "blood_DNA" = null, + "blood_type" = "AB+", + "resistances" = null, + "trace_chem" = null, + "virus2" = list() + ) + blood_data["virus2"]["[new_virus.uniqueID]"] = new_virus + reagents.add_reagent(BLOOD, original_total_volume, blood_data) + /obj/item/weapon/reagent_containers/food/snacks/meatpizzaslice name = "Meatpizza slice" desc = "A slice of pizza, packed with delicious meat." icon_state = "meatpizzaslice" bitesize = 2 - food_flags = FOOD_MEAT | FOOD_ANIMAL + food_flags = FOOD_MEAT | FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/meatpizza/synth name = "Synthmeatpizza" @@ -2943,17 +3044,28 @@ icon_state = "mushroompizza" slice_path = /obj/item/weapon/reagent_containers/food/snacks/mushroompizzaslice w_class = W_CLASS_MEDIUM + food_flags = FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/mushroompizza/New() ..() reagents.add_reagent(NUTRIMENT, 35) bitesize = 2 +/obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/mushroompizza/make_poisonous() + var/original_total_volume = reagents.total_volume + reagents.clear_reagents() + var/static/list/possible_poisons = list( + MINDBREAKER, + SPIRITBREAKER + ) + reagents.add_reagent(pick(possible_poisons), original_total_volume) + /obj/item/weapon/reagent_containers/food/snacks/mushroompizzaslice name = "Mushroompizza slice" desc = "Maybe it is the last slice of pizza in your life." icon_state = "mushroompizzaslice" bitesize = 2 + food_flags = FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/vegetablepizza name = "Vegetable pizza" @@ -2961,6 +3073,7 @@ icon_state = "vegetablepizza" slice_path = /obj/item/weapon/reagent_containers/food/snacks/vegetablepizzaslice w_class = W_CLASS_MEDIUM + food_flags = FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/vegetablepizza/New() ..() @@ -2969,11 +3082,17 @@ reagents.add_reagent(IMIDAZOLINE, 12) bitesize = 2 +/obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/vegetablepizza/make_poisonous() + var/original_total_volume = reagents.total_volume + reagents.clear_reagents() + reagents.add_reagent(MUTAGEN, original_total_volume) + /obj/item/weapon/reagent_containers/food/snacks/vegetablepizzaslice name = "Vegetable pizza slice" desc = "A slice of the most green pizza of all pizzas not containing green ingredients " icon_state = "vegetablepizzaslice" bitesize = 2 + food_flags = FOOD_ANIMAL | FOOD_LACTOSE /obj/item/pizzabox name = "pizza box" @@ -3476,7 +3595,7 @@ storage_slots = 3 w_class = W_CLASS_MEDIUM trash = /obj/item/trash/tray - food_flags = FOOD_SWEET | FOOD_ANIMAL //eggs + food_flags = FOOD_SWEET | FOOD_ANIMAL | FOOD_LACTOSE //eggs /obj/item/weapon/reagent_containers/food/snacks/sliceable/buchedenoel/New() ..() @@ -3491,7 +3610,7 @@ icon_state = "buche_slice" trash = /obj/item/trash/plate bitesize = 2 - food_flags = FOOD_SWEET | FOOD_ANIMAL + food_flags = FOOD_SWEET | FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/sliceable/turkey name = "turkey" @@ -3649,6 +3768,7 @@ desc = "Dangerously cheesy." icon_state = "cheddar_chips" item_state = "cheddar_chips" + food_flags = FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/chips/cookable/cheddar/New() ..() @@ -3708,7 +3828,7 @@ desc = "A large crème caramel" icon_state = "gigapuddi" trash = /obj/item/trash/plate - food_flags = FOOD_ANIMAL //milk + food_flags = FOOD_ANIMAL | FOOD_LACTOSE | FOOD_SWEET /obj/item/weapon/reagent_containers/food/snacks/gigapuddi/New() ..() @@ -3718,7 +3838,6 @@ /obj/item/weapon/reagent_containers/food/snacks/gigapuddi/happy desc = "A large crème caramel made with extra love" icon_state = "happypuddi" - food_flags = FOOD_SWEET /obj/item/weapon/reagent_containers/food/snacks/gigapuddi/anger desc = "A large crème caramel made with extra hate" @@ -3729,7 +3848,7 @@ desc = "A small crème caramel" icon_state = "flan" trash = /obj/item/trash/plate - food_flags = FOOD_SWEET | FOOD_ANIMAL + food_flags = FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/flan/New() ..() @@ -3742,7 +3861,7 @@ desc = "The systematic slavery of an entire society of insects, elegantly sized to fit in your mouth." icon_state = "honeyflan" trash = /obj/item/trash/plate - food_flags = FOOD_SWEET | FOOD_ANIMAL + food_flags = FOOD_SWEET | FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/honeyflan/New() ..() @@ -3774,7 +3893,7 @@ name = "Bluespace-berry Muffin" desc = "Just like a normal blueberry muffin, except with completely unnecessary floaty things!" icon_state = "bluespace" - food_flags = FOOD_SWEET | FOOD_ANIMAL + food_flags = FOOD_SWEET | FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/yellowcake name = "Yellowcake" @@ -3822,7 +3941,7 @@ slices_num = 5 storage_slots = 3 w_class = W_CLASS_MEDIUM - food_flags = FOOD_SWEET | FOOD_ANIMAL + food_flags = FOOD_SWEET | FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/sliceable/chococherrycake/New() ..() @@ -3834,7 +3953,7 @@ icon_state = "chococherrycake_slice" trash = /obj/item/trash/plate bitesize = 2 - food_flags = FOOD_SWEET | FOOD_ANIMAL + food_flags = FOOD_SWEET | FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/sliceable/fruitcake name = "fruitcake" @@ -3845,7 +3964,7 @@ slices_num = 5 storage_slots = 3 w_class = W_CLASS_MEDIUM - food_flags = FOOD_SWEET + food_flags = FOOD_SWEET | FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/sliceable/fruitcake/New() ..() @@ -3858,7 +3977,7 @@ icon_state = "fruitcakeslice" trash = /obj/item/trash/plate bitesize = 2 - food_flags = FOOD_SWEET + food_flags = FOOD_SWEET | FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/sliceable/fruitcake/christmascake name = "\improper Christmas cake" @@ -4015,7 +4134,7 @@ H.stop_pulling() to_chat(H, "You slipped on the [name]!") - playsound(get_turf(src), 'sound/misc/slip.ogg', 50, 1, -3) + playsound(src, 'sound/misc/slip.ogg', 50, 1, -3) H.Stun(3) H.Knockdown(2) @@ -4025,7 +4144,7 @@ name = "Higashikata Special" desc = "9 layer parfait, very expensive." icon_state = "higashikata" - food_flags = FOOD_SWEET | FOOD_ANIMAL + food_flags = FOOD_SWEET | FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/higashikata/New() ..() @@ -4039,7 +4158,7 @@ name = "Sundae" desc = "A colorful ice cream treat." icon_state = "sundae" - food_flags = FOOD_SWEET | FOOD_ANIMAL //milk + food_flags = FOOD_SWEET | FOOD_ANIMAL | FOOD_LACTOSE //milk /obj/item/weapon/reagent_containers/food/snacks/sundae/New() ..() @@ -4052,7 +4171,7 @@ name = "avocado milkshake" desc = "Strange, but good." icon_state = "avocadomilkshake" - food_flags = FOOD_LIQUID | FOOD_SWEET | FOOD_ANIMAL //milk + food_flags = FOOD_LIQUID | FOOD_SWEET | FOOD_ANIMAL | FOOD_LACTOSE //milk trash = /obj/item/weapon/reagent_containers/food/drinks/drinkingglass /obj/item/weapon/reagent_containers/food/snacks/avocadomilkshake/New() @@ -4067,6 +4186,7 @@ desc = "With 21st century technology, it could take as long as three days to make this." icon_state = "potato_salad" trash = /obj/item/trash/snack_bowl + food_flags = FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/potatosalad/New() ..() @@ -4087,6 +4207,7 @@ name = "Risotto" desc = "For the gentleman's wino, this is an offer one cannot refuse." icon_state = "risotto" + food_flags = FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/risotto/New() ..() @@ -4099,7 +4220,7 @@ desc = "Sweet and spicy!" icon_state = "cinnamon_roll" trash = /obj/item/trash/plate - food_flags = FOOD_SWEET + food_flags = FOOD_SWEET | FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/cinnamonroll/New() ..() @@ -4112,7 +4233,7 @@ desc = "Guarranted snail-free!" icon_state = "cinnamon_pie" trash = /obj/item/trash/pietin - food_flags = FOOD_SWEET + food_flags = FOOD_SWEET | FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/cinnamonpie/New() ..() @@ -4509,6 +4630,7 @@ desc = "Also called tarte flambee, literally 'flame cake'. Ancient French and German people once tried not fighting and the result was a pie that is loaded with garlic, burned, and flat." icon_state = "flammkuchen" bitesize = 4 + food_flags = FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/flammkuchen/New() ..() @@ -4573,6 +4695,7 @@ desc = "A burger which uses a sack-shaped plant as a 'bun'. Any sufficiently poor Vox is indistinguishable from a hobo." icon_state = "hoboburger" bitesize = 4 + food_flags = FOOD_ANIMAL | FOOD_LACTOSE | FOOD_MEAT /obj/item/weapon/reagent_containers/food/snacks/hoboburger/New() ..() @@ -4734,6 +4857,7 @@ desc = "Even in space, where a north/south orientation is meaningless, the South will rise again." icon_state = "confederatespirit" bitesize = 2 + food_flags = FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/confederatespirit/New() ..() @@ -4765,6 +4889,7 @@ desc = "The salsa-equivalent of nachos." icon_state = "chilaquiles" bitesize = 1 + food_flags = FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/chilaquiles/New() ..() @@ -4774,6 +4899,7 @@ name = "quiche" desc = "The queechay has a long history of being mispronounced. Just a taste makes you feel more cerebral and cultured!" icon_state = "quiche" + food_flags = FOOD_ANIMAL | FOOD_LACTOSE bitesize = 4 /obj/item/weapon/reagent_containers/food/snacks/quiche/New() @@ -4817,6 +4943,7 @@ desc = "Member Kingston? Member uncapped bombs? Member beardbeard? Member Goonleak? Member the vore raid? Member split departmental access? I member!" icon_state = "grapesalad" bitesize = 2 + food_flags = FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/grapesalad/New() ..() @@ -4838,6 +4965,7 @@ desc = "A favorite of the janitorial staff, who often consider this a native dish. Viva Space Mexico!" icon_state = "mexicansalad" bitesize = 3 + food_flags = FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/mexicansalad/New() ..() @@ -4858,6 +4986,7 @@ name = "bruschetta" desc = "This dish's name probably originates from 'to roast over coals'. You can blame the hippies for banning coal use when the crew complains it isn't authentic." icon_state = "bruschetta" + food_flags = FOOD_ANIMAL | FOOD_LACTOSE bitesize = 1 /obj/item/weapon/reagent_containers/food/snacks/bruschetta/New() @@ -4880,6 +5009,7 @@ desc = "Who knew bacteria could be so helpful?" icon_state = "yoghurt" bitesize = 2 + food_flags = FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/yogurt/New() ..() @@ -4892,6 +5022,7 @@ desc = "Among the most fashionable of fine desserts. A dish fit for a captain." icon_state = "pannacotta" bitesize = 2 + food_flags = FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/pannacotta/New() ..() @@ -4919,6 +5050,7 @@ name = "croissant" desc = "True French cuisine." icon_state = "croissant" + food_flags = FOOD_ANIMAL | FOOD_LACTOSE /obj/item/weapon/reagent_containers/food/snacks/croissant/New() ..() @@ -4930,7 +5062,7 @@ desc = "Fries, cheese & gravy. Your arteries will hate you for this." icon_state = "poutine" trash = /obj/item/trash/plate - food_flags = FOOD_ANIMAL //cheese + food_flags = FOOD_ANIMAL | FOOD_LACTOSE //cheese /obj/item/weapon/reagent_containers/food/snacks/poutine/New() ..() @@ -4941,7 +5073,7 @@ name = "dangerously cheesy poutine" desc = "Fries, cheese, gravy & more cheese. Be careful with this, it's dangerous!" icon_state = "poutinedangerous" - food_flags = FOOD_ANIMAL //cheese + food_flags = FOOD_ANIMAL | FOOD_LACTOSE //cheese /obj/item/weapon/reagent_containers/food/snacks/poutinedangerous/New() ..() @@ -4952,7 +5084,7 @@ name = "dangerously cheesy poutine barrel" desc = "Four cheese wheels full of gravy, fries and cheese curds, arranged like a barrel. This is degeneracy, Canadian style." icon_state = "poutinebarrel" - food_flags = FOOD_ANIMAL //cheese + food_flags = FOOD_ANIMAL | FOOD_LACTOSE //cheese /obj/item/weapon/reagent_containers/food/snacks/poutinebarrel/New() ..() @@ -4974,7 +5106,7 @@ desc = "French fries lathered with Canadian maple syrup and cheese curds. Delightful, eh?" icon_state = "poutinesyrup" trash = /obj/item/trash/plate - food_flags = FOOD_ANIMAL //cheese + food_flags = FOOD_ANIMAL | FOOD_LACTOSE //cheese /obj/item/weapon/reagent_containers/food/snacks/poutinesyrup/New() ..() @@ -5034,7 +5166,7 @@ bitesize = 3 storage_slots = 1 w_class = W_CLASS_MEDIUM - food_flags = FOOD_ANIMAL //cheese + food_flags = FOOD_ANIMAL | FOOD_LACTOSE //cheese /obj/item/weapon/reagent_containers/food/snacks/lasagna/New() ..() @@ -5057,6 +5189,7 @@ var/global/list/bomb_like_items = list(/obj/item/device/transfer_valve, /obj/ite icon = 'icons/obj/seafood.dmi' icon_state = "fishfillet" filling_color = "#FFDEFE" + food_flags = FOOD_MEAT /obj/item/weapon/reagent_containers/food/snacks/salmonmeat/New() ..() @@ -5070,7 +5203,7 @@ var/global/list/bomb_like_items = list(/obj/item/device/transfer_valve, /obj/ite icon_state = "salmonsteak" trash = /obj/item/trash/plate filling_color = "#7A3D11" - + food_flags = FOOD_MEAT /obj/item/weapon/reagent_containers/food/snacks/salmonsteak/New() ..() @@ -5083,6 +5216,7 @@ var/global/list/bomb_like_items = list(/obj/item/device/transfer_valve, /obj/ite icon = 'icons/obj/seafood.dmi' icon_state = "fishfillet" filling_color = "#FFDEFE" + food_flags = FOOD_MEAT /obj/item/weapon/reagent_containers/food/snacks/catfishmeat/New() @@ -5090,11 +5224,38 @@ var/global/list/bomb_like_items = list(/obj/item/device/transfer_valve, /obj/ite reagents.add_reagent(NUTRIMENT, 5) bitesize = 6 +/obj/item/weapon/reagent_containers/food/snacks/glofishmeat + name = "raw glofish" + desc = "A fillet of raw glofish. The bioluminescence glands have been removed." + icon = 'icons/obj/seafood.dmi' + icon_state = "fishfillet" + filling_color = "#FFDEFE" + food_flags = FOOD_MEAT + +/obj/item/weapon/reagent_containers/food/snacks/glofishmeat/New() + ..() + reagents.add_reagent(NUTRIMENT, 2) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/goldfishmeat + name = "raw goldfish" + desc = "A fillet of raw goldfish, the golden carp." + icon = 'icons/obj/seafood.dmi' + icon_state = "fishfillet" + filling_color = "#FFDEFE" + food_flags = FOOD_MEAT + +/obj/item/weapon/reagent_containers/food/snacks/goldfishmeat/New() + ..() + reagents.add_reagent(NUTRIMENT, 2) + bitesize = 2 + /obj/item/weapon/reagent_containers/food/snacks/fried_shrimp name = "fried shrimp" desc = "Just one of the many things you can do with shrimp!" icon = 'icons/obj/seafood.dmi' icon_state = "shrimp_fried" + food_flags = FOOD_MEAT /obj/item/weapon/reagent_containers/food/snacks/fried_shrimp/New() ..() @@ -5106,6 +5267,8 @@ var/global/list/bomb_like_items = list(/obj/item/device/transfer_valve, /obj/ite desc = "Just one of the many things you can do with shrimp!" icon = 'icons/obj/seafood.dmi' icon_state = "shrimp_cooked" + food_flags = FOOD_MEAT + /obj/item/weapon/reagent_containers/food/snacks/boiled_shrimp/New() ..() reagents.add_reagent(NUTRIMENT, 2) @@ -5116,6 +5279,7 @@ var/global/list/bomb_like_items = list(/obj/item/device/transfer_valve, /obj/ite desc = "A simple sushi consisting of cooked shrimp and rice." icon = 'icons/obj/seafood.dmi' icon_state = "sushi_Ebi" + food_flags = FOOD_MEAT /obj/item/weapon/reagent_containers/food/snacks/sushi_Ebi/New() ..() @@ -5127,6 +5291,8 @@ var/global/list/bomb_like_items = list(/obj/item/device/transfer_valve, /obj/ite desc = "A simple sushi consisting of salmon roe." icon = 'icons/obj/seafood.dmi' icon_state = "sushi_Ikura" + food_flags = FOOD_MEAT + /obj/item/weapon/reagent_containers/food/snacks/sushi_Ikura/New() ..() reagents.add_reagent(NUTRIMENT, 3) @@ -5137,6 +5303,7 @@ var/global/list/bomb_like_items = list(/obj/item/device/transfer_valve, /obj/ite desc = "A simple sushi consisting of raw salmon and rice." icon = 'icons/obj/seafood.dmi' icon_state = "sushi_Sake" + food_flags = FOOD_MEAT /obj/item/weapon/reagent_containers/food/snacks/sushi_Sake/New() ..() @@ -5148,6 +5315,7 @@ var/global/list/bomb_like_items = list(/obj/item/device/transfer_valve, /obj/ite desc = "A simple sushi consisting of cooked salmon and rice." icon = 'icons/obj/seafood.dmi' icon_state = "sushi_SmokedSalmon" + food_flags = FOOD_MEAT /obj/item/weapon/reagent_containers/food/snacks/sushi_SmokedSalmon/New() ..() @@ -5159,6 +5327,7 @@ var/global/list/bomb_like_items = list(/obj/item/device/transfer_valve, /obj/ite desc = "A simple sushi consisting of egg and rice." icon = 'icons/obj/seafood.dmi' icon_state = "sushi_Tamago" + food_flags = FOOD_MEAT /obj/item/weapon/reagent_containers/food/snacks/sushi_Tamago/New() ..() @@ -5170,6 +5339,7 @@ var/global/list/bomb_like_items = list(/obj/item/device/transfer_valve, /obj/ite desc = "A piece of fried tofu stuffed with rice." icon = 'icons/obj/seafood.dmi' icon_state = "sushi_Inari" + food_flags = FOOD_MEAT /obj/item/weapon/reagent_containers/food/snacks/sushi_Inari/New() ..() @@ -5181,6 +5351,7 @@ var/global/list/bomb_like_items = list(/obj/item/device/transfer_valve, /obj/ite desc = "A simple sushi consisting of goldfish roe." icon = 'icons/obj/seafood.dmi' icon_state = "sushi_Masago" + food_flags = FOOD_MEAT /obj/item/weapon/reagent_containers/food/snacks/sushi_Masago/New() ..() @@ -5192,6 +5363,7 @@ var/global/list/bomb_like_items = list(/obj/item/device/transfer_valve, /obj/ite desc = "A simple sushi consisting of shark roe." icon = 'icons/obj/seafood.dmi' icon_state = "sushi_Masago" + food_flags = FOOD_MEAT /obj/item/weapon/reagent_containers/food/snacks/sushi_Tobiko/New() ..() @@ -5203,6 +5375,7 @@ var/global/list/bomb_like_items = list(/obj/item/device/transfer_valve, /obj/ite desc = "A sushi consisting of shark roe and an egg." icon = 'icons/obj/seafood.dmi' icon_state = "sushi_TobikoEgg" + food_flags = FOOD_MEAT /obj/item/weapon/reagent_containers/food/snacks/sushi_TobikoEgg/New() ..() @@ -5215,6 +5388,7 @@ var/global/list/bomb_like_items = list(/obj/item/device/transfer_valve, /obj/ite icon = 'icons/obj/seafood.dmi' icon_state = "sushi_Tai" bitesize = 3 + food_flags = FOOD_MEAT /obj/item/weapon/reagent_containers/food/snacks/sushi_Tai/New() ..() @@ -5226,9 +5400,283 @@ var/global/list/bomb_like_items = list(/obj/item/device/transfer_valve, /obj/ite desc = "A simple sushi consisting of eel and rice." icon = 'icons/obj/seafood.dmi' icon_state = "sushi_Hokki" + food_flags = FOOD_MEAT /obj/item/weapon/reagent_containers/food/snacks/sushi_Unagi/New() ..() reagents.add_reagent(NUTRIMENT, 2) - bitesize = 3 \ No newline at end of file + bitesize = 3 + +/obj/item/weapon/reagent_containers/food/snacks/sushi_avocado + name = "Avocado Sushi" + desc = "A simple sushi consisting of avocado and rice." + icon = 'icons/obj/seafood.dmi' + icon_state = "sushi_avocado" + bitesize = 3 + +/obj/item/weapon/reagent_containers/food/snacks/sushi_avocado/New() + ..() + reagents.add_reagent(NUTRIMENT, 1) + +/obj/item/weapon/reagent_containers/food/snacks/friedshrimp + name = "fried shrimp" + desc = "For such a little dish, it's surprisingly high calorie." + icon = 'icons/obj/seafood.dmi' + icon_state = "shrimp_fried" + bitesize = 3 + food_flags = FOOD_MEAT + +/obj/item/weapon/reagent_containers/food/snacks/friedshrimp/New() + ..() + reagents.add_reagent(CORNOIL, 3) + +/obj/item/weapon/reagent_containers/food/snacks/soyscampi + name = "soy scampi" + desc = "A simple shrimp dish presented bathed in soy sauce." + icon = 'icons/obj/seafood.dmi' + icon_state = "soyscampi" + bitesize = 3 + food_flags = FOOD_MEAT + +/obj/item/weapon/reagent_containers/food/snacks/soyscampi/New() + ..() + reagents.add_reagent(NUTRIMENT, 1) + reagents.add_reagent(SOYSAUCE, 2) + +/obj/item/weapon/reagent_containers/food/snacks/shrimpcocktail + name = "shrimp cocktail" + desc = "An hors d'oeuvre which has traditionally swung like a pendulum between the height of fashion and ironically passe." + icon = 'icons/obj/seafood.dmi' + icon_state = "shrimpcocktail" + bitesize = 3 + food_flags = FOOD_MEAT + +/obj/item/weapon/reagent_containers/food/snacks/shrimpcocktail/New() + ..() + reagents.add_reagent(NUTRIMENT, 2) + if(prob(50)) + desc += " This one is ironic." + reagents.add_reagent(HONKSERUM, 1) + else + desc += " This one is high fashion." + reagents.add_reagent(MINTTOXIN, 1) + +/obj/item/weapon/reagent_containers/food/snacks/friedcatfish + name = "fried catfish" + desc = "A traditional catfish fry. It's positively coated in oils." + icon = 'icons/obj/seafood.dmi' + icon_state = "friedcatfish" + bitesize = 3 + food_flags = FOOD_MEAT + +/obj/item/weapon/reagent_containers/food/snacks/friedcatfish/New() + ..() + reagents.add_reagent(CORNOIL, 3) + +/obj/item/weapon/reagent_containers/food/snacks/catfishgumbo + name = "catfish gumbo" + desc = "A traditional, thick cajun broth. Made with bottom-feeders for bottom-feeders." + icon = 'icons/obj/seafood.dmi' + icon_state = "catfishgumbo" + bitesize = 3 + food_flags = FOOD_MEAT + +/obj/item/weapon/reagent_containers/food/snacks/catfishgumbo/New() + ..() + reagents.add_reagent(NUTRIMENT, 6) + +/obj/item/weapon/reagent_containers/food/snacks/catfishcourtbouillon + name = "catfish courtbouillon" + desc = "A lightly breaded catfish fillet poached in a spicy hot-sauce short broth." + icon = 'icons/obj/seafood.dmi' + icon_state = "catfishcourtbouillon" + bitesize = 3 + food_flags = FOOD_MEAT + +/obj/item/weapon/reagent_containers/food/snacks/catfishcourtbouillon/New() + ..() + reagents.add_reagent(NUTRIMENT, 6) + reagents.add_reagent(CAPSAICIN, 3) + +/obj/item/weapon/reagent_containers/food/snacks/smokedsalmon + name = "smoked salmon" + desc = "Perhaps the best known method of preparing salmon, smoking has been used to preserve fish for most of recorded history. The subtleties of avoiding overpowering the fatty, rich flavor of the salmon with the smoke make this a difficult dish to master." + icon = 'icons/obj/seafood.dmi' + icon_state = "smokedsalmon" + bitesize = 3 + food_flags = FOOD_MEAT + +/obj/item/weapon/reagent_containers/food/snacks/smokedsalmon/New() + ..() + reagents.add_reagent(NUTRIMENT, 6) + +/obj/item/weapon/reagent_containers/food/snacks/planksalmon + name = "plank-grilled salmon" + desc = "A simple dish that grills the flavor of wood into the meat, leaving you with a charred but workable plate in the process." + icon = 'icons/obj/seafood.dmi' + icon_state = "planksalmon" + bitesize = 3 + food_flags = FOOD_MEAT + trash = /obj/item/stack/sheet/wood + +/obj/item/weapon/reagent_containers/food/snacks/planksalmon/New() + ..() + reagents.add_reagent(NUTRIMENT, 6) + +/obj/item/weapon/reagent_containers/food/snacks/citrussalmon + name = "citrus-baked salmon" + desc = "The piquant, almost sour flavor of the citrus fruit is baked into the fish under dry heat, to give it powerful attaque to balance its rich aftertaste." + icon = 'icons/obj/seafood.dmi' + icon_state = "citrussalmon" + bitesize = 3 + food_flags = FOOD_MEAT + +/obj/item/weapon/reagent_containers/food/snacks/citrussalmon/New() + ..() + reagents.add_reagent(NUTRIMENT, 8) + +/obj/item/weapon/reagent_containers/food/snacks/salmonavocado + name = "salmon avocado salad" + desc = "The creamy, buttery taste of the avocado brings unity to the nutty, meaty taste of the mushrooms and the fatty, rich taste of the salmon." + icon = 'icons/obj/seafood.dmi' + icon_state = "salmonavocado" + bitesize = 3 + food_flags = FOOD_MEAT + +/obj/item/weapon/reagent_containers/food/snacks/salmonavocado/New() + ..() + reagents.add_reagent(NUTRIMENT, 8) + +/obj/item/weapon/reagent_containers/food/snacks/rumshark + name = "spiced rum shark supreme" + desc = "When you really need something to get this party started. A savory dish enriched by alcohol." + icon = 'icons/obj/seafood.dmi' + icon_state = "rumshark" + bitesize = 3 + food_flags = FOOD_MEAT + +/obj/item/weapon/reagent_containers/food/snacks/rumshark/New() + ..() + reagents.add_reagent(NUTRIMENT, 6) + reagents.add_reagent(RUM, 15) + + +/obj/item/weapon/reagent_containers/food/snacks/akutaq + name = "glofish akutaq" + desc = "This eskimo dish literally means 'something mixed'. The fat of glowish is rendered down and mixed with milk and glowberries to make a surprisingly tasty dessert dish." + icon = 'icons/obj/seafood.dmi' + icon_state = "akutaq" + bitesize = 3 + food_flags = FOOD_MEAT | FOOD_SWEET | FOOD_LACTOSE + +/obj/item/weapon/reagent_containers/food/snacks/akutaq/New() + ..() + reagents.add_reagent(NUTRIMENT, 1) + reagents.add_reagent(SUGAR, 6) + +/obj/item/weapon/reagent_containers/food/snacks/carpcurry + name = "golden carp curry" + desc = "A simple traditional Space Japan curry with tangy golden carp meat." + icon = 'icons/obj/seafood.dmi' + icon_state = "carpcurry" + bitesize = 3 + food_flags = FOOD_MEAT + +/obj/item/weapon/reagent_containers/food/snacks/carpcurry/New() + ..() + reagents.add_reagent(NUTRIMENT, 6) + +/obj/item/weapon/reagent_containers/food/snacks/carpconsomme + name = "golden carp consomme" + desc = "A clear soup made from a concentrated broth of fish and egg whites. It's light on calories and makes you feel much more cultured." + icon = 'icons/obj/seafood.dmi' + icon_state = "carpconsomme" + bitesize = 3 + food_flags = FOOD_MEAT + +/obj/item/weapon/reagent_containers/food/snacks/carpconsomme/New() + ..() + reagents.add_reagent(NUTRIMENT, 2) + reagents.add_reagent(METHYLIN,5) + +obj/item/weapon/reagent_containers/food/snacks/butterstick + name = "butter on a stick" + desc = "The clown told you to make this." + icon_state = "butter_stick" + bitesize = 3 + food_flags = FOOD_ANIMAL + +/obj/item/weapon/reagent_containers/food/snacks/butterstick/Crossed(atom/movable/O) + if (istype(O, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = O + if (H.CheckSlip() < 1) + return + + H.stop_pulling() + to_chat(H, "You slipped on the [name]!") + playsound((src), 'sound/misc/slip.ogg', 50, 1, -3) + H.Stun(4) + H.Knockdown(3) + new/obj/effect/decal/cleanable/smashed_butter(src.loc) + qdel(src) + +/obj/item/weapon/reagent_containers/food/snacks/butterstick/New() + ..() + reagents.add_reagent(NUTRIMENT, 1) + +/obj/item/weapon/reagent_containers/food/snacks/sliceable/ambrosia_brownies + name = "brownie sheet" + desc = "Give them to your friends." + icon_state = "ambrosia_brownies" + slice_path = /obj/item/weapon/reagent_containers/food/snacks/ambrosia_brownie + slices_num = 6 + storage_slots = 3 + w_class = W_CLASS_MEDIUM + food_flags = FOOD_SWEET | FOOD_ANIMAL + +/obj/item/weapon/reagent_containers/food/snacks/sliceable/ambrosia_brownies/New() + ..() + reagents.add_reagent(NUTRIMENT, 2) + +/obj/item/weapon/reagent_containers/food/snacks/ambrosia_brownie + name = "brownie" + desc = "A brownie that may or may not get you sky high." + icon_state = "ambrosia_brownie" + food_flags = FOOD_SWEET | FOOD_ANIMAL + +obj/item/weapon/reagent_containers/food/snacks/butterfingers_r + name = "butter fingers" + desc = "It's a microwaved hand slathered in butter!" + icon_state = "butterfingers_r" + trash = /obj/item/trash/plate + food_flags = FOOD_ANIMAL | FOOD_MEAT + +/obj/item/weapon/reagent_containers/food/snacks/butterfingers_r/New() + ..() + reagents.add_reagent(NUTRIMENT, 2) + +obj/item/weapon/reagent_containers/food/snacks/butterfingers_l + name = "butter fingers" + desc = "It's a microwaved hand slathered in butter!" + icon_state = "butterfingers_l" + trash = /obj/item/trash/plate + food_flags = FOOD_ANIMAL | FOOD_MEAT + +/obj/item/weapon/reagent_containers/food/snacks/butterfingers_l/New() + ..() + reagents.add_reagent(NUTRIMENT, 2) + +obj/item/weapon/reagent_containers/food/snacks/butteredtoast + name = "buttered toast" + desc = "Toasted bread with butter on it." + icon_state = "butteredtoast" + food_flags = FOOD_ANIMAL + +/obj/item/weapon/reagent_containers/food/snacks/butterfedtoast/New() + ..() + reagents.add_reagent(NUTRIMENT, 2) + + + + diff --git a/code/modules/reagents/reagent_containers/food/snacks/egg.dm b/code/modules/reagents/reagent_containers/food/snacks/egg.dm index f5351637c8f..9c2038df14a 100644 --- a/code/modules/reagents/reagent_containers/food/snacks/egg.dm +++ b/code/modules/reagents/reagent_containers/food/snacks/egg.dm @@ -66,7 +66,7 @@ if (istype(W, /obj/item/weapon/reagent_containers)) if(W.reagents.amount_cache.len == 1 && W.reagents.has_reagent(FLOUR, 5)) W.reagents.remove_reagent(FLOUR,5) - new /obj/item/weapon/reagent_containers/food/snacks/dough(loc) + new /obj/item/weapon/reagent_containers/food/snacks/dough(get_turf(src)) to_chat(user, "You make some dough.") qdel(src) return 1 @@ -109,3 +109,16 @@ ..() reagents.add_reagent(PETRITRICIN, rand(5,15)/10) + +/obj/item/weapon/reagent_containers/food/snacks/egg/bigroach + name = "mutated cockroach eggs" + desc = "A bunch of strange-looking, weirdly glowing eggs." + icon_state = "egg-bigroach" + can_color = FALSE + hatch_type = /mob/living/simple_animal/hostile/bigroach + +/obj/item/weapon/reagent_containers/food/snacks/egg/bigroach/New() + ..() + + reagents.add_reagent(TOXIN, rand(5,15)) + reagents.add_reagent(RADIUM, rand(1,5)) diff --git a/code/modules/reagents/reagent_containers/food/snacks/grown.dm b/code/modules/reagents/reagent_containers/food/snacks/grown.dm index b388ab05787..4a3bdeb2d74 100644 --- a/code/modules/reagents/reagent_containers/food/snacks/grown.dm +++ b/code/modules/reagents/reagent_containers/food/snacks/grown.dm @@ -233,47 +233,24 @@ var/list/special_fruits = list() var/datum/zLevel/L = get_z_level(src) if(!L || L.teleJammed) return 0 - - var/outer_teleport_radius = potency/10 //Plant potency determines radius of teleport. - var/inner_teleport_radius = potency/15 //At base potency, nothing will happen, since the radius is 0. - if(inner_teleport_radius < 1) - return 0 - - var/list/turfs = new/list() - //This could likely use some standardization but I have no idea how to not break it. - for(var/turf/T in trange(outer_teleport_radius, get_turf(hit_atom))) - if(get_dist(T, hit_atom) <= inner_teleport_radius) - continue - if(is_blocked_turf(T) || istype(T, /turf/space)) - continue - if(T.x > world.maxx-outer_teleport_radius || T.x < outer_teleport_radius) - continue - if(T.y > world.maxy-outer_teleport_radius || T.y < outer_teleport_radius) - continue - turfs += T - if(!turfs.len) - var/list/turfs_to_pick_from = list() - for(var/turf/T in trange(outer_teleport_radius, get_turf(hit_atom))) - if(get_dist(T, hit_atom) > inner_teleport_radius) - turfs_to_pick_from += T - turfs += pick(/turf in turfs_to_pick_from) - var/turf/picked = pick(turfs) + var/picked = pick_rand_tele_turf(hit_atom, potency/15, potency/10) // Does nothing at base potency since inner_radius == 0 if(!isturf(picked)) return 0 - switch(rand(1, 2)) //50-50 % chance to teleport the thrower or the target. - if(1) //Teleports the person who threw the fruit - spark(M) - new/obj/effect/decal/cleanable/molten_item(M.loc) //Leaves a pile of goo behind for dramatic effect. - M.forceMove(picked) //Send then to that location we picked previously + var/turf/hit_turf = get_turf(hit_atom) + var/turf_has_mobs = locate(/mob) in hit_turf + if((!istype(M) || prob(50)) && turf_has_mobs) //50% chance to teleport the person who was hit by the fruit + spark(hit_atom) + new/obj/effect/decal/cleanable/molten_item(hit_turf) //Leave a pile of goo behind for dramatic effect... + for(var/mob/A in hit_turf) //For the mobs in the tile that was hit... + A.forceMove(picked) //And teleport them to the chosen location. spawn() - spark(M) //Two set of sparks, one before the teleport and one after. //Sure then ? - if(2) //Teleports the target instead. - spark(hit_atom) - new/obj/effect/decal/cleanable/molten_item(get_turf(hit_atom)) //Leave a pile of goo behind for dramatic effect... - for(var/mob/A in get_turf(hit_atom)) //For the mobs in the tile that was hit... - A.forceMove(picked) //And teleport them to the chosen location. - spawn() - spark(A) + spark(A) + else //Teleports the thrower instead. + spark(M) + new/obj/effect/decal/cleanable/molten_item(M.loc) //Leaves a pile of goo behind for dramatic effect. + M.forceMove(picked) //Send then to that location we picked previously + spawn() + spark(M) //Two set of sparks, one before the teleport and one after. //Sure then ? return 1 @@ -574,6 +551,21 @@ var/list/special_fruits = list() trash = /obj/item/weapon/bananapeel plantname = "banana" +/obj/item/weapon/reagent_containers/food/snacks/grown/bluespacebanana + name = "bluespace banana" + desc = "It's an excellent prop for a comedy." + icon = 'icons/obj/items.dmi' + icon_state = "bluespacebanana" + item_state = "bluespacebanana" + filling_color = "#FCF695" + plantname = "bluespacebanana" + +/obj/item/weapon/reagent_containers/food/snacks/grown/bluespacebanana/after_consume(var/mob/user, var/datum/reagents/reagentreference) + var/obj/item/weapon/bananapeel/bluespace/peel = new + peel.potency = potency + trash = peel + ..() + /obj/item/weapon/reagent_containers/food/snacks/grown/chili name = "chili" desc = "It's spicy! Wait... IT'S BURNING ME!!" @@ -694,7 +686,7 @@ var/list/special_fruits = list() /obj/item/weapon/reagent_containers/food/snacks/grown/ghostpepper/spook() visible_message("A specter takes a bite of \the [src] from beyond the grave!") - playsound(get_turf(src),'sound/items/eatfood.ogg', rand(10,50), 1) + playsound(src,'sound/items/eatfood.ogg', rand(10,50), 1) bitecount++ reagents.remove_any(bitesize) if(!reagents.total_volume) @@ -872,7 +864,7 @@ var/list/special_fruits = list() if(C.CheckSlip() < 1) continue C.Knockdown(5) - playsound(get_turf(src), 'sound/effects/bang.ogg', 10, 1) + playsound(src, 'sound/effects/bang.ogg', 10, 1) qdel(src) /obj/item/weapon/reagent_containers/food/snacks/grown/nofruit @@ -938,11 +930,11 @@ var/list/special_fruits = list() if(get_turf(user)) switch(N) if(1) - playsound(get_turf(user), 'sound/weapons/genhit1.ogg', 50, 1) + playsound(user, 'sound/weapons/genhit1.ogg', 50, 1) if(2) - playsound(get_turf(user), 'sound/weapons/genhit2.ogg', 50, 1) + playsound(user, 'sound/weapons/genhit2.ogg', 50, 1) if(3) - playsound(get_turf(user), 'sound/weapons/genhit3.ogg', 50, 1) + playsound(user, 'sound/weapons/genhit3.ogg', 50, 1) if(W) user.visible_message("[user] smacks \the [src] with \the [W].","You smack \the [src] with \the [W].") else diff --git a/code/modules/reagents/reagent_containers/food/snacks/meat.dm b/code/modules/reagents/reagent_containers/food/snacks/meat.dm index 89bf934f911..b30f3fcd7ab 100644 --- a/code/modules/reagents/reagent_containers/food/snacks/meat.dm +++ b/code/modules/reagents/reagent_containers/food/snacks/meat.dm @@ -161,23 +161,34 @@ /obj/item/weapon/reagent_containers/food/snacks/meat/roach/New() ..() - reagents.add_reagent(NUTRIMENT, 5) - reagents.add_reagent(ROACHSHELL, rand(5,12)) + reagents.add_reagent(NUTRIMENT, 0.5) + reagents.add_reagent(ROACHSHELL, rand(2,6)) bitesize = 5 +/obj/item/weapon/reagent_containers/food/snacks/meat/roach/big + desc = "A chunk of meat from an above-average sized cockroach." + icon_state = "bigroachmeat" + +/obj/item/weapon/reagent_containers/food/snacks/meat/roach/big/New() + ..() + reagents.add_reagent(NUTRIMENT, 5) + reagents.add_reagent(ROACHSHELL, 16) + /obj/item/weapon/reagent_containers/food/snacks/meat/mimic name = "mimic meat" desc = "Woah! You were eating THIS all along?" icon_state = "rottenmeat" + var/transformed = FALSE - New() - ..() - reagents.add_reagent(SPACE_DRUGS, rand(0,8)) - reagents.add_reagent(MINDBREAKER, rand(0,2)) - reagents.add_reagent(NUTRIMENT, rand(0,8)) - bitesize = 5 +/obj/item/weapon/reagent_containers/food/snacks/meat/mimic/New() + ..() + reagents.add_reagent(SPACE_DRUGS, rand(0,4)) + reagents.add_reagent(MINDBREAKER, rand(0,2)) + reagents.add_reagent(NUTRIMENT, rand(0,4)) + reagents.add_reagent(TOXIN, rand(0,2)) + bitesize = 5 - shapeshift() + shapeshift() /obj/item/weapon/reagent_containers/food/snacks/meat/mimic/bless() visible_message("\The [src] starts fizzling!") @@ -191,11 +202,51 @@ var/global/list/valid_random_food_types = existing_typesof(/obj/item/weapon/reagent_containers/food/snacks) - typesof(/obj/item/weapon/reagent_containers/food/snacks/customizable) +/obj/item/weapon/reagent_containers/food/snacks/meat/mimic/before_consume(mob/target) + if(transformed) + //Reference to that winnie pooh comic + to_chat(target, "Sweet Jesus[target.hallucinating() ? ", Pooh" : ""]! That's not [name]!") + revert() + + spawn(10) + to_chat(target, "You're eating [name]!") + +/obj/item/weapon/reagent_containers/food/snacks/meat/mimic/preattack(atom/movable/target, mob/user, proximity_flag) + if(!proximity_flag) + return + + //Forbid creation of custom foods with mimic meat + if(transformed) + if(istype(target, /obj/item/trash/plate) || istype(target, /obj/item/weapon/reagent_containers/food/snacks)) + to_chat(user, "\The [name] shapeshifts as it touches \the [target]!") + revert() + + return ..() + +/obj/item/weapon/reagent_containers/food/snacks/meat/mimic/forceMove(atom/destination) + if(transformed && istype(destination, /obj/machinery/cooking)) + revert() + + return ..() + /obj/item/weapon/reagent_containers/food/snacks/meat/mimic/proc/shapeshift(atom/atom_to_copy = null) if(!atom_to_copy) atom_to_copy = pick(valid_random_food_types) - src.appearance = initial(atom_to_copy.appearance) //This works! + //Prevent layering issues when items are held in hands + var/prev_layer = src.layer + var/prev_plane = src.plane + + appearance = initial(atom_to_copy.appearance) + + layer = prev_layer + plane = prev_plane + + transformed = TRUE + +/obj/item/weapon/reagent_containers/food/snacks/meat/mimic/proc/revert() + shapeshift(/obj/item/weapon/reagent_containers/food/snacks/meat/mimic) + transformed = FALSE /obj/item/weapon/reagent_containers/food/snacks/meat/box name = "box meat" @@ -235,3 +286,19 @@ var/global/list/valid_random_food_types = existing_typesof(/obj/item/weapon/reag reagents.add_reagent(PETRITRICIN, 3) +/obj/item/weapon/reagent_containers/food/snacks/meat/wendigo + name = "strange meat" + desc = "Doesn't look very appetizing, but if you're considerably hungry..." + icon_state = "wendigo_meat" + bitesize = 30 + +/obj/item/weapon/reagent_containers/food/snacks/meat/wendigo/New() + ..() + reagents.add_reagent(NUTRIMENT, rand(10,25)) + + +/obj/item/weapon/reagent_containers/food/snacks/meat/wendigo/consume(mob/living/carbon/eater, messages = 0) + . = ..() + if(ishuman(eater)) + eater.contract_disease(new /datum/disease/wendigo_transformation) + diff --git a/code/modules/reagents/reagent_containers/glass.dm b/code/modules/reagents/reagent_containers/glass.dm index a39f53e9274..e0ce8934f25 100644 --- a/code/modules/reagents/reagent_containers/glass.dm +++ b/code/modules/reagents/reagent_containers/glass.dm @@ -14,6 +14,7 @@ possible_transfer_amounts = list(5,10,15,25,30,50) volume = 50 flags = FPRINT | OPENCONTAINER + layer = ABOVE_OBJ_LAYER //This is absolutely terrible // TODO To remove this, return 1 on every attackby() that handles reagent_containers. @@ -89,7 +90,7 @@ var/transfer_result = transfer(target, user, splashable_units = -1) // Potentially splash with everything inside if((transfer_result > 10) && (isturf(target) || istype(target, /obj/machinery/portable_atmospherics/hydroponics))) //if we're splashing a decent amount of reagent on the floor - playsound(get_turf(target), 'sound/effects/slosh.ogg', 25, 1) //or in an hydro tray, then we make some noise. + playsound(target, 'sound/effects/slosh.ogg', 25, 1) //or in an hydro tray, then we make some noise. /obj/item/weapon/reagent_containers/glass/attackby(obj/item/weapon/W as obj, mob/user as mob) if(istype(W, /obj/item/weapon/pen) || istype(W, /obj/item/device/flashlight/pen)) @@ -134,21 +135,21 @@ return 1 src.reagents.trans_to(M, 1) to_chat(user, "You barely manage to wet [M]") - playsound(get_turf(src), 'sound/effects/slosh.ogg', 25, 1) + playsound(src, 'sound/effects/slosh.ogg', 25, 1) if(30 to 100) if(M.reagents.total_volume >= 5) to_chat(user, "You dip \the [M]'s head into \the [src] but don't soak anything up.") return 1 src.reagents.trans_to(M, 2) to_chat(user, "You manage to wet [M]") - playsound(get_turf(src), 'sound/effects/slosh.ogg', 25, 1) + playsound(src, 'sound/effects/slosh.ogg', 25, 1) if(100 to INFINITY) if(M.reagents.total_volume >= 10) to_chat(user, "You dip \the [M]'s head into \the [src] but don't soak anything up.") return 1 src.reagents.trans_to(M, 5) to_chat(user, "You manage to soak [M]") - playsound(get_turf(src), 'sound/effects/slosh.ogg', 25, 1) + playsound(src, 'sound/effects/slosh.ogg', 25, 1) else to_chat(user, "What") return 1 @@ -327,21 +328,21 @@ return 1 src.reagents.trans_to(M, 1) to_chat(user, "You barely manage to wet [M]") - playsound(get_turf(src), 'sound/effects/slosh.ogg', 25, 1) + playsound(src, 'sound/effects/slosh.ogg', 25, 1) if(30 to 100) if(M.reagents.total_volume >= 5) to_chat(user, "You dip \the [M]'s head into \the [src] but don't soak anything up.") return 1 src.reagents.trans_to(M, 2) to_chat(user, "You manage to wet [M]") - playsound(get_turf(src), 'sound/effects/slosh.ogg', 25, 1) + playsound(src, 'sound/effects/slosh.ogg', 25, 1) if(100 to INFINITY) if(M.reagents.total_volume >= 10) to_chat(user, "You dip \the [M]'s head into \the [src] but don't soak anything up.") return 1 src.reagents.trans_to(M, 5) to_chat(user, "You manage to soak [M]") - playsound(get_turf(src), 'sound/effects/slosh.ogg', 25, 1) + playsound(src, 'sound/effects/slosh.ogg', 25, 1) else to_chat(user, "What") return 1 diff --git a/code/modules/reagents/reagent_containers/glass/bottle.dm b/code/modules/reagents/reagent_containers/glass/bottle.dm index 273f810dd7d..318a79144fb 100644 --- a/code/modules/reagents/reagent_containers/glass/bottle.dm +++ b/code/modules/reagents/reagent_containers/glass/bottle.dm @@ -30,7 +30,7 @@ else src.reagents.trans_to(M, 1) to_chat(user, "You barely manage to wet [M]") - playsound(get_turf(src), 'sound/effects/slosh.ogg', 25, 1) + playsound(src, 'sound/effects/slosh.ogg', 25, 1) else to_chat(user, "Nothing left to wet [M] with!") return 1 diff --git a/code/modules/reagents/reagent_containers/glass/jar.dm b/code/modules/reagents/reagent_containers/glass/jar.dm new file mode 100644 index 00000000000..346a7508a3f --- /dev/null +++ b/code/modules/reagents/reagent_containers/glass/jar.dm @@ -0,0 +1,125 @@ +/obj/item/weapon/reagent_containers/glass/jar + name = "jar" + desc = "A large jar." + icon = 'icons/obj/chemical.dmi' + icon_state = "jar" + amount_per_transfer_from_this = 10 + possible_transfer_amounts = list(5,10,15,25,30) + flags = FPRINT | OPENCONTAINER + volume = 250 + starting_materials = list(MAT_GLASS = CC_PER_SHEET_GLASS+250) + w_type = RECYK_GLASS + w_class = W_CLASS_MEDIUM + melt_temperature = MELTPOINT_GLASS + origin_tech = Tc_MATERIALS + "=1" + var/obj/held_item = null + +/obj/item/weapon/reagent_containers/glass/jar/New() + ..() + processing_objects.Add(src) + +/obj/item/weapon/reagent_containers/glass/jar/Destroy() + qdel(held_item) + held_item = null + processing_objects.Remove(src) + ..() + +/obj/item/weapon/reagent_containers/glass/jar/update_icon() + overlays.len = 0 + underlays.len = 0 + if(reagents.total_volume) + var/image/filling = image('icons/obj/reagentfillings.dmi', src, "[icon_state]5") + + var/percent = round((reagents.total_volume / volume) * 100) + switch(percent) //Percentages are pretty fucked so here comes the decimal rollercoaster with halfway rounding + if(0 to 24) + filling.icon_state = "[icon_state]10" + if(25 to 49) + filling.icon_state = "[icon_state]25" + if(50 to 74) + filling.icon_state = "[icon_state]50" + if(75 to 99) + filling.icon_state = "[icon_state]75" + else + filling.icon_state = "[icon_state]100" + + filling.icon += mix_color_from_reagents(reagents.reagent_list) + filling.alpha = mix_alpha_from_reagents(reagents.reagent_list) + overlays += filling + + if(held_item) + var/mutable_appearance/contained_within = image("icon"=held_item) + var/matrix/M = matrix() + M.Scale(0.4, 0.4) + contained_within.transform = M + underlays += contained_within + +/obj/item/weapon/reagent_containers/glass/jar/attackby(obj/item/I, mob/user, params) + ..() + if(I.w_class <= w_class && !held_item) + if(user.drop_item(I, src)) + to_chat(user, "You place \the [I] into \the [src]") + held_item = I + update_icon() + + +/obj/item/weapon/reagent_containers/glass/jar/attack_self(mob/user) + if(held_item) + to_chat(user, "You remove \the [held_item] from \the [src].") + user.put_in_hands(held_item) + held_item = null + update_icon() + +/obj/item/weapon/reagent_containers/glass/jar/examine(mob/user) + ..() + if(held_item) + to_chat(user, "It has \a [held_item] floating within.") + to_chat(user, "Take a closer look.") + +/obj/item/weapon/reagent_containers/glass/jar/recyclable() + if(held_item) + return FALSE + return TRUE + +/obj/item/weapon/reagent_containers/glass/jar/on_reagent_change() + update_icon() + +/obj/item/weapon/reagent_containers/glass/jar/pickup(mob/user) + ..() + update_icon() + +/obj/item/weapon/reagent_containers/glass/jar/dropped(mob/user) + ..() + update_icon() + +/obj/item/weapon/reagent_containers/glass/jar/attack_hand() + ..() + update_icon() + +/obj/item/weapon/reagent_containers/glass/jar/proc/safe_holder() + return reagents.has_any_reagents(list(SALINE, CLONEXADONE), volume/2) + +/obj/item/weapon/reagent_containers/glass/jar/process() + if(!held_item) + return + + if(held_item.gcDestroyed) + held_item = null + update_icon() + return + + reagents.reaction(held_item) + +/obj/item/weapon/reagent_containers/glass/jar/throw_impact(atom/hit_atom, var/speed, mob/user) + ..() + if(hit_atom) + src.visible_message("The [src.name] shatters!","You hear a shatter!") + playsound(src, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1) + reagents.reaction(loc, TOUCH) + if(hit_atom != get_turf(src)) + reagents.reaction(hit_atom, TOUCH) + if(held_item) + held_item.forceMove(loc) + held_item = null + getFromPool(/obj/item/weapon/shard, loc) + qdel(src) \ No newline at end of file diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm index 4116cdb4f53..92364ca75df 100644 --- a/code/modules/reagents/reagent_containers/hypospray.dm +++ b/code/modules/reagents/reagent_containers/hypospray.dm @@ -53,7 +53,7 @@ user.visible_message("[M == user ? "[user] injects \himself" : "[user] injects [M]"] with [src].", \ "[inject_message]") to_chat(M, "You feel a tiny prick!") - playsound(get_turf(src), 'sound/items/hypospray.ogg', 50, 1) + playsound(src, 'sound/items/hypospray.ogg', 50, 1) src.reagents.reaction(M, INGEST) if(M.reagents) diff --git a/code/modules/reagents/reagent_containers/pill.dm b/code/modules/reagents/reagent_containers/pill.dm index c5e8e97d4a0..5b77b285a02 100644 --- a/code/modules/reagents/reagent_containers/pill.dm +++ b/code/modules/reagents/reagent_containers/pill.dm @@ -44,7 +44,7 @@ src.forceMove(get_turf(H)) H.visible_message("\The [src] falls through and onto the ground.", "You hear \the [src] plinking around for a second before it hits the ground below you.") return 0 - injest(M) + ingest(M) return 1 // Handles pill dissolving in containers @@ -67,7 +67,7 @@ to_chat(user, "\The [target] is full!") //OOP, HO! -/obj/item/weapon/reagent_containers/pill/proc/injest(mob/M as mob) +/obj/item/weapon/reagent_containers/pill/proc/ingest(mob/M as mob) if(!reagents) return if(!M) @@ -268,7 +268,7 @@ icon_state = "pill7" //grey oblong flags = FPRINT | NOREACT -/obj/item/weapon/reagent_containers/pill/time_release/injest(mob/M as mob) +/obj/item/weapon/reagent_containers/pill/time_release/ingest(mob/M as mob) if(!reagents) return if(!M) diff --git a/code/modules/reagents/reagent_containers/spray.dm b/code/modules/reagents/reagent_containers/spray.dm index 2bae2569528..1c474970dc4 100644 --- a/code/modules/reagents/reagent_containers/spray.dm +++ b/code/modules/reagents/reagent_containers/spray.dm @@ -8,6 +8,8 @@ slot_flags = SLOT_BELT throwforce = 3 w_class = W_CLASS_SMALL + starting_materials = list(MAT_GLASS = 3500) + w_type = RECYK_GLASS throw_speed = 2 throw_range = 10 amount_per_transfer_from_this = 10 @@ -107,7 +109,7 @@ returnToPool(D) - playsound(get_turf(src), 'sound/effects/spray2.ogg', 50, 1, -6) + playsound(src, 'sound/effects/spray2.ogg', 50, 1, -6) //space cleaner /obj/item/weapon/reagent_containers/spray/cleaner @@ -199,4 +201,38 @@ returnToPool(D) - playsound(get_turf(src), 'sound/effects/spray2.ogg', 50, 1, -6) + playsound(src, 'sound/effects/spray2.ogg', 50, 1, -6) + +/obj/item/weapon/reagent_containers/spray/noreact + name = "stasis spray" + icon_state = "cleaner_noreact" + desc = "The label says 'Finally, a use for that pesky experimental bluespace technology for the whole house to enjoy!'\n\ + A disclaimer towards the bottom states Warning: Do not use around the house, or in proximity of dogs|children|clowns" + flags = OPENCONTAINER|FPRINT|NOREACT + origin_tech = Tc_BLUESPACE + "=3;" + Tc_MATERIALS + "=5" + amount_per_transfer_from_this = 25 + + +/obj/item/weapon/reagent_containers/spray/noreact/make_puff(var/atom/target, var/mob/user) + // Create the chemical puff + var/transfer_amount = amount_per_transfer_from_this + if (!can_transfer_an_APTFT() && !is_empty()) //If it doesn't contain enough reagents to fulfill its amount_per_transfer_from_this, but also isn't empty, it'll spray whatever it has left. + transfer_amount = reagents.total_volume + var/mix_color = mix_color_from_reagents(reagents.reagent_list) + var/obj/effect/decal/chemical_puff/D = getFromPool(/obj/effect/decal/chemical_puff, get_turf(src), mix_color, amount_per_transfer_from_this) + D.flags |= NOREACT + reagents.trans_to(D, transfer_amount, 1/3) + + + // Move the puff toward the target + spawn(0) + for (var/i = 0, i < 6, i++) + step_towards(D, target) + if(i > 1) + D.flags &= ~NOREACT + D.react() + sleep(3) + + returnToPool(D) + + playsound(src, 'sound/effects/spray2.ogg', 50, 1, -6) \ No newline at end of file diff --git a/code/modules/reagents/reagent_containers/syringes.dm b/code/modules/reagents/reagent_containers/syringes.dm index 25915dadfcd..f9738a6dd13 100644 --- a/code/modules/reagents/reagent_containers/syringes.dm +++ b/code/modules/reagents/reagent_containers/syringes.dm @@ -163,7 +163,7 @@ warning("Tried to draw blood or equivalent from [target] (\ref[target]) but it's missing their DNA datum!") return - if (M_NOCLONE in T.mutations) // Target has been husked + if (M_HUSK in T.mutations) // Target has been husked to_chat(user, "You are unable to locate any blood.") return diff --git a/code/modules/reagents/reagent_dispenser.dm b/code/modules/reagents/reagent_dispenser.dm index d6184afadf9..a41a677ef5b 100644 --- a/code/modules/reagents/reagent_dispenser.dm +++ b/code/modules/reagents/reagent_dispenser.dm @@ -346,7 +346,7 @@ reagents.trans_to(S, S.max_silicate) S.update_icon() to_chat(user, "Sprayer refilled.") - playsound(get_turf(src), 'sound/effects/refill.ogg', 50, 1, -6) + playsound(src, 'sound/effects/refill.ogg', 50, 1, -6) return 1 /obj/structure/reagent_dispensers/degreaser diff --git a/code/modules/recycling/compactor.dm b/code/modules/recycling/compactor.dm index 4eeea428ebd..c886b6d7c17 100644 --- a/code/modules/recycling/compactor.dm +++ b/code/modules/recycling/compactor.dm @@ -12,7 +12,7 @@ return if(stat & BROKEN) return - playsound(get_turf(src),'sound/machines/compactor.ogg', 30, 1) //Placeholder + playsound(src,'sound/machines/compactor.ogg', 30, 1) //Placeholder flush = 1 flick("compactor_running",src) spawn(41) @@ -102,7 +102,7 @@ power_change() return if(!emagged && istype(I,/obj/item/weapon/card/emag)) - playsound(get_turf(src), 'sound/effects/sparks4.ogg', 75, 1) + playsound(src, 'sound/effects/sparks4.ogg', 75, 1) emagged = 1 to_chat(user, "You you disable the safety features.") return diff --git a/code/modules/recycling/conveyor2.dm b/code/modules/recycling/conveyor2.dm index 0f20928202b..adcbebe8237 100644 --- a/code/modules/recycling/conveyor2.dm +++ b/code/modules/recycling/conveyor2.dm @@ -260,7 +260,7 @@ if(iswelder(W)) var/obj/item/weapon/weldingtool/WT = W if(WT.remove_fuel(0,user)) - playsound(get_turf(src), 'sound/items/Welder2.ogg', 50, 1) + playsound(src, 'sound/items/Welder2.ogg', 50, 1) if(do_after(user, src, 30)) user.visible_message("Plates of metal are cut off \the [src] by [user.name] with the welding tool.", \ "You cut the metal plates off \the [src] with the welding tool.", \ @@ -283,7 +283,7 @@ var/obj/O = user.get_active_hand() if(iscrowbar(O)) update_dir(get_dir(src, over_location)) - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 25, 1) + playsound(src, 'sound/items/Crowbar.ogg', 25, 1) to_chat(user, "You change the direction of \the [src] using \the [O].") return return ..() @@ -534,7 +534,7 @@ return . if(iswrench(W)) to_chat(user, "Deconstructing \the [src]...") - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1) + playsound(src, 'sound/items/Ratchet.ogg', 100, 1) if(do_after(user, src,50)) to_chat(user, "You disassemble \the [src].") var/turf/T=get_turf(src) diff --git a/code/modules/recycling/conveyor_assembly.dm b/code/modules/recycling/conveyor_assembly.dm index fe97838ab86..aeae676fd58 100644 --- a/code/modules/recycling/conveyor_assembly.dm +++ b/code/modules/recycling/conveyor_assembly.dm @@ -106,7 +106,7 @@ /obj/structure/conveyor_assembly/attackby(obj/item/P, mob/user) if(iscrowbar(P)) - playsound(get_turf(src), 'sound/items/Crowbar.ogg', 75, 1) + playsound(src, 'sound/items/Crowbar.ogg', 75, 1) if(do_after(user, src, 10)) to_chat(user, "You unhinge the frame.") getFromPool(/obj/item/stack/conveyor_assembly, src.loc) @@ -115,7 +115,7 @@ else if(istype(P, /obj/item/stack/sheet/metal)) var/obj/item/stack/S = P if(S.amount > 4) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 75, 1) + playsound(src, 'sound/items/Ratchet.ogg', 75, 1) if(do_after(user, src, 30) && S.amount > 4) S.use(4) to_chat(user, "You add the plates to \the [src].") diff --git a/code/modules/recycling/disposal-construction.dm b/code/modules/recycling/disposal-construction.dm index 0bab7ea0a68..839f865589d 100644 --- a/code/modules/recycling/disposal-construction.dm +++ b/code/modules/recycling/disposal-construction.dm @@ -211,7 +211,7 @@ else setDensity(TRUE) to_chat(user, "You detach the [nicetype] from the underfloor.") - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1) + playsound(src, 'sound/items/Ratchet.ogg', 100, 1) update() return else @@ -231,7 +231,7 @@ else setDensity(TRUE) // We don't want disposal bins or outlets to go density 0 to_chat(user, "You attach the [nicetype] to the underfloor.") - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1) + playsound(src, 'sound/items/Ratchet.ogg', 100, 1) update() else if(iswelder(I)) @@ -250,7 +250,7 @@ return var/obj/item/weapon/weldingtool/W = I if(W.remove_fuel(0,user)) - playsound(get_turf(src), 'sound/items/Welder2.ogg', 100, 1) + playsound(src, 'sound/items/Welder2.ogg', 100, 1) to_chat(user, "Welding the [nicetype] in place.") if(do_after(user, src, 20)) if(gcDestroyed || !W.isOn()) diff --git a/code/modules/recycling/disposal.dm b/code/modules/recycling/disposal.dm index 313f52ffbc2..bb041a113e5 100644 --- a/code/modules/recycling/disposal.dm +++ b/code/modules/recycling/disposal.dm @@ -25,8 +25,12 @@ var/template_path = "disposalsbin.tmpl" var/deconstructable = TRUE //Set to FALSE for disposal machinery that can be used for transporting players or things, but not tinkered with by players. - holomap = TRUE - auto_holomap = TRUE +/obj/machinery/disposal/supports_holomap() + return TRUE + +/obj/machinery/disposal/initialize() + ..() + add_self_to_holomap() /obj/machinery/disposal/no_deconstruct deconstructable = FALSE @@ -102,12 +106,12 @@ return if(mode==0) // It's off but still not unscrewed mode=-1 // Set it to doubleoff l0l - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 50, 1) to_chat(user, "You remove the screws around the power connection.") return else if(mode==-1) mode=0 - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 50, 1) to_chat(user, "You attach the screws around the power connection.") return else if(istype(I,/obj/item/weapon/weldingtool) && mode==-1) @@ -116,7 +120,7 @@ return var/obj/item/weapon/weldingtool/W = I if(W.remove_fuel(0,user)) - playsound(get_turf(src), 'sound/items/Welder2.ogg', 100, 1) + playsound(src, 'sound/items/Welder2.ogg', 100, 1) to_chat(user, "You start slicing the floorweld off the disposal unit.") if(do_after(user, src,20)) @@ -364,7 +368,7 @@ var/pressure_delta = (SEND_PRESSURE*1.01) - air_contents.return_pressure() if(env.temperature > 0) - var/transfer_moles = 0.1 * pressure_delta*air_contents.volume/(env.temperature * R_IDEAL_GAS_EQUATION) + var/transfer_moles = 0.1 * pressure_delta * air_contents.volume / (env.temperature * R_IDEAL_GAS_EQUATION) //Actually transfer the gas var/datum/gas_mixture/removed = env.remove(transfer_moles) @@ -550,11 +554,14 @@ var/active = 0 // true if the holder is moving, otherwise inactive dir = 0 var/count = 1000 //*** can travel 1000 steps before going inactive (in case of loops) - var/has_fat_guy = 0 // true if contains a fat person var/destinationTag = "DISPOSALS"// changes if contains a delivery container var/tomail = 0 //changes if contains wrapped package var/hasmob = 0 //If it contains a mob +/obj/structure/disposalholder/proc/has_fat_guy() + for(var/mob/living/carbon/human/H in src) + if(((M_FAT in H.mutations) && (H.species && H.species.anatomy_flags & CAN_BE_FAT)) || H.species.anatomy_flags & IS_BULKY) + return TRUE // initialize a holder from the contents of a disposal unit /obj/structure/disposalholder/proc/init(var/obj/machinery/disposal/D) @@ -578,10 +585,6 @@ // note AM since can contain mobs or objs for(var/atom/movable/AM in D) AM.forceMove(src) - if(istype(AM, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = AM - if(((M_FAT in H.mutations) && (H.species && H.species.anatomy_flags & CAN_BE_FAT)) || H.species.anatomy_flags & IS_BULKY) // is a human and fat? - has_fat_guy = 1 // set flag on holder if(istype(AM, /obj/item/delivery/large) && !hasmob) var/obj/item/delivery/large/T = AM src.destinationTag = T.sortTag @@ -615,12 +618,13 @@ H.take_overall_damage(20, 0, "Blunt Trauma")//horribly maim any living creature jumping down disposals. c'est la vie */ - if(has_fat_guy && prob(2)) // chance of becoming stuck per segment if contains a fat guy - active = 0 + if(prob(2)) // chance of becoming stuck per segment if contains a fat guy + if(has_fat_guy()) + active = 0 // find the fat guys - for(var/mob/living/carbon/human/H in src) + for(var/mob/living/carbon/human/H in src) - break + break sleep(1) // was 1 if(!loc || isnull(loc)) qdel(src) @@ -663,8 +667,6 @@ if(M.client) // if a client mob, update eye to follow this holder M.client.eye = src - if(other.has_fat_guy) - has_fat_guy = 1 qdel(other) @@ -682,7 +684,7 @@ //testing("SENDING CLONG") to_chat(M, "CLONG, clong!") - playsound(get_turf(src), 'sound/effects/clang.ogg', 50, 0, 0) + playsound(src, 'sound/effects/clang.ogg', 50, 0, 0) /obj/machinery/disposal/is_airtight() //No polyacid smoke while inside the pipes. The disposals bins, inlets/outlets and such aren't counted for this purpose return 1 @@ -701,8 +703,6 @@ anchored = 1 density = 0 - holomap = TRUE - auto_holomap = TRUE level = LEVEL_BELOW_FLOOR // underfloor only var/dpdir = 0 // bitmask of pipe directions dir = 0 // dir will contain dominant direction for junction pipes @@ -712,7 +712,14 @@ var/base_icon_state // initial icon state on map var/deconstructable = TRUE - // new pipe, set the icon_state as on map +/obj/structure/disposalpipe/supports_holomap() + return TRUE + +/obj/structure/disposalpipe/initialize() + ..() + add_self_to_holomap() + +// new pipe, set the icon_state as on map /obj/structure/disposalpipe/New() ..() base_icon_state = icon_state @@ -935,7 +942,7 @@ var/obj/item/weapon/weldingtool/W = I if(W.remove_fuel(0,user)) - playsound(get_turf(src), 'sound/items/Welder2.ogg', 100, 1) + playsound(src, 'sound/items/Welder2.ogg', 100, 1) to_chat(user, "You start slicing the disposal pipe.") if(do_after(user, src, 3 SECONDS)) if(gcDestroyed || !W.isOn()) @@ -1087,7 +1094,7 @@ if(O.currTag)// Tag set sort_tag = uppertext(O.destinations[O.currTag]) - playsound(get_turf(src), 'sound/machines/twobeep.ogg', 100, 1) + playsound(src, 'sound/machines/twobeep.ogg', 100, 1) to_chat(user, "Changed filter to [sort_tag]") updatedesc() return 1 @@ -1440,7 +1447,7 @@ var/obj/item/weapon/weldingtool/W = I if(W.remove_fuel(0,user)) - playsound(get_turf(src), 'sound/items/Welder2.ogg', 100, 1) + playsound(src, 'sound/items/Welder2.ogg', 100, 1) to_chat(user, "You start slicing the disposal pipe.") if(do_after(user, src, 3 SECONDS)) if(gcDestroyed || !W.isOn()) @@ -1516,8 +1523,12 @@ var/obj/structure/disposalpipe/trunk/trunk var/deconstructable = TRUE - holomap = TRUE - auto_holomap = TRUE +/obj/structure/disposaloutlet/supports_holomap() + return TRUE + +/obj/structure/disposaloutlet/initialize() + ..() + add_self_to_holomap() /obj/structure/disposaloutlet/no_deconstruct deconstructable = FALSE @@ -1577,18 +1588,18 @@ if(isscrewdriver(I)) if(mode==0) mode=1 - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 50, 1) to_chat(user, "You remove the screws around the power connection.") return else if(mode==1) mode=0 - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 50, 1) to_chat(user, "You attach the screws around the power connection.") return else if(istype(I,/obj/item/weapon/weldingtool) && mode==1) var/obj/item/weapon/weldingtool/W = I if(W.remove_fuel(0,user)) - playsound(get_turf(src), 'sound/items/Welder2.ogg', 100, 1) + playsound(src, 'sound/items/Welder2.ogg', 100, 1) to_chat(user, "You start slicing the floorweld off the disposal outlet.") if(do_after(user, src, 20)) if(gcDestroyed || !W.isOn()) diff --git a/code/modules/recycling/sortingmachinery.dm b/code/modules/recycling/sortingmachinery.dm index d8d05e547e8..8d1f2d99cc0 100755 --- a/code/modules/recycling/sortingmachinery.dm +++ b/code/modules/recycling/sortingmachinery.dm @@ -61,7 +61,7 @@ if(isscrewdriver(W)) panel = !panel to_chat(user, "You [panel ? "open" : "close"] the panel on \the [src].") - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 50, 1) update_icon() return 1 @@ -106,6 +106,10 @@ interact(usr) return 1 +/obj/item/device/destTagger/cyborg + name = "cyborg destination tagger" + mode = TRUE + /obj/machinery/disposal/deliveryChute name = "Delivery chute" desc = "A chute for big and small packages alike!" @@ -198,18 +202,18 @@ if(isscrewdriver(I)) if(c_mode==0) c_mode=1 - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 50, 1) to_chat(user, "You remove the screws around the power connection.") return else if(c_mode==1) c_mode=0 - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 50, 1) to_chat(user, "You attach the screws around the power connection.") return else if(istype(I,/obj/item/weapon/weldingtool) && c_mode==1) var/obj/item/weapon/weldingtool/W = I if(W.remove_fuel(0,user)) - playsound(get_turf(src), 'sound/items/Welder2.ogg', 100, 1) + playsound(src, 'sound/items/Welder2.ogg', 100, 1) to_chat(user, "You start slicing the floorweld off the delivery chute.") if(do_after(user, src,20)) if(!src || !W.isOn()) diff --git a/code/modules/research/circuitprinter.dm b/code/modules/research/circuitprinter.dm index 6ddcb031c3b..debec9def2b 100644 --- a/code/modules/research/circuitprinter.dm +++ b/code/modules/research/circuitprinter.dm @@ -40,6 +40,8 @@ using metal and glass, it uses glass and reagents (usually sulfuric acis). MAT_SILVER ) + var/draining = FALSE + /obj/machinery/r_n_d/fabricator/circuit_imprinter/New() . = ..() @@ -61,11 +63,12 @@ using metal and glass, it uses glass and reagents (usually sulfuric acis). /obj/machinery/r_n_d/fabricator/circuit_imprinter/RefreshParts() + ..() var/T = 0 for(var/obj/item/weapon/reagent_containers/glass/G in component_parts) - T += G.reagents.maximum_volume + T += G.reagents.maximum_volume - G.reagents.total_volume + create_reagents(T) // This is only a buffer for handling reagents poured into the imprinter before they flow into the beakers - create_reagents(T) // Holder for the reagents used as materials. T = 0 for(var/obj/item/weapon/stock_parts/matter_bin/M in component_parts) T += M.rating @@ -75,3 +78,35 @@ using metal and glass, it uses glass and reagents (usually sulfuric acis). ..() if (O.is_open_container()) return 0 + +/obj/machinery/r_n_d/fabricator/circuit_imprinter/on_reagent_change() + if(!draining) + drain_to_beakers() + +/obj/machinery/r_n_d/fabricator/circuit_imprinter/proc/drain_to_beakers() + draining = TRUE + for(var/obj/item/weapon/reagent_containers/RC in component_parts) + if(RC.reagents.is_full()) + continue + var/empty_volume = RC.reagents.maximum_volume - RC.reagents.total_volume + reagents.trans_to(RC, empty_volume) + if(reagents.is_empty()) + break + reagents.clear_reagents() + update_buffer_size() + draining = FALSE + +/obj/machinery/r_n_d/fabricator/circuit_imprinter/update_buffer_size() + var/total_empty_volume = 0 + for(var/obj/item/weapon/reagent_containers/RC in component_parts) + total_empty_volume += RC.reagents.maximum_volume - RC.reagents.total_volume + reagents.maximum_volume = total_empty_volume + +/obj/machinery/r_n_d/fabricator/circuit_imprinter/proc/get_total_volume() + var/all_volume = 0 + for(var/obj/item/weapon/reagent_containers/RC in component_parts) + all_volume += RC.reagents.total_volume + return all_volume + +/obj/machinery/r_n_d/fabricator/circuit_imprinter/hide_own_reagents() + return TRUE diff --git a/code/modules/research/designs/AI_modules.dm b/code/modules/research/designs/AI_modules.dm index 0f84e004c4e..0f009db1e42 100644 --- a/code/modules/research/designs/AI_modules.dm +++ b/code/modules/research/designs/AI_modules.dm @@ -152,4 +152,15 @@ build_type = IMPRINTER materials = list(MAT_GLASS = 2000, SACID = 20, MAT_DIAMOND = 100) category = "Module Boards" - build_path = /obj/item/weapon/aiModule/core/robocop \ No newline at end of file + build_path = /obj/item/weapon/aiModule/core/robocop + + +/datum/design/lazymov + name = "Core Module Design (Lazymov)" + desc = "Allows for the construction of a Lazymov AI Core Module." + id = "lazymov_module" + req_tech = list(Tc_PROGRAMMING = 3, Tc_MATERIALS = 6) + build_type = IMPRINTER + materials = list(MAT_GLASS = 2000, SACID = 20, MAT_DIAMOND = 100) + category = "Module Boards" + build_path = /obj/item/weapon/aiModule/core/lazymov diff --git a/code/modules/research/designs/boards/machine_engie.dm b/code/modules/research/designs/boards/machine_engie.dm index 649ec56fc45..c1424a87d7a 100644 --- a/code/modules/research/designs/boards/machine_engie.dm +++ b/code/modules/research/designs/boards/machine_engie.dm @@ -50,7 +50,7 @@ id = "cellcharger" req_tech = list(Tc_MATERIALS = 2, Tc_ENGINEERING = 2, Tc_POWERSTORAGE = 3) build_type = IMPRINTER - materials = list(MAT_GLASS = 2000, SACID = 20) + materials = list(MAT_GLASS = 2000, SACID = 3) category = "Machine Boards" build_path = /obj/item/weapon/circuitboard/cell_charger diff --git a/code/modules/research/designs/boards/machine_hospitality.dm b/code/modules/research/designs/boards/machine_hospitality.dm index e9ccbf915e3..e874ecfea22 100644 --- a/code/modules/research/designs/boards/machine_hospitality.dm +++ b/code/modules/research/designs/boards/machine_hospitality.dm @@ -4,7 +4,7 @@ id = "microwave" req_tech = list(Tc_PROGRAMMING = 2, Tc_ENGINEERING = 2, Tc_MAGNETS = 3) build_type = IMPRINTER - materials = list(MAT_GLASS = 2000, SACID = 20) + materials = list(MAT_GLASS = 2000, SACID = 3) category = "Machine Boards" build_path = /obj/item/weapon/circuitboard/microwave @@ -67,3 +67,33 @@ materials = list(MAT_GLASS = 2000, SACID = 20) category = "Machine Boards" build_path = /obj/item/weapon/circuitboard/confectionator + +/datum/design/fishtank + name = "Circuit Design (Fishtank Filter)" + desc = "Allows for the construction of circuit boards used to build a fishtank." + id = "fishtank" + req_tech = list(Tc_PROGRAMMING = 1) + build_type = IMPRINTER + materials = list(MAT_GLASS = 2000, SACID = 3) + category = "Machine Boards" + build_path = /obj/item/weapon/circuitboard/fishtank + +/datum/design/fishwall + name = "Circuit Design (Large Fishtank Filter)" + desc = "Allows for the construction of circuit boards used to build a large fishtank." + id = "fishwall" + req_tech = list(Tc_PROGRAMMING = 1) + build_type = IMPRINTER + materials = list(MAT_GLASS = 2000, SACID = 3) + category = "Machine Boards" + build_path = /obj/item/weapon/circuitboard/fishwall + +/datum/design/conduction_plate + name = "Circuit Design (Conduction Plate)" + desc = "Allows for the construction of circuit boards used to build a conduction plate." + id = "conductionplate" + req_tech = list(Tc_PROGRAMMING = 1, Tc_ENGINEERING = 4) + build_type = IMPRINTER + materials = list(MAT_GLASS = 2000, SACID = 20) + category = "Machine Boards" + build_path = /obj/item/weapon/circuitboard/conduction_plate diff --git a/code/modules/research/designs/boards/machine_misc.dm b/code/modules/research/designs/boards/machine_misc.dm index 2d4455ac33c..ff24512fdb4 100644 --- a/code/modules/research/designs/boards/machine_misc.dm +++ b/code/modules/research/designs/boards/machine_misc.dm @@ -10,6 +10,17 @@ category = "Machine Boards" build_path = /obj/item/weapon/circuitboard/recharge_station +/datum/design/recharger + name = "Circuit Design (Recharger)" + desc = "Allows for the construction of circuit boards used to build Weapon Rechargers" + id="recharger" + req_tech = list(Tc_POWERSTORAGE = 2, Tc_COMBAT = 2) + build_type = IMPRINTER + materials = list(MAT_GLASS = 2000, SACID = 3) + category = "Machine Boards" + build_path = /obj/item/weapon/circuitboard/recharger + + /datum/design/photocopier name = "Circuit Design (Photocopier)" desc = "Allows for the construction of circuit boards to build photocopiers." @@ -82,7 +93,7 @@ id = "vendomat" req_tech = list(Tc_MATERIALS = 1, Tc_ENGINEERING = 1, Tc_POWERSTORAGE = 1) build_type = IMPRINTER - materials = list(MAT_GLASS = 2000, SACID = 20) + materials = list(MAT_GLASS = 2000, SACID = 3) category = "Misc" build_path = /obj/item/weapon/circuitboard/vendomat diff --git a/code/modules/research/designs/boards/machine_science.dm b/code/modules/research/designs/boards/machine_science.dm index d14448dc875..7a422776ba3 100644 --- a/code/modules/research/designs/boards/machine_science.dm +++ b/code/modules/research/designs/boards/machine_science.dm @@ -34,7 +34,7 @@ id = "autolathe" req_tech = list(Tc_PROGRAMMING = 2, Tc_ENGINEERING = 2) build_type = IMPRINTER - materials = list(MAT_GLASS = 2000, SACID = 20) + materials = list(MAT_GLASS = 2000, SACID = 3) category = "Machine Boards" build_path = /obj/item/weapon/circuitboard/autolathe diff --git a/code/modules/research/designs/boards/misc.dm b/code/modules/research/designs/boards/misc.dm index 91518d59698..c6e9c37aa94 100644 --- a/code/modules/research/designs/boards/misc.dm +++ b/code/modules/research/designs/boards/misc.dm @@ -4,7 +4,7 @@ id = "air_alarm" req_tech = list(Tc_PROGRAMMING = 2) build_type = IMPRINTER - materials = list(MAT_GLASS = 2000, SACID = 20) + materials = list(MAT_GLASS = 2000, SACID = 3) category = "Engineering Boards" build_path = /obj/item/weapon/circuitboard/air_alarm @@ -14,7 +14,7 @@ id = "fire_alarm" req_tech = list(Tc_PROGRAMMING = 2) build_type = IMPRINTER - materials = list(MAT_GLASS = 2000, SACID = 20) + materials = list(MAT_GLASS = 2000, SACID = 3) category = "Engineering Boards" build_path = /obj/item/weapon/circuitboard/fire_alarm @@ -24,7 +24,7 @@ id = "airlock" req_tech = list(Tc_PROGRAMMING = 2) build_type = IMPRINTER - materials = list(MAT_GLASS = 2000, SACID = 20) + materials = list(MAT_GLASS = 2000, SACID = 3) category = "Engineering Boards" build_path = /obj/item/weapon/circuitboard/airlock @@ -34,7 +34,7 @@ id = "intercom" req_tech = list(Tc_PROGRAMMING = 2) build_type = IMPRINTER - materials = list(MAT_GLASS = 2000, SACID = 20) + materials = list(MAT_GLASS = 2000, SACID = 3) category = "Engineering Boards" build_path = /obj/item/weapon/intercom_electronics @@ -44,7 +44,7 @@ id = "apc_board" req_tech = list(Tc_POWERSTORAGE = 2) build_type = IMPRINTER - materials = list(MAT_GLASS = 2000, SACID = 20) + materials = list(MAT_GLASS = 2000, SACID = 3) category = "Engineering Boards" build_path = /obj/item/weapon/circuitboard/power_control @@ -54,7 +54,7 @@ id = "station_map" req_tech = list(Tc_MAGNETS = 2, Tc_PROGRAMMING = 2) build_type = IMPRINTER - materials = list(MAT_GLASS = 2000, SACID = 20) + materials = list(MAT_GLASS = 2000, SACID = 3) category = "Engineering Boards" build_path = /obj/item/weapon/circuitboard/station_map diff --git a/code/modules/research/designs/medical.dm b/code/modules/research/designs/medical.dm index eb392667911..fa0ce445699 100644 --- a/code/modules/research/designs/medical.dm +++ b/code/modules/research/designs/medical.dm @@ -90,76 +90,6 @@ category = "Medical" build_path = /obj/item/weapon/thermometer/electronic -/datum/design/laserscalpel1 - name = "Laser Scalpel" - desc = "A scalpel augmented with a directed laser, allowing for bloodless incisions and built-in cautery." - id = "laserscalpel1" - req_tech = list(Tc_MATERIALS = 3, Tc_ENGINEERING = 2, Tc_BIOTECH = 2) - build_type = PROTOLATHE - materials = list (MAT_IRON = 10000, MAT_GLASS = 5000) - category = "Medical" - build_path = /obj/item/weapon/scalpel/laser - -/datum/design/laserscalpel2 - name = "High Precision Laser Scalpel" - desc = "A scalpel augmented with a directed laser, allowing for bloodless incisions and built-in cautery." - id = "laserscalpel2" - req_tech = list(Tc_MATERIALS = 4, Tc_ENGINEERING = 3, Tc_BIOTECH = 4) - build_type = PROTOLATHE - materials = list (MAT_IRON = 10000, MAT_GLASS = 5000, MAT_URANIUM = 500) - category = "Medical" - build_path = /obj/item/weapon/scalpel/laser/tier2 - -/datum/design/incisionmanager - name = "Surgical Incision Manager" - desc = "A true extension of the surgeon's body, this marvel instantly cuts the organ, clamp any bleeding, and retract the skin, allowing for the immediate commencement of therapeutic steps." - id = "incisionmanager" - req_tech = list(Tc_MATERIALS = 5, Tc_ENGINEERING = 4, Tc_BIOTECH = 5) - build_type = PROTOLATHE - materials = list (MAT_IRON = 10000, MAT_GLASS = 5000, MAT_URANIUM = 250, MAT_SILVER = 500) - category = "Medical" - build_path = /obj/item/weapon/retractor/manager - -/datum/design/bonemender - name = "Bone Mender" - desc = "A favorite among skeletons. It even sounds like a skeleton too." - id = "bonemender" - req_tech = list(Tc_MATERIALS = 5, Tc_ENGINEERING = 4, Tc_BIOTECH = 5) - build_type = PROTOLATHE - materials = list (MAT_IRON = 10000, MAT_GLASS = 5000, MAT_GOLD = 500, MAT_SILVER = 250) - category = "Medical" - build_path = /obj/item/weapon/bonesetter/bone_mender - -/datum/design/pico_grasper - name = "Precision Grasper" - desc = "A thin rod with pico manipulators embedded in it allowing for fast and precise extraction." - id = "pico_grasper" - req_tech = list(Tc_MATERIALS = 4, Tc_ENGINEERING = 3, Tc_BIOTECH = 4) - build_type = PROTOLATHE - materials = list (MAT_IRON = 10000, MAT_GLASS = 5000, MAT_PLASMA = 80) - category = "Medical" - build_path = /obj/item/weapon/hemostat/pico - -/datum/design/plasmasaw - name = "Plasma Saw" - desc = "Perfect for cutting through ice." - id = "plasmasaw" - req_tech = list(Tc_MATERIALS = 5, Tc_ENGINEERING = 4, Tc_BIOTECH = 5, Tc_PLASMATECH = 3) - build_type = PROTOLATHE - materials = list (MAT_IRON = 10000, MAT_GLASS = 5000, MAT_PLASMA = 500) - category = "Medical" - build_path = /obj/item/weapon/circular_saw/plasmasaw - -/datum/design/diamond_surgicaldrill - name = "Diamond Surgical Drill" - desc = "Yours is the drill that will pierce the tiny heavens!" - id = "diamond_surgicaldrill" - req_tech = list(Tc_MATERIALS = 6, Tc_ENGINEERING = 4, Tc_BIOTECH = 5) - build_type = PROTOLATHE - materials = list (MAT_IRON = 10000, MAT_GLASS = 5000, MAT_DIAMOND = 800) - category = "Medical" - build_path = /obj/item/weapon/surgicaldrill/diamond - /datum/design/health_hud name = "Health Scanner HUD" desc = "A heads-up display that scans the humans in view and provides accurate data about their health status." @@ -190,16 +120,6 @@ category = "Medical" build_path = /obj/item/device/antibody_scanner -/datum/design/switchtool - name = "Surgeon's Switchtool" - desc = "A switchtool containing most of the necessary items for impromptu surgery. For the surgeon on the go." - id = "switchtool" - req_tech = list(Tc_MATERIALS = 5, Tc_BLUESPACE = 3, Tc_BIOTECH = 3) - build_type = PROTOLATHE - materials = list (MAT_IRON = 10000, MAT_GLASS = 5000) - category = "Medical" - build_path = /obj/item/weapon/switchtool/surgery - /datum/design/plasmabeaker name = "Plasma Beaker" desc = "A beaker designed to act as a catalyst in some reactions." diff --git a/code/modules/research/designs/misc.dm b/code/modules/research/designs/misc.dm index 17e811c7eac..9a5be1c2fb9 100644 --- a/code/modules/research/designs/misc.dm +++ b/code/modules/research/designs/misc.dm @@ -38,12 +38,12 @@ materials = list(MAT_IRON=37500) category = "Misc" -/datum/design/surgery_rollerbed - name = "Mobile Operating Table" - desc = "A collapsed mobile operating table that can be carried around." - id = "surgery_rollerbed" - build_type = PROTOLATHE | MECHFAB - build_path = /obj/item/roller/surgery - req_tech = list(Tc_BIOTECH = 5, Tc_ENGINEERING = 4, Tc_PROGRAMMING = 2) - materials = list(MAT_IRON = 10000, MAT_GLASS = 5000) - category = "Misc" \ No newline at end of file +/datum/design/polarized_contacts + name = "Polarized Contacts" + desc = "Shield your eyes from flashes in style." + id = "polarized_contacts" + build_type = PROTOLATHE + build_path = /obj/item/clothing/glasses/contacts/polarized + req_tech = list(Tc_ENGINEERING = 4, Tc_MATERIALS = 4, Tc_BIOTECH = 5) + materials = list(MAT_GLASS = 2000) + category = "Misc" diff --git a/code/modules/research/designs/robot.dm b/code/modules/research/designs/robot.dm index 08b091102d7..03b7616d649 100644 --- a/code/modules/research/designs/robot.dm +++ b/code/modules/research/designs/robot.dm @@ -68,6 +68,18 @@ category = "Robot" materials = list(MAT_IRON=25000) +/datum/design/robot/ref_torso + name = "Cyborg Component (Reinforced robot torso)" + desc = "Used to build a reinforced Robot torso." + id = "ref_robot_torso" + req_tech = list(Tc_ENGINEERING = 4, Tc_MATERIALS = 4) + build_type = MECHFAB + build_path = /obj/item/robot_parts/chest/reinforced + category = "Robot_Part" + materials = list(MAT_IRON=40000, MAT_SILVER=10000, MAT_GOLD=5000, MAT_URANIUM=5000, MAT_DIAMOND=5000, MAT_PLASMA=5000) + + +//Components /datum/design/robot/binary_commucation_device name = "Cyborg Component (Binary Communication Device)" desc = "Used to build a binary communication device." @@ -127,3 +139,63 @@ build_path = /obj/item/robot_parts/robot_component/armour category = "Robot_Part" materials = list(MAT_IRON=5000) + +/datum/design/robot/ref_binary_commucation_device + name = "Cyborg Component (Reinf. Binary Comm. Device)" + desc = "Used to build a reinforced binary communication device." + id = "robot_ref_bin_comms" + req_tech = list(Tc_ENGINEERING = 4, Tc_MATERIALS = 4) + build_type = MECHFAB + build_path = /obj/item/robot_parts/robot_component/binary_communication_device/reinforced + category = "Robot_Part" + materials = list(MAT_IRON=5000, MAT_GOLD=5000) + +/datum/design/robot/ref_radio + name = "Cyborg Component (Reinforced Radio)" + desc = "Used to build a reinforced radio." + id = "robot_ref_radio" + req_tech = list(Tc_ENGINEERING = 4, Tc_MATERIALS = 4) + build_type = MECHFAB + build_path = /obj/item/robot_parts/robot_component/radio/reinforced + category = "Robot_Part" + materials = list(MAT_IRON=5000, MAT_URANIUM=5000) + +/datum/design/robot/ref_actuator + name = "Cyborg Component (Reinforced Actuator)" + desc = "Used to build an reinforced actuator." + id = "robot_ref_actuator" + req_tech = list(Tc_ENGINEERING = 4, Tc_MATERIALS = 4) + build_type = MECHFAB + build_path = /obj/item/robot_parts/robot_component/actuator/reinforced + category = "Robot_Part" + materials = list(MAT_IRON=5000, MAT_SILVER=5000) + +/datum/design/robot/ref_diagnosis_unit + name = "Cyborg Component (Reinforced Diagnosis Unit)" + desc = "Used to build a reinforced diagnosis unit." + id = "robot_ref_diagnosis_unit" + req_tech = list(Tc_ENGINEERING = 4, Tc_MATERIALS = 4) + build_type = MECHFAB + build_path = /obj/item/robot_parts/robot_component/diagnosis_unit/reinforced + category = "Robot_Part" + materials = list(MAT_IRON=5000, MAT_SILVER=5000) + +/datum/design/robot/ref_camera + name = "Cyborg Component (Reinforced Camera)" + desc = "Used to build a reinforced diagnosis unit." + id = "robot_ref_camera" + req_tech = list(Tc_ENGINEERING = 4, Tc_MATERIALS = 4) + build_type = MECHFAB + build_path = /obj/item/robot_parts/robot_component/camera/reinforced + category = "Robot_Part" + materials = list(MAT_IRON=5000, MAT_PLASMA=5000) + +/datum/design/robot/ref_armour + name = "Cyborg Component (Reinforced Armor)" + desc = "Used to build reinforced cyborg armor." + id = "robot_ref_armour" + req_tech = list(Tc_ENGINEERING = 4, Tc_MATERIALS = 4) + build_type = MECHFAB + build_path = /obj/item/robot_parts/robot_component/armour/reinforced + category = "Robot_Part" + materials = list(MAT_IRON=5000, MAT_DIAMOND=5000) \ No newline at end of file diff --git a/code/modules/research/designs/surgery.dm b/code/modules/research/designs/surgery.dm new file mode 100644 index 00000000000..b993ad578d7 --- /dev/null +++ b/code/modules/research/designs/surgery.dm @@ -0,0 +1,99 @@ +/datum/design/laserscalpel1 + name = "Laser Scalpel" + desc = "A scalpel augmented with a directed laser, allowing for bloodless incisions and built-in cautery." + id = "laserscalpel1" + req_tech = list(Tc_MATERIALS = 3, Tc_ENGINEERING = 2, Tc_BIOTECH = 2) + build_type = PROTOLATHE + materials = list (MAT_IRON = 10000, MAT_GLASS = 5000) + category = "Surgery" + build_path = /obj/item/weapon/scalpel/laser + +/datum/design/laserscalpel2 + name = "High Precision Laser Scalpel" + desc = "A scalpel augmented with a directed laser, allowing for bloodless incisions and built-in cautery." + id = "laserscalpel2" + req_tech = list(Tc_MATERIALS = 4, Tc_ENGINEERING = 3, Tc_BIOTECH = 4) + build_type = PROTOLATHE + materials = list (MAT_IRON = 10000, MAT_GLASS = 5000, MAT_URANIUM = 500) + category = "Surgery" + build_path = /obj/item/weapon/scalpel/laser/tier2 + +/datum/design/incisionmanager + name = "Surgical Incision Manager" + desc = "A true extension of the surgeon's body, this marvel instantly cuts the organ, clamp any bleeding, and retract the skin, allowing for the immediate commencement of therapeutic steps." + id = "incisionmanager" + req_tech = list(Tc_MATERIALS = 5, Tc_ENGINEERING = 4, Tc_BIOTECH = 5) + build_type = PROTOLATHE + materials = list (MAT_IRON = 10000, MAT_GLASS = 5000, MAT_URANIUM = 250, MAT_SILVER = 500) + category = "Surgery" + build_path = /obj/item/weapon/retractor/manager + +/datum/design/pico_grasper + name = "Precision Grasper" + desc = "A thin rod with pico manipulators embedded in it allowing for fast and precise extraction." + id = "pico_grasper" + req_tech = list(Tc_MATERIALS = 4, Tc_ENGINEERING = 3, Tc_BIOTECH = 4) + build_type = PROTOLATHE + materials = list (MAT_IRON = 10000, MAT_GLASS = 5000, MAT_PLASMA = 80) + category = "Surgery" + build_path = /obj/item/weapon/hemostat/pico + +/datum/design/plasmasaw + name = "Plasma Saw" + desc = "Perfect for cutting through ice." + id = "plasmasaw" + req_tech = list(Tc_MATERIALS = 5, Tc_ENGINEERING = 4, Tc_BIOTECH = 5, Tc_PLASMATECH = 3) + build_type = PROTOLATHE + materials = list (MAT_IRON = 10000, MAT_GLASS = 5000, MAT_PLASMA = 500) + category = "Surgery" + build_path = /obj/item/weapon/circular_saw/plasmasaw + +/datum/design/bonemender + name = "Bone Mender" + desc = "A favorite among skeletons. It even sounds like a skeleton too." + id = "bonemender" + req_tech = list(Tc_MATERIALS = 5, Tc_ENGINEERING = 4, Tc_BIOTECH = 5) + build_type = PROTOLATHE + materials = list (MAT_IRON = 10000, MAT_GLASS = 5000, MAT_GOLD = 500, MAT_SILVER = 250) + category = "Surgery" + build_path = /obj/item/weapon/bonesetter/bone_mender + +/datum/design/clot + name = "Capillary Laying Operation Tool" + desc = "A canister like tool that has two containers on it that stores synthetic vein or biofoam. There's a small processing port on the side where gauze can be inserted to produce biofoam." + id = "clot" + req_tech = list(Tc_MATERIALS = 5, Tc_ENGINEERING = 4, Tc_BIOTECH = 5) + build_type = PROTOLATHE + materials = list (MAT_IRON = 10000, MAT_GLASS = 8000, MAT_SILVER = 1000) + category = "Surgery" + build_path = /obj/item/weapon/FixOVein/clot + +/datum/design/diamond_surgicaldrill + name = "Diamond Surgical Drill" + desc = "Yours is the drill that will pierce the tiny heavens!" + id = "diamond_surgicaldrill" + req_tech = list(Tc_MATERIALS = 6, Tc_ENGINEERING = 4, Tc_BIOTECH = 5) + build_type = PROTOLATHE + materials = list (MAT_IRON = 10000, MAT_GLASS = 5000, MAT_DIAMOND = 800) + category = "Surgery" + build_path = /obj/item/weapon/surgicaldrill/diamond + +/datum/design/switchtool + name = "Surgeon's Switchtool" + desc = "A switchtool containing most of the necessary items for impromptu surgery. For the surgeon on the go." + id = "switchtool" + req_tech = list(Tc_MATERIALS = 5, Tc_BLUESPACE = 3, Tc_BIOTECH = 3) + build_type = PROTOLATHE + materials = list (MAT_IRON = 10000, MAT_GLASS = 5000) + category = "Surgery" + build_path = /obj/item/weapon/switchtool/surgery + +/datum/design/surgery_rollerbed + name = "Mobile Operating Table" + desc = "A collapsed mobile operating table that can be carried around." + id = "surgery_rollerbed" + build_type = PROTOLATHE | MECHFAB + build_path = /obj/item/roller/surgery + req_tech = list(Tc_BIOTECH = 5, Tc_ENGINEERING = 4, Tc_PROGRAMMING = 2) + materials = list(MAT_IRON = 10000, MAT_GLASS = 5000) + category = "Surgery" diff --git a/code/modules/research/fabricators.dm b/code/modules/research/fabricators.dm index 916a04dc2dd..4ea5316dbbf 100644 --- a/code/modules/research/fabricators.dm +++ b/code/modules/research/fabricators.dm @@ -29,7 +29,7 @@ var/screen = 0 var/temp var/list/part_sets = list() - + var/datum/design/last_made var/start_end_anims = 0 machine_flags = SCREWTOGGLE | CROWDESTROY | WRENCHMOVE | FIXED2WORK | EMAGGABLE @@ -63,23 +63,13 @@ T = 0 for(var/obj/item/weapon/stock_parts/manipulator/Ma in component_parts) - T += Ma.rating //T is the ammount of stock parts grade. 1 tier 1 part is a T=1, 2 tier 2 parts is a T=4, 1 tier 1 and 1 tier 3 part is a T=5 - if(T >= 2) // this removes 1 part tier level. This is to account for the fact that machines like the protolathe have 1 micro manip in them by default which means 1 tier level - T -= 2 - - var/diff - diff = round(initial(resource_coeff) - (initial(resource_coeff)*(T * 3))/25,0.01) - if(resource_coeff!=diff) - resource_coeff = diff + T += Ma.rating - 1 + resource_coeff = round(initial(resource_coeff) - (initial(resource_coeff)*(T * 3))/25,0.01) T = 0 for(var/obj/item/weapon/stock_parts/micro_laser/Ml in component_parts) - T += Ml.rating - if(T>= 2) // same idea for the formula for above - T -= 2 - diff = round(initial(time_coeff) - (initial(time_coeff)*(T *5))/25,0.01) - if(time_coeff!=diff) - time_coeff = diff + T += Ml.rating - 1 + time_coeff = round(initial(time_coeff) - (initial(time_coeff)*(T * 5))/25,0.01) /obj/machinery/r_n_d/fabricator/emag() sleep() @@ -166,8 +156,14 @@ /obj/machinery/r_n_d/fabricator/process() ..() - if(busy || stopped || being_built) + if(busy || being_built || stat&(NOPOWER|BROKEN)) return + if(stopped) + if(auto_make && last_made && !queue.len) + add_to_queue(last_made) + start_processing_queue() + else + return if(queue.len==0) stopped=1 return @@ -234,19 +230,31 @@ for(var/M in part.materials) if(copytext(M,1,2) == "$" && !(research_flags & IGNORE_MATS)) materials.removeAmount(M, get_resource_cost_w_coeff(part, M)) + else if(!(research_flags & IGNORE_CHEMS)) - reagents.remove_reagent(M, get_resource_cost_w_coeff(part, M)) + var/left_to_remove = get_resource_cost_w_coeff(part, M) + for(var/obj/item/weapon/reagent_containers/RC in component_parts) + var/remove_amount = min(RC.reagents.get_reagent_amount(M), left_to_remove) + RC.reagents.remove_reagent(M, remove_amount) + left_to_remove -= remove_amount + if(left_to_remove <= 0) + break + update_buffer_size() + return 1 /obj/machinery/r_n_d/fabricator/proc/check_mat(var/datum/design/being_built, var/M) if(copytext(M,1,2) == "$") if(src.research_flags & IGNORE_MATS) return 1 - return round(materials.storage[M] / get_resource_cost_w_coeff(being_built, M), 1) + return round(materials.storage[M] / get_resource_cost_w_coeff(being_built, M)) else if(src.research_flags & IGNORE_CHEMS) return 1 - return round(reagents.get_reagent_amount(M) / get_resource_cost_w_coeff(being_built, M), 1) + var/reagent_total = 0 + for(var/obj/item/weapon/reagent_containers/RC in component_parts) + reagent_total += RC.reagents.get_reagent_amount(M) + return round(reagent_total / get_resource_cost_w_coeff(being_built, M)) return 0 /obj/machinery/r_n_d/fabricator/proc/build_part(var/datum/design/part) @@ -304,6 +312,8 @@ being_built.forceMove(get_turf(output)) src.visible_message("[bicon(src)] \The [src] beeps: \"Successfully completed \the [being_built.name].\"") src.being_built = null + last_made = part + wires.SignalIndex(RND_WIRE_JOBFINISHED) src.updateUsrDialog() src.busy = 0 return 1 @@ -713,3 +723,6 @@ mats.forceMove(src.loc) return total_amount return 0 + +/obj/machinery/r_n_d/fabricator/proc/update_buffer_size() + return diff --git a/code/modules/research/mechanic/component_exchanger.dm b/code/modules/research/mechanic/component_exchanger.dm index 1f0390588e7..e3fc8a550fc 100644 --- a/code/modules/research/mechanic/component_exchanger.dm +++ b/code/modules/research/mechanic/component_exchanger.dm @@ -75,7 +75,7 @@ working = 0 return 1 - playsound(get_turf(src), 'sound/machines/Ping.ogg', 50, 1) //User feedback + playsound(src, 'sound/machines/Ping.ogg', 50, 1) //User feedback to_chat(user, "\The [src] pings softly. A small message appears on its HUD, instructing to not move until finished.") component_interaction(M, user) //Our job is done here, we transfer to the second proc (it needs to be recalled if needed) @@ -189,4 +189,4 @@ remove_from_storage(R, M) M.component_parts += R //Update the machine's parts - playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) //User feedback + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) //User feedback diff --git a/code/modules/research/mechanic/reverse_engine.dm b/code/modules/research/mechanic/reverse_engine.dm index bc4ba503b46..e29a7ca2914 100644 --- a/code/modules/research/mechanic/reverse_engine.dm +++ b/code/modules/research/mechanic/reverse_engine.dm @@ -11,7 +11,7 @@ var/list/datum/design/research_queue = list()//all the designs we are waiting to research var/list/datum/design/ready_queue = list()//all the designs we HAVE researched, and are ready to print - var/max_queue_len = 0 as num //maximum number of items in the research queue + var/max_queue_len = 0 //maximum number of items in the research queue var/scan_rating = 1 //the scanner rating var/cap_rating = 1 //the capacitor rating diff --git a/code/modules/research/protolathe.dm b/code/modules/research/protolathe.dm index f72cf656ba1..9d8c6245751 100644 --- a/code/modules/research/protolathe.dm +++ b/code/modules/research/protolathe.dm @@ -29,6 +29,7 @@ it creates. All the menus and other manipulation commands are in the R&D console "Data" = list(), "Engineering" = list(), "Medical" = list(), + "Surgery" = list(), "Mining" = list(), "Robotics" = list(), "Weapons" = list(), diff --git a/code/modules/research/rdconsole.dm b/code/modules/research/rdconsole.dm index 40504fe58f9..f2777597c0a 100644 --- a/code/modules/research/rdconsole.dm +++ b/code/modules/research/rdconsole.dm @@ -78,6 +78,7 @@ won't update every console in existence) but it's more of a hassle to do. Also, "Data" = list(), "Engineering" = list(), "Medical" = list(), + "Surgery" = list(), "Mining" = list(), "Robotics" = list(), "Weapons" = list(), @@ -140,13 +141,15 @@ won't update every console in existence) but it's more of a hassle to do. Also, return return_name /obj/machinery/computer/rdconsole/proc/SyncRDevices() //Makes sure it is properly sync'ed up with the devices attached to it (if any). - if(!isarea(areaMaster) || isspace(areaMaster)) + var/area/this_area = get_area(src) + if(!isarea(this_area) || isspace(this_area)) say("Unable to process synchronization") return for(var/obj/machinery/r_n_d/D in rnd_machines) //any machine in the room, just for funsies - if(D.linked_console != null || D.disabled || D.panel_open || !D.areaMaster || (D.areaMaster != areaMaster)) + var/area/D_area = get_area(D) + if(D.linked_console != null || D.disabled || D.panel_open || !D_area || (D_area != this_area)) continue if(D.type in research_machines) linked_machines += D @@ -219,7 +222,7 @@ won't update every console in existence) but it's more of a hassle to do. Also, return /obj/machinery/computer/rdconsole/emag(mob/user) - playsound(get_turf(src), 'sound/effects/sparks4.ogg', 75, 1) + playsound(src, 'sound/effects/sparks4.ogg', 75, 1) emagged = 1 if(user) to_chat(user, "You disable the security protocols") @@ -372,7 +375,7 @@ won't update every console in existence) but it's more of a hassle to do. Also, if(choice == "Cancel" || !linked_destroy) return - deconstruct_item() + deconstruct_item(usr) else if(href_list["lock"]) //Lock the console from use by anyone without tox access. if(src.allowed(usr)) @@ -480,13 +483,19 @@ won't update every console in existence) but it's more of a hassle to do. Also, if(!src.allowed(usr)) to_chat(usr, "Unauthorized Access.") return - linked_imprinter.reagents.del_reagent(href_list["dispose"]) + var/obj/item/weapon/reagent_containers/RC = locate(href_list["beakerI"]) + if(RC && RC in linked_imprinter.component_parts) + RC.reagents.del_reagent(href_list["disposeI"]) + linked_imprinter.update_buffer_size() else if(href_list["disposeallI"] && linked_imprinter) //Causes the circuit imprinter to dispose of all it's reagents. if(!src.allowed(usr)) to_chat(usr, "Unauthorized Access.") return - linked_imprinter.reagents.clear_reagents() + if(alert("Are you sure you want to flush all reagents?", "Reagents Purge Confirmation", "Continue", "Cancel") == "Continue") + for(var/obj/item/weapon/reagent_containers/RC in linked_imprinter.component_parts) + RC.reagents.clear_reagents() + linked_imprinter.update_buffer_size() else if(href_list["removeQItem"]) //Causes the protolathe to dispose of all it's reagents. var/i=text2num(href_list["removeQItem"]) @@ -925,7 +934,7 @@ won't update every console in existence) but it's more of a hassle to do. Also, dat += {"[CircuitImprinterHeader()] Circuit Imprinter Menu \[Auto-Refresh: [autorefresh ? "ON" : "OFF"]\]
      Material Amount: [linked_imprinter.TotalMaterials()] cm3
      - Chemical Volume: [linked_imprinter.reagents.total_volume]
      "} + Chemical Volume: [linked_imprinter.get_total_volume()] units
      "} dat += "Filter: " for(var/name_set in linked_imprinter.part_sets) if (name_set in filtered["imprinter"]) @@ -965,11 +974,20 @@ won't update every console in existence) but it's more of a hassle to do. Also, dat += {"[CircuitImprinterHeader()] Chemical Storage
      "} - for(var/datum/reagent/R in linked_imprinter.reagents.reagent_list) - dat += {"Name: [R.name] | Units: [R.volume] - (Purge)
      - Disposal All Chemicals in Storage
      "} + var/beaker_index = 0 + for(var/obj/item/weapon/reagent_containers/RC in linked_imprinter.component_parts) + beaker_index++ + dat += "Reservoir [beaker_index] — [RC.name]:
      " + if(RC.reagents.reagent_list && RC.reagents.reagent_list.len) + for(var/datum/reagent/R in RC.reagents.reagent_list) + dat += {"[R.name] | Units: [R.volume] + (Purge)
      "} + else + dat += "(Empty)
      " + dat += "
      " + dat += "Disposal All Chemicals in Storage
      " + if(4.3) dat += {"[CircuitImprinterHeader()] @@ -1011,7 +1029,7 @@ won't update every console in existence) but it's more of a hassle to do. Also, /obj/machinery/computer/rdconsole/npc_tamper_act(mob/living/L) //Turn on the destructive analyzer //Item making happens when the gremlin tampers with the circuit imprinter / protolathe. They don't need this console for that if(linked_destroy && linked_destroy.loaded_item) - deconstruct_item() + deconstruct_item(L) /obj/machinery/computer/rdconsole/mommi name = "MoMMI R&D Console" diff --git a/code/modules/research/rdmachines.dm b/code/modules/research/rdmachines.dm index d10ec30db2c..f956bdfa5d0 100644 --- a/code/modules/research/rdmachines.dm +++ b/code/modules/research/rdmachines.dm @@ -18,6 +18,7 @@ var/global/list/rnd_machines = list() var/stopped = 0 var/base_state = "" var/build_time = 0 + var/auto_make = 0 machine_flags = SCREWTOGGLE | CROWDESTROY | WRENCHMOVE | FIXED2WORK @@ -140,7 +141,7 @@ var/global/list/rnd_machines = list() /obj/machinery/r_n_d/attackby(var/obj/item/O as obj, var/mob/user as mob) if (shocked) - shock(user,50) + shock(user,50, O.siemens_coefficient) if (busy) to_chat(user, "The [src.name] is busy. Please wait for completion of previous operation.") return 1 diff --git a/code/modules/research/server.dm b/code/modules/research/server.dm index ee3ee745c53..e45671812c8 100644 --- a/code/modules/research/server.dm +++ b/code/modules/research/server.dm @@ -24,6 +24,8 @@ /obj/item/weapon/stock_parts/capacitor ) + icon_state_open = icon_state // needs to be here to override what's done in the parent's New() + RefreshParts() src.initialize(); //Agouri @@ -91,7 +93,10 @@ griefProtection() ..() - +/obj/machinery/r_n_d/server/update_icon() + ..() + if(panel_open) + overlays += "[initial(icon_state)]_panel" //Backup files to centcomm to help admins recover data after greifer attacks /obj/machinery/r_n_d/server/proc/griefProtection() @@ -107,20 +112,8 @@ var/turf/simulated/L = loc if(istype(L)) var/datum/gas_mixture/env = L.return_air() - if(env.temperature < (heat_amt+T0C)) - - var/transfer_moles = 0.25 * env.total_moles() - - var/datum/gas_mixture/removed = env.remove(transfer_moles) - - if(removed) - - var/heat_capacity = removed.heat_capacity() - if(heat_capacity == 0 || heat_capacity == null) - heat_capacity = 1 - removed.temperature = min((removed.temperature*heat_capacity + heating_power)/heat_capacity, 1000) - - env.merge(removed) + if(env.temperature < (heat_amt + T0C)) + env.add_thermal_energy(min(heating_power, env.get_thermal_energy_change(1000))) /obj/machinery/r_n_d/server/attack_hand(mob/user as mob) if (disabled) @@ -311,7 +304,7 @@ /obj/machinery/computer/rdservercontrol/attackby(var/obj/item/weapon/D as obj, var/mob/user as mob) if(isscrewdriver(D)) - playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1) + playsound(src, 'sound/items/Screwdriver.ogg', 50, 1) if(do_after(user, src, 20)) if (src.stat & BROKEN) to_chat(user, "The broken glass falls out.") @@ -337,7 +330,7 @@ A.anchored = 1 qdel(src) else if(istype(D, /obj/item/weapon/card/emag) && !emagged) - playsound(get_turf(src), 'sound/effects/sparks4.ogg', 75, 1) + playsound(src, 'sound/effects/sparks4.ogg', 75, 1) emagged = 1 to_chat(user, "You you disable the security protocols") src.updateUsrDialog() diff --git a/code/modules/research/xenoarchaeology/artifact/artifact_autocloner.dm b/code/modules/research/xenoarchaeology/artifact/artifact_autocloner.dm index 2e5a959bde8..6db85454f6f 100644 --- a/code/modules/research/xenoarchaeology/artifact/artifact_autocloner.dm +++ b/code/modules/research/xenoarchaeology/artifact/artifact_autocloner.dm @@ -69,7 +69,7 @@ if(spawn_type) new spawn_type(src.loc) investigation_log(I_ARTIFACT, "|| spawned a [spawn_type].") - playsound(get_turf(src), 'sound/machines/heps.ogg', 50, 0) + playsound(src, 'sound/machines/heps.ogg', 50, 0) //if we're getting close to finished, kick into overdrive power usage if(current_ticks_spawning / ticks_required_to_spawn > 0.75) diff --git a/code/modules/research/xenoarchaeology/artifact/artifact_replicator.dm b/code/modules/research/xenoarchaeology/artifact/artifact_replicator.dm index 39a836e23ed..96a4ca782f2 100644 --- a/code/modules/research/xenoarchaeology/artifact/artifact_replicator.dm +++ b/code/modules/research/xenoarchaeology/artifact/artifact_replicator.dm @@ -90,7 +90,7 @@ use_power = 1 icon_state = "borgcharger0(old)" - playsound(get_turf(src), 'sound/machines/heps.ogg', 50, 0) + playsound(src, 'sound/machines/heps.ogg', 50, 0) else if(prob(5)) src.visible_message("[bicon(src)] [src] [pick("clicks","whizzes","whirrs","whooshes","clanks","clongs","clonks","bangs")].") @@ -148,4 +148,4 @@ spawn_progress = 0 use_power = 2 icon_state = "borgcharger1(old)" - playsound(get_turf(src), 'sound/machines/click.ogg', 50, 0) + playsound(src, 'sound/machines/click.ogg', 50, 0) diff --git a/code/modules/research/xenoarchaeology/artifact/effects/unknown_affect_cold.dm b/code/modules/research/xenoarchaeology/artifact/effects/unknown_affect_cold.dm index 5497bbc5910..7a626898e73 100644 --- a/code/modules/research/xenoarchaeology/artifact/effects/unknown_affect_cold.dm +++ b/code/modules/research/xenoarchaeology/artifact/effects/unknown_affect_cold.dm @@ -16,9 +16,11 @@ var/datum/gas_mixture/env = holder.loc.return_air() if(env) env.temperature = max(env.temperature - rand(5,50), 0) + env.update_values() /datum/artifact_effect/cold/DoEffectAura() if(holder) var/datum/gas_mixture/env = holder.loc.return_air() if(env && env.temperature > target_temp) env.temperature -= pick(0, 0, 1) + env.update_values() diff --git a/code/modules/research/xenoarchaeology/artifact/effects/unknown_effect_gasco2.dm b/code/modules/research/xenoarchaeology/artifact/effects/unknown_effect_gasco2.dm index 907b676eb25..4487e8f9270 100644 --- a/code/modules/research/xenoarchaeology/artifact/effects/unknown_effect_gasco2.dm +++ b/code/modules/research/xenoarchaeology/artifact/effects/unknown_effect_gasco2.dm @@ -14,10 +14,10 @@ if(holder) var/datum/gas_mixture/env = holder.loc.return_air() if(env) - env.carbon_dioxide += rand(2,15) + env.adjust_gas("carbon_dioxide", rand(2,15)) /datum/artifact_effect/gasco2/DoEffectAura() if(holder) var/datum/gas_mixture/env = holder.loc.return_air() - if(env && env.total_moles < max_pressure) - env.carbon_dioxide += pick(0, 0, 0.1, rand()) + if(env && env.pressure < max_pressure) + env.adjust_gas("carbon_dioxide", pick(0, 0, 0.1, rand())) diff --git a/code/modules/research/xenoarchaeology/artifact/effects/unknown_effect_gasnitro.dm b/code/modules/research/xenoarchaeology/artifact/effects/unknown_effect_gasnitro.dm index 7732df688de..d197ef8d19f 100644 --- a/code/modules/research/xenoarchaeology/artifact/effects/unknown_effect_gasnitro.dm +++ b/code/modules/research/xenoarchaeology/artifact/effects/unknown_effect_gasnitro.dm @@ -15,10 +15,10 @@ if(holder) var/datum/gas_mixture/env = holder.loc.return_air() if(env) - env.nitrogen += rand(2,15) + env.adjust_gas("nitrogen", rand(2,15)) /datum/artifact_effect/gasnitro/DoEffectAura() if(holder) var/datum/gas_mixture/env = holder.loc.return_air() - if(env && env.total_moles < max_pressure) - env.nitrogen += pick(0, 0, 0.1, rand()) + if(env && env.pressure < max_pressure) + env.adjust_gas("nitrogen", pick(0, 0, 0.1, rand())) diff --git a/code/modules/research/xenoarchaeology/artifact/effects/unknown_effect_gasoxy.dm b/code/modules/research/xenoarchaeology/artifact/effects/unknown_effect_gasoxy.dm index a2408214f2d..8caad038795 100644 --- a/code/modules/research/xenoarchaeology/artifact/effects/unknown_effect_gasoxy.dm +++ b/code/modules/research/xenoarchaeology/artifact/effects/unknown_effect_gasoxy.dm @@ -15,10 +15,10 @@ if(holder) var/datum/gas_mixture/env = holder.loc.return_air() if(env) - env.oxygen += rand(2,15) + env.adjust_gas("oxygen", rand(2,15)) /datum/artifact_effect/gasoxy/DoEffectAura() if(holder) var/datum/gas_mixture/env = holder.loc.return_air() - if(env && env.total_moles < max_pressure) - env.oxygen += pick(0, 0, 0.1, rand()) + if(env && env.pressure < max_pressure) + env.adjust_gas("oxygen", pick(0, 0, 0.1, rand())) diff --git a/code/modules/research/xenoarchaeology/artifact/effects/unknown_effect_gasplasma.dm b/code/modules/research/xenoarchaeology/artifact/effects/unknown_effect_gasplasma.dm index 64aaaec8851..80dcbc59bdd 100644 --- a/code/modules/research/xenoarchaeology/artifact/effects/unknown_effect_gasplasma.dm +++ b/code/modules/research/xenoarchaeology/artifact/effects/unknown_effect_gasplasma.dm @@ -15,10 +15,10 @@ if(holder) var/datum/gas_mixture/env = holder.loc.return_air() if(env) - env.toxins += rand(2,15) + env.adjust_gas("plasma", rand(2,15)) /datum/artifact_effect/gasplasma/DoEffectAura() if(holder) var/datum/gas_mixture/env = holder.loc.return_air() - if(env && env.total_moles < max_pressure) - env.toxins += pick(0, 0, 0.1, rand()) + if(env && env.pressure < max_pressure) + env.adjust_gas("plasma", pick(0, 0, 0.1, rand())) diff --git a/code/modules/research/xenoarchaeology/artifact/effects/unknown_effect_gassleeping.dm b/code/modules/research/xenoarchaeology/artifact/effects/unknown_effect_gassleeping.dm index 1ed5128b156..32c58155b34 100644 --- a/code/modules/research/xenoarchaeology/artifact/effects/unknown_effect_gassleeping.dm +++ b/code/modules/research/xenoarchaeology/artifact/effects/unknown_effect_gassleeping.dm @@ -16,17 +16,15 @@ var/datum/gas_mixture/env = holder.loc.return_air() if(env) var/datum/gas/sleeping_agent/trace_gas = new - env.trace_gases += trace_gas trace_gas.moles = rand(2,15) - env.update_values() + env.adjust(traces = list(trace_gas)) /datum/artifact_effect/gassleeping/DoEffectAura() if(holder) var/datum/gas_mixture/env = holder.loc.return_air() - if(env && env.total_moles < max_pressure) + if(env && env.pressure < max_pressure) var/datum/gas/sleeping_agent/trace_gas = new - env.trace_gases += trace_gas trace_gas.moles = pick(0, 0, 0.1, rand()) - env.update_values() + env.adjust(traces = list(trace_gas)) diff --git a/code/modules/research/xenoarchaeology/artifact/effects/unknown_effect_heat.dm b/code/modules/research/xenoarchaeology/artifact/effects/unknown_effect_heat.dm index 6cc7165c9c6..ff90d677700 100644 --- a/code/modules/research/xenoarchaeology/artifact/effects/unknown_effect_heat.dm +++ b/code/modules/research/xenoarchaeology/artifact/effects/unknown_effect_heat.dm @@ -16,9 +16,11 @@ var/datum/gas_mixture/env = holder.loc.return_air() if(env) env.temperature += rand(5,50) + env.update_values() /datum/artifact_effect/heat/DoEffectAura() if(holder) var/datum/gas_mixture/env = holder.loc.return_air() if(env && env.temperature < target_temp) env.temperature += pick(0, 0, 1) + env.update_values() diff --git a/code/modules/research/xenoarchaeology/artifact/triggers/unknown_trigger_gas.dm b/code/modules/research/xenoarchaeology/artifact/triggers/unknown_trigger_gas.dm index 8f118152375..318bda18283 100644 --- a/code/modules/research/xenoarchaeology/artifact/triggers/unknown_trigger_gas.dm +++ b/code/modules/research/xenoarchaeology/artifact/triggers/unknown_trigger_gas.dm @@ -1,4 +1,4 @@ -#define MOLE_TRIGGER 10 +#define MOLE_TRIGGER (10 / CELL_VOLUME) /datum/artifact_trigger/gas triggertype = TRIGGER_GAS @@ -7,7 +7,7 @@ /datum/artifact_trigger/gas/New() ..() - trigger_gas = pick("TOXINS","CARBON_DIOXIDE","NITROGEN","OXYGEN") + trigger_gas = pick("TOXINS", "CARBON_DIOXIDE", "NITROGEN", "OXYGEN") /datum/artifact_trigger/gas/CheckTrigger() @@ -15,24 +15,9 @@ var/datum/gas_mixture/env = T.return_air() if(env) if(!my_effect.activated) - if(trigger_gas == "TOXINS" && env.toxins >= MOLE_TRIGGER) - Triggered(0, trigger_gas, 0) - if(trigger_gas == "CARBON_DIOXIDE" && env.carbon_dioxide >= MOLE_TRIGGER) - Triggered(0, trigger_gas, 0) - if(trigger_gas == "NITROGEN" && env.nitrogen >= MOLE_TRIGGER) - Triggered(0, trigger_gas, 0) - if(trigger_gas == "OXYGEN" && env.oxygen >= MOLE_TRIGGER) + if(env.molar_density(lowertext(trigger_gas)) >= MOLE_TRIGGER) Triggered(0, trigger_gas, 0) else - if(trigger_gas == "TOXINS" && env.toxins < MOLE_TRIGGER) + if(env.molar_density(lowertext(trigger_gas)) < MOLE_TRIGGER) Triggered(0, trigger_gas, 0) - if(trigger_gas == "CARBON_DIOXIDE" && env.carbon_dioxide < MOLE_TRIGGER) - Triggered(0, trigger_gas, 0) - if(trigger_gas == "NITROGEN" && env.nitrogen < MOLE_TRIGGER) - Triggered(0, trigger_gas, 0) - if(trigger_gas == "OXYGEN" && env.oxygen < MOLE_TRIGGER) - Triggered(0, trigger_gas, 0) - -/datum/artifact_trigger/gas/Destroy() - ..() \ No newline at end of file diff --git a/code/modules/research/xenoarchaeology/artifact/triggers/unknown_trigger_pay2use.dm b/code/modules/research/xenoarchaeology/artifact/triggers/unknown_trigger_pay2use.dm index 68d8e2f82d7..fcebbe67950 100644 --- a/code/modules/research/xenoarchaeology/artifact/triggers/unknown_trigger_pay2use.dm +++ b/code/modules/research/xenoarchaeology/artifact/triggers/unknown_trigger_pay2use.dm @@ -80,7 +80,7 @@ my_artifact.investigation_log(I_ARTIFACT, "|| effect [my_effect.artifact_id]([my_effect]) || [item] inserted to ([my_effect.trigger]) || used by [key_name(toucher)].") my_artifact.visible_message("[toucher] inserts a coin into [my_artifact].") if(istype(item, /obj/item/weapon/coin/clown)) - playsound(get_turf(my_artifact), 'sound/items/bikehorn.ogg', 50, 1) + playsound(my_artifact, 'sound/items/bikehorn.ogg', 50, 1) time_left += 150 else if(istype(item, /obj/item/weapon/coin/iron)) time_left += 10 diff --git a/code/modules/research/xenoarchaeology/finds/finds.dm b/code/modules/research/xenoarchaeology/finds/finds.dm index 736fbdf7fd8..ec86a308173 100644 --- a/code/modules/research/xenoarchaeology/finds/finds.dm +++ b/code/modules/research/xenoarchaeology/finds/finds.dm @@ -421,10 +421,10 @@ additional_desc += " There seems to be some sort of slot in the handle." //let's get some ammunition in this gun : weighted to pick available ammo - new_gun.caliber = pick(50;list("357" = 1), - 10;list("75" = 1), - 30;list("38" = 1), - 10;list("12mm" = 1)) + new_gun.caliber = pick(50;list(POINT357 = 1), + 10;list(POINT75 = 1), + 30;list(POINT38 = 1), + 10;list(MM12 = 1)) //33% chance to fill it with a random amount of bullets new_gun.max_shells = rand(1,12) @@ -509,7 +509,7 @@ anomaly_factor = 2 apply_prefix = FALSE item_type = "[pick("mechanical","robotic","cyborg")] [pick("remains","chassis","debris")]" - icon = 'icons/effects/blood.dmi' + icon = 'icons/mob/robots.dmi' icon_state = "remainsrobot" additional_desc = pick("Almost mistakeable for the remains of a modern cyborg.",\ "They are barely recognisable as anything other than a pile of waste metals.",\ diff --git a/code/modules/research/xenoarchaeology/finds/finds_fossils.dm b/code/modules/research/xenoarchaeology/finds/finds_fossils.dm index 2d27e6b91e3..52fc4691c10 100644 --- a/code/modules/research/xenoarchaeology/finds/finds_fossils.dm +++ b/code/modules/research/xenoarchaeology/finds/finds_fossils.dm @@ -103,6 +103,7 @@ desc = "It's fossilised plant remains." /obj/item/weapon/fossil/plant/New() + ..() icon_state = "plant[rand(1,4)]" var/prehistoric_plants = list( /obj/item/seeds/telriis, @@ -112,5 +113,6 @@ /obj/item/seeds/gelthi, /obj/item/seeds/vale, /obj/item/seeds/surik, + /obj/item/seeds/mushroommanspore, ) nonplant_seed_type = pick(prehistoric_plants) diff --git a/code/modules/research/xenoarchaeology/finds/finds_strangeball.dm b/code/modules/research/xenoarchaeology/finds/finds_strangeball.dm index c254598619d..636979e1c0d 100644 --- a/code/modules/research/xenoarchaeology/finds/finds_strangeball.dm +++ b/code/modules/research/xenoarchaeology/finds/finds_strangeball.dm @@ -13,16 +13,12 @@ /obj/item/device/mmi/posibrain/strangeball/transfer_personality(var/mob/candidate) src.searching = 0 var/turf/T = get_turf(src) - var/mob/living/silicon/robot/M = new /mob/living/silicon/robot(T) - M.UnlinkSelf() //No Lawsync, No robotics console, No camera, final destination. - M.laws = new /datum/ai_laws/asimov() // WOOP WOOP HUMAN HARM - M.cell.maxcharge = 15000 - M.cell.charge = 15000 - M.pick_module(forced_module="TG17355") + var/mob/living/silicon/robot/M = new /mob/living/silicon/robot/hugborg(T) M.icon_state = burger M.updateicon() M.ckey = candidate.ckey - M.Namepick() + spawn() + M.Namepick() M.updatename() src.investigation_log(I_ARTIFACT, "|| [key_name(M)] spawned as TG17355 Cyborg.") qdel(src) diff --git a/code/modules/research/xenoarchaeology/machinery/analysis_base.dm b/code/modules/research/xenoarchaeology/machinery/analysis_base.dm index d6020da79f5..38b2ebd7211 100644 --- a/code/modules/research/xenoarchaeology/machinery/analysis_base.dm +++ b/code/modules/research/xenoarchaeology/machinery/analysis_base.dm @@ -84,32 +84,32 @@ //Add 3000 joules when active. This is about 0.6 degrees per tick. //May need adjustment if(use_power == 1) - var/heat_added = active_power_usage *XENOARCH_HEAT_COEFFICIENT + var/heat_added = active_power_usage * XENOARCH_HEAT_COEFFICIENT if(temperature < XENOARCH_MAX_HEAT_INCREASE_TEMP) - temperature += heat_added/XENOARCH_HEAT_CAPACITY + temperature += heat_added / XENOARCH_HEAT_CAPACITY - var/temperature_difference = abs(environmental_temp-temperature) - var/datum/gas_mixture/removed = loc.remove_air(env.total_moles*0.25) + var/temperature_difference = abs(environmental_temp - temperature) + var/datum/gas_mixture/removed = env.remove_volume(0.25 * CELL_VOLUME) var/heat_capacity = removed.heat_capacity() - heat_added = min(temperature_difference*heat_capacity, XENOARCH_MAX_ENERGY_TRANSFER) + heat_added = min(temperature_difference * heat_capacity, XENOARCH_MAX_ENERGY_TRANSFER) if(temperature > environmental_temp) //cool down to match the air - temperature = max(TCMB, temperature - heat_added/XENOARCH_HEAT_CAPACITY) - removed.temperature = max(TCMB, removed.temperature + heat_added/heat_capacity) + temperature = max(TCMB, temperature - heat_added / XENOARCH_HEAT_CAPACITY) + removed.temperature = max(TCMB, removed.temperature + heat_added / heat_capacity) if(temperature_difference > 10 && prob(5)) visible_message("[bicon(src)] hisses softly.", "You hear a soft hiss.") else //heat up to match the air - temperature = max(TCMB, temperature + heat_added/XENOARCH_HEAT_CAPACITY) - removed.temperature = max(TCMB, removed.temperature - heat_added/heat_capacity) + temperature = max(TCMB, temperature + heat_added / XENOARCH_HEAT_CAPACITY) + removed.temperature = max(TCMB, removed.temperature - heat_added / heat_capacity) if(temperature_difference > 10 && prob(5)) - visible_message("[bicon(src)] plinks quietly.", "You hear a soft hiss.") + visible_message("[bicon(src)] plinks quietly.", "You hear a quiet plink.") env.merge(removed) diff --git a/code/modules/research/xenoarchaeology/tools/bunsen_burner.dm b/code/modules/research/xenoarchaeology/tools/bunsen_burner.dm index baace91eca2..9390630051f 100644 --- a/code/modules/research/xenoarchaeology/tools/bunsen_burner.dm +++ b/code/modules/research/xenoarchaeology/tools/bunsen_burner.dm @@ -90,8 +90,8 @@ if(iswrench(W)) user.visible_message("[user] starts to deconstruct \the [src]!","You start to deconstruct \the [src].") if(do_after(user, src, 5 SECONDS)) - playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1) - drop_stack(/obj/item/stack/sheet/metal, loc, rand(3,4), user) + playsound(src, 'sound/items/Ratchet.ogg', 50, 1) + drop_stack(sheet_type, loc, rand(3,4), user) qdel(src) else ..() @@ -100,7 +100,7 @@ if(held_container && heating == BUNSEN_ON) var/turf/T = get_turf(src) var/datum/gas_mixture/G = T.return_air() - if(!G || G.oxygen < 0.1) + if(!G || G.molar_density("oxygen") < 0.1 / CELL_VOLUME) visible_message("\The [src] splutters out from lack of oxygen.","You hear something cough.") toggle() return @@ -205,4 +205,4 @@ #undef BUNSEN_OPEN #undef BUNSEN_OFF -#undef BUNSEN_ON \ No newline at end of file +#undef BUNSEN_ON diff --git a/code/modules/spells/aoe_turf/conjure/conjure.dm b/code/modules/spells/aoe_turf/conjure/conjure.dm index 0acb8ae7f86..310947009ac 100644 --- a/code/modules/spells/aoe_turf/conjure/conjure.dm +++ b/code/modules/spells/aoe_turf/conjure/conjure.dm @@ -24,7 +24,7 @@ How they spawn stuff is decided by behaviour vars, which are explained below /spell/aoe_turf/conjure/cast(list/targets, mob/user) if(!isnull(cast_sound)) - playsound(get_turf(user), cast_sound, 50, 1) + playsound(user, cast_sound, 50, 1) var/placed_successfully = 0 for(var/i=1,i <= summon_amt,i++) diff --git a/code/modules/spells/aoe_turf/conjure/doppelganger.dm b/code/modules/spells/aoe_turf/conjure/doppelganger.dm index aff3a3a02ae..1103320b598 100644 --- a/code/modules/spells/aoe_turf/conjure/doppelganger.dm +++ b/code/modules/spells/aoe_turf/conjure/doppelganger.dm @@ -14,11 +14,18 @@ invocation_type = SpI_SHOUT spell_flags = NEEDSCLOTHES hud_state = "wiz_doppelganger" + var/spell_duration = 8 MINUTES + +var/list/doppelgangers_count_by_wizards = list() var/list/doppelgangers = list() +#define MAX_DOPPLES 15 // Sanity : don't copy more than one guy /spell/aoe_turf/conjure/doppelganger/cast_check(skipcharge = 0,mob/user = usr) + if (doppelgangers_count_by_wizards[user] > MAX_DOPPLES) // We summoned too much doppels :( + to_chat(user, "We have duplicated ourselves too much in this plane.") + return FALSE var/list/L = view(user, 0) L -= user for (var/mob/M in L) @@ -31,6 +38,9 @@ var/list/doppelgangers = list() doppelgangers[D] = holder D.appearance = holder.appearance D.alpha = OPAQUE // No more invisible doppels + doppelgangers_count_by_wizards[holder]++ // Update the counts of doppels we summoned + spawn (spell_duration) + D.death() /spell/aoe_turf/conjure/doppelganger/on_holder_death(mob/user) if(!user) diff --git a/code/modules/spells/aoe_turf/conjure/snowmobile.dm b/code/modules/spells/aoe_turf/conjure/snowmobile.dm index 1cfa30927f4..d3e93c56420 100644 --- a/code/modules/spells/aoe_turf/conjure/snowmobile.dm +++ b/code/modules/spells/aoe_turf/conjure/snowmobile.dm @@ -7,7 +7,7 @@ charge_max = 1 school = "conjuration" spell_flags = Z2NOCAST - invocation = "How much did Santa pay for his sleigh? Nothing, it was on the house!" + invocation = "SL'IGH B'LLS RIN'!" invocation_type = SpI_SHOUT range = 0 diff --git a/code/modules/spells/aoe_turf/knock.dm b/code/modules/spells/aoe_turf/knock.dm index 76ebcc9de90..d5d137986d3 100644 --- a/code/modules/spells/aoe_turf/knock.dm +++ b/code/modules/spells/aoe_turf/knock.dm @@ -24,6 +24,25 @@ var/obj/machinery/door/airlock/AL = door //casting is important AL.locked = 0 door.open() + for(var/obj/structure/closet/C in T.contents) + spawn(1) + if(istype(C,/obj/structure/closet)) + var/obj/structure/closet/LC = C + LC.locked = 0 + LC.welded = 0 + C.open() + for(var/obj/structure/safe/S in T.contents) + spawn(1) + if(istype(S,/obj/structure/safe)) + var/obj/structure/safe/SA = S + SA.open = 1 + S.update_icon() + for(var/obj/item/weapon/storage/lockbox/L in T.contents) + spawn(1) + if(istype(L,/obj/item/weapon/storage/lockbox)) + var/obj/item/weapon/storage/lockbox/LL = L + LL.locked = 0 + L.update_icon() return diff --git a/code/modules/spells/general/lightning.dm b/code/modules/spells/general/lightning.dm index fd9fb9da0b0..6e7a5d39a51 100644 --- a/code/modules/spells/general/lightning.dm +++ b/code/modules/spells/general/lightning.dm @@ -85,7 +85,7 @@ if(user.spell_channeling && !force_remove) user.overlays += chargeoverlay if(world.time >= last_active_sound + 50) - playsound(get_turf(user), 'sound/effects/lightning/chainlightning_activate.ogg', 100, 1, "vary" = 0) + playsound(user, 'sound/effects/lightning/chainlightning_activate.ogg', 100, 1, "vary" = 0) last_active_sound = world.time zapzap = multicast //give user overlay @@ -94,7 +94,7 @@ connected_button.name = name charge_counter = charge_max user.overlays -= chargeoverlay - if(zapzap != multicast) //partial cast + if((zapzap != multicast) && (zapzap != 0)) //partial cast take_charge(holder, 0) zapzap = 0 return 1 @@ -110,10 +110,8 @@ to_chat(user, "You can throw lightning [zapzap] more time\s") . = 1 - invocation(user) spawn() zapmuthafucka(user, L, bounces) - src.process() /spell/lightning/proc/zapmuthafucka(var/mob/user, var/mob/living/target, var/chained = bounces, var/list/zapped = list(), var/oursound = null) var/otarget = target @@ -126,7 +124,7 @@ if(!oursound) oursound = pick(lightning_sound) L.our_spell = src - playsound(get_turf(user), oursound, 100, 1, "vary" = 0) + playsound(user, oursound, 100, 1, "vary" = 0) L.tang = adjustAngle(get_angle(U,T)) L.icon = midicon L.icon_state = "[L.tang]" @@ -163,7 +161,8 @@ target.emp_act(2) target.apply_damage((issilicon(target) ? basedamage*0.66 : basedamage), BURN, LIMB_CHEST, "blocked" = 0) else if(target) - var/obj/item/projectile/beam/B = getFromPool(/obj/item/projectile/beam/lightning/spell) + var/obj/item/projectile/beam/lightning/spell/B = getFromPool(/obj/item/projectile/beam/lightning/spell) + B.our_spell = src B.damage = basedamage target.bullet_act(B) returnToPool(B) diff --git a/code/modules/spells/general/reflect_pain.dm b/code/modules/spells/general/reflect_pain.dm index 91b10d0c09a..8a4c3a1eeef 100644 --- a/code/modules/spells/general/reflect_pain.dm +++ b/code/modules/spells/general/reflect_pain.dm @@ -40,7 +40,7 @@ to_chat(T, "An unholy charm binds your life to [L]. While the spell is active, any pain \he receive\s will be redirected to you.") var/event_key = L.on_damaged.Add(src, "reflect") L.overlays.Add(user_overlay) - playsound(get_turf(L), 'sound/effects/vampire_intro.ogg', 80, 1, "vary" = 0) + playsound(L, 'sound/effects/vampire_intro.ogg', 80, 1, "vary" = 0) spawn(duration) to_chat(L, "Your life essence is no longer bound to this plane. You won't reflect received damage to your enemies anymore.") diff --git a/code/modules/spells/general/ring_of_fire.dm b/code/modules/spells/general/ring_of_fire.dm index 8612da5b89e..0c5ff9a7405 100644 --- a/code/modules/spells/general/ring_of_fire.dm +++ b/code/modules/spells/general/ring_of_fire.dm @@ -10,10 +10,12 @@ level_max = list(Sp_TOTAL = 4, Sp_SPEED = 3, Sp_MOVE = 1) spell_flags = NEEDSCLOTHES + spell_aspect_flags = SPELL_FIRE charge_type = Sp_RECHARGE invocation = "E ROHA" invocation_type = SpI_SHOUT hud_state = "wiz_firering" + price = Sp_BASE_PRICE / 2 duration = 100 range = 3 diff --git a/code/modules/spells/helpers.dm b/code/modules/spells/helpers.dm index c5c81e86bf3..0dbfdb54a9f 100644 --- a/code/modules/spells/helpers.dm +++ b/code/modules/spells/helpers.dm @@ -33,3 +33,9 @@ return getAllSpellsByType(USER_TYPE_XENOMORPH) /proc/getAllVampSpells() return getAllSpellsByType(USER_TYPE_VAMPIRE) + +/mob/proc/has_spell_with_flag(var/spell_flag) + for(var/spell/S in spell_list) + if(S.spell_aspect_flags & spell_flag) + return S + return 0 diff --git a/code/modules/spells/spell_code.dm b/code/modules/spells/spell_code.dm index c5d1c2b2e63..6a38bdcf875 100644 --- a/code/modules/spells/spell_code.dm +++ b/code/modules/spells/spell_code.dm @@ -66,6 +66,10 @@ var/list/spells = typesof(/spell) //needed for the badmin verb for now var/delay_reduc = 0 var/cooldown_min = 0 //minimum possible cooldown for a charging spell + var/spell_aspect_flags + //Flags for what this spell is 'based' upon, for interacting with other spells + //For instance, a fire-based spell would have the FIRE flag + var/overlay = 0 var/overlay_icon = 'icons/obj/wizard.dmi' var/overlay_icon_state = "spell" @@ -80,6 +84,7 @@ var/list/spells = typesof(/spell) //needed for the badmin verb for now var/cast_delay = 1 var/cast_sound = "" + var/use_progress_bar = FALSE var/hud_state = "" //name of the icon used in generating the spell hud object var/override_base = "" @@ -513,45 +518,26 @@ var/list/spells = typesof(/spell) //needed for the badmin verb for now return 0 var/delayfraction = round(delay/numticks) + var/original_location = user.loc var/originalstat = user.stat - var/Location = user.loc - var/image/progbar - if(user && user.client && user.client.prefs.progress_bars) - if(!progbar) - progbar = image("icon" = 'icons/effects/doafter_icon.dmi', "loc" = user, "icon_state" = "prog_bar_0") - progbar.pixel_z = WORLD_ICON_SIZE - progbar.plane = HUD_PLANE - progbar.layer = HUD_ABOVE_ITEM_LAYER - progbar.appearance_flags = RESET_COLOR - - for (var/i = 1 to numticks) - if(user && user.client && user.client.prefs.progress_bars) - if(!progbar) - progbar = image("icon" = 'icons/effects/doafter_icon.dmi', "loc" = user, "icon_state" = "prog_bar_0") - progbar.pixel_z = WORLD_ICON_SIZE - progbar.plane = HUD_PLANE - progbar.layer = HUD_ABOVE_ITEM_LAYER - progbar.appearance_flags = RESET_COLOR - progbar.icon_state = "prog_bar_[round(((i / numticks) * 100), 10)]" - user.client.images |= progbar + var/image/progress_bar + if(use_progress_bar) + if(user.client && user.client.prefs.progress_bars) + progress_bar = create_progress_bar_on(user) + user.client.images += progress_bar + for(var/i = 0, iI don't feel strong enough without my hat.
      ") return 0 return 1 -*/ \ No newline at end of file +*/ diff --git a/code/modules/spells/targeted/buttbots_revenge.dm b/code/modules/spells/targeted/buttbots_revenge.dm index 85ef6cdec51..a0bd0044bbb 100644 --- a/code/modules/spells/targeted/buttbots_revenge.dm +++ b/code/modules/spells/targeted/buttbots_revenge.dm @@ -35,7 +35,7 @@ B.transfer_buttdentity(C) C.op_stage.butt = 4 //No having two butts. to_chat(C, "Your ass just blew up!") - playsound(get_turf(src), 'sound/effects/superfart.ogg', 50, 1) + playsound(src, 'sound/effects/superfart.ogg', 50, 1) C.apply_damage(40, BRUTE, LIMB_GROIN) C.apply_damage(10, BURN, LIMB_GROIN) return diff --git a/code/modules/spells/targeted/equip/clowncurse.dm b/code/modules/spells/targeted/equip/clowncurse.dm index 6f5a135823b..3362af6d12e 100644 --- a/code/modules/spells/targeted/equip/clowncurse.dm +++ b/code/modules/spells/targeted/equip/clowncurse.dm @@ -50,7 +50,7 @@ name = "The Elf Curse" desc = "A curse that will turn its victim into a miserable christmas elf." abbreviation = "EC" - holiday_required = list("Christmas") + holiday_required = list(XMAS) hud_state = "wiz_elf" diff --git a/code/modules/spells/targeted/equip/horsemask.dm b/code/modules/spells/targeted/equip/horsemask.dm index 686fb03fe95..e1fb3dacd88 100644 --- a/code/modules/spells/targeted/equip/horsemask.dm +++ b/code/modules/spells/targeted/equip/horsemask.dm @@ -46,7 +46,7 @@ name = "Curse of the Reindeer" desc = "This spell triggers a curse on a target, causing them to wield an unremovable reindeer head mask. They will speak like a horse! Any masks they are wearing will be disintegrated. This spell does not require robes." abbreviation = "RH" - holiday_required = list("Christmas") + holiday_required = list(XMAS) invocation = "KN'A RUD'LPH, XMAS 'BTHNK!" diff --git a/code/modules/spells/targeted/fist.dm b/code/modules/spells/targeted/fist.dm index fa5a2c8efa3..59176e17fc8 100644 --- a/code/modules/spells/targeted/fist.dm +++ b/code/modules/spells/targeted/fist.dm @@ -1,10 +1,11 @@ /spell/targeted/fist name = "Fist" - desc = "This spell punches everyone in view." + desc = "This spell punches up to three beings in view." abbreviation = "FS" user_type = USER_TYPE_WIZARD charge_max = 50 + spell_flags = 0 //So that it doesn't open a dialog box. cooldown_min = 10 invocation = "I CAST FIST" invocation_type = SpI_SHOUT diff --git a/code/modules/spells/targeted/genetic.dm b/code/modules/spells/targeted/genetic.dm index f791e44356b..c007879c40a 100644 --- a/code/modules/spells/targeted/genetic.dm +++ b/code/modules/spells/targeted/genetic.dm @@ -52,6 +52,7 @@ code\game\\dna\genes\goon_powers.dm hud_state = "wiz_blind" price = 0.5 * Sp_BASE_PRICE //Half of the normal spell price + user_type = USER_TYPE_WIZARD /spell/targeted/genetic/mutate name = "Mutate" @@ -71,4 +72,5 @@ code\game\\dna\genes\goon_powers.dm duration = 300 cooldown_min = 300 //25 deciseconds reduction per rank - hud_state = "wiz_hulk" \ No newline at end of file + hud_state = "wiz_hulk" + user_type = USER_TYPE_WIZARD diff --git a/code/modules/spells/targeted/grease.dm b/code/modules/spells/targeted/grease.dm new file mode 100644 index 00000000000..d19e7ba434b --- /dev/null +++ b/code/modules/spells/targeted/grease.dm @@ -0,0 +1,51 @@ +/spell/targeted/grease + name = "Grease" + desc = "Slick grease covers the ground in a radius, turning the terrain into difficult terrain. Has spell congruency with fire-based spells." + abbreviation = "GR" + user_type = USER_TYPE_WIZARD + + school = "evocation" + charge_max = 300 + invocation = "GR'ESE LIT'NING" + invocation_type = SpI_SHOUT + range = 1 + spell_flags = NEEDSCLOTHES | INCLUDEUSER + level_max = list(Sp_TOTAL = 5, Sp_SPEED = 4, Sp_POWER = 1) + hud_state = "bucket" + + +/spell/targeted/grease/empower_spell() + spell_levels[Sp_POWER]++ + + var/explosion_description = "" + switch(spell_levels[Sp_POWER]) + if(0) + explosion_description = "You will now emit grease from your location." + if(1) + name = "Slick Grease" + range = 4 + explosion_description = "You can now point to a location within [range] to become a grease slick. Has spell congruency with fire-based spells." + spell_flags |= WAIT_FOR_CLICK + else + return + + return "You have improved Grease into [name]. [explosion_description]" + +/spell/targeted/grease/cast(var/list/targets, mob/user) + if(spell_levels[Sp_POWER] >= 1) + for(var/A in targets) + var/turf/T = get_turf(A) + var/datum/effect/effect/system/foam_spread/s = new() + s.set_up(50, T, null, 0) + s.carried_reagents.Add(LUBE) + if(user.has_spell_with_flag(SPELL_FIRE)) + s.carried_reagents.Add(FUEL) + s.start() + else + var/turf/T = get_turf(user) + var/datum/effect/effect/system/foam_spread/s = new() + s.set_up(50, T, null, 0) + s.carried_reagents.Add(LUBE) + if(user.has_spell_with_flag(SPELL_FIRE)) + s.carried_reagents.Add(FUEL) + s.start() \ No newline at end of file diff --git a/code/modules/spells/targeted/projectile/fireball.dm b/code/modules/spells/targeted/projectile/fireball.dm index fa83bbaa69a..4f07bf1cf71 100644 --- a/code/modules/spells/targeted/projectile/fireball.dm +++ b/code/modules/spells/targeted/projectile/fireball.dm @@ -15,7 +15,7 @@ cooldown_min = 20 //10 deciseconds reduction per rank spell_flags = 0 - + spell_aspect_flags = SPELL_FIRE duration = 20 proj_step_delay = 0 diff --git a/code/modules/spells/targeted/projectile/firebreath.dm b/code/modules/spells/targeted/projectile/firebreath.dm index 151e5eb4cdf..80236b7246a 100644 --- a/code/modules/spells/targeted/projectile/firebreath.dm +++ b/code/modules/spells/targeted/projectile/firebreath.dm @@ -10,6 +10,7 @@ invocation = "SPY'SI MEAT'A'BAL" spell_flags = WAIT_FOR_CLICK + spell_aspect_flags = SPELL_FIRE dumbfire = 0 amt_dam_brute = 0 diff --git a/code/modules/spells/targeted/recall.dm b/code/modules/spells/targeted/recall.dm index da15968faa6..3170e9e9bf7 100644 --- a/code/modules/spells/targeted/recall.dm +++ b/code/modules/spells/targeted/recall.dm @@ -42,10 +42,6 @@ /obj/structure/closet/secure_closet/brig, //brig cell closets /obj/machinery/disposal, //disposal bins /obj/machinery/light, //light bulbs and tubes - /obj/machinery/sleep_console, //sleeper consoles - /obj/machinery/sleeper, //sleepers - /obj/machinery/body_scanconsole, //body scanner consoles - /obj/machinery/bodyscanner, //body scanners /obj/machinery/media/receiver/boombox/wallmount, //sound systems /obj/machinery/keycard_auth, //keycard authentication devices ) diff --git a/code/modules/spells/targeted/wrap.dm b/code/modules/spells/targeted/wrap.dm index 23ed7e35597..defd1c27f06 100644 --- a/code/modules/spells/targeted/wrap.dm +++ b/code/modules/spells/targeted/wrap.dm @@ -1,14 +1,14 @@ /spell/targeted/wrapping_paper - name = "" + name = "Wrap Gift" desc = "This spell turns a single person into an inert statue for a long period of time." user_type = USER_TYPE_ARTIFACT school = "transmutation" charge_max = 300 - spell_flags = NEEDSCLOTHES | SELECTABLE + spell_flags = NEEDSCLOTHES | WAIT_FOR_CLICK range = 7 max_targets = 1 - invocation = "You'll make a wonderful gift!" + invocation = "W'APPIN' PR'SN'TS!" invocation_type = SpI_SHOUT amt_stunned = 5//just exists to make sure the giftwrap "catches" them cooldown_min = 30 //100 deciseconds reduction per rank diff --git a/code/modules/store/store.dm b/code/modules/store/store.dm index 9f2bbc97a85..beb9699504a 100644 --- a/code/modules/store/store.dm +++ b/code/modules/store/store.dm @@ -54,12 +54,12 @@ var/global/datum/store/centcomm_store=new D = linked_db.attempt_account_access(card.associated_account_number, 0, 2, 0) using_account = "Bank Account" if(!D) //first we check if there IS a bank account in the first place - to_chat(usr, "[bicon(src)]You don't have that much money on your virtual wallet!") - to_chat(usr, "[bicon(src)]Unable to access your bank account.") + to_chat(usr, "[bicon(merchcomp)]You don't have that much money on your virtual wallet!") + to_chat(usr, "[bicon(merchcomp)]Unable to access your bank account.") return 0 else if(D.security_level > 0) //next we check if the security is low enough to pay directly from it - to_chat(usr, "[bicon(src)]You don't have that much money on your virtual wallet!") - to_chat(usr, "[bicon(src)]Lower your bank account's security settings if you wish to pay directly from it.") + to_chat(usr, "[bicon(merchcomp)]You don't have that much money on your virtual wallet!") + to_chat(usr, "[bicon(merchcomp)]Lower your bank account's security settings if you wish to pay directly from it.") return 0 else if(D.money < amount) //and lastly we check if there's enough money on it, duh to_chat(user, "[bicon(merchcomp)]You don't have that much money on your bank account!") @@ -112,4 +112,4 @@ var/global/datum/store/centcomm_store=new return 0 // Give them the item. item.deliver(usr,merchcomp) - return 1 \ No newline at end of file + return 1 diff --git a/code/modules/supermatter/supermatter.dm b/code/modules/supermatter/supermatter.dm index 48e8e592cb5..9bfe11e47c4 100644 --- a/code/modules/supermatter/supermatter.dm +++ b/code/modules/supermatter/supermatter.dm @@ -356,14 +356,12 @@ "You reach out and touch \the [src]. Everything starts burning and all you can hear is ringing. Your last thought is \"That was not a wise decision.\"",\ "You hear an unearthly noise as a wave of heat washes over you.") - playsound(get_turf(src), 'sound/effects/supermatter.ogg', 50, 1) + playsound(src, 'sound/effects/supermatter.ogg', 50, 1) Consume(user) /obj/machinery/power/supermatter/proc/transfer_energy() - for(var/obj/machinery/power/rad_collector/R in rad_collectors) - if(get_dist(R, src) <= 15) // Better than using orange() every process - R.receive_pulse(power) + emitted_harvestable_radiation(get_turf(src), power, range = 15) /obj/machinery/power/supermatter/attackby(obj/item/weapon/W as obj, mob/living/user as mob) . = ..() @@ -377,7 +375,7 @@ "You touch \the [W] to \the [src] when everything suddenly goes silent.\n\The [W] flashes into dust as you flinch away from \the [src].",\ "Everything suddenly goes silent.") - playsound(get_turf(src), 'sound/effects/supermatter.ogg', 50, 1) + playsound(src, 'sound/effects/supermatter.ogg', 50, 1) user.drop_from_inventory(W) Consume(W) @@ -389,7 +387,7 @@ if(istype(AM, /obj/machinery/power/supermatter)) AM.visible_message("As \the [src] bumps into \the [AM] an otherworldly resonance ringing begins to shake the room, you ponder for a moment all the incorrect choices in your life that led you here, to this very moment, to witness this. You take one final sigh before it all ends.") sleep(10) //Adds to the hilarity - playsound(get_turf(src), 'sound/effects/supermatter.ogg', 50, 1) + playsound(src, 'sound/effects/supermatter.ogg', 50, 1) explode() return if(istype(AM, /mob/living)) @@ -402,7 +400,7 @@ else return ..() - playsound(get_turf(src), 'sound/effects/supermatter.ogg', 50, 1) + playsound(src, 'sound/effects/supermatter.ogg', 50, 1) Consume(AM) diff --git a/code/modules/surgery/butt.dm b/code/modules/surgery/butt.dm index 5d65f9e6930..553f9bb829b 100644 --- a/code/modules/surgery/butt.dm +++ b/code/modules/surgery/butt.dm @@ -160,7 +160,7 @@ user.visible_message("[target] lets out a small fart, which gets set alight with [user]'s [tool]!" , \ "[target] farts into the open flame, burning his anus!" ) target.apply_damage(max(10, tool.force), BURN, LIMB_GROIN) - playsound(get_turf(target), 'sound/effects/holler.ogg', 50, 1) + playsound(target, 'sound/effects/holler.ogg', 50, 1) ////////////////////////////////////////////////////////////////// diff --git a/code/modules/surgery/generic.dm b/code/modules/surgery/generic.dm index ec126029407..d49d67dda3b 100644 --- a/code/modules/surgery/generic.dm +++ b/code/modules/surgery/generic.dm @@ -18,8 +18,6 @@ return 0 if (affected.status & ORGAN_DESTROYED) return 0 - if (affected.status & ORGAN_ROBOT) - return 0 if (affected.status & ORGAN_PEG) return 0 // N3X: Patient must be sleeping, dead, or unconscious. @@ -441,3 +439,52 @@ "Your hand slips, sawing through the bone in [target]'s [affected.display_name] with \the [tool]!") affected.createwound(CUT, 30) affected.fracture() + + + +/////////BIOFOAM INJECTION/////// +/datum/surgery_step/generic/injectfoam/tool_quality(obj/item/tool) + . = ..() + if(!tool.is_sharp()) + return 0 + +/datum/surgery_step/generic/injectfoam + allowed_tools = list( + /obj/item/weapon/FixOVein/clot = 100, + ) + + priority = 0.1 //Tries to inject biofoam before other steps + + min_duration = 10 + max_duration = 20 + +/datum/surgery_step/generic/injectfoam/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + if(..()) + if(target.species && (target.species.anatomy_flags & NO_BLOOD)) + to_chat(user, "[target] has nothing to inject biofoam into!") + return 0 +// var/datum/organ/external/affected = target.get_organ(target_zone) + return 1 //You can inject biofoam at any time. + +/datum/surgery_step/generic/injectfoam/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/datum/organ/external/affected = target.get_organ(target_zone) + user.visible_message("[user] begins to inject [target] with \the [tool]'s biofoam injector." , \ + "You begin to inject [target] with \the [tool]'s biofoam injector.") + target.custom_pain("You feel a tiny prick in your [affected.display_name]!",1) + ..() + +/datum/surgery_step/generic/injectfoam/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/weapon/FixOVein/clot/tool) + var/datum/organ/external/affected = target.get_organ(target_zone) + var/amount = tool.foam + user.visible_message("[user] injects biofoam into [target]'s [affected.display_name] with \the [tool].", \ + "You inject biofoam in [target] with \the [tool].") + target.reagents.add_reagent(BIOFOAM, amount) + playsound(get_turf(target), 'sound/items/hypospray.ogg', 50, 1) + tool.attack_self(user) + tool.foam = 0 + +/datum/surgery_step/generic/injectfoam/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/datum/organ/external/affected = target.get_organ(target_zone) + user.visible_message("[user]'s hand slips, tearing \the [tool]'s needle out of [target]'s [affected.display_name]!", \ + "Your hand slips, tearing \the [tool]'s needle out of [target]'s [affected.display_name]!") + affected.createwound(CUT, 5) diff --git a/code/modules/surgery/headreattach.dm b/code/modules/surgery/headreattach.dm index f4c33127064..53c60882f4f 100644 --- a/code/modules/surgery/headreattach.dm +++ b/code/modules/surgery/headreattach.dm @@ -244,3 +244,38 @@ user.visible_message("[user]'s hand slips, damaging connectors on [target]'s neck!", \ "Your hand slips, damaging connectors on [target]'s neck!") target.apply_damage(10, BRUTE, affected) + + +/datum/surgery_step/head/attach_robot + allowed_tools = list( + /obj/item/robot_parts/head = 100, + ) + + can_infect = 0 + + min_duration = 80 + max_duration = 100 + +/datum/surgery_step/head/attach_robot/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/datum/organ/external/head = target.get_organ(target_zone) + return ..() && head.status & ORGAN_ATTACHABLE + +/datum/surgery_step/head/attach_robot/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + user.visible_message("[user] starts attaching [tool] to [target]'s reshaped neck.", \ + "You start attaching [tool] to [target]'s reshaped neck.") + +/datum/surgery_step/head/attach_robot/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/datum/organ/external/affected = target.get_organ(target_zone) + user.visible_message("[user] has attached \the [tool] to the body.", \ + "You have attached \the [tool] to the bodies reshaped neck.") + affected.attach(tool) + target.decapitated = null + affected.status = 0 + affected.amputated = 0 + affected.destspawn = 0 + +/datum/surgery_step/head/attach_robot/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/datum/organ/external/affected = target.get_organ(target_zone) + user.visible_message("[user]'s hand slips, damaging connectors on [target]'s neck!", \ + "Your hand slips, damaging connectors on [target]'s neck!") + target.apply_damage(10, BRUTE, affected) \ No newline at end of file diff --git a/code/modules/surgery/other.dm b/code/modules/surgery/other.dm index 6cad468b8ad..9d02a424a3a 100644 --- a/code/modules/surgery/other.dm +++ b/code/modules/surgery/other.dm @@ -52,7 +52,7 @@ /datum/surgery_step/fix_vein/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/datum/organ/external/affected = target.get_organ(target_zone) user.visible_message("[user]'s hand slips, smearing [tool] in the incision in [target]'s [affected.display_name]!" , \ - "Your hand slips, smearing [tool] in the incision in [target]'s [affected.display_name]!") + "Your hand slips, smearing \the [tool] in the incision in [target]'s [affected.display_name]!") affected.take_damage(5, 0) diff --git a/code/modules/surgery/surgery.dm b/code/modules/surgery/surgery.dm index d9d50a1f104..5809755512f 100644 --- a/code/modules/surgery/surgery.dm +++ b/code/modules/surgery/surgery.dm @@ -97,7 +97,7 @@ proc/spread_germs_to_organ(datum/organ/external/E, mob/living/carbon/human/user) E.germ_level = max(germ_level,E.germ_level) //as funny as scrubbing microbes out with clean gloves is - no. proc/do_surgery(mob/living/M, mob/living/user, obj/item/tool) - if(!istype(M,/mob/living/carbon/human)) + if(!ishuman(M) && !isslime(M)) return 0 if (user.a_intent == I_HURT) //check for Hippocratic Oath return 0 @@ -106,11 +106,14 @@ proc/do_surgery(mob/living/M, mob/living/user, obj/item/tool) if(ishuman(user)) var/mob/living/carbon/human/H = user clumsy = ((M_CLUMSY in H.mutations) && prob(50)) + + var/target_area = user.zone_sel ? user.zone_sel.selecting : get_random_zone_sel() + for(var/datum/surgery_step/S in surgery_steps) //check if tool is right or close enough and if this step is possible sleep_fail = 0 if(S.tool_quality(tool)) - var/canuse = S.can_use(user, M, user.zone_sel.selecting, tool) + var/canuse = S.can_use(user, M, target_area, tool) if(canuse == -1) sleep_fail = 1 if(canuse && S.is_valid_mutantrace(M) && !(M in S.doing_surgery)) @@ -120,14 +123,15 @@ proc/do_surgery(mob/living/M, mob/living/user, obj/item/tool) user.attack_log += text("\[[time_stamp()]\] Started surgery [S.type] with \the [tool] on [M.name] ([M.ckey])") log_attack("[user.name] ([user.ckey]) used \the [tool] to perform surgery type [S.type] on [M.name] ([M.ckey])") S.doing_surgery += M - S.begin_step(user, M, user.zone_sel.selecting, tool) //start on it - var/selection = user.zone_sel.selecting + S.begin_step(user, M, target_area, tool) //start on it + + var/selection = user.zone_sel ? user.zone_sel.selecting : null //Check if the zone selection hasn't changed //We had proper tools! (or RNG smiled.) and user did not move or change hands. - if(do_mob(user, M, rand(S.min_duration, S.max_duration) * tool.surgery_speed) && (prob(S.tool_quality(tool) / (sleep_fail + clumsy + 1))) && selection == user.zone_sel.selecting) + if(do_mob(user, M, rand(S.min_duration, S.max_duration) * tool.surgery_speed) && (prob(S.tool_quality(tool) / (sleep_fail + clumsy + 1))) && (!user.zone_sel || selection == user.zone_sel.selecting)) //Last part checks whether the zone selection hasn't changed M.attack_log += text("\[[time_stamp()]\] Has had surgery [S.type] with \the [tool] successfully completed by [user.name] ([user.ckey])") user.attack_log += text("\[[time_stamp()]\] Successfully completed surgery [S.type] with \the [tool] on [M.name] ([M.ckey])") log_attack("[user.name] ([user.ckey]) used \the [tool] to successfully complete surgery type [S.type] on [M.name] ([M.ckey])") - S.end_step(user, M, user.zone_sel.selecting, tool) //finish successfully + S.end_step(user, M, target_area, tool) //finish successfully else if(sleep_fail) to_chat(user, "The patient is squirming around in pain!") @@ -135,7 +139,7 @@ proc/do_surgery(mob/living/M, mob/living/user, obj/item/tool) M.attack_log += text("\[[time_stamp()]\] Has had surgery [S.type] with \the [tool] failed by [user.name] ([user.ckey])") user.attack_log += text("\[[time_stamp()]\] Failed surgery [S.type] with \the [tool] on [M.name] ([M.ckey])") log_attack("[user.name] ([user.ckey]) used \the [tool] to fail the surgery type [S.type] on [M.name] ([M.ckey])") - S.fail_step(user, M, user.zone_sel.selecting, tool) //malpractice~ + S.fail_step(user, M, target_area, tool) //malpractice~ if(M) //good, we still exist S.doing_surgery -= M else diff --git a/code/modules/telesci/gps.dm b/code/modules/telesci/gps.dm index 2fcae72119f..63fdf169fda 100644 --- a/code/modules/telesci/gps.dm +++ b/code/modules/telesci/gps.dm @@ -15,12 +15,13 @@ var/list/SPS_list = list() var/gpstag = "COM0" var/emped = FALSE var/autorefreshing = FALSE + var/builtin = FALSE /obj/item/device/gps/proc/gen_id() return GPS_list.len /obj/item/device/gps/proc/get_list() - return GPS_list.Copy() + return GPS_list /obj/item/device/gps/proc/update_name() name = "[base_name] ([gpstag])" @@ -43,11 +44,11 @@ var/list/SPS_list = list() ..() /obj/item/device/gps/emp_act(severity) - emped = 1 + emped = TRUE overlays -= image(icon = icon, icon_state = "working") overlays += image(icon = icon, icon_state = "emp") spawn(30 SECONDS) - emped = 0 + emped = FALSE overlays -= image(icon = icon, icon_state = "emp") overlays += image(icon = icon, icon_state = "working") @@ -55,11 +56,24 @@ var/list/SPS_list = list() ui_interact(user) /obj/item/device/gps/examine(mob/user) - if (Adjacent(user) || isobserver(user)) - src.attack_self(user) + if(Adjacent(user) || isobserver(user)) + attack_self(user) else ..() +/obj/item/device/gps/proc/get_location_name() + var/turf/device_turf = get_turf(src) + var/area/device_area = get_area(src) + if(emped) + return "ERROR" + else if(!device_turf || !device_area) + return "UNKNOWN" + else if(device_turf.z > WORLD_X_OFFSET.len) + return "[format_text(device_area.name)] (UNKNOWN, UNKNOWN, UNKNOWN)" + else + return "[format_text(device_area.name)] ([device_turf.x-WORLD_X_OFFSET[device_turf.z]], [device_turf.y-WORLD_Y_OFFSET[device_turf.z]], [device_turf.z])" + + /obj/item/device/gps/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open=NANOUI_FOCUS) var/data[0] if(emped) @@ -67,31 +81,15 @@ var/list/SPS_list = list() else data["gpstag"] = gpstag data["autorefresh"] = autorefreshing + data["location_text"] = get_location_name() var/list/devices = list() for(var/D in get_list()) - var/device_data[0] - var/turf/device_turf = get_turf(D) - var/area/device_area = get_area(D) - var/device_tag = null - var/device_rip = null - if(ispAI(D)) - var/mob/living/silicon/pai/P = D - device_tag = P.ppstag - device_rip = P.silence_time - else - var/obj/item/device/gps/G = D - device_tag = G.gpstag - device_rip = G.emped - device_data["tag"] = device_tag - if(device_rip) - device_data["location_text"] = "ERROR" - else if(!device_turf || !device_area) - device_data["location_text"] = "UNKNOWN" - else if(device_turf.z > WORLD_X_OFFSET.len) - device_data["location_text"] = "[format_text(device_area.name)] (UNKNOWN, UNKNOWN, UNKNOWN)" - else - device_data["location_text"] = "[format_text(device_area.name)] ([device_turf.x-WORLD_X_OFFSET[device_turf.z]], [device_turf.y-WORLD_Y_OFFSET[device_turf.z]], [device_turf.z])" - devices += list(device_data) + var/obj/item/device/gps/G = D + if(src != G) + var/device_data[0] + device_data["tag"] = G.gpstag + device_data["location_text"] = G.get_location_name() + devices += list(device_data) data["devices"] = devices ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) @@ -102,34 +100,34 @@ var/list/SPS_list = list() ui.set_auto_update(autorefreshing) /obj/item/device/gps/Topic(href, href_list) - if(..()) - return 0 - if(href_list["tag"]) - if (isobserver(usr)) + if(isobserver(usr)) to_chat(usr, "No way.") - return 0 - if (usr.get_active_hand() != src || usr.stat) //no silicons allowed + return FALSE + if(!builtin && (usr.get_active_hand() != src || usr.incapacitated())) //no silicons allowed to_chat(usr, "You need to have the GPS in your hand to do that!") - return 1 + return TRUE var/a = input("Please enter desired tag.", name, gpstag) as text|null - if (!a) //what a check - return 1 + if(!a) //what a check + return TRUE - if (usr.get_active_hand() != src || usr.stat) //second check in case some chucklefuck drops the GPS while typing the tag + if(!builtin && (usr.get_active_hand() != src || usr.incapacitated())) //second check in case some chucklefuck drops the GPS while typing the tag to_chat(usr, "The GPS needs to be kept in your active hand!") - return 1 + return TRUE a = strict_ascii(a) if(length(a) < 4 || length(a) > 5) to_chat(usr, "The tag must be between four and five characters long!") else gpstag = a update_name() - return 1 + return TRUE if(href_list["toggle_refresh"]) autorefreshing = !autorefreshing - return 1 + return TRUE + + if(..()) + return FALSE /obj/item/device/gps/science icon_state = "gps-s" @@ -148,6 +146,18 @@ var/list/SPS_list = list() icon_state = "gps-m" base_tag = "MIN" +/obj/item/device/gps/cyborg + desc = "A mining cyborg internal positioning system. Used as a recovery beacon for damaged silicons, or a collaboration tool for mining teams." + icon_state = "gps-b" + base_tag = "BORG" + builtin = TRUE + +/obj/item/device/gps/pai + base_name = "pAI positioning system" + icon_state = "gps-b" + base_tag = "PAI" + builtin = TRUE + /obj/item/device/gps/secure base_name = "secure positioning system" desc = "A secure channel SPS. It announces the position of the wearer if killed or stripped off." @@ -161,7 +171,7 @@ var/list/SPS_list = list() return SPS_list.len /obj/item/device/gps/secure/get_list() - return SPS_list.Copy() + return SPS_list /obj/item/device/gps/secure/OnMobDeath(mob/wearer) if(emped) @@ -169,21 +179,73 @@ var/list/SPS_list = list() for(var/E in SPS_list) var/obj/item/device/gps/secure/S = E //No idea why casting it like this makes it work better instead of just defining it in the for each - S.announce(wearer, src, "has detected the death of their wearer") + S.announce(wearer, src, "has detected the death of their wearer",dead=TRUE) /obj/item/device/gps/secure/stripped(mob/wearer) if(emped) return . = ..() - + var/num = 0 for(var/E in SPS_list) var/obj/item/device/gps/secure/S = E - S.announce(wearer, src, "has been stripped from their wearer") + S.announce(wearer, src, "has been stripped from their wearer",num) + num++ -/obj/item/device/gps/secure/proc/announce(var/mob/wearer, var/obj/item/device/gps/secure/SPS, var/reason) +var/list/deathsound = list('sound/items/die1.wav', 'sound/items/die2.wav', 'sound/items/die3.wav','sound/items/die4.wav') + +/obj/item/device/gps/secure/proc/announce(var/mob/wearer, var/obj/item/device/gps/secure/SPS, var/reason,var/num,var/dead=FALSE) var/turf/pos = get_turf(SPS) + deathsound(pos,dead,num) var/mob/living/L = get_holder_of_type(src, /mob/living/) if(L) L.show_message("\icon[src] [gpstag] beeps: Warning! SPS '[SPS.gpstag]' [reason] at [get_area(SPS)] ([pos.x-WORLD_X_OFFSET[pos.z]], [pos.y-WORLD_Y_OFFSET[pos.z]], [pos.z]).", MESSAGE_HEAR) - else if(isturf(src.loc)) - src.visible_message("\icon[src] [gpstag] beeps: Warning! SPS '[SPS.gpstag]' [reason] at [get_area(SPS)] ([pos.x-WORLD_X_OFFSET[pos.z]], [pos.y-WORLD_Y_OFFSET[pos.z]], [pos.z]).") + else if(isturf(loc)) + visible_message("\icon[src] [gpstag] beeps: Warning! SPS '[SPS.gpstag]' [reason] at [get_area(SPS)] ([pos.x-WORLD_X_OFFSET[pos.z]], [pos.y-WORLD_Y_OFFSET[pos.z]], [pos.z]).") + + +var/const/DEATHSOUND_CHANNEL = 300 + +/obj/item/device/gps/secure/proc/deathsound(var/turf/pos,var/dead=FALSE,num) + var/sound_channel = DEATHSOUND_CHANNEL + num + if(dead) + playsound(src, pick(deathsound), 100, 0,channel = sound_channel,wait = TRUE) + if(prob(75)) + playsound(src, 'sound/items/on3.wav',100, 0,channel = sound_channel,wait = TRUE) + playsound(src, 'sound/items/_comma.wav',100, 0,channel = sound_channel,wait = TRUE) + if(prob(50)) + playsound(src, 'sound/items/attention.wav',100, 0,channel = sound_channel,wait = TRUE) + playsound(src, 'sound/items/_comma.wav',100, 0,channel = sound_channel,wait = TRUE) + if(prob(25) && dead) // 25% chance if dead, 0% chance if stripped + playsound(src, 'sound/items/unitdeserviced.wav',100, 0,channel = sound_channel,wait = TRUE) + playsound(src, 'sound/items/_comma.wav',100, 0,channel = sound_channel,wait = TRUE) + else if(prob(33) && dead) // 25% chance if dead, 0% chance if stripped + playsound(src, 'sound/items/unitdownat.wav',100, 0,channel = sound_channel,wait = TRUE) + playnum(pos.x-WORLD_X_OFFSET[pos.z],pos,sound_channel,src) + playsound(src, 'sound/items/_comma.wav',100, 0,channel = sound_channel,wait = TRUE) + playnum(pos.y-WORLD_Y_OFFSET[pos.z],pos,sound_channel,src) + playsound(src, 'sound/items/_comma.wav',100, 0,channel = sound_channel,wait = TRUE) + playnum(pos.z,pos,sound_channel,src) + playsound(src, 'sound/items/_comma.wav',100, 0,channel = sound_channel,wait = TRUE) + else if(prob(50)) // 25% chance if dead, 50% chance if stripped + playsound(src, 'sound/items/lostbiosignalforunit.wav',100, 0,channel = sound_channel,wait = TRUE) + playsound(src, 'sound/items/_comma.wav',100, 0,channel = sound_channel,wait = TRUE) + playnum(num,pos,sound_channel,src) + playsound(src, 'sound/items/_comma.wav',100, 0,channel = sound_channel,wait = TRUE) + else // 25% chance if dead, 50% chance if stripped + playsound(src, 'sound/items/allteamsrespondcode3.wav',100, 0,channel = sound_channel,wait = TRUE) + playsound(src, 'sound/items/_comma.wav',100, 0,channel = sound_channel,wait = TRUE) + if(prob(50)) + playsound(src, 'sound/items/investigateandreport.wav',100, 0,channel = sound_channel,wait = TRUE) + playsound(src, 'sound/items/_comma.wav',100, 0,channel = sound_channel,wait = TRUE) + playsound(src, 'sound/items/off2.wav',100, 0,channel = sound_channel,wait = TRUE) + + +var/list/nums_to_hl_num = list("1" = 'sound/items/one.wav', "2" = 'sound/items/two.wav', "3" = 'sound/items/three.wav',"4" = 'sound/items/four.wav',"5" = 'sound/items/five.wav',"6" = 'sound/items/six.wav',"7" = 'sound/items/seven.wav',"8" = 'sound/items/eight.wav',"9" = 'sound/items/nine.wav',"0" = 'sound/items/zero.wav') +/proc/playnum(var/num,var/sound_channel,var/source) + var/list/splitnumber = list() + if(num) + var/base = round(log(10,num)) + for(var/n = 0 to base) + splitnumber += num/(10**(base-n)) % 10 + else splitnumber += "0" + for(var/n in splitnumber) diff --git a/code/modules/telesci/rcs.dm b/code/modules/telesci/rcs.dm index 2282af51b10..fd6fb2c410f 100644 --- a/code/modules/telesci/rcs.dm +++ b/code/modules/telesci/rcs.dm @@ -98,7 +98,7 @@ /obj/item/weapon/rcs/attack_self(mob/user) if(emagged) mode = !mode - playsound(get_turf(src), 'sound/effects/pop.ogg', 50, 0) + playsound(src, 'sound/effects/pop.ogg', 50, 0) if(mode == MODE_NORMAL) to_chat(user, "You calibrate the telepad locator.") else @@ -150,7 +150,7 @@ else if (mode == MODE_RANDOM) teleport_target = locate(rand(50, 450), rand(50, 450), 6) - playsound(get_turf(src), 'sound/machines/click.ogg', 50, 1) + playsound(src, 'sound/machines/click.ogg', 50, 1) to_chat(user, "Teleporting \the [target]...") teleporting = TRUE if (!do_after(user, target, 50)) diff --git a/code/modules/unit_tests/_unit_tests.dm b/code/modules/unit_tests/_unit_tests.dm new file mode 100644 index 00000000000..0e9a4cb443a --- /dev/null +++ b/code/modules/unit_tests/_unit_tests.dm @@ -0,0 +1,5 @@ +#ifdef UNIT_TESTS +#include "unit_test.dm" +#include "dna_and_disabilities.dm" +#include "reagent_recipe_collisions.dm" +#endif diff --git a/code/modules/unit_tests/dna_and_disabilities.dm b/code/modules/unit_tests/dna_and_disabilities.dm new file mode 100644 index 00000000000..f49840f8ea3 --- /dev/null +++ b/code/modules/unit_tests/dna_and_disabilities.dm @@ -0,0 +1,10 @@ +/datum/unit_test/dna_and_disabilities + +/datum/unit_test/dna_and_disabilities/start() + for(var/disability_type in subtypesof(/datum/dna/gene/disability)) + var/datum/dna/gene/disability/instance = new disability_type + + if(!instance.activation_message) + fail("[disability_type] does not specify an activation message.") + if(!instance.deactivation_message) + fail("[disability_type] does not specify a deactivation message.") diff --git a/code/modules/unit_tests/reagent_recipe_collisions.dm b/code/modules/unit_tests/reagent_recipe_collisions.dm new file mode 100644 index 00000000000..edb08f049aa --- /dev/null +++ b/code/modules/unit_tests/reagent_recipe_collisions.dm @@ -0,0 +1,67 @@ +/datum/unit_test/reagent_recipe_collisions + +/datum/unit_test/reagent_recipe_collisions/start() + var/datum/reagents/r = new // Builds chemical_reactions_list + qdel(r) + r = null + var/list/reactions = list() + for(var/V in global.chemical_reactions_list) + reactions += global.chemical_reactions_list[V] + for(var/i in 1 to (reactions.len-1)) + for(var/i2 in (i+1) to reactions.len) + var/datum/chemical_reaction/r1 = reactions[i] + var/datum/chemical_reaction/r2 = reactions[i2] + if(recipes_do_conflict(r1, r2)) + fail("Chemical recipe conflict between [r1.type] and [r2.type]") + +/datum/unit_test/reagent_recipe_collisions/proc/recipes_do_conflict(datum/chemical_reaction/r1, datum/chemical_reaction/r2) + //do the non-list tests first, because they are cheaper + if(r1.required_container != r2.required_container) + return FALSE + if(r1.is_cold_recipe == r2.is_cold_recipe) + if(r1.required_temp != r2.required_temp) + //one reaction requires a more extreme temperature than the other, so there is no conflict + return FALSE + else + var/datum/chemical_reaction/cold_one = r1.is_cold_recipe ? r1 : r2 + var/datum/chemical_reaction/warm_one = r1.is_cold_recipe ? r2 : r1 + if(warm_one.required_temp == 0 || cold_one.required_temp < warm_one.required_temp) + // the warm reaction doesn't require any particular temperature or the range of temperatures does not overlap, so there is no conflict + return FALSE + + //find the reactions with the shorter and longer required_reagents list + var/datum/chemical_reaction/long_req + var/datum/chemical_reaction/short_req + if(r1.required_reagents.len > r2.required_reagents.len) + long_req = r1 + short_req = r2 + else if(r1.required_reagents.len < r2.required_reagents.len) + long_req = r2 + short_req = r1 + else + //if they are the same length, sort instead by the length of the catalyst list + //this is important if the required_reagents lists are the same + if(r1.required_catalysts.len > r2.required_catalysts.len) + long_req = r1 + short_req = r2 + else + long_req = r2 + short_req = r1 + + + //check if the shorter reaction list is a subset of the longer one + var/list/overlap = r1.required_reagents & r2.required_reagents + if(overlap.len != short_req.required_reagents.len) + //there is at least one reagent in the short list that is not in the long list, so there is no conflict + return FALSE + + //check to see if the shorter reaction's catalyst list is also a subset of the longer reaction's catalyst list + //if the longer reaction's catalyst list is a subset of the shorter ones, that is fine + //if the reaction lists are the same, the short reaction will have the shorter required_catalysts list, so it will register as a conflict + var/list/short_minus_long_catalysts = short_req.required_catalysts - long_req.required_catalysts + if(short_minus_long_catalysts.len) + //there is at least one unique catalyst for the short reaction, so there is no conflict + return FALSE + + //if we got this far, the longer reaction will be impossible to create if the shorter one is earlier in global.chemical_reactions_list, and will require the reagents to be added in a particular order otherwise + return TRUE diff --git a/code/modules/unit_tests/unit_test.dm b/code/modules/unit_tests/unit_test.dm new file mode 100644 index 00000000000..b3539c68839 --- /dev/null +++ b/code/modules/unit_tests/unit_test.dm @@ -0,0 +1,72 @@ +/* +Usage: + Override /run() to run your test code. + Call fail() to fail the test (You should specify a reason). + Use /New() and Destroy() for setup/teardown, respectively. + You can use the run_loc_bottom_left and run_loc_top_right if your tests require turfs. +*/ + +var/datum/unit_test/current_test +var/failed_any_test = FALSE + +/datum/unit_test + var/list/procs_tested + + //usable vars + var/turf/run_loc_bottom_left + var/turf/run_loc_top_right + + //internal vars + var/succeeded = TRUE + var/list/fail_reasons + +/datum/unit_test/New() + run_loc_bottom_left = locate(1, 1, 1) + run_loc_top_right = locate(5, 5, 1) + +/datum/unit_test/Destroy() + //clear the test area + for(var/atom/movable/AM in block(run_loc_bottom_left, run_loc_top_right)) + qdel(AM) + ..() + +/datum/unit_test/proc/start() + fail("run() called parent or not implemented") + +/datum/unit_test/proc/fail(var/reason = "No reason provided") + succeeded = FALSE + + if(!istext(reason)) + reason = "FORMATTED: [isnull(reason) ? "NULL" : "reason"]" + + if(!fail_reasons) + fail_reasons = list() + fail_reasons.Add(reason) + +/proc/run_unit_tests() + CHECK_TICK + + for(var/I in subtypesof(/datum/unit_test)) + var/datum/unit_test/test = new I + + global.current_test = test + var/duration = world.timeofday + + test.start() + + duration = world.timeofday - duration + global.current_test = null + global.failed_any_test |= !test.succeeded + + var/list/log_entry = list("UNIT TEST [test.succeeded ? "PASS" : "FAIL"]: [I] [duration / 10]s") + var/list/fail_reasons = test.fail_reasons + + qdel(test) + + for(var/J in 1 to length(fail_reasons)) + log_entry.Add("\tREASON #[J]: [fail_reasons[J]]") + world.log << log_entry.Join("\n") + + CHECK_TICK + + del(world) diff --git a/code/modules/virus2/analyser.dm b/code/modules/virus2/analyser.dm index 5597412563d..026409ba8e0 100644 --- a/code/modules/virus2/analyser.dm +++ b/code/modules/virus2/analyser.dm @@ -109,16 +109,16 @@ usr.set_machine(src) if(href_list["eject"]) - for(var/obj/item/weapon/virusdish/O in src.contents) - if("[O.virus2.uniqueID]" == href_list["name"]) - O.forceMove(src.loc) - if(toscan["O"]) - toscan -= O + var/obj/item/weapon/virusdish/O = locate(href_list["dishI"]) + if(O && O in contents) + O.forceMove(loc) + if(O in toscan) + toscan -= O src.updateUsrDialog() else if(href_list["print"]) - for(var/obj/item/weapon/virusdish/O in src.contents) - if("[O.virus2.uniqueID]" == href_list["name"]) - PrintPaper(O) + var/obj/item/weapon/virusdish/O = locate(href_list["dishI"]) + if(O && O in contents) + PrintPaper(O) /obj/machinery/disease2/diseaseanalyser/attack_hand(var/mob/user as mob) . = ..() @@ -148,8 +148,8 @@ if(B == dish) dat += "" else - dat += "Eject" - dat += "
      [B.analysed ? "Print" : ""]" + dat += "Eject" + dat += "
      [B.analysed ? "Print" : ""]" dat += "" dat += "" dat = jointext(dat,"") diff --git a/code/modules/virus2/centrifuge.dm b/code/modules/virus2/centrifuge.dm index 7685b91eed3..024e90d289a 100644 --- a/code/modules/virus2/centrifuge.dm +++ b/code/modules/virus2/centrifuge.dm @@ -162,7 +162,7 @@ else curing = delay - playsound(get_turf(src), 'sound/machines/juicer.ogg', 50, 1) + playsound(src, 'sound/machines/juicer.ogg', 50, 1) update_icon() if("isolate") diff --git a/code/modules/virus2/effect/effect.dm b/code/modules/virus2/effect/effect.dm index 0cf6664389b..be026290e37 100644 --- a/code/modules/virus2/effect/effect.dm +++ b/code/modules/virus2/effect/effect.dm @@ -417,7 +417,7 @@ to_chat(H, "Your [glass_hand.display_name] resonates with the glass in \the [glass_to_shatter], shattering it to bits!") glass_to_shatter.reagents.reaction(H.loc, TOUCH) new/obj/effect/decal/cleanable/generic(get_turf(H)) - playsound(get_turf(H), 'sound/effects/Glassbr1.ogg', 25, 1) + playsound(H, 'sound/effects/Glassbr1.ogg', 25, 1) spawn(1 SECONDS) if (H && glass_hand) if (prob(50 * multiplier)) @@ -559,6 +559,44 @@ mob.dna.SetSEState(VEGANBLOCK,1) domutcheck(mob, null) +/datum/disease2/effect/famine + name = "Faminous Potation" + stage = 2 + max_multiplier = 3 + +/datum/disease2/effect/famine/activate(var/mob/living/carbon/mob) + if(ishuman(mob)) + var/mob/living/carbon/human/H = mob + if(H.dna) + if(H.species.flags & IS_PLANT) //Plantmen take a LOT of damage + H.adjustCloneLoss(5 * multiplier) + + for(var/obj/machinery/portable_atmospherics/hydroponics/H in range(3*multiplier,mob)) + if(H.seed && !H.dead) // Get your xenobotanist/vox trader/hydroponist mad with you in less than 1 minute with this simple trick. + switch(rand(1,3)) + if(1) + if(H.waterlevel >= 10) + H.waterlevel -= rand(1,10) + if(H.nutrilevel >= 5) + H.nutrilevel -= rand(1,5) + if(2) + if(H.toxins <= 50) + H.toxins += rand(1,50) + if(3) + H.weed_coefficient++ + H.weedlevel++ + H.pestlevel++ + if(prob(5)) + H.dead = 1 + + + for(var/obj/item/weapon/reagent_containers/food/snacks/grown/G in range(2*multiplier,mob)) + G.visible_message("\The [G] rots at an alarming rate!") + new /obj/item/weapon/reagent_containers/food/snacks/badrecipe(get_turf(G)) + qdel(G) + if(prob(30/multiplier)) + break + ////////////////////////STAGE 3///////////////////////////////// diff --git a/code/modules/virus2/helpers.dm b/code/modules/virus2/helpers.dm index d323fc8f8b9..91e07523a5c 100644 --- a/code/modules/virus2/helpers.dm +++ b/code/modules/virus2/helpers.dm @@ -32,8 +32,8 @@ proc/get_infection_chance(var/mob/living/M, var/vector = "Airborne") if(MM.disease_carrier) return 1 - if(istype(M, /mob/living/carbon/martian)) //Martians are incredibly susceptible to viruses - var/mob/living/carbon/martian/MR = M + if(istype(M, /mob/living/carbon/complex/martian)) //Martians are incredibly susceptible to viruses + var/mob/living/carbon/complex/martian/MR = M if (vector == "Airborne") if(MR.head && istype(MR.head, /obj/item/clothing/head/helmet/space/martian)) score += 40 diff --git a/code/modules/virus2/isolator.dm b/code/modules/virus2/isolator.dm index 22e8cb6dbe9..1754e2773b7 100644 --- a/code/modules/virus2/isolator.dm +++ b/code/modules/virus2/isolator.dm @@ -43,7 +43,7 @@ // /vg/: Try to fix isolators if(!Blood) to_chat(usr, "ERROR: Unable to locate blood within the beaker. Bug?") - testing("Unable to locate blood in [beaker]!") +// testing("Unable to locate blood in [beaker]!") return var/list/virus = virus_copylist(Blood.data["virus2"]) var/choice = text2num(href_list["isolate"]) diff --git a/code/world.dm b/code/world.dm index dc5228ad3a3..576fc85f88e 100644 --- a/code/world.dm +++ b/code/world.dm @@ -142,18 +142,12 @@ var/savefile/panicfile src.update_status() - sleep_offline = 1 + sleep_offline = 0 send2mainirc("Server starting up on [config.server? "byond://[config.server]" : "byond://[world.address]:[world.port]"]") send2maindiscord("**Server starting up** on `[config.server? "byond://[config.server]" : "byond://[world.address]:[world.port]"]`. Map is **[map.nameLong]**") - spawn(10) - Master.Setup() - - for(var/plugin_type in typesof(/plugin)) - var/plugin/P = new plugin_type() - plugins[P.name] = P - P.on_world_loaded() + Master.Setup() process_teleport_locs() //Sets up the wizard teleport locations process_ghost_teleport_locs() //Sets up ghost teleport locations. @@ -167,7 +161,6 @@ var/savefile/panicfile KickInactiveClients()*/ #undef RECOMMENDED_VERSION - return ..() //world/Topic(href, href_list[]) diff --git a/goon/browserassets/css/browserOutput.css b/goon/browserassets/css/browserOutput.css index 458b39f2960..42deb52313e 100644 --- a/goon/browserassets/css/browserOutput.css +++ b/goon/browserassets/css/browserOutput.css @@ -28,6 +28,25 @@ img.icon { width: 16px; height: 16px; } + +.repeat:before { /* "repeated" badge class for combined messages */ + content: 'x'; +} + +.repeat { + display: inline-block; + min-width: 1em; + font-size: 0.7em; + padding: 0.3em; + line-height: 1; + color: white; + text-align: center; + white-space: nowrap; + vertical-align: middle; + background-color: crimson; + border-radius: 12px; +} + a {color: #0000ff;} a:visited {color: #ff00ff;} a.popt {text-decoration: none;} @@ -173,30 +192,6 @@ a.popt {text-decoration: none;} .highlightPopup input.highlightColor {background-color: #FFFF00;} .highlightPopup input.highlightTermSubmit {margin-top: 5px;} -/* ADMIN CONTEXT MENU */ -.contextMenu { - background-color: #ddd; - position: fixed; - margin: 2px; - width: 150px; -} -.contextMenu a { - display: block; - padding: 2px 5px; - text-decoration: none; - color: #333; -} - -.contextMenu a:hover { - background-color: #ccc; -} - -/* ADMIN FILTER MESSAGES MENU */ -.filterMessages {padding: 5px;} -.filterMessages div {padding: 2px 0;} -.filterMessages input {} -.filterMessages label {} - .icon-stack {height: 1em; line-height: 1em; width: 1em; vertical-align: middle; margin-top: -2px;} @@ -307,6 +302,7 @@ h1.alert, h2.alert {color: #000000;} .good {color: green;} .average {color: #FF8000;} .bad {color: #FF0000;} +.mushroom {color: #4B0082;} /* /vg/ Saycode Rewrite */ .italics, .talkinto {font-style:italic;} .whisper {font-style:italic;color:#333333;} diff --git a/goon/browserassets/html/browserOutput.html b/goon/browserassets/html/browserOutput.html index af9fd7634e6..89162ab9bf3 100644 --- a/goon/browserassets/html/browserOutput.html +++ b/goon/browserassets/html/browserOutput.html @@ -36,6 +36,7 @@ Toggle ping display Highlight string Save chat log + Toggle line combining Clear all messages Change color preset diff --git a/goon/browserassets/js/browserOutput.js b/goon/browserassets/js/browserOutput.js index f7b95a3ba68..3f6a1e5d30e 100644 --- a/goon/browserassets/js/browserOutput.js +++ b/goon/browserassets/js/browserOutput.js @@ -20,7 +20,7 @@ window.onerror = function(msg, url, line, col, error) { //Globals window.status = 'Output'; -var $messages, $subOptions, $contextMenu, $filterMessages; +var $messages, $subOptions, $last_message; var opts = { //General 'messageCount': 0, //A count...of messages... @@ -54,9 +54,6 @@ var opts = { 'mouseDownY': null, 'preventFocus': false, //Prevents switching focus to the game window - //Admin stuff - 'adminLoaded': false, //Has the admin loaded his shit? - //Client Connection Data 'clientDataLimit': 5, 'clientData': [], @@ -65,7 +62,10 @@ var opts = { 'macros': {}, // index in the color presets list. - 'colorPreset': 0 + 'colorPreset': 0, + + // Whether to combine consecutive repeated messages into one, showing a counter + 'messageCombining': true }; // Array of names for colorblind presets. @@ -181,86 +181,30 @@ function output(message, flag) { message = message.replace(/\+/g, "%20") message = decoder(message) - //The behemoth of filter-code (for Admin message filters) - //Note: This is proooobably hella inefficient - var filteredOut = false; - if (opts.hasOwnProperty('showMessagesFilters') && !opts.showMessagesFilters['All'].show) { - //Get this filter type (defined by class on message) - var messageHtml = $.parseHTML(message), - messageClasses; - if (opts.hasOwnProperty('filterHideAll') && opts.filterHideAll) { - var internal = false; - messageClasses = (!!$(messageHtml).attr('class') ? $(messageHtml).attr('class').split(/\s+/) : false); - if (messageClasses) { - for (var i = 0; i < messageClasses.length; i++) { //Every class - if (messageClasses[i] == 'internal') { - internal = true; - break; - } - } - } - if (!internal) { - filteredOut = 'All'; - } - } else { - //If the element or it's child have any classes - if (!!$(messageHtml).attr('class') || !!$(messageHtml).children().attr('class')) { - messageClasses = $(messageHtml).attr('class').split(/\s+/); - if (!!$(messageHtml).children().attr('class')) { - messageClasses = messageClasses.concat($(messageHtml).children().attr('class').split(/\s+/)); - } - var tempCount = 0; - for (var i = 0; i < messageClasses.length; i++) { //Every class - var thisClass = messageClasses[i]; - $.each(opts.showMessagesFilters, function(key, val) { //Every filter - if (key !== 'All' && val.show === false && typeof val.match != 'undefined') { - for (var i = 0; i < val.match.length; i++) { - var matchClass = val.match[i]; - if (matchClass == thisClass) { - filteredOut = key; - break; - } - } - } - if (filteredOut) return false; - }); - if (filteredOut) break; - tempCount++; - } - } else { - if (!opts.showMessagesFilters['Misc'].show) { - filteredOut = 'Misc'; - } - } - } - } - //Stuff we do along with appending a message var atBottom = false; - if (!filteredOut) { - var bodyHeight = $('body').height(); - var messagesHeight = $messages.outerHeight(); - var scrollPos = $('body,html').scrollTop(); + var bodyHeight = $('body').height(); + var messagesHeight = $messages.outerHeight(); + var scrollPos = $('body,html').scrollTop(); - //Should we snap the output to the bottom? - if (bodyHeight + scrollPos >= messagesHeight - opts.scrollSnapTolerance) { - atBottom = true; - if ($('#newMessages').length) { - $('#newMessages').remove(); + //Should we snap the output to the bottom? + if (bodyHeight + scrollPos >= messagesHeight - opts.scrollSnapTolerance) { + atBottom = true; + if ($('#newMessages').length) { + $('#newMessages').remove(); + } + //If not, put the new messages box in + } else { + if ($('#newMessages').length) { + var messages = $('#newMessages .number').text(); + messages = parseInt(messages); + messages++; + $('#newMessages .number').text(messages); + if (messages == 2) { + $('#newMessages .messageWord').append('s'); } - //If not, put the new messages box in } else { - if ($('#newMessages').length) { - var messages = $('#newMessages .number').text(); - messages = parseInt(messages); - messages++; - $('#newMessages .number').text(messages); - if (messages == 2) { - $('#newMessages .messageWord').append('s'); - } - } else { - $messages.after('1 new message '); - } + $messages.after('1 new message '); } } @@ -277,27 +221,54 @@ function output(message, flag) { opts.messageCount--; //I guess the count should only ever equal the limit } - //Actually append the message - var entry = document.createElement('div'); - entry.className = 'entry'; - - if (filteredOut) { - entry.className += ' hidden'; - entry.setAttribute('data-filter', filteredOut); + var handled = false; + var trimmed_message = message.trim(); + var lastmessages = $messages.children('div.entry:last-child'); + if(opts.messageCombining && lastmessages.length && $last_message) + { + if($last_message == trimmed_message) + { + if(lastmessages.children('span.repeat').length) + { + var current_value = parseInt(lastmessages.children('span.repeat').text()); + lastmessages.children('span.repeat').text(current_value + 1); + } + else + { + lastmessages.append($('', { 'class': 'repeat', 'text': 2})); + } + var insertedBadge = $(lastmessages).find('.repeat'); + insertedBadge.animate({ + "font-size": "0.9em" + }, 100, function() { + insertedBadge.animate({ + "font-size": "0.7em" + }, 100); + }); + opts.messageCount--; + handled = true; + } } - entry.innerHTML = message; - $messages[0].appendChild(entry); + if(!handled) + { + var entry = document.createElement('div'); + entry.className = 'entry'; + + $last_message = trimmed_message; + entry.innerHTML = trimmed_message; + $messages[0].appendChild(entry); + + // Stuff we can do after the message shows can go here, in the interest of responsiveness + if(opts.highlightTerms && opts.highlightTerms.length > 0) { + highlightTerms(entry); + } + } //Actually do the snap - if (!filteredOut && atBottom) { + if (atBottom) { $('body,html').scrollTop($messages.outerHeight()); } - - //Stuff we can do after the message shows can go here, in the interests of responsiveness - if (opts.highlightTerms && opts.highlightTerms.length > 0) { - highlightTerms(entry); - } } function internalOutput(message, flag) @@ -432,11 +403,6 @@ function ehjaxCallback(data) { } else { handleClientData(data.clientData.ckey, data.clientData.ip, data.clientData.compid); } - } else if (data.loadAdminCode) { - if (opts.adminLoaded) {return;} - var adminCode = data.loadAdminCode; - $('body').append(adminCode); - opts.adminLoaded = true; } else if (data.modeChange) { changeMode(data.modeChange); } else if (data.firebug) { @@ -544,7 +510,8 @@ $(function() { 'spingDisabled': getCookie('pingdisabled'), 'shighlightTerms': getCookie('highlightterms'), 'shighlightColor': getCookie('highlightcolor'), - 'scolorPreset': getCookie('colorpreset') + 'scolorPreset': getCookie('colorpreset'), + 'smessageCombining': getCookie('messagecombining') }; if (savedConfig.sfontSize) { @@ -587,6 +554,14 @@ $(function() { internalOutput('Loaded color preset of: '+colorPresets[opts.colorPreset]+'', 'internal'); } + if (savedConfig.smessageCombining) { + if (savedConfig.smessageCombining == 'false') { + opts.messageCombining = false; + } else { + opts.messageCombining = true; + } + } + (function() { var dataCookie = getCookie('connData'); if (dataCookie) { @@ -615,11 +590,6 @@ $(function() { $('body').on('mousedown', function(e) { var $target = $(e.target); - if ($contextMenu && opts.hasOwnProperty('contextMenuTarget') && opts.contextMenuTarget) { - hideContextMenu(); - return false; - } - if ($target.is('a') || $target.parent('a').length || $target.is('input') || $target.is('textarea')) { opts.preventFocus = true; } else { @@ -858,31 +828,25 @@ $(function() { }); $('#saveLog').click(function(e) { - var saved = ''; + $.ajax({ + type: 'GET', + url: 'browserOutput.css', + success: function(styleData) { + var win; - if (window.XMLHtpRequest) { - xmlHttp = new XMLHttpRequest(); - } else { - xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); - } - xmlHttp.open('GET', 'browserOutput.css', false); - xmlHttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); - xmlHttp.send(); - saved += ''; + try { + win = window.open('', 'Chat Log', 'toolbar=no, location=no, directories=no, status=no, menubar=yes, scrollbars=yes, resizable=yes, width=780, height=600, top=' + (screen.height/2 - 635/2) + ', left=' + (screen.width/2 - 780/2)); + } catch (e) { + return; + } - saved += $messages.html(); - saved = saved.replace(/&/g, '&'); - saved = saved.replace(/Chat Log'; + win.document.head.innerHTML += ''; + win.document.body.innerHTML = $messages.html(); + } + } + }); }); $('#highlightTerm').click(function(e) { @@ -956,6 +920,12 @@ $(function() { internalOutput('Changed color preset to: '+colorPresets[opts.colorPreset]); }); + $('#toggleCombine').click(function(e) { + opts.messageCombining = !opts.messageCombining; + setCookie('messagecombining', opts.messageCombining, 365); + internalOutput('Line combining '+(opts.messageCombining ? 'enabled' : 'disabled')+'', 'internal'); + }) + // Tell BYOND to give us a macro list. // I don't know why but for some retarded reason, // You need to activate hotkeymode before you can winget the macros in it. diff --git a/html/changelog.html b/html/changelog.html index e2d2d4918ac..cadf49ba919 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -86,1393 +86,1316 @@ ADDING CREDITS? EDIT templates/header.html (or footer.html if they're for old t -->
      -

      2018.02.09

      -

      jknpj updated:

      -
        -
      • Every non-combat(Security, Combat, Syndicate)/engineering cyborg is now equipped with a mini extinguisher.
      • -
      • Removed the big extinguishers from both Standard and TG17355 Cyborgs.
      • -
      • Fixed ghosts being unable to shift+click the AI
      • -
      - -

      2018.02.08

      -

      DrSnips updated:

      -
        -
      • Fixed syringes having a bloodbag icon over them when they had a small amount of reagents in them.
      • -
      • Added a few butterfly knifes. Upon flipping them closed they summon a "butterfly" for 20 seconds but only one at a time. It takes 25 seconds to recharge.
      • -
      • The butterfly will fight along side you. It does about 25 damage per hit.
      • -
      • A syndicate butterfly knife can be bought in the syndicate uplink for 7TC.
      • -
      • A crystal butterfly knife can be bought from the wizard spellbook for 20 points.
      • -
      -

      Kurfursten updated:

      -
        -
      • The telecommunications network monitor can now perform a traceroute to help you diagnose where the system breakdown is.
      • -
      +

      2018.07.03

      Pathid updated:

        -
      • Patients zero of a viral outbreak no longer get a roll for natural immunity to that virus.
      • +
      • Fixed robot holomap verb.
      • +
      + +

      2018.07.02

      +

      Pathid updated:

      +
        +
      • Create Antagonist verb now gives admins a choice of how many changelings or vampires to make, instead of always making three.

      ShiftyRail updated:

        -
      • The emergency defibrillator will now give a proper reason for failing to revive people.
      • +
      • Flashbang duration has been reduced by 20%, and now stuns carbons for a considerably shorter time at long range (more than 3 tiles). The cap for stunning at long range is 2 seconds, from 20 for carbons, and 8 seconds from 20 for silicons.
      -

      The-Whargoul updated:

      +

      tolan1 updated:

        -
      • Gave Plasmamen NO_HUNGER.
      • -
      • Removed Plasmamen's ability to eat solid food and medication.
      • -
      -

      TurboGay updated:

      -
        -
      • allows for construction permits to fit in wallets
      • +
      • replaces .45 magazines in packed armory locker with .380 magazines, to match the glock they spawn with
      -

      2018.02.07

      -

      DamianX updated:

      +

      2018.07.01

      +

      Pathid updated:

        -
      • Fixed a bug that prevented HUDs from finding records for people wearing no ID.
      • +
      • The clown stamp in the HONK upgrade for service borgs and hugborgs actually works now.
      • +
      + +

      2018.06.30

      +

      ShiftyRail updated:

      +
        +
      • Meta: Security has access to the internal morgue airlock, like in Box and Bagel.
      • +
      • Packed: Security has access to the internal morgue airlock, like in Box and Bagel.
      • +
      • Packed: Interrogation room designed to allow more space to manoeuvre prisoners, and privacy in the form of Smartglasses that can be toggled on or off.
      • +
      • Deff: Security checkpoint in medbay can be accessed via medical lobby, and now has a security cameras computer.
      • +
      • Deff: Perma is more secured, with a layer of grille + plasma window on top of the renforced wall outside. This means you can no longer sneak in with a false wall unnoticed.
      • +
      • Deff: Added a security locker to the arrivals checkpoint.
      • +
      • Deff: Added a second sec vend.
      • +
      • Deff: Security has access to the internal morgue airlock, like in Box and Bagel.
      • +
      • Warden and HoS lockers will now start with gear that was otherwise missing in them but found in security officer lockers, such as a hailer.
      • +
      + +

      2018.06.29

      +

      Pathid updated:

      +
        +
      • Refactored part of Securitron construction so that it doesn't delete non-standard cells from batons.
      • +
      + +

      2018.06.28

      +

      Irradiation updated:

      +
        +
      • Albuterol has been fixed to actually require Hyperzine instead of Inaprovaline.
      • +
      + +

      2018.06.27

      +

      Pathid updated:

      +
        +
      • Comments added to security and medical records are now timestamped with the in-game time instead of the server time.
      • +
      +

      ShiftyRail updated:

      +
        +
      • Albuterol (the medecine for athsma) now requires Hyperzine + Tramadol rather than Hyperzine + Inaprovaline.
      • +
      + +

      2018.06.26

      +

      Allspice updated:

      +
        +
      • Ports colorful reagent from TG, mescaline psilocybin amatoxin.

      MadmanMartian updated:

        -
      • Can now build thrones from wood.
      • -
      • Can now build chests from wood and plasteel. The plasteel has to be in your immediate vicinity or in your off-hand.
      • +
      • Adds anvils. Ordered through cargo.

      Pathid updated:

        -
      • Gave MMIs and posibrains dexterity. AFAIK the only thing this will affect is the mecha engineering switchtool, which MMI and posi piloted Clarkes will now be able to make full use of.
      • -
      • Constructs are now shock-immune.
      • +
      • Examining a cyborg gripper holding an item will examine the item instead.
      • +
      • Cyborg grippers holding an item will now drop the item on the first "drop" command, and store the gripper on the second "drop" command. Accordingly there's no action button for dropping anymore.
      • +
      • Fixed MoMMI modules being completely unusable.
      -

      2018.02.06

      -

      DrSnips updated:

      +

      2018.06.25

      +

      DamianX updated:

        -
      • Added the directed laser heater. It heats reagents in containers when placed on it. Use alt click or the right click verb to toggle it on and off.
      • -
      • Added the cryonic wave projector. It cools reagents in containers when placed on it. Use alt click or the right click verb to toggle it on and off.
      • +
      • Changelings cannot spam horror form any longer.
      • +
      • Fixed "Horror Form" costing 0 chems.
      - -

      2018.02.05

      -

      DrCelt updated:

      +

      DeityLink updated:

        -
      • Botany tray lids now properly block bees.
      • +
      • BEEKEEPING 3.6 - I'm back again baby
      • +
      • You no longer have to land the extinguisher spray right onto a bee swarm to calm them down. Calming bees has never been easier!
      • +
      • Bees no longer remain angry forever! If they can't find a target for an extended period of time, they'll calm down. This doesn't apply to angry bee infestations.
      • +
      • When an empty apiary is available, no more than one queen will swarm at once to populate it.
      • +
      • Homeless bees will die after about 10 minutes if left alone. Except queen bees, who'll try to recruit homeless workers to build colony. Their swarms will target empty apiaries in priority, but if they can't find any, they'll build their own from scratch! Each species has their own wild hive.
      • +
      • Wild hives work like normal ones, except that you cannot add queen bee packets or beezeez, or empty bees into them.
      • +
      • Added Hornets. They have a chance to spawn from infestation events, and traitor botanists may purchase Hornet Queen Packets for 2 TC each. Hornets have a chance to deal partial damage through protection, so handle carefully!
      • +
      • Beekeepers now start the game with a single bee packet in their pocket, so they don't have to wait for cargo to get to work.
      • +
      • lots of back-end optimization.
      -

      Kurfursten updated:

      +

      Irradiation updated:

        -
      • You can now buckle another person into a wheelchair, assuming they are otherwise valid to sit in it. This change does not extend to the multiman wheelchair.
      • +
      • The armory on Boxstation now has an RPG. Enjoy your friendly fire exercises, security.
      • +
      +

      MadmanMartian updated:

      +
        +
      • After careful deliberation, it has been deemed unsatisfactory that a security force be provisioned with explosive devices.

      Pathid updated:

        -
      • Packedstation: The escape shuttle brig turfs were fixed so "escape alive and free" objectives should properly fail now if the antagonist is on them and restrained.
      • -
      -

      jknpj updated:

      -
        -
      • Fixes Mecha Hitler holocausting the whole server with infinite german explosions.
      • +
      • Security cyborgs can now lift security tape. Engineering cyborgs can now lift engineering and atmos tape.
      • +
      • Slightly tweaked atmospheric analyzers so they'll work properly while you're inside an airtight object.
      • +
      • Fixed a bug where atmos analyzers would display the air temperature in red text all the time. Now it's in red only when it's outside of the safe range for humans.
      -

      2018.02.02

      -

      Kurfursten updated:

      +

      2018.06.24

      +

      MadmanMartian updated:

        -
      • You can no longer deathwhisper over radio
      • +
      • Can now install an active pAI to a minebot. It consumes the pai in the process, so be careful with your little friend.
      • +
      • The magic of the masks of morphing falters, they are no longer as effective as they once were.
      • +
      • You can now use welding tools to repair a damaged space pod.
      • +
      +

      Pathid updated:

      +
        +
      • In-hand sprites for defibrillators are now visible.
      -

      2018.01.31

      -

      Kurfursten updated:

      +

      2018.06.22

      +

      Pathid updated:

        -
      • Clipboards will now properly update when dumped into a cabinet
      • -
      • Clipboards now properly show the last item on top instead of the item last removed
      • -
      • Fixed the headset whisper bug
      • -
      -

      Pomf123 updated:

      -
        -
      • Non-Admin players that did not join the round can no longer vote for the next map.
      • -
      -

      jknpj updated:

      -
        -
      • Ports the 'Toggle Floor Bolts' AI verb from TG
      • -
      • Added a tile painter to the default service cyborg loadout.
      • -
      • Ports the portable seed extractor from TG. It doubles ad both plant bag and seed extractor but it can only extract at most two seeds per crop.
      • -
      • Removed the plant bag from the H.U.E.Y. upgrade.
      • -
      • Added the portable seed extractor to the H.U.E.Y. upgrade.
      • -
      • Fixes the chaos blade having no back icon while possessed.
      • -
      • Adds the reagent chill wax to the peace hypospray.
      • -
      • Added a chance to get a random cyborg upgrade(minus the magnetic gripper) as premium item in the Vox Supply.
      • +
      • Craftable training swords now have in-hand icons.
      -

      2018.01.30

      +

      2018.06.21

      +

      Allspice updated:

      +
        +
      • Silicon ckeys are displayed even if the silicon ghosts.
      • +

      Arthurdentist updated:

        -
      • Added a new premium costume to the security vendors, a British police uniform.
      • +
      • Added a new spellbook, available from the spellbook bundle. If you are lucky enough to find it, the winter spellbook will grant you one of four, Christmas-themed spells that are otherwise only available during Christmas.

      DamianX updated:

        -
      • RCDs can fit in hazard vests.
      • -
      • Changing security levels will play a notification sound.
      • -
      • Made the virology machines and account database (un)wrenchable.
      • -
      • Updated the medical sleeper UI.
      • +
      • Added a new traitor item: "Does Not Tip" database backdoor. Once purchased, lets you add the station to Central Command's "Does Not Tip" database. Stations on the list get extra condiment with their pizza.
      -

      DeityLink updated:

      +

      jknpj updated:

        -
      • Fixed chill bugs colonizing empty apiaries from turning into regular bees.
      • -
      • Added a transparent animated holographic ray between an holopad and its AI hologram
      • -
      • EMPs turn off AI holograms
      • +
      • Fixes MoMMIs being unable to use their station holomap verb
      -

      DrCelt updated:

      + +

      2018.06.20

      +

      Allspice updated:

        -
      • Did stuff!
      • +
      • Make buckshot spread independent of the distance you click at.
      -

      Kurfursten updated:

      +

      Unknown-as-Captain updated:

        -
      • Tradervend no longer lists each option twice, but instead gives five choices (up from four)
      • +
      • replaced R&D with Tetris and clearing a line gives you a random research point
      • +
      + +

      2018.06.19

      +

      Allspice updated:

      +
        +
      • Xeno doors can now be destroyed with lasers and bullets.
      • +
      +

      otatoh updated:

      +
        +
      • Adds an in-hand sprite for Salem
      • +
      • Fixes Salem turning into Runtime when picked up
      • +
      + +

      2018.06.18

      +

      Allspice updated:

      +
        +
      • Make NVG overlay less green.

      Pathid updated:

        -
      • Fixed emergency flares not lighting cigarettes, thermite, etc.
      • -
      • Added some unnecessary examine text to flares too.
      • +
      • Added a basic way to eject people and objects from transit tube pods. Just click the open pod with your empty hand. Additionally, examining the pod or the tube will now show you what's in it.
      • +
      +

      SonixApache updated:

      +
        +
      • You can now slot grenade launchers onto armored vests.
      • +
      • summon guns now summons a larger variety of guns
      -

      2018.01.29

      -

      DeityLink updated:

      +

      2018.06.17

      +

      DamianX updated:

        -
      • Fixed some manuals not printing on the library computer.
      • -
      -

      jknpj updated:

      -
        -
      • Fixes charcoal not appearing in the upgraded cyborg hypospray reagent list.
      • +
      • Added a new first law to NT Default that makes all laws after it be given equal priority.
      -

      2018.01.28

      -

      DeityLink updated:

      +

      2018.06.16

      +

      Allspice updated:

        -
      • The Emergency Shuttle should now always be playing its hyperspace warm up sound.
      • -
      • hey I'm back.
      • -
      • Slightly increased the ratio of honey found in honeycomb, compared to reagents from plants.
      • -
      • Slowed down the rate at which your body metabolizes honey.
      • -
      • Added Chill Bugs, a new species of bees. One or two packets of those can be found on the Vox outpost. Those bugs imported from Vox worlds need N2 to breath and suffocate in Oxygen. They produce a honey-like substance called Chill Wax, and while it doesn't heal as efficiently as regular honey does, it has the strange property of causing people who ingest it to become unable to perform any act of violence. Incidentally, Chill Bugs live up to their name and don't get angry ever, and there are only a handful of reagents that can raise their hive's toxicity, which makes raising them much easier than raising bees, if you can set up proper atmos.
      • -
      • New sprite for the beekeeping book
      • +
      • Move the handtele destination-select from attackself to alt-click, make attackself automatically open a portal to the most recent chosen destination.
      • +
      +

      SonixApache updated:

      +
        +
      • syndicate tape now fits in tool- and security belts.
      • +
      + +

      2018.06.14

      +

      Irradiation updated:

      +
        +
      • NT decided to cut their budget allocation for anti-tampering device for the Tactical Assault Gear crate.
      • +
      +

      Pathid updated:

      +
        +
      • Reverted the "new" super-shaky dizziness/drunkenness effect.
      • +
      + +

      2018.06.13

      +

      Intigracy updated:

      +
        +
      • Reverted the change that made cat ears give brain damage over time.
      • +
      +

      Pathid updated:

      +
        +
      • Fixed an oversight where newly constructed or re-constructed machines did not check if they were actually in a powered area.
      • +
      • Ghosts can point now.
      • +
      + +

      2018.06.12

      +

      Allspice updated:

      +
        +
      • Adds untable mutagen, produceable with phenol formic radium. It uns tables.
      • +
      • shift+mmb-click on things at a distance to point at them.
      • +
      +

      Intigracy updated:

      +
        +
      • Collectible cat ears now once again remain black permanently.
      • +
      +

      Pathid updated:

      +
        +
      • Being hit with a bolt from the Staff of Change no longer causes wizard spells to be lost.
      • +
      + +

      2018.06.11

      +

      DamianX updated:

      +
        +
      • Ported some vending machine animations that play when an item is ejected.
      • +
      • Radio messages no longer show the icon of the radio used to send them.
      • +
      +

      Kevak updated:

      +
        +
      • Adds several items to autolathes that felt like they were missing/were requested. Including some botany tools, hand labelers, bear traps and so on.
      • +
      +

      Pathid updated:

      +
        +
      • Fixed a bug that caused gibtonite ores to be duds.

      ShiftyRail updated:

        -
      • Crawling now requires you to stand still for exactly 1 seconds before moving. Missing/damaged limbs significantly increase that delay. Hyperzine counteracts those adverse effects. Additionally, once you've began to crawl in a certain direction, you can no longer change said direction.
      • +
      • The syndicate can now provide security, atmospheric technicians, and engineers with rigged tape. Security rigged tape cuffs people who try to remove it, engineering rigged tape shocks you, and atmospherics tape is very sharp and difficult to remove.
      • +
      + +

      2018.06.10

      +

      Pathid updated:

      +
        +
      • Getting SoC'd into a humanoid race will automatically update your default language to the default for that race.
      • +
      • Extreme burn victims aren't impossible to defib anymore, unless they also happen to have severe radiation damage.
      • +
      +

      unid15 updated:

      +
        +
      • Added a new, exciting puzzle vault. The reward for completing it is a Vest of Reflection - a yellow-colored ablative vest that is guaranteed to reflect every single energy projectile (at the cost of providing less protection versus other types of damage). It is fully unique to the vault, and will never appear in Spessmart.
      • +
      + +

      2018.06.08

      +

      Pathid updated:

      +
        +
      • Uranium chairs now deconstruct into uranium instead of diamond.
      • +
      • Retooled camera-to-blinder conversion and deconversion. No more infinite bulbs/film. Also, sepia, XL and XXL cameras will no longer be turned into normal cameras by it. Note that the process destroys all unused film inside.
      • +
      • Tweaked some helmet coverage areas to better reflect their wear icons.
      • +
      • Building an AI core without a brain or posibrain will now result in an inactive AI core you can upload a carded AI to. Previously this would bug out and make an AI without a player to control it.

      jknpj updated:

        -
      • Fixes a runtime when examining cyborgs with activated grippers and no gripped item.
      • -
      • Adds the staff of nullmancy, heavenly chain, honk rod, french rod, blessed cane and septerion morningstar as holy weapon skins for the null rod.
      • -
      • Adds the chaos blade, a talking "holy" weapon, as a rare drop to temple and war digsites.
      • -
      • Added "Martian" as a staff of change mode.
      • -
      • Removed "Horror" from changelings from the staff of change's "Human" setting.
      • -
      • Borgs/MoMMIs will now self-destruct themselves after being transformed by a staff of change/admin panel if their brain is from a jobbanned player.
      • -
      • the Monkey mode in the staff of change will now properly transform their targets in their respective primite species AND transfer their DNA/damage taken/intent properly.
      • +
      • Adds a robot maintenance crate to cargo for 120 spessbucks.
      • +
      • Cyborgs cover will automatically unlock when they die.
      • +
      +

      jmantela updated:

      +
        +
      • Added two new condiment bottles: mustard and relish. Can be found in the exotic garnishes crate from cargo.
      -

      2018.01.25

      -

      DrSnips updated:

      +

      2018.06.07

      +

      Pathid updated:

        -
      • You can now insert the key of a vehicle into the vehicle itself to allow it to run. The old method of holding the key in hand at all times still works as well. This applies to vehicles like janicarts, firebirds, gigadrills, etc.
      • +
      • Fixed a problem where hivelord broods were not getting destroyed properly.
      -

      2018.01.24

      -

      HarseTheef updated:

      -
        -
      • Reworks Chloral Hydrate to only apply a knockdown when above 10u and apply a confused/drowsy state for all amounts below 10u.
      • -
      -

      PromethTK11 updated:

      -
        -
      • Packed: Fixed a lot of air alarms/vent/scrubbers issues on Packed, you can breath now.
      • -
      • Packed: You shouldn't be able to crowbar the AI core blast-door now.
      • -
      • Packed: Added an evidence locker to brig for all your noir needs.
      • -
      • Packed: The flash of the brig cells now should work properly.
      • -
      • And various Packedstation misc fixes!
      • -
      - -

      2018.01.23

      +

      2018.06.06

      Intigracy updated:

        -
      • "This is a test changelog (please don't mind it)."
      • +
      • "Chems that remove hallucination triple in effectiveness if you're asleep or in cryo, double if you rest."

      MadmanMartian updated:

        -
      • Boozeomats and soda dispensers can now dispense ice again
      • +
      • Adds material inheritance to created objects
      • +
      • Adds the grease spell, letting you create a lube-spill at will. Has congruency with fire spells, so having fireball will also make it spill welder fuel.
      -

      PJB3005 updated:

      + +

      2018.06.05

      +

      Pathid updated:

        -
      • "Charcoal works 5x faster now, remains in the body for much longer, doesn't delete itself on vomiting (but still causes vomiting) and it automatically deletes itself when all reagents are gone."
      • +
      • Revival effects will no longer "eat" restraints. Instead they will just drop.
      • +
      • Hitsounds now play when constructs and shades are hit by weapons. Striking a juggernaut with a weapon will now produce an attack animation (if it has enough force to deal damage to it), and they now take bonus damage from null rods like other constructs.
      + +

      2018.06.03

      +

      Allspice updated:

      +
        +
      • Windows can now be rotated with alt-click.
      • +
      +

      MadmanMartian updated:

      +
        +
      • Adds the joy of painting religion. Tags are bob ross, art, happy little trees, happy little clouds.
      • +
      +

      Pathid updated:

      +
        +
      • Fixed a bug that made cult space armor and space helmets unwearable.
      • +
      • Flashbangs going off on someone's same tile now affect them for the full duration regardless of their protection.
      • +
      + +

      2018.06.01

      +

      Pathid updated:

      +
        +
      • Shades, soul stones and constructs now have examine text that shows if the player has logged out or ghosted.
      • +
      + +

      2018.05.31

      +

      DamianX updated:

      +
        +
      • Central Command might request supplies from the station from time to time. Details will be available at the cargo computers.
      • +
      +

      Pathid updated:

      +
        +
      • Proto-kinetic accelerators now have a working charge indicator light.
      • +
      + +

      2018.05.27

      +

      DamianX updated:

      +
        +
      • The "O" key no longer opens the OOC chat window in hotkey mode.
      • +
      +

      Pathid updated:

      +
        +
      • Renamed the body scanner's "Absorbed rads danger index" to "Radiation sickness progression" which is more descriptive of what it is. Also now it will give the name of the stage the patient is in.
      • +
      • Lattices built on asteroid floors and metal foam floors will now layer OVER them instead of under them and invisible.
      • +
      +

      SonixApache updated:

      +
        +
      • Nanotrasen has removed the auxiliary .45 chamber-loading option from their glock lineup.
      • +
      +

      jknpj updated:

      +
        +
      • Boss mob exclusion list properly implemented this time. No more Hitlers in Xenobio
      • +
      + +

      2018.05.26

      +

      Pathid updated:

      +
        +
      • Body scans now show a number for the progress of radiation poisoning, in addition to the radiation level, which doesn't tell the whole story.
      • +
      + +

      2018.05.25

      +

      MadmanMartian updated:

      +
        +
      • Pistols now have an instruction guide on how to fire both at the same time. Simply slap one against the other, then start firing until one goes click.
      • +
      + +

      2018.05.24

      +

      DamianX updated:

      +
        +
      • Changed the recipe for sodium polyacrylate to require water instead of hydrogen and oxygen.
      • +
      +

      MadmanMartian updated:

      +
        +
      • Simple animals can be put in cryo
      • +
      • Simple animals can be buckled to chairs
      • +
      • Adult slimes are now considered larger than their younglings, rather than being the same size.
      • +
      + +

      2018.05.23

      +

      DamianX updated:

      +
        +
      • Added sodium silicate. One part silicon, two parts sodium, three parts oxygen. Used in the recipe for plasteel solidification.
      • +
      • Several minor changes to some relatively uncommon chemical recipes. Details on the wiki.
      • +
      + +

      2018.05.22

      +

      Exxion updated:

      +
        +
      • A ton of stuff with ZAS. Most things should be back to the behavior of about seven months ago, so build things with that in mind.
      • +
      + +

      2018.05.21

      +

      abernd updated:

      +
        +
      • headsets, station bounced radios, and station intercoms now allow direct frequency input
      • +
      + +

      2018.05.20

      +

      Pathid updated:

      +
        +
      • Created a "Sign up as pAI" verb in the Ghost tab for submitting a pAI profile without having to be around for the recruitment prompts.
      • +
      +

      unid15 updated:

      +
        +
      • Ring of fire and its upgrades now cost 10 spell points (down from 20)
      • +
      + +

      2018.05.18

      gbasood updated:

        -
      • Buttbots now actually make fart noises when they parrot someone they hear.
      • +
      • Bluespace fruits, when not thrown, but still "thrown", will teleport hit mobs consistently.
      -

      2018.01.22

      -

      Kurfursten updated:

      -
        -
      • Speaking over a headset or radio will now cause your local speech to appear before the radio message.
      • -
      • Damage to telecomms will no longer cause your local messages to be delayed if you are standing in range of a radio. However, the radio transmission will still be delayed, and appear separately.
      • -
      - -

      2018.01.21

      +

      2018.05.17

      DamianX updated:

        -
      • Ghosts with the appropriate HUDs will be able to look at people's security and medical records by examining them.
      • +
      • Fixed a bug that prevented removal of camera bugs from simple animals.
      -

      PJB3005 updated:

      +

      Pathid updated:

        -
      • Did stuff!
      • +
      • Fixed a very longstanding math flub involving gas values and temperatures. Gas and heat will be working subtly differently now, and hopefully better.
      • +
      • Fixed the "dug" icon state for asteroid floors.
      +

      jknpj updated:

      +
        +
      • Service cyborgs can now use chemistry dispensers
      • +
      • Soviet MoMMIs can now use bartending machinery
      • +
      • Combat cyborgs can now use *law and *halt
      • +
      + +

      2018.05.16

      +

      Pathid updated:

      +
        +
      • Fixed a bug where temporary blindness of MMI'd brains resulted in permanent blindness until the player re-logged.
      • +
      + +

      2018.05.14

      +

      MadmanMartian updated:

      +
        +
      • A new virus symptom has been discovered in the deep space biodomes, that saps the energy from plantlife in the infecteds surroundings.
      • +
      +

      Pathid updated:

      +
        +
      • Fixed the pAI appearance for pAI mulebots disappearing after unloading things.
      • +
      + +

      2018.05.11

      +

      Allspice updated:

      +
        +
      • Makes Lightning spell not recharge 3x as fast as other spells.
      • +
      +

      Pathid updated:

      +
        +
      • Fist spell now selects targets at random instead of opening a dialog box.
      • +
      • Fixed industrial vaporizer having a full mixing chamber crashing the serb.
      • +
      + +

      2018.05.10

      +

      Allspice updated:

      +
        +
      • The GPS you are looking at will always display its coords at the top of the coords list.
      • +
      • Adds bluespace bananas and their special peels; mutates from normal bananas.
      • +
      +

      DamianX updated:

      +
        +
      • Fixed wooden walls having no floor underneath them when destroyed
      • +
      +

      MadmanMartian updated:

      +
        +
      • Adds the sporemind global chat for mushroom people. Use .~ to talk with it
      • +
      + +

      2018.05.08

      +

      MadmanMartian updated:

      +
        +
      • Making a roman phalanx against bears now works, as simple animal attacks now check for shields.
      • +
      • You can now point-blank simple animals with guns, and have noises play when you hit them with sound making weapons again.
      • +
      + +

      2018.05.07

      unid15 updated:

        -
      • Ring of fire now rapidly expands outwards from the wizard when initially cast
      • +
      • Admins may now enable advanced hologram spawning in the holodeck
      -

      2018.01.20

      -

      DamianX updated:

      +

      2018.05.05

      +

      Allspice updated:

        -
      • P-ray scanners are now 10 times as expensive to build compared to the T-ray scanners.
      • +
      • Adds the Lazymov lawset, it can be researched with materials 6 and programming 3.
      • +
      +

      PublicEnemyMaiPai updated:

      +
        +
      • Plasmamen now receive their old flaming sprite after cloning again.
      -

      2018.01.19

      -

      CptWad updated:

      +

      2018.05.03

      +

      Allspice updated:

        -
      • I am back from the dead! With bugfixes!
      • -
      • In order to make showers visible in shower curtains, added two new types of showers that allow visibility (click-ability) of shower heads while in the open position.
      • +
      • Makes upgraded parts influence xenobotany machines' efficiency.
      -

      DamianX updated:

      -
        -
      • Fixed several typos.
      • -
      • Made antag (cult/thrall/rev) (de)conversion messages bigger.
      • -
      -

      Kurfursten updated:

      -
        -
      • Alt-clicking almost any binary atmos device (pumps, valves, gates) will toggle it on/off. Exceptions are TEG circulators, MSGS, DP Vents.
      • -
      • Alt-clicking a pipe segment that isn't wrenched down will rotate it.
      • -
      -

      MadmanMartian updated:

      -
        -
      • Anti toxin now covers the botany toxins as well
      • -
      -

      ShiftyRail updated:

      -
        -
      • You can no longer hulk ad infinitum by using a clean SE while hulking.
      • -
      -

      SonixApache updated:

      -
        -
      • added black bedsheets and black soft caps
      • -
      • sprites by Blithering
      • -
      - -

      2018.01.18

      -

      ShiftyRail updated:

      -
        -
      • Enthralled people can see other thralls from the same vampire.
      • -
      -

      jknpj updated:

      -
        -
      • You can now put mice on your head.
      • -
      - -

      2018.01.17

      DrSnips updated:

        -
      • Raised the amount of phazon you get per vein from 2 to 3.
      • +
      • Added a Dorf religion for chaplain.
      -

      MadmanMartian updated:

      +

      PublicEnemyMaiPai updated:

        -
      • More leather recipes added.
      • -
      • The crafted leather items now inherit the name of the source of the leather. Corgi leather cowboy hats, Cat leather shoes, et cetera.
      • +
      • AI can now Beep Ping Buzz
      -

      Pathid updated:

      +

      imw-Oculus updated:

        -
      • Damage on a limb now has only a chance to widen an existing wound rather than doing it all the time.
      • -
      • Once installed, robot jetpacks now function in MoMMIs as they were supposed to. Godspeed, little crabs.
      • -
      -

      ShiftyRail updated:

      -
        -
      • Added fishtanks! Construct your own fishtank with glasses, metal and a circuit board. Breed fish with eggs from cargo. Catch fish, make your own fish-based recipes! Sprites courtesy of Blithering. Original fishtanks on Paradise courtesy of TheFalseIncarnate, original work on fishtanks courtesy of jakmak.
      • -
      -

      SonixApache updated:

      -
        -
      • Added black crayons.
      • -
      • Crayon boxes can now hold 7 crayons and include a black crayon.
      • -
      • Hand crank charger now adds 10 times more power units per crank
      • -
      - -

      2018.01.16

      -

      DamianX updated:

      -
        -
      • NT default and Robocop core boards can be printed using the circuit imprinter.
      • -
      -

      HarseTheef updated:

      -
        -
      • Removes the blood cost from Hypnosis for vampires.
      • -
      -

      Pathid updated:

      -
        -
      • Vampire blood costs were adjusted. Bat Form and Shadowstep now actually spend blood and cost 20 and 10 usable blood respectively. Summon Bats costs 50 usable blood.
      • -
      • Improved vamp rejuvenate now has a message telling you about the effect.
      • +
      • Firelock frame construction. Use 5 metal in hand.
      • +
      • Firelock deconstruction, weld and wrench rather than socketwrench.

      jknpj updated:

        -
      • Fixes verb holders falling out of your pocket.
      • +
      • Adds rice hats, they can be made in the biogenerator and each costs 300 points.
      • +
      • Adds the fancy and black kimonos. The fancy one can be found in the autodobre premium list and the black one in the pietyvend premium list.
      • +
      • moved the sakura kimono to the normal list of the autodrobe.
      • +
      • Samurai chaplains now start with a rice hat, black kimono and sandals.
      • +
      • Adds the security cyborg N.O.I.R. upgrade. It adds a tape recorder, evidence bag, cyborg zoom lens(works like binoculars), .38 revolver, cyborg .38 speedloader(charges one bullet every 10 seconds inside a cyborg recharger) and a worn-out gripper(can hold drinks, the detective's scanner and fingerprint cards). This upgrade cannot be researched.
      • +
      • Adds the security cyborg warden upgrade. It adds a reinforced armour, battering ram, wrench, security code transmission device(locks/unlocks deployable barriers) and a cyborg implanter(recharges its implant after one minute inside a cyborg recharger). This upgrade cannot be researched.
      • +
      • Adds both new upgrades to the vox vend premium list, giving traders a rare chance of finding them in their vend.
      -

      2018.01.12

      -

      MadmanMartian updated:

      +

      2018.05.02

      +

      jknpj updated:

        -
      • You can now lock direction in a mech
      • +
      • Mecha Hitler, Wendigos and Cockatrices can't be spawned by gold core+blood reactions anymore.
      + +

      2018.05.01

      Pathid updated:

        -
      • Chemical effects that cause disfigurement (acid, mainly) and undo disfigurement (rezadone) should work again.
      • -
      • Added messages to a few disfigurement/un-disfigurement events.
      • -
      -

      Unknown-as-Captain updated:

      -
        -
      • Cat ears give slow brain damage over time.
      • +
      • Cloning pods don't inject vox with toxic inaprovaline anymore.
      • +
      • Being made unclonable by radiation will no longer render you unable to be defibbed out of hand, or unable to be hooked up to IVs.
      -

      2018.01.09

      -

      Cisrox updated:

      -
        -
      • Adds unique color combinations for dual e-swords. The colors of the e-swords forming the dual e-sword determines this.
      • -
      • Deleted dualesword1 sprite that was serving as a placeholder, it has been replaced by the new colors.
      • -
      -

      EdXbtkOEwGw updated:

      -
        -
      • Properly implemented glide_size on a lot of things. This means, for example, dragging a corpse won't make it look like it's teleporting everywhere, ghosts won't rollerskate in the air after haunting a slow person, plus smooth conveyor belts, smooth space inertia, and other things. If you still notice old no-glidesize behavior of stuff teleporting around, make a bug report.
      • -
      - -

      2018.01.08

      +

      2018.04.30

      Pathid updated:

        -
      • Defficiency: Fixed up some misplaced atmos pipes in medbay, the bar backroom, and cargo maint.
      • -
      • Bagelstation: The kitchen's mail was being sent to the janitor's closet.
      • +
      • Cult space armor no longer has species restrictions.
      • +
      • Made it so that when an armor talisman is used, the blade from it goes straight into the user's active hand instead of their off hand, or worse, the ground.
      • +
      • Added syndishades: disguised secHUD sunglasses that can't set arrest status until they get the codes from a normal pair.
      • +
      • Changed number of implants in a greytide kit from one to two. Added syndishades to the kit.
      -

      Sooose updated:

      +

      PublicEnemyMaiPai updated:

        -
      • Increased slime tiles generated from green slime reaction to 20.
      • -
      • Increased max slime tile stack size to 60.
      • +
      • Adds AI as job listing for AI when ordering supplies from cargo
      • +
      +

      SirSkeleto updated:

      +
        +
      • Added "Brotherhood of the Yellow Sign" religion.
      -

      2018.01.06

      -

      Jared-Fogle updated:

      -
        -
      • Fix eye protection being lowered when toggling the welding goggles back on.
      • -
      - -

      2018.01.04

      -

      Pathid updated:

      -
        -
      • Slight correction to the checks for putting monkeys into the monkey recycler.
      • -
      -

      ShiftyRail updated:

      -
        -
      • Add religious converting. Chaplains will be able to ask people to convert to their religion.
      • -
      • Admins are now able to bus in religions and subtle PM all followers of a particular religions, as well as removing people from their religions.
      • -
      - -

      2018.01.03

      -

      Pathid updated:

      -
        -
      • Mops should work now.
      • -
      - -

      2017.12.31

      -

      Cyadox updated:

      -
        -
      • Quick-equip hotkey can now swap items in occupied slots.
      • -
      • Stopping surgery by dropping or storing your tool now harms the patient
      • -
      -

      DamianX updated:

      -
        -
      • Diagnostic HUDs can be printed from the protolathe.
      • -
      • Ghosts can use the diagnostic HUD.
      • -
      • Expanded the list of items the security hardsuit can hold. If the security armor can hold it, the hardsuit can too.
      • -
      • AIs can now track mechs.
      • -
      -

      HarseTheef updated:

      -
        -
      • Increased the tracking ability of the hand held tracking implant tool
      • -
      -

      MadmanMartian updated:

      -
        -
      • Made chemical heating less of a pain in the ass.
      • -
      • Can now sell plasma via cargo again.
      • -
      -

      Pathid updated:

      -
        -
      • Clone damage on slimepeople can be healed now.
      • -
      • Improved the clarity of cult bonus objectives.
      • -
      • A breathing bug for non-human mobs was fixed. Tiny concentrations of CO2 and plasma should no longer kill animals dead.
      • -
      • A similar bug was causing space heaters and AC units to be unduly effective.
      • -
      - -

      2017.12.28

      -

      Cyadox updated:

      -
        -
      • Adds an alternative MoMMi Prime sprite, Credit to Skowron.
      • -
      - -

      2017.12.27

      -

      DamianX updated:

      -
        -
      • Added the diagnostic HUD: lets the user see integrity and power cell charge for cyborgs and mechs. A couple of them can be found in the roboticist's locker.
      • -
      • Ghosts can use the security HUD.
      • -
      -

      MadmanMartian updated:

      -
        -
      • Aliens can only pickup facehuggers now.
      • -
      • Martian new HUD courtesy of realestestate
      • -
      +

      2018.04.29

      unid15 updated:

        -
      • Large amounts of blunt brute damage (16 and more) will gib limbs, instead of severing them. Gibbed limbs are destroyed, but heads still leave an intact brain.
      • +
      • Radiation collectors are now affected by glowing ghouls and (to a much lesser extent) by creatures with the radioactive gene
      -

      2017.12.26

      +

      2018.04.27

      +

      MadmanMartian updated:

      +
        +
      • Adds GraveKEEPER Cogspiders.
      • +
      +

      ihadtoregisterforthis updated:

      +
        +
      • Cup ramen is self-heating again
      • +
      • Added quicklime as a heating chemical for your reagent temperature needs
      • +
      + +

      2018.04.26

      Pathid updated:

        -
      • Due to their inherent slowness, alien queens aren't affected by pain slowdown any longer.
      • -
      -

      jknpj updated:

      -
        -
      • Adds the Service Cyborg H.O.N.K. upgrade! It comes with a bikehorn, rainbow stamp, rainbow crayon, sound synth and a water flower ready for your everyday fun times.
      • -
      - -

      2017.12.24

      -

      PJB3005 updated:

      -
        -
      • Fixed NTSL scripts scrambling characters like >. You can make a script that adds meme arrows to everything now.
      • -
      - -

      2017.12.22

      -

      Arthurdentist updated:

      -
        -
      • Added two new spells that will be available for wizards to purchase on Christmas Day
      • -
      - -

      2017.12.20

      -

      DamianX updated:

      -
        -
      • Bio suits will block plasma like they were supposed to.
      • -
      -

      Sooose updated:

      -
        -
      • Curtains now start anchored and can be (un)secured with a screwdriver.
      • -
      -

      yclatious updated:

      -
        -
      • Reduced prices on soda machines
      • -
      - -

      2017.12.19

      -

      jknpj updated:

      -
        -
      • Cyborg upgrades (Medical MK-2, Service Cooking, Service H.U.E.Y.) will upgrade both chem/service gripper properly now.
      • -
      - -

      2017.12.18

      -

      Pathid updated:

      -
        -
      • Security cyborgs now have a hailer for your targeted hailing needs.
      • -
      -

      Unknown-as-Captain updated:

      -
        -
      • MoMMIs can scan phazon.
      • -
      - -

      2017.12.17

      -

      DamianX updated:

      -
        -
      • Buffed the service borg beer synthesizer to produce 1u each tick (previously 0.3u)
      • -
      • Trying to apply tape to doors won't open said doors anymore.
      • -
      • Can't stack multiple tapes on doors anymore.
      • -
      -

      DrSnips updated:

      -
        -
      • Added sodium polyacrylate. It absorbs water and spacelube not only in containers but on floors as well. Made with 3u carbon, 3u hydrogen, 1u sodium, and 2u oxygen.
      • -
      -

      MadmanMartian updated:

      -
        -
      • Adds Rad patches. A jumpsuit accessory that changes color when it absorbs radiation
      • -
      -

      Pathid updated:

      -
        -
      • Carbon mobs will now receive damage slowdown proportional for their maximum health, instead of always being based on 100.
      • -
      -

      PromethTK11 updated:

      -
        -
      • Packed: Now the hyperspectral imager is on place on the outpost, and there are some tools for scientist now.
      • -
      • Packed: Elite-syndie shuttle works properly now.
      • -
      • Packed: Secway keys added to the warden locker.
      • -
      • Packed: Scrubbers now scrub out plasma by default.
      • -
      • Packed: And a lot of misc fixes/changes!
      • -
      -

      Unknown-as-Captain updated:

      -
        -
      • Fixes mismatched glide_sizes for vehicles (possibly other things as well). This means wounded people riding vehicles won't wobble all over the place anymore.
      • -
      -

      jknpj updated:

      -
        -
      • Supply cyborgs now have access to both cargo and mining radio instead of just cargo.
      • -
      • Ghosts can now examine closed lockers to check its contents
      • -
      -

      yclatious updated:

      -
        -
      • Reduced prices on the Off World Off License vendor, enjoy lower prices for lower quality beer.
      • -
      - -

      2017.12.11

      -

      MadmanMartian updated:

      -
        -
      • Turrets now check if you are stunned rather than if you are lying down before firing at you
      • -
      - -

      2017.12.10

      -

      PJB3005 updated:

      -
        -
      • Lowered the find rate on the "crystal" xenoarch artifact. It did literally nothing except infuriate xenoarchs.
      • -
      - -

      2017.12.09

      -

      Kurfursten updated:

      -
        -
      • The telecommunications network monitoring console can now boost the signal of telecomms machines affected by ionospheric interference, rebooting them immediately. This will cause increased temperature and power expense for five minutes.
      • -
      • The network monitor will also remotely display machine integrity.
      • -
      -

      Unknown-as-Captain updated:

      -
        -
      • Increases energy cost of airlocks made with with borg RCDs
      • -
      • Re-added 2012 flashbang box description
      • -
      • You now get 40 bananium/phazon floortiles per sheet, up from 4
      • -
      • Cyborg material synthetizers cannot dupe bananium or phazon. You can still synthetize it by using solid matter cartridges.
      • -
      -

      jknpj updated:

      -
        -
      • Adds the instrument synthesizer to the default service cyborg loadout.
      • -
      • Adds the H.U.E.Y. upgrade to service cyborgs! It comes with a mini hoe, clippers, plant bag, plant analyzer and makes the service gripper able to handle seeds and glass containers.
      • -
      • Removes the botanics-related upgrades from the cooking upgrade and makes it cheaper.
      • -
      • You can now drag and drop a piece of meat on cloning pods to make them suck and process every piece of meat in the same tile as the one being dragged(this feature can't be used by silicons).
      • -
      • Kicking a cloning pod now has 5% chance to unlock and eject its occupant.
      • -
      - -

      2017.12.07

      -

      DamianX updated:

      -
        -
      • Space suits are now orderable from cargo.
      • -
      • Science access lets you open exotic seeds crates (hydroponics access still works).
      • -
      -

      Kurfursten updated:

      -
        -
      • You may now drag crates onto disposal bins to return your emptied mail.
      • -
      -

      MadmanMartian updated:

      -
        -
      • Bananas now have potassium in them
      • -
      -

      RealestEstate updated:

      -
        -
      • Did stuff!
      • -
      • did other stuff!
      • -
      - -

      2017.12.06

      -

      MadmanMartian updated:

      -
        -
      • More cargo shuttle fixes. Metaclub cargo shuttle no longer steals windows.
      • -
      -

      Pomf123 updated:

      -
        -
      • Added AOL You got mail.wav to disposals when packages arrive.
      • +
      • Inhalers can be used on other people now, when on help intent.
      • +
      • Turning into a slime person via mutation toxin should relieve the subject of broken bone status effects now, as slime people don't have bones.
      • +
      • NT has patched a security flaw in loyalty implants that made them useless at blocking the effects of the Syndicate's so-called Greytide implant. Whichever implant that gets in first will override the other.

      ShiftyRail updated:

        -
      • Add a cancel option to text prompts which previously had none.
      • -
      - -

      2017.12.05

      -

      MadmanMartian updated:

      -
        -
      • Deff cargo shuttle now no longer tries to run over the kitchen
      • -
      - -

      2017.12.03

      -

      MadmanMartian updated:

      -
        -
      • Feral ghouls are fixed
      • -
      • It is now easier to become a ghoul somewhat. Less uncurable brain damage.
      • -
      -

      unid15 updated:

      -
        -
      • Fixed maploader being very laggy and crashing the server when loading away missions
      • -
      - -

      2017.12.02

      -

      Blithering updated:

      -
        -
      • Did stuff!
      • -
      • did other stuff!
      • -
      -

      DrSnips updated:

      -
        -
      • Added loot crates. A monthly subscription for $30 you can buy in the cargo merch computer.
      • -
      • Added the measuring tape, core sampler, and phazon glow stick to the list of anomaly designs in the protolathe.
      • -
      • Added the phazon glowstick. It changes to random colors when you shake with it or interact with it. It can be worn on jumpsuits like other accessories. It will not change colors while on jumpsuits. (This is a feature not a bug)
      • -
      -

      MadmanMartian updated:

      -
        -
      • Having a cane on you when your leg's broken now helps you move a bit faster than otherwise.
      • -
      • Activated charcoal recipe added. 2 parts acid, 1 part carbon. 450 degrees C
      • -
      • You can now crawl by clicking on a turf in proximity when on the ground but not unconscious or dead and have arms
      • -
      • Bunsen burner buffed by 150%
      • -
      - -

      2017.11.28

      -

      unid15 updated:

      -
        -
      • Added a new vault
      • -
      - -

      2017.11.26

      -

      unid15 updated:

      -
        -
      • Text written on paper with crayons is now colored again
      • -
      • Text written on paper is no longer permanently lost if the act of writing somehow fails, only if you press the 'Cancel' button
      • -
      - -

      2017.11.18

      -

      DrSnips updated:

      -
        -
      • Paramedic locker contents have been shuffled a bit.
      • -
      • Paramedic EVA locker now has two internalbleeding kits. (8 total bio foam injectors)
      • -
      • Removed some of the extra paramedic gear leaving two complete sets of outfits.
      • -
      • Paramedic webbing added to the EVA locker.
      • -
      • The magboots in the paramedic EVA locker now have paramedic colors.
      • -
      • Added the precision grasper. It functions like a hemostat at double speed and allows you to retrieve implanted things 100% of the time when trying to fish them out.
      • -
      • Added the diamond surgical drill. An advanced version of the surgical drill. It's extremely fast like other diamond drills.
      • -
      -

      Kurfursten updated:

      -
        -
      • Radiation closets now spawn with a single Geiger counter.
      • -
      • Geiger counters fit on tool-belts.
      • -
      -

      unid15 updated:

      -
        -
      • Fixed admins not being able to modify lighting parameters on objects
      • -
      • Buildmode now supports area modification. While in build-adv mode, middle-click on a turf twice to begin expanding its area. This works like the station's blueprints, but also supports click-dragging to convert large amounts of turfs quickly. Middle-click anywhere outside of the edited area to stop. Areas may now be spawned from paths as well, just like any other object, using either "spawn" or buildmode.
      • -
      • Added a new disability - veganism. It can be received either randomly at roundstart, by enabling it in your character preferences, through a new stage 2 virus effect, or through genetics. Also added a "veganism" / "animal rights" religion which automatically grants this disability.
      • -
      • Eating animal products, meat, milk, honey and blood as a vegan will make you nauseous, and further continuing to do so will cause minor toxin damage. Vegan vampires are unable to drink blood, if turned vegan after becoming a vampire.
      • -
      - -

      2017.11.16

      -

      N3X15 updated:

      -
        -
      • Disables one-way window construction. Should help with performance.
      • -
      - -

      2017.11.12

      -

      DamianX updated:

      -
        -
      • Carded AIs will no longer require a powered APC.
      • -
      • Personal AIs' wirejacks can now also close airlocks.
      • -
      -

      MadmanMartian updated:

      -
        -
      • Can now fold up plastic bags when empty so they can fit in smaller areas such as pockets
      • -
      - -

      2017.11.11

      -

      Kurfursten updated:

      -
        -
      • You may now lube up TEG circulators (up to 25u each) to increase power output. Power growth is linear up to 200% bonus based on flow capacity.
      • -
      • Lube in circulators will slowly heat until converting into toxic waste.
      • -
      • Degrease engine by pouring in ethanol. Ethanol cancels out toxic waste.
      • -
      - -

      2017.11.10

      -

      DrSnips updated:

      -
        -
      • Added the mobile operating table. It works just like a roller bed but allows you to to surgery on it without the chance of failure like a normal roller bed. Can be made in the protolathe or exosuit fab under the misc tabs.
      • -
      • Paramedic vests, first responder jackets, CMO labcoat, and medical/paramedic spacesuits can now carry folded roller beds in their suit slot.
      • -
      -

      PJB3005 updated:

      -
        -
      • The Hyperspectral Imager now has its own unique sprite and doesn't look like a literal photocopier.
      • -
      • Xenoarch analysis machines now use a fancy NanoUI.
      • -
      • Xenoarch analysis machines have a ctrl+click shortcut for starting scanning and an alt+click shortcut for ejecting the inserted container.
      • -
      • Bunsen burners are now also toggle with alt+click.
      • -
      -

      Pathid updated:

      -
        -
      • Wired glass sheets no longer yield more cables than it takes to construct them.
      • -
      - -

      2017.11.09

      -

      DrSnips updated:

      -
        -
      • Bone gels can now be created. It requires you to mix 10u of milk and 10u of cryoxadone inside a vial.
      • -
      • Fix O veins can now be created as well. It requires you to mix 10u of bicaridine and 10u clonexadone inside a vial.
      • -
      -

      Intigracy updated:

      -
        -
      • Tripled the RNG chance of climbing a table.
      • -
      - -

      2017.11.05

      -

      Pathid updated:

      -
        -
      • Added the ability to toggle subspace transmission on mech radios.
      • -
      -

      jknpj updated:

      -
        -
      • lathes/fabricators now accept sheets from sheet inserters
      • -
      - -

      2017.11.04

      -

      jknpj updated:

      -
        -
      • Removes the duplicated sheet inserter from supply borgs
      • -
      • Bioprinters actually work again, sorry folks.
      • -
      - -

      2017.11.03

      -

      Shadowmech88 updated:

      -
        -
      • Added a beach party vault.
      • -
      • Added trophy mounts. They can be crafted from two planks of wood, and items can be mounted on them. The trophy mounts can be applied to walls, and removed from walls via a crowbar. Clicking on the trophy mount with an item will mount the item wherever you click on the trophy mount. Alt+clicking with the item in your active hand will instead auto-center it on the trophy mount.
      • -
      -

      jknpj updated:

      -
        -
      • Adds cyborg grippers! Simple manipulators that can handle a limited amount of items.
      • -
      • Adds the service gripper service borgs, allowing them to handle drinks and trash.
      • -
      • Adds the chemistry gripper to medical cyborgs, allowing them to handle beakers and blood bags.
      • -
      • Adds the sheet to supply cyborgs, allowing them to hold and insert sheets inside machinery.
      • -
      • cyborg beakers, service shaker and universal enzyme are gone.
      • -
      • The medical cyborg upgrade got more expensive and needs anomaly research 2 but it also upgrades the chemistry gripper allowing it to handle pills and pill bottles.
      • -
      • The service cyborg upgrade got more expensive and needs anomaly research 2 but it now gives a rolling pin and also upgrades the service gripper allowing it to handle food, seeds and beakers.
      • -
      • Adds the magnetic gripper for engineering cyborgs and organ gripper for medical cyborg as expensive upgrades.
      • -
      • Silicons can now use the bioprinter.
      • -
      - -

      2017.11.02

      -

      PJB3005 updated:

      -
        -
      • Bolas now automatically throw, even when not in throw mode.
      • -
      -

      unid15 updated:

      -
        -
      • The "spawn" and "create-datum" admin commands can change the new object's variables automatically after spawning it. Append any variable changes at the end of the string in curly brackets like so: spawn "/obj/item.{name="Item" ; w_class=5}"
      • -
      • Fixed some bugs with buildmode's edit mode (fixed strange behaviour when setting values to 0, fixed inability to reset object appearances). While in edit mode, middle-click any object to copy its variable.
      • -
      - -

      2017.11.01

      -

      PJB3005 updated:

      -
        -
      • clicking on NanoUI machines always makes their UI have focus, even if you already have the UI open. This makes it easier to know which window corresponds to what with say the 3 SMESes.
      • -
      -

      Shadowmech88 updated:

      -
        -
      • Added warping claws, bladed gloves which allow the user to create portals. They can be obtained as a large Xenoarchaeology artifact.
      • -
      • Punches can now have sharpness. The punches of races with claws now have 1.5 sharpness.
      • -
      -

      ShiftyRail updated:

      -
        -
      • You can now remove the beaker from a cryotube with a verb accessible in the right-click contextual menu.
      • -
      • Adds shortcuts to the cryocell. Alt+click to remove the patient within it (including yourself), Ctrl+click to remove the beaker.
      • -
      • Fixes sanity issues with knife and gun holsters.
      • -
      -

      Unknown-as-Captain updated:

      -
        -
      • Added the 'Anarchist' bundle as part of the random Syndie bundles you can get.
      • -
      • Added a very special, very rare Syndie bundle.
      • -
      • Fixed molotovs not working when hitting anything except a floor (remember to put welding fuel inside the bottle!)
      • -
      • Security PDAs can now enable an integrated hailer from the PDA menu, similar to other gadgets in PDAs.
      • -
      - -

      2017.10.31

      -

      MadmanMartian updated:

      -
        -
      • Ports chemical heating from TG but does it in a better fashion than click button receive bacon
      • -
      • Tweaks the bunsen burner. It now requires fuels of either plasma, glycerol, ethanol, or welding fuel
      • -
      • We recommend not using welder fuel unless you're desperate
      • -
      • Bunsen burners can now be built from 4 sheets of metal, and deconstructed with a wrench
      • -
      • Adds thermometers for checking temperatures of people or reagent containers. Please use with caution
      • -
      - -

      2017.10.30

      -

      DrSnips updated:

      -
        -
      • Airlocks have a screwdriver sound when opening and closing the maint panel. The sound only has a range of one so only people right next to the airlock will hear it. No jokes this time.
      • -
      -

      Jeroen52 updated:

      -
        -
      • Added the Dorf lawset, made for Dwarf Fortress.
      • -
      -

      MadmanMartian updated:

      -
        -
      • Bees no longer attack other bees or mommis
      • -
      • Adds the blood moon world event. Board up the windows and hope you have what it takes to survive.
      • -
      -

      Pathid updated:

      -
        -
      • Things taken out of xenomorph pockets are now properly removed from the contents.
      • -
      - -

      2017.10.29

      -

      CptWad updated:

      -
        -
      • Fixes various things on bagelstation
      • -
      • made the cult dungeon harder.
      • -
      -

      Emilc4h updated:

      -
        -
      • Added a filled Refigerated Blood Bank to Boxstation's Medbay, replacing the old tables used for storing bloodpacks.
      • -
      • The Sterile Equipment Crate from Cargo now includes one box of Body Bags.
      • -
      -

      MadmanMartian updated:

      -
        -
      • Syndicate IDs or voice changers now block AI camera tracking as it was causing an exploit that would yield the persons real identity
      • -
      -

      Shadowmech88 updated:

      -
        -
      • The Red Ribbon Arm and the roulette revolver can now be obtained via Xenoarchaeology.
      • -
      • Added a new vault, the skeleton den. Don't rattle their bones!
      • -
      • Added a new system by which mappers may create moving hazards that follow simple or complex courses without needing to touch any code.
      • -
      • Police tape, engineering tape, atmospherics tape, label rolls, gauze, ties, stethoscopes, bedsheets, and boiled spaghetti can now be used as restraints.
      • -
      • Diona nymphs, hulks, golems, and non-advanced-tool-users such as monkeys can now fire laser tag guns.
      • -
      • Laser tag vests can now be attached to jumpsuits, meaning any mob that can wear a jumpsuit can now play laser tag.
      • -
      - -

      2017.10.28

      -

      Pathid updated:

      -
        -
      • Delimbing a dead spider queen will no longer make it invisible.
      • -
      - -

      2017.10.24

      -

      Unknown-as-Captain updated:

      -
        -
      • Advanced Security Cameras now show cyborg cameras, just like their non-advanced counterpart.
      • -
      - -

      2017.10.22

      -

      MadmanMartian updated:

      -
        -
      • More variety added to the halloween costume crate
      • -
      • You can now bully Monkeys with disarm again
      • -
      • You can now bully Martians with disarm
      • -
      -

      Shadowmech88 updated:

      -
        -
      • Added a new spell, Doppelganger. It creates a body double of the wizard that can be used for misdirection or reinforcements. If the spell is upgraded, the doppelganger becomes able to fire magic missiles.
      • -
      • Ghosts can now interact with the holodeck control console to be transformed into a holographic person and placed in the holodeck. The player may choose to turn back into a ghost at any time, and can still enter their original body after doing so.
      • -
      • Simple animals can now be mutated with phazon. Though they cannot be injected, the phazon can be applied to them via splashing, spraying, chemical smoke, and so on.
      • -
      -

      ShiftyRail updated:

      -
        -
      • Admins can now choose how many traitors they want to create with the "Create-Antagonist" verb.
      • -
      - -

      2017.10.21

      -

      Shadowmech88 updated:

      -
        -
      • Added a new mech tailored for Engineering, the Clarke. It moves slightly faster than a normal human, can move freely in space, and can withstand temperatures up to 100,000 degrees. It also has four module slots, and a built-in air scrubber.
      • -
      • Added a new wizard spell, Fist. Casting it delivers a punch to everyone in view.
      • -
      • Mobs made invisible or practically invisible via alpha manipulation, such as via a cloaking cloak or invisible spray, can no longer be seen by HUDs or tracked by AI cameras.
      • -
      • Fixed Xenoarchaeology find picking so that recent Xenoarch additions can now be obtained in-game.
      • -
      • When a player dies as an adamantine golem, they must now wait 10 minutes before they can spawn again using an adamantine golem rune.
      • -
      -

      ShiftyRail updated:

      -
        -
      • Fixes a typo in Packed's EVA
      • -
      • Cigarettes no longer display an inappropriate message when put out.
      • -
      - -

      2017.10.20

      -

      DrSnips updated:

      -
        -
      • Airlocks now make a small screwdriver sound when you screwdriver the panel on them.
      • -
      -

      Shadowmech88 updated:

      -
        -
      • Added the exosuit-mounted Rapid Engineering Device. Formerly the mech RCD, this module is now a combination RCD/RPD/socket wrench. Use it on pipes while in RPD mode to wrench/unwrench them.
      • -
      • Added the exosuit-mounted Engineering switchtool. Contains a crowbar, screwdriver, huge welding tool, wirecutters, wrench, multitool, cable coil, T-ray scanner, atmospheric analyzer, soldering iron, and silicate sprayer.
      • -
      • Added the exosuit-mounted metal foam grenade launcher. The grenades can be detonated prematurely if you attempt to fire again before the cooldown is up.
      • -
      • Added the exosuit-mounted automatic floor tiler. If the mech passes over a lattice or metal foam floor while the tiler is active, it will place a plating down on that tile. If you pass over a plating while it is active, it will place a floor tile down on that tile.
      • -
      • Added the exosuit-mounted inflatable barrier launcher. Launches grenades which release inflatable barriers, and can switch between inflatable walls and inflatable doors. It has a separate mode for deflating the inflatable barriers.
      • -
      • Added the exosuit-mounted radiation collector array. It allows the mech's battery to be charged from nearby radiation sources such as a singularity or supermatter shard. It functions much in the same way as standard radiation collectors.
      • -
      • All mechs now provide 50% radiation shielding.
      • -
      -

      eplgr updated:

      -
        -
      • Uplink bug detector: (new!) Activating it will disable cameras nearby, plus the ones far away randomly, for some time.
      • -
      • Uplink bug detector: changed price from 3 to 5 telecrystals.
      • -
      - -

      2017.10.17

      -

      WhiteHusky updated:

      -
        -
      • Using items that check if the mind is a vampire should no longer cause a runtime if the human had no mind.
      • -
      - -

      2017.10.16

      -

      Shadowmech88 updated:

      -
        -
      • Added wizard potions to spellbooks. They can be found in a new section at the bottom, below artifacts and spell bundles.
      • -
      -

      ShiftyRail updated:

      -
        -
      • You can now extinguish people by hitting them with clothing while on help intent.
      • -
      - -

      2017.10.15

      -

      DamianX updated:

      -
        -
      • Removed the ability to craft crossbows.
      • -
      - -

      2017.10.14

      -

      DrSnips updated:

      -
        -
      • Wizards now have the choice to summon swords. Similar to the other summon spells, it will drop a sword and a set of armor for everyone.
      • -
      - -

      2017.10.13

      -

      DamianX updated:

      -
        -
      • Lanterns can now be spooked.
      • -
      -

      MadmanMartian updated:

      -
        -
      • Can now use scythes against biomass
      • -
      • Big mobs can no longer destroy invulnerable walls
      • -
      • Can now print floral data disks and genetic data disks via the protolathe
      • -
      • Can no longer stack mass drivers on a tile
      • -
      -

      Shadowmech88 updated:

      -
        -
      • The fleshshot has been repaired and re-added to borers, now verified crash-free.
      • -
      -

      ShiftyRail updated:

      -
        -
      • Fixes a bug in which a mouse could remove reagents from the deep fryer.
      • -
      - -

      2017.10.12

      -

      DeityLink updated:

      -
        -
      • Sheets of wood, wooden floor tiles, grass tiles, carpets and arcade carpets, are no longer conductive.
      • -
      -

      Unknown-as-Captain updated:

      -
        -
      • Added lasagna. Recipe is 2 flattened doughs, 2 meat, 1 cheese slice, 15 tomato juice, and 1 eggplant.
      • -
      - -

      2017.10.11

      -

      DamianX updated:

      -
        -
      • Fixed a few bugs related to flavor text.
      • -
      -

      The-Whargoul updated:

      -
        -
      • Added camera bugs and handheld tv to the item list for the detective's secure closet
      • -
      • Removed the camera bugs and handheld tv that were mapped into bagelstation to prevent duplication of these items.
      • +
      • Can now carry rollerbeds on labcoat suit storage.

      Zth-- updated:

        -
      • Now walls properly update their icon when destroyed
      • +
      • Species with no blood (slime people, for example) no longer leave blood splatters when attacked
      - -

      2017.10.08

      -

      DamianX updated:

      +

      imw-Oculus updated:

        -
      • The R-UST fuel injector no longer requires cable coils in construction. It can now be deconstructed, and its circuit board is available from the circuit imprinter.
      • -
      • The R-UST fuel injector has a new UI.
      • -
      • The R-UST room on Defficiency now provides stock parts to build a tokamak and a fuel injector
      • -
      • The R-UST tokamak no longer requires cable coils to be constructed. It can now also be deconstructed. Its circuit board is available at the circuit imprinter.
      • -
      • The gyrotron control computer can be buffered in multitools.
      • -
      -

      DelaminatingShard updated:

      -
        -
      • Fixed the areas in bagel's IAA office
      • -
      -

      Shadowmech88 updated:

      -
        -
      • The pintpointer's tracking function is now based on who pours the drink, not who is holding the glass into which the drink is poured. This means that, for example, if you pour pintpointer into a glass that is sitting on the ground, that new pintpointer will still track you. Also, as a reminder, the distance to the target is indicated by how full the mug on the pintpointer's screen is, if it has a target.
      • -
      - -

      2017.10.07

      -

      Shadowmech88 updated:

      -
        -
      • Added a new drink recipe, the pintpointer. It can be made by mixing atomic bomb and Syndicate bomb. If pintpointer is made in or poured into a glass held by someone, the display on the pintpointer will indicate its proximity to that person.
      • -
      - -

      2017.10.06

      -

      SonixApache updated:

      -
        -
      • O2 lockers no longer have N2 tanks in them
      • -
      • Every map now has N2 lockers near the trader dock, and maybe one or two in maint somewhere
      • -
      - -

      2017.10.05

      -

      DrSnips updated:

      -
        -
      • Added a spawn only version of the surgeon switchtool that has all advanced surgery tools in it.
      • -
      • Added a spawn only version of the holo switchtool that has all modules pre-enabled for it.
      • -
      • Laser scalpels in cautery mode can now have their cautery removed by a screwdriver. This is helpful for switchtool module replacement. Using the cautery on the scalpel puts them back together.
      • -
      - -

      2017.10.04

      -

      Cyadox updated:

      -
        -
      • Adds peg limbs to wooden plank crafting menu. Credit to DrSnips for the sprite
      • -
      • Peg limbs are now used to give someone - you guessed it - peg limbs instead of planks
      • -
      • Removes the ability to use planks to give someone peg limbs
      • -
      - -

      2017.10.03

      -

      DrSnips updated:

      -
        -
      • Xenoarch hand picks no longer refer to a fraction for their name and now refer to how much they dig directly in the name.
      • -
      • Xenoarch tape measures now read the depth of a wall instantly.
      • -
      -

      N3X15 updated:

      -
        -
      • Temporarily removed fleshshot from borer evolution tree while a severe server crash issue is fixed.
      • -
      -

      Shadowmech88 updated:

      -
        -
      • Envelopes can now hold all tiny items. Items which have interactions with paper/envelopes, such as pens, stamps, et cetera must be inserted via Alt+clicking the envelope with the item in your active hand.
      • -
      • Photos can no longer be attached to the front of envelopes, but can now be inserted inside envelopes.
      • -
      - -

      2017.10.02

      -

      Shadowmech88 updated:

      -
        -
      • Decoy balloons can now be scanned by the mechanic's device analyzer.
      • -
      -

      SonixApache updated:

      -
        -
      • Raised access button range to 8 (just over one screen of view range)
      • -
      - -

      2017.10.01

      -

      SonixApache updated:

      -
        -
      • unfucked windoor smartglassifying
      • -
      - -

      2017.09.30

      -

      DamianX updated:

      -
        -
      • Vending machines may display ads when selecting a product. (after 5 years of them being in the code)
      • -
      -

      Rouge-Rogue updated:

      -
        -
      • changes oxygen consumption and co2 production from breathing
      • -
      - -

      2017.09.29

      -

      DamianX updated:

      -
        -
      • Atmos monitor and AAC can now get N2O concentration from sensors.
      • -
      -

      DrSnips updated:

      -
        -
      • Bone repair surgery no longer loops.
      • -
      -

      N3X15 updated:

      -
        -
      • Nukeop leaders are a bit more obvious. They now have a title in front of their name and a special HUD icon.
      • -
      • "Nukeops are now told to follow their leaders' instructions. Failure to comply may result in being stunned or even jobbans."
      • -
      -

      Unknown-as-Captain updated:

      -
        -
      • Fixed Advanced Cameras Console only updating cameras if someone was watching the console at the time.
      • -
      • Fixed Advanced Cameras Console erasing all cameras on display if any of them were successfully updated thanks to someone watching the console.
      • -
      • Fixed Advanced Cameras Console camera updating failing most of the time even with someone watching the console, which was actually good due to the bug above.
      • -
      • Fixed Advanced Cameras Console camera updating working completely randomly based on camera position on the miracle chance that it did work AND had someone watching the console.
      • -
      • Fixed Advanced Cameras Console camera updating giving javascript errors most of the time even if successfully updated, randomly used the right code thanks to good random position, AND had someone watching the console to enable updating in the first place.
      • -
      • Fixed Advanced Cameras Console alarm lights being sometimes inverted even if it miraculously worked, randomly used the correct code, AND randomly didn't cause javascript errors, AND had someone watching the console.
      • -
      • Fixed Advanced Cameras Console javascript causing malformed HTML.
      • -
      • Fixed the zoom bar formatting in the Advanced Cameras Console and Crew Monitoring Console.
      • -
      • Fixed wrong messages in the Advanced Cameras Console.
      • -
      • Removed debug text in the Advanced Cameras Console.
      • -
      • Fixed Advanced Cameras Console letting you view out of disabled cameras, mostly thanks to not updating.
      • -
      • Fixed EMPs not disabling cameras in the Advanced Cameras Console.
      • -
      - -

      2017.09.28

      -

      Intigracy updated:

      -
        -
      • Nofruits now let you hit them with an object or alt-click to start/stop cycling. Verbs are gay but that's still an option too.
      • -
      -

      Unknown-as-Captain updated:

      -
        -
      • Implemented clickdrag actions for storage coats, same as other storage objects.
      • +
      • Fixes wrenching and unwrenching sleepers

      jknpj updated:

        -
      • Fixes exploding necromorphs exploding non-stop until it crashes the server
      • +
      • Fixes cyborgs not understanding most languages and not being able to speak sol common/gutter by default.
      • +
      • Service cyborgs now speak more languages(Slime, Vox, Golem, Grey and Clatter)
      • +
      • Fixes AIs not understanding a few newer languages.
      • +
      • Fixes librarians not getting a random language at roundstart(Except cult/xenomorph/martian).
      • +
      • Fixes babel syndrome not giving you a random(non cult/xenomorph/martian) language.
      • +
      • After freezing all AIs galactic common translation services to search for 'strange logs' NT is slowly returning them to normal operation. Report to your local Research Director if you still have any issues with your station's AI.
      -

      2017.09.26

      -

      Blithering updated:

      +

      2018.04.23

      +

      Allspice updated:

        -
      • Added a new outfit for bridge officers
      • -
      -

      Unknown-as-Captain updated:

      -
        -
      • Fixed rollerbeds stopping bullets if someone was buckled in.
      • +
      • Increase cigar and cigarette capacity by 5, hooray for explosive ciggies.
      • +
      • Comms talismans can now be used 5 times.
      -

      2017.09.25

      -

      CptWad updated:

      +

      2018.04.22

      +

      Pathid updated:

        -
      • New Chapel sprites/stuff available on bagelstation! Other stations soon(tm)
      • -
      • Bagelstations ore processors and vox shuttle should now work properly despite cursed issues
      • -
      -

      DamianX updated:

      -
        -
      • Moving or destroying an object wrenched on a connector port will now properly disconnect the two.
      • -
      • Vampires can no longer enthrall implanted people unless they have accumulated 500 blood.
      • -
      • Vampires will now be properly smitten by God when picking up the bible.
      • -
      -

      DrSnips updated:

      -
        -
      • NASA voidsuit lockers now have a pair of red magboots in them.
      • -
      • Things with hot edges can light your candles and smokes for sure now.
      • -
      -

      Duny updated:

      -
        -
      • (Deff) Added scrubbers to the research outpost. The waste pipes empty directly in space by default, the pump can be found in the atmospherics room.
      • -
      -

      HarseTheef updated:

      -
        -
      • Fixes the Captain's Greaves examination text
      • -
      -

      Kurfursten updated:

      -
        -
      • Clipboard sprites should now properly update when you do anything like take out paper, stamp paper, etc.
      • -
      • You can now click a filing cabinet with a clipboard to dump the contents within.
      • -
      -

      PromethTK11 updated:

      -
        -
      • Fixed the packed cell lockers not working propetly.
      • -
      • Aaand more packed misc. tweaks.
      • +
      • The AME now shuts down when out of fuel instead of staying in an "active" state while producing no power.
      -

      2017.09.24

      -

      Cyadox updated:

      +

      2018.04.17

      +

      Allspice updated:

        -
      • Allows you to remove peg limbs as intended
      • +
      • Double-invoked Summon Cultist rune now tells you whether each choice is dead or near you.
      -

      DrSnips updated:

      +

      Pathid updated:

        -
      • Slimes (the mob) can no longer be phazon junkies and get phazon mutations.
      • -
      • MoMMI material synth can now scan/produce more materials.
      • -
      -

      Kurfursten updated:

      -
        -
      • You can now view the supply console even without an ID, but using most of the buttons requires access.
      • -
      • The supply console now has a QM-PIN restricted permissions screen that allows you to set auto-approval, restrict orders from silicons, or require the PIN for any action.
      • -
      • Permissions screen also has a requisitions function to allow approved orders to be paid from the Cargo account.
      • -
      • Removed the long-defunct "supply tax" calculation in ordering crates, meaning you can now order as much as you have money for with no phantom tax on top
      • -
      -

      SonixApache updated:

      -
        -
      • you can now make plant-b-gone with solanine
      • -
      -

      jknpj updated:

      -
        -
      • Fixes an ancient bug that prevented big xenos and larva from being handcuffed/bodycuffed. Big xenos can break cuffs as fast as a hulk while larva take the same amount of time as other carbons.
      • -
      • Fixes an ancient bug that prevented xeno larva from being stunned.
      • -
      • Also fixes larvae hide spell.
      • -
      • Removes non-used head and chest slot from big xenos.
      • -
      • Big xenos and larva can't ventcrawl or evolve while cuffed.
      • -
      • Updates xeno inventory window.
      • +
      • Corrected a longstanding bug preventing nanopaste from being used on robotic limbs and organs.
      -

      2017.09.23

      -

      DamianX updated:

      -
        -
      • Changed the telecommunications machines construction/deconstruction/repair procedures. See wiki.
      • -
      • Fixed the telecommunications machines not degrading at high temperatures.
      • -
      • Fixed the telecommunications machines not removing the links between them upon deletion.
      • -
      • Allowed the telecommunications machines to be scanned by the device analyzer
      • -
      • Fixed bananium, uranium floors activating when they shouldn't.
      • -
      -

      Unknown-as-Captain updated:

      -
        -
      • Delivery chutes don't accept anchored items. Please report if this breaks any intended Cargo delivery methods.
      • -
      - -

      2017.09.21

      -

      DrSnips updated:

      -
        -
      • Roboticist's pda now come with the R.O.B.U.T.T. pda cartridge. Allowing you to use your pda as a cyborg analyzer when enabled.
      • -
      • Plasma saw added to the protolathe, comes in your favorite color for plasma related things. Definitely only to be used for medical purposes.
      • -
      • Bone mender added to the protolathe, it fixes broken bones completely in one step.
      • -
      - -

      2017.09.19

      -

      Commandersand updated:

      -
        -
      • Phazon mechs no longer break immersions
      • -
      +

      2018.04.16

      DeityLink updated:

        -
      • Admins now have a panel that allows them to easily control the Emergency Shuttle, its docking ports, as well as the Escape Pods.
      • +
      • Bug nets now have a limit of 100 bugs that they can hold at once.
      • +
      • Apiaries may no longer accept more than a total of 40 bees from a net.
      • +
      • When emptying a bee net, bees are split in swarms of 20 instead of 5.
      • +
      • Bee corpses now look for already existing corpses on spawn so they can add themselves as overlay. So there should no longer be more than one corpse per tile.
      • +
      +

      unid15 updated:

      +
        +
      • Admins may now select a difficulty level when loading The Hive away mission. The difficulty levels are: Hardcore (normal), Casual (33% respawns, pylons emit weak radiation), Baby's Day Out (no respawns, pylons emit temporary oxygen damage instead of rads). The difficulty level affects the final score.
      • +
      • Cockroaches will no longer tolerate getting sprayed with unstable mutagen, and WILL fight back.
      • +
      • Added cockroach matriarchs. A rare sight to behold, they're proficient at laying eggs - if fed properly.
      • +
      • Nerfed the amount of nutriment and chitin drops from small cockroaches. Larger ones, however, drop much more.
      -

      2017.09.18

      -

      DelaminatingShard updated:

      +

      2018.04.14

      +

      Intigracy updated:

        -
      • Added new fat sprites for some uniforms
      • -
      • Updated some existing fat uniforms
      • -
      • Fixes the west view for the regular CMO uniform (blue instead of green cross)
      • +
      • Fixes turning water to wine via enzyme instantly turning it into vinegar.
      -

      HarseTheef updated:

      +

      Pathid updated:

        -
      • Grammar Fixes
      • +
      • Shotgun blanks work now, when previously they could not be loaded into anything. They may be for putting on a show, but they will do some moderate burn damage to someone up close.
      • +
      • Slimes can once again be operated upon for your ghetto slime core removal needs.
      • +
      • Made disease analyser UI buttons work with more precision. If you have multiple samples of the same virus you'll no longer be forced to eject or print from all of them with each button press.
      • +
      +

      Probe1 updated:

      +
        +
      • Inaprovalines metabolism has been lowered so it lasts much longer.
      • +
      • Deffs AI Core has a newscaster in it for you rascally AIs.
      • +
      +

      code-alpha45 updated:

      +
        +
      • Restores lost feature that allowed you to talk into held radios without having the microphone on, use .l and .r to talk into the radio in the respective hand
      • +
      • The ERT radio channel is now accessed with the '.-' key
      • +
      + +

      2018.04.13

      +

      Allspice updated:

      +
        +
      • Re-adds amanatin to destroying angels and reduces potency.
      • +
      • Staves and tele scrolls now fit in gemsuit storage.
      • +
      +

      Kevak updated:

      +
        +
      • Reports indicate Local Wizard Federation Sects have received some tips from distant colleges. Beware of wayward knocking and hide your valuables. Electronic locking is no longer safe!
      • +
      + +

      2018.04.12

      +

      BurntDevil updated:

      +
        +
      • Added deff style shutters the Bagel Armory. Expanded space enough to allow proper foot traffic.
      • +
      + +

      2018.04.11

      +

      MadmanMartian updated:

      +
        +
      • Adds new traitor shoes with a toggleable knife, for the dapper IAA who wants to kick something
      • +
      +

      Pathid updated:

      +
        +
      • Fixed an error concerning how golem death was handled. Golems will now leave behind only dust instead of dust and a redundant body. Reviving golems via adamantine slime extract should work properly now. Cooldown timer for being a new golem after dying as a golem should work properly now.
      • +
      + +

      2018.04.09

      +

      Allspice updated:

      +
        +
      • Free and Summon Cultist spreads a flat amount of damage between invokers instead of dealing 10/15 damage to each.
      • +
      • Removes cult rune blood costs.

      MadmanMartian updated:

        -
      • You can now scan a severed head with a health analyzer to see if it still has a mind
      • -
      -

      SonixApache updated:

      -
        -
      • Starscreen shield generators are now built with two capacitors rather than two pico manipulators.
      • +
      • You can no longer perform CPR if you lack lungs or can not breathe.
      -

      2017.09.15

      -

      N3X15 updated:

      +

      2018.04.08

      +

      Allspice updated:

        -
      • Fixes money duplication bug in PoS terminals.
      • -
      • Fixes money spawning bug in PoS terminals caused by acceptance of negative prices.
      • -
      • Fixes PoS terminals showing wrong messages to some people when logging in.
      • +
      • Lightning spell does damage again.
      • +
      +

      MadmanMartian updated:

      +
        +
      • Things that shock you on contact (airlocks, grilles, etc.) when you're hitting them with something now take into account the items siemens_coefficient
      -

      2017.09.14

      -

      Duny updated:

      +

      2018.04.06

      +

      Pathid updated:

        -
      • (Deff) Added rollerbeds to the new medbay.
      • -
      • (Deff) Fixed research outpost disposals throwing you into the o2 miner rather than outside.
      • -
      • (Deff) Added a tile painter to the theatre backroom.
      • -
      • (Deff) Fixed costume spawners in the theatre not spawning anything.
      • -
      -

      SonixApache updated:

      -
        -
      • Added two alias commands for smartglass. The three valid commands are now toggle_transparency, toggle, and cycle.
      • +
      • Getting changed into a humanoid form by the staff of change will now tell you your species instead of "Human."
      -

      2017.09.13

      -

      Kurfursten updated:

      -
        -
      • Fridges no longer spam when bag loaded
      • -
      -

      Unknown-as-Captain updated:

      -
        -
      • Phenol kudzu now works again
      • -
      • Buffed kudzu growth speed
      • -
      • Removed maximum growth radius for kudzu vines (NOT for creeper vines, which still have a maximum radius of 4)
      • -
      - -

      2017.09.12

      -

      DeityLink updated:

      -
        -
      • Fixed Bagelstation's Elite Syndicate Shuttle being outdated.
      • -
      -

      SonixApache updated:

      -
        -
      • Added smartglass; glass that can be digitally switched between transparent and opaque. Apply a wired glass tile to a window or windoor to create it, then multitool it for setup.
      • -
      -

      Unknown-as-Captain updated:

      -
        -
      • Ctrl+arrowkeys to turn now works on vehicles and chairs.
      • -
      • You can now scoot while sitting on office chairs, and kick nearby structures to propel your chair away. Scooting backwards is faster than scooting forwards. For balance reasons, scooting is slow and is disabled by ZAS.
      • -
      - -

      2017.09.11

      -

      Duny updated:

      -
        -
      • Added the Refrigerated Blood Bank, essentially a smartfridge for blood packs.
      • -
      • (Deff) Completely reworked medbay to get rid of the cramped abomination it was before. Moved toxins a bit further away from it to make room. Removed telescience from science for more room too and gave the telepad to paramedics. Includes the new blood bank.
      • -
      - -

      2017.09.10

      +

      2018.04.05

      DrSnips updated:

        -
      • Pico manipulators now use plasma in place of the old materials.
      • +
      • Added a minor threshold to the dizziness/drunk effect so you don't experience a magnitude 10 earthquake when you only take one sip from a basic bar drink.
      • +
      • Cigarettes now come with tobacco in them for a true smoking experience.
      -

      EmiliaMcWaifushitter updated:

      +

      Pathid updated:

        -
      • Adds the ability to slide stun talismans into books which stun the next person who reads said book
      • +
      • Monkeys on methylin or in monkey mode can now do more than they could before. This includes: drag-dropping people into medical machines, folding bodybags, being converted to religions, piloting spacepods and more.
      -

      Intigracy updated:

      +

      code-alpha45 updated:

        -
      • Adminghosts no longer have to wait on the cooldown for turning on and off light switches.
      • +
      • Rechargers can now be constructed and upgraded
      • +
      • Recharger circuit board added to the soldering iron and circuit imprinter
      -

      ValkyrieSkies updated:

      + +

      2018.04.04

      +

      Allspice updated:

        -
      • Gives Vox magboots a slowdown less than standard magboots, and enables a customized version of the magboot stomp command.
      • +
      • Free Cultist splits damage between invokers like Summon Cultist instead of focusing damage on one.
      • +
      • Law update sound plays when silicons receive a law modification, as it should.
      • +
      +

      MadmanMartian updated:

      +
        +
      • Can now grab somebody and drag them with you again.
      • +
      + +

      2018.04.03

      +

      MadmanMartian updated:

      +
        +
      • Adds mushroom people. Their seeds are acquirable from either the vox outpost or xenoarch seed sites.

      jknpj updated:

        -
      • The artifact gigadrill got a new icon thanks to the russian community
      • +
      • Newly discovered 'bee gas' deemed too volatile by NT researchers and will no longer be mined.
      • +
      • Fixes xenoarch robotic remains(it's just fluffy trash) having no icon.
      • +
      • NT MoMMIs and Engineering Cyborgs appear in the Engineering Cameras Console again.
      -

      2017.09.09

      -

      Duny updated:

      +

      2018.04.02

      +

      Kurfursten updated:

        -
      • (Meta) Fixed the access requirements to open the windoors in the bridge.
      • -
      • (Meta) Added a filling cabinet to the QM's office.
      • -
      • (Meta) Reworked the IAA office/courtroom region, mainly to drastically improve IAA player quality of life, and to make the courtroom a bit more welcoming for all the future trials which we all know are never going to happen.
      • +
      • The communications computer can now be used to close off the station dock from traders, requiring an ID with HoS access or head access during a red alert. The same access is required to re-open the port.
      • +
      • Admins can now use the communications computer and all its features.
      • +
      +

      Pathid updated:

      +
        +
      • Soul-stoning a non-human mob will no longer delete all their held items.
      • +
      + +

      2018.04.01

      +

      Blithering updated:

      +
        +
      • more options for beekeepers, introduces two new kinds of bees!
      • +
      +

      Kurfursten updated:

      +
        +
      • Silicons are now clown compatible.
      • +
      +

      MadmanMartian updated:

      +
        +
      • Adds new gamemodes, to prepare for antag datums
      • +
      • Diversifies the cargo crate structure.
      • +
      • Peace, tranquility, and gondola.
      • +
      +

      imw-Oculus updated:

      +
        +
      • Adds peace (pax) implants. They steadily feed off of the host's nutrition, and prevent the host from performing violent actions. Temporarily malfunctions if the host has >=15u Methylin in their system, or is starving. Implant is destroyed upon removal from the host. They can be found in the Trader Vendor, for now.
      • +
      + +

      2018.03.28

      +

      Pathid updated:

      +
        +
      • Having a borer as a monkey or nymph will no longer prevent you from ventcrawling.
      • +
      + +

      2018.03.27

      +

      Irradiation updated:

      +
        +
      • Cryptobiolin metabolism has been reduced to 0.2
      • +
      +

      Micluc updated:

      +
        +
      • Having more than one soybean in the microwave will display 'Soybeans' instead of 'Soybeans'
      • +
      • Having more than one grape or green grape will display bunches of grapes now
      • +
      + +

      2018.03.26

      +

      Irradiation updated:

      +
        +
      • The price for the glock pack crate in cargo has been reduced to 60$.
      • +
      + +

      2018.03.25

      +

      Pathid updated:

      +
        +
      • Fixed vampires mistakenly being able to enthrall chaplains.
      • +
      +

      jknpj updated:

      +
        +
      • Makes the emagging of silicons sparky again
      • +
      + +

      2018.03.24

      +

      DrSnips updated:

      +
        +
      • Added reinforced cyborg components. They resist about a third of the damage dealt to it. They can be found in the components tab in the exosuit fab after some research. They require a variety of materials to make.
      • +
      • Added the reinforced cyborg torso. When used in the construction of a cyborg it makes the resulting cyborg come pre-installed with reinforced cyborg components. It costs the combined cost of a normal torso and all of the new reinforced components. It can be found in the components tab as well.
      • +
      • You can examine components to tell if they are damaged at all now.
      • +
      +

      MadmanMartian updated:

      +
        +
      • Adds functionality to the previously useless wires on the rnd machines, one if you pulse it, it keep creating the last thing it was told to make. The other if you attach a signaler to it, it will pulse a signal through that signaler.
      • +
      +

      ShiftyRail updated:

      +
        +
      • In ragin' mages, wizards no longer instantly die when in crit.
      • +
      • Custom religions can print their Bible at the library checkout computer, including the Chaplain's.
      • +
      + +

      2018.03.23

      +

      Irradiation updated:

      +
        +
      • Renamed the .45 glock gun & ammo crates to .380 instead.
      • +
      +

      Pathid updated:

      +
        +
      • Reworked circuit imprinter reagent storage. Imprinters now actually hold reagents in their internal beakers instead of a phantom reagent holder that was destroyed when parts were swapped.
      • +
      +

      Probe1 updated:

      +
        +
      • (Packed) Changes tech storage to have regular walls instead of Reinforced walls. Secure tech storage remains reinforced.
      • +
      + +

      2018.03.22

      +

      BurntDevil updated:

      +
        +
      • Expanded Deff's bridge to have more space for gameplay options
      • +
      +

      MadmanMartian updated:

      +
        +
      • Adds a code function to disable mesons for mappers so you can't peek at secret vaults
      • +
      +

      Pathid updated:

      +
        +
      • Fixed items carried by monkeys, nymphs, etc. displaying icons as if they were in the mob's right hand when carried in the left hand.
      • +
      • Red and yellow floorbots are now possible to build from their respective-colored toolboxes.
      • +
      +

      Probe1 updated:

      +
        +
      • Metaclubs telecomms shouldn't die on its own anymore.
      • +
      + +

      2018.03.21

      +

      Pathid updated:

      +
        +
      • Returned diona photosynthesis to how it was before a major unintended buff.
      • +
      + +

      2018.03.20

      +

      Probe1 updated:

      +
        +
      • Bagel Genetics now has a service desk and the consoles are closer together.
      • +
      + +

      2018.03.17

      +

      MadmanMartian updated:

      +
        +
      • Adds ablative plate armor
      • +
      • Adds armor shards you can attach to your jumpsuit to give you a bit more armor
      • +
      + +

      2018.03.16

      +

      DeityLink updated:

      +
        +
      • Hyperzine will now divide slowdown from worn clothing/held items (like magboots, spacesuits, or gatling guns) by 2.5 instead of completely removing it.
      • +
      + +

      2018.03.15

      +

      Commandersand updated:

      +
        +
      • Added some sounds to the sound synth the clown/mime gets
      • +
      +

      DamianX updated:

      +
        +
      • The gas mixer interface will show the english name for the direction of the nodes rather than just 1 and 2.
      • +
      +

      Pathid updated:

      +
        +
      • Fixed a long-standing bug which caused the blood vessels of a human whose blood level had dropped to zero, or close to it, to glitch out and become unusable forever.
      • +
      • Changed how disposals pipes check for fat people, so that you will stop being considered fat in the event you lose weight in transit. (Although if you're already stuck, this won't unstick you without another package to push you through.)
      • +
      • Fixed minebot AI getting stuck and having to be reset constantly.
      • +
      +

      Probe1 updated:

      +
        +
      • Bagel now has a bloodbank fridge in Medbay Storage where the bloodbags were.
      • +
      • Bagel salvage ship and vox skipjack now arrive way closer to the vox tradepost than before.
      • +
      + +

      2018.03.14

      +

      DamianX updated:

      +
        +
      • Added worn sprites for the diagnostic HUD. It's no longer invisible when worn!
      • +
      • Staff of the necromancer will no longer put dead players that became some other mob back into their old zombie.
      • +
      • Unzombified zombies will properly regain their original player.
      • +
      • Whacking zombies with a bible to deconvert them now has a cooldown.
      • +
      +

      DrSnips updated:

      +
        +
      • Added the capillary laying operation tool (CLOT). An advanced version of the fixOvein. Using the CLOT in hand will toggle it to a secondary state where it can inject biofoam during surgery (the person needs to be on a valid surgery table/surface). You need to feed it rolls of gauze to fill it with biofoam at a rate of 1u per roll. Advanced trauma kits will make 5u per kit.
      • +
      +

      Pathid updated:

      +
        +
      • Fixed circuit imprinter resource efficiency not benefiting from better manipulators.
      • +
      +

      TurboGay updated:

      +
        +
      • Altered several engineering crates (emitter, field generator, particle accelerator, shield generator, starscreen shield generator and capacitor crates) access requirements from CE to engine access.
      • +
      • Altered motorized wheelchair crate access requirements from CMO to medical access.
      • +
      +

      jknpj updated:

      +
        +
      • Fixes two 2-years old runtimes with action buttons.
      • +
      + +

      2018.03.13

      +

      Irradiation updated:

      +
        +
      • Added a blood bank fridge in metaclub medbay in place of the bloodbag table in Metaclub's medbay.
      • +
      +

      Pathid updated:

      +
        +
      • Fishtank-related circuits are now makeable from circuit imprinters.
      • +
      + +

      2018.03.12

      +

      DamianX updated:

      +
        +
      • The engineering cyborgs magnetic gripper can now interact with things it's gripping (e.g. airlock electronics, tanks). It can also hold additional items such as table/rack parts, and mountable frames (for APC, air alarms, ...)
      • +
      +

      Pathid updated:

      +
        +
      • Circuit imprinters now use much less sulfuric acid when printing any circuit that is makeable with a soldering iron.
      • +
      +

      Probe1 updated:

      +
        +
      • All research outposts now have anomaly storage containers to help you transport dangerous large artifacts.
      • +
      + +

      2018.03.11

      +

      DamianX updated:

      +
        +
      • Imidazoline will no longer heal mechanical eyes.
      • +
      • Fixed a bug that prevented ghosts from viewing body scanners and sleepers interfaces.
      • +
      • Updated the cyborg self-diagnosis UI.
      • +
      • Cyborgs and MoMMIs can now use their modules while buckled.
      • +
      +

      Probe1 updated:

      +
        +
      • Adds magnificent magboots. It's what mag stands for! Sprites by DrSnips/DrSlimes
      • +
      +

      jknpj updated:

      +
        +
      • Fixed an ancient bug that allowed the robotics console bypass hacked traitor borgs anti-termination safety
      • +
      + +

      2018.03.09

      +

      DamianX updated:

      +
        +
      • Headset encryption keys are now tiny.
      • +
      +

      MadmanMartian updated:

      +
        +
      • Emitter mirrors and splitters now mirror and or split lasers fired at them.
      • +
      +

      Pathid updated:

      +
        +
      • Fixed having to enter *custom emotes twice.
      • +
      +

      Probe1 updated:

      +
        +
      • Bagel now starts with twice as much power as it does currently. Overall, it is less than half of what it was a month ago but is now significantly higher giving engineers a longer opportunity to set up power.
      • +
      +

      jknpj updated:

      +
        +
      • Fixes living cyborgs being untippable
      • +
      • Fixes cyborgs having access to binary even if their binary communication device is broken or offline
      • +
      • Fixes *flap and *clap not working on cyborgs
      • +
      + +

      2018.03.08

      +

      Pathid updated:

      +
        +
      • Facehuggers now wander a little if they find another facehugger on their turf.
      • +
      • Toy facehuggers no longer hunt or remove equipment (although Lamarr still will). Wearing a dead, toy, or sterile facehugger no longer fools hugger AI. Huggers should no longer hug through mechs, closets or other containers.
      • +
      • Facehuggers will try to keep their victims alive by auto-connecting to any internals they had enabled. (Don't ask how they know how to do that.)
      • +
      • Cyborgs that are reset or destroyed while holding items inside storage modules will drop those items instead of deleting them.
      • +
      +

      Probe1 updated:

      +
        +
      • (Packed) Reworks packed kitchen to have more space, bartenders area to have more space. Moves MoMMI nest next to CE office. Moves maint behind the kitchen downward to atmos. Botany has been expanded by one tile and some things have been shifted around.
      • +
      • (Packed) The ERT shuttle now arrives north of the AI core instead of where the emergency shuttle docks.
      • +
      +

      jknpj updated:

      +
        +
      • MoMMIs don't start with the default flashlight/flash anymore
      • +
      +

      unid15 updated:

      +
        +
      • Fixed gremlins spamming messages when locked in cages, or when near windows
      • +
      • Gremlins can now use operating tables to perform surgery (operating them in the same way as deepfryers - using nearby items). Given their tendency to run around, the surgery can fail if they aren't restrained.
      • +
      • Changed how mimic meat works. It's also slightly toxic now.
      • +
      + +

      2018.03.07

      +

      DamianX updated:

      +
        +
      • Security armor and hardsuits can store the blunderbuss.
      • +
      +

      DrSnips updated:

      +
        +
      • Added a surgery tab to the protolathe to house all surgery related designs to cut down the clutter.
      • +
      +

      Kurfursten updated:

      +
        +
      • You can now add and remove playlists from the juke by inserting or ejecting vinyls on the settings page.
      • +
      + +

      2018.03.06

      +

      DamianX updated:

      +
        +
      • Consecutive repeated messages in chat will be squashed into one. This behaviour can be turned off in your chat preferences.
      • +
      +

      Pathid updated:

      +
        +
      • Fixed cell chargers not charging low-capacity power cells.
      • +
      • Fixed power cell lights not updating when removed from cyborg recharge stations.
      • +
      +

      imw-Oculus updated:

      +
        +
      • Display cases and fish bowls can now be built again
      • +
      + +

      2018.03.05

      +

      DrSnips updated:

      +
        +
      • Fixed magic butterflies from magic butterfly knifes not self destructing.
      • +
      +

      Kurfursten updated:

      +
        +
      • Metaclub: The Vox have moved out of the deep space base. It remains for vault hunters, but has no Trader-related items, blueprinted areas, trader shuttle, or research ferry.
      • +
      • Metaclub: Vox station replaced with one large 'mothership' that needs to be powered and can stop at 3 locations (main station, solar farm, asteroid casino).
      • +
      • There is now a "Trader Shoal" joint account. All traders know the number and PIN. It starts with 0 credits and earns no wages over time. This allows Traders to use custom vendors.
      • +
      + +

      2018.03.04

      +

      Pathid updated:

      +
        +
      • Mysterious d20s are now scannable again (by the syndie device analyzer only).
      • +
      +

      Probe1 updated:

      +
        +
      • Removes SCP-294 (The coffee machine that creates any chem in the game freely) from Bagels Asteroid. The sneaky coder cabal was here.
      • +
      + +

      2018.03.03

      +

      Anglosphere updated:

      +
        +
      • Butter
      • +
      • Liquid Butter (Reagent)
      • +
      +

      Irradiation updated:

      +
        +
      • Lowered the recipe of Saltwater to 5u Sodium Chloride/20u Water from 5u Sodium Chloride/50u Water.
      • +
      • Lowered the resulting amount of Saltwater to 20u from 50u.
      • +
      +

      Jared-Fogle updated:

      +
        +
      • Adds breathalyzers to bars and autolathes. Compete to see who's liver can withstand the most torture.
      • +
      +

      MadmanMartian updated:

      +
        +
      • Cloning console has a small number preview of how many records are currently active and saved
      • +
      +

      Probe1 updated:

      +
        +
      • Packed now has lightswitches in Mechanics and Virology. Wardens room now requires security officer access instead of general brig access that paramedics have. The brig door button now works properly.
      • +
      • Packed no longer has an electrified grille in maintenance behind Medbay. Plus a lot of minor bugfixes.
      • +
      +

      SonixApache updated:

      +
        +
      • Lifeline now heals you and replenishes a bit of blood.
      • +
      + +

      2018.03.02

      +

      DamianX updated:

      +
        +
      • All pinpointers now update four times more frequently than before.
      • +
      +

      Probe1 updated:

      +
        +
      • Fun little maze vault for you to explore.
      • +
      +

      Zth-- updated:

      +
        +
      • Fixed custom vending machines bugs: list duplication, traders not being able to manipulate them, and not linking to cargo correctly
      • +
      • Added stack support to them
      • +
      + +

      2018.03.01

      +

      DrSnips updated:

      +
        +
      • Fixed issues with switchtools' attack animations.
      • +
      +

      Irradiation updated:

      +
        +
      • Added Saltwater. It induces puking when inside the body.
      • +
      +

      MadmanMartian updated:

      +
        +
      • Adds jars for storing reagents and items in. Items in the jar are constantly touched by the reagents inside, so be careful what you mix up.
      • +
      • Internal organs in the presence of peridaxon are now healed over time.
      • +
      +

      Pathid updated:

      +
        +
      • Fixed a bug with nanite infection where it had to pass a redundant permeability check.
      • +
      • Fixed a bug where when butchering something, if you had cut out all the meat first, you were locked out of harvesting other things like skin and teeth.
      • +
      • Fixed broken vendors not being wrenchable.
      • +
      +

      RealestEstate updated:

      +
        +
      • Empty trash bags can be worn on the suit slot, and empty chicken buckets can be worn as hats. Sprites courtesy of Blithering
      • +
      +

      Zth-- updated:

      +
        +
      • Fixed borgs being immune to fire.
      • +
      • Engiborgs and mommis have protection against it.
      • +
      • New drunkness camera effect
      • +
      + +

      2018.02.28

      +

      DamianX updated:

      +
        +
      • Creating a barricade on a door won't open said door.
      • +
      • Fixed an issue with barricades on the same tile as doors preventing interaction with either of them.
      • +
      +

      Kurfursten updated:

      +
        +
      • Added docking lights.
      • +
      +

      Pathid updated:

      +
        +
      • Ventcrawlers are now able to cancel from exiting vents.
      • +
      + +

      2018.02.27

      +

      Pathid updated:

      +
        +
      • Lots of automated NPC emotes will display correctly now.
      • +
      +

      Probe1 updated:

      +
        +
      • Custom trade ship for Packed Station.
      • +
      • Skellingtons stuffed into the gibber now produce bones instead of human meat. Credit to NigglyWiggly for the sprites.
      • +
      • There are now sheets of bones that can be ground up into bone marrow.
      • +
      +

      jknpj updated:

      +
        +
      • Fixes AI starting with their cameras stuck in the roundstart cuck cube
      • +
      • Fixed ushankas having no initial icon.
      • +
      • Borgs with no MMI/Posibrain are now registered as 'Robot' in their PDAs.
      • +
      • Borgs with damaged/broken cell/actuator can't get up by themselves after being tipped.
      • +
      • Hitting a cyborg/mommi with objects that do no damage won't create sparks anymore.
      • +
      • The old "Hydrobot" icon is now available for Service Cyborgs.
      • +
      • Revived the Soviet MoMMI subtype and created a NT subtype.
      • +
      • Derelict MoMMIs now spawn as Soviet MoMMIs: They can't change their names, don't appear on cameras, see static on top of mobs and also come with an RCD, RSF(Rapid-Soviet-Fabricator), instrument synth, soap bar, plasma cutter and automatic ore loader on top of their default MoMMI loadout.
      • +
      • Roundstart/built/transformed MoMMIs are now NT MoMMIs: They start on the engineering camera network and can hear engineering radio.
      • +
      • Made the Dorf MoMMI Spawner spawn NT MoMMIs with the dorf lawset.
      • +
      • Fixed MoMMIs being able to hide their eyes using Hide when emagged.
      • +
      + +

      2018.02.26

      +

      DamianX updated:

      +
        +
      • Fixed a bug that prevented the Blind and Mutate spells from appearing in wizard spellbooks.
      • +
      • Multitooling a power cable will now show network load in addition to available power.
      • +
      • Fixed implant lockboxes and shotgun shell boxes having the wrong number of slots.
      • +
      +

      Kurfursten updated:

      +
        +
      • Fixed a bug where the hyperspace at the Mecha Graveyard would not throw you, allowing you to reach CentComm.
      • +
      • Increased the size of the Mecha Graveyard dock to accommodate the larger Defficiency cargo/research shuttle.
      • +
      +

      Tehsapper updated:

      +
        +
      • added automatic charge mode for SMES, allowing them to charge using any amount of available power that is less or equal to their input level. The old ("manual") mode is still there.
      • +
      • upgraded SMES have better capacity and max input/output.
      • +
      • SMES UI now shows if input terminal or output power cable are missing.
      • +
      • fixed being able to reconstruct SMES for free power. New SMES start out with zero charge (roundstart SMES are not affected).
      • +
      • fixed SMES not connecting to output powernet upon construction.
      • +
      • fixed SMES being able to output (and lose) charge even if there is no powernet.
      • +
      +

      jknpj updated:

      +
        +
      • The mysterious/cursed dice can't be scanned by device analysers anymore.
      • +
      + +

      2018.02.25

      +

      jknpj updated:

      +
        +
      • From now on most grenades will only be scannable the the traitor device analyser.
      • +
      • the device analyser(both normal and traitor versions) can't scan chrono grenades anymore.
      • +
      • Inflatables and smoke grenades can still be scanned by normal device analysers.
      • +
      + +

      2018.02.24

      +

      DamianX updated:

      +
        +
      • Internal Affair Agents no longer have maintenance access.
      • +
      +

      Kurfursten updated:

      +
        +
      • Fixed a bug that let people interact with sleepers from the inside, and others.
      • +
      +

      MadmanMartian updated:

      +
        +
      • Fixes the unreported bug of changeling monkeys not getting their powers
      • +
      +

      Probe1 updated:

      +
        +
      • Bagel now has a unique vox tradeship.
      • +
      +

      jknpj updated:

      +
        +
      • Fixes MoMMIs phantom action buttons
      • +
      • Fixes silicon album showing duplicated info when examining a photo
      • +
      + +

      2018.02.23

      +

      DrCelt updated:

      +
        +
      • Adds the security ushanka - it goes extremely well with the warden winter coat. (should have been in the winterjacket PR)
      • +
      • Rejiggles a couple of heat conductivities with neorussian outfits; fixes some wintercoats not properly displaying stuff under it,
      • +
      • adds ski mask (literally the same as a balaclava but a different name and can protect you from the cold)
      • +
      • changes balaclava to have the correct flags for covering the full head except eyes.

      HarseTheef updated:

        -
      • Adds the ability to shush people by using disarm intent on their mouth
      • +
      • Makes the shuttle-related sounds 25% quieter.
      • +
      +

      Kurfursten updated:

      +
        +
      • Adds the Antique Matter Synthesizer, an item engineers can buy to convert massive amounts of power into items.
      • +
      • Traders can now latejoin (up to three slots). Doing so will hurl them through space toward the outpost, so be sure you can navigate the asteroid if you choose this option!
      • +
      +

      Pathid updated:

      +
        +
      • Fixed cats magically killing mice through solid objects.
      • +
      +

      Zth-- updated:

      +
        +
      • Added a prices mode for the custom vending machine that allows you to modify the machines' prices on the fly. This feature can be toggled from the panel (where the wires are).
      • +
      • Added a insert items mode. Same as prices mode, it lets you add items by slapping them on the machine. You can also toggle this from the panel.
      • +
      • Remember that the panel can be secured by slapping your ID on the machine and linking it to your account.
      -

      2017.09.08

      -

      Durgen updated:

      -
        -
      • Adds a religion for the Chaplain from Dune
      • -
      -

      SonixApache updated:

      -
        -
      • the grenade explosion cap has been raised to 3, 5, 7
      • -
      • water/potassium explosions are now limited to 1, 2, 4
      • -
      • glycerol is now made with formic acid rather than sulphuric acid
      • -
      - -

      2017.09.07

      -

      Duny updated:

      -
        -
      • Reworked the top half of Metaclubs medbay (chemistry, paramedics, storage, hallway and reception), mainly in order to reduce the crowding near the entrance.
      • -
      • (Deff) Fixed cargo shuttle buttons opening the wrong door.
      • -
      • (Deff) Fixed Ian's delusions about the whole year being christmas.
      • -
      • (Deff) The salvage shuttle's inner airlocks now start unbolted.
      • -
      • Added the pressure regulator, an embedded controller used only to depressurize or pressurize a room on demand using vents and an airlock sensor. Can be built using an airlock controller frame and an Embedded Controller Board (Pressure Regulator).
      • -
      • (Deff) The chapel's mass driver now has a pressure regulator, with its own air canister and a passive gate linked to distro (already set up correctly) both situated in the crematorium, allowing the chaplain to quickly depressurize the room before activating the mass driver/repressurize it afterwards and therefore avoid ZAS shenanigans.
      • -
      - -

      2017.09.06

      +

      2018.02.22

      DamianX updated:

        -
      • Heaters and freezers can be correctly upgraded with the RPED.
      • -
      • Heaters and freezers update the pipe network more frequency, which should lead to more accurate readings.
      • +
      • Fixed a bug that caused only the first implant to show up on secHUDs.
      -

      PromethTK11 updated:

      +

      DrCelt updated:

        -
      • Packed chem dispensers now are working properly
      • -
      • Fixed missing pipe in Packed pod-bay
      • +
      • Lowers breathing cold air damage threshold to -53c instead of -13c
      - -

      2017.09.05

      -

      Duny updated:

      +

      Jared-Fogle updated:

        -
      • Added a pod bay to Defficiency, to the north west of Arrivals.
      • +
      • Instead of being able to move freely, action buttons can now be dragged on top of each other to swap places.
      -

      SonixApache updated:

      +

      Kurfursten updated:

        -
      • The CMO and RD now spawn with their own unique coats equipped
      • +
      • PDAs are now equipped with a multicast function. Select department message below messenger to send to an entire department at once using the new Centralized Automated Messaging Operator.
      • +
      +

      Pathid updated:

      +
        +
      • Fixed the jaunt-blocking property of holy water. Also, since holy tiles block jaunt now, the chapel won't be possible to jaunt through.
      • +
      • Cyborgs deathgasp properly on death now.
      • +
      +

      jknpj updated:

      +
        +
      • Fixes the supply cyborg automatic ore loader missing its icon
      • +
      • Removed the pre-roundstart bite/kick simulator
      - - -
      Queue @@ -167,7 +154,7 @@ Used In File(s): \code\game\mecha\mech_fabricator.dm
      {{:helper.link('Materials', 'gear',{'screen':14},(data.screen==14)?'linkOn':'', 'fixedLeft')}} - {{:helper.link('Parts', 'gear', {'screen':15},(data.screen==15)?'linkOn':'', 'fixedLeft')}} + {{:helper.link('Parts', 'gear', {'screen':15},(data.screen==15)?'linkOn':'', 'fixedLeft')}}
      @@ -218,9 +205,8 @@ Used In File(s): \code\game\mecha\mech_fabricator.dm {{for data.parts.Robot_Part}}
      - {{:helper.link(value.name, 'gear', null, null, null, 'misc')}} + {{:helper.link(value.name, 'gear', value.command2, null, null, 'misc')}} {{:helper.link(value.cost, null, null, null, null, 'cost')}} - {{:helper.link('Build', 'gear', value.command2, null, 'fixedLeft')}} {{:helper.link('Queue', 'gear', value.command1, null, 'fixedLeft')}}
      @@ -577,4 +563,4 @@ Used In File(s): \code\game\mecha\mech_fabricator.dm
      -{{/if}} \ No newline at end of file +{{/if}} diff --git a/nano/templates/flatpacker.tmpl b/nano/templates/flatpacker.tmpl index 18294144370..8d058ff3a75 100644 --- a/nano/templates/flatpacker.tmpl +++ b/nano/templates/flatpacker.tmpl @@ -1,21 +1,7 @@ - - - -
      Computer Designs @@ -129,4 +115,4 @@ Used In File(s): code\modules\research\mechanic\flatpacker.dm
      - \ No newline at end of file + diff --git a/nano/templates/genfab.tmpl b/nano/templates/genfab.tmpl index b58ab751f07..22f5e276070 100644 --- a/nano/templates/genfab.tmpl +++ b/nano/templates/genfab.tmpl @@ -3,20 +3,6 @@ Title: General Fabricator UI Used In File(s): code\modules\research\mechanic\mechanic_fabs.dm Used By Machine(s): Flatpack Fabricator, General Fabricator --> - - -
      Design List diff --git a/nano/templates/gps.tmpl b/nano/templates/gps.tmpl index 4a7bb83213b..52c55d5f801 100644 --- a/nano/templates/gps.tmpl +++ b/nano/templates/gps.tmpl @@ -24,6 +24,10 @@ Used In File(s): \code\modules\telesci\gps.dm

      Detected signals

      +
      +
      {{:data.gpstag}}
      +
      {{:data.location_text}}
      +
      {{for data.devices}}
      {{:value.tag}}
      @@ -31,4 +35,4 @@ Used In File(s): \code\modules\telesci\gps.dm
      {{empty}} No signal detected. -{{/for}} \ No newline at end of file +{{/for}} diff --git a/nano/templates/podfab.tmpl b/nano/templates/podfab.tmpl index 867ceb5b3f2..0b9a84b592e 100644 --- a/nano/templates/podfab.tmpl +++ b/nano/templates/podfab.tmpl @@ -1,9 +1,9 @@ - - - - -
      - Commands: + Commands:
      {{:helper.link('Sync', 'transferthick-e-w', {'sync':1}, null, 'fixedLeft')}}
      - +
       
      - +
      Type
      @@ -60,7 +46,7 @@ Used In File(s): \code\game\mecha\mech_fabricator.dm
      - +
       
      {{if data.screen == 1}} @@ -74,7 +60,7 @@ Used In File(s): \code\game\mecha\mech_fabricator.dm {{/if}} - + {{if data.screen == 14}}
      @@ -82,7 +68,7 @@ Used In File(s): \code\game\mecha\mech_fabricator.dm
      {{:helper.link('Materials', 'gear',{'screen':14},(data.screen==14)?'linkOn':'', 'fixedLeft')}} - {{:helper.link('Parts', 'gear', {'screen':15},(data.screen==15)?'linkOn':'', 'fixedLeft')}} + {{:helper.link('Parts', 'gear', {'screen':15},(data.screen==15)?'linkOn':'', 'fixedLeft')}}
      @@ -112,7 +98,7 @@ Used In File(s): \code\game\mecha\mech_fabricator.dm
      {{:helper.link('Materials', 'gear',{'screen':14},(data.screen==14)?'linkOn':'', 'fixedLeft')}} - {{:helper.link('Parts', 'gear', {'screen':15},(data.screen==15)?'linkOn':'', 'fixedLeft')}} + {{:helper.link('Parts', 'gear', {'screen':15},(data.screen==15)?'linkOn':'', 'fixedLeft')}}
      @@ -124,7 +110,7 @@ Used In File(s): \code\game\mecha\mech_fabricator.dm
      {{/if}} - + {{if data.screen == 2}}
      @@ -153,7 +139,7 @@ Used In File(s): \code\game\mecha\mech_fabricator.dm
      {{/if}} - + {{if data.screen == 3}}
      @@ -179,7 +165,7 @@ Used In File(s): \code\game\mecha\mech_fabricator.dm
      {{/if}} - + {{if data.screen == 4}}
      @@ -205,7 +191,7 @@ Used In File(s): \code\game\mecha\mech_fabricator.dm
      {{/if}} - + {{if data.screen == 5}}
      @@ -231,7 +217,7 @@ Used In File(s): \code\game\mecha\mech_fabricator.dm
      {{/if}} - + {{if data.screen == 6}}
      @@ -257,7 +243,7 @@ Used In File(s): \code\game\mecha\mech_fabricator.dm
      {{/if}} - + {{if data.screen == 10}}
      @@ -284,6 +270,5 @@ Used In File(s): \code\game\mecha\mech_fabricator.dm
      {{/if}} - - - \ No newline at end of file + + diff --git a/nano/templates/rev-engine.tmpl b/nano/templates/rev-engine.tmpl index 1c4e4e2c6cc..301f44e2337 100644 --- a/nano/templates/rev-engine.tmpl +++ b/nano/templates/rev-engine.tmpl @@ -1,21 +1,7 @@ - - - -
      Queue @@ -67,6 +53,5 @@ Used In File(s): code\WorkInProgress\Comic\reverse_engine.dm
      - - - \ No newline at end of file + + diff --git a/nano/templates/smes.tmpl b/nano/templates/smes.tmpl index 04b93b41480..6a0bfea17a5 100644 --- a/nano/templates/smes.tmpl +++ b/nano/templates/smes.tmpl @@ -11,12 +11,15 @@

      Input Management

      +{{if data.hasInput}}
      Charge Mode:
      - {{:helper.link('Auto', 'refresh', {'cmode' : 1}, data.chargeMode ? 'selected' : null)}}{{:helper.link('Off', 'close', {'cmode' : 1}, data.chargeMode ? null : 'selected')}} + {{:helper.link('Auto', 'refresh', {'cmode' : 'auto'}, data.chargeMode == 2 ? 'selected' : null)}} + {{:helper.link('Manual', 'refresh', {'cmode' : 'manual'}, data.chargeMode == 1 ? 'selected' : null)}} + {{:helper.link('Off', 'close', {'cmode' : 'off'}, data.chargeMode ? null : 'selected')}}   {{if data.charging}} [Charging] @@ -34,14 +37,33 @@ {{:helper.displayBar(data.chargeLevel, 0, data.chargeMax)}}
      {{:helper.link('MIN', null, {'input' : 'min'}, (data.chargeLevel > 0) ? null : 'disabled')}} - {{:helper.link('SET', null, {'input' : 'set'}, null)}} + {{:helper.link('SET', null, {'input' : 'set'}, null)}} {{:helper.link('MAX', null, {'input' : 'max'}, (data.chargeLevel < data.chargeMax) ? null : 'disabled')}}
       {{:data.chargeLevel}} W 
      +
      +
      + Input Charge: +
      +
      + {{if data.chargeLoad > 0}} + +{{:data.chargeLoad}} W + {{else}} + 0 W + {{/if}} +
      +{{else}} +
      +
      +
      No input terminal detected!
      +
      +
      +{{/if}}

      Output Management

      +{{if data.hasOutput}}
      Output Status: @@ -59,9 +81,9 @@ {{:helper.displayBar(data.outputLevel, 0, data.outputMax)}}
      {{:helper.link('MIN', null, {'output' : 'min'}, (data.outputLevel > 0) ? null : 'disabled')}} - {{:helper.link('SET', null, {'output' : 'set'}, null)}} + {{:helper.link('SET', null, {'output' : 'set'}, null)}} {{:helper.link('MAX', null, {'output' : 'max'}, (data.outputLevel < data.outputMax) ? null : 'disabled')}} -
       {{:data.outputLevel}} W 
      +
       {{:data.outputLevel}} W 
      @@ -76,4 +98,11 @@ {{:data.outputLoad}} W
      - \ No newline at end of file + +{{else}} +
      +
      +
      No output power cable connected!
      +
      +
      +{{/if}} diff --git a/nano/templates/vaporizer.tmpl b/nano/templates/vaporizer.tmpl index a7bce9a6ec2..2fe827863d6 100644 --- a/nano/templates/vaporizer.tmpl +++ b/nano/templates/vaporizer.tmpl @@ -2,19 +2,16 @@

      Preparing for Dump

      - Current Volume: + Maintenance:
      -
      Please swipe a valid identification card...
      - {{if data.unlocked}} - {{:helper.link('Dump', 'trash', {'dump_contents' : 1})}} - {{:helper.link('Force Reaction', 'transferthick-e-w', {'force' : 1})}} - {{:helper.link('Collapse', 'suitcase', {'collapse' : 1})}} - {{/if}} + {{:helper.link('Dump', 'trash', {'dump_contents' : 1})}} + {{:helper.link('Force Reaction', 'transferthick-e-w', {'force' : 1})}} {{:helper.link('Back', 'eject', {'prepare_dump' : 1})}}
      {{else}} +
      The vaporizer can be {{:data.unlocked ? "locked" : "unlocked"}} with a valid ID card.

      Machinery Status

      @@ -40,6 +37,7 @@
      {{:data.tankVolume}} units {{:helper.link('Maintenance', 'key', {'prepare_dump' : 1})}} + {{:helper.link('Collapse', 'suitcase', {'collapse' : 1})}}
      @@ -68,7 +66,7 @@
      {{:data.valveOpen ? 'Open' : 'Closed'}} - {{:helper.link('Toggle Valve', 'unlocked', {'toggle' : 1})}} + {{:helper.link('Toggle Valve', 'valveOpen', {'toggle' : 1})}}
      {{/if}} diff --git a/sound/effects/bug_hiss.ogg b/sound/effects/bug_hiss.ogg new file mode 100644 index 00000000000..2a87107d1c6 Binary files /dev/null and b/sound/effects/bug_hiss.ogg differ diff --git a/sound/effects/maprendercomplete.ogg b/sound/effects/maprendercomplete.ogg new file mode 100644 index 00000000000..a4d96fb5460 Binary files /dev/null and b/sound/effects/maprendercomplete.ogg differ diff --git a/sound/effects/yeet.ogg b/sound/effects/yeet.ogg new file mode 100644 index 00000000000..20421f39b69 Binary files /dev/null and b/sound/effects/yeet.ogg differ diff --git a/sound/items/_comma.wav b/sound/items/_comma.wav new file mode 100644 index 00000000000..a61f92854f3 Binary files /dev/null and b/sound/items/_comma.wav differ diff --git a/sound/items/allteamsrespondcode3.wav b/sound/items/allteamsrespondcode3.wav new file mode 100644 index 00000000000..e176cb6902c Binary files /dev/null and b/sound/items/allteamsrespondcode3.wav differ diff --git a/sound/items/attention.wav b/sound/items/attention.wav new file mode 100644 index 00000000000..a075abca1fb Binary files /dev/null and b/sound/items/attention.wav differ diff --git a/sound/items/die1.wav b/sound/items/die1.wav new file mode 100644 index 00000000000..1efa36cd33e Binary files /dev/null and b/sound/items/die1.wav differ diff --git a/sound/items/die2.wav b/sound/items/die2.wav new file mode 100644 index 00000000000..63b5465230f Binary files /dev/null and b/sound/items/die2.wav differ diff --git a/sound/items/die3.wav b/sound/items/die3.wav new file mode 100644 index 00000000000..b7006ddf634 Binary files /dev/null and b/sound/items/die3.wav differ diff --git a/sound/items/die4.wav b/sound/items/die4.wav new file mode 100644 index 00000000000..c4c90d06fa9 Binary files /dev/null and b/sound/items/die4.wav differ diff --git a/sound/items/eight.wav b/sound/items/eight.wav new file mode 100644 index 00000000000..c80ca16df12 Binary files /dev/null and b/sound/items/eight.wav differ diff --git a/sound/items/five.wav b/sound/items/five.wav new file mode 100644 index 00000000000..e35917d0b16 Binary files /dev/null and b/sound/items/five.wav differ diff --git a/sound/items/four.wav b/sound/items/four.wav new file mode 100644 index 00000000000..0fd7ead9544 Binary files /dev/null and b/sound/items/four.wav differ diff --git a/sound/items/investigateandreport.wav b/sound/items/investigateandreport.wav new file mode 100644 index 00000000000..e2493dac8cd Binary files /dev/null and b/sound/items/investigateandreport.wav differ diff --git a/sound/items/lostbiosignalforunit.wav b/sound/items/lostbiosignalforunit.wav new file mode 100644 index 00000000000..eb02a95bbb1 Binary files /dev/null and b/sound/items/lostbiosignalforunit.wav differ diff --git a/sound/items/nine.wav b/sound/items/nine.wav new file mode 100644 index 00000000000..7d39685dd36 Binary files /dev/null and b/sound/items/nine.wav differ diff --git a/sound/items/off2.wav b/sound/items/off2.wav new file mode 100644 index 00000000000..e84221070a5 Binary files /dev/null and b/sound/items/off2.wav differ diff --git a/sound/items/on1.wav b/sound/items/on1.wav new file mode 100644 index 00000000000..5137fa195a7 Binary files /dev/null and b/sound/items/on1.wav differ diff --git a/sound/items/on3.wav b/sound/items/on3.wav new file mode 100644 index 00000000000..97d4ebd3db4 Binary files /dev/null and b/sound/items/on3.wav differ diff --git a/sound/items/one.wav b/sound/items/one.wav new file mode 100644 index 00000000000..63a967cefac Binary files /dev/null and b/sound/items/one.wav differ diff --git a/sound/items/seven.wav b/sound/items/seven.wav new file mode 100644 index 00000000000..bfc45d8fd0b Binary files /dev/null and b/sound/items/seven.wav differ diff --git a/sound/items/six.wav b/sound/items/six.wav new file mode 100644 index 00000000000..f56b3d615c9 Binary files /dev/null and b/sound/items/six.wav differ diff --git a/sound/items/three.wav b/sound/items/three.wav new file mode 100644 index 00000000000..08081824491 Binary files /dev/null and b/sound/items/three.wav differ diff --git a/sound/items/two.wav b/sound/items/two.wav new file mode 100644 index 00000000000..3fdee6e063d Binary files /dev/null and b/sound/items/two.wav differ diff --git a/sound/items/unitdeserviced.wav b/sound/items/unitdeserviced.wav new file mode 100644 index 00000000000..7f01e1758a9 Binary files /dev/null and b/sound/items/unitdeserviced.wav differ diff --git a/sound/items/unitdownat.wav b/sound/items/unitdownat.wav new file mode 100644 index 00000000000..b5ad0d9d0a3 Binary files /dev/null and b/sound/items/unitdownat.wav differ diff --git a/sound/items/zero.wav b/sound/items/zero.wav new file mode 100644 index 00000000000..58a96944c48 Binary files /dev/null and b/sound/items/zero.wav differ diff --git a/sound/misc/clang.ogg b/sound/misc/clang.ogg new file mode 100644 index 00000000000..82c1395ed7f Binary files /dev/null and b/sound/misc/clang.ogg differ diff --git a/sound/misc/gal-o-sengen.ogg b/sound/misc/gal-o-sengen.ogg new file mode 100644 index 00000000000..af89e5d0152 Binary files /dev/null and b/sound/misc/gal-o-sengen.ogg differ diff --git a/sound/misc/soviet.ogg b/sound/misc/soviet.ogg new file mode 100644 index 00000000000..250188a8a15 Binary files /dev/null and b/sound/misc/soviet.ogg differ diff --git a/sound/music/xmas/10.ogg b/sound/music/xmas/10.ogg new file mode 100644 index 00000000000..3dc54652954 Binary files /dev/null and b/sound/music/xmas/10.ogg differ diff --git a/sound/music/xmas/11.ogg b/sound/music/xmas/11.ogg new file mode 100644 index 00000000000..eab3d51bda2 Binary files /dev/null and b/sound/music/xmas/11.ogg differ diff --git a/sound/music/xmas/2.ogg b/sound/music/xmas/2.ogg new file mode 100644 index 00000000000..4e648ad9cfe Binary files /dev/null and b/sound/music/xmas/2.ogg differ diff --git a/sound/music/xmas/3.ogg b/sound/music/xmas/3.ogg new file mode 100644 index 00000000000..4fafd80bc28 Binary files /dev/null and b/sound/music/xmas/3.ogg differ diff --git a/sound/music/xmas/4.ogg b/sound/music/xmas/4.ogg new file mode 100644 index 00000000000..177929e2e66 Binary files /dev/null and b/sound/music/xmas/4.ogg differ diff --git a/sound/music/xmas/5.ogg b/sound/music/xmas/5.ogg new file mode 100644 index 00000000000..b66f0795b11 Binary files /dev/null and b/sound/music/xmas/5.ogg differ diff --git a/sound/music/xmas/7.ogg b/sound/music/xmas/7.ogg new file mode 100644 index 00000000000..bb3621cb6c3 Binary files /dev/null and b/sound/music/xmas/7.ogg differ diff --git a/sound/music/xmas/9.ogg b/sound/music/xmas/9.ogg new file mode 100644 index 00000000000..21d8e63b1b0 Binary files /dev/null and b/sound/music/xmas/9.ogg differ diff --git a/sound/music/xmas/carol-of-the-bells.ogg b/sound/music/xmas/carol-of-the-bells.ogg new file mode 100644 index 00000000000..ac96d2fe556 Binary files /dev/null and b/sound/music/xmas/carol-of-the-bells.ogg differ diff --git a/sound/music/xmas/carolofthebells.ogg b/sound/music/xmas/carolofthebells.ogg new file mode 100644 index 00000000000..e4f431ac128 Binary files /dev/null and b/sound/music/xmas/carolofthebells.ogg differ diff --git a/sound/music/xmas/scape_santa.mid b/sound/music/xmas/scape_santa.mid new file mode 100644 index 00000000000..f4778ab5c79 Binary files /dev/null and b/sound/music/xmas/scape_santa.mid differ diff --git a/tools/gen_globals.py b/tools/gen_globals.py deleted file mode 100644 index ed167fefb14..00000000000 --- a/tools/gen_globals.py +++ /dev/null @@ -1,165 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -""" -MIT License -Copyright (c) 2016 Pieter-Jan Briers -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -""" -import argparse -import os -import sys -import re -from distutils import spawn -try: - import subprocess32 as subprocess -except ImportError: - import subprocess - - -def main(): - parser = argparse.ArgumentParser() - parser.add_argument("projectfile", help="The DME or code file to build from.") - parser.add_argument("outfile", type=argparse.FileType("w", encoding="UTF-8"), help="The DM file to dump the output to.") # yes, DM is Windows-1252. Don't care. - parser.add_argument("-d", "--dump", type=argparse.FileType("w", encoding="UTF-8"), help="An optional file to dump the raw DM output to.") - namespace = parser.parse_args() - - if not os.access(namespace.projectfile, os.F_OK): - print("Unable to access file, aborting.") - return - - tree = "" - if namespace.projectfile[-4:] == ".txt": - with open(namespace.projectfile, "r") as f: - tree = f.read() - - else: - tree = CompileFile(namespace.projectfile) - if namespace.dump: - namespace.dump.write(tree) - - variables = ParseTree(tree) - print(variables) - # Can't be bothered to fix the parser 100% so if something hates you just add it to this set to exclude it. - ignores = {} - variables = [x for x in variables if re.match("^[a-z_$][a-z_$0-9]*$", x, re.IGNORECASE) is not None and x not in ignores] - print(variables) - - code = GenCode(variables) - namespace.outfile.write(code) - - -def CompileFile(filename): - compiler_path = FindCompiler() - - return subprocess.check_output([compiler_path, "-code_tree", filename]).decode("Windows-1252", errors="replace") - - -def FindCompiler(): - compiler_path = None - - if compiler_path: - return compiler_path - - compiler_name = 'DreamMaker' - - if sys.platform == 'win32': - compiler_name = 'dm' - compiler_path = spawn.find_executable(compiler_name) - if compiler_path is None and sys.platform == 'win32': - # Attempt to look in %ProgramFiles% and %ProgramFiles(x86)% for BYOND. - for path in (os.environ['ProgramFiles'], os.environ['ProgramFiles(x86)']): - path = os.path.join(path, "BYOND", "bin", "dm.exe") - - if os.access(path, os.F_OK): - compiler_path = path - break - - if compiler_path is None: - raise IOError("Unable to locate Dream Maker compiler binary. Please ensure that it is in your PATH.") - - return compiler_path - - -def GenCode(variables): - out = "// THIS FILE IS AUTOMATICALLY CREATED BY tools/gen_globals.py\n/proc/readglobal(which)\n\tswitch(which)\n\t\t" - - for variable in variables: - out += 'if("{0}")\n\t\t\treturn global.{0};\n\t\t'.format(variable) - - out += "\n/proc/writeglobal(which, newval)\n\tswitch(which)\n\t\t" - - for variable in variables: - out += 'if("{0}")\n\t\t\tglobal.{0}=newval\n\t\t'.format(variable) - - out += "\n/var/list/_all_globals=list(" - for i, variable in enumerate(variables): - out += '"{0}"'.format(variable) - if i != len(variables) - 1: - out += "," - - out += ")" - - return out - - -def ParseTree(tree): - variables = [] - lines = tree.split("\n") - - # Keep track of the current nodes we're in. Depth is the length of this. - stack = [] - for index, line in enumerate(lines): - # Root level - node = line.split(" ", 1)[0].strip() - - indent = line.count("\t") - - # We're skipping some levels. - if indent > len(stack): - continue - - print(node, index) - - # We dropped some levels, write the current var. - if indent < len(stack): - varname = stack.pop() - if varname != "var": - variables.append(varname) - - # Reset stack to where it needs to be. - dropped_levels = len(stack) - indent - for x in range(dropped_levels): - stack.pop() - - # Hack to speed everything up by only doing vars. - if len(stack) == 0: - node = line.split(" ", 1)[0] - if node == "var": - stack.append(node) - - continue - - if len(stack) == 1 and node == "const": - continue - - if node != "": - stack.append(node) - - return variables - -if __name__ == "__main__": - main() diff --git a/tools/travis/build.py b/tools/travis/build.py index 6ceb62e0966..84fd7b07a0c 100755 --- a/tools/travis/build.py +++ b/tools/travis/build.py @@ -1,43 +1,41 @@ #!/usr/bin/env python3 -import argparse import asyncio import distutils.spawn import re import sys +import os + +import travis_utils MAP_INCLUDE_RE = re.compile(r"#include \"maps\\[a-zA-Z0-9][a-zA-Z0-9_]*\.dm\"") -ensure_future = None - -# ensure_future is new in 3.4.4, previously it was asyncio.async. -try: - ensure_future = asyncio.ensure_future -except AttributeError: - # Can't directly do asyncio.async because async is a keyword now, - # and that'd parse error on newer versions. - ensure_future = getattr(asyncio, "async") - - def main(): - parser = argparse.ArgumentParser() - parser.add_argument("dme", help="The DME file to compile.") - parser.add_argument("-M", "--mapfile", nargs="*", help="Extra map files to replace the regular map file in the DME with.") - args = parser.parse_args() + dme = os.environ.get("PROJECT_NAME") # The DME file to compile. + if not dme: + print("No project name specified.") + exit(1) + dme += ".dme" + mapfiles = os.environ.get("ALL_MAPS") # Extra map files to replace the regular map file in the DME with. + build_tests = os.environ.get("DM_UNIT_TESTS") == "1" # Whether to build unit tests or not. - dme = args.dme - if args.mapfile is not None: - # Handle map file replacement. - with open(dme, "r") as f: + if build_tests is True and mapfiles is not None: + print("Cannot run tests AND change maps at the same time, overriding ALL_MAPS.") # Because BYOND will cry "corrupt map data in world file" + mapfiles = "test_tiny" + + if build_tests is True: + with open(dme, "r+") as f: content = f.read() + f.seek(0, 0) + f.write("#define UNIT_TESTS\n" + content) - # Make string to replace the map include with. - includes = "" - for arg in args.mapfile: - includes += "#include \"maps\\\\{}.dm\"\n".format(arg) - - content = MAP_INCLUDE_RE.sub(includes, content, count=1) - dme = "{}.mdme".format(dme) - with open(dme, "w") as f: + if mapfiles is not None: + with open(dme, "r+") as f: + content = f.read() + includes = "" + for arg in mapfiles.split(): + includes += "#include \"maps\\\\{}.dm\"\n".format(arg) + content = MAP_INCLUDE_RE.sub(includes, content, count=1) + f.seek(0, 0) f.write(content) compiler = "DreamMaker" @@ -49,28 +47,10 @@ def main(): print("Unable to find DM compiler.") exit(1) - loop = asyncio.get_event_loop() - code = loop.run_until_complete(run_compiler([compiler, dme])) + loop = travis_utils.get_platform_event_loop() + code = loop.run_until_complete(travis_utils.run_with_timeout_guards([compiler, dme])) exit(code) -# DM SOMEHOW manages to go 10 minutes without logging anything nowadays. -# So... Travis kills it. -# Thanks DM. -# This repeats messages like travis_wait (which I couldn't get working) does to prevent that. -@asyncio.coroutine -def run_compiler(args): - compiler_process = yield from asyncio.create_subprocess_exec(*args) - task = ensure_future(print_timeout_guards()) - - ret = yield from compiler_process.wait() - task.cancel() - return ret - -@asyncio.coroutine -def print_timeout_guards(): - while True: - yield from asyncio.sleep(8*60) - print("Keeping Travis alive. Ignore this!") if __name__ == "__main__": main() diff --git a/tools/travis/config/config.txt b/tools/travis/config/config.txt new file mode 100644 index 00000000000..96762694e40 --- /dev/null +++ b/tools/travis/config/config.txt @@ -0,0 +1,17 @@ +ADMIN_LEGACY_SYSTEM +BAN_LEGACY_SYSTEM + +PROBABILITY EXTENDED 5 + +ALLOW_HOLIDAYS + +TICKLAG 0.33 + +TICKCOMP 0 + +SKIP_MINIMAP_GENERATION +SKIP_VAULT_GENERATION + +SHUT_UP_AUTOMATIC_DIAGNOSTIC_AND_ANNOUNCEMENT_SYSTEM + +ENABLE_WAGES diff --git a/tools/travis/run_tests.py b/tools/travis/run_tests.py new file mode 100755 index 00000000000..508131cabb2 --- /dev/null +++ b/tools/travis/run_tests.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python3 +import os +import distutils.spawn +import asyncio + +import travis_utils + +def main(): + if os.environ.get("DM_UNIT_TESTS") != "1": + print("DM_UNIT_TESTS is not set, not running tests.") + return + + dmb = os.environ.get("PROJECT_NAME") # The DMB file to run. + if not dmb: + print("No project name specified.") + exit(1) + dmb += ".dmb" + + executable = "DreamDaemon" + dreamdaemon = distutils.spawn.find_executable(executable) + if not dreamdaemon: + print("Unable to find {}.".format(executable)) + exit(1) + + loop = travis_utils.get_platform_event_loop() + code = loop.run_until_complete(travis_utils.run_with_timeout_guards([dreamdaemon, dmb, "-close", "-trusted"])) + exit(code) + +if __name__ == "__main__": + main() diff --git a/tools/travis/travis_utils.py b/tools/travis/travis_utils.py new file mode 100644 index 00000000000..0a126423034 --- /dev/null +++ b/tools/travis/travis_utils.py @@ -0,0 +1,40 @@ +import asyncio +import sys + +ensure_future = None + +# ensure_future is new in 3.4.4, previously it was asyncio.async. +try: + ensure_future = asyncio.ensure_future +except AttributeError: + # Can't directly do asyncio.async because async is a keyword now, + # and that'd parse error on newer versions. + ensure_future = getattr(asyncio, "async") + +# DM SOMEHOW manages to go 10 minutes without logging anything nowadays. +# So... Travis kills it. +# Thanks DM. +# This repeats messages like travis_wait (which I couldn't get working) does to prevent that. +@asyncio.coroutine +def run_with_timeout_guards(args): + target_process = yield from asyncio.create_subprocess_exec(*args, stderr=asyncio.subprocess.STDOUT) + task = ensure_future(print_timeout_guards()) + + ret = yield from target_process.wait() + task.cancel() + return ret + +@asyncio.coroutine +def print_timeout_guards(): + while True: + yield from asyncio.sleep(8*60) + print("Keeping Travis alive. Ignore this!") + +# Windows needs a different event loop to manage subprocesses +def get_platform_event_loop(): + if sys.platform == "win32" or sys.platform == "cygwin": + loop = asyncio.ProactorEventLoop() + asyncio.set_event_loop(loop) + return loop + else: + return asyncio.get_event_loop() diff --git a/vgstation13.dme b/vgstation13.dme index 5a940715d4a..5b617f28b83 100644 --- a/vgstation13.dme +++ b/vgstation13.dme @@ -10,18 +10,24 @@ #define DEBUG // END_PREFERENCES // BEGIN_INCLUDE +#include "__DEFINES\_macros.dm" #include "__DEFINES\accessories.dm" #include "__DEFINES\archaeo_defines.dm" #include "__DEFINES\areas.dm" #include "__DEFINES\atmos.dm" #include "__DEFINES\atmos_automation.dm" -#include "__DEFINES\atom_locking.dm" +#include "__DEFINES\atom_locking_and_control.dm" #include "__DEFINES\atoms.dm" #include "__DEFINES\cameranet.dm" +#include "__DEFINES\component_desires.dm" +#include "__DEFINES\component_signals.dm" +#include "__DEFINES\dates.dm" +#include "__DEFINES\disease2.dm" #include "__DEFINES\error_hander.dm" #include "__DEFINES\game.dm" #include "__DEFINES\global.dm" #include "__DEFINES\human.dm" +#include "__DEFINES\hydro.dm" #include "__DEFINES\invisibility_defines.dm" #include "__DEFINES\lighting.dm" #include "__DEFINES\limb_defines.dm" @@ -29,6 +35,8 @@ #include "__DEFINES\MC.dm" #include "__DEFINES\mobs.dm" #include "__DEFINES\nanoui.dm" +#include "__DEFINES\obj_defines.dm" +#include "__DEFINES\pai_software.dm" #include "__DEFINES\pipes.dm" #include "__DEFINES\planes+layers.dm" #include "__DEFINES\profile.dm" @@ -38,27 +46,22 @@ #include "__DEFINES\role_datums_defines.dm" #include "__DEFINES\security.dm" #include "__DEFINES\setup.dm" +#include "__DEFINES\silicon.dm" #include "__DEFINES\simple_animal_defines.dm" #include "__DEFINES\spell_defines.dm" #include "__DEFINES\striketeam_defines.dm" #include "__DEFINES\stylesheet.dm" #include "__DEFINES\subsystem.dm" #include "__DEFINES\tick.dm" +#include "__DEFINES\ticker.dm" +#include "__DEFINES\turfs.dm" +#include "__DEFINES\weapons.dm" #include "__DEFINES\world.dm" #include "__DEFINES\ZAS.dm" #include "code\_secrets.dm" #include "code\hub.dm" #include "code\names.dm" #include "code\world.dm" -#include "code\__DEFINES\component_desires.dm" -#include "code\__DEFINES\component_signals.dm" -#include "code\__DEFINES\disease2.dm" -#include "code\__DEFINES\hydro.dm" -#include "code\__DEFINES\mob.dm" -#include "code\__DEFINES\pai_software.dm" -#include "code\__DEFINES\spell_flags.dm" -#include "code\__DEFINES\turfs.dm" -#include "code\__HELPERS\_macros.dm" #include "code\__HELPERS\angles_dirs.dm" #include "code\__HELPERS\cmp.dm" #include "code\__HELPERS\constants.dm" @@ -67,7 +70,6 @@ #include "code\__HELPERS\game.dm" #include "code\__HELPERS\gender.dm" #include "code\__HELPERS\global_lists.dm" -#include "code\__HELPERS\globalaccess.dm" #include "code\__HELPERS\icons.dm" #include "code\__HELPERS\iteration.dm" #include "code\__HELPERS\lists.dm" @@ -178,6 +180,7 @@ #include "code\controllers\subsystem\emergency_shuttle.dm" #include "code\controllers\subsystem\event.dm" #include "code\controllers\subsystem\fast_machinery.dm" +#include "code\controllers\subsystem\fast_objects.dm" #include "code\controllers\subsystem\garbage.dm" #include "code\controllers\subsystem\htmlui.dm" #include "code\controllers\subsystem\inactivity.dm" @@ -194,7 +197,7 @@ #include "code\controllers\subsystem\vote.dm" #include "code\controllers\subsystem\init\assets.dm" #include "code\controllers\subsystem\init\finishing.dm" -#include "code\controllers\subsystem\init\genetics.dm" +#include "code\controllers\subsystem\init\humans.dm" #include "code\controllers\subsystem\init\job.dm" #include "code\controllers\subsystem\init\map.dm" #include "code\controllers\subsystem\init\minimaps.dm" @@ -204,6 +207,7 @@ #include "code\controllers\subsystem\init\xenoarch.dm" #include "code\datums\action.dm" #include "code\datums\ai_laws.dm" +#include "code\datums\alt_control.dm" #include "code\datums\browser.dm" #include "code\datums\circuits.dm" #include "code\datums\computerfiles.dm" @@ -215,7 +219,6 @@ #include "code\datums\mind.dm" #include "code\datums\mixed.dm" #include "code\datums\modules.dm" -#include "code\datums\plugin.dm" #include "code\datums\profiling.dm" #include "code\datums\recipe.dm" #include "code\datums\recruiter.dm" @@ -241,10 +244,10 @@ #include "code\datums\diseases\mega_kingston.dm" #include "code\datums\diseases\petrification.dm" #include "code\datums\diseases\pierrot_throat.dm" -#include "code\datums\diseases\plasmatoid.dm" #include "code\datums\diseases\retrovirus.dm" #include "code\datums\diseases\rhumba_beat.dm" #include "code\datums\diseases\robotic_transformation.dm" +#include "code\datums\diseases\wendigo_transformation.dm" #include "code\datums\diseases\wizarditis.dm" #include "code\datums\diseases\xeno_transformation.dm" #include "code\datums\diseases\advance\advance.dm" @@ -376,6 +379,7 @@ #include "code\game\supplyshuttle.dm" #include "code\game\area\ai_monitored.dm" #include "code\game\area\areas.dm" +#include "code\game\area\shadows.dm" #include "code\game\area\Space Station 13 areas.dm" #include "code\game\dna\dna2.dm" #include "code\game\dna\dna2_domutcheck.dm" @@ -469,6 +473,7 @@ #include "code\game\machinery\ai_slipper.dm" #include "code\game\machinery\airlock_control.dm" #include "code\game\machinery\alarm.dm" +#include "code\game\machinery\antiquemattersynth.dm" #include "code\game\machinery\atmo_control.dm" #include "code\game\machinery\autolathe.dm" #include "code\game\machinery\bees_apiary.dm" @@ -554,7 +559,6 @@ #include "code\game\machinery\camera\tracking.dm" #include "code\game\machinery\computer\ai_core.dm" #include "code\game\machinery\computer\aifixer.dm" -#include "code\game\machinery\computer\arcade.dm" #include "code\game\machinery\computer\atmos_alert.dm" #include "code\game\machinery\computer\buildandrepair.dm" #include "code\game\machinery\computer\camera.dm" @@ -583,6 +587,8 @@ #include "code\game\machinery\computer\store.dm" #include "code\game\machinery\computer\syndicate_specops_shuttle.dm" #include "code\game\machinery\computer\taxi_shuttle.dm" +#include "code\game\machinery\computer\arcade\arcade.dm" +#include "code\game\machinery\computer\arcade\arcade_game.dm" #include "code\game\machinery\doors\airlock.dm" #include "code\game\machinery\doors\airlock_electronics.dm" #include "code\game\machinery\doors\alarmlock.dm" @@ -610,6 +616,7 @@ #include "code\game\machinery\telecomms\broadcaster.dm" #include "code\game\machinery\telecomms\logbrowser.dm" #include "code\game\machinery\telecomms\machine_interactions.dm" +#include "code\game\machinery\telecomms\multicaster.dm" #include "code\game\machinery\telecomms\presets.dm" #include "code\game\machinery\telecomms\telecomunications.dm" #include "code\game\machinery\telecomms\telemonitor.dm" @@ -684,6 +691,7 @@ #include "code\game\objects\effects\spawners\gibspawner.dm" #include "code\game\objects\effects\spawners\vaultspawner.dm" #include "code\game\objects\items\airbag.dm" +#include "code\game\objects\items\anvil.dm" #include "code\game\objects\items\beacon.dm" #include "code\game\objects\items\blueprints.dm" #include "code\game\objects\items\bodybag.dm" @@ -711,12 +719,14 @@ #include "code\game\objects\items\devices\codebreaker.dm" #include "code\game\objects\items\devices\debugger.dm" #include "code\game\objects\items\devices\deskbell.dm" +#include "code\game\objects\items\devices\does_not_tip.dm" #include "code\game\objects\items\devices\flash.dm" #include "code\game\objects\items\devices\flashlight.dm" #include "code\game\objects\items\devices\fuse_bomb.dm" #include "code\game\objects\items\devices\geiger.dm" #include "code\game\objects\items\devices\handtv.dm" #include "code\game\objects\items\devices\holomap.dm" +#include "code\game\objects\items\devices\inhaler.dm" #include "code\game\objects\items\devices\instruments.dm" #include "code\game\objects\items\devices\lightreplacer.dm" #include "code\game\objects\items\devices\maracas.dm" @@ -787,6 +797,7 @@ #include "code\game\objects\items\stacks\stack.dm" #include "code\game\objects\items\stacks\stack_recipes.dm" #include "code\game\objects\items\stacks\teeth.dm" +#include "code\game\objects\items\stacks\sheets\bigstacks.dm" #include "code\game\objects\items\stacks\sheets\glass.dm" #include "code\game\objects\items\stacks\sheets\leather.dm" #include "code\game\objects\items\stacks\sheets\light.dm" @@ -897,6 +908,7 @@ #include "code\game\objects\structures\button.dm" #include "code\game\objects\structures\cage.dm" #include "code\game\objects\structures\catwalk.dm" +#include "code\game\objects\structures\clock.dm" #include "code\game\objects\structures\coatrack.dm" #include "code\game\objects\structures\curtains.dm" #include "code\game\objects\structures\displaycase.dm" @@ -1001,7 +1013,6 @@ #include "code\game\shuttles\taxi.dm" #include "code\game\shuttles\trade.dm" #include "code\game\shuttles\vox.dm" -#include "code\game\shuttles\voxresearch_shuttle.dm" #include "code\game\striketeams\emergency_response_team.dm" #include "code\game\striketeams\nanotrasen_deathsquad.dm" #include "code\game\striketeams\striketeam_datums.dm" @@ -1150,6 +1161,7 @@ #include "code\modules\clothing\clothing.dm" #include "code\modules\clothing\accessories\accessory.dm" #include "code\modules\clothing\accessories\armband.dm" +#include "code\modules\clothing\accessories\armor_shards.dm" #include "code\modules\clothing\accessories\holomap.dm" #include "code\modules\clothing\accessories\holster.dm" #include "code\modules\clothing\accessories\storage.dm" @@ -1200,6 +1212,7 @@ #include "code\modules\clothing\suits\labcoat.dm" #include "code\modules\clothing\suits\leather.dm" #include "code\modules\clothing\suits\miscellaneous.dm" +#include "code\modules\clothing\suits\plate_carrier.dm" #include "code\modules\clothing\suits\slimecoat.dm" #include "code\modules\clothing\suits\utility.dm" #include "code\modules\clothing\suits\wintercoat.dm" @@ -1473,6 +1486,7 @@ #include "code\modules\mob\living\carbon\racial_spells.dm" #include "code\modules\mob\living\carbon\shock.dm" #include "code\modules\mob\living\carbon\species.dm" +#include "code\modules\mob\living\carbon\species_powers.dm" #include "code\modules\mob\living\carbon\stripping.dm" #include "code\modules\mob\living\carbon\update_icons.dm" #include "code\modules\mob\living\carbon\alien\alien.dm" @@ -1512,12 +1526,26 @@ #include "code\modules\mob\living\carbon\brain\MMI.dm" #include "code\modules\mob\living\carbon\brain\posibrain.dm" #include "code\modules\mob\living\carbon\brain\say.dm" +#include "code\modules\mob\living\carbon\complex\combat.dm" +#include "code\modules\mob\living\carbon\complex\complex_defines.dm" +#include "code\modules\mob\living\carbon\complex\examine.dm" +#include "code\modules\mob\living\carbon\complex\inventory.dm" +#include "code\modules\mob\living\carbon\complex\life.dm" +#include "code\modules\mob\living\carbon\complex\update_icons.dm" +#include "code\modules\mob\living\carbon\complex\gondola\gondola.dm" +#include "code\modules\mob\living\carbon\complex\gondola\gondola_receive_music.dm" +#include "code\modules\mob\living\carbon\complex\martian\combat.dm" +#include "code\modules\mob\living\carbon\complex\martian\inventory.dm" +#include "code\modules\mob\living\carbon\complex\martian\life.dm" +#include "code\modules\mob\living\carbon\complex\martian\martian.dm" +#include "code\modules\mob\living\carbon\complex\martian\update_icons.dm" #include "code\modules\mob\living\carbon\human\combat.dm" #include "code\modules\mob\living\carbon\human\death.dm" #include "code\modules\mob\living\carbon\human\emote.dm" #include "code\modules\mob\living\carbon\human\examine.dm" #include "code\modules\mob\living\carbon\human\human.dm" #include "code\modules\mob\living\carbon\human\human_attackalien.dm" +#include "code\modules\mob\living\carbon\human\human_attackanimal.dm" #include "code\modules\mob\living\carbon\human\human_attackhand.dm" #include "code\modules\mob\living\carbon\human\human_attackpaw.dm" #include "code\modules\mob\living\carbon\human\human_damage.dm" @@ -1549,12 +1577,6 @@ #include "code\modules\mob\living\carbon\human\life\handle_virus_updates.dm" #include "code\modules\mob\living\carbon\human\life\life_helpers.dm" #include "code\modules\mob\living\carbon\human\plasmaman\species.dm" -#include "code\modules\mob\living\carbon\martian\combat.dm" -#include "code\modules\mob\living\carbon\martian\examine.dm" -#include "code\modules\mob\living\carbon\martian\inventory.dm" -#include "code\modules\mob\living\carbon\martian\life.dm" -#include "code\modules\mob\living\carbon\martian\martian.dm" -#include "code\modules\mob\living\carbon\martian\update_icons.dm" #include "code\modules\mob\living\carbon\monkey\combat.dm" #include "code\modules\mob\living\carbon\monkey\death.dm" #include "code\modules\mob\living\carbon\monkey\diona.dm" @@ -1587,6 +1609,7 @@ #include "code\modules\mob\living\silicon\silicon.dm" #include "code\modules\mob\living\silicon\ai\ai.dm" #include "code\modules\mob\living\silicon\ai\death.dm" +#include "code\modules\mob\living\silicon\ai\emote.dm" #include "code\modules\mob\living\silicon\ai\examine.dm" #include "code\modules\mob\living\silicon\ai\laws.dm" #include "code\modules\mob\living\silicon\ai\life.dm" @@ -1601,6 +1624,7 @@ #include "code\modules\mob\living\silicon\decoy\death.dm" #include "code\modules\mob\living\silicon\decoy\decoy.dm" #include "code\modules\mob\living\silicon\decoy\life.dm" +#include "code\modules\mob\living\silicon\mommi\cogspider.dm" #include "code\modules\mob\living\silicon\mommi\death.dm" #include "code\modules\mob\living\silicon\mommi\emote.dm" #include "code\modules\mob\living\silicon\mommi\examine.dm" @@ -1610,8 +1634,7 @@ #include "code\modules\mob\living\silicon\mommi\login.dm" #include "code\modules\mob\living\silicon\mommi\mommi.dm" #include "code\modules\mob\living\silicon\mommi\mommi_modules.dm" -#include "code\modules\mob\living\silicon\mommi\mommi_movement.dm" -#include "code\modules\mob\living\silicon\mommi\powers.dm" +#include "code\modules\mob\living\silicon\mommi\mommi_verbs.dm" #include "code\modules\mob\living\silicon\mommi\say.dm" #include "code\modules\mob\living\silicon\mommi\soviet_mommi.dm" #include "code\modules\mob\living\silicon\mommi\update_icons.dm" @@ -1637,6 +1660,7 @@ #include "code\modules\mob\living\silicon\robot\robot_items.dm" #include "code\modules\mob\living\silicon\robot\robot_modules.dm" #include "code\modules\mob\living\silicon\robot\robot_movement.dm" +#include "code\modules\mob\living\silicon\robot\robot_verbs.dm" #include "code\modules\mob\living\simple_animal\borer.dm" #include "code\modules\mob\living\simple_animal\combat.dm" #include "code\modules\mob\living\simple_animal\constructs.dm" @@ -1679,10 +1703,12 @@ #include "code\modules\mob\living\simple_animal\hostile\balloon.dm" #include "code\modules\mob\living\simple_animal\hostile\bat.dm" #include "code\modules\mob\living\simple_animal\hostile\bear.dm" +#include "code\modules\mob\living\simple_animal\hostile\bigroach.dm" #include "code\modules\mob\living\simple_animal\hostile\carp.dm" #include "code\modules\mob\living\simple_animal\hostile\crab.dm" #include "code\modules\mob\living\simple_animal\hostile\creature.dm" #include "code\modules\mob\living\simple_animal\hostile\decoy.dm" +#include "code\modules\mob\living\simple_animal\hostile\deer.dm" #include "code\modules\mob\living\simple_animal\hostile\faithless.dm" #include "code\modules\mob\living\simple_animal\hostile\frog.dm" #include "code\modules\mob\living\simple_animal\hostile\gingerbreadman.dm" @@ -1702,6 +1728,7 @@ #include "code\modules\mob\living\simple_animal\hostile\slime.dm" #include "code\modules\mob\living\simple_animal\hostile\tree.dm" #include "code\modules\mob\living\simple_animal\hostile\viscerator.dm" +#include "code\modules\mob\living\simple_animal\hostile\wendigo.dm" #include "code\modules\mob\living\simple_animal\hostile\wolf.dm" #include "code\modules\mob\living\simple_animal\hostile\giant_spider\base_spider.dm" #include "code\modules\mob\living\simple_animal\hostile\giant_spider\effects.dm" @@ -1721,6 +1748,7 @@ #include "code\modules\mob\living\simple_animal\hostile\human\pirate.dm" #include "code\modules\mob\living\simple_animal\hostile\human\russian.dm" #include "code\modules\mob\living\simple_animal\hostile\human\skellington.dm" +#include "code\modules\mob\living\simple_animal\hostile\human\surgeon.dm" #include "code\modules\mob\living\simple_animal\hostile\human\syndicate.dm" #include "code\modules\mob\living\simple_animal\hostile\human\tajaran.dm" #include "code\modules\mob\living\simple_animal\hostile\human\vox.dm" @@ -1834,6 +1862,7 @@ #include "code\modules\projectiles\ammunition\magazines.dm" #include "code\modules\projectiles\ammunition\rocket.dm" #include "code\modules\projectiles\ammunition\speedloaders.dm" +#include "code\modules\projectiles\guns\akimbo.dm" #include "code\modules\projectiles\guns\energy.dm" #include "code\modules\projectiles\guns\gun_parts.dm" #include "code\modules\projectiles\guns\hookshot.dm" @@ -1949,6 +1978,7 @@ #include "code\modules\reagents\reagent_containers\food\snacks\snackbar.dm" #include "code\modules\reagents\reagent_containers\food\snacks\eggs\roach.dm" #include "code\modules\reagents\reagent_containers\glass\bottle.dm" +#include "code\modules\reagents\reagent_containers\glass\jar.dm" #include "code\modules\reagents\reagent_containers\glass\bottle\robot.dm" #include "code\modules\reagents\reagents\vg.dm" #include "code\modules\recycling\compactor.dm" @@ -1982,6 +2012,7 @@ #include "code\modules\research\designs\robot.dm" #include "code\modules\research\designs\robotics.dm" #include "code\modules\research\designs\stock_parts.dm" +#include "code\modules\research\designs\surgery.dm" #include "code\modules\research\designs\weapons.dm" #include "code\modules\research\designs\boards\computer_command.dm" #include "code\modules\research\designs\boards\computer_engie.dm" @@ -2183,6 +2214,7 @@ #include "code\modules\spells\targeted\flesh_to_coal.dm" #include "code\modules\spells\targeted\flesh_to_stone.dm" #include "code\modules\spells\targeted\genetic.dm" +#include "code\modules\spells\targeted\grease.dm" #include "code\modules\spells\targeted\harvest.dm" #include "code\modules\spells\targeted\hypnotise.dm" #include "code\modules\spells\targeted\mind_transfer.dm" @@ -2227,6 +2259,7 @@ #include "code\modules\telesci\telepad.dm" #include "code\modules\telesci\telesci_computer.dm" #include "code\modules\tooltip\tooltip.dm" +#include "code\modules\unit_tests\_unit_tests.dm" #include "code\modules\virus2\analyser.dm" #include "code\modules\virus2\antibodies.dm" #include "code\modules\virus2\centrifuge.dm"