diff --git a/.travis.yml b/.travis.yml index b6eb33966b7..edd9984f84c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,9 +36,14 @@ script: - (num=`grep -E '\\\\(red|blue|green|black|b|i[^mc])' **/*.dm | wc -l`; echo "$num escapes (expecting ${MACRO_COUNT} or less)"; [ $num -le ${MACRO_COUNT} ]) - source $HOME/BYOND-${BYOND_MAJOR}.${BYOND_MINOR}/byond/bin/byondsetup - python tools/TagMatcher/tag-matcher.py ../.. - - echo "#define UNIT_TEST 1" > code/_unit_tests.dm + #First compile is to ensure maps are valid. + - echo "#define MAP_TEST 1" > code/_map_tests.dm - cp config/example/* config/ - DreamMaker polaris.dme + - echo "#define MAP_TEST 0" > code/_map_tests.dm + #Second compile is for the unit tests. Compiling a second time to exclude the validated maps is actually faster than waiting for startup with them compiled. + - echo "#define UNIT_TEST 1" > code/_unit_tests.dm + - DreamMaker polaris.dme - DreamDaemon polaris.dmb -invisible -trusted -core 2>&1 | tee log.txt - grep "All Unit Tests Passed" log.txt diff --git a/code/ZAS/_docs.dm b/code/ZAS/_docs.dm index 4433478e321..7b28d52688f 100644 --- a/code/ZAS/_docs.dm +++ b/code/ZAS/_docs.dm @@ -28,7 +28,7 @@ Notes for people who used ZAS before: */ //#define ZASDBG -//#define MULTIZAS +#define MULTIZAS #define AIR_BLOCKED 1 #define ZONE_BLOCKED 2 #define BLOCKED 3 diff --git a/code/__defines/damage_organs.dm b/code/__defines/damage_organs.dm index 3c0e190427b..2e14fb96eb6 100644 --- a/code/__defines/damage_organs.dm +++ b/code/__defines/damage_organs.dm @@ -6,6 +6,7 @@ #define OXY "oxy" #define CLONE "clone" #define HALLOSS "halloss" +#define ELECTROCUTE "electrocute" #define CUT "cut" #define BRUISE "bruise" @@ -56,3 +57,4 @@ #define INFECTION_LEVEL_ONE 100 #define INFECTION_LEVEL_TWO 500 #define INFECTION_LEVEL_THREE 1000 +#define INFECTION_LEVEL_MAX 1500 \ No newline at end of file diff --git a/code/__defines/map.dm b/code/__defines/map.dm index 9419415e1c1..13b1bfd7955 100644 --- a/code/__defines/map.dm +++ b/code/__defines/map.dm @@ -6,3 +6,6 @@ #define MAP_LEVEL_SEALED 0x010 // Z-levels that don't allow random transit at edge #define MAP_LEVEL_EMPTY 0x020 // Empty Z-levels that may be used for various things (currently used by bluespace jump) #define MAP_LEVEL_CONSOLES 0x040 // Z-levels available to various consoles, such as the crew monitor (when that gets coded in). Defaults to station_levels if unset. + +// Misc map defines. +#define SUBMAP_MAP_EDGE_PAD 15 // Automatically created submaps are forbidden from being this close to the main map's edge. \ No newline at end of file diff --git a/code/_map_tests.dm b/code/_map_tests.dm new file mode 100644 index 00000000000..90a4004b792 --- /dev/null +++ b/code/_map_tests.dm @@ -0,0 +1,10 @@ +/* + * + * This file is used by Travis to indicate that additional maps need to be compiled to look for errors such as missing paths. + * Do not add anything but the MAP_TEST definition here as it will be overwritten by Travis when running tests. + * + * + * Should you wish to edit set MAP_TEST to 1 like so: + * #define MAP_TEST 1 + */ +#define MAP_TEST 0 diff --git a/code/controllers/Processes/planet.dm b/code/controllers/Processes/planet.dm index 063d6d3fb9b..f9fd57f7889 100644 --- a/code/controllers/Processes/planet.dm +++ b/code/controllers/Processes/planet.dm @@ -51,9 +51,10 @@ var/datum/controller/process/planet/planet_controller = null //Redraw weather icons for(var/T in P.planet_floors) var/turf/simulated/turf = T - turf.overlays -= turf.weather_overlay + // turf.overlays -= turf.weather_overlay turf.weather_overlay = new_overlay - turf.overlays += turf.weather_overlay + // turf.overlays += turf.weather_overlay + turf.update_icon() SCHECK //Sun light needs changing diff --git a/code/controllers/master.dm b/code/controllers/master.dm index 5056e82e7b6..4ca4bebf0a8 100644 --- a/code/controllers/master.dm +++ b/code/controllers/master.dm @@ -540,10 +540,10 @@ var/datum/controller/master/Master = new() stat("Byond:", "(FPS:[world.fps]) (TickCount:[world.time/world.tick_lag]) (TickDrift:[round(Master.tickdrift,1)]([round((Master.tickdrift/(world.time/world.tick_lag))*100,0.1)]%))") stat("Master Controller:", statclick.update("(TickRate:[Master.processing]) (Iteration:[Master.iteration])")) -/datum/controller/master/StartLoadingMap() +/datum/controller/master/StartLoadingMap(var/quiet = TRUE) if(map_loading) admin_notice("Another map is attempting to be loaded before first map released lock. Delaying.", R_DEBUG) - else + else if(!quiet) admin_notice("Map is now being built. Locking.", R_DEBUG) //disallow more than one map to load at once, multithreading it will just cause race conditions @@ -557,8 +557,9 @@ var/datum/controller/master/Master = new() air_processing_killed = TRUE map_loading = TRUE -/datum/controller/master/StopLoadingMap(bounds = null) - admin_notice("Map is finished. Unlocking.", R_DEBUG) +/datum/controller/master/StopLoadingMap(var/quiet = TRUE) + if(!quiet) + admin_notice("Map is finished. Unlocking.", R_DEBUG) air_processing_killed = FALSE map_loading = FALSE for(var/S in subsystems) diff --git a/code/controllers/subsystems/creation.dm b/code/controllers/subsystems/creation.dm index e92a0447c82..d6f4b3c9c55 100644 --- a/code/controllers/subsystems/creation.dm +++ b/code/controllers/subsystems/creation.dm @@ -13,10 +13,10 @@ SUBSYSTEM_DEF(creation) var/map_loading = FALSE -/datum/controller/subsystem/creation/StartLoadingMap() +/datum/controller/subsystem/creation/StartLoadingMap(var/quiet) map_loading = TRUE -/datum/controller/subsystem/creation/StopLoadingMap() +/datum/controller/subsystem/creation/StopLoadingMap(var/quiet) map_loading = FALSE /datum/controller/subsystem/creation/proc/initialize_late_atoms() diff --git a/code/datums/autolathe/arms.dm b/code/datums/autolathe/arms.dm index a79bf09d951..c52c904bc58 100644 --- a/code/datums/autolathe/arms.dm +++ b/code/datums/autolathe/arms.dm @@ -147,17 +147,27 @@ name = "rifle magazine (5.45mm practice)" path =/obj/item/ammo_magazine/m545/practice +/datum/category_item/autolathe/arms/rifle_545_hunter + name = "rifle magazine (5.45mm hunting)" + path =/obj/item/ammo_magazine/m545/hunter + /datum/category_item/autolathe/arms/machinegun_545 name = "machinegun box magazine (5.56)" path =/obj/item/ammo_magazine/m545saw hidden = 1 +/datum/category_item/autolathe/arms/machinegun_545_hunter + name = "machinegun box magazine (5.56 hunting)" + path =/obj/item/ammo_magazine/m545saw/hunter + hidden = 1 + /////// 7.62 /datum/category_item/autolathe/arms/rifle_762 name = "rifle magazine (7.62mm)" path =/obj/item/ammo_magazine/m762 hidden = 1 + /* /datum/category_item/autolathe/arms/rifle_small_762 name = "rifle magazine (7.62mm)" @@ -298,6 +308,15 @@ name = "speedloader (.38 rubber)" path =/obj/item/ammo_magazine/s38/rubber +/datum/category_item/autolathe/arms/speedloader_45 + name = "speedloader (.45)" + path = /obj/item/ammo_magazine/s45 + hidden = 1 + +/datum/category_item/autolathe/arms/speedloader_45r + name = "speedloader (.45 rubber)" + path = /obj/item/ammo_magazine/s45/rubber + // Commented out until metal exploits with autolathe is fixed. /*/datum/category_item/autolathe/arms/pistol_clip_45 name = "ammo clip (.45)" @@ -375,6 +394,10 @@ path =/obj/item/ammo_magazine/clip/c762 hidden = 1 +/datum/category_item/autolathe/arms/rifle_clip_762_hunter + name = "ammo clip (7.62mm hunting)" + path =/obj/item/ammo_magazine/clip/c762/hunter + /datum/category_item/autolathe/arms/rifle_clip_762_practice name = "ammo clip (7.62mm practice)" path =/obj/item/ammo_magazine/clip/c762/practice diff --git a/code/datums/outfits/jobs/civilian.dm b/code/datums/outfits/jobs/civilian.dm index ab102d2a8b5..afbd7278e09 100644 --- a/code/datums/outfits/jobs/civilian.dm +++ b/code/datums/outfits/jobs/civilian.dm @@ -87,3 +87,18 @@ l_hand = /obj/item/weapon/storage/bible id_type = /obj/item/weapon/card/id/civilian/chaplain pda_type = /obj/item/device/pda/chaplain + +/decl/hierarchy/outfit/job/explorer + name = OUTFIT_JOB_NAME("Explorer") + shoes = /obj/item/clothing/shoes/boots/winter/explorer + uniform = /obj/item/clothing/under/explorer + mask = /obj/item/clothing/mask/gas/explorer + suit = /obj/item/clothing/suit/storage/hooded/explorer + gloves = /obj/item/clothing/gloves/black + l_ear = /obj/item/device/radio/headset + id_slot = slot_wear_id + id_type = /obj/item/weapon/card/id/civilian + pda_slot = slot_belt + pda_type = /obj/item/device/pda/cargo // Brown looks more rugged + r_pocket = /obj/item/device/gps/explorer + id_pda_assignment = "Explorer" diff --git a/code/datums/supplypacks/contraband.dm b/code/datums/supplypacks/contraband.dm index cbe52301dff..4ca0ae51d51 100644 --- a/code/datums/supplypacks/contraband.dm +++ b/code/datums/supplypacks/contraband.dm @@ -43,10 +43,10 @@ containername = "Moghes imports crate" contraband = 1 -/datum/supply_packs/security/bolt_rifles_mosin +/datum/supply_packs/security/bolt_rifles_militia name = "Surplus militia rifles" contains = list( - /obj/item/weapon/gun/projectile/shotgun/pump/rifle/mosin = 3, + /obj/item/weapon/gun/projectile/shotgun/pump/rifle = 3, /obj/item/ammo_magazine/clip/c762 = 6 ) cost = 50 @@ -63,11 +63,13 @@ /obj/item/clothing/suit/storage/vest/heavy/merc, /obj/item/clothing/glasses/night, /obj/item/weapon/storage/box/anti_photons, - /obj/item/ammo_magazine/clip/c12g/pellet, /obj/item/ammo_magazine/clip/c12g + /obj/item/ammo_magazine/clip/c12g/pellet, + /obj/item/ammo_magazine/clip/c12g ), list( //the doc, /obj/item/weapon/storage/firstaid/combat, - /obj/item/weapon/gun/projectile/dartgun, /obj/item/weapon/reagent_containers/hypospray, + /obj/item/weapon/gun/projectile/dartgun, + /obj/item/weapon/reagent_containers/hypospray, /obj/item/weapon/reagent_containers/glass/bottle/chloralhydrate, /obj/item/weapon/reagent_containers/glass/bottle/cyanide, /obj/item/ammo_magazine/chemdart @@ -78,7 +80,7 @@ /obj/item/weapon/storage/box/syndie_kit/demolitions, /obj/item/device/multitool/ai_detector, /obj/item/weapon/plastique, - /obj/item/weapon/storage/toolbox/syndicate + /obj/item/weapon/storage/toolbox/syndicate/powertools ), list( //the infiltrator, /obj/item/weapon/gun/projectile/silenced, diff --git a/code/datums/supplypacks/medical.dm b/code/datums/supplypacks/medical.dm index b4d51ed1b53..fef3f3e350c 100644 --- a/code/datums/supplypacks/medical.dm +++ b/code/datums/supplypacks/medical.dm @@ -119,7 +119,7 @@ /obj/item/weapon/storage/belt/medical, /obj/item/device/radio/headset/heads/cmo, /obj/item/clothing/under/rank/chief_medical_officer, - /obj/item/weapon/reagent_containers/hypospray, + /obj/item/weapon/reagent_containers/hypospray/vial, /obj/item/clothing/accessory/stethoscope, /obj/item/clothing/glasses/hud/health, /obj/item/clothing/suit/storage/toggle/labcoat/cmo, diff --git a/code/datums/supplypacks/voidsuits.dm b/code/datums/supplypacks/voidsuits.dm index 658ed5562f4..dda9aa4ed4b 100644 --- a/code/datums/supplypacks/voidsuits.dm +++ b/code/datums/supplypacks/voidsuits.dm @@ -142,7 +142,7 @@ /obj/item/clothing/shoes/magboots = 2, /obj/item/weapon/tank/oxygen = 2 ) - cost = 50 + cost = 60 containertype = "/obj/structure/closet/crate/secure" containername = "Vey-Med Medical voidsuit crate" access = access_medical_equip diff --git a/code/datums/uplink/ammunition.dm b/code/datums/uplink/ammunition.dm index d644a9eaa8c..c0b7600aad7 100644 --- a/code/datums/uplink/ammunition.dm +++ b/code/datums/uplink/ammunition.dm @@ -22,6 +22,14 @@ name = "Pistol Magazine (.45 AP)" path = /obj/item/ammo_magazine/m45/ap +/datum/uplink_item/item/ammo/s45m + name = "Speedloader (.45)" + path = /obj/item/ammo_magazine/s45 + +/datum/uplink_item/item/ammo/s45map + name = "Speedloader (.45 AP)" + path = /obj/item/ammo_magazine/s45/ap + /datum/uplink_item/item/ammo/tommymag name = "Tommygun Magazine (.45)" path = /obj/item/ammo_magazine/m45tommy diff --git a/code/datums/uplink/tools.dm b/code/datums/uplink/tools.dm index 250d4b6412b..558c922b465 100644 --- a/code/datums/uplink/tools.dm +++ b/code/datums/uplink/tools.dm @@ -9,11 +9,16 @@ item_cost = 5 path = /obj/item/device/binoculars -/datum/uplink_item/item/tools/toolbox +/datum/uplink_item/item/tools/toolbox // Leaving the basic as an option since powertools are loud. name = "Fully Loaded Toolbox" - item_cost = 10 + item_cost = 5 path = /obj/item/weapon/storage/toolbox/syndicate +/datum/uplink_item/item/tools/powertoolbox + name = "Fully Loaded Powertool Box" + item_cost = 10 + path = /obj/item/weapon/storage/toolbox/syndicate/powertools + /datum/uplink_item/item/tools/clerical name = "Morphic Clerical Kit" item_cost = 10 diff --git a/code/game/antagonist/outsider/raider.dm b/code/game/antagonist/outsider/raider.dm index 596ac1451e2..190488b38c6 100644 --- a/code/game/antagonist/outsider/raider.dm +++ b/code/game/antagonist/outsider/raider.dm @@ -85,7 +85,7 @@ var/datum/antagonist/raider/raiders /obj/item/weapon/gun/projectile/silenced, /obj/item/weapon/gun/projectile/shotgun/pump, /obj/item/weapon/gun/projectile/shotgun/pump/combat, - /obj/item/weapon/gun/projectile/shotgun/pump/rifle/mosin, + /obj/item/weapon/gun/projectile/shotgun/pump/rifle, /obj/item/weapon/gun/projectile/shotgun/doublebarrel, /obj/item/weapon/gun/projectile/shotgun/doublebarrel/pellet, /obj/item/weapon/gun/projectile/shotgun/doublebarrel/sawn, diff --git a/code/game/antagonist/station/renegade.dm b/code/game/antagonist/station/renegade.dm index d9796432c0c..08d411aec93 100644 --- a/code/game/antagonist/station/renegade.dm +++ b/code/game/antagonist/station/renegade.dm @@ -48,7 +48,7 @@ var/datum/antagonist/renegade/renegades /obj/item/weapon/gun/projectile/revolver, /obj/item/weapon/gun/projectile/derringer, /obj/item/weapon/gun/projectile/shotgun/pump, - /obj/item/weapon/gun/projectile/shotgun/pump/rifle/mosin, + /obj/item/weapon/gun/projectile/shotgun/pump/rifle, /obj/item/weapon/gun/projectile/shotgun/pump/combat, /obj/item/weapon/gun/projectile/shotgun/doublebarrel, /obj/item/weapon/gun/projectile/revolver/judge, diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index b7210f22a30..e4bd3b85ead 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -1,6 +1,6 @@ /atom/movable layer = 3 - appearance_flags = TILE_BOUND + appearance_flags = TILE_BOUND|PIXEL_SCALE var/last_move = null var/anchored = 0 // var/elevation = 2 - not used anywhere @@ -15,7 +15,7 @@ var/moved_recently = 0 var/mob/pulledby = null var/item_state = null // Used to specify the item state for the on-mob overlays. - + var/icon_scale = 1 // Used to scale icons up or down in update_transform(). var/auto_init = 1 /atom/movable/New() @@ -296,3 +296,12 @@ return null return text2num(pickweight(candidates)) +/atom/movable/proc/update_transform() + var/matrix/M = matrix() + M.Scale(icon_scale) + src.transform = M + +// Use this to set the object's scale. +/atom/movable/proc/adjust_scale(new_scale) + icon_scale = new_scale + update_transform() diff --git a/code/game/gamemodes/changeling/changeling_powers.dm b/code/game/gamemodes/changeling/changeling_powers.dm index e54eb3c1cd0..b0f19c3ba3a 100644 --- a/code/game/gamemodes/changeling/changeling_powers.dm +++ b/code/game/gamemodes/changeling/changeling_powers.dm @@ -4,6 +4,7 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E var/list/datum/absorbed_dna/absorbed_dna = list() var/list/absorbed_languages = list() // Necessary because of set_species stuff var/absorbedcount = 0 + var/lingabsorbedcount = 1 //Starts at one, because that's us var/chem_charges = 20 var/chem_recharge_rate = 0.5 var/chem_storage = 50 @@ -11,8 +12,8 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E var/changelingID = "Changeling" var/geneticdamage = 0 var/isabsorbing = 0 - var/geneticpoints = 5 - var/max_geneticpoints = 5 + var/geneticpoints = 7 + var/max_geneticpoints = 7 var/readapts = 1 var/max_readapts = 2 var/list/purchased_powers = list() @@ -22,6 +23,7 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E var/recursive_enhancement = 0 //Used to power up other abilities from the ling power with the same name. var/list/purchased_powers_history = list() //Used for round-end report, includes respec uses too. var/last_shriek = null // world.time when the ling last used a shriek. + var/next_escape = 0 // world.time when the ling can next use Escape Restraints /datum/changeling/New(var/gender=FEMALE) ..() @@ -219,7 +221,11 @@ turf/proc/AdjacentTurfsRangedSting() victims += C var/mob/living/carbon/T = input(src, "Who will we sting?") as null|anything in victims - if(!T) return + if(!T) + return + if(T.isSynthetic()) + src << "We are unable to pierce the outer shell of [T]." + return if(!(T in view(changeling.sting_range))) return if(!sting_can_reach(T, changeling.sting_range)) return if(!changeling_power(required_chems)) return diff --git a/code/game/gamemodes/changeling/powers/absorb.dm b/code/game/gamemodes/changeling/powers/absorb.dm index 396e6faf347..0af67b22ed6 100644 --- a/code/game/gamemodes/changeling/powers/absorb.dm +++ b/code/game/gamemodes/changeling/powers/absorb.dm @@ -90,16 +90,23 @@ continue absorbDNA(dna_data) changeling.absorbedcount++ + T.mind.changeling.absorbed_dna.len = 1 - changeling.geneticpoints += 5 - changeling.max_geneticpoints += 5 + // This is where lings get boosts from eating eachother + if(T.mind.changeling.lingabsorbedcount) + for(var/a = 1 to T.mind.changeling.lingabsorbedcount) + changeling.lingabsorbedcount++ + changeling.geneticpoints += 4 + changeling.max_geneticpoints += 4 + src << "We absorbed another changeling, and we grow stronger. Our genomes increase." T.mind.changeling.chem_charges = 0 T.mind.changeling.geneticpoints = -1 T.mind.changeling.max_geneticpoints = -1 //To prevent revival. T.mind.changeling.absorbedcount = 0 + T.mind.changeling.lingabsorbedcount = 0 changeling.absorbedcount++ changeling.isabsorbing = 0 diff --git a/code/game/gamemodes/changeling/powers/armblade.dm b/code/game/gamemodes/changeling/powers/armblade.dm index 139950e900b..5ab724789b4 100644 --- a/code/game/gamemodes/changeling/powers/armblade.dm +++ b/code/game/gamemodes/changeling/powers/armblade.dm @@ -134,4 +134,5 @@ /obj/item/weapon/melee/changeling/claw/greater name = "hand greatclaw" force = 20 - armor_penetration = 20 \ No newline at end of file + armor_penetration = 20 + pry = 1 \ No newline at end of file diff --git a/code/game/gamemodes/changeling/powers/escape_restraints.dm b/code/game/gamemodes/changeling/powers/escape_restraints.dm new file mode 100644 index 00000000000..4e6ed4e5cf8 --- /dev/null +++ b/code/game/gamemodes/changeling/powers/escape_restraints.dm @@ -0,0 +1,63 @@ +/datum/power/changeling/escape_restraints + name = "Escape Restraints" + desc = "We evolve more complex joints" + helptext = "We can instantly escape from most restraints and bindings, but we cannot do it often." + enhancedtext = "More frequent escapes." + ability_icon_state = "ling_escape_restraints" + genomecost = 2 + verbpath = /mob/proc/changeling_escape_restraints + +//Escape Cuffs. By design this does not escape from straight jackets +/mob/proc/changeling_escape_restraints() + set category = "Changeling" + set name = "Escape Restraints (40)" + set desc = "Removes handcuffs and legcuffs instantly." + + var/escape_cooldown = 5 MINUTES //This is used later to prevent spamming + var/mob/living/carbon/human/C = src + var/datum/changeling/changeling = changeling_power(40,0,100,CONSCIOUS) + if(!changeling) + return 0 + if(world.time < changeling.next_escape) + to_chat(src, "We are still recovering from our last escape...") + return 0 + if(!(C.handcuffed || C.legcuffed)) // No need to waste chems if there's nothing to break out of + to_chat(C, "We are are not restrained in a way we can escape...") + return 0 + + changeling.chem_charges -= 40 + + to_chat(C,"We contort our extremities and slip our cuffs.") + playsound(src, 'sound/effects/blobattack.ogg', 30, 1) + if(C.handcuffed) + var/obj/item/weapon/W = C.handcuffed + C.handcuffed = null + if(C.buckled && C.buckled.buckle_require_restraints) + C.buckled.unbuckle_mob() + C.update_inv_handcuffed() + if (C.client) + C.client.screen -= W + if(W) + W.loc = C.loc + W.dropped(C) + if(W) + W.layer = initial(W.layer) + if(C.legcuffed) + var/obj/item/weapon/W = C.legcuffed + C.legcuffed = null + C.update_inv_legcuffed() + if(C.client) + C.client.screen -= W + if(W) + W.loc = C.loc + W.dropped(C) + if(W) + W.layer = initial(W.layer) + + if(src.mind.changeling.recursive_enhancement) + escape_cooldown *= 0.5 + + changeling.next_escape = world.time + escape_cooldown //And now we set the timer + + feedback_add_details("changeling_powers","ESR") + return 1 \ No newline at end of file diff --git a/code/game/gamemodes/cult/ritual.dm b/code/game/gamemodes/cult/ritual.dm index ca1d5639e90..8db7a49255e 100644 --- a/code/game/gamemodes/cult/ritual.dm +++ b/code/game/gamemodes/cult/ritual.dm @@ -123,7 +123,7 @@ var/global/list/rnwords = list("ire","ego","nahlizet","certum","veri","jatkaa"," if(word1 == cultwords["hell"] && word2 == cultwords["join"] && word3 == cultwords["self"]) return tearreality() if(word1 == cultwords["destroy"] && word2 == cultwords["see"] && word3 == cultwords["technology"]) - return emp(src.loc,3) + return emp(src.loc,5) if(word1 == cultwords["travel"] && word2 == cultwords["blood"] && word3 == cultwords["self"]) return drain() if(word1 == cultwords["see"] && word2 == cultwords["hell"] && word3 == cultwords["join"]) diff --git a/code/game/gamemodes/gameticker.dm b/code/game/gamemodes/gameticker.dm index 38316a6c50c..0885cdef60f 100644 --- a/code/game/gamemodes/gameticker.dm +++ b/code/game/gamemodes/gameticker.dm @@ -43,10 +43,13 @@ var/global/datum/controller/gameticker/ticker 'sound/music/title2.ogg',\ 'sound/music/clouds.s3m',\ 'sound/music/space_oddity.ogg') //Ground Control to Major Tom, this song is cool, what's going on? - do + + send2mainirc("Server lobby is loaded and open at byond://[config.serverurl ? config.serverurl : (config.server ? config.server : "[world.address]:[world.port]")]") + + do pregame_timeleft = 180 - world << "Welcome to the pre-game lobby!" - world << "Please, setup your character and select ready. Game will start in [pregame_timeleft] seconds" + to_chat(world, "Welcome to the pregame lobby!") + to_chat(world, "Please set up your character and select ready. The round will start in [pregame_timeleft] seconds.") while(current_state == GAME_STATE_PREGAME) for(var/i=0, i<10, i++) sleep(1) @@ -76,7 +79,7 @@ var/global/datum/controller/gameticker/ticker if(!runnable_modes.len) current_state = GAME_STATE_PREGAME Master.SetRunLevel(RUNLEVEL_LOBBY) - world << "Unable to choose playable game mode. Reverting to pre-game lobby." + to_chat(world, "Unable to choose playable game mode. Reverting to pregame lobby.") return 0 if(secret_force_mode != "secret") src.mode = config.pick_mode(secret_force_mode) @@ -87,11 +90,11 @@ var/global/datum/controller/gameticker/ticker src.mode = gamemode_cache[pickweight(weighted_modes)] else src.mode = config.pick_mode(master_mode) - + if(!src.mode) current_state = GAME_STATE_PREGAME Master.SetRunLevel(RUNLEVEL_LOBBY) - world << "Serious error in mode setup! Reverting to pre-game lobby." + to_chat(world, "Serious error in mode setup! Reverting to pregame lobby.") //Uses setup instead of set up due to computational context. return 0 job_master.ResetOccupations() @@ -100,7 +103,7 @@ var/global/datum/controller/gameticker/ticker job_master.DivideOccupations() // Apparently important for new antagonist system to register specific job antags properly. if(!src.mode.can_start()) - world << "Unable to start [mode.name]. Not enough players, [mode.required_players] players needed. Reverting to pre-game lobby." + world << "Unable to start [mode.name]. Not enough players readied, [mode.required_players] players needed. Reverting to pregame lobby." current_state = GAME_STATE_PREGAME Master.SetRunLevel(RUNLEVEL_LOBBY) mode.fail_setup() @@ -116,13 +119,13 @@ var/global/datum/controller/gameticker/ticker tmpmodes+=M.name tmpmodes = sortList(tmpmodes) if(tmpmodes.len) - world << "Possibilities: [english_list(tmpmodes, and_text= "; ", comma_text = "; ")]" + to_chat(world, "Possibilities: [english_list(tmpmodes, and_text= "; ", comma_text = "; ")]") else src.mode.announce() setup_economy() current_state = GAME_STATE_PLAYING - create_characters() //Create player characters and transfer them + create_characters() //Create player characters and transfer them. collect_minds() equip_characters() data_core.manifest() @@ -139,7 +142,7 @@ var/global/datum/controller/gameticker/ticker //Deleting Startpoints but we need the ai point to AI-ize people later if (S.name != "AI") qdel(S) - world << "Enjoy the game!" + to_chat(world, "Enjoy the game!") world << sound('sound/AI/welcome.ogg') // Skie //Holiday Round-start stuff ~Carn Holiday_Game_Start() @@ -152,7 +155,7 @@ var/global/datum/controller/gameticker/ticker if(C.holder) admins_number++ if(admins_number == 0) - send2adminirc("Round has started with no admins online.") + send2adminirc("A round has started with no admins online.") /* supply_controller.process() //Start the supply shuttle regenerating points -- TLE // handled in scheduler master_controller.process() //Start master_controller.process() @@ -304,7 +307,7 @@ var/global/datum/controller/gameticker/ticker if(captainless) for(var/mob/M in player_list) if(!istype(M,/mob/new_player)) - M << "Colony Directorship not forced on anyone." + to_chat(M, "Colony Directorship not forced on anyone.") proc/process() @@ -340,7 +343,7 @@ var/global/datum/controller/gameticker/ticker feedback_set_details("end_proper","nuke") time_left = 1 MINUTE //No point waiting five minutes if everyone's dead. if(!delay_end) - world << "Rebooting due to destruction of station in [round(time_left/600)] minutes." + to_chat(world, "Rebooting due to destruction of station in [round(time_left/600)] minutes.") else feedback_set_details("end_proper","proper completion") time_left = round(restart_timeout) @@ -353,15 +356,15 @@ var/global/datum/controller/gameticker/ticker while(time_left > 0) if(delay_end) break - world << "Restarting in [round(time_left/600)] minute\s." + to_chat(world, "Restarting in [round(time_left/600)] minute\s.") time_left -= 1 MINUTES sleep(600) if(!delay_end) world.Reboot() else - world << "An admin has delayed the round end." + to_chat(world, "An admin has delayed the round end.") else - world << "An admin has delayed the round end." + to_chat(world, "An admin has delayed the round end.") else if (mode_finished) post_game = 1 @@ -371,7 +374,7 @@ var/global/datum/controller/gameticker/ticker //call a transfer shuttle vote spawn(50) if(!round_end_announced) // Spam Prevention. Now it should announce only once. - world << "The round has ended!" + to_chat(world, "The round has ended!") round_end_announced = 1 vote.autotransfer() @@ -385,7 +388,7 @@ var/global/datum/controller/gameticker/ticker var/turf/playerTurf = get_turf(Player) if(emergency_shuttle.departed && emergency_shuttle.evac) if(isNotAdminLevel(playerTurf.z)) - Player << "You managed to survive, but were marooned on [station_name()] as [Player.real_name]..." + Player << "You survived the round, but remained on [station_name()] as [Player.real_name]." else Player << "You managed to survive the events on [station_name()] as [Player.real_name]." else if(isAdminLevel(playerTurf.z)) @@ -426,9 +429,9 @@ var/global/datum/controller/gameticker/ticker if (!robo.connected_ai) if (robo.stat != 2) - world << "[robo.name] (Played by: [robo.key]) survived as an AI-less synthetic! Its laws were:" + world << "[robo.name] (Played by: [robo.key]) survived as an AI-less stationbound synthetic! Its laws were:" else - world << "[robo.name] (Played by: [robo.key]) was unable to survive the rigors of being a synthetic without an AI. Its laws were:" + world << "[robo.name] (Played by: [robo.key]) was unable to survive the rigors of being a stationbound synthetic without an AI. Its laws were:" if(robo) //How the hell do we lose robo between here and the world messages directly above this? robo.laws.show_laws(world) diff --git a/code/game/gamemodes/heist/heist.dm b/code/game/gamemodes/heist/heist.dm index 48f0f02bfca..65ad3d7f01f 100644 --- a/code/game/gamemodes/heist/heist.dm +++ b/code/game/gamemodes/heist/heist.dm @@ -7,8 +7,8 @@ var/global/list/obj/cortical_stacks = list() //Stacks for 'leave nobody behind' /datum/game_mode/heist name = "Heist" config_tag = "heist" - required_players = 9 - required_players_secret = 9 + required_players = 12 + required_players_secret = 12 required_enemies = 3 round_description = "An unidentified bluespace signature is approaching the station!" extended_round_description = "The Company's majority control of phoron in the system has marked the \ diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm index e85af7e82b6..f7233c1266a 100644 --- a/code/game/gamemodes/nuclear/nuclear.dm +++ b/code/game/gamemodes/nuclear/nuclear.dm @@ -12,8 +12,8 @@ var/list/nuke_disks = list() colony of sizable population and considerable wealth causes it to often be the target of various \ attempts of robbery, fraud and other malicious actions." config_tag = "mercenary" - required_players = 9 - required_players_secret = 9 + required_players = 12 + required_players_secret = 12 required_enemies = 3 end_on_antag_death = 0 var/nuke_off_station = 0 //Used for tracking if the syndies actually haul the nuke to the station diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index 39d3f739d72..850f061250d 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -440,7 +440,7 @@ datum/objective/steal "a chief medical officer's jumpsuit" = /obj/item/clothing/under/rank/chief_medical_officer, "a head of security's jumpsuit" = /obj/item/clothing/under/rank/head_of_security, "a head of personnel's jumpsuit" = /obj/item/clothing/under/rank/head_of_personnel, - "the hypospray" = /obj/item/weapon/reagent_containers/hypospray, + "the hypospray" = /obj/item/weapon/reagent_containers/hypospray/vial, "the colony director's pinpointer" = /obj/item/weapon/pinpointer, "an ablative armor vest" = /obj/item/clothing/suit/armor/laserproof, ) diff --git a/code/game/gamemodes/technomancer/spell_objs_helpers.dm b/code/game/gamemodes/technomancer/spell_objs_helpers.dm index 05afae4a3b0..f11c027566a 100644 --- a/code/game/gamemodes/technomancer/spell_objs_helpers.dm +++ b/code/game/gamemodes/technomancer/spell_objs_helpers.dm @@ -21,9 +21,14 @@ return 0 /obj/item/weapon/spell/proc/allowed_to_teleport() - if(owner && owner.z in using_map.admin_levels) - return 0 - return 1 + if(owner) + if(owner.z in using_map.admin_levels) + return FALSE + + var/turf/T = get_turf(owner) + if(T.block_tele) + return FALSE + return TRUE /obj/item/weapon/spell/proc/within_range(var/atom/target, var/max_range = 7) // Beyond 7 is off the screen. if(range(get_dist(owner, target) <= max_range)) diff --git a/code/game/gamemodes/technomancer/spells/blink.dm b/code/game/gamemodes/technomancer/spells/blink.dm index c0012c991c9..320374542de 100644 --- a/code/game/gamemodes/technomancer/spells/blink.dm +++ b/code/game/gamemodes/technomancer/spells/blink.dm @@ -23,9 +23,12 @@ var/turf/starting = get_turf(AM) var/list/targets = list() + if(starting.block_tele) + return + valid_turfs: for(var/turf/simulated/T in range(AM, range)) - if(T.density || istype(T, /turf/simulated/mineral)) //Don't blink to vacuum or a wall + if(T.density || T.block_tele || istype(T, /turf/simulated/mineral)) //Don't blink to vacuum or a wall continue for(var/atom/movable/stuff in T.contents) if(stuff.density) @@ -54,7 +57,10 @@ if(istype(hit_atom, /atom/movable)) var/atom/movable/AM = hit_atom if(!within_range(AM)) - user << "\The [AM] is too far away to blink." + to_chat(user, "\The [AM] is too far away to blink.") + return + if(!allowed_to_teleport()) + to_chat(user, "Teleportation doesn't seem to work here.") return if(pay_energy(400)) if(check_for_scepter()) @@ -67,6 +73,9 @@ to_chat(user, "You need more energy to blink [AM] away!") /obj/item/weapon/spell/blink/on_use_cast(mob/user) + if(!allowed_to_teleport()) + to_chat(user, "Teleportation doesn't seem to work here.") + return if(pay_energy(200)) if(check_for_scepter()) safe_blink(user, calculate_spell_power(10)) @@ -80,6 +89,9 @@ /obj/item/weapon/spell/blink/on_melee_cast(atom/hit_atom, mob/living/user, def_zone) if(istype(hit_atom, /atom/movable)) var/atom/movable/AM = hit_atom + if(!allowed_to_teleport()) + to_chat(user, "Teleportation doesn't seem to work here.") + return if(pay_energy(300)) visible_message("\The [user] reaches out towards \the [AM] with a glowing hand.") if(check_for_scepter()) diff --git a/code/game/gamemodes/technomancer/spells/mark_recall.dm b/code/game/gamemodes/technomancer/spells/mark_recall.dm index e47b62c031b..306de85043c 100644 --- a/code/game/gamemodes/technomancer/spells/mark_recall.dm +++ b/code/game/gamemodes/technomancer/spells/mark_recall.dm @@ -68,6 +68,9 @@ user << "There's no Mark!" return 0 else + if(!allowed_to_teleport()) + to_chat(user, "Teleportation doesn't seem to work here.") + return visible_message("\The [user] starts glowing!") var/light_intensity = 2 var/time_left = 3 diff --git a/code/game/gamemodes/technomancer/spells/passwall.dm b/code/game/gamemodes/technomancer/spells/passwall.dm index e786134b4c0..fa7b5f34b99 100644 --- a/code/game/gamemodes/technomancer/spells/passwall.dm +++ b/code/game/gamemodes/technomancer/spells/passwall.dm @@ -46,6 +46,9 @@ checked_turf = get_step(checked_turf, direction) //Advance in the given direction total_cost += check_for_scepter() ? 400 : 800 //Phasing through matter's expensive, you know. i-- + if(checked_turf.block_tele) // The fun ends here. + break + if(!checked_turf.density) //If we found a destination (a non-dense turf), then we can stop. var/dense_objs_on_turf = 0 for(var/atom/movable/stuff in checked_turf.contents) //Make sure nothing dense is where we want to go, like an airlock or window. diff --git a/code/game/jobs/access_datum.dm b/code/game/jobs/access_datum.dm index 322a71f7d4f..b63662cd868 100644 --- a/code/game/jobs/access_datum.dm +++ b/code/game/jobs/access_datum.dm @@ -462,3 +462,9 @@ /datum/access/trader id = access_trader access_type = ACCESS_TYPE_PRIVATE + +/var/const/access_alien = 300 // For things like crashed ships. +/datum/access/alien + id = access_alien + desc = "#%_^&*@!" + access_type = ACCESS_TYPE_PRIVATE diff --git a/code/game/jobs/job_controller.dm b/code/game/jobs/job_controller.dm index f74b1d6185f..a0ac2f646cb 100644 --- a/code/game/jobs/job_controller.dm +++ b/code/game/jobs/job_controller.dm @@ -74,7 +74,7 @@ var/global/datum/controller/occupations/job_master proc/FreeRole(var/rank) //making additional slot on the fly var/datum/job/job = GetJob(rank) - if(job && job.current_positions >= job.total_positions && job.total_positions != -1) + if(job && job.total_positions != -1) job.total_positions++ return 1 return 0 diff --git a/code/game/machinery/camera/tracking.dm b/code/game/machinery/camera/tracking.dm index 1aadf981c4f..4f6b7df94f1 100644 --- a/code/game/machinery/camera/tracking.dm +++ b/code/game/machinery/camera/tracking.dm @@ -2,7 +2,7 @@ #define TRACKING_NO_COVERAGE 1 #define TRACKING_TERMINATE 2 -/mob/living/silicon/ai/var/max_locations = 10 +/mob/living/silicon/ai/var/max_locations = 30 /mob/living/silicon/ai/var/stored_locations[0] /proc/InvalidPlayerTurf(turf/T as turf) diff --git a/code/game/machinery/computer/robot.dm b/code/game/machinery/computer/robot.dm index 4d29a56b89a..f91ac2b677f 100644 --- a/code/game/machinery/computer/robot.dm +++ b/code/game/machinery/computer/robot.dm @@ -37,6 +37,7 @@ // Locks or unlocks the cyborg if (href_list["lockdown"]) var/mob/living/silicon/robot/target = get_cyborg_by_name(href_list["lockdown"]) + var/failmsg = "" if(!target || !istype(target)) return @@ -57,11 +58,19 @@ var/istraitor = target.mind.special_role if (istraitor) + failmsg = "failed (target is traitor) " target.lockcharge = !target.lockcharge if (target.lockcharge) - target << "Someone tried to lock you down!" + to_chat(target, "Someone tried to lock you down!") else - target << "Someone tried to lift your lockdown!" + to_chat(target, "Someone tried to lift your lockdown!") + else if (target.emagged) + failmsg = "failed (target is hacked) " + target.lockcharge = !target.lockcharge + if (target.lockcharge) + to_chat(target, "Someone tried to lock you down!") + else + to_chat(target, "Someone tried to lift your lockdown!") else target.canmove = !target.canmove target.lockcharge = !target.canmove //when canmove is 1, lockcharge should be 0 @@ -70,7 +79,7 @@ target << "You have been locked down!" else target << "Your lockdown has been lifted!" - message_admins("[key_name_admin(usr)] [istraitor ? "failed (target is traitor) " : ""][target.lockcharge ? "lockdown" : "release"] on [target.name]!") + message_admins("[key_name_admin(usr)] [failmsg][target.lockcharge ? "lockdown" : "release"] on [target.name]!") log_game("[key_name(usr)] attempted to [target.lockcharge ? "lockdown" : "release"] [target.name] on the robotics console!") diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index acd7a446c19..87da7c7ac68 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -127,6 +127,36 @@ icon = 'icons/obj/doors/Doormaint.dmi' assembly_type = /obj/structure/door_assembly/door_assembly_mai +/obj/machinery/door/airlock/maintenance/cargo + icon = 'icons/obj/doors/Doormaint_cargo.dmi' + req_one_access = list(access_cargo) + +/obj/machinery/door/airlock/maintenance/command + icon = 'icons/obj/doors/Doormaint_command.dmi' + req_one_access = list(access_heads) + +/obj/machinery/door/airlock/maintenance/common + icon = 'icons/obj/doors/Doormaint_common.dmi' + +/obj/machinery/door/airlock/maintenance/engi + icon = 'icons/obj/doors/Doormaint_engi.dmi' + req_one_access = list(access_engine) + +/obj/machinery/door/airlock/maintenance/int + icon = 'icons/obj/doors/Doormaint_int.dmi' + +/obj/machinery/door/airlock/maintenance/medical + icon = 'icons/obj/doors/Doormaint_med.dmi' + req_one_access = list(access_medical) + +/obj/machinery/door/airlock/maintenance/rnd + icon = 'icons/obj/doors/Doormaint_rnd.dmi' + req_one_access = list(access_research) + +/obj/machinery/door/airlock/maintenance/sec + icon = 'icons/obj/doors/Doormaint_sec.dmi' + req_one_access = list(access_security) + /obj/machinery/door/airlock/external name = "External Airlock" icon = 'icons/obj/doors/Doorext.dmi' @@ -386,6 +416,24 @@ icon = 'icons/obj/doors/shuttledoors_vertical.dmi' assembly_type = /obj/structure/door_assembly/door_assembly_voidcraft/vertical +/obj/machinery/door/airlock/alien + name = "alien airlock" + desc = "You're fairly sure this is a door." + icon = 'icons/obj/doors/Dooralien.dmi' + explosion_resistance = 20 + secured_wires = TRUE + hackProof = TRUE + assembly_type = /obj/structure/door_assembly/door_assembly_alien + req_one_access = list(access_alien) + +/obj/machinery/door/airlock/alien/locked + icon_state = "door_locked" + locked = TRUE + +/obj/machinery/door/airlock/alien/public // Entry to UFO. + req_one_access = list() + normalspeed = FALSE // So it closes faster and hopefully keeps the warm air inside. + /* About the new airlock wires panel: * An airlock wire dialog can be accessed by the normal way or by using wirecutters or a multitool on the door while the wire-panel is open. This would show the following wires, which you can either wirecut/mend or send a multitool pulse through. There are 9 wires. diff --git a/code/game/machinery/doors/multi_tile.dm b/code/game/machinery/doors/multi_tile.dm index 45501a3de76..434f7e64cb5 100644 --- a/code/game/machinery/doors/multi_tile.dm +++ b/code/game/machinery/doors/multi_tile.dm @@ -2,15 +2,44 @@ /obj/machinery/door/airlock/multi_tile width = 2 appearance_flags = 0 + var/obj/machinery/filler_object/filler1 + var/obj/machinery/filler_object/filler2 /obj/machinery/door/airlock/multi_tile/New() ..() SetBounds() + if(opacity) + create_fillers() + +/obj/machinery/door/airlock/multi_tile/Destroy() + qdel_null(filler1) + qdel_null(filler2) + return ..() /obj/machinery/door/airlock/multi_tile/Move() . = ..() SetBounds() +/obj/machinery/door/airlock/multi_tile/open() + . = ..() + + if(filler1) + filler1.set_opacity(opacity) + if(filler2) + filler2.set_opacity(opacity) + + return . + +/obj/machinery/door/airlock/multi_tile/close() + . = ..() + + if(filler1) + filler1.set_opacity(opacity) + if(filler2) + filler2.set_opacity(opacity) + + return . + /obj/machinery/door/airlock/multi_tile/proc/SetBounds() if(dir in list(EAST, WEST)) bound_width = width * world.icon_size @@ -19,9 +48,35 @@ bound_width = world.icon_size bound_height = width * world.icon_size +/obj/machinery/door/airlock/multi_tile/proc/create_fillers() + if(src.dir > 3) + filler1 = new/obj/machinery/filler_object (src.loc) + filler2 = new/obj/machinery/filler_object (get_step(src,EAST)) + else + filler1 = new/obj/machinery/filler_object (src.loc) + filler2 = new/obj/machinery/filler_object (get_step(src,NORTH)) + filler1.density = 0 + filler2.density = 0 + filler1.set_opacity(opacity) + filler2.set_opacity(opacity) + /obj/machinery/door/airlock/multi_tile/glass name = "Glass Airlock" icon = 'icons/obj/doors/Door2x1glass.dmi' opacity = 0 glass = 1 assembly_type = /obj/structure/door_assembly/multi_tile + +/obj/machinery/door/airlock/multi_tile/metal + name = "Airlock" + icon = 'icons/obj/doors/Door2x1metal.dmi' + assembly_type = /obj/structure/door_assembly/multi_tile + +/obj/machinery/filler_object + name = "" + icon = 'icons/obj/doors/rapid_pdoor.dmi' + icon_state = "" + density = 0 + +/obj/machinery/door/airlock/multi_tile/metal/mait + icon = 'icons/obj/doors/Door2x1_Maint.dmi' diff --git a/code/game/machinery/portable_turret.dm b/code/game/machinery/portable_turret.dm index 1b181aebb5d..fe0ebfdb2f9 100644 --- a/code/game/machinery/portable_turret.dm +++ b/code/game/machinery/portable_turret.dm @@ -86,6 +86,23 @@ health = 250 // Since lasers do 40 each. maxhealth = 250 +/obj/machinery/porta_turret/alien // The kind used on the UFO submap. + name = "interior anti-boarding turret" + desc = "A very tough looking turret made by alien hands." + installation = /obj/item/weapon/gun/energy/alien + enabled = TRUE + lethal = TRUE + ailock = TRUE + check_all = TRUE + health = 250 // Similar to the AI turrets. + maxhealth = 250 + +/obj/machinery/porta_turret/alien/destroyed // Turrets that are already dead, to act as a warning of what the rest of the submap contains. + name = "broken interior anti-boarding turret" + desc = "A very tough looking turret made by alien hands. This one looks destroyed, thankfully." + icon_state = "destroyed_target_prism" + stat = BROKEN + /obj/machinery/porta_turret/New() ..() req_access.Cut() @@ -103,6 +120,11 @@ req_one_access.Cut() req_access = list(access_cent_specops) +/obj/machinery/porta_turret/alien/New() + ..() + req_one_access.Cut() + req_access = list(access_alien) + /obj/machinery/porta_turret/Destroy() qdel(spark_system) spark_system = null @@ -436,6 +458,14 @@ var/list/turret_icons return ..() +/obj/machinery/porta_turret/alien/emp_act(severity) // This is overrided to give an EMP resistance as well as avoid scambling the turret settings. + if(prob(75)) // Superior alien technology, I guess. + return + enabled = FALSE + spawn(rand(1 MINUTE, 2 MINUTES)) + if(!enabled) + enabled = TRUE + /obj/machinery/porta_turret/ex_act(severity) switch (severity) if(1) diff --git a/code/game/machinery/rechargestation.dm b/code/game/machinery/rechargestation.dm index 65ef3edc65e..7a2aed97708 100644 --- a/code/game/machinery/rechargestation.dm +++ b/code/game/machinery/rechargestation.dm @@ -282,3 +282,27 @@ if(!usr.incapacitated()) return go_in(usr) + +/obj/machinery/recharge_station/ghost_pod_recharger + name = "drone pod" + desc = "This is a pod which used to contain a drone... Or maybe it still does?" + icon = 'icons/obj/structures.dmi' + +/obj/machinery/recharge_station/ghost_pod_recharger/update_icon() + ..() + if(stat & BROKEN) + icon_state = "borg_pod_closed" + desc = "It appears broken..." + return + + if(occupant) + if((stat & NOPOWER) && !has_cell_power()) + icon_state = "borg_pod_closed" + desc = "It appears to be unpowered..." + else + icon_state = "borg_pod_closed" + else + icon_state = "borg_pod_opened" + + if(icon_update_tick == 0) + build_overlays() \ 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 30a0743e097..7f76bc978c4 100644 --- a/code/game/machinery/suit_storage_unit.dm +++ b/code/game/machinery/suit_storage_unit.dm @@ -640,7 +640,7 @@ name = "Nonstandard suit cycler" model_text = "Nonstandard" req_access = list(access_syndicate) - departments = list("Mercenary") + departments = list("Mercenary", "Charring") can_repair = 1 /obj/machinery/suit_cycler/attack_ai(mob/user as mob) @@ -752,7 +752,7 @@ //Clear the access reqs, disable the safeties, and open up all paintjobs. user << "You run the sequencer across the interface, corrupting the operating protocols." - departments = list("Engineering","Mining","Medical","Security","Atmos","HAZMAT","Construction","Biohazard","Crowd Control","Emergency Medical Response","^%###^%$") + departments = list("Engineering","Mining","Medical","Security","Atmos","HAZMAT","Construction","Biohazard","Crowd Control","Emergency Medical Response","^%###^%$", "Charring") species = list("Human","Tajara","Skrell","Unathi", "Teshari") emagged = 1 @@ -1073,6 +1073,15 @@ suit.name = "blood-red voidsuit" suit.item_state = "syndie_voidsuit" suit.icon_state = "rig-syndie" + if("Charring") + if(helmet) + helmet.name = "soot-covered voidsuit helmet" + helmet.icon_state = "rig0-firebug" + helmet.item_state = "rig0-firebug" + if(suit) + suit.name = "soot-covered voidsuit" + suit.item_state = "rig-firebug" + suit.icon_state = "rig-firebug" if(helmet) helmet.name = "refitted [helmet.name]" if(suit) suit.name = "refitted [suit.name]" diff --git a/code/game/machinery/supplybeacon.dm b/code/game/machinery/supplybeacon.dm index 3441b09cbb2..0f58bd9a48c 100644 --- a/code/game/machinery/supplybeacon.dm +++ b/code/game/machinery/supplybeacon.dm @@ -47,7 +47,7 @@ /obj/machinery/power/supply_beacon/attackby(var/obj/item/weapon/W, var/mob/user) if(!use_power && istype(W, /obj/item/weapon/wrench)) if(!anchored && !connect_to_network()) - user << "This device must be placed over an exposed cable." + to_chat(user, "This device must be placed over an exposed cable.") return anchored = !anchored user.visible_message("\The [user] [anchored ? "secures" : "unsecures"] \the [src].") @@ -59,13 +59,13 @@ if(expended) use_power = 0 - user << "\The [src] has used up its charge." + to_chat (user, "\The [src] has used up its charge.") return if(anchored) return use_power ? deactivate(user) : activate(user) else - user << "You need to secure the beacon with a wrench first!" + to_chat(user, "You need to secure the beacon with a wrench first!") return /obj/machinery/power/supply_beacon/attack_ai(var/mob/user) @@ -76,12 +76,12 @@ if(expended) return if(surplus() < 500) - if(user) user << "The connected wire doesn't have enough current." + if(user) to_chat(user, "The connected wire doesn't have enough current.") return set_light(3, 3, "#00CCAA") icon_state = "beacon_active" use_power = 1 - if(user) user << "You activate the beacon. The supply drop will be dispatched soon." + if(user) to_chat(user, "You activate the beacon. The supply drop will be dispatched soon.") /obj/machinery/power/supply_beacon/proc/deactivate(var/mob/user, var/permanent) if(permanent) @@ -92,7 +92,7 @@ set_light(0) use_power = 0 target_drop_time = null - if(user) user << "You deactivate the beacon." + if(user) to_chat(user, "You deactivate the beacon.") /obj/machinery/power/supply_beacon/Destroy() if(use_power) diff --git a/code/game/machinery/transportpod.dm b/code/game/machinery/transportpod.dm new file mode 100644 index 00000000000..96401c09082 --- /dev/null +++ b/code/game/machinery/transportpod.dm @@ -0,0 +1,110 @@ +/obj/machinery/transportpod + name = "Ballistic Transportation Pod" + desc = "A fast transit ballistic pod used to get from one place to the next. Batteries not included!" + icon = 'icons/obj/structures.dmi' + icon_state = "borg_pod_opened" + + density = 1 //thicc + anchored = 1 + use_power = 0 + + var/in_transit = 0 + var/mob/occupant = null + + var/xc = list(137, 209, 163, 110, 95, 60, 129, 201) // List of x values on the map to go to. + var/yc = list(134, 99, 169, 120, 96, 122, 189, 219) // List of y values on the map to go to. + + var/limit_x = 3 + var/limit_y = 3 + +/obj/machinery/transportpod/process() + if(occupant) + if(in_transit) + var/locNum = rand(0, 7) //pick a random location + var/turf/L = locate(xc[locNum], yc[locNum], 1) // Pairs the X and Y to get an actual location. + limit_x = xc[locNum]+1 + limit_y = yc[locNum]+1 + build() + sleep(20) //Give explosion time so the pod itself doesn't go boom + src.forceMove(L) + playsound(src, pick('sound/effects/Explosion1.ogg', 'sound/effects/Explosion2.ogg', 'sound/effects/Explosion3.ogg', 'sound/effects/Explosion4.ogg')) + in_transit = 0 + sleep(2) + go_out() + sleep(2) + del(src) + +/obj/machinery/transportpod/relaymove(mob/user as mob) + if(user.stat) + return + go_out() + return + +/obj/machinery/transportpod/update_icon() + ..() + if(occupant) + icon_state = "borg_pod_closed" + else + icon_state = "borg_pod_opened" + +/obj/machinery/transportpod/Bumped(var/mob/living/O) + go_in(O) + +/obj/machinery/transportpod/proc/go_in(var/mob/living/carbon/human/O) + if(occupant) + return + + if(O.incapacitated()) //aint no sleepy people getting in here + return + + add_fingerprint(O) + O.reset_view(src) + O.forceMove(src) + occupant = O + update_icon() + if(alert(O, "Are you sure you're ready to launch?", , "Yes", "No") == "Yes") + in_transit = 1 + playsound(src, HYPERSPACE_WARMUP) + else + go_out() + return 1 + +/obj/machinery/transportpod/proc/go_out() + if(!occupant) + return + + occupant.forceMove(src.loc) + occupant.reset_view() + occupant = null + update_icon() + +/obj/machinery/transportpod/verb/move_eject() + set category = "Object" + set name = "Eject Pod" + set src in oview(1) + + if(usr.incapacitated()) + return + + go_out() + add_fingerprint(usr) + return + +/obj/machinery/transportpod/verb/move_inside() + set category = "Object" + set name = "Enter Pod" + set src in oview(1) + + if(usr.incapacitated()) //just to DOUBLE CHECK the damn sleepy people don't touch the pod + return + + go_in(usr) + +/obj/machinery/transportpod/proc/build() + for(var/x = limit_x-2, x <= limit_x, x++) + for(var/y = limit_y-2, y <= limit_y, y++) + var/current_cell = locate(x, y, 1) + var/turf/T = get_turf(current_cell) + if(!current_cell) + continue + T.ChangeTurf(/turf/unsimulated/floor/shuttle_ceiling) \ No newline at end of file diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm index fdab318780c..960ac923eb7 100644 --- a/code/game/machinery/vending.dm +++ b/code/game/machinery/vending.dm @@ -147,7 +147,7 @@ /obj/machinery/vending/emag_act(var/remaining_charges, var/mob/user) if(!emagged) emagged = 1 - user << "You short out the product lock on \the [src]" + to_chat(user, "You short out \the [src]'s product lock.") return 1 /obj/machinery/vending/attackby(obj/item/weapon/W as obj, mob/user as mob) @@ -182,7 +182,7 @@ return else if(istype(W, /obj/item/weapon/screwdriver)) panel_open = !panel_open - user << "You [panel_open ? "open" : "close"] the maintenance panel." + to_chat(user, "You [panel_open ? "open" : "close"] the maintenance panel.") playsound(src, W.usesound, 50, 1) overlays.Cut() if(panel_open) @@ -199,7 +199,7 @@ W.forceMove(src) coin = W categories |= CAT_COIN - user << "You insert \the [W] into \the [src]." + to_chat(user, "You insert \the [W] into \the [src].") nanomanager.update_uis(src) return else if(istype(W, /obj/item/weapon/wrench)) @@ -211,7 +211,7 @@ if(do_after(user, 20 * W.toolspeed)) if(!src) return - user << "You [anchored? "un" : ""]secured \the [src]!" + to_chat(user, "You [anchored? "un" : ""]secured \the [src]!") anchored = !anchored return else @@ -232,7 +232,7 @@ // This is not a status display message, since it's something the character // themselves is meant to see BEFORE putting the money in - usr << "\icon[cashmoney] That is not enough money." + to_chat(usr, "\icon[cashmoney] That is not enough money.") return 0 if(istype(cashmoney, /obj/item/weapon/spacecash)) @@ -418,21 +418,22 @@ if(href_list["remove_coin"] && !istype(usr,/mob/living/silicon)) if(!coin) - usr << "There is no coin in this machine." + to_chat(usr, "There is no coin in this machine.") return coin.forceMove(src.loc) if(!usr.get_active_hand()) usr.put_in_hands(coin) - usr << "You remove \the [coin] from \the [src]" + to_chat(usr, "You remove \the [coin] from \the [src]") coin = null categories &= ~CAT_COIN if((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf)))) if((href_list["vend"]) && (vend_ready) && (!currently_vending)) if((!allowed(usr)) && !emagged && scan_id) //For SECURE VENDING MACHINES YEAH - usr << "Access denied." //Unless emagged of course + to_chat(usr, "Access denied.") //Unless emagged of course flick(icon_deny,src) + playsound(src.loc, 'sound/machines/deniedbeep.ogg', 50, 0) return var/key = text2num(href_list["vend"]) @@ -445,12 +446,12 @@ if(R.price <= 0) vend(R, usr) else if(istype(usr,/mob/living/silicon)) //If the item is not free, provide feedback if a synth is trying to buy something. - usr << "Artificial unit recognized. Artificial units cannot complete this transaction. Purchase canceled." + to_chat(usr, "Lawed unit recognized. Lawed units cannot complete this transaction. Purchase canceled.") return else currently_vending = R if(!vendor_account || vendor_account.suspended) - status_message = "This machine is currently unable to process payments due to problems with the associated account." + status_message = "This machine is currently unable to process payments due to issues with the associated account." status_error = 1 else status_message = "Please swipe a card or insert cash to pay for the item." @@ -467,8 +468,9 @@ /obj/machinery/vending/proc/vend(datum/stored_item/vending_product/R, mob/user) if((!allowed(usr)) && !emagged && scan_id) //For SECURE VENDING MACHINES YEAH - usr << "Access denied." //Unless emagged of course + to_chat(usr, "Access denied.") //Unless emagged of course flick(icon_deny,src) + playsound(src.loc, 'sound/machines/deniedbeep.ogg', 50, 0) return vend_ready = 0 //One thing at a time!! status_message = "Vending..." @@ -477,13 +479,13 @@ if(R.category & CAT_COIN) if(!coin) - user << "You need to insert a coin to get this item." + to_chat(user, "You need to insert a coin to get this item.") return if(coin.string_attached) if(prob(50)) - user << "You successfully pull the coin out before \the [src] could swallow it." + to_chat(user, "You successfully pull the coin out before \the [src] could swallow it.") else - user << "You weren't able to pull the coin out fast enough, the machine ate it, string and all." + to_chat(user, "You weren't able to pull the coin out fast enough, the machine ate it, string and all.") qdel(coin) coin = null categories &= ~CAT_COIN @@ -806,7 +808,6 @@ contraband = list(/obj/item/weapon/reagent_containers/syringe/steroid = 4) -//This one's from bay12 /obj/machinery/vending/cart name = "PTech" desc = "Cartridges for PDAs." @@ -821,7 +822,7 @@ has_logs = 1 /obj/machinery/vending/cigarette - name = "Cigarette machine" //OCD had to be uppercase to look nice with the new formating + name = "cigarette machine" desc = "If you want to get cancer, might as well do it in style!" product_slogans = "Space cigs taste good like a cigarette should.;I'd rather toolbox than switch.;Smoke!;Don't believe the reports - smoke today!" product_ads = "Probably not bad for you!;Don't believe the scientists!;It's good for you!;Don't quit, buy more!;Smoke!;Nicotine heaven.;Best cigarettes since 2150.;Award-winning cigs.;Feeling temperamental? Try a Temperamento!;Carcinoma Angels - go fuck yerself!;Don't be so hard on yourself, kid. Smoke a Lucky Star!" @@ -865,7 +866,6 @@ req_log_access = access_cmo has_logs = 1 -//This one's from bay12 /obj/machinery/vending/phoronresearch name = "Toximate 3000" desc = "All the fine parts you need in one vending machine!" @@ -1051,7 +1051,6 @@ req_log_access = access_ce has_logs = 1 -//This one's from bay12 /obj/machinery/vending/engineering name = "Robco Tool Maker" desc = "Everything you need for do-it-yourself station repair." @@ -1070,7 +1069,6 @@ req_log_access = access_ce has_logs = 1 -//This one's from bay12 /obj/machinery/vending/robotics name = "Robotech Deluxe" desc = "All the tools you need to create your own robot army." diff --git a/code/game/machinery/vr_console.dm b/code/game/machinery/vr_console.dm new file mode 100644 index 00000000000..79fdf882fa2 --- /dev/null +++ b/code/game/machinery/vr_console.dm @@ -0,0 +1,226 @@ +/obj/machinery/vr_sleeper + name = "VR sleeper" + desc = "A fancy bed with built-in sensory I/O ports and connectors to interface users' minds with their bodies in virtual reality." + icon = 'icons/obj/Cryogenic2.dmi' + icon_state = "syndipod_0" + density = 1 + anchored = 1 + circuit = /obj/item/weapon/circuitboard/vr_sleeper + var/mob/living/carbon/human/occupant = null + var/mob/living/carbon/human/avatar = null + var/datum/mind/vr_mind = null + + use_power = 1 + idle_power_usage = 15 + active_power_usage = 200 + light_color = "#FF0000" + +/obj/machinery/vr_sleeper/New() + ..() + component_parts = list() + component_parts += new /obj/item/weapon/stock_parts/scanning_module(src) + component_parts += new /obj/item/stack/material/glass/reinforced(src, 2) + + RefreshParts() + +/obj/machinery/vr_sleeper/initialize() + update_icon() + +/obj/machinery/vr_sleeper/process() + if(stat & (NOPOWER|BROKEN)) + return + +/obj/machinery/vr_sleeper/update_icon() + icon_state = "syndipod_[occupant ? "1" : "0"]" + +/obj/machinery/vr_sleeper/Topic(href, href_list) + if(..()) + return 1 + + if(usr == occupant) + to_chat(usr, "You can't reach the controls from the inside.") + return + + add_fingerprint(usr) + + if(href_list["eject"]) + go_out() + + return 1 + +/obj/machinery/vr_sleeper/attackby(var/obj/item/I, var/mob/user) + add_fingerprint(user) + if(default_deconstruction_screwdriver(user, I)) + return + else if(default_deconstruction_crowbar(user, I)) + if(occupant && avatar) + avatar.exit_vr() + avatar = null + go_out() + return + + +/obj/machinery/vr_sleeper/MouseDrop_T(var/mob/target, var/mob/user) + if(user.stat || user.lying || !Adjacent(user) || !target.Adjacent(user)|| !isliving(target)) + return + go_in(target, user) + + + +/obj/machinery/sleeper/relaymove(var/mob/user) + ..() + if(usr.incapacitated()) + return + go_out() + + + +/obj/machinery/vr_sleeper/emp_act(var/severity) + if(stat & (BROKEN|NOPOWER)) + ..(severity) + return + + if(occupant) + // This will eject the user from VR + // ### Fry the brain? + go_out() + + ..(severity) + +/obj/machinery/vr_sleeper/verb/eject() + set src in oview(1) + set category = "Object" + set name = "Eject VR Capsule" + + if(usr.incapacitated()) + return + + if(usr != occupant && avatar && alert(avatar, "Someone wants to remove you from virtual reality. Do you want to leave?", "Leave VR?", "Yes", "No") == "No") + return + + // The player in VR is fine with leaving, kick them out and reset avatar + avatar.exit_vr() + avatar = null + go_out() + add_fingerprint(usr) + +/obj/machinery/vr_sleeper/verb/climb_in() + set src in oview(1) + set category = "Object" + set name = "Enter VR Capsule" + + if(usr.incapacitated()) + return + go_in(usr, usr) + add_fingerprint(usr) + +/obj/machinery/vr_sleeper/relaymove(mob/user as mob) + if(user.incapacitated()) + return 0 //maybe they should be able to get out with cuffs, but whatever + go_out() + +/obj/machinery/vr_sleeper/proc/go_in(var/mob/M, var/mob/user) + if(!M) + return + if(stat & (BROKEN|NOPOWER)) + return + if(!ishuman(M)) + user << "\The [src] rejects [M] with a sharp beep." + if(occupant) + user << "\The [src] is already occupied." + return + + if(M == user) + visible_message("\The [user] starts climbing into \the [src].") + else + visible_message("\The [user] starts putting [M] into \the [src].") + + if(do_after(user, 20)) + if(occupant) + to_chat(user, "\The [src] is already occupied.") + return + M.stop_pulling() + if(M.client) + M.client.perspective = EYE_PERSPECTIVE + M.client.eye = src + M.loc = src + update_use_power(2) + occupant = M + + update_icon() + + enter_vr() + return + +/obj/machinery/vr_sleeper/proc/go_out() + if(!occupant) + return + + if(occupant.client) + occupant.client.eye = occupant.client.mob + occupant.client.perspective = MOB_PERSPECTIVE + occupant.loc = src.loc + occupant = null + for(var/atom/movable/A in src) // In case an object was dropped inside or something + if(A == circuit) + continue + if(A in component_parts) + continue + A.loc = src.loc + update_use_power(1) + update_icon() + +/obj/machinery/vr_sleeper/proc/enter_vr() + + // No mob to transfer a mind from + if(!occupant) + return + + // No mind to transfer + if(!occupant.mind) + return + + // Mob doesn't have an active consciousness to send/receive from + if(occupant.stat != CONSCIOUS) + return + + avatar = occupant.vr_link + // If they've already enterred VR, and are reconnecting, prompt if they want a new body + if(avatar && alert(occupant, "You already have a Virtual Reality avatar. Would you like to use it?", "New avatar", "Yes", "No") == "No") + // Delink the mob + occupant.vr_link = null + avatar = null + + if(!avatar) + // Get the desired spawn location to put the body + var/S = null + var/list/vr_landmarks = list() + for(var/obj/effect/landmark/virtual_reality/sloc in landmarks_list) + vr_landmarks += sloc.name + + S = input(occupant, "Please select a location to spawn your avatar at:", "Spawn location") as null|anything in vr_landmarks + if(!S) + return 0 + + for(var/obj/effect/landmark/virtual_reality/i in landmarks_list) + if(i.name == S) + S = i + break + + avatar = new(S, "Virtual Reality Avatar") + // If the user has a non-default (Human) bodyshape, make it match theirs. + if(occupant.species.name != "Promethean" && occupant.species.name != "Human") + avatar.shapeshifter_change_shape(occupant.species.name) + avatar.forceMove(get_turf(S)) // Put the mob on the landmark, instead of inside it + avatar.Sleeping(1) + + occupant.enter_vr(avatar) + + // Prompt for username after they've enterred the body. + var/newname = sanitize(input(avatar, "You are enterring virtual reality. Your username is currently [src.name]. Would you like to change it to something else?", "Name change") as null|text, MAX_NAME_LEN) + if (newname) + avatar.real_name = newname + + else + occupant.enter_vr(avatar) + diff --git a/code/game/mecha/medical/odysseus.dm b/code/game/mecha/medical/odysseus.dm index 6aec830c899..38c3cffb308 100644 --- a/code/game/mecha/medical/odysseus.dm +++ b/code/game/mecha/medical/odysseus.dm @@ -99,7 +99,9 @@ C.images += holder holder = patient.hud_list[STATUS_HUD] - if(patient.stat == DEAD) + if(patient.isSynthetic()) + holder.icon_state = "hudrobo" + else if(patient.stat == DEAD) holder.icon_state = "huddead" else if(foundVirus) holder.icon_state = "hudill" diff --git a/code/game/objects/effects/landmarks.dm b/code/game/objects/effects/landmarks.dm index 547406aa1db..b8cb8006d29 100644 --- a/code/game/objects/effects/landmarks.dm +++ b/code/game/objects/effects/landmarks.dm @@ -107,6 +107,18 @@ return 1 +/obj/effect/landmark/virtual_reality + name = "virtual_reality" + icon = 'icons/mob/screen1.dmi' + icon_state = "x" + anchored = 1.0 + +/obj/effect/landmark/virtual_reality/New() + ..() + tag = "virtual_reality*[name]" + invisibility = 101 + return 1 + //Costume spawner landmarks /obj/effect/landmark/costume/New() //costume spawner, selects a random subclass and disappears diff --git a/code/game/objects/effects/spiders.dm b/code/game/objects/effects/spiders.dm index 94c0a7999f0..4cc39d4e676 100644 --- a/code/game/objects/effects/spiders.dm +++ b/code/game/objects/effects/spiders.dm @@ -210,25 +210,8 @@ //================= if(isturf(loc)) - if(prob(25)) - var/list/nearby = trange(5, src) - loc - if(nearby.len) - var/target_atom = pick(nearby) - walk_to(src, target_atom, 5) - if(prob(25)) - src.visible_message("\The [src] skitters[pick(" away"," around","")].") - else if(prob(5)) - //vent crawl! - for(var/obj/machinery/atmospherics/unary/vent_pump/v in view(7,src)) - if(!v.welded) - entry_vent = v - walk_to(src, entry_vent, 5) - break + skitter() - if(amount_grown >= 100) - var/spawn_type = pick(grow_as) - new spawn_type(src.loc, src) - qdel(src) else if(isorgan(loc)) if(!amount_grown) amount_grown = 1 var/obj/item/organ/external/O = loc @@ -249,6 +232,27 @@ if(amount_grown) amount_grown += rand(0,2) +/obj/effect/spider/spiderling/proc/skitter() + if(isturf(loc)) + if(prob(25)) + var/list/nearby = trange(5, src) - loc + if(nearby.len) + var/target_atom = pick(nearby) + walk_to(src, target_atom, 5) + if(prob(25)) + src.visible_message("\The [src] skitters[pick(" away"," around","")].") + else if(prob(5)) + //vent crawl! + for(var/obj/machinery/atmospherics/unary/vent_pump/v in view(7,src)) + if(!v.welded) + entry_vent = v + walk_to(src, entry_vent, 5) + break + if(amount_grown >= 100) + var/spawn_type = pick(grow_as) + new spawn_type(src.loc, src) + qdel(src) + /obj/effect/decal/cleanable/spiderling_remains name = "spiderling remains" desc = "Green squishy mess." @@ -261,7 +265,7 @@ icon_state = "cocoon1" health = 60 - New() +/obj/effect/spider/cocoon/New() icon_state = pick("cocoon1","cocoon2","cocoon3") /obj/effect/spider/cocoon/Destroy() diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 6b4a09c6a5f..8b00612641c 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -80,6 +80,7 @@ var/list/sprite_sheets_obj = list() var/toolspeed = 1.0 // This is a multipler on how 'fast' a tool works. e.g. setting this to 0.5 will make the tool work twice as fast. + var/addblends // Icon overlay for ADD highlights when applicable. /obj/item/New() ..() diff --git a/code/game/objects/items/bodybag.dm b/code/game/objects/items/bodybag.dm index 16e27006b49..a23abb5b066 100644 --- a/code/game/objects/items/bodybag.dm +++ b/code/game/objects/items/bodybag.dm @@ -59,7 +59,7 @@ //..() //Doesn't need to run the parent. Since when can fucking bodybags be welded shut? -Agouri return else if(istype(W, /obj/item/weapon/wirecutters)) - user << "You cut the tag off the bodybag" + to_chat(user, "You cut the tag off the bodybag") src.name = "body bag" src.overlays.Cut() return @@ -160,7 +160,7 @@ O.name = "used stasis bag" O.icon = src.icon O.icon_state = "bodybag_used" - O.desc = "Pretty useless now.." + O.desc = "Pretty useless now..." qdel(src) /obj/structure/closet/body_bag/cryobag/MouseDrop(over_object, src_location, over_location) @@ -211,9 +211,9 @@ /obj/structure/closet/body_bag/cryobag/examine(mob/user) ..() if(Adjacent(user)) //The bag's rather thick and opaque from a distance. - user << "You peer into \the [src]." + to_chat(user, "You peer into \the [src].") if(syringe) - user << "It has a syringe added to it." + to_chat(user, "It has a syringe added to it.") for(var/mob/living/L in contents) L.examine(user) diff --git a/code/game/objects/items/devices/defib.dm b/code/game/objects/items/devices/defib.dm index cd1484548c7..e4932793a18 100644 --- a/code/game/objects/items/devices/defib.dm +++ b/code/game/objects/items/devices/defib.dm @@ -35,8 +35,8 @@ qdel_null(paddles) qdel_null(bcell) -/obj/item/device/defib_kit/loaded //starts with highcap cell - bcell = /obj/item/weapon/cell/high +/obj/item/device/defib_kit/loaded //starts with a cell + bcell = /obj/item/weapon/cell/apc /obj/item/device/defib_kit/update_icon() @@ -209,7 +209,7 @@ var/combat = 0 //If it can be used to revive people wearing thick clothing (e.g. spacesuits) var/cooldowntime = (6 SECONDS) // How long in deciseconds until the defib is ready again after use. var/chargetime = (2 SECONDS) - var/chargecost = 1000 //units of charge + var/chargecost = 1250 //units of charge per zap //With the default APC level cell, this allows 4 shocks var/burn_damage_amt = 5 var/use_on_synthetic = 0 //If 1, this is only useful on FBPs, if 0, this is only useful on fleshies @@ -284,10 +284,12 @@ return "buzzes, \"Resuscitation failed - Excessive neural degeneration. Further attempts futile.\"" H.updatehealth() - if(H.isSynthetic() && H.health + H.getOxyLoss() + H.getToxLoss() <= config.health_threshold_dead || (HUSK in H.mutations)) - return "buzzes, \"Resuscitation failed - Severe damage detected. Begin manual repair before further attempts futile.\"" - if(!H.isSynthetic() && H.health + H.getOxyLoss() <= config.health_threshold_dead || (HUSK in H.mutations)) + if(H.isSynthetic()) + if(H.health + H.getOxyLoss() + H.getToxLoss() <= config.health_threshold_dead) + return "buzzes, \"Resuscitation failed - Severe damage detected. Begin manual repair before further attempts futile.\"" + + else(H.health + H.getOxyLoss() <= config.health_threshold_dead || (HUSK in H.mutations) || !H.can_defib) return "buzzes, \"Resuscitation failed - Severe tissue damage makes recovery of patient impossible via defibrillator. Further attempts futile.\"" var/bad_vital_organ = check_vital_organs(H) @@ -377,7 +379,10 @@ // This proc is used so that we can return out of the revive process while ensuring that busy and update_icon() are handled /obj/item/weapon/shockpaddles/proc/do_revive(mob/living/carbon/human/H, mob/user) if(!H.client && !H.teleop) - to_chat(find_dead_player(H.ckey, 1), "Someone is attempting to resuscitate you. Re-enter your body if you want to be revived!") + for(var/mob/observer/dead/ghost in player_list) + if(ghost.mind == H.mind) + to_chat(ghost, "Someone is attempting to resuscitate you. Re-enter your body if you want to be revived! (Verbs -> Ghost -> Re-enter corpse)") + break //beginning to place the paddles on patient's chest to allow some time for people to move away to stop the process user.visible_message("\The [user] begins to place [src] on [H]'s chest.", "You begin to place [src] on [H]'s chest...") diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index dd10e808599..083f83c1c95 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -290,6 +290,7 @@ name = "desk lamp" desc = "A desk lamp with an adjustable mount." icon_state = "lamp" + force = 10 brightness_on = 5 w_class = ITEMSIZE_LARGE flags = CONDUCT diff --git a/code/game/objects/items/devices/geiger.dm b/code/game/objects/items/devices/geiger.dm index 62cb9d9862c..dbac918609c 100644 --- a/code/game/objects/items/devices/geiger.dm +++ b/code/game/objects/items/devices/geiger.dm @@ -1,7 +1,7 @@ -#define RAD_LEVEL_LOW 5 //10 // Around the level at which radiation starts to become harmful -#define RAD_LEVEL_MODERATE 15 //15 -#define RAD_LEVEL_HIGH 50 //50 -#define RAD_LEVEL_VERY_HIGH 100 //100 +#define RAD_LEVEL_LOW 0.01 // Around the level at which radiation starts to become harmful +#define RAD_LEVEL_MODERATE 10 +#define RAD_LEVEL_HIGH 25 +#define RAD_LEVEL_VERY_HIGH 50 //Geiger counter //Rewritten version of TG's geiger counter @@ -19,7 +19,14 @@ /obj/item/device/geiger/New() processing_objects |= src +/obj/item/device/geiger/Destroy() + processing_objects -= src + return ..() + /obj/item/device/geiger/process() + get_radiation() + +/obj/item/device/geiger/proc/get_radiation() if(!scanning) return radiation_count = radiation_repository.get_rads_at_turf(get_turf(src)) @@ -27,12 +34,29 @@ /obj/item/device/geiger/examine(mob/user) ..(user) - to_chat(user, "[scanning ? "ambient" : "stored"] radiation level: [radiation_count ? radiation_count : "0"]Bq.") + get_radiation() + to_chat(user, "[scanning ? "Ambient" : "Stored"] radiation level: [radiation_count ? radiation_count : "0"]Bq.") + +/obj/item/device/geiger/rad_act(amount) + if(!amount || !scanning) + return FALSE + + if(amount > radiation_count) + radiation_count = amount + + var/sound = "geiger" + if(amount < 5) + sound = "geiger_weak" + playsound(src, sound, between(10, 10 + (radiation_count * 4), 100), 0) + if(sound == "geiger_weak") // A weak geiger sound every two seconds sounds too infrequent. + spawn(1 SECOND) + playsound(src, sound, between(10, 10 + (radiation_count * 4), 100), 0) + update_icon() /obj/item/device/geiger/attack_self(var/mob/user) scanning = !scanning update_icon() - to_chat(user, "\icon[src] You switch [scanning ? "on" : "off"] [src].") + to_chat(user, "\icon[src] You switch [scanning ? "on" : "off"] \the [src].") /obj/item/device/geiger/update_icon() if(!scanning) @@ -40,12 +64,18 @@ return 1 switch(radiation_count) - if(null) icon_state = "geiger_on_1" - if(-INFINITY to RAD_LEVEL_LOW) icon_state = "geiger_on_1" - if(RAD_LEVEL_LOW + 1 to RAD_LEVEL_MODERATE) icon_state = "geiger_on_2" - if(RAD_LEVEL_MODERATE + 1 to RAD_LEVEL_HIGH) icon_state = "geiger_on_3" - if(RAD_LEVEL_HIGH + 1 to RAD_LEVEL_VERY_HIGH) icon_state = "geiger_on_4" - if(RAD_LEVEL_VERY_HIGH + 1 to INFINITY) icon_state = "geiger_on_5" + if(null) + icon_state = "geiger_on_1" + if(-INFINITY to RAD_LEVEL_LOW) + icon_state = "geiger_on_1" + if(RAD_LEVEL_LOW to RAD_LEVEL_MODERATE) + icon_state = "geiger_on_2" + if(RAD_LEVEL_MODERATE to RAD_LEVEL_HIGH) + icon_state = "geiger_on_3" + if(RAD_LEVEL_HIGH to RAD_LEVEL_VERY_HIGH) + icon_state = "geiger_on_4" + if(RAD_LEVEL_VERY_HIGH to INFINITY) + icon_state = "geiger_on_5" #undef RAD_LEVEL_LOW #undef RAD_LEVEL_MODERATE diff --git a/code/game/objects/items/devices/gps.dm b/code/game/objects/items/devices/gps.dm new file mode 100644 index 00000000000..18fc47b617f --- /dev/null +++ b/code/game/objects/items/devices/gps.dm @@ -0,0 +1,211 @@ +var/list/GPS_list = list() + +/obj/item/device/gps + name = "global positioning system" + desc = "Triangulates the approximate co-ordinates using a nearby satellite network. Alt+click to toggle power." + icon = 'icons/obj/gps.dmi' + icon_state = "gps-c" + w_class = ITEMSIZE_TINY + slot_flags = SLOT_BELT + origin_tech = list(TECH_MATERIALS = 2, TECH_BLUESPACE = 2, TECH_MAGNETS = 1) + matter = list(DEFAULT_WALL_MATERIAL = 500) + var/gps_tag = "COM0" + var/emped = FALSE + var/tracking = FALSE // Will not show other signals or emit its own signal if false. + var/long_range = FALSE // If true, can see farther, depending on get_map_levels(). + var/local_mode = FALSE // If true, only GPS signals of the same Z level are shown. + var/hide_signal = FALSE // If true, signal is not visible to other GPS devices. + var/can_hide_signal = FALSE // If it can toggle the above var. + +/obj/item/device/gps/initialize() + GPS_list += src + name = "global positioning system ([gps_tag])" + update_icon() + +/obj/item/device/gps/Destroy() + GPS_list -= src + return ..() + +/obj/item/device/gps/AltClick(mob/user) + toggletracking(user) + +/obj/item/device/gps/proc/toggletracking(mob/living/user) + if(!istype(user)) + return + if(emped) + to_chat(user, "It's busted!") + return + if(tracking) + to_chat(user, "[src] is no longer tracking, or visible to other GPS devices.") + tracking = FALSE + update_icon() + else + to_chat(user, "[src] is now tracking, and visible to other GPS devices.") + tracking = TRUE + update_icon() + +/obj/item/device/gps/emp_act(severity) + if(emped) // Without a fancy callback system, this will have to do. + return + var/severity_modifier = severity ? severity : 4 // In case emp_act gets called without any arguments. + var/duration = 5 MINUTES / severity_modifier + emped = TRUE + update_icon() + + spawn(duration) + emped = FALSE + update_icon() + visible_message("\The [src] appears to be functional again.") + +/obj/item/device/gps/update_icon() + overlays.Cut() + if(emped) + overlays += image(icon, src, "emp") + else if(tracking) + overlays += image(icon, src, "working") + +/obj/item/device/gps/attack_self(mob/user) + display(user) + +/obj/item/device/gps/proc/display(mob/user) + if(!tracking) + to_chat(user, "The device is off. Alt-click it to turn it on.") + return + if(emped) + to_chat(user, "It's busted!") + return + + var/list/dat = list() + + var/turf/curr = get_turf(src) + var/area/my_area = get_area(src) + dat += "Current location: [my_area.name] ([curr.x], [curr.y], [curr.z])" + dat += "[hide_signal ? "Tagged" : "Broadcasting"] as '[gps_tag]'. \[Change Tag\] \ + \[Toggle Scan Range\] \ + [can_hide_signal ? "\[Toggle Signal Visibility\]":""]" + + var/list/signals = list() + + for(var/gps in GPS_list) + var/obj/item/device/gps/G = gps + if(G.emped || !G.tracking || G.hide_signal || G == src) // Their GPS isn't on or functional. + continue + var/turf/T = get_turf(G) + var/z_level_detection = using_map.get_map_levels(curr.z, long_range) + + if(local_mode && T.z != curr.z) // Only care about the current z-level. + continue + else if(!(T.z in z_level_detection)) // Too far away. + continue + + var/area/their_area = get_area(G) + var/area_name = their_area.name + if(istype(their_area, /area/submap)) + area_name = "Unknown Area" // Avoid spoilers. + var/coord = "[T.x], [T.y], [T.z]" + var/degrees = round(Get_Angle(curr, T)) + var/direction = uppertext(dir2text(get_dir(curr, T))) + var/distance = get_dist(curr, T) + var/local = curr.z == T.z ? TRUE : FALSE + if(!direction) + direction = "CENTER" + degrees = "N/A" + + signals += " [G.gps_tag]: [area_name] ([coord]) [local ? "Dist: [distance]m Dir: [degrees]° ([direction])":""]" + + if(signals.len) + dat += "Detected signals;" + for(var/line in signals) + dat += line + else + dat += "No other signals detected." + + var/result = dat.Join("
") + to_chat(user, result) + +/obj/item/device/gps/Topic(var/href, var/list/href_list) + if(..()) + return 1 + + if(href_list["tag"]) + var/a = input("Please enter desired tag.", name, gps_tag) as text + a = uppertext(copytext(sanitize(a), 1, 11)) + if(in_range(src, usr)) + gps_tag = a + name = "global positioning system ([gps_tag])" + to_chat(usr, "You set your GPS's tag to '[gps_tag]'.") + + if(href_list["range"]) + local_mode = !local_mode + to_chat(usr, "You set the signal receiver to [local_mode ? "'NARROW'" : "'BROAD'"].") + + if(href_list["hide"]) + if(!can_hide_signal) + return + hide_signal = !hide_signal + to_chat(usr, "You set the device to [hide_signal ? "not " : ""]broadcast a signal while scanning for other signals.") + +/obj/item/device/gps/on // Defaults to off to avoid polluting the signal list with a bunch of GPSes without owners. If you need to spawn active ones, use these. + tracking = TRUE + +/obj/item/device/gps/science + icon_state = "gps-s" + gps_tag = "SCI0" + +/obj/item/device/gps/science/on + tracking = TRUE + +/obj/item/device/gps/engineering + icon_state = "gps-e" + gps_tag = "ENG0" + +/obj/item/device/gps/engineering/on + tracking = TRUE + +/obj/item/device/gps/mining + icon_state = "gps-m" + gps_tag = "MINE0" + desc = "A positioning system helpful for rescuing trapped or injured miners, keeping one on you at all times while mining might just save your life. Alt+click to toggle power." + +/obj/item/device/gps/mining/on + tracking = TRUE + +/obj/item/device/gps/explorer + icon_state = "gps-ex" + gps_tag = "EX0" + desc = "A positioning system helpful for rescuing trapped or injured explorers, keeping one on you at all times while exploring might just save your life. Alt+click to toggle power." + +/obj/item/device/gps/explorer/on + tracking = TRUE + +/obj/item/device/gps/syndie + icon_state = "gps-syndie" + gps_tag = "NULL" + desc = "A positioning system that has extended range and can detect other GPS device signals without revealing its own. How that works is best left a mystery. Alt+click to toggle power." + origin_tech = list(TECH_MATERIALS = 2, TECH_BLUESPACE = 3, TECH_MAGNETS = 2, TECH_ILLEGAL = 2) + long_range = TRUE + hide_signal = TRUE + can_hide_signal = TRUE + +/obj/item/device/gps/robot + icon_state = "gps-b" + gps_tag = "SYNTH0" + desc = "A synthetic internal positioning system. Used as a recovery beacon for damaged synthetic assets, or a collaboration tool for mining or exploration teams. \ + Alt+click to toggle power." + tracking = TRUE // On by default. + +/obj/item/device/gps/internal // Base type for immobile/internal GPS units. + icon_state = null + gps_tag = "Eerie Signal" + desc = "Report to a coder immediately." + invisibility = INVISIBILITY_MAXIMUM + tracking = TRUE // Meant to point to a location, so it needs to be on. + anchored = TRUE + +/obj/item/device/gps/internal/base + gps_tag = "NT_BASE" + desc = "A homing signal from NanoTrasen's outpost." + +/obj/item/device/gps/internal/alien_vessel + gps_tag = "Mysterious Signal" + desc = "A signal that seems forboding." \ No newline at end of file diff --git a/code/game/objects/items/devices/lightreplacer.dm b/code/game/objects/items/devices/lightreplacer.dm index 35f41730dfe..8fd96981fc2 100644 --- a/code/game/objects/items/devices/lightreplacer.dm +++ b/code/game/objects/items/devices/lightreplacer.dm @@ -42,7 +42,7 @@ name = "light replacer" desc = "A device to automatically replace lights. Refill with working lightbulbs or sheets of glass." - + force = 8 icon = 'icons/obj/janitor.dmi' icon_state = "lightreplacer0" flags = CONDUCT @@ -61,32 +61,32 @@ /obj/item/device/lightreplacer/examine(mob/user) if(..(user, 2)) - user << "It has [uses] lights remaining." + to_chat(user, "It has [uses] lights remaining.") /obj/item/device/lightreplacer/attackby(obj/item/W, mob/user) if(istype(W, /obj/item/stack/material) && W.get_material_name() == "glass") var/obj/item/stack/G = W if(uses >= max_uses) - user << "[src.name] is full." + to_chat(user, "[src.name] is full.") return else if(G.use(1)) - AddUses(16) //Autolathe converts 1 sheet into 16 lights. - user << "You insert a piece of glass into \the [src.name]. You have [uses] light\s remaining." + add_uses(16) //Autolathe converts 1 sheet into 16 lights. + to_chat(user, "You insert a piece of glass into \the [src.name]. You have [uses] light\s remaining.") return else - user << "You need one sheet of glass to replace lights." + to_chat(user, "You need one sheet of glass to replace lights.") if(istype(W, /obj/item/weapon/light)) var/obj/item/weapon/light/L = W if(L.status == 0) // LIGHT OKAY if(uses < max_uses) - AddUses(1) - user << "You insert \the [L.name] into \the [src.name]. You have [uses] light\s remaining." + add_uses(1) + to_chat(user, "You insert \the [L.name] into \the [src.name]. You have [uses] light\s remaining.") user.drop_item() qdel(L) return else - user << "You need a working light." + to_chat(user, "You need a working light.") return /obj/item/device/lightreplacer/attack_self(mob/user) @@ -95,10 +95,10 @@ var/mob/living/silicon/robot/R = user if(R.emagged) src.Emag() - usr << "You shortcircuit the [src]." + to_chat(usr, You short circuit the [src].") return */ - usr << "It has [uses] lights remaining." + to_chat(usr, "It has [uses] lights remaining.") /obj/item/device/lightreplacer/update_icon() icon_state = "lightreplacer[emagged]" @@ -107,17 +107,17 @@ /obj/item/device/lightreplacer/proc/Use(var/mob/user) playsound(src.loc, 'sound/machines/click.ogg', 50, 1) - AddUses(-1) + add_uses(-1) return 1 // Negative numbers will subtract -/obj/item/device/lightreplacer/proc/AddUses(var/amount = 1) +/obj/item/device/lightreplacer/proc/add_uses(var/amount = 1) uses = min(max(uses + amount, 0), max_uses) /obj/item/device/lightreplacer/proc/Charge(var/mob/user, var/amount = 1) charge += amount if(charge > 6) - AddUses(1) + add_uses(1) charge = 0 /obj/item/device/lightreplacer/proc/ReplaceLight(var/obj/machinery/light/target, var/mob/living/U) diff --git a/code/game/objects/items/devices/megaphone.dm b/code/game/objects/items/devices/megaphone.dm index 53d647a4f0b..ca4b8d8066e 100644 --- a/code/game/objects/items/devices/megaphone.dm +++ b/code/game/objects/items/devices/megaphone.dm @@ -8,7 +8,7 @@ var/spamcheck = 0 var/emagged = 0 var/insults = 0 - var/list/insultmsg = list("FUCK EVERYONE!", "I'M A TATER!", "ALL SECURITY TO SHOOT ME ON SIGHT!", "I HAVE A BOMB!", "CAPTAIN IS A COMDOM!", "FOR THE SYNDICATE!") + var/list/insultmsg = list("FUCK EVERYONE!", "I'M A TERRORIST!", "ALL SECURITY TO SHOOT ME ON SIGHT!", "I HAVE A BOMB!", "CAPTAIN IS A COMDOM!", "GLORY TO ALMACH!") /obj/item/device/megaphone/attack_self(mob/living/user as mob) if (user.client) diff --git a/code/game/objects/items/gunbox.dm b/code/game/objects/items/gunbox.dm new file mode 100644 index 00000000000..add1530ca48 --- /dev/null +++ b/code/game/objects/items/gunbox.dm @@ -0,0 +1,19 @@ +/obj/item/gunbox + name = "detective's gun box" + desc = "A secure box containing a Detective's sidearm." + icon = 'icons/obj/storage.dmi' + icon_state = "gunbox" + w_class = ITEMSIZE_HUGE + +/obj/item/gunbox/attack_self(mob/living/user) + var/list/options = list() + options[".45 Pistol"] = list(/obj/item/weapon/gun/projectile/colt/detective, /obj/item/ammo_magazine/m45/rubber, /obj/item/ammo_magazine/m45/rubber) + options[".45 Revolver"] = list(/obj/item/weapon/gun/projectile/revolver/detective45, /obj/item/ammo_magazine/s45/rubber, /obj/item/ammo_magazine/s45/rubber) + var/choice = input(user,"Would you prefer a pistol or a revolver?") as null|anything in options + if(src && choice) + var/list/things_to_spawn = options[choice] + for(var/new_type in things_to_spawn) // Spawn all the things, the gun and the ammo. + var/atom/movable/AM = new new_type(get_turf(src)) + if(istype(AM, /obj/item/weapon/gun)) + to_chat(user, "You have chosen \the [AM]. Say hello to your new friend.") + qdel(src) \ No newline at end of file diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm index dde2f168b0e..d878dd74fec 100644 --- a/code/game/objects/items/stacks/medical.dm +++ b/code/game/objects/items/stacks/medical.dm @@ -75,11 +75,11 @@ var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting) if(affecting.open) - user << "The [affecting.name] is cut open, you'll need more than a bandage!" + to_chat(user, "The [affecting.name] is cut open, you'll need more than a bandage!") return if(affecting.is_bandaged()) - user << "The wounds on [M]'s [affecting.name] have already been bandaged." + to_chat(user, "The wounds on [M]'s [affecting.name] have already been bandaged.") return 1 else user.visible_message("\The [user] starts treating [M]'s [affecting.name].", \ @@ -93,9 +93,13 @@ if(used == amount) break if(!do_mob(user, M, W.damage/5)) - user << "You must stand still to bandage wounds." + to_chat(user, "You must stand still to bandage wounds.") break + if(affecting.is_bandaged()) // We do a second check after the delay, in case it was bandaged after the first check. + to_chat(user, "The wounds on [M]'s [affecting.name] have already been bandaged.") + return 1 + if (W.current_stage <= W.max_bleeding_stage) user.visible_message("\The [user] bandages \a [W.desc] on [M]'s [affecting.name].", \ "You bandage \a [W.desc] on [M]'s [affecting.name]." ) @@ -111,9 +115,9 @@ affecting.update_damages() if(used == amount) if(affecting.is_bandaged()) - user << "\The [src] is used up." + to_chat(user, "\The [src] is used up.") else - user << "\The [src] is used up, but there are more wounds to treat on \the [affecting.name]." + to_chat(user, "\The [src] is used up, but there are more wounds to treat on \the [affecting.name].") use(used) /obj/item/stack/medical/ointment @@ -135,17 +139,20 @@ var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting) if(affecting.open) - user << "The [affecting.name] is cut open, you'll need more than a bandage!" + to_chat(user, "The [affecting.name] is cut open, you'll need more than a bandage!") return if(affecting.is_salved()) - user << "The wounds on [M]'s [affecting.name] have already been salved." + to_chat(user, "The wounds on [M]'s [affecting.name] have already been salved.") return 1 else user.visible_message("\The [user] starts salving wounds on [M]'s [affecting.name].", \ "You start salving the wounds on [M]'s [affecting.name]." ) if(!do_mob(user, M, 10)) - user << "You must stand still to salve wounds." + to_chat(user, "You must stand still to salve wounds.") + return 1 + if(affecting.is_salved()) // We do a second check after the delay, in case it was bandaged after the first check. + to_chat(user, "The wounds on [M]'s [affecting.name] have already been salved.") return 1 user.visible_message("[user] salved wounds on [M]'s [affecting.name].", \ "You salved wounds on [M]'s [affecting.name]." ) @@ -169,11 +176,11 @@ var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting) if(affecting.open) - user << "The [affecting.name] is cut open, you'll need more than a bandage!" + to_chat(user, "The [affecting.name] is cut open, you'll need more than a bandage!") return if(affecting.is_bandaged() && affecting.is_disinfected()) - user << "The wounds on [M]'s [affecting.name] have already been treated." + to_chat(user, "The wounds on [M]'s [affecting.name] have already been treated.") return 1 else user.visible_message("\The [user] starts treating [M]'s [affecting.name].", \ @@ -187,8 +194,11 @@ if(used == amount) break if(!do_mob(user, M, W.damage/5)) - user << "You must stand still to bandage wounds." + to_chat(user, "You must stand still to bandage wounds.") break + if(affecting.is_bandaged() && affecting.is_disinfected()) // We do a second check after the delay, in case it was bandaged after the first check. + to_chat(user, "The wounds on [M]'s [affecting.name] have already been bandaged.") + return 1 if (W.current_stage <= W.max_bleeding_stage) user.visible_message("\The [user] cleans \a [W.desc] on [M]'s [affecting.name] and seals the edges with bioglue.", \ "You clean and seal \a [W.desc] on [M]'s [affecting.name]." ) @@ -205,9 +215,9 @@ affecting.update_damages() if(used == amount) if(affecting.is_bandaged()) - user << "\The [src] is used up." + to_chat(user, "\The [src] is used up.") else - user << "\The [src] is used up, but there are more wounds to treat on \the [affecting.name]." + to_chat(user, "\The [src] is used up, but there are more wounds to treat on \the [affecting.name].") use(used) /obj/item/stack/medical/advanced/ointment @@ -228,16 +238,19 @@ var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting) if(affecting.open) - user << "The [affecting.name] is cut open, you'll need more than a bandage!" + to_chat(user, "The [affecting.name] is cut open, you'll need more than a bandage!") if(affecting.is_salved()) - user << "The wounds on [M]'s [affecting.name] have already been salved." + to_chat(user, "The wounds on [M]'s [affecting.name] have already been salved.") return 1 else user.visible_message("\The [user] starts salving wounds on [M]'s [affecting.name].", \ "You start salving the wounds on [M]'s [affecting.name]." ) if(!do_mob(user, M, 10)) - user << "You must stand still to salve wounds." + to_chat(user, "You must stand still to salve wounds.") + return 1 + if(affecting.is_salved()) // We do a second check after the delay, in case it was bandaged after the first check. + to_chat(user, "The wounds on [M]'s [affecting.name] have already been salved.") return 1 user.visible_message( "[user] covers wounds on [M]'s [affecting.name] with regenerative membrane.", \ "You cover wounds on [M]'s [affecting.name] with regenerative membrane." ) @@ -264,20 +277,23 @@ var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting) var/limb = affecting.name if(!(affecting.organ_tag in splintable_organs)) - user << "You can't use \the [src] to apply a splint there!" + to_chat(user, "You can't use \the [src] to apply a splint there!") return if(affecting.splinted) - user << "[M]'s [limb] is already splinted!" + to_chat(user, "[M]'s [limb] is already splinted!") return if (M != user) user.visible_message("[user] starts to apply \the [src] to [M]'s [limb].", "You start to apply \the [src] to [M]'s [limb].", "You hear something being wrapped.") else if(( !user.hand && (affecting.organ_tag in list(BP_R_ARM, BP_R_HAND)) || \ user.hand && (affecting.organ_tag in list(BP_L_ARM, BP_L_HAND)) )) - user << "You can't apply a splint to the arm you're using!" + to_chat(user, "You can't apply a splint to the arm you're using!") return user.visible_message("[user] starts to apply \the [src] to their [limb].", "You start to apply \the [src] to your [limb].", "You hear something being wrapped.") if(do_after(user, 50, M)) + if(affecting.splinted) + to_chat(user, "[M]'s [limb] is already splinted!") + return if(M == user && prob(75)) user.visible_message("\The [user] fumbles [src].", "You fumble [src].", "You hear something being wrapped.") return diff --git a/code/game/objects/items/stacks/nanopaste.dm b/code/game/objects/items/stacks/nanopaste.dm index 95803696d49..63a0df6d326 100644 --- a/code/game/objects/items/stacks/nanopaste.dm +++ b/code/game/objects/items/stacks/nanopaste.dm @@ -6,6 +6,7 @@ icon_state = "nanopaste" origin_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 3) amount = 10 + toolspeed = 0.75 //Used in surgery, shouldn't be the same speed as a normal screwdriver on mechanical organ repair. w_class = ITEMSIZE_SMALL no_variants = FALSE @@ -14,12 +15,13 @@ return 0 if (istype(M,/mob/living/silicon/robot)) //Repairing cyborgs var/mob/living/silicon/robot/R = M - if (R.getBruteLoss() || R.getFireLoss() ) - R.adjustBruteLoss(-15) - R.adjustFireLoss(-15) - R.updatehealth() - use(1) - user.visible_message("\The [user] applied some [src] on [R]'s damaged areas.",\ + if (R.getBruteLoss() || R.getFireLoss()) + if(do_after(user,7 * toolspeed)) + R.adjustBruteLoss(-15) + R.adjustFireLoss(-15) + R.updatehealth() + use(1) + user.visible_message("\The [user] applied some [src] on [R]'s damaged areas.",\ "You apply some [src] at [R]'s damaged areas.") else user << "All [R]'s systems are nominal." @@ -28,14 +30,17 @@ var/mob/living/carbon/human/H = M var/obj/item/organ/external/S = H.get_organ(user.zone_sel.selecting) - if(S.open >= 2) - if (S && (S.robotic >= ORGAN_ROBOT)) - if(!S.get_damage()) - user << "Nothing to fix here." - else if(can_use(1)) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) - S.heal_damage(15, 15, robo_repair = 1) - H.updatehealth() - use(1) - user.visible_message("\The [user] applies some nanite paste on [user != M ? "[M]'s [S.name]" : "[S]"] with [src].",\ - "You apply some nanite paste on [user == M ? "your" : "[M]'s"] [S.name].") + if (S && (S.robotic >= ORGAN_ROBOT)) + if(!S.get_damage()) + user << "Nothing to fix here." + else if(can_use(1)) + user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + if(S.open >= 2) + if(do_after(user,5 * toolspeed)) + S.heal_damage(20, 20, robo_repair = 1) + else if(do_after(user,5 * toolspeed)) + S.heal_damage(10,10, robo_repair =1) + H.updatehealth() + use(1) + user.visible_message("\The [user] applies some nanite paste on [user != M ? "[M]'s [S.name]" : "[S]"] with [src].",\ + "You apply some nanite paste on [user == M ? "your" : "[M]'s"] [S.name].") diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index 6065d6a514d..62f02816edf 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -699,54 +699,6 @@ desc = "A \"Space Life\" brand Emergency Response Team Commander action figure." icon_state = "ert" -/obj/item/toy/therapy_red - name = "red therapy doll" - desc = "A toy for therapeutic and recreational purposes. This one is red." - icon = 'icons/obj/toy.dmi' - icon_state = "therapyred" - item_state = "egg4" // It's the red egg in items_left/righthand - w_class = ITEMSIZE_TINY - -/obj/item/toy/therapy_purple - name = "purple therapy doll" - desc = "A toy for therapeutic and recreational purposes. This one is purple." - icon = 'icons/obj/toy.dmi' - icon_state = "therapypurple" - item_state = "egg1" // It's the magenta egg in items_left/righthand - w_class = ITEMSIZE_TINY - -/obj/item/toy/therapy_blue - name = "blue therapy doll" - desc = "A toy for therapeutic and recreational purposes. This one is blue." - icon = 'icons/obj/toy.dmi' - icon_state = "therapyblue" - item_state = "egg2" // It's the blue egg in items_left/righthand - w_class = ITEMSIZE_TINY - -/obj/item/toy/therapy_yellow - name = "yellow therapy doll" - desc = "A toy for therapeutic and recreational purposes. This one is yellow." - icon = 'icons/obj/toy.dmi' - icon_state = "therapyyellow" - item_state = "egg5" // It's the yellow egg in items_left/righthand - w_class = ITEMSIZE_TINY - -/obj/item/toy/therapy_orange - name = "orange therapy doll" - desc = "A toy for therapeutic and recreational purposes. This one is orange." - icon = 'icons/obj/toy.dmi' - icon_state = "therapyorange" - item_state = "egg4" // It's the red one again, lacking an orange item_state and making a new one is pointless - w_class = ITEMSIZE_TINY - -/obj/item/toy/therapy_green - name = "green therapy doll" - desc = "A toy for therapeutic and recreational purposes. This one is green." - icon = 'icons/obj/toy.dmi' - icon_state = "therapygreen" - item_state = "egg3" // It's the green egg in items_left/righthand - w_class = ITEMSIZE_TINY - /* * Plushies */ @@ -800,9 +752,10 @@ //Small plushies. /obj/item/toy/plushie name = "generic small plush" - desc = "A very generic small plushie. It seems to not want to exist." + desc = "A small toy plushie. It's very cute." icon = 'icons/obj/toy.dmi' icon_state = "nymphplushie" + w_class = ITEMSIZE_TINY var/last_message = 0 /obj/item/toy/plushie/attack_self(mob/user as mob) @@ -815,9 +768,24 @@ else if (user.a_intent == I_GRAB) user.visible_message("\The [user] attempts to strangle [src]!","You attempt to strangle [src]!") else - user.visible_message("\The [user] pokes the [src].","You poke the [src].") + user.visible_message("\The [user] pokes [src].","You poke [src].") last_message = world.time +/obj/item/toy/plushie/verb/rename_plushie() + set name = "Name Plushie" + set category = "Object" + set desc = "Give your plushie a cute name!" + var/mob/M = usr + if(!M.mind) + return 0 + + var/input = sanitizeSafe(input("What do you want to name the plushie?", ,""), MAX_NAME_LEN) + + if(src && input && !M.stat && in_range(M,src)) + name = input + to_chat(M, "You name the plushie [input], giving it a hug for good luck.") + return 1 + /obj/item/toy/plushie/nymph name = "diona nymph plush" desc = "A plushie of an adorable diona nymph! While its level of self-awareness is still being debated, its level of cuteness is not." @@ -830,7 +798,7 @@ /obj/item/toy/plushie/kitten name = "kitten plush" - desc = "A plushie of a cute kitten! Watch as it purrs it's way right into your heart." + desc = "A plushie of a cute kitten! Watch as it purrs its way right into your heart." icon_state = "kittenplushie" /obj/item/toy/plushie/lizard @@ -848,6 +816,49 @@ desc = "A farwa plush doll. It's soft and comforting!" icon_state = "farwaplushie" +/obj/item/toy/plushie/therapy/red + name = "red therapy doll" + desc = "A toy for therapeutic and recreational purposes. This one is red." + icon = 'icons/obj/toy.dmi' + icon_state = "therapyred" + item_state = "egg4" // It's the red egg in items_left/righthand + +/obj/item/toy/plushie/therapy/purple + name = "purple therapy doll" + desc = "A toy for therapeutic and recreational purposes. This one is purple." + icon = 'icons/obj/toy.dmi' + icon_state = "therapypurple" + item_state = "egg1" // It's the magenta egg in items_left/righthand + +/obj/item/toy/plushie/therapy/blue + name = "blue therapy doll" + desc = "A toy for therapeutic and recreational purposes. This one is blue." + icon = 'icons/obj/toy.dmi' + icon_state = "therapyblue" + item_state = "egg2" // It's the blue egg in items_left/righthand + +/obj/item/toy/plushie/therapy/yellow + name = "yellow therapy doll" + desc = "A toy for therapeutic and recreational purposes. This one is yellow." + icon = 'icons/obj/toy.dmi' + icon_state = "therapyyellow" + item_state = "egg5" // It's the yellow egg in items_left/righthand + +/obj/item/toy/plushie/therapy/orange + name = "orange therapy doll" + desc = "A toy for therapeutic and recreational purposes. This one is orange." + icon = 'icons/obj/toy.dmi' + icon_state = "therapyorange" + item_state = "egg4" // It's the red one again, lacking an orange item_state and making a new one is pointless + +/obj/item/toy/plushie/therapy/green + name = "green therapy doll" + desc = "A toy for therapeutic and recreational purposes. This one is green." + icon = 'icons/obj/toy.dmi' + icon_state = "therapygreen" + item_state = "egg3" // It's the green egg in items_left/righthand + + //Toy cult sword /obj/item/toy/cultsword name = "foam sword" diff --git a/code/game/objects/items/weapons/circuitboards/frame.dm b/code/game/objects/items/weapons/circuitboards/frame.dm index fa48be65bbf..b22c4ca6491 100644 --- a/code/game/objects/items/weapons/circuitboards/frame.dm +++ b/code/game/objects/items/weapons/circuitboards/frame.dm @@ -37,7 +37,7 @@ matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50) /obj/item/weapon/circuitboard/request - name = T_BOARD("reques console") + name = T_BOARD("request console") build_path = /obj/machinery/requests_console board_type = new /datum/frame/frame_types/supply_request_console matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50) @@ -202,6 +202,15 @@ /obj/item/weapon/reagent_containers/syringe = 3, /obj/item/stack/material/glass/reinforced = 2) +/obj/item/weapon/circuitboard/vr_sleeper + name = T_BOARD("VR sleeper") + build_path = /obj/machinery/vr_sleeper + board_type = new /datum/frame/frame_types/medical_pod + origin_tech = list(TECH_MAGNET = 2, TECH_BIO = 2) + req_components = list( + /obj/item/weapon/stock_parts/scanning_module = 1, + /obj/item/stack/material/glass/reinforced = 2) + /obj/item/weapon/circuitboard/dna_analyzer name = T_BOARD("dna analyzer") build_path = /obj/machinery/dnaforensics @@ -221,4 +230,4 @@ /obj/item/weapon/stock_parts/motor = 2, /obj/item/weapon/stock_parts/capacitor = 1, /obj/item/weapon/stock_parts/spring = 1, - /obj/item/stack/cable_coil = 5) \ No newline at end of file + /obj/item/stack/cable_coil = 5) diff --git a/code/game/objects/items/weapons/handcuffs.dm b/code/game/objects/items/weapons/handcuffs.dm index 0b4700ca6a7..897ac43ff4f 100644 --- a/code/game/objects/items/weapons/handcuffs.dm +++ b/code/game/objects/items/weapons/handcuffs.dm @@ -17,6 +17,7 @@ var/breakouttime = 1200 //Deciseconds = 120s = 2 minutes var/cuff_sound = 'sound/weapons/handcuffs.ogg' var/cuff_type = "handcuffs" + var/use_time = 30 sprite_sheets = list("Teshari" = 'icons/mob/species/seromi/handcuffs.dmi') /obj/item/weapon/handcuffs/attack(var/mob/living/carbon/C, var/mob/living/user) @@ -69,7 +70,7 @@ user.visible_message("\The [user] is attempting to put [cuff_type] on \the [H]!") - if(!do_after(user,30)) + if(!do_after(user,use_time)) return 0 if(!can_place(target, user)) //victim may have resisted out of the grab in the meantime @@ -199,6 +200,44 @@ var/last_chew = 0 elastic = 0 cuff_sound = 'sound/weapons/handcuffs.ogg' //This shold work for now. +/obj/item/weapon/handcuffs/legcuffs/bola + name = "bola" + desc = "Keeps prey in line." + elastic = 1 + use_time = 0 + breakouttime = 30 + cuff_sound = 'sound/weapons/towelwipe.ogg' //Is there anything this sound can't do? + +/obj/item/weapon/handcuffs/legcuffs/bola/can_place(var/mob/target, var/mob/user) + if(user) //A ranged legcuff, until proper implementation as items it remains a projectile-only thing. + return 1 + +/obj/item/weapon/handcuffs/legcuffs/bola/dropped() + visible_message("\The [src] falls apart!") + qdel(src) + +/obj/item/weapon/handcuffs/legcuffs/bola/place_legcuffs(var/mob/living/carbon/target, var/mob/user) + playsound(src.loc, cuff_sound, 30, 1, -2) + + var/mob/living/carbon/human/H = target + if(!istype(H)) + src.dropped() + return 0 + + if(!H.has_organ_for_slot(slot_legcuffed)) + H.visible_message("\The [src] slams into [H], but slides off!") + src.dropped() + return 0 + + H.visible_message("\The [H] has been snared by \the [src]!") + + // Apply cuffs. + var/obj/item/weapon/handcuffs/legcuffs/lcuffs = src + lcuffs.loc = target + target.legcuffed = lcuffs + target.update_inv_legcuffed() + return 1 + /obj/item/weapon/handcuffs/legcuffs/attack(var/mob/living/carbon/C, var/mob/living/user) if(!user.IsAdvancedToolUser()) return @@ -236,7 +275,7 @@ var/last_chew = 0 user.visible_message("\The [user] is attempting to put [cuff_type] on \the [H]!") - if(!do_after(user,30)) + if(!do_after(user,use_time)) return 0 if(!can_place(target, user)) //victim may have resisted out of the grab in the meantime diff --git a/code/game/objects/items/weapons/id cards/station_ids.dm b/code/game/objects/items/weapons/id cards/station_ids.dm index f075ea49f9e..e0975361eb7 100644 --- a/code/game/objects/items/weapons/id cards/station_ids.dm +++ b/code/game/objects/items/weapons/id cards/station_ids.dm @@ -373,8 +373,8 @@ job_access_type = /datum/job/bartender /obj/item/weapon/card/id/civilian/botanist - assignment = "Gardener" - rank = "Gardener" + assignment = "Botanist" + rank = "Botanist" job_access_type = /datum/job/hydro /obj/item/weapon/card/id/civilian/chaplain diff --git a/code/game/objects/items/weapons/material/knives.dm b/code/game/objects/items/weapons/material/knives.dm index 9545504f84e..7b6e6184f1c 100644 --- a/code/game/objects/items/weapons/material/knives.dm +++ b/code/game/objects/items/weapons/material/knives.dm @@ -92,3 +92,11 @@ desc = "A huge thing used for chopping and chopping up meat. This includes clowns and clown-by-products." force_divisor = 0.25 // 15 when wielded with hardness 60 (steel) attack_verb = list("cleaved", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") + +/obj/item/weapon/material/hatchet/tacknife/survival + name = "survival knife" + desc = "A hunting grade survival knife." + icon = 'icons/obj/kitchen.dmi' + icon_state = "survivalknife" + item_state = "knife" + applies_material_colour = FALSE diff --git a/code/game/objects/items/weapons/storage/belt.dm b/code/game/objects/items/weapons/storage/belt.dm index 38130f27395..6d261a8b3f0 100644 --- a/code/game/objects/items/weapons/storage/belt.dm +++ b/code/game/objects/items/weapons/storage/belt.dm @@ -247,6 +247,7 @@ icon = 'icons/obj/abductor.dmi' icon_state = "belt" item_state = "security" + storage_slots = 8 can_hold = list( /obj/item/device/healthanalyzer, /obj/item/weapon/dnainjector, @@ -284,6 +285,7 @@ new /obj/item/weapon/surgical/FixOVein/alien(src) new /obj/item/weapon/surgical/bone_clamp/alien(src) new /obj/item/weapon/surgical/cautery/alien(src) + new /obj/item/weapon/surgical/surgicaldrill/alien(src) /obj/item/weapon/storage/belt/champion name = "championship belt" diff --git a/code/game/objects/items/weapons/storage/storage.dm b/code/game/objects/items/weapons/storage/storage.dm index db55e95b44d..a3ca9a46013 100644 --- a/code/game/objects/items/weapons/storage/storage.dm +++ b/code/game/objects/items/weapons/storage/storage.dm @@ -426,12 +426,12 @@ for(var/obj/item/weapon/light/L in src.contents) if(L.status == 0) if(LP.uses < LP.max_uses) - LP.AddUses(1) + LP.add_uses(1) amt_inserted++ remove_from_storage(L, T) qdel(L) if(amt_inserted) - user << "You inserted [amt_inserted] light\s into \the [LP.name]. You have [LP.uses] light\s remaining." + to_chat(user, "You inserted [amt_inserted] light\s into \the [LP.name]. You have [LP.uses] light\s remaining.") return if(!can_be_inserted(W)) @@ -441,14 +441,14 @@ var/obj/item/weapon/tray/T = W if(T.calc_carry() > 0) if(prob(85)) - user << "The tray won't fit in [src]." + to_chat(user, "The tray won't fit in [src].") return else W.forceMove(get_turf(user)) if ((user.client && user.s_active != src)) user.client.screen -= W W.dropped(user) - user << "God damnit!" + to_chat(user, "God damn it!") W.add_fingerprint(user) return handle_item_insertion(W) @@ -506,9 +506,9 @@ collection_mode = !collection_mode switch (collection_mode) if(1) - usr << "[src] now picks up all items in a tile at once." + to_chat(usr, "[src] now picks up all items on a tile at once.") if(0) - usr << "[src] now picks up one item at a time." + to_chat(usr, "[src] now picks up one item at a time.") /obj/item/weapon/storage/verb/quick_empty() @@ -539,7 +539,7 @@ var/total_storage_space = 0 for(var/obj/item/I in contents) total_storage_space += I.get_storage_cost() - max_storage_space = max(total_storage_space,max_storage_space) //prevents spawned containers from being too small for their contents + max_storage_space = max(total_storage_space,max_storage_space) //Prevents spawned containers from being too small for their contents. src.boxes = new /obj/screen/storage( ) src.boxes.name = "storage" diff --git a/code/game/objects/items/weapons/storage/toolbox.dm b/code/game/objects/items/weapons/storage/toolbox.dm index 8391c90434a..ec3f3e26310 100644 --- a/code/game/objects/items/weapons/storage/toolbox.dm +++ b/code/game/objects/items/weapons/storage/toolbox.dm @@ -69,14 +69,24 @@ origin_tech = list(TECH_COMBAT = 1, TECH_ILLEGAL = 1) force = 14 -/obj/item/weapon/storage/toolbox/syndicate/New() +/obj/item/weapon/storage/toolbox/syndicate/New() // This is found in maint, so it should have the basics, plus some gloves. ..() new /obj/item/clothing/gloves/yellow(src) + new /obj/item/weapon/screwdriver(src) + new /obj/item/weapon/wrench(src) + new /obj/item/weapon/weldingtool(src) + new /obj/item/weapon/crowbar(src) + new /obj/item/weapon/wirecutters(src) + new /obj/item/device/multitool(src) + +/obj/item/weapon/storage/toolbox/syndicate/powertools/New() // Available in the uplink and is the 'real' syndie toolbox. + // ..() isn't called or else this box would contain the basic tools, power tools, and duplicate gloves. + new /obj/item/clothing/gloves/yellow(src) new /obj/item/weapon/screwdriver/power(src) - new /obj/item/stack/cable_coil/random(src,30) new /obj/item/weapon/weldingtool/experimental(src) new /obj/item/weapon/crowbar/power(src) new /obj/item/device/multitool(src) + new /obj/item/stack/cable_coil/random(src,30) new /obj/item/device/analyzer(src) /obj/item/weapon/storage/toolbox/lunchbox diff --git a/code/game/objects/items/weapons/teleportation.dm b/code/game/objects/items/weapons/teleportation.dm index b991db05109..33ed9f96e1d 100644 --- a/code/game/objects/items/weapons/teleportation.dm +++ b/code/game/objects/items/weapons/teleportation.dm @@ -133,7 +133,7 @@ Frequency: /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. + if(!current_location||current_location.z==2||current_location.z>=7 || current_location.block_tele)//If turf was not found or they're on z level 2 or >7 which does not currently exist. user << "\The [src] is malfunctioning." return var/list/L = list( ) @@ -148,6 +148,7 @@ Frequency: for(var/turf/T in orange(10)) if(T.x>world.maxx-8 || T.x<8) continue //putting them at the edge is dumb if(T.y>world.maxy-8 || T.y<8) continue + if(T.block_tele) continue turfs += T if(turfs.len) L["None (Dangerous)"] = pick(turfs) diff --git a/code/game/objects/items/weapons/tools.dm b/code/game/objects/items/weapons/tools.dm index 2c56cd690bd..045f910190a 100644 --- a/code/game/objects/items/weapons/tools.dm +++ b/code/game/objects/items/weapons/tools.dm @@ -656,6 +656,61 @@ nextrefueltick = world.time + 10 reagents.add_reagent("fuel", 1) +/* + * Backpack Welder. + */ + +/obj/item/weapon/weldingtool/tubefed + name = "tube-fed welding tool" + desc = "A bulky, cooler-burning welding tool that draws from a worn welding tank." + icon_state = "tubewelder" + max_fuel = 10 + w_class = ITEMSIZE_NO_CONTAINER + matter = null + toolspeed = 1.25 + change_icons = 0 + flame_intensity = 1 + eye_safety_modifier = 1 + always_process = TRUE + var/obj/item/weapon/weldpack/mounted_pack = null + +/obj/item/weapon/weldingtool/tubefed/New(location) + ..() + if(istype(location, /obj/item/weapon/weldpack)) + var/obj/item/weapon/weldpack/holder = location + mounted_pack = holder + else + qdel(src) + +/obj/item/weapon/weldingtool/tubefed/Destroy() + mounted_pack.nozzle = null + mounted_pack = null + return ..() + +/obj/item/weapon/weldingtool/tubefed/process() + if(mounted_pack) + if(!istype(mounted_pack.loc,/mob/living/carbon/human)) + mounted_pack.return_nozzle() + else + var/mob/living/carbon/human/H = mounted_pack.loc + if(H.back != mounted_pack) + mounted_pack.return_nozzle() + + if(mounted_pack.loc != src.loc && src.loc != mounted_pack) + mounted_pack.return_nozzle() + visible_message("\The [src] retracts to its fueltank.") + + if(get_fuel() <= get_max_fuel()) + mounted_pack.reagents.trans_to_obj(src, 1) + + ..() + +/obj/item/weapon/weldingtool/tubefed/dropped(mob/user) + ..() + if(src.loc != user) + mounted_pack.return_nozzle() + to_chat(user, "\The [src] retracts to its fueltank.") + /* * Electric/Arc Welder */ diff --git a/code/game/objects/items/weapons/weldbackpack.dm b/code/game/objects/items/weapons/weldbackpack.dm index 6a6d77521ec..0312ca55f8b 100644 --- a/code/game/objects/items/weapons/weldbackpack.dm +++ b/code/game/objects/items/weapons/weldbackpack.dm @@ -6,46 +6,140 @@ icon_state = "welderpack" w_class = ITEMSIZE_LARGE var/max_fuel = 350 + var/obj/item/weapon/nozzle = null //Attached welder, or other spray device. + var/nozzle_attached = 0 /obj/item/weapon/weldpack/New() var/datum/reagents/R = new/datum/reagents(max_fuel) //Lotsa refills reagents = R R.my_atom = src R.add_reagent("fuel", max_fuel) + nozzle = new/obj/item/weapon/weldingtool/tubefed(src) + nozzle_attached = 1 + +/obj/item/weapon/weldpack/Destroy() + qdel(nozzle) + nozzle = null + return ..() + +/obj/item/weapon/weldpack/dropped(mob/user) + ..() + if(nozzle) + user.remove_from_mob(nozzle) + return_nozzle() + to_chat(user, "\The [nozzle] retracts to its fueltank.") + +/obj/item/weapon/weldpack/proc/get_nozzle(var/mob/living/user) + if(!ishuman(user)) + return 0 + + var/mob/living/carbon/human/H = user + + if(H.hands_are_full()) //Make sure our hands aren't full. + to_chat(H, "Your hands are full. Drop something first.") + return 0 + + var/obj/item/weapon/F = nozzle + H.put_in_hands(F) + nozzle_attached = 0 + + return 1 + +/obj/item/weapon/weldpack/proc/return_nozzle(var/mob/living/user) + nozzle.forceMove(src) + nozzle_attached = 1 /obj/item/weapon/weldpack/attackby(obj/item/W as obj, mob/user as mob) - if(istype(W, /obj/item/weapon/weldingtool)) + if(istype(W, /obj/item/weapon/weldingtool) && !(W == nozzle)) var/obj/item/weapon/weldingtool/T = W if(T.welding & prob(50)) message_admins("[key_name_admin(user)] triggered a fueltank explosion.") log_game("[key_name(user)] triggered a fueltank explosion.") - user << "That was stupid of you." + to_chat(user,"That was stupid of you.") explosion(get_turf(src),-1,0,2) if(src) qdel(src) return - else + else if(T.status) if(T.welding) - user << "That was close!" + to_chat(user,"That was close!") src.reagents.trans_to_obj(W, T.max_fuel) - user << "Welder refilled!" + to_chat(user, "Welder refilled!") playsound(src.loc, 'sound/effects/refill.ogg', 50, 1, -6) return - user << "The tank scoffs at your insolence. It only provides services to welders." + else if(nozzle) + if(nozzle == W) + if(!user.unEquip(W)) + to_chat(user,"\The [W] seems to be stuck to your hand.") + return + if(!nozzle_attached) + return_nozzle() + to_chat(user,"You attach \the [W] to the [src].") + return + else + to_chat(user,"The [src] already has a nozzle!") + else + to_chat(user,"The tank scoffs at your insolence. It only provides services to welders.") return +/obj/item/weapon/weldpack/attack_hand(mob/user as mob) + if(istype(user, /mob/living/carbon/human)) + var/mob/living/carbon/human/wearer = user + if(wearer.back == src) + if(nozzle && nozzle_attached) + if(!wearer.incapacitated()) + get_nozzle(user) + else + to_chat(user,"\The [src] does not have a nozzle attached!") + else + ..() + else + ..() + /obj/item/weapon/weldpack/afterattack(obj/O as obj, mob/user as mob, proximity) if(!proximity) // this replaces and improves the get_dist(src,O) <= 1 checks used previously return if (istype(O, /obj/structure/reagent_dispensers/fueltank) && src.reagents.total_volume < max_fuel) O.reagents.trans_to_obj(src, max_fuel) - user << "You crack the cap off the top of the pack and fill it back up again from the tank." + to_chat(user,"You crack the cap off the top of the pack and fill it back up again from the tank.") playsound(src.loc, 'sound/effects/refill.ogg', 50, 1, -6) return else if (istype(O, /obj/structure/reagent_dispensers/fueltank) && src.reagents.total_volume == max_fuel) - user << "The pack is already full!" + to_chat(user,"The pack is already full!") return +/obj/item/weapon/weldpack/MouseDrop(obj/over_object as obj) //This is terrifying. + if(!canremove) + return + + if (ishuman(usr) || issmall(usr)) //so monkeys can take off their backpacks -- Urist + + if (istype(usr.loc,/obj/mecha)) // stops inventory actions in a mech. why? + return + + if (!( istype(over_object, /obj/screen) )) + return ..() + + //makes sure that the thing is equipped, so that we can't drag it into our hand from miles away. + //there's got to be a better way of doing this. + if (!(src.loc == usr) || (src.loc && src.loc.loc == usr)) + return + + if (( usr.restrained() ) || ( usr.stat )) + return + + if ((src.loc == usr) && !(istype(over_object, /obj/screen)) && !usr.unEquip(src)) + return + + switch(over_object.name) + if("r_hand") + usr.u_equip(src) + usr.put_in_r_hand(src) + if("l_hand") + usr.u_equip(src) + usr.put_in_l_hand(src) + src.add_fingerprint(usr) + /obj/item/weapon/weldpack/examine(mob/user) ..(user) user << text("\icon[] [] units of fuel left!", src, src.reagents.total_volume) diff --git a/code/game/objects/random/random.dm b/code/game/objects/random/random.dm index c15b454878a..d23f18e9bb3 100644 --- a/code/game/objects/random/random.dm +++ b/code/game/objects/random/random.dm @@ -313,7 +313,6 @@ prob(2);/obj/item/weapon/gun/projectile/shotgun/pump/combat, prob(4);/obj/item/weapon/gun/projectile/shotgun/pump/rifle, prob(3);/obj/item/weapon/gun/projectile/shotgun/pump/rifle/lever, - prob(3);/obj/item/weapon/gun/projectile/shotgun/pump/rifle/mosin, prob(2);/obj/item/weapon/gun/projectile/silenced) /obj/random/projectile/sec @@ -504,12 +503,12 @@ /obj/random/toy/item_to_spawn() return pick(/obj/item/toy/bosunwhistle, - /obj/item/toy/therapy_red, - /obj/item/toy/therapy_purple, - /obj/item/toy/therapy_blue, - /obj/item/toy/therapy_yellow, - /obj/item/toy/therapy_orange, - /obj/item/toy/therapy_green, + /obj/item/toy/plushie/therapy/red, + /obj/item/toy/plushie/therapy/purple, + /obj/item/toy/plushie/therapy/blue, + /obj/item/toy/plushie/therapy/yellow, + /obj/item/toy/plushie/therapy/orange, + /obj/item/toy/plushie/therapy/green, /obj/item/toy/cultsword, /obj/item/toy/katana, /obj/item/toy/snappop, @@ -1060,4 +1059,22 @@ var/list/multi_point_spawns /obj/item/clothing/suit/space/void/security/riot, /obj/item/clothing/head/helmet/space/void/security/riot ) + ) + +/obj/random/multiple/voidsuit/mining + name = "Random Mining Voidsuit" + desc = "This is a random mining voidsuit." + icon = 'icons/obj/clothing/suits.dmi' + icon_state = "rig-mining" + +/obj/random/multiple/voidsuit/mining/item_to_spawn() + return pick( + prob(5);list( + /obj/item/clothing/suit/space/void/mining, + /obj/item/clothing/head/helmet/space/void/mining + ), + prob(1);list( + /obj/item/clothing/suit/space/void/mining/alt, + /obj/item/clothing/head/helmet/space/void/mining/alt + ) ) \ No newline at end of file diff --git a/code/game/objects/structures/alien_props.dm b/code/game/objects/structures/alien_props.dm new file mode 100644 index 00000000000..cb791ec54b8 --- /dev/null +++ b/code/game/objects/structures/alien_props.dm @@ -0,0 +1,79 @@ +// These contain structures to make certain 'alien' (as in the ayyy ones, not xenomorphs) submaps more filled, and don't really do anything. + +/obj/structure/prop/alien + name = "some alien thing" + desc = "My description is broken, bug a developer." + icon = 'icons/obj/abductor.dmi' + density = TRUE + anchored = TRUE + var/interaction_message = null + +/obj/structure/prop/alien/attack_hand(mob/living/user) // Used to tell the player that this isn't useful for anything. + if(!istype(user)) + return FALSE + if(!interaction_message) + return ..() + else + to_chat(user, interaction_message) + +/obj/structure/prop/alien/computer + name = "alien console" + desc = "The console flashes what appear to be symbols you've never seen before." + icon_state = "console-c" + interaction_message = "The console flashes a series of unknown symbols as you press a button on what is presumably a keyboard. It probably some sort of \ + authentication error. Since you're not an alien, you should probably leave it alone." + +/obj/structure/prop/alien/computer/camera + desc = "This console is briefly flashing video feeds of various locations close by." + icon_state = "camera" + +/obj/structure/prop/alien/computer/camera/flipped + icon_state = "camera_flipped" + +/obj/structure/prop/alien/dispenser + name = "alien dispenser" + desc = "This looks like it dispenses... something?" + icon_state = "dispenser" + interaction_message = "You don't see any mechanism to operate this. Probably for the best." + +/obj/structure/prop/alien/pod + name = "alien pod" + desc = "This seems to be a container for something." + icon_state = "experiment" + interaction_message = "You don't see any mechanism to open this thing. Probably for the best." + +/obj/structure/prop/alien/pod/open + name = "opened alien pod" + desc = "At one point, this probably contained something interesting..." + icon_state = "experiment-open" + interaction_message = "You don't see any mechanism to close this thing." + +/obj/structure/prop/alien/power + name = "void core" + icon_state = "core" + desc = "An alien machine that seems to be producing energy seemingly out of nowhere." + interaction_message = "Messing with something that makes energy out of nowhere seems very unwise." + +/obj/item/prop/alien + name = "some alien item" + desc = "My description is broken, bug a developer." + icon = 'icons/obj/abductor.dmi' + +// Mostly useless. Research might like it, however. +/obj/item/prop/alien/junk + name = "alien object" + desc = "You have no idea what this thing does." + icon_state = "health" + w_class = ITEMSIZE_SMALL + var/static/list/possible_states = list("health", "spider", "slime", "emp", "species", "egg", "vent", "mindshock", "viral", "gland") + var/static/list/possible_tech = list(TECH_MATERIAL, TECH_ENGINEERING, TECH_PHORON, TECH_POWER, TECH_BIO, TECH_COMBAT, TECH_MAGNET, TECH_DATA) + +/obj/item/prop/alien/junk/initialize() + ..() + icon_state = pick(possible_states) + var/list/techs = possible_tech.Copy() + origin_tech = list() + for(var/i = 1 to rand(1, 4)) + var/new_tech = pick(techs) + techs -= new_tech + origin_tech[new_tech] = rand(5, 9) \ No newline at end of file diff --git a/code/game/objects/structures/crates_lockers/closets/fireaxe.dm b/code/game/objects/structures/crates_lockers/closets/fireaxe.dm index fe838a5291f..0af7913df8f 100644 --- a/code/game/objects/structures/crates_lockers/closets/fireaxe.dm +++ b/code/game/objects/structures/crates_lockers/closets/fireaxe.dm @@ -36,7 +36,7 @@ playsound(user, 'sound/machines/lockreset.ogg', 50, 1) if(do_after(user, 20 * O.toolspeed)) src.locked = 0 - user << " You disable the locking modules." + to_chat(user, " You disable the locking modules.") update_icon() return else if(istype(O, /obj/item/weapon)) @@ -50,7 +50,7 @@ else playsound(user, 'sound/effects/Glasshit.ogg', 100, 1) //We don't want this playing every time if(W.force < 15) - user << "The cabinet's protective glass glances off the hit." + to_chat(user, "The cabinet's protective glass glances off the hit.") else src.hitstaken++ if(src.hitstaken == 4) @@ -63,12 +63,14 @@ if (istype(O, /obj/item/weapon/material/twohanded/fireaxe) && src.localopened) if(!fireaxe) if(O:wielded) - user << "Unwield the axe first." - return + O:wielded = 0 + O.update_icon() + //to_chat(user, "Unwield the axe first.") + //return fireaxe = O user.remove_from_mob(O) src.contents += O - user << "You place the fire axe back in the [src.name]." + to_chat(user, "You place the fire axe back in the [src.name].") update_icon() else if(src.smashed) @@ -91,11 +93,11 @@ spawn(10) update_icon() return else - user << "Resetting circuitry..." + to_chat(user, "Resetting circuitry...") playsound(user, 'sound/machines/lockenable.ogg', 50, 1) if(do_after(user,20 * O.toolspeed)) src.locked = 1 - user << " You re-enable the locking modules." + to_chat(user, " You re-enable the locking modules.") return else localopened = !localopened @@ -116,13 +118,13 @@ hasaxe = 1 if(src.locked) - user <<"The cabinet won't budge!" + to_chat(user, "The cabinet won't budge!") return if(localopened) if(fireaxe) user.put_in_hands(fireaxe) fireaxe = null - user << "You take the fire axe from the [name]." + to_chat (user, "You take the fire axe from the [name].") src.add_fingerprint(user) update_icon() else @@ -149,7 +151,7 @@ attack_tk(mob/user as mob) if(localopened && fireaxe) fireaxe.forceMove(loc) - user << "You telekinetically remove the fire axe." + to_chat(user, "You telekinetically remove the fire axe.") fireaxe = null update_icon() return @@ -161,9 +163,9 @@ if (isrobot(usr) || src.locked || src.smashed) if(src.locked) - usr << "The cabinet won't budge!" + to_chat(usr, "The cabinet won't budge!") else if(src.smashed) - usr << "The protective glass is broken!" + to_chat(usr, "The protective glass is broken!") return localopened = !localopened @@ -180,23 +182,23 @@ if(fireaxe) usr.put_in_hands(fireaxe) fireaxe = null - usr << "You take the Fire axe from the [name]." + to_chat(usr, "You take the Fire axe from the [name].") else - usr << "The [src.name] is empty." + to_chat(usr, "The [src.name] is empty.") else - usr << "The [src.name] is closed." + to_chat(usr, "The [src.name] is closed.") update_icon() attack_ai(mob/user as mob) if(src.smashed) - user << "The security of the cabinet is compromised." + to_chat(user, "The security of the cabinet is compromised.") return else locked = !locked if(locked) - user << "Cabinet locked." + to_chat(user, "Cabinet locked.") else - user << "Cabinet unlocked." + to_chat(user, "Cabinet unlocked.") return update_icon() //Template: fireaxe[has fireaxe][is opened][hits taken][is smashed]. If you want the opening or closing animations, add "opening" or "closing" right after the numbers diff --git a/code/game/objects/structures/crates_lockers/closets/gimmick.dm b/code/game/objects/structures/crates_lockers/closets/gimmick.dm index 3a6b7ac0452..8ebd9358b5d 100644 --- a/code/game/objects/structures/crates_lockers/closets/gimmick.dm +++ b/code/game/objects/structures/crates_lockers/closets/gimmick.dm @@ -134,3 +134,12 @@ new /obj/item/clothing/head/helmet/thunderdome(src) new /obj/item/clothing/head/helmet/thunderdome(src) new /obj/item/clothing/head/helmet/thunderdome(src) + +/obj/structure/closet/alien + name = "alien container" + desc = "Contains secrets of the universe." + icon = 'icons/obj/abductor.dmi' + icon_state = "alien_locker" + icon_closed = "alien_locker" + icon_opened = "alien_locker_open" + anchored = TRUE \ No newline at end of file diff --git a/code/game/objects/structures/crates_lockers/closets/secure/medical.dm b/code/game/objects/structures/crates_lockers/closets/secure/medical.dm index 92bc2ab4699..9e5f0b7815c 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/medical.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/medical.dm @@ -204,7 +204,7 @@ new /obj/item/device/radio/headset/heads/cmo(src) new /obj/item/device/radio/headset/heads/cmo/alt(src) new /obj/item/device/flash(src) - new /obj/item/weapon/reagent_containers/hypospray(src) + new /obj/item/weapon/reagent_containers/hypospray/vial(src) new /obj/item/clothing/suit/storage/hooded/wintercoat/medical(src) new /obj/item/clothing/shoes/boots/winter/medical(src) new /obj/item/weapon/storage/box/freezer(src) @@ -243,21 +243,17 @@ New() ..() - new /obj/item/clothing/under/rank/psych(src) - new /obj/item/clothing/under/rank/psych/turtleneck(src) - new /obj/item/clothing/suit/straight_jacket(src) - new /obj/item/weapon/reagent_containers/glass/bottle/stoxin(src) - new /obj/item/weapon/reagent_containers/syringe(src) - new /obj/item/weapon/storage/pill_bottle/citalopram(src) - new /obj/item/weapon/reagent_containers/pill/methylphenidate(src) - new /obj/item/weapon/clipboard(src) - new /obj/item/weapon/folder/white(src) - new /obj/item/device/taperecorder(src) - new /obj/item/device/tape/random(src) - new /obj/item/device/tape/random(src) - new /obj/item/device/tape/random(src) - new /obj/item/device/camera(src) - new /obj/item/toy/therapy_blue(src) + new /obj/item/weapon/storage/box/pillbottles(src) + new /obj/item/weapon/storage/box/pillbottles(src) + new /obj/item/weapon/storage/box/beakers(src) + new /obj/item/weapon/storage/box/autoinjectors(src) + new /obj/item/weapon/storage/box/syringes(src) + new /obj/item/weapon/reagent_containers/dropper(src) + new /obj/item/weapon/reagent_containers/dropper(src) + new /obj/item/weapon/reagent_containers/glass/bottle/inaprovaline(src) + new /obj/item/weapon/reagent_containers/glass/bottle/inaprovaline(src) + new /obj/item/weapon/reagent_containers/glass/bottle/antitoxin(src) + new /obj/item/weapon/reagent_containers/glass/bottle/antitoxin(src) return /obj/structure/closet/secure_closet/psych @@ -274,8 +270,21 @@ New() ..() - new /obj/item/weapon/storage/box/pillbottles(src) - new /obj/item/weapon/storage/box/pillbottles(src) + new /obj/item/clothing/under/rank/psych(src) + new /obj/item/clothing/under/rank/psych/turtleneck(src) + new /obj/item/clothing/suit/straight_jacket(src) + new /obj/item/weapon/reagent_containers/glass/bottle/stoxin(src) + new /obj/item/weapon/reagent_containers/syringe(src) + new /obj/item/weapon/storage/pill_bottle/citalopram(src) + new /obj/item/weapon/reagent_containers/pill/methylphenidate(src) + new /obj/item/weapon/clipboard(src) + new /obj/item/weapon/folder/white(src) + new /obj/item/device/taperecorder(src) + new /obj/item/device/tape/random(src) + new /obj/item/device/tape/random(src) + new /obj/item/device/tape/random(src) + new /obj/item/device/camera(src) + new /obj/item/toy/plushie/therapy/blue(src) return /obj/structure/closet/secure_closet/medical_wall 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 d863aecd24b..83aa687957a 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm @@ -276,15 +276,13 @@ ..() new /obj/item/clothing/accessory/badge/holo/detective(src) new /obj/item/clothing/gloves/black(src) + new /obj/item/gunbox(src) new /obj/item/weapon/storage/belt/detective(src) new /obj/item/weapon/storage/box/evidence(src) new /obj/item/device/radio/headset/headset_sec(src) new /obj/item/device/radio/headset/headset_sec/alt(src) new /obj/item/clothing/suit/storage/vest/detective(src) - new /obj/item/ammo_magazine/m45/rubber(src) - new /obj/item/ammo_magazine/m45/rubber(src) new /obj/item/taperoll/police(src) - new /obj/item/weapon/gun/projectile/colt/detective(src) new /obj/item/clothing/accessory/holster/armpit(src) new /obj/item/device/flashlight/maglight(src) new /obj/item/weapon/reagent_containers/food/drinks/flask/detflask(src) diff --git a/code/game/objects/structures/door_assembly.dm b/code/game/objects/structures/door_assembly.dm index 7d1810c46fc..f63290c0104 100644 --- a/code/game/objects/structures/door_assembly.dm +++ b/code/game/objects/structures/door_assembly.dm @@ -117,6 +117,12 @@ base_icon_state = "voidcraft_vertical" airlock_type = "/voidcraft/vertical" +/obj/structure/door_assembly/door_assembly_alien + base_icon_state = "alien" + base_name = "alien airlock" + airlock_type = "/alien" + glass = -1 + /obj/structure/door_assembly/multi_tile icon = 'icons/obj/doors/door_assembly2x1.dmi' dir = EAST diff --git a/code/game/objects/structures/fitness.dm b/code/game/objects/structures/fitness.dm new file mode 100644 index 00000000000..3bb158a576b --- /dev/null +++ b/code/game/objects/structures/fitness.dm @@ -0,0 +1,65 @@ +/obj/structure/fitness + icon = 'icons/obj/stationobjs.dmi' + anchored = 1 + var/being_used = 0 + +/obj/structure/fitness/punchingbag + name = "punching bag" + desc = "A punching bag." + icon_state = "punchingbag" + density = 1 + var/list/hit_message = list("hit", "punch", "kick", "robust") + +/obj/structure/fitness/punchingbag/attack_hand(var/mob/living/carbon/human/user) + if(!istype(user)) + ..() + return + if(user.nutrition < 20) + to_chat(user, "You need more energy to use the punching bag. Go eat something.") + else + if(user.a_intent == I_HURT) + user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + flick("[icon_state]_hit", src) + playsound(src.loc, 'sound/effects/woodhit.ogg', 25, 1, -1) + user.do_attack_animation(src) + user.nutrition = user.nutrition - 5 + to_chat(user, "You [pick(hit_message)] \the [src].") + +/obj/structure/fitness/weightlifter + name = "weightlifting machine" + desc = "A machine used to lift weights." + icon_state = "weightlifter" + var/weight = 1 + var/list/qualifiers = list("with ease", "without any trouble", "with great effort") + +/obj/structure/fitness/weightlifter/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(istype(W, /obj/item/weapon/wrench)) + playsound(src.loc, 'sound/items/Deconstruct.ogg', 75, 1) + weight = ((weight) % qualifiers.len) + 1 + to_chat(user, "You set the machine's weight level to [weight].") + +/obj/structure/fitness/weightlifter/attack_hand(var/mob/living/carbon/human/user) + if(!istype(user)) + return + if(user.loc != src.loc) + to_chat(user, "You must be on the weight machine to use it.") + return + if(user.nutrition < 50) + to_chat(user, "You need more energy to lift weights. Go eat something.") + return + if(being_used) + to_chat(user, "The weight machine is already in use by somebody else.") + return + else + being_used = 1 + playsound(src.loc, 'sound/effects/weightlifter.ogg', 50, 1) + user.set_dir(SOUTH) + flick("[icon_state]_[weight]", src) + if(do_after(user, 20 + (weight * 10))) + playsound(src.loc, 'sound/effects/weightdrop.ogg', 25, 1) + user.nutrition -= weight * 10 + to_chat(user, "You lift the weights [qualifiers[weight]].") + being_used = 0 + else + to_chat(user, "Against your previous judgement, perhaps working out is not for you.") + being_used = 0 diff --git a/code/game/objects/structures/ghost_pods/ghost_pods.dm b/code/game/objects/structures/ghost_pods/ghost_pods.dm index 7beba29caac..9eeefeee618 100644 --- a/code/game/objects/structures/ghost_pods/ghost_pods.dm +++ b/code/game/objects/structures/ghost_pods/ghost_pods.dm @@ -22,6 +22,8 @@ if(winner.len) var/mob/observer/dead/D = winner[1] create_occupant(D) + new /obj/machinery/recharge_station/ghost_pod_recharger(src.loc) + del(src) return TRUE else return FALSE @@ -29,7 +31,6 @@ // Override this to create whatever mob you need. Be sure to call ..() if you don't want it to make infinite mobs. /obj/structure/ghost_pod/proc/create_occupant(var/mob/M) used = TRUE - icon_state = icon_state_opened return TRUE diff --git a/code/game/objects/structures/kitchen_spike.dm b/code/game/objects/structures/kitchen_spike.dm index 8271c3a0d52..42b78841695 100644 --- a/code/game/objects/structures/kitchen_spike.dm +++ b/code/game/objects/structures/kitchen_spike.dm @@ -1,7 +1,7 @@ //////Kitchen Spike /obj/structure/kitchenspike - name = "a meat spike" + name = "meat spike" icon = 'icons/obj/kitchen.dmi' icon_state = "spike" desc = "A spike for collecting meat from animals." @@ -16,16 +16,16 @@ if(!istype(G, /obj/item/weapon/grab) || !ismob(G.affecting)) return if(occupied) - user << "The spike already has something on it, finish collecting its meat first!" + to_chat(user, "The spike already has something on it, finish collecting its meat first!") else if(spike(G.affecting)) - visible_message("[user] has forced [G.affecting] onto the spike, killing them instantly!") + visible_message("[user] has forced [G.affecting] onto the spike, killing \him instantly!") var/mob/M = G.affecting M.forceMove(src) qdel(G) qdel(M) else - user << "They are too big for the spike, try something smaller!" + to_chat(user, "They are too big for the spike, try something smaller!") /obj/structure/kitchenspike/proc/spike(var/mob/living/victim) if(!istype(victim)) @@ -33,10 +33,11 @@ if(istype(victim, /mob/living/carbon/human)) var/mob/living/carbon/human/H = victim - if(!issmall(H)) + if(istype(H.species, /datum/species/monkey)) + meat_type = H.species.meat_type + icon_state = "spikebloody" + else return 0 - meat_type = H.species.meat_type - icon_state = "spikebloody" else if(istype(victim, /mob/living/carbon/alien)) meat_type = /obj/item/weapon/reagent_containers/food/snacks/xenomeat icon_state = "spikebloodygreen" @@ -54,8 +55,8 @@ meat-- new meat_type(get_turf(src)) if(meat > 1) - user << "You remove some meat from \the [victim_name]." + to_chat(user, "You cut some meat from \the [victim_name]'s body.") else if(meat == 1) - user << "You remove the last piece of meat from \the [victim_name]!" + to_chat(user, "You remove the last piece of meat from \the [victim_name]!") icon_state = "spike" occupied = 0 diff --git a/code/game/objects/structures/loot_piles.dm b/code/game/objects/structures/loot_piles.dm index daa6e8c94ac..0d92af11b29 100644 --- a/code/game/objects/structures/loot_piles.dm +++ b/code/game/objects/structures/loot_piles.dm @@ -435,3 +435,89 @@ Loot piles can be depleted, if loot_depleted is turned on. Note that players wh loot_depletion = TRUE loot_left = 5 // This is to prevent people from asking the whole station to go down to some alien ruin to get massive amounts of phat lewt. +// Base type for alien piles. +/obj/structure/loot_pile/surface/alien + name = "alien pod" + desc = "A pod which looks bigger on the inside. Something quiet shiny might be inside?" + icon_state = "alien_pile1" + +/obj/structure/loot_pile/surface/alien + common_loot = list( + /obj/item/prop/alien/junk + ) + +// May contain alien tools. +/obj/structure/loot_pile/surface/alien/engineering + uncommon_loot = list( + /obj/item/device/multitool/alien, + /obj/item/stack/cable_coil/alien, + /obj/item/weapon/crowbar/alien, + /obj/item/weapon/screwdriver/alien, + /obj/item/weapon/weldingtool/alien, + /obj/item/weapon/wirecutters/alien, + /obj/item/weapon/wrench/alien + ) + rare_loot = list( + /obj/item/weapon/storage/belt/utility/alien/full + ) + +// May contain alien surgery equipment or powerful medication. +/obj/structure/loot_pile/surface/alien/medical + uncommon_loot = list( + /obj/item/weapon/surgical/FixOVein/alien, + /obj/item/weapon/surgical/bone_clamp/alien, + /obj/item/weapon/surgical/cautery/alien, + /obj/item/weapon/surgical/circular_saw/alien, + /obj/item/weapon/surgical/hemostat/alien, + /obj/item/weapon/surgical/retractor/alien, + /obj/item/weapon/surgical/scalpel/alien, + /obj/item/weapon/surgical/surgicaldrill/alien + ) + rare_loot = list( + /obj/item/weapon/storage/belt/medical/alien + ) + +// May contain powercells or alien weaponry. +/obj/structure/loot_pile/surface/alien/security + uncommon_loot = list( + /obj/item/weapon/cell/device/weapon/recharge/alien, + /obj/item/clothing/suit/armor/alien, + /obj/item/clothing/head/helmet/alien + ) + rare_loot = list( + /obj/item/clothing/suit/armor/alien/tank, + /obj/item/weapon/gun/energy/alien + ) + +// The pile found at the very end, and as such has the best loot. +/obj/structure/loot_pile/surface/alien/end + chance_uncommon = 30 + chance_rare = 10 + + common_loot = list( + /obj/item/device/multitool/alien, + /obj/item/stack/cable_coil/alien, + /obj/item/weapon/crowbar/alien, + /obj/item/weapon/screwdriver/alien, + /obj/item/weapon/weldingtool/alien, + /obj/item/weapon/wirecutters/alien, + /obj/item/weapon/wrench/alien, + /obj/item/weapon/surgical/FixOVein/alien, + /obj/item/weapon/surgical/bone_clamp/alien, + /obj/item/weapon/surgical/cautery/alien, + /obj/item/weapon/surgical/circular_saw/alien, + /obj/item/weapon/surgical/hemostat/alien, + /obj/item/weapon/surgical/retractor/alien, + /obj/item/weapon/surgical/scalpel/alien, + /obj/item/weapon/surgical/surgicaldrill/alien, + /obj/item/weapon/cell/device/weapon/recharge/alien, + /obj/item/clothing/suit/armor/alien, + /obj/item/clothing/head/helmet/alien, + /obj/item/weapon/gun/energy/alien + ) + uncommon_loot = list( + /obj/item/weapon/storage/belt/medical/alien, + /obj/item/weapon/storage/belt/utility/alien/full, + /obj/item/clothing/suit/armor/alien/tank, + /obj/item/clothing/head/helmet/alien/tank, + ) diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm index 42ee6af2e3e..c457e3ae2cc 100644 --- a/code/game/objects/structures/morgue.dm +++ b/code/game/objects/structures/morgue.dm @@ -77,6 +77,9 @@ return return +/obj/structure/morgue/attack_robot(mob/user) + if(Adjacent(user)) + attack_hand(user) /obj/structure/morgue/attack_hand(mob/user as mob) if (src.connected) @@ -156,6 +159,10 @@ connected = null return ..() +/obj/structure/m_tray/attack_robot(mob/user) + if(Adjacent(user)) + attack_hand(user) + /obj/structure/m_tray/attack_hand(mob/user as mob) if (src.connected) for(var/atom/movable/A as mob|obj in src.loc) @@ -181,7 +188,7 @@ if (user != O) for(var/mob/B in viewers(user, 3)) if ((B.client && !( B.blinded ))) - B << "\The [user] stuffs [O] into [src]!" + to_chat(B, "\The [user] stuffs [O] into [src]!") return @@ -189,25 +196,16 @@ * Crematorium */ -/obj/structure/crematorium +/obj/structure/morgue/crematorium name = "crematorium" desc = "A human incinerator. Works well on barbeque nights." icon = 'icons/obj/stationobjs.dmi' icon_state = "crema1" - density = 1 - var/obj/structure/c_tray/connected = null - anchored = 1.0 var/cremating = 0 var/id = 1 var/locked = 0 -/obj/structure/crematorium/Destroy() - if(connected) - qdel(connected) - connected = null - return ..() - -/obj/structure/crematorium/proc/update() +/obj/structure/morgue/crematorium/update() if (src.connected) src.icon_state = "crema0" else @@ -217,37 +215,7 @@ src.icon_state = "crema1" return -/obj/structure/crematorium/ex_act(severity) - switch(severity) - if(1.0) - for(var/atom/movable/A as mob|obj in src) - A.forceMove(src.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) - ex_act(severity) - qdel(src) - return - if(3.0) - if (prob(5)) - for(var/atom/movable/A as mob|obj in src) - A.forceMove(src.loc) - ex_act(severity) - qdel(src) - return - return - -/obj/structure/crematorium/attack_hand(mob/user as mob) -// if (cremating) AWW MAN! THIS WOULD BE SO MUCH MORE FUN ... TO WATCH -// user.show_message("Uh-oh, that was a bad idea.", 1) -// //usr << "Uh-oh, that was a bad idea." -// src:loc:poison += 20000000 -// src:loc:firelevel = src:loc:poison -// return +/obj/structure/morgue/crematorium/attack_hand(mob/user as mob) if (cremating) usr << "It's locked." return @@ -260,10 +228,10 @@ qdel(src.connected) else if (src.locked == 0) playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1) - src.connected = new /obj/structure/c_tray( src.loc ) - step(src.connected, SOUTH) + src.connected = new /obj/structure/m_tray/c_tray( src.loc ) + step(src.connected, EAST) src.connected.layer = OBJ_LAYER - var/turf/T = get_step(src, SOUTH) + var/turf/T = get_step(src, EAST) if (T.contents.Find(src.connected)) src.connected.connected = src src.icon_state = "crema0" @@ -276,7 +244,7 @@ src.add_fingerprint(user) update() -/obj/structure/crematorium/attackby(P as obj, mob/user as mob) +/obj/structure/morgue/crematorium/attackby(P as obj, mob/user as mob) if (istype(P, /obj/item/weapon/pen)) var/t = input(user, "What would you like the label to be?", text("[]", src.name), null) as text if (user.get_active_hand() != P) @@ -291,13 +259,13 @@ src.add_fingerprint(user) return -/obj/structure/crematorium/relaymove(mob/user as mob) +/obj/structure/morgue/crematorium/relaymove(mob/user as mob) if (user.stat || locked) return - src.connected = new /obj/structure/c_tray( src.loc ) - step(src.connected, SOUTH) + src.connected = new /obj/structure/m_tray/c_tray( src.loc ) + step(src.connected, EAST) src.connected.layer = OBJ_LAYER - var/turf/T = get_step(src, SOUTH) + var/turf/T = get_step(src, EAST) if (T.contents.Find(src.connected)) src.connected.connected = src src.icon_state = "crema0" @@ -309,25 +277,22 @@ src.connected = null return -/obj/structure/crematorium/proc/cremate(atom/A, mob/user as mob) -// for(var/obj/machinery/crema_switch/O in src) //trying to figure a way to call the switch, too drunk to sort it out atm -// if(var/on == 1) -// return +/obj/structure/morgue/crematorium/proc/cremate(atom/A, mob/user as mob) if(cremating) return //don't let you cremate something twice or w/e if(contents.len <= 0) for (var/mob/M in viewers(src)) - M.show_message("You hear a hollow crackle.", 1) + to_chat(M,"You hear a hollow crackle.") return else if(!isemptylist(src.search_contents_for(/obj/item/weapon/disk/nuclear))) - usr << "You get the feeling that you shouldn't cremate one of the items in the cremator." + to_chat(user,"You get the feeling that you shouldn't cremate one of the items in the cremator.") return for (var/mob/M in viewers(src)) - M.show_message("You hear a roar as the crematorium activates.", 1) + to_chat(M,"You hear a roar as the crematorium activates.") cremating = 1 locked = 1 @@ -363,51 +328,11 @@ /* * Crematorium tray */ -/obj/structure/c_tray +/obj/structure/m_tray/c_tray name = "crematorium tray" desc = "Apply body before burning." icon = 'icons/obj/stationobjs.dmi' icon_state = "cremat" - density = 1 - layer = 2.0 - var/obj/structure/crematorium/connected = null - anchored = 1 - throwpass = 1 - -/obj/structure/c_tray/Destroy() - if(connected && connected.connected == src) - connected.connected = null - connected = null - return ..() - -/obj/structure/c_tray/attack_hand(mob/user as mob) - if (src.connected) - for(var/atom/movable/A as mob|obj in src.loc) - if (!( A.anchored )) - A.forceMove(src.connected) - //Foreach goto(26) - src.connected.connected = null - src.connected.update() - add_fingerprint(user) - //SN src = null - qdel(src) - return - return - -/obj/structure/c_tray/MouseDrop_T(atom/movable/O as mob|obj, mob/user as mob) - if ((!( istype(O, /atom/movable) ) || O.anchored || get_dist(user, src) > 1 || get_dist(user, O) > 1 || user.contents.Find(src) || user.contents.Find(O))) - return - if (!ismob(O) && !istype(O, /obj/structure/closet/body_bag)) - return - if (!ismob(user) || user.stat || user.lying || user.stunned) - return - O.forceMove(src.loc) - if (user != O) - for(var/mob/B in viewers(user, 3)) - if ((B.client && !( B.blinded ))) - B << text("[] stuffs [] into []!", user, O, src) - //Foreach goto(99) - return /obj/machinery/button/crematorium name = "crematorium igniter" @@ -421,9 +346,9 @@ if(..()) return if(src.allowed(user)) - for (var/obj/structure/crematorium/C in world) + for (var/obj/structure/morgue/crematorium/C in world) if (C.id == id) if (!C.cremating) C.cremate(user) else - usr << "Access denied." + to_chat(user,"Access denied.") diff --git a/code/game/objects/structures/musician.dm b/code/game/objects/structures/musician.dm index dacd1013c4e..3b36cb00873 100644 --- a/code/game/objects/structures/musician.dm +++ b/code/game/objects/structures/musician.dm @@ -27,6 +27,23 @@ desc = "This is a space piano, like a regular piano, but always in tune! Even if the musician isn't." icon_state = "piano" +/obj/structure/device/piano/verb/rotate() + set name = "Rotate Piano" + set category = "Object" + set src in oview(1) + + if(istype(usr,/mob/living/simple_animal/mouse)) + return + else if(!usr || !isturf(usr.loc)) + return + else if(usr.stat || usr.restrained()) + return + else if (istype(usr,/mob/observer/ghost) && !config.ghost_interaction) + return + else + src.set_dir(turn(src.dir, 90)) + return + /obj/structure/device/piano/proc/playnote(var/note as text) //world << "Note: [note]" var/soundfile diff --git a/code/game/objects/structures/railing.dm b/code/game/objects/structures/railing.dm index ea52ed3845b..7000e399741 100644 --- a/code/game/objects/structures/railing.dm +++ b/code/game/objects/structures/railing.dm @@ -199,7 +199,7 @@ /obj/structure/railing/attackby(obj/item/W as obj, mob/user as mob) // Dismantle if(istype(W, /obj/item/weapon/wrench) && !anchored) - playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1) + playsound(src.loc, W.usesound, 50, 1) if(do_after(user, 20, src)) user.visible_message("\The [user] dismantles \the [src].", "You dismantle \the [src].") new /obj/item/stack/material/steel(get_turf(usr), 2) @@ -210,7 +210,7 @@ if(health < maxhealth && istype(W, /obj/item/weapon/weldingtool)) var/obj/item/weapon/weldingtool/F = W if(F.welding) - playsound(src.loc, 'sound/items/Welder.ogg', 50, 1) + playsound(src.loc, F.usesound, 50, 1) if(do_after(user, 20, src)) user.visible_message("\The [user] repairs some damage to \the [src].", "You repair some damage to \the [src].") health = min(health+(maxhealth/5), maxhealth) // 20% repair per application @@ -219,7 +219,7 @@ // Install if(istype(W, /obj/item/weapon/screwdriver)) user.visible_message(anchored ? "\The [user] begins unscrewing \the [src]." : "\The [user] begins fasten \the [src]." ) - playsound(loc, 'sound/items/Screwdriver.ogg', 75, 1) + playsound(loc, W.usesound, 75, 1) if(do_after(user, 10, src)) to_chat(user, (anchored ? "You have unfastened \the [src] from the floor." : "You have fastened \the [src] to the floor.")) anchored = !anchored 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 0e577bb36b9..ad2ce1be821 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/bed.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/bed.dm @@ -20,6 +20,7 @@ var/material/material var/material/padding_material var/base_icon = "bed" + var/applies_material_colour = 1 /obj/structure/bed/New(var/newloc, var/new_material, var/new_padding_material) ..(newloc) @@ -46,7 +47,8 @@ var/cache_key = "[base_icon]-[material.name]" if(isnull(stool_cache[cache_key])) var/image/I = image('icons/obj/furniture.dmi', base_icon) - I.color = material.icon_colour + if(applies_material_colour) //VOREStation Add - Goes with added var + I.color = material.icon_colour stool_cache[cache_key] = I overlays |= stool_cache[cache_key] // Padding overlay. @@ -172,13 +174,6 @@ /obj/structure/bed/padded/New(var/newloc) ..(newloc,"plastic","cotton") -/obj/structure/bed/alien - name = "resting contraption" - desc = "This looks similar to contraptions from earth. Could aliens be stealing our technology?" - -/obj/structure/bed/alien/New(var/newloc) - ..(newloc,"resin") - /obj/structure/bed/double name = "double bed" icon_state = "doublebed" @@ -303,3 +298,15 @@ spawn(0) qdel(src) return + +/obj/structure/bed/alien + name = "resting contraption" + desc = "Whatever species designed this must've enjoyed relaxation as well. Looks vaguely comfy." + icon = 'icons/obj/abductor.dmi' + icon_state = "bed" + +/obj/structure/bed/alien/update_icon() + return // Doesn't care about material or anything else. + +/obj/structure/bed/alien/attackby(obj/item/weapon/W, mob/user) + return // No deconning. \ No newline at end of file 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 0e6064785d7..d1f2753e52b 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm @@ -82,6 +82,14 @@ src.set_dir(turn(src.dir, 90)) return +/obj/structure/bed/chair/shuttle + name = "chair" + desc = "You sit in this. Either by will or force." + icon_state = "shuttle_chair" + color = null + base_icon = "shuttle_chair" + applies_material_colour = 0 + // Leaving this in for the sake of compilation. /obj/structure/bed/chair/comfy desc = "It's a chair. It looks comfy." diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index 028e0af3dc6..49f3bb84370 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -91,16 +91,13 @@ playsound(src, "shatter", 70, 1) if(display_message) visible_message("[src] shatters!") - if(dir == SOUTHWEST) - var/index = null - index = 0 - while(index < 2) - new shardtype(loc) //todo pooling? - if(reinf) new /obj/item/stack/rods(loc) - index++ - else + new shardtype(loc) + if(reinf) + new /obj/item/stack/rods(loc) + if(is_fulltile()) new shardtype(loc) //todo pooling? - if(reinf) new /obj/item/stack/rods(loc) + if(reinf) + new /obj/item/stack/rods(loc) qdel(src) return @@ -290,11 +287,9 @@ else playsound(src, W.usesound, 75, 1) visible_message("[user] dismantles \the [src].") - if(dir == SOUTHWEST) - var/obj/item/stack/material/mats = new glasstype(loc) - mats.amount = is_fulltile() ? 4 : 2 - else - new glasstype(loc) + var/obj/item/stack/material/mats = new glasstype(loc) + if(is_fulltile()) + mats.amount = 4 qdel(src) else if(istype(W,/obj/item/frame) && anchored) var/obj/item/frame/F = W @@ -329,6 +324,9 @@ if(usr.incapacitated()) return 0 + if(is_fulltile()) + return 0 + if(anchored) usr << "It is fastened to the floor therefore you can't rotate it!" return 0 @@ -348,6 +346,9 @@ if(usr.incapacitated()) return 0 + if(is_fulltile()) + return 0 + if(anchored) usr << "It is fastened to the floor therefore you can't rotate it!" return 0 @@ -361,13 +362,16 @@ /obj/structure/window/New(Loc, start_dir=null, constructed=0) ..() + if (start_dir) + set_dir(start_dir) + //player-constructed windows if (constructed) anchored = 0 + state = 0 update_verbs() - - if (start_dir) - set_dir(start_dir) + if(is_fulltile()) + maxhealth *= 2 health = maxhealth @@ -406,10 +410,10 @@ //Updates the availabiliy of the rotation verbs /obj/structure/window/proc/update_verbs() - if(anchored) + if(anchored || is_fulltile()) verbs -= /obj/structure/window/proc/rotate verbs -= /obj/structure/window/proc/revrotate - else + else if(!is_fulltile()) verbs += /obj/structure/window/proc/rotate verbs += /obj/structure/window/proc/revrotate @@ -424,7 +428,7 @@ var/list/dirs = list() if(anchored) for(var/obj/structure/window/W in orange(src,1)) - if(W.anchored && W.density && W.type == src.type && W.is_fulltile()) //Only counts anchored, not-destroyed fill-tile windows. + if(W.anchored && W.density && W.glasstype == src.glasstype && W.is_fulltile()) //Only counts anchored, not-destroyed fill-tile windows. dirs += get_dir(src, W) var/list/connections = dirs_to_corner_states(dirs) @@ -507,14 +511,6 @@ glasstype = /obj/item/stack/material/glass/reinforced force_threshold = 6 - -/obj/structure/window/New(Loc, constructed=0) - ..() - - //player-constructed windows - if (constructed) - state = 0 - /obj/structure/window/reinforced/full dir = SOUTHWEST icon_state = "fwindow" diff --git a/code/game/sound.dm b/code/game/sound.dm index c23614942bc..afeeaafcaef 100644 --- a/code/game/sound.dm +++ b/code/game/sound.dm @@ -51,6 +51,8 @@ var/list/keyboard_sound = list ('sound/effects/keyboard/keyboard1.ogg','sound/ef var/list/mechstep_sound = list('sound/mecha/mechstep1.ogg', 'sound/mecha/mechstep2.ogg') var/list/bodyfall_sound = list('sound/effects/bodyfall1.ogg','sound/effects/bodyfall2.ogg','sound/effects/bodyfall3.ogg','sound/effects/bodyfall4.ogg') var/list/can_sound = list('sound/effects/can_open1.ogg','sound/effects/can_open2.ogg','sound/effects/can_open3.ogg','sound/effects/can_open4.ogg') +var/list/geiger_sound = list('sound/items/geiger1.ogg', 'sound/items/geiger2.ogg', 'sound/items/geiger3.ogg', 'sound/items/geiger4.ogg', 'sound/items/geiger5.ogg') +var/list/geiger_weak_sound = list('sound/items/geiger_weak1.ogg', 'sound/items/geiger_weak2.ogg', 'sound/items/geiger_weak3.ogg', 'sound/items/geiger_weak4.ogg') //var/list/gun_sound = list('sound/weapons/Gunshot.ogg', 'sound/weapons/Gunshot2.ogg','sound/weapons/Gunshot3.ogg','sound/weapons/Gunshot4.ogg') @@ -186,4 +188,6 @@ var/const/FALLOFF_SOUNDS = 0.5 if ("canopen") soundin = pick(can_sound) if ("mechstep") soundin = pick(mechstep_sound) //if ("gunshot") soundin = pick(gun_sound) + if("geiger") soundin = pick(geiger_sound) + if("geiger_weak") soundin = pick(geiger_weak_sound) return soundin diff --git a/code/game/turfs/simulated/dungeon/floor.dm b/code/game/turfs/simulated/dungeon/floor.dm new file mode 100644 index 00000000000..743b4978785 --- /dev/null +++ b/code/game/turfs/simulated/dungeon/floor.dm @@ -0,0 +1,7 @@ +// Special floor type for Point of Interests. + +/turf/simulated/floor/dungeon + block_tele = TRUE // Anti-cheese. + +/turf/simulated/floor/dungeon/ex_act() + return \ No newline at end of file diff --git a/code/game/turfs/simulated/dungeon/wall.dm b/code/game/turfs/simulated/dungeon/wall.dm new file mode 100644 index 00000000000..b6a8f53c27c --- /dev/null +++ b/code/game/turfs/simulated/dungeon/wall.dm @@ -0,0 +1,13 @@ +// Special wall type for Point of Interests. + +/turf/simulated/wall/dungeon + block_tele = TRUE // Anti-cheese. + +/turf/simulated/wall/dungeon/New(var/newloc) + ..(newloc,"dungeonium") + +/turf/simulated/wall/dungeon/attackby() + return + +/turf/simulated/wall/dungeon/ex_act() + return \ No newline at end of file diff --git a/code/game/turfs/simulated/floor_icon.dm b/code/game/turfs/simulated/floor_icon.dm index 9a7fec800a4..4bc4911f2ea 100644 --- a/code/game/turfs/simulated/floor_icon.dm +++ b/code/game/turfs/simulated/floor_icon.dm @@ -5,6 +5,8 @@ var/list/flooring_cache = list() if(lava) return + overlays.Cut() + if(flooring) // Set initial icon and strings. name = flooring.name @@ -20,7 +22,6 @@ var/list/flooring_cache = list() flooring_override = icon_state // Apply edges, corners, and inner corners. - overlays.Cut() var/has_border = 0 if(flooring.flags & TURF_HAS_EDGES) for(var/step_dir in cardinal) diff --git a/code/game/turfs/simulated/floor_types.dm b/code/game/turfs/simulated/floor_types.dm index e62ba0d7f4d..723998d4da3 100644 --- a/code/game/turfs/simulated/floor_types.dm +++ b/code/game/turfs/simulated/floor_types.dm @@ -166,6 +166,21 @@ icon_state = "floor_glass" takes_underlays = 1 +/turf/simulated/shuttle/floor/alien + icon_state = "alienpod1" + light_range = 3 + light_power = 3 + light_color = "#66ffff" // Bright cyan. + block_tele = TRUE + +/turf/simulated/shuttle/floor/alien/initialize() + ..() + icon_state = "alienpod[rand(1, 9)]" + +/turf/simulated/shuttle/floor/alienplating + icon_state = "alienplating" + block_tele = TRUE + /turf/simulated/shuttle/plating name = "plating" icon = 'icons/turf/floors.dmi' diff --git a/code/game/turfs/simulated/outdoors/grass.dm b/code/game/turfs/simulated/outdoors/grass.dm index 6693c458746..1870f8bd811 100644 --- a/code/game/turfs/simulated/outdoors/grass.dm +++ b/code/game/turfs/simulated/outdoors/grass.dm @@ -20,12 +20,12 @@ var/list/grass_types = list( grass_chance = 0 var/tree_chance = 2 -/turf/simulated/floor/outdoors/grass/sif/New() +/turf/simulated/floor/outdoors/grass/sif/initialize() if(tree_chance && prob(tree_chance)) new /obj/structure/flora/tree/sif(src) ..() -/turf/simulated/floor/outdoors/grass/New() +/turf/simulated/floor/outdoors/grass/initialize() if(prob(50)) icon_state += "2" //edge_blending_priority++ diff --git a/code/game/turfs/simulated/outdoors/outdoors.dm b/code/game/turfs/simulated/outdoors/outdoors.dm index e5c64653298..941aa5abc90 100644 --- a/code/game/turfs/simulated/outdoors/outdoors.dm +++ b/code/game/turfs/simulated/outdoors/outdoors.dm @@ -40,7 +40,10 @@ var/list/outdoor_turfs = list() /turf/simulated/proc/make_indoors() outdoors = FALSE - planet_controller.unallocateTurf(src) + if(planet_controller) + planet_controller.unallocateTurf(src) + else // This is happening during map gen, if there's no planet_controller (hopefully). + outdoor_turfs -= src qdel(weather_overlay) update_icon() diff --git a/code/game/turfs/simulated/wall_types.dm b/code/game/turfs/simulated/wall_types.dm index ce4451ff121..19264e23ba7 100644 --- a/code/game/turfs/simulated/wall_types.dm +++ b/code/game/turfs/simulated/wall_types.dm @@ -107,6 +107,25 @@ icon_state = "dark-nj" join_group = null +/turf/simulated/shuttle/wall/alien + icon = 'icons/turf/shuttle_alien.dmi' + icon_state = "alien" + base_state = "alien" + light_range = 3 + light_power = 3 + light_color = "#ff0066" // Pink-ish + block_tele = TRUE // Will be used for dungeons so this is needed to stop cheesing with handteles. + +/turf/simulated/shuttle/wall/alien/hard_corner + name = "hardcorner wall" + icon_state = "alien-hc" + hard_corner = 1 + +/turf/simulated/shuttle/wall/alien/no_join + name = "nojoin wall" + icon_state = "alien-nj" + join_group = null + /turf/simulated/shuttle/wall/New() ..() //To allow mappers to rename shuttle walls to like "redfloor interior" or whatever for ease of use. diff --git a/code/game/turfs/simulated/water.dm b/code/game/turfs/simulated/water.dm index 8e32a004d90..6f2c606c0de 100644 --- a/code/game/turfs/simulated/water.dm +++ b/code/game/turfs/simulated/water.dm @@ -19,8 +19,8 @@ update_icon() /turf/simulated/floor/water/update_icon() - ..() // To get the edges. This also gets rid of other overlays so it needs to go first. overlays.Cut() + ..() // To get the edges. icon_state = water_state var/image/floorbed_sprite = image(icon = 'icons/turf/outdoors.dmi', icon_state = under_state) underlays.Add(floorbed_sprite) diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index d34b210b997..10cee9b6b7c 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -28,6 +28,8 @@ var/list/footstep_sounds = null + var/block_tele = FALSE // If true, most forms of teleporting to or from this turf tile will fail. + /turf/New() ..() for(var/atom/movable/AM as mob|obj in src) diff --git a/code/game/verbs/ooc.dm b/code/game/verbs/ooc.dm index fa6dec5715b..8fafb555a33 100644 --- a/code/game/verbs/ooc.dm +++ b/code/game/verbs/ooc.dm @@ -43,6 +43,8 @@ var/ooc_style = "everyone" if(holder && !holder.fakekey) ooc_style = "elevated" + if(holder.rights & R_EVENT) + ooc_style = "event_manager" if(holder.rights & R_MOD) ooc_style = "moderator" if(holder.rights & R_DEBUG) diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index 121e355d22e..61f2d174ac3 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -1223,21 +1223,6 @@ proc/admin_notice(var/message, var/rights) if(istype(H)) H.regenerate_icons() - -/* - helper proc to test if someone is an event manager or not. Got tired of writing this same check all over the place. -*/ -/proc/is_eventM(client/C) - - if(!istype(C)) - return 0 - if(!C.holder) - return 0 - - if(C.holder.rights == R_EVENT) - return 1 - return 0 - /proc/get_options_bar(whom, detail = 2, name = 0, link = 1, highlight_special = 1) if(!whom) return "(*null*)" @@ -1482,7 +1467,7 @@ datum/admins/var/obj/item/weapon/paper/admin/faxreply // var to hold fax replies - if(destination.recievefax(P)) + if(destination.receivefax(P)) src.owner << "Message reply to transmitted successfully." if(P.sender) // sent as a reply log_admin("[key_name(src.owner)] replied to a fax message from [key_name(P.sender)]") diff --git a/code/modules/admin/admin_secrets.dm b/code/modules/admin/admin_secrets.dm index b6d0abbe1c3..473770ac2b5 100644 --- a/code/modules/admin/admin_secrets.dm +++ b/code/modules/admin/admin_secrets.dm @@ -100,18 +100,18 @@ var/datum/admin_secrets/admin_secrets = new() /datum/admin_secret_item/admin_secret category = /datum/admin_secret_category/admin_secrets log = 0 - permissions = R_ADMIN + permissions = R_ADMIN|R_EVENT /datum/admin_secret_item/random_event category = /datum/admin_secret_category/random_events - permissions = R_FUN + permissions = R_FUN|R_EVENT warn_before_use = 1 /datum/admin_secret_item/fun_secret category = /datum/admin_secret_category/fun_secrets - permissions = R_FUN + permissions = R_FUN|R_EVENT warn_before_use = 1 /datum/admin_secret_item/final_solution category = /datum/admin_secret_category/final_solutions - permissions = R_FUN|R_SERVER|R_ADMIN + permissions = R_FUN|R_SERVER|R_ADMIN|R_EVENT diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 2503c73abba..0b02b98ef32 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -8,7 +8,6 @@ var/list/admin_verbs_default = list( /client/proc/debug_variables, //allows us to -see- the variables of any instance in the game. +VAREDIT needed to modify, // /client/proc/check_antagonists, //shows all antags, // /client/proc/cmd_mod_say, - /client/proc/cmd_eventM_check_new_players, // /client/proc/deadchat //toggles deadchat on/off, // /client/proc/toggle_ahelp_sound, ) @@ -330,11 +329,11 @@ var/list/admin_verbs_mod = list( ) var/list/admin_verbs_event_manager = list( + /client/proc/cmd_event_say, /client/proc/cmd_admin_pm_context, /client/proc/cmd_admin_pm_panel, /datum/admins/proc/PlayerNotes, /client/proc/admin_ghost, - /client/proc/cmd_mod_say, /datum/admins/proc/show_player_info, /client/proc/dsay, /client/proc/cmd_admin_subtle_message, @@ -448,9 +447,6 @@ var/list/admin_verbs_event_manager = list( feedback_add_details("admin_verb","TAVVS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - - - /client/proc/admin_ghost() set category = "Admin" set name = "Aghost" @@ -461,7 +457,7 @@ var/list/admin_verbs_event_manager = list( if(ghost.can_reenter_corpse) ghost.reenter_corpse() else - ghost << "Error: Aghost: Can't reenter corpse, event managers that use adminHUD while aghosting are not permitted to enter their corpse again" + to_chat(ghost, "Error: Aghost: Can't reenter corpse.") return feedback_add_details("admin_verb","P") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! @@ -777,7 +773,7 @@ var/list/admin_verbs_event_manager = list( set category = "Admin" if(holder) - if(alert("Confirm self-deadmin for the round? You can't re-admin yourself without someont promoting you.",,"Yes","No") == "Yes") + if(alert("Confirm self-deadmin for the round? You can't re-admin yourself without someone promoting you.",,"Yes","No") == "Yes") log_admin("[src] deadmined themself.") message_admins("[src] deadmined themself.", 1) deadmin() diff --git a/code/modules/admin/player_panel.dm b/code/modules/admin/player_panel.dm index 15317902684..92536a6e053 100644 --- a/code/modules/admin/player_panel.dm +++ b/code/modules/admin/player_panel.dm @@ -363,20 +363,14 @@ PM "} - - if(usr.client) - var/client/C = usr.client - if(is_eventM(C)) - dat += {" N/A "} - else - switch(is_special_character(M)) - if(0) - dat += {"Traitor?"} - if(1) - dat += {"Traitor?"} - if(2) - dat += {"Traitor?"} + switch(is_special_character(M)) + if(0) + dat += {"Traitor?"} + if(1) + dat += {"Traitor?"} + if(2) + dat += {"Traitor?"} else dat += {" N/A "} diff --git a/code/modules/admin/verbs/adminsay.dm b/code/modules/admin/verbs/adminsay.dm index 63209f84b4e..264e5ad64eb 100644 --- a/code/modules/admin/verbs/adminsay.dm +++ b/code/modules/admin/verbs/adminsay.dm @@ -36,7 +36,8 @@ if(check_rights(R_ADMIN, 0)) sender_name = "[sender_name]" for(var/client/C in admins) - C << "" + create_text_tag("mod", "MOD:", C) + " [sender_name]([admin_jump_link(mob, C.holder)]): [msg]" + if(check_rights(R_ADMIN|R_MOD|R_SERVER)) + C << "" + create_text_tag("mod", "MOD:", C) + " [sender_name]([admin_jump_link(mob, C.holder)]): [msg]" feedback_add_details("admin_verb","MS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! @@ -45,7 +46,7 @@ set name = "Esay" set hidden = 1 - if(!check_rights(R_ADMIN|R_MOD|R_EVENT|R_SERVER)) + if(!check_rights(R_ADMIN|R_MOD|R_EVENT|R_SERVER|R_EVENT)) return msg = sanitize(msg) diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index c14c74edd12..b80d95e3c18 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -65,42 +65,6 @@ message_admins("SubtleMessage: [key_name_admin(usr)] -> [key_name_admin(M)] : [msg]", 1) feedback_add_details("admin_verb","SMS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! -/client/proc/cmd_eventM_check_new_players() //Allows event managers / admins to determine who the newer players are. - set category = "Admin" - set name = "Check new Players" - if(!holder) - src << "Only staff members may use this command." - - var/age = alert(src, "Age check", "Show accounts yonger then _____ days","7", "30" , "All") - - if(age == "All") - age = 9999999 - else - age = text2num(age) - - var/missing_ages = 0 - var/msg = "" - - var/highlight_special_characters = 1 - if(is_eventM(usr.client)) - highlight_special_characters = 0 - - for(var/client/C in clients) - if(C.player_age == "Requires database") - missing_ages = 1 - continue - if(C.player_age < age) - msg += "[key_name(C, 1, 1, highlight_special_characters)]: account is [C.player_age] days old
" - - if(missing_ages) - src << "Some accounts did not have proper ages set in their clients. This function requires database to be present" - - if(msg != "") - src << browse(msg, "window=Player_age_check") - else - src << "No matches for that age range found." - - /client/proc/cmd_admin_world_narrate() // Allows administrators to fluff events a little easier -- TLE set category = "Special Verbs" set name = "Global Narrate" diff --git a/code/modules/busy_space/organizations.dm b/code/modules/busy_space/organizations.dm index b8bc38b2910..da08c70c4a6 100644 --- a/code/modules/busy_space/organizations.dm +++ b/code/modules/busy_space/organizations.dm @@ -104,7 +104,7 @@ // Note that the current station being used will be pruned from this list upon being instantiated destination_names = list( "NSS Exodus in Nyx", - "NCS Northern Star in Vir", + //"NCS Northern Star in Vir", "NLS Southern Cross in Vir", "NAS Vir Central Command", "a dockyard orbiting Sif", diff --git a/code/modules/client/preference_setup/general/03_body.dm b/code/modules/client/preference_setup/general/03_body.dm index c6500143f00..73d91129e77 100644 --- a/code/modules/client/preference_setup/general/03_body.dm +++ b/code/modules/client/preference_setup/general/03_body.dm @@ -3,6 +3,9 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O /datum/preferences var/equip_preview_mob = EQUIP_PREVIEW_ALL + var/icon/bgstate = "000" + var/list/bgstate_options = list("000", "fff", "steel", "white") + /datum/category_item/player_setup_item/general/body name = "Body" sort_order = 3 @@ -34,6 +37,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O S["synth_green"] >> pref.g_synth S["synth_blue"] >> pref.b_synth pref.preview_icon = null + S["bgstate"] >> pref.bgstate /datum/category_item/player_setup_item/general/body/save_character(var/savefile/S) S["species"] << pref.species @@ -61,6 +65,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O S["synth_red"] << pref.r_synth S["synth_green"] << pref.g_synth S["synth_blue"] << pref.b_synth + S["bgstate"] << pref.bgstate /datum/category_item/player_setup_item/general/body/sanitize_character(var/savefile/S) if(!pref.species || !(pref.species in playable_species)) @@ -87,6 +92,8 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O if(!pref.rlimb_data) pref.rlimb_data = list() if(!pref.body_markings) pref.body_markings = list() else pref.body_markings &= body_marking_styles_list + if(!pref.bgstate || !(pref.bgstate in pref.bgstate_options)) + pref.bgstate = "000" // Moved from /datum/preferences/proc/copy_to() /datum/category_item/player_setup_item/general/body/copy_to_mob(var/mob/living/carbon/human/character) @@ -268,6 +275,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O . += "Preview
" . += "
" + . += "
Cycle background" . += "
[pref.equip_preview_mob & EQUIP_PREVIEW_LOADOUT ? "Hide loadout" : "Show loadout"]" . += "
[pref.equip_preview_mob & EQUIP_PREVIEW_JOB ? "Hide job gear" : "Show job gear"]" . += "" @@ -694,6 +702,10 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O pref.b_synth = hex2num(copytext(new_color, 6, 8)) return TOPIC_REFRESH_UPDATE_PREVIEW + else if(href_list["cycle_bg"]) + pref.bgstate = next_in_list(pref.bgstate, pref.bgstate_options) + return TOPIC_REFRESH_UPDATE_PREVIEW + return ..() /datum/category_item/player_setup_item/general/body/proc/reset_limbs() diff --git a/code/modules/client/preference_setup/loadout/loadout_accessories.dm b/code/modules/client/preference_setup/loadout/loadout_accessories.dm index 6bc944552c6..bf1796ea29c 100644 --- a/code/modules/client/preference_setup/loadout/loadout_accessories.dm +++ b/code/modules/client/preference_setup/loadout/loadout_accessories.dm @@ -209,3 +209,26 @@ var/obj/item/clothing/suit/sweater_type = sweater sweaters[initial(sweater_type.name)] = sweater_type gear_tweaks += new/datum/gear_tweak/path(sortAssoc(sweaters)) + +/datum/gear/accessory/bracelet/material + display_name = "bracelet selection" + description = "Choose from a number of bracelets." + path = /obj/item/clothing/accessory/bracelet + cost = 1 + +/datum/gear/accessory/bracelet/material/New() + ..() + var/bracelettype = list() + bracelettype["bracelet, steel"] = /obj/item/clothing/accessory/bracelet/material/steel + bracelettype["bracelet, iron"] = /obj/item/clothing/accessory/bracelet/material/iron + bracelettype["bracelet, silver"] = /obj/item/clothing/accessory/bracelet/material/silver + bracelettype["bracelet, gold"] = /obj/item/clothing/accessory/bracelet/material/gold + bracelettype["bracelet, platinum"] = /obj/item/clothing/accessory/bracelet/material/platinum + bracelettype["bracelet, glass"] = /obj/item/clothing/accessory/bracelet/material/glass + bracelettype["bracelet, wood"] = /obj/item/clothing/accessory/bracelet/material/wood + bracelettype["bracelet, plastic"] = /obj/item/clothing/accessory/bracelet/material/plastic + gear_tweaks += new/datum/gear_tweak/path(bracelettype) + +/datum/gear/accessory/bracelet/friendship + display_name = "friendship bracelet" + path = /obj/item/clothing/accessory/bracelet/friendship \ No newline at end of file diff --git a/code/modules/client/preference_setup/loadout/loadout_general.dm b/code/modules/client/preference_setup/loadout/loadout_general.dm index 6f3115fd2f2..860869883fc 100644 --- a/code/modules/client/preference_setup/loadout/loadout_general.dm +++ b/code/modules/client/preference_setup/loadout/loadout_general.dm @@ -34,6 +34,18 @@ display_name = "Spaceball booster pack" path = /obj/item/weapon/pack/spaceball +/datum/gear/plushie + display_name = "plushie selection" + path = /obj/item/toy/plushie/ + +/datum/gear/plushie/New() + ..() + var/list/plushies = list() + for(var/plushie in subtypesof(/obj/item/toy/plushie/) - /obj/item/toy/plushie/therapy) + var/obj/item/toy/plushie/plushie_type = plushie + plushies[initial(plushie_type.name)] = plushie_type + gear_tweaks += new/datum/gear_tweak/path(sortAssoc(plushies)) + /datum/gear/flask display_name = "flask" path = /obj/item/weapon/reagent_containers/food/drinks/flask/barflask diff --git a/code/modules/client/preference_setup/loadout/loadout_head.dm b/code/modules/client/preference_setup/loadout/loadout_head.dm index f7737c9dde0..bbaca4c3636 100644 --- a/code/modules/client/preference_setup/loadout/loadout_head.dm +++ b/code/modules/client/preference_setup/loadout/loadout_head.dm @@ -154,34 +154,10 @@ path = /obj/item/clothing/head/fedora/grey /datum/gear/head/hairflower - display_name = "hair flower pin, red" - path = /obj/item/clothing/head/hairflower - -/datum/gear/head/hairflower/yellow - display_name = "hair flower pin, yellow" - path = /obj/item/clothing/head/hairflower/yellow - -/datum/gear/head/hairflower/pink - display_name = "hair flower pin, pink" - path = /obj/item/clothing/head/hairflower/pink - -/datum/gear/head/hairflower/blue - display_name = "hair flower pin, blue" - path = /obj/item/clothing/head/hairflower/blue - -/datum/gear/head/hairflower/violet - display_name = "hair flower pin, violet" - path = /obj/item/clothing/head/hairflower/violet - -/datum/gear/head/hairflower/orange - display_name = "hair flower pin, orange" - path = /obj/item/clothing/head/hairflower/orange - -/datum/gear/head/hairflower/white display_name = "hair flower pin" path = /obj/item/clothing/head/hairflower/white -/datum/gear/head/hairflower/white/New() +/datum/gear/head/hairflower/New() ..() gear_tweaks = list(gear_tweak_free_color_choice) @@ -372,4 +348,4 @@ /datum/gear/head/surgical/purple display_name = "surgical cap, purple" - path = /obj/item/clothing/head/surgery/purple \ No newline at end of file + path = /obj/item/clothing/head/surgery/purple diff --git a/code/modules/client/preference_setup/loadout/loadout_shoes.dm b/code/modules/client/preference_setup/loadout/loadout_shoes.dm index ba2d995b279..6b15fba5ea7 100644 --- a/code/modules/client/preference_setup/loadout/loadout_shoes.dm +++ b/code/modules/client/preference_setup/loadout/loadout_shoes.dm @@ -73,10 +73,6 @@ display_name = "shoes, yellow" path = /obj/item/clothing/shoes/yellow -/datum/gear/shoes/flats - display_name = "flats, black" - path = /obj/item/clothing/shoes/flats - /datum/gear/shoes/hitops/ display_name = "high-top, white" path = /obj/item/clothing/shoes/hitops/ @@ -109,30 +105,6 @@ display_name = "high-top, yellow" path = /obj/item/clothing/shoes/hitops/yellow -/datum/gear/shoes/flats/blue - display_name = "flats, blue" - path = /obj/item/clothing/shoes/flats/blue - -/datum/gear/shoes/flats/brown - display_name = "flats, brown" - path = /obj/item/clothing/shoes/flats/brown - -/datum/gear/shoes/flats/orange - display_name = "flats, orange" - path = /obj/item/clothing/shoes/flats/orange - -/datum/gear/shoes/flats/purple - display_name = "flats, purple" - path = /obj/item/clothing/shoes/flats/purple - -/datum/gear/shoes/flats/red - display_name = "flats, red" - path = /obj/item/clothing/shoes/flats/red - -/datum/gear/shoes/flats/white - display_name = "flats, white" - path = /obj/item/clothing/shoes/flats/white - /datum/gear/shoes/flipflops display_name = "flip flops" path = /obj/item/clothing/shoes/flipflop @@ -157,11 +129,11 @@ ..() gear_tweaks = list(gear_tweak_free_color_choice) -/datum/gear/shoes/flats/color +/datum/gear/shoes/flats display_name = "flats" path = /obj/item/clothing/shoes/flats/white/color -/datum/gear/shoes/flats/color/New() +/datum/gear/shoes/flats/New() ..() gear_tweaks = list(gear_tweak_free_color_choice) @@ -246,4 +218,4 @@ /datum/gear/shoes/boots/winter/hydro display_name = "hydroponics winter boots" path = /obj/item/clothing/shoes/boots/winter/hydro - allowed_roles = list("Botanist", "Xenobiologist") \ No newline at end of file + allowed_roles = list("Botanist", "Xenobiologist") diff --git a/code/modules/client/preference_setup/traits/trait_defines.dm b/code/modules/client/preference_setup/traits/trait_defines.dm index 0431ac611b9..86b8ede6f70 100644 --- a/code/modules/client/preference_setup/traits/trait_defines.dm +++ b/code/modules/client/preference_setup/traits/trait_defines.dm @@ -72,6 +72,25 @@ Regardless, you find it quite difficult to land shots where you wanted them to go." modifier_type = /datum/modifier/trait/inaccurate +/datum/trait/modifier/physical/smaller + name = "Smaller" + modifier_type = /datum/modifier/trait/smaller + mutually_exclusive = list(/datum/trait/modifier/physical/small, /datum/trait/modifier/physical/large, /datum/trait/modifier/physical/larger) + +/datum/trait/modifier/physical/small + name = "Small" + modifier_type = /datum/modifier/trait/small + mutually_exclusive = list(/datum/trait/modifier/physical/smaller, /datum/trait/modifier/physical/large, /datum/trait/modifier/physical/larger) + +/datum/trait/modifier/physical/large + name = "Large" + modifier_type = /datum/modifier/trait/large + mutually_exclusive = list(/datum/trait/modifier/physical/smaller, /datum/trait/modifier/physical/small, /datum/trait/modifier/physical/larger) + +/datum/trait/modifier/physical/larger + name = "Larger" + modifier_type = /datum/modifier/trait/larger + mutually_exclusive = list(/datum/trait/modifier/physical/smaller, /datum/trait/modifier/physical/small, /datum/trait/modifier/physical/large) // These two traits might be borderline, feel free to remove if they get abused. /datum/trait/modifier/physical/high_metabolism diff --git a/code/modules/clothing/gloves/color.dm b/code/modules/clothing/gloves/color.dm index 94ed2c9f87a..d7e03622724 100644 --- a/code/modules/clothing/gloves/color.dm +++ b/code/modules/clothing/gloves/color.dm @@ -77,6 +77,7 @@ desc = "A pair of gloves that reach past the elbow. Fancy!" name = "evening gloves" icon_state = "evening_gloves" + addblends = "evening_gloves_a" cold_protection = HANDS min_cold_protection_temperature = GLOVES_MIN_COLD_PROTECTION_TEMPERATURE diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm index 66827de3464..8527e8b501d 100644 --- a/code/modules/clothing/head/helmet.dm +++ b/code/modules/clothing/head/helmet.dm @@ -109,6 +109,17 @@ min_cold_protection_temperature = SPACE_HELMET_MIN_COLD_PROTECTION_TEMPERATURE siemens_coefficient = 0.5 +/obj/item/clothing/head/helmet/alien + name = "alien helmet" + desc = "It's quite larger than your head, but it might still protect it." + icon_state = "alienhelmet" + siemens_coefficient = 0.4 + armor = list(melee = 50, bullet = 50, laser = 50, energy = 50, bomb = 50, bio = 0, rad = 40) + +/obj/item/clothing/head/helmet/alien/tank + name = "alien warhelm" + armor = list(melee = 70, bullet = 70, laser = 70, energy = 70, bomb = 70, bio = 0, rad = 40) + /obj/item/clothing/head/helmet/thunderdome name = "\improper Thunderdome helmet" desc = "'Let the battle commence!'" diff --git a/code/modules/clothing/head/misc.dm b/code/modules/clothing/head/misc.dm index cc3f2765666..85f51e2cdd0 100644 --- a/code/modules/clothing/head/misc.dm +++ b/code/modules/clothing/head/misc.dm @@ -34,9 +34,11 @@ /obj/item/clothing/head/hairflower/white icon_state = "hairflower_white" + addblends = "hairflower_white_a" /obj/item/clothing/head/hairflower/bow icon_state = "bow" + addblends = "bow_a" name = "hair bow" desc = "A ribbon tied into a bow with a clip on the back to attach to hair." item_state_slots = list(slot_r_hand_str = "pill", slot_l_hand_str = "pill") @@ -155,6 +157,7 @@ /obj/item/clothing/head/flatcap/grey icon_state = "flat_capw" + addblends = "flat_capw_a" item_state_slots = list(slot_r_hand_str = "greysoft", slot_l_hand_str = "greysoft") /obj/item/clothing/head/pirate @@ -300,6 +303,7 @@ name = "hijab" desc = "A veil that is wrapped to cover the head and chest" icon_state = "hijab" + addblends = "hijab_a" item_state_slots = list(slot_r_hand_str = "beret_white", slot_l_hand_str = "beret_white") body_parts_covered = 0 flags_inv = BLOCKHAIR @@ -308,12 +312,14 @@ name = "kippa" desc = "A small, brimless cap." icon_state = "kippa" + addblends = "kippa_a" body_parts_covered = 0 /obj/item/clothing/head/turban name = "turban" desc = "A cloth used to wind around the head" icon_state = "turban" + addblends = "turban_a" item_state_slots = list(slot_r_hand_str = "beret_white", slot_l_hand_str = "beret_white") body_parts_covered = 0 flags_inv = BLOCKHEADHAIR @@ -322,24 +328,28 @@ name = "taqiyah" desc = "A short, rounded skullcap usually worn for religious purposes." icon_state = "taqiyah" + addblends = "taqiyah_a" item_state_slots = list(slot_r_hand_str = "taq", slot_l_hand_str = "taq") /obj/item/clothing/head/beanie name = "beanie" desc = "A head-hugging brimless winter cap. This one is tight." icon_state = "beanie" + addblends = "beanie_a" body_parts_covered = 0 /obj/item/clothing/head/beanie_loose name = "loose beanie" desc = "A head-hugging brimless winter cap. This one is loose." icon_state = "beanie_hang" + addblends = "beanie_hang_a" body_parts_covered = 0 /obj/item/clothing/head/beretg name = "beret" desc = "A beret, an artists favorite headwear." icon_state = "beret_g" + addblends = "beret_g_a" body_parts_covered = 0 /obj/item/clothing/head/sombrero diff --git a/code/modules/clothing/masks/gasmask.dm b/code/modules/clothing/masks/gasmask.dm index 4facc9fef72..299680b8642 100644 --- a/code/modules/clothing/masks/gasmask.dm +++ b/code/modules/clothing/masks/gasmask.dm @@ -67,6 +67,15 @@ icon_state = "swat" siemens_coefficient = 0.7 +/obj/item/clothing/mask/gas/explorer + name = "explorer gas mask" + desc = "A military-grade gas mask that can be connected to an air supply." + icon_state = "explorer" + item_state_slots = list(slot_r_hand_str = "gas", slot_l_hand_str = "gas") + armor = list(melee = 10, bullet = 5, laser = 5,energy = 5, bomb = 0, bio = 50, rad = 0) + body_parts_covered = HEAD|FACE|EYES + siemens_coefficient = 0.9 + /obj/item/clothing/mask/gas/clown_hat name = "clown wig and mask" desc = "A true prankster's facial attire. A clown is incomplete without their wig and mask." diff --git a/code/modules/clothing/shoes/boots.dm b/code/modules/clothing/shoes/boots.dm index 88206f41320..40dd1c7242c 100644 --- a/code/modules/clothing/shoes/boots.dm +++ b/code/modules/clothing/shoes/boots.dm @@ -96,6 +96,12 @@ desc = "A pair of winter boots. These ones are lined with brown fur, and their trim is ambrosia green" icon_state = "winterboots_hydro" +/obj/item/clothing/shoes/boots/winter/explorer + name = "explorer winter boots" + desc = "Steel-toed winter boots for mining or exploration in hazardous environments. Very good at keeping toes warm and uncrushed." + icon_state = "explorer" + armor = list(melee = 30, bullet = 10, laser = 10, energy = 15, bomb = 20, bio = 0, rad = 0) + /obj/item/clothing/shoes/boots/tactical name = "tactical boots" desc = "Tan boots with extra padding and armor." diff --git a/code/modules/clothing/shoes/colour.dm b/code/modules/clothing/shoes/colour.dm index 6b4b270f97c..85ffb970b8d 100644 --- a/code/modules/clothing/shoes/colour.dm +++ b/code/modules/clothing/shoes/colour.dm @@ -54,6 +54,7 @@ name = "white flats" desc = "Shiny white flats." icon_state = "flatswhite" + addblends = "flatswhite_a" item_state_slots = list(slot_r_hand_str = "white", slot_l_hand_str = "white") /obj/item/clothing/shoes/flats/white/color diff --git a/code/modules/clothing/shoes/miscellaneous.dm b/code/modules/clothing/shoes/miscellaneous.dm index c1c833a308d..8ee0ae2d322 100644 --- a/code/modules/clothing/shoes/miscellaneous.dm +++ b/code/modules/clothing/shoes/miscellaneous.dm @@ -124,23 +124,27 @@ name = "flip flops" desc = "A pair of foam flip flops. For those not afraid to show a little ankle." icon_state = "thongsandal" + addblends = "thongsandal_a" /obj/item/clothing/shoes/athletic name = "athletic shoes" desc = "A pair of sleek atheletic shoes. Made by and for the sporty types." icon_state = "sportshoe" + addblends = "sportshoe_a" item_state_slots = list(slot_r_hand_str = "sportheld", slot_l_hand_str = "sportheld") /obj/item/clothing/shoes/skater name = "skater shoes" desc = "A pair of wide shoes with thick soles. Designed for skating." icon_state = "skatershoe" + addblends = "skatershoe_a" item_state_slots = list(slot_r_hand_str = "skaterheld", slot_l_hand_str = "skaterheld") /obj/item/clothing/shoes/heels name = "high heels" desc = "A pair of high-heeled shoes. Fancy!" icon_state = "heels" + addblends = "heels_a" /obj/item/clothing/shoes/footwraps name = "cloth footwraps" diff --git a/code/modules/clothing/spacesuits/rig/modules/ninja.dm b/code/modules/clothing/spacesuits/rig/modules/ninja.dm index 075411cd294..31e08a9f35d 100644 --- a/code/modules/clothing/spacesuits/rig/modules/ninja.dm +++ b/code/modules/clothing/spacesuits/rig/modules/ninja.dm @@ -37,8 +37,8 @@ var/mob/living/carbon/human/H = holder.wearer - H << "You are now invisible to normal detection." - H.invisibility = INVISIBILITY_LEVEL_TWO + to_chat(H, "You are now nearly invisible to normal detection.") + H.alpha = 5 anim(get_turf(H), H, 'icons/effects/effects.dmi', "electricity",null,20,null) @@ -51,11 +51,11 @@ var/mob/living/carbon/human/H = holder.wearer - H << "You are now visible." - H.invisibility = 0 + to_chat(H, "You are now visible.") anim(get_turf(H), H,'icons/mob/mob.dmi',,"uncloak",,H.dir) anim(get_turf(H), H, 'icons/effects/effects.dmi', "electricity",null,20,null) + H.alpha = initial(H.alpha) for(var/mob/O in oviewers(H)) O.show_message("[H.name] appears from thin air!",1) diff --git a/code/modules/clothing/spacesuits/void/station.dm b/code/modules/clothing/spacesuits/void/station.dm index 31830fb275c..3c5dc32e687 100644 --- a/code/modules/clothing/spacesuits/void/station.dm +++ b/code/modules/clothing/spacesuits/void/station.dm @@ -150,20 +150,20 @@ item_state_slots = list(slot_r_hand_str = "medical_voidsuit_bio", slot_l_hand_str = "medical_voidsuit_bio") armor = list(melee = 45, bullet = 5, laser = 20, energy = 5, bomb = 15, bio = 100, rad = 75) -//Medical Surplus Voidsuit +//Medical Streamlined Voidsuit /obj/item/clothing/head/helmet/space/void/medical/alt name = "streamlined medical voidsuit helmet" desc = "A trendy, lightly radiation-shielded voidsuit helmet trimmed in a fetching green." icon_state = "rig0-medicalalt" - armor = list(melee = 30, bullet = 5, laser = 10,energy = 5, bomb = 5, bio = 100, rad = 60) + armor = list(melee = 30, bullet = 5, laser = 20,energy = 5, bomb = 25, bio = 100, rad = 80) light_overlay = "helmet_light_dual_green" /obj/item/clothing/suit/space/void/medical/alt icon_state = "rig-medicalalt" name = "streamlined medical voidsuit" desc = "A more recent model of Vey-Med voidsuit, featuring the latest in radiation shielding technology, without sacrificing comfort or style." - allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/device/suit_cooling_unit,/obj/item/weapon/storage/firstaid,/obj/item/device/healthanalyzer,/obj/item/stack/medical) - armor = list(melee = 30, bullet = 5, laser = 10,energy = 5, bomb = 5, bio = 100, rad = 60) + slowdown = 0 + armor = list(melee = 30, bullet = 5, laser = 20,energy = 5, bomb = 25, bio = 100, rad = 80) //Security /obj/item/clothing/head/helmet/space/void/security diff --git a/code/modules/clothing/spacesuits/void/void.dm b/code/modules/clothing/spacesuits/void/void.dm index 934d7407d9e..dfc416aa696 100644 --- a/code/modules/clothing/spacesuits/void/void.dm +++ b/code/modules/clothing/spacesuits/void/void.dm @@ -54,7 +54,7 @@ //Breach thresholds, should ideally be inherited by most (if not all) voidsuits. //With 0.2 resiliance, will reach 10 breach damage after 3 laser carbine blasts or 8 smg hits. - breach_threshold = 18 + breach_threshold = 12 can_breach = 1 //Inbuilt devices. diff --git a/code/modules/clothing/suits/aliens/seromi.dm b/code/modules/clothing/suits/aliens/seromi.dm index ccba8986d5f..245ebc5436f 100644 --- a/code/modules/clothing/suits/aliens/seromi.dm +++ b/code/modules/clothing/suits/aliens/seromi.dm @@ -49,7 +49,7 @@ item_state = "tesh_cloak_by" /obj/item/clothing/suit/storage/seromi/cloak/black_green - name = "black and Green cloak" + name = "black and green cloak" icon_state = "tesh_cloak_bgr" item_state = "tesh_cloak_bgr" @@ -115,8 +115,8 @@ /obj/item/clothing/suit/storage/seromi/cloak/blue_grey name = "blue and grey cloak" - icon_state = "tesh_cloak_blg" - item_state = "tesh_cloak_blg" + icon_state = "tesh_cloak_blug" + item_state = "tesh_cloak_blug" /obj/item/clothing/suit/storage/seromi/cloak/purple_grey name = "purple and grey cloak" @@ -124,11 +124,11 @@ item_state = "tesh_cloak_pg" /obj/item/clothing/suit/storage/seromi/cloak/pink_grey - name = "black and orange cloak" + name = "pink and grey cloak" icon_state = "tesh_cloak_pig" item_state = "tesh_cloak_pig" /obj/item/clothing/suit/storage/seromi/cloak/brown_grey - name = "purple and grey cloak" + name = "brown and grey cloak" icon_state = "tesh_cloak_brg" item_state = "tesh_cloak_brg" \ No newline at end of file diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm index 864ee369ba5..97fc8721a8d 100644 --- a/code/modules/clothing/suits/armor.dm +++ b/code/modules/clothing/suits/armor.dm @@ -210,6 +210,36 @@ icon_state = "reactiveoff" ..() +// Alien armor has a chance to completely block attacks. +/obj/item/clothing/suit/armor/alien + name = "alien enhancement vest" + desc = "It's a strange piece of what appears to be armor. It looks very light and agile. Strangely enough it seems to have been designed for a humanoid shape." + description_info = "It has a 20% chance to completely nullify an incoming attack, and the wearer moves slightly faster." + icon_state = "alien_speed" + blood_overlay_type = "armor" + item_state_slots = list(slot_r_hand_str = "armor", slot_l_hand_str = "armor") + slowdown = -1 + body_parts_covered = UPPER_TORSO|LOWER_TORSO + armor = list(melee = 50, bullet = 50, laser = 50, energy = 50, bomb = 50, bio = 0, rad = 40) + siemens_coefficient = 0.4 + var/block_chance = 20 + +/obj/item/clothing/suit/armor/alien/tank + name = "alien protection suit" + desc = "It's really resilient yet lightweight, so it's probably meant to be armor. Strangely enough it seems to have been designed for a humanoid shape." + description_info = "It has a 40% chance to completely nullify an incoming attack." + icon_state = "alien_tank" + slowdown = 0 + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + armor = list(melee = 70, bullet = 70, laser = 70, energy = 70, bomb = 70, bio = 0, rad = 40) + block_chance = 40 + +/obj/item/clothing/suit/armor/alien/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack") + if(prob(block_chance)) + user.visible_message("\The [src] completely absorbs [attack_text]!") + return TRUE + return FALSE + //Non-hardsuit ERT armor. /obj/item/clothing/suit/armor/vest/ert name = "emergency response team armor" diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm index 602b8542879..5819a5e065d 100644 --- a/code/modules/clothing/suits/miscellaneous.dm +++ b/code/modules/clothing/suits/miscellaneous.dm @@ -277,6 +277,7 @@ obj/item/clothing/suit/kimono name = "kimono" desc = "A traditional Japanese kimono." icon_state = "kimono" + addblends = "kimono_a" /* * coats @@ -344,6 +345,7 @@ obj/item/clothing/suit/storage/toggle/peacoat name = "peacoat" desc = "A well-tailored, stylish peacoat." icon_state = "peacoat" + addblends = "peacoat_a" item_state_slots = list(slot_r_hand_str = "peacoat", slot_l_hand_str = "peacoat") flags_inv = HIDEHOLSTER /* @@ -768,6 +770,42 @@ obj/item/clothing/suit/storage/toggle/peacoat name = "mining winter hood" armor = list(melee = 10, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0) +/obj/item/clothing/suit/storage/hooded/explorer + name = "explorer suit" + desc = "An armoured suit for exploring harsh environments." + icon_state = "explorer" + item_state = "explorer" + flags = THICKMATERIAL + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + min_cold_protection_temperature = SPACE_SUIT_MIN_COLD_PROTECTION_TEMPERATURE + cold_protection = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + hooded = TRUE + hoodtype = /obj/item/clothing/head/explorer + siemens_coefficient = 0.9 + armor = list(melee = 30, bullet = 20, laser = 20, energy = 20, bomb = 50, bio = 100, rad = 50) // Inferior to sec vests in bullet/laser but better for environmental protection. + allowed = list( + /obj/item/device/flashlight, + /obj/item/weapon/gun, + /obj/item/ammo_magazine, + /obj/item/weapon/melee, + /obj/item/weapon/material/knife, + /obj/item/weapon/tank, + /obj/item/device/radio, + /obj/item/weapon/pickaxe + ) + +/obj/item/clothing/head/explorer + name = "explorer hood" + desc = "An armoured hood for exploring harsh environments." + icon_state = "explorer" + body_parts_covered = HEAD + cold_protection = HEAD + flags = THICKMATERIAL + flags_inv = HIDEEARS | BLOCKHAIR + min_cold_protection_temperature = SPACE_SUIT_MIN_COLD_PROTECTION_TEMPERATURE + siemens_coefficient = 0.9 + armor = list(melee = 30, bullet = 20, laser = 20, energy = 20, bomb = 50, bio = 100, rad = 50) + /obj/item/clothing/suit/varsity name = "black varsity jacket" desc = "A favorite of jocks everywhere from Sol to Nyx." diff --git a/code/modules/clothing/suits/toggles.dm b/code/modules/clothing/suits/toggles.dm index 1176b910891..b7b3b2b0b37 100644 --- a/code/modules/clothing/suits/toggles.dm +++ b/code/modules/clothing/suits/toggles.dm @@ -31,6 +31,7 @@ /obj/item/clothing/suit/storage/hooded/proc/RemoveHood() icon_state = "[initial(icon_state)]" suittoggled = 0 + hood.canremove = TRUE // This shouldn't matter anyways but just incase. if(ishuman(hood.loc)) var/mob/living/carbon/H = hood.loc H.unEquip(hood, 1) @@ -53,6 +54,7 @@ else H.equip_to_slot_if_possible(hood,slot_head,0,0,1) suittoggled = 1 + hood.canremove = FALSE icon_state = "[initial(icon_state)]_t" H.update_inv_wear_suit() else diff --git a/code/modules/clothing/under/accessories/accessory.dm b/code/modules/clothing/under/accessories/accessory.dm index 4392a264927..5d18858cc35 100644 --- a/code/modules/clothing/under/accessories/accessory.dm +++ b/code/modules/clothing/under/accessories/accessory.dm @@ -45,6 +45,16 @@ mob_overlay = image("icon" = sprite_sheets[wearer.species.get_bodytype(wearer)], "icon_state" = "[tmp_icon_state]") else mob_overlay = image("icon" = INV_ACCESSORIES_DEF_ICON, "icon_state" = "[tmp_icon_state]") + if(addblends) + var/icon/base = new/icon("icon" = mob_overlay.icon, "icon_state" = mob_overlay.icon_state) + var/addblend_icon = new/icon("icon" = mob_overlay.icon, "icon_state" = src.addblends) + if(color) + base.Blend(src.color, ICON_MULTIPLY) + base.Blend(addblend_icon, ICON_ADD) + mob_overlay = image(base) + else + mob_overlay.color = src.color + return mob_overlay //when user attached an accessory to S @@ -234,6 +244,14 @@ name = "medal of exceptional heroism" desc = "An extremely rare golden medal awarded only by high ranking officials. To recieve such a medal is the highest honor and as such, very few exist. This medal is almost never awarded to anybody but distinguished veteran staff." +// Base type for 'medals' found in a "dungeon" submap, as a sort of trophy to celebrate the player's conquest. +/obj/item/clothing/accessory/medal/dungeon + +/obj/item/clothing/accessory/medal/dungeon/alien_ufo + name = "alien captain's medal" + desc = "It vaguely like a star. It looks like something an alien captain might've worn. Probably." + icon_state = "alien_medal" + //Scarves /obj/item/clothing/accessory/scarf @@ -292,3 +310,81 @@ /obj/item/clothing/accessory/scarf/stripedblue name = "striped blue scarf" icon_state = "stripedbluescarf" + +//bracelets + +/obj/item/clothing/accessory/bracelet + name = "bracelet" + desc = "A simple silver bracelet with a clasp." + icon = 'icons/obj/clothing/ties.dmi' + icon_state = "bracelet" + w_class = ITEMSIZE_TINY + slot_flags = SLOT_TIE + +/obj/item/clothing/accessory/bracelet/friendship + name = "friendship bracelet" + desc = "A beautiful friendship bracelet in all the colors of the rainbow." + icon_state = "friendbracelet" + +/obj/item/clothing/accessory/bracelet/friendship/verb/dedicate_bracelet() + set name = "Dedicate Bracelet" + set category = "Object" + set desc = "Dedicate your friendship bracelet to a special someone." + var/mob/M = usr + if(!M.mind) + return 0 + + var/input = sanitizeSafe(input("Who do you want to dedicate the bracelet to?", ,""), MAX_NAME_LEN) + + if(src && input && !M.stat && in_range(M,src)) + desc = "A beautiful friendship bracelet in all the colors of the rainbow. It's dedicated to [input]." + to_chat(M, "You dedicate the bracelet to [input], remembering the times you've had together.") + return 1 + + +/obj/item/clothing/accessory/bracelet/material + icon_state = "materialbracelet" + +/obj/item/clothing/accessory/bracelet/material/New(var/newloc, var/new_material) + ..(newloc) + if(!new_material) + new_material = DEFAULT_WALL_MATERIAL + material = get_material_by_name(new_material) + if(!istype(material)) + qdel(src) + return + name = "[material.display_name] bracelet" + desc = "A bracelet made from [material.display_name]." + color = material.icon_colour + +/obj/item/clothing/accessory/bracelet/material/get_material() + return material + +/obj/item/clothing/accessory/bracelet/material/wood/New(var/newloc) + ..(newloc, "wood") + +/obj/item/clothing/accessory/bracelet/material/plastic/New(var/newloc) + ..(newloc, "plastic") + +/obj/item/clothing/accessory/bracelet/material/iron/New(var/newloc) + ..(newloc, "iron") + +/obj/item/clothing/accessory/bracelet/material/steel/New(var/newloc) + ..(newloc, "steel") + +/obj/item/clothing/accessory/bracelet/material/silver/New(var/newloc) + ..(newloc, "silver") + +/obj/item/clothing/accessory/bracelet/material/gold/New(var/newloc) + ..(newloc, "gold") + +/obj/item/clothing/accessory/bracelet/material/platinum/New(var/newloc) + ..(newloc, "platinum") + +/obj/item/clothing/accessory/bracelet/material/phoron/New(var/newloc) + ..(newloc, "phoron") + +/obj/item/clothing/accessory/bracelet/material/glass/New(var/newloc) + ..(newloc, "glass") + + ..() \ No newline at end of file diff --git a/code/modules/clothing/under/accessories/armband.dm b/code/modules/clothing/under/accessories/armband.dm index 3f53c443929..bf40074a2a2 100644 --- a/code/modules/clothing/under/accessories/armband.dm +++ b/code/modules/clothing/under/accessories/armband.dm @@ -37,6 +37,7 @@ /obj/item/clothing/accessory/armband/med/color name = "armband" desc = "A fancy armband." + addblends = "med_a" /obj/item/clothing/accessory/armband/medblue name = "EMT armband" diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm index f9a0a9ab379..ddfb109ef6b 100644 --- a/code/modules/clothing/under/miscellaneous.dm +++ b/code/modules/clothing/under/miscellaneous.dm @@ -627,17 +627,20 @@ name = "long dress" desc = "A long dress." icon_state = "whitedress2" + addblends = "whitedress2_a" flags_inv = HIDESHOES /obj/item/clothing/under/dress/white3 name = "short dress" desc = "A short, plain dress." icon_state = "whitedress3" + addblends = "whitedress3_a" /obj/item/clothing/under/dress/white4 name = "long flared dress" desc = "A long white dress that flares out at the bottom." icon_state = "whitedress4" + addblends = "whitedress4_a" flags_inv = HIDESHOES /obj/item/clothing/under/dress/darkred @@ -809,3 +812,8 @@ desc = "A fluffy robe to keep you from showing off to the world." icon_state = "bathrobe" worn_state = "bathrobe" + +/obj/item/clothing/under/explorer + desc = "A green uniform for operating in hazardous environments." + name = "explorer's jumpsuit" + icon_state = "explorer" \ No newline at end of file diff --git a/code/modules/clothing/under/pants.dm b/code/modules/clothing/under/pants.dm index 322115cc0b6..c306d842d07 100644 --- a/code/modules/clothing/under/pants.dm +++ b/code/modules/clothing/under/pants.dm @@ -121,6 +121,7 @@ name = "yoga pants" desc = "A pair of tight-fitting yoga pants for those lazy days." icon_state = "yogapants" + addblends = "yogapants_a" /* * Baggy Pants diff --git a/code/modules/clothing/under/xenos/seromi.dm b/code/modules/clothing/under/xenos/seromi.dm index f99317b7d06..5ec18a48594 100644 --- a/code/modules/clothing/under/xenos/seromi.dm +++ b/code/modules/clothing/under/xenos/seromi.dm @@ -82,7 +82,7 @@ item_state = "tesh_uniform_by" /obj/item/clothing/under/seromi/undercoat/black_green - name = "black and Green undercoat" + name = "black and green undercoat" icon_state = "tesh_uniform_bgr" item_state = "tesh_uniform_bgr" @@ -148,8 +148,8 @@ /obj/item/clothing/under/seromi/undercoat/blue_grey name = "blue and grey undercoat" - icon_state = "tesh_uniform_blg" - item_state = "tesh_uniform_blg" + icon_state = "tesh_uniform_blug" + item_state = "tesh_uniform_blug" /obj/item/clothing/under/seromi/undercoat/purple_grey name = "purple and grey undercoat" @@ -157,11 +157,11 @@ item_state = "tesh_uniform_pg" /obj/item/clothing/under/seromi/undercoat/pink_grey - name = "black and orange undercoat" + name = "pink and grey undercoat" icon_state = "tesh_uniform_pig" item_state = "tesh_uniform_pig" /obj/item/clothing/under/seromi/undercoat/brown_grey - name = "purple and grey undercoat" + name = "brown and grey undercoat" icon_state = "tesh_uniform_brg" item_state = "tesh_uniform_brg" \ No newline at end of file diff --git a/code/modules/economy/economy_misc.dm b/code/modules/economy/economy_misc.dm index a2cc9aafb9e..84a187ef91d 100644 --- a/code/modules/economy/economy_misc.dm +++ b/code/modules/economy/economy_misc.dm @@ -49,6 +49,7 @@ /var/list/economic_species_modifier = list( /datum/species/human = 10, + /datum/species/human/vatgrown = 10, /datum/species/skrell = 12, /datum/species/unathi = 7, /datum/species/tajaran = 7, diff --git a/code/modules/integrated_electronics/core/helpers.dm b/code/modules/integrated_electronics/core/helpers.dm index edfa6b1a86c..e31b26fbb1a 100644 --- a/code/modules/integrated_electronics/core/helpers.dm +++ b/code/modules/integrated_electronics/core/helpers.dm @@ -18,7 +18,9 @@ else io_list.Add(new io_type(src, io_entry, default_data)) -/obj/item/integrated_circuit/proc/set_pin_data(var/pin_type, var/pin_number, var/new_data) +/obj/item/integrated_circuit/proc/set_pin_data(var/pin_type, var/pin_number, datum/new_data) + if (istype(new_data) && !isweakref(new_data)) + new_data = weakref(new_data) var/datum/integrated_io/pin = get_pin_ref(pin_type, pin_number) return pin.write_data_to_pin(new_data) diff --git a/code/modules/integrated_electronics/core/pins.dm b/code/modules/integrated_electronics/core/pins.dm index c22d65e4214..8621e2b7ed1 100644 --- a/code/modules/integrated_electronics/core/pins.dm +++ b/code/modules/integrated_electronics/core/pins.dm @@ -112,6 +112,8 @@ list[]( /datum/integrated_io/proc/write_data_to_pin(var/new_data) if(isnull(new_data) || isnum(new_data) || istext(new_data) || isweakref(new_data)) // Anything else is a type we don't want. + if(istext(new_data)) + new_data = sanitizeSafe(new_data, MAX_MESSAGE_LEN, 0, 0) data = new_data holder.on_data_written() diff --git a/code/modules/integrated_electronics/core/special_pins/string_pin.dm b/code/modules/integrated_electronics/core/special_pins/string_pin.dm index 6128418c1f3..595a2053187 100644 --- a/code/modules/integrated_electronics/core/special_pins/string_pin.dm +++ b/code/modules/integrated_electronics/core/special_pins/string_pin.dm @@ -4,11 +4,14 @@ /datum/integrated_io/string/ask_for_pin_data(mob/user) var/new_data = input("Please type in a string.","[src] string writing") as null|text - if(holder.check_interactivity(user) ) + new_data = sanitizeSafe(new_data, MAX_MESSAGE_LEN, 0, 0) + + if(new_data && holder.check_interactivity(user) ) to_chat(user, "You input [new_data ? "new_data" : "NULL"] into the pin.") write_data_to_pin(new_data) /datum/integrated_io/string/write_data_to_pin(var/new_data) + new_data = sanitizeSafe(new_data, MAX_MESSAGE_LEN, 0, 0) if(isnull(new_data) || istext(new_data)) data = new_data holder.on_data_written() diff --git a/code/modules/integrated_electronics/core/tools.dm b/code/modules/integrated_electronics/core/tools.dm index 08765b94e51..0f702be3de0 100644 --- a/code/modules/integrated_electronics/core/tools.dm +++ b/code/modules/integrated_electronics/core/tools.dm @@ -125,6 +125,7 @@ if("string") accepting_refs = 0 new_data = input("Now type in a string.","[src] string writing") as null|text + new_data = sanitizeSafe(new_data, MAX_MESSAGE_LEN, 0, 0) if(istext(new_data) && CanInteract(user, physical_state)) data_to_write = new_data to_chat(user, "You set \the [src]'s memory to \"[new_data]\".") diff --git a/code/modules/integrated_electronics/passive/power.dm b/code/modules/integrated_electronics/passive/power.dm index c417c3e4fd0..0a516e360a7 100644 --- a/code/modules/integrated_electronics/passive/power.dm +++ b/code/modules/integrated_electronics/passive/power.dm @@ -29,6 +29,28 @@ if(assembly) assembly.give_power(adjusted_power) +/obj/item/integrated_circuit/passive/power/starter + name = "starter" + desc = "This tiny circuit will send a pulse right after device is turned on, or when power is restored." + icon_state = "led" + complexity = 1 + activators = list("pulse out" = IC_PINTYPE_PULSE_OUT) + origin_tech = list(TECH_POWER = 3, TECH_ENGINEERING = 3, TECH_DATA = 2) + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + var/is_charge=0 + +/obj/item/integrated_circuit/passive/power/starter/make_energy() + if(assembly.battery) + if(assembly.battery.charge) + if(!is_charge) + activate_pin(1) + is_charge=1 + else + is_charge=0 + else + is_charge=0 + return FALSE + // For implants. /obj/item/integrated_circuit/passive/power/metabolic_siphon name = "metabolic siphon" @@ -82,6 +104,44 @@ origin_tech = list(TECH_POWER = 3, TECH_ENGINEERING = 3, TECH_DATA = 2) spawn_flags = IC_SPAWN_RESEARCH var/power_amount = 250 +//fuel cell + +/obj/item/integrated_circuit/passive/power/chemical_cell + name = "fuel cell" + desc = "Produces electricity from chemicals." + icon_state = "chemical_cell" + extended_desc = "This is effectively an internal beaker. It will consume and produce power from phoron, slime jelly, welding fuel, carbon,\ + ethanol, nutriments and blood, in order of decreasing efficiency. It will consume fuel only if the battery can take more energy." + flags = OPENCONTAINER + complexity = 4 + inputs = list() + outputs = list("volume used" = IC_PINTYPE_NUMBER,"self reference" = IC_PINTYPE_REF) + activators = list() + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2) + var/volume = 60 + var/list/fuel = list("phoron" = 50000, "slimejelly" = 25000, "fuel" = 15000, "carbon" = 10000, "ethanol"= 10000, "nutriment" =8000, "blood" = 5000) + +/obj/item/integrated_circuit/passive/power/chemical_cell/New() + ..() + create_reagents(volume) + +/obj/item/integrated_circuit/passive/power/chemical_cell/interact(mob/user) + set_pin_data(IC_OUTPUT, 2, weakref(src)) + push_data() + ..() + +/obj/item/integrated_circuit/passive/power/chemical_cell/on_reagent_change() + set_pin_data(IC_OUTPUT, 1, reagents.total_volume) + push_data() + +/obj/item/integrated_circuit/passive/power/chemical_cell/make_energy() + if(assembly) + for(var/I in fuel) + if((assembly.battery.maxcharge-assembly.battery.charge) / CELLRATE > fuel[I]) + if(reagents.remove_reagent(I, 1)) + assembly.give_power(fuel[I]) + // For really fat machines. /obj/item/integrated_circuit/passive/power/relay/large diff --git a/code/modules/integrated_electronics/subtypes/data_transfer.dm b/code/modules/integrated_electronics/subtypes/data_transfer.dm index 7b5846eb8d0..e490ccd27a9 100644 --- a/code/modules/integrated_electronics/subtypes/data_transfer.dm +++ b/code/modules/integrated_electronics/subtypes/data_transfer.dm @@ -27,13 +27,10 @@ /obj/item/integrated_circuit/transfer/multiplexer/do_work() var/input_index = get_pin_data(IC_INPUT, 1) - var/output = null if(!isnull(input_index) && (input_index >= 1 && input_index < inputs.len)) - output = get_pin_data(IC_INPUT, input_index + 1) - - set_pin_data(IC_OUTPUT, 1, output) - push_data() + set_pin_data(IC_OUTPUT, 1,get_pin_data(IC_INPUT, input_index + 1)) + push_data() activate_pin(2) /obj/item/integrated_circuit/transfer/multiplexer/medium @@ -79,10 +76,8 @@ /obj/item/integrated_circuit/transfer/demultiplexer/do_work() var/output_index = get_pin_data(IC_INPUT, 1) - var/output = get_pin_data(IC_INPUT, 2) - for(var/i = 1 to outputs.len) - set_pin_data(IC_OUTPUT, i, i == output_index ? output : null) + set_pin_data(IC_OUTPUT, i, i == output_index ? get_pin_data(IC_INPUT, 2) : null) activate_pin(2) @@ -101,4 +96,51 @@ name = "sixteen demultiplexer" icon_state = "dmux16" w_class = ITEMSIZE_SMALL + number_of_outputs = 16 + +/obj/item/integrated_circuit/transfer/pulsedemultiplexer + name = "two pulse demultiplexer" + desc = "Selector switch to choose the pin to be activated by number." + extended_desc = "The first input pin is used to select which of the pulse out pins will be activated after activation of the circuit. \ + If the output selection is outside the valid range then no output is given." + complexity = 2 + icon_state = "dmux2" + inputs = list("output selection" = IC_PINTYPE_NUMBER) + outputs = list() + activators = list("select" = IC_PINTYPE_PULSE_IN) + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + power_draw_per_use = 4 + var/number_of_outputs = 2 + +/obj/item/integrated_circuit/transfer/pulsedemultiplexer/New() + for(var/i = 1 to number_of_outputs) + // outputs += "output [i]" + activators["output [i]"] = IC_PINTYPE_PULSE_OUT + complexity = number_of_outputs + + ..() + desc += " It has [number_of_outputs] output pins." + extended_desc += " This pulse demultiplexer has a range from 1 to [activators.len - 1]." + +/obj/item/integrated_circuit/transfer/pulsedemultiplexer/do_work() + var/output_index = get_pin_data(IC_INPUT, 1) + + if(output_index == Clamp(output_index, 1, number_of_outputs)) + activate_pin(round(output_index + 1 ,1)) + +/obj/item/integrated_circuit/transfer/pulsedemultiplexer/medium + name = "four pulse demultiplexer" + icon_state = "dmux4" + number_of_outputs = 4 + +/obj/item/integrated_circuit/transfer/pulsedemultiplexer/large + name = "eight pulse demultiplexer" + icon_state = "dmux8" + w_class = ITEMSIZE_SMALL + number_of_outputs = 8 + +/obj/item/integrated_circuit/transfer/pulsedemultiplexer/huge + name = "sixteen pulse demultiplexer" + icon_state = "dmux16" + w_class = ITEMSIZE_SMALL number_of_outputs = 16 \ No newline at end of file diff --git a/code/modules/integrated_electronics/subtypes/input.dm b/code/modules/integrated_electronics/subtypes/input.dm index d752f0d5cd9..8da4fad6d8e 100644 --- a/code/modules/integrated_electronics/subtypes/input.dm +++ b/code/modules/integrated_electronics/subtypes/input.dm @@ -110,8 +110,10 @@ /obj/item/integrated_circuit/input/adv_med_scanner - name = "integrated advanced medical analyser" - desc = "A very small version of the medbot's medical analyser. This allows the machine to know how healthy someone is. \ + + name = "integrated advanced medical analyzer" + desc = "A very small version of the medibot's medical analyzer. This allows the machine to know how healthy someone is. \ + This type is much more precise, allowing the machine to know much more about the target than a normal analyzer." icon_state = "medscan_adv" complexity = 12 @@ -134,7 +136,9 @@ var/mob/living/carbon/human/H = get_pin_data_as_type(IC_INPUT, 1, /mob/living/carbon/human) if(!istype(H)) //Invalid input return + if(H in view(get_turf(H))) // Like medbot's analyzer it can be used in range.. + var/total_health = round(H.health/H.getMaxHealth(), 0.01)*100 var/missing_health = H.getMaxHealth() - H.health @@ -336,6 +340,7 @@ // Set the pins so when someone sees them, they won't show as null set_pin_data(IC_INPUT, 1, frequency) set_pin_data(IC_INPUT, 2, code) + push_data() /obj/item/integrated_circuit/input/signaler/Destroy() if(radio_controller) @@ -464,6 +469,7 @@ set_pin_data(IC_OUTPUT, 1, null) set_pin_data(IC_OUTPUT, 2, null) if(!T) + push_data() return set_pin_data(IC_OUTPUT, 1, T.x) @@ -486,7 +492,7 @@ "speaker" = IC_PINTYPE_STRING, "message" = IC_PINTYPE_STRING ) - activators = list("on message received" = IC_PINTYPE_PULSE_IN, "on translation" = IC_PINTYPE_PULSE_OUT) + activators = list("on message received" = IC_PINTYPE_PULSE_OUT, "on translation" = IC_PINTYPE_PULSE_OUT) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH power_draw_per_use = 15 @@ -618,4 +624,235 @@ push_data() activate_pin(2) +/obj/item/integrated_circuit/input/atmo_scanner + name = "integrated atmospheric analyser" + desc = "The same atmospheric analysis module that is integrated into every PDA. \ + This allows the machine to know the composition, temperature and pressure of the surrounding atmosphere." + icon_state = "medscan_adv" + complexity = 9 + inputs = list() + outputs = list( + "pressure" = IC_PINTYPE_NUMBER, + "temperature" = IC_PINTYPE_NUMBER, + "oxygen" = IC_PINTYPE_NUMBER, + "nitrogen" = IC_PINTYPE_NUMBER, + "carbon dioxide" = IC_PINTYPE_NUMBER, + "phoron" = IC_PINTYPE_NUMBER, + "other" = IC_PINTYPE_NUMBER + ) + activators = list("scan" = IC_PINTYPE_PULSE_IN, "on scanned" = IC_PINTYPE_PULSE_OUT) + spawn_flags = IC_SPAWN_RESEARCH + origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3) + power_draw_per_use = 60 +/obj/item/integrated_circuit/input/atmo_scanner/do_work() + var/turf/T = get_turf(src) + if(!istype(T)) //Invalid input + return + var/datum/gas_mixture/environment = T.return_air() + + var/pressure = environment.return_pressure() + var/total_moles = environment.total_moles + + if (total_moles) + var/o2_level = environment.gas["oxygen"]/total_moles + var/n2_level = environment.gas["nitrogen"]/total_moles + var/co2_level = environment.gas["carbon_dioxide"]/total_moles + var/phoron_level = environment.gas["phoron"]/total_moles + var/unknown_level = 1-(o2_level+n2_level+co2_level+phoron_level) + set_pin_data(IC_OUTPUT, 1, pressure) + set_pin_data(IC_OUTPUT, 2, round(environment.temperature-T0C,0.1)) + set_pin_data(IC_OUTPUT, 3, round(o2_level*100,0.1)) + set_pin_data(IC_OUTPUT, 4, round(n2_level*100,0.1)) + set_pin_data(IC_OUTPUT, 5, round(co2_level*100,0.1)) + set_pin_data(IC_OUTPUT, 6, round(phoron_level*100,0.01)) + set_pin_data(IC_OUTPUT, 7, round(unknown_level, 0.01)) + else + set_pin_data(IC_OUTPUT, 1, 0) + set_pin_data(IC_OUTPUT, 2, -273.15) + set_pin_data(IC_OUTPUT, 3, 0) + set_pin_data(IC_OUTPUT, 4, 0) + set_pin_data(IC_OUTPUT, 5, 0) + set_pin_data(IC_OUTPUT, 6, 0) + set_pin_data(IC_OUTPUT, 7, 0) + push_data() + activate_pin(2) + +/obj/item/integrated_circuit/input/pressure_sensor + name = "integrated pressure sensor" + desc = "A tiny pressure sensor module similar to that found in a PDA atmosphere analyser." + icon_state = "medscan_adv" + complexity = 3 + inputs = list() + outputs = list( + "pressure" = IC_PINTYPE_NUMBER + ) + activators = list("scan" = IC_PINTYPE_PULSE_IN, "on scanned" = IC_PINTYPE_PULSE_OUT) + spawn_flags = IC_SPAWN_RESEARCH + origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3) + power_draw_per_use = 20 + +/obj/item/integrated_circuit/input/pressure_sensor/do_work() + var/turf/T = get_turf(src) + if(!istype(T)) //Invalid input + return + var/datum/gas_mixture/environment = T.return_air() + + var/pressure = environment.return_pressure() + var/total_moles = environment.total_moles + + if (total_moles) + set_pin_data(IC_OUTPUT, 1, pressure) + else + set_pin_data(IC_OUTPUT, 1, 0) + push_data() + activate_pin(2) + +/obj/item/integrated_circuit/input/temperature_sensor + name = "integrated temperature sensor" + desc = "A tiny temperature sensor module similar to that found in a PDA atmosphere analyser." + icon_state = "medscan_adv" + complexity = 3 + inputs = list() + outputs = list( + "temperature" = IC_PINTYPE_NUMBER + ) + activators = list("scan" = IC_PINTYPE_PULSE_IN, "on scanned" = IC_PINTYPE_PULSE_OUT) + spawn_flags = IC_SPAWN_RESEARCH + origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3) + power_draw_per_use = 20 + +/obj/item/integrated_circuit/input/temperature_sensor/do_work() + var/turf/T = get_turf(src) + if(!istype(T)) //Invalid input + return + var/datum/gas_mixture/environment = T.return_air() + + var/total_moles = environment.total_moles + + if (total_moles) + set_pin_data(IC_OUTPUT, 1, round(environment.temperature-T0C,0.1)) + else + set_pin_data(IC_OUTPUT, 1, -273.15) + push_data() + activate_pin(2) + +/obj/item/integrated_circuit/input/oxygen_sensor + name = "integrated oxygen sensor" + desc = "A tiny oxygen sensor module similar to that found in a PDA atmosphere analyser." + icon_state = "medscan_adv" + complexity = 3 + inputs = list() + outputs = list( + "oxygen" = IC_PINTYPE_NUMBER + ) + activators = list("scan" = IC_PINTYPE_PULSE_IN, "on scanned" = IC_PINTYPE_PULSE_OUT) + spawn_flags = IC_SPAWN_RESEARCH + origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3) + power_draw_per_use = 20 + +/obj/item/integrated_circuit/input/oxygen_sensor/do_work() + var/turf/T = get_turf(src) + if(!istype(T)) //Invalid input + return + var/datum/gas_mixture/environment = T.return_air() + + var/total_moles = environment.total_moles + + if (total_moles) + var/o2_level = environment.gas["oxygen"]/total_moles + set_pin_data(IC_OUTPUT, 1, round(o2_level*100,0.1)) + else + set_pin_data(IC_OUTPUT, 1, 0) + push_data() + activate_pin(2) + +/obj/item/integrated_circuit/input/co2_sensor + name = "integrated co2 sensor" + desc = "A tiny carbon dioxide sensor module similar to that found in a PDA atmosphere analyser." + icon_state = "medscan_adv" + complexity = 3 + inputs = list() + outputs = list( + "co2" = IC_PINTYPE_NUMBER + ) + activators = list("scan" = IC_PINTYPE_PULSE_IN, "on scanned" = IC_PINTYPE_PULSE_OUT) + spawn_flags = IC_SPAWN_RESEARCH + origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3) + power_draw_per_use = 20 + +/obj/item/integrated_circuit/input/co2_sensor/do_work() + var/turf/T = get_turf(src) + if(!istype(T)) //Invalid input + return + var/datum/gas_mixture/environment = T.return_air() + + var/total_moles = environment.total_moles + + if (total_moles) + var/co2_level = environment.gas["carbon_dioxide"]/total_moles + set_pin_data(IC_OUTPUT, 1, round(co2_level*100,0.1)) + else + set_pin_data(IC_OUTPUT, 1, 0) + push_data() + activate_pin(2) + +/obj/item/integrated_circuit/input/nitrogen_sensor + name = "integrated nitrogen sensor" + desc = "A tiny nitrogen sensor module similar to that found in a PDA atmosphere analyser." + icon_state = "medscan_adv" + complexity = 3 + inputs = list() + outputs = list( + "nitrogen" = IC_PINTYPE_NUMBER + ) + activators = list("scan" = IC_PINTYPE_PULSE_IN, "on scanned" = IC_PINTYPE_PULSE_OUT) + spawn_flags = IC_SPAWN_RESEARCH + origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3) + power_draw_per_use = 20 + +/obj/item/integrated_circuit/input/nitrogen_sensor/do_work() + var/turf/T = get_turf(src) + if(!istype(T)) //Invalid input + return + var/datum/gas_mixture/environment = T.return_air() + + var/total_moles = environment.total_moles + + if (total_moles) + var/n2_level = environment.gas["nitrogen"]/total_moles + set_pin_data(IC_OUTPUT, 1, round(n2_level*100,0.1)) + else + set_pin_data(IC_OUTPUT, 1, 0) + push_data() + activate_pin(2) + +/obj/item/integrated_circuit/input/phoron_sensor + name = "integrated phoron sensor" + desc = "A tiny phoron gas sensor module similar to that found in a PDA atmosphere analyser." + icon_state = "medscan_adv" + complexity = 3 + inputs = list() + outputs = list( + "phoron" = IC_PINTYPE_NUMBER + ) + activators = list("scan" = IC_PINTYPE_PULSE_IN, "on scanned" = IC_PINTYPE_PULSE_OUT) + spawn_flags = IC_SPAWN_RESEARCH + origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3) + power_draw_per_use = 20 + +/obj/item/integrated_circuit/input/phoron_sensor/do_work() + var/turf/T = get_turf(src) + if(!istype(T)) //Invalid input + return + var/datum/gas_mixture/environment = T.return_air() + + var/total_moles = environment.total_moles + + if (total_moles) + var/phoron_level = environment.gas["phoron"]/total_moles + set_pin_data(IC_OUTPUT, 1, round(phoron_level*100,0.1)) + else + set_pin_data(IC_OUTPUT, 1, 0) + push_data() + activate_pin(2) diff --git a/code/modules/integrated_electronics/subtypes/lists.dm b/code/modules/integrated_electronics/subtypes/lists.dm index 84e0724bb93..943141b071a 100644 --- a/code/modules/integrated_electronics/subtypes/lists.dm +++ b/code/modules/integrated_electronics/subtypes/lists.dm @@ -52,12 +52,123 @@ push_data() activate_pin(2) +/obj/item/integrated_circuit/list/search + name = "search circuit" + desc = "This circuit will give index of desired element in the list." + extended_desc = "Search will start at 1 position and will return first matching position." + inputs = list( + "list" = IC_PINTYPE_LIST, + "item" = IC_PINTYPE_ANY + ) + outputs = list( + "index" = IC_PINTYPE_NUMBER + ) + icon_state = "addition" + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + +/obj/item/integrated_circuit/list/search/do_work() + var/list/input_list = get_pin_data(IC_INPUT, 1) + var/item = get_pin_data(IC_INPUT, 2) + set_pin_data(IC_OUTPUT, 1, input_list.Find(item)) + push_data() + activate_pin(2) + +/obj/item/integrated_circuit/list/at + name = "at circuit" + desc = "This circuit will pick an element from a list by index." + extended_desc = "If there is no element with such index, result will be null." + inputs = list( + "list" = IC_PINTYPE_LIST, + "index" = IC_PINTYPE_NUMBER + ) + outputs = list("item" = IC_PINTYPE_ANY) + icon_state = "addition" + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + +/obj/item/integrated_circuit/list/at/do_work() + var/list/input_list = get_pin_data(IC_INPUT, 1) + var/index = get_pin_data(IC_INPUT, 2) + var/item = input_list[index] + set_pin_data(IC_OUTPUT, 1, item) + push_data() + activate_pin(2) + +/obj/item/integrated_circuit/list/delete + name = "delete circuit" + desc = "This circuit will delete the element from a list by index." + extended_desc = "If there is no element with such index, result list will be unchanged." + inputs = list( + "list" = IC_PINTYPE_LIST, + "index" = IC_PINTYPE_NUMBER + ) + outputs = list( + "item" = IC_PINTYPE_LIST + ) + icon_state = "addition" + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + +/obj/item/integrated_circuit/list/delete/do_work() + var/list/input_list = get_pin_data(IC_INPUT, 1) + var/list/red_list = list() + var/index = get_pin_data(IC_INPUT, 2) + var/j = 0 + for(var/I in input_list) + j = j + 1 + if(j != index) + red_list.Add(I) + set_pin_data(IC_OUTPUT, 1, red_list) + push_data() + activate_pin(2) + +/obj/item/integrated_circuit/list/write + name = "write circuit" + desc = "This circuit will write element in list with given index." + extended_desc = "If there is no element with such index, it will give the same list, as before." + inputs = list( + "list" = IC_PINTYPE_LIST, + "index" = IC_PINTYPE_NUMBER, + "item" = IC_PINTYPE_ANY + ) + outputs = list( + "redacted list" = IC_PINTYPE_LIST + ) + icon_state = "addition" + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + +/obj/item/integrated_circuit/list/write/do_work() + var/list/input_list = get_pin_data(IC_INPUT, 1) + var/index = get_pin_data(IC_INPUT, 2) + var/item = get_pin_data(IC_INPUT, 3) + input_list[index] = item + set_pin_data(IC_OUTPUT, 1, input_list) + push_data() + activate_pin(2) + +obj/item/integrated_circuit/list/len + name = "len circuit" + desc = "This circuit will give length of the list." + inputs = list( + "list" = IC_PINTYPE_LIST, + ) + outputs = list( + "item" = IC_PINTYPE_NUMBER + ) + icon_state = "addition" + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + +/obj/item/integrated_circuit/list/len/do_work() + var/list/input_list = get_pin_data(IC_INPUT, 1) + set_pin_data(IC_OUTPUT, 1, input_list.len) + push_data() + activate_pin(2) + + /obj/item/integrated_circuit/list/jointext name = "join text circuit" desc = "This circuit will add all elements of a list into one string, seperated by a character." extended_desc = "Default settings will encode the entire list into a string." inputs = list( - "list to join" = IC_PINTYPE_LIST, + "list to join" = IC_PINTYPE_LIST,// "delimiter" = IC_PINTYPE_CHAR, "start" = IC_PINTYPE_NUMBER, "end" = IC_PINTYPE_NUMBER diff --git a/code/modules/integrated_electronics/subtypes/memory.dm b/code/modules/integrated_electronics/subtypes/memory.dm index fa4fd9ded63..40f617e62e7 100644 --- a/code/modules/integrated_electronics/subtypes/memory.dm +++ b/code/modules/integrated_electronics/subtypes/memory.dm @@ -40,8 +40,15 @@ O.push_data() activate_pin(2) +/obj/item/integrated_circuit/memory/tiny + name = "small memory circuit" + desc = "This circuit can store two pieces of data." + icon_state = "memory2" + power_draw_per_use = 2 + number_of_pins = 2 + /obj/item/integrated_circuit/memory/medium - name = "memory circuit" + name = "medium memory circuit" desc = "This circuit can store four pieces of data." icon_state = "memory4" power_draw_per_use = 2 diff --git a/code/modules/integrated_electronics/subtypes/power.dm b/code/modules/integrated_electronics/subtypes/power.dm index f5284341294..e1e3f56c892 100644 --- a/code/modules/integrated_electronics/subtypes/power.dm +++ b/code/modules/integrated_electronics/subtypes/power.dm @@ -37,9 +37,7 @@ amount_to_move = 20000 /obj/item/integrated_circuit/power/transmitter/do_work() - set_pin_data(IC_OUTPUT, 1, null) - set_pin_data(IC_OUTPUT, 2, null) - set_pin_data(IC_OUTPUT, 3, null) + var/atom/movable/AM = get_pin_data_as_type(IC_INPUT, 1, /atom/movable) if(AM) if(!assembly) @@ -72,7 +70,15 @@ set_pin_data(IC_OUTPUT, 2, cell.maxcharge) set_pin_data(IC_OUTPUT, 3, cell.percent()) activate_pin(2) + push_data() return TRUE + else + set_pin_data(IC_OUTPUT, 1, null) + set_pin_data(IC_OUTPUT, 2, null) + set_pin_data(IC_OUTPUT, 3, null) + activate_pin(2) + push_data() + return FALSE return FALSE /obj/item/integrated_circuit/power/transmitter/large/do_work() diff --git a/code/modules/integrated_electronics/subtypes/reagents.dm b/code/modules/integrated_electronics/subtypes/reagents.dm index 25a80c2a28d..e6d65bd07a3 100644 --- a/code/modules/integrated_electronics/subtypes/reagents.dm +++ b/code/modules/integrated_electronics/subtypes/reagents.dm @@ -1,6 +1,8 @@ /obj/item/integrated_circuit/reagent category_text = "Reagent" var/volume = 0 + unacidable = 1 + phoronproof = 1 origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2) /obj/item/integrated_circuit/reagent/New() @@ -18,13 +20,23 @@ complexity = 20 cooldown_per_use = 30 SECONDS inputs = list() - outputs = list() - activators = list("create smoke" = IC_PINTYPE_PULSE_IN) + outputs = list("volume used" = IC_PINTYPE_NUMBER,"self reference" = IC_PINTYPE_REF) + activators = list("create smoke" = IC_PINTYPE_PULSE_IN,"on smoked" = IC_PINTYPE_PULSE_OUT) spawn_flags = IC_SPAWN_RESEARCH origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3, TECH_BIO = 3) volume = 100 power_draw_per_use = 20 +/obj/item/integrated_circuit/reagent/smoke/on_reagent_change() + set_pin_data(IC_OUTPUT, 1, reagents.total_volume) + push_data() + + +/obj/item/integrated_circuit/reagent/smoke/interact(mob/user) + set_pin_data(IC_OUTPUT, 2, weakref(src)) + push_data() + ..() + /obj/item/integrated_circuit/reagent/smoke/do_work() playsound(src.loc, 'sound/effects/smoke.ogg', 50, 1, -3) var/datum/effect/effect/system/smoke_spread/chem/smoke_system = new() @@ -33,52 +45,141 @@ for(var/i = 1 to 8) smoke_system.start() reagents.clear_reagents() + activate_pin(2) /obj/item/integrated_circuit/reagent/injector name = "integrated hypo-injector" desc = "This scary looking thing is able to pump liquids into whatever it's pointed at." icon_state = "injector" extended_desc = "This autoinjector can push reagents into another container or someone else outside of the machine. The target \ - must be adjacent to the machine, and if it is a person, they cannot be wearing thick clothing." + must be adjacent to the machine, and if it is a person, they cannot be wearing thick clothing. A negative amount makes the injector draw out reagents." flags = OPENCONTAINER complexity = 20 cooldown_per_use = 6 SECONDS inputs = list("target" = IC_PINTYPE_REF, "injection amount" = IC_PINTYPE_NUMBER) inputs_default = list("2" = 5) - outputs = list() - activators = list("inject" = IC_PINTYPE_PULSE_IN) + outputs = list("volume used" = IC_PINTYPE_NUMBER,"self reference" = IC_PINTYPE_REF) + activators = list("inject" = IC_PINTYPE_PULSE_IN, "on injected" = IC_PINTYPE_PULSE_OUT, "on fail" = IC_PINTYPE_PULSE_OUT) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH volume = 30 power_draw_per_use = 15 + var/direc = 1 + var/transfer_amount = 10 + +/obj/item/integrated_circuit/reagent/injector/interact(mob/user) + set_pin_data(IC_OUTPUT, 2, weakref(src)) + push_data() + ..() + + +/obj/item/integrated_circuit/reagent/injector/on_reagent_change() + set_pin_data(IC_OUTPUT, 1, reagents.total_volume) + push_data() + +/obj/item/integrated_circuit/reagent/injector/on_data_written() + var/new_amount = get_pin_data(IC_INPUT, 2) + if(new_amount < 0) + new_amount = -new_amount + direc = 0 + else + direc = 1 + if(isnum(new_amount)) + new_amount = Clamp(new_amount, 0, volume) + transfer_amount = new_amount -/obj/item/integrated_circuit/reagent/injector/proc/inject_amount() - var/amount = get_pin_data(IC_INPUT, 2) - if(isnum(amount)) - return Clamp(amount, 0, 30) /obj/item/integrated_circuit/reagent/injector/do_work() set waitfor = 0 // Don't sleep in a proc that is called by a processor without this set, otherwise it'll delay the entire thing - var/atom/movable/AM = get_pin_data_as_type(IC_INPUT, 1, /atom/movable) if(!istype(AM)) //Invalid input + activate_pin(3) return - if(!reagents.total_volume) // Empty - return - if(AM.can_be_injected_by(src)) - if(isliving(AM)) - var/mob/living/L = AM - var/turf/T = get_turf(AM) - T.visible_message("[src] is trying to inject [L]!") - sleep(3 SECONDS) - if(!L.can_be_injected_by(src)) + + if(direc == 1) + + if(!istype(AM)) //Invalid input + activate_pin(3) + return + if(!reagents.total_volume) // Empty + activate_pin(3) + return + if(AM.can_be_injected_by(src)) + if(isliving(AM)) + var/mob/living/L = AM + var/turf/T = get_turf(AM) + T.visible_message("[src] is trying to inject [L]!") + sleep(3 SECONDS) + if(!L.can_be_injected_by(src)) + activate_pin(3) + return + var/contained = reagents.get_reagents() + var/trans = reagents.trans_to_mob(L, transfer_amount, CHEM_BLOOD) + message_admins("[src] injected \the [L] with [trans]u of [contained].") + to_chat(AM, "You feel a tiny prick!") + visible_message("[src] injects [L]!") + else + reagents.trans_to(AM, transfer_amount) + else + + if(reagents.total_volume >= volume) // Full + activate_pin(3) + return + var/obj/target = AM + if(!target.reagents) + activate_pin(3) + return + var/turf/TS = get_turf(src) + var/turf/TT = get_turf(AM) + if(!TS.Adjacent(TT)) + activate_pin(3) + return + var/tramount = Clamp(min(transfer_amount, reagents.maximum_volume - reagents.total_volume), 0, reagents.maximum_volume) + if(ismob(target))//Blood! + if(istype(target, /mob/living/carbon)) + var/mob/living/carbon/T = target + if(!T.dna) + if(T.reagents.trans_to_obj(src, tramount)) + activate_pin(2) + else + activate_pin(3) + return + if(NOCLONE in T.mutations) //target done been et, no more blood in him + if(T.reagents.trans_to_obj(src, tramount)) + activate_pin(2) + else + activate_pin(3) + return + return + var/datum/reagent/B + if(istype(T, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = T + if(H.species && !H.should_have_organ(O_HEART)) + H.reagents.trans_to_obj(src, tramount) + else + B = T.take_blood(src, tramount) + else + B = T.take_blood(src,tramount) + if (B) + reagents.reagent_list |= B + reagents.update_total() + on_reagent_change() + reagents.handle_reactions() + B = null + visible_message( "Machine takes a blood sample from [target].") + else + activate_pin(3) return - var/contained = reagents.get_reagents() - var/trans = reagents.trans_to_mob(L, inject_amount(), CHEM_BLOOD) - message_admins("[src] injected \the [L] with [trans]u of [contained].") - to_chat(AM, "You feel a tiny prick!") - visible_message("[src] injects [L]!") - else - reagents.trans_to(AM, inject_amount()) + + else //if not mob + if(!target.reagents.total_volume) + visible_message( "[target] is empty.") + activate_pin(3) + return + target.reagents.trans_to_obj(src, tramount) + activate_pin(2) + + + /obj/item/integrated_circuit/reagent/pump name = "reagent pump" @@ -96,11 +197,17 @@ spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2) var/transfer_amount = 10 + var/direc = 1 power_draw_per_use = 10 /obj/item/integrated_circuit/reagent/pump/on_data_written() var/new_amount = get_pin_data(IC_INPUT, 3) - if(!isnull(new_amount)) + if(new_amount < 0) + new_amount = -new_amount + direc = 0 + else + direc = 1 + if(isnum(new_amount)) new_amount = Clamp(new_amount, 0, 50) transfer_amount = new_amount @@ -111,17 +218,23 @@ if(!istype(source) || !istype(target)) //Invalid input return var/turf/T = get_turf(src) - if(source.Adjacent(T) && target.Adjacent(T)) + var/turf/TS = get_turf(source) + var/turf/TT = get_turf(target) + if(TS.Adjacent(T) && TT.Adjacent(T)) if(!source.reagents || !target.reagents) return if(ismob(source) || ismob(target)) return if(!source.is_open_container() || !target.is_open_container()) return - if(!target.reagents.get_free_space()) - return - - source.reagents.trans_to(target, transfer_amount) + if(direc) + if(!target.reagents.get_free_space()) + return + source.reagents.trans_to(target, transfer_amount) + else + if(!source.reagents.get_free_space()) + return + target.reagents.trans_to(source, transfer_amount) activate_pin(2) /obj/item/integrated_circuit/reagent/storage @@ -132,12 +245,18 @@ flags = OPENCONTAINER complexity = 4 inputs = list() - outputs = list("volume used" = IC_PINTYPE_NUMBER) + outputs = list("volume used" = IC_PINTYPE_NUMBER,"self reference" = IC_PINTYPE_REF) activators = list() spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2) volume = 60 + +/obj/item/integrated_circuit/reagent/storage/interact(mob/user) + set_pin_data(IC_OUTPUT, 2, weakref(src)) + push_data() + ..() + /obj/item/integrated_circuit/reagent/storage/on_reagent_change() set_pin_data(IC_OUTPUT, 1, reagents.total_volume) push_data() @@ -150,4 +269,95 @@ flags = OPENCONTAINER | NOREACT complexity = 8 spawn_flags = IC_SPAWN_RESEARCH - origin_tech = list(TECH_MATERIAL = 3, TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2) \ No newline at end of file + origin_tech = list(TECH_MATERIALS = 4, TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2) + +/obj/item/integrated_circuit/reagent/storage/big + name = "big reagent storage" + desc = "Stores liquid inside, and away from electrical components. Can store up to 180u." + icon_state = "reagent_storage_big" + extended_desc = "This is effectively an internal beaker." + flags = OPENCONTAINER + complexity = 16 + volume = 180 + spawn_flags = IC_SPAWN_RESEARCH + origin_tech = list(TECH_MATERIALS = 3, TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2) + +/obj/item/integrated_circuit/reagent/storage/scan + name = "reagent scanner" + desc = "Stores liquid inside, and away from electrical components. Can store up to 60u. On pulse this beaker will send list of contained reagents." + icon_state = "reagent_scan" + extended_desc = "Mostly useful for reagent filter." + flags = OPENCONTAINER + complexity = 8 + outputs = list("volume used" = IC_PINTYPE_NUMBER,"self reference" = IC_PINTYPE_REF,"list of reagents" = IC_PINTYPE_LIST) + activators = list("scan" = IC_PINTYPE_PULSE_IN) + spawn_flags = IC_SPAWN_RESEARCH + origin_tech = list(TECH_MATERIALS = 3, TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2) + +/obj/item/integrated_circuit/reagent/storage/scan/do_work() + var/cont[0] + for(var/datum/reagent/RE in reagents.reagent_list) + cont += RE.id + set_pin_data(IC_OUTPUT, 3, cont) + push_data() + + +/obj/item/integrated_circuit/reagent/filter + name = "reagent filter" + desc = "Filtering liquids by list of desired or unwanted reagents." + icon_state = "reagent_filter" + extended_desc = "This is a filter which will move liquids from the source ref to the target ref. \ + It will move all reagents, except list, given in fourth pin if amount value is positive.\ + Or it will move only desired reagents if amount is negative, The third pin determines \ + how much reagent is moved per pulse, between 0 and 50. Amount is given for each separate reagent." + flags = OPENCONTAINER + complexity = 8 + inputs = list("source" = IC_PINTYPE_REF, "target" = IC_PINTYPE_REF, "injection amount" = IC_PINTYPE_NUMBER, "list of reagents" = IC_PINTYPE_LIST) + inputs_default = list("3" = 5) + outputs = list() + activators = list("transfer reagents" = IC_PINTYPE_PULSE_IN, "on transfer" = IC_PINTYPE_PULSE_OUT) + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2) + var/transfer_amount = 10 + var/direc = 1 + power_draw_per_use = 10 + +/obj/item/integrated_circuit/reagent/filter/on_data_written() + var/new_amount = get_pin_data(IC_INPUT, 3) + if(new_amount < 0) + new_amount = -new_amount + direc = 0 + else + direc = 1 + if(isnum(new_amount)) + new_amount = Clamp(new_amount, 0, 50) + transfer_amount = new_amount + +/obj/item/integrated_circuit/reagent/filter/do_work() + var/atom/movable/source = get_pin_data_as_type(IC_INPUT, 1, /atom/movable) + var/atom/movable/target = get_pin_data_as_type(IC_INPUT, 2, /atom/movable) + var/list/demand = get_pin_data(IC_INPUT, 4) + if(!istype(source) || !istype(target)) //Invalid input + return + var/turf/T = get_turf(src) + if(source.Adjacent(T) && target.Adjacent(T)) + if(!source.reagents || !target.reagents) + return + if(ismob(source) || ismob(target)) + return + if(!source.is_open_container() || !target.is_open_container()) + return + if(!target.reagents.get_free_space()) + return + for(var/datum/reagent/G in source.reagents.reagent_list) + if (!direc) + if(G.id in demand) + source.reagents.trans_id_to(target, G.id, transfer_amount) + else + if(!(G.id in demand)) + source.reagents.trans_id_to(target, G.id, transfer_amount) + activate_pin(2) + push_data() + + + diff --git a/code/modules/maps/tg/map_template.dm b/code/modules/maps/tg/map_template.dm index 3aaf324463b..54b08c74d9e 100644 --- a/code/modules/maps/tg/map_template.dm +++ b/code/modules/maps/tg/map_template.dm @@ -18,6 +18,12 @@ var/list/global/map_templates = list() var/mappath = null var/loaded = 0 // Times loaded this round var/annihilate = FALSE // If true, all (movable) atoms at the location where the map is loaded will be deleted before the map is loaded in. + + var/cost = null // The map generator has a set 'budget' it spends to place down different submaps. It will pick available submaps randomly until \ + it runs out. The cost of a submap should roughly corrispond with several factors such as size, loot, difficulty, desired scarcity, etc. \ + Set to -1 to force the submap to always be made. + var/allow_duplicates = FALSE // If false, only one map template will be spawned by the game. Doesn't affect admins spawning then manually. + var/static/dmm_suite/maploader = new /datum/map_template/New(path = null, rename = null) @@ -111,7 +117,7 @@ var/list/global/map_templates = list() log_game("Z-level [name] loaded at at [x],[y],[world.maxz]") return TRUE -/datum/map_template/proc/load(turf/T, centered = FALSE) +/datum/map_template/proc/load(turf/T, centered = FALSE, dont_init = FALSE) var/old_T = T if(centered) T = locate(T.x - round(width/2) , T.y - round(height/2) , T.z) @@ -133,7 +139,8 @@ var/list/global/map_templates = list() // repopulate_sorted_areas() //initialize things that are normally initialized after map load - initTemplateBounds(bounds) + if(!dont_init) + initTemplateBounds(bounds) log_game("[name] loaded at at [T.x],[T.y],[T.z]") loaded++ @@ -163,4 +170,118 @@ var/list/global/map_templates = list() //⤠- Cyberboss /proc/load_new_z_level(var/file, var/name) var/datum/map_template/template = new(file, name) - template.load_new_z() \ No newline at end of file + template.load_new_z() + +// Very similar to the /tg/ version. +/proc/seed_submaps(var/list/z_levels, var/budget = 0, var/whitelist = /area/space, var/desired_map_template_type = null) + set background = TRUE + + if(!z_levels || !z_levels.len) + admin_notice("seed_submaps() was not given any Z-levels.", R_DEBUG) + return + + for(var/zl in z_levels) + var/turf/T = locate(1, 1, zl) + if(!T) + admin_notice("Z level [zl] does not exist - Not generating submaps", R_DEBUG) + return + + var/overall_sanity = 100 // If the proc fails to place a submap more than this, the whole thing aborts. + var/list/potential_submaps = list() // Submaps we may or may not place. + var/list/priority_submaps = list() // Submaps that will always be placed. + + // Lets go find some submaps to make. + for(var/map in map_templates) + var/datum/map_template/MT = map_templates[map] + if(!MT.allow_duplicates && MT.loaded > 0) // This probably won't be an issue but we might as well. + continue + if(!istype(MT, desired_map_template_type)) // Not the type wanted. + continue + if(MT.cost && MT.cost < 0) // Negative costs always get spawned. + priority_submaps += MT + else + potential_submaps += MT + + CHECK_TICK + + var/list/loaded_submap_names = list() + + // Now lets start choosing some. + while(budget > 0 && overall_sanity > 0) + overall_sanity-- + var/datum/map_template/chosen_template = null + + if(potential_submaps.len) + if(priority_submaps.len) // Do these first. + chosen_template = pick(priority_submaps) + else + chosen_template = pick(potential_submaps) + + else // We're out of submaps. + admin_notice("Submap loader had no submaps to pick from with [budget] left to spend.", R_DEBUG) + break + + CHECK_TICK + + // Can we afford it? + if(chosen_template.cost > budget) + continue + + // If so, try to place it. + var/specific_sanity = 100 // A hundred chances to place the chosen submap. + while(specific_sanity > 0) + specific_sanity-- + var/width_border = TRANSITIONEDGE + SUBMAP_MAP_EDGE_PAD + round(chosen_template.width / 2) + var/height_border = TRANSITIONEDGE + SUBMAP_MAP_EDGE_PAD + round(chosen_template.height / 2) + var/z_level = pick(z_levels) + var/turf/T = locate(rand(width_border, world.maxx - width_border), rand(height_border, world.maxy - height_border), z_level) + var/valid = TRUE + + for(var/turf/check in chosen_template.get_affected_turfs(T,1)) + var/area/new_area = get_area(check) + if(!(istype(new_area, whitelist))) + valid = FALSE // Probably overlapping something important. + // world << "Invalid due to overlapping with area [new_area.type], when wanting area [whitelist]." + break + CHECK_TICK + + CHECK_TICK + + if(!valid) + continue + + admin_notice("Submap \"[chosen_template.name]\" placed at ([T.x], [T.y], [T.z])", R_DEBUG) + + // Do loading here. + chosen_template.load(T, centered = TRUE, dont_init = TRUE) // This is run before the main map's initialization routine, so that can initilize our submaps for us instead. + + CHECK_TICK + + if(loaded_submap_names[chosen_template.name]) + loaded_submap_names[chosen_template.name] += 1 + else + loaded_submap_names[chosen_template.name] = 1 + + if(chosen_template.cost >= 0) + budget -= chosen_template.cost + + if(chosen_template in priority_submaps) // Always remove priority submaps. + priority_submaps -= chosen_template + else if(!chosen_template.allow_duplicates) + potential_submaps -= chosen_template + + break // Load the next submap. + + var/list/pretty_submap_list = list() + for(var/submap_name in loaded_submap_names) + var/count = loaded_submap_names[submap_name] + if(count > 1) + pretty_submap_list += "[count] [submap_name]" + else + pretty_submap_list += "[submap_name]" + + if(!overall_sanity) + admin_notice("Submap loader gave up with [budget] left to spend.", R_DEBUG) + else + admin_notice("Submaps loaded.", R_DEBUG) + admin_notice("Loaded: [english_list(pretty_submap_list)]", R_DEBUG) \ No newline at end of file diff --git a/code/modules/materials/material_recipes.dm b/code/modules/materials/material_recipes.dm index c0c1eecd9e7..7408b692a73 100644 --- a/code/modules/materials/material_recipes.dm +++ b/code/modules/materials/material_recipes.dm @@ -13,7 +13,7 @@ recipes += new/datum/stack_recipe("[display_name] armor plate", /obj/item/weapon/material/armor_plating, 1, time = 20, on_floor = 1, supplied_material = "[name]") recipes += new/datum/stack_recipe("[display_name] grave marker", /obj/item/weapon/material/gravemarker, 5, time = 50, supplied_material = "[name]") recipes += new/datum/stack_recipe("[display_name] ring", /obj/item/clothing/gloves/ring/material, 1, on_floor = 1, supplied_material = "[name]") - + recipes += new/datum/stack_recipe("[display_name] bracelet", /obj/item/clothing/accessory/bracelet/material, 1, on_floor = 1, supplied_material = "[name]") if(integrity>=50) recipes += new/datum/stack_recipe("[display_name] door", /obj/structure/simple_door, 10, one_per_turf = 1, on_floor = 1, supplied_material = "[name]") diff --git a/code/modules/materials/materials.dm b/code/modules/materials/materials.dm index 0db3a1016ec..1ce1eca2d81 100644 --- a/code/modules/materials/materials.dm +++ b/code/modules/materials/materials.dm @@ -642,6 +642,19 @@ var/list/name_to_material display_name = "elevator panelling" icon_colour = "#666666" +// Ditto. +/material/alienalloy/dungeonium + name = "dungeonium" + display_name = "ultra-durable" + icon_base = "dungeon" + icon_colour = "#FFFFFF" + +/material/alienalloy/alium + name = "alium" + display_name = "alien" + icon_base = "alien" + icon_colour = "#FFFFFF" + /material/resin name = "resin" icon_colour = "#35343a" diff --git a/code/modules/mob/_modifiers/modifiers.dm b/code/modules/mob/_modifiers/modifiers.dm index ee6d914fa69..3facabe6f97 100644 --- a/code/modules/mob/_modifiers/modifiers.dm +++ b/code/modules/mob/_modifiers/modifiers.dm @@ -41,6 +41,7 @@ var/accuracy // Positive numbers makes hitting things with guns easier, negatives make it harder. Each point makes it 15% easier or harder, just like evasion. var/accuracy_dispersion // Positive numbers make gun firing cover a wider tile range, and therefore more inaccurate. Negatives help negate dispersion penalties. var/metabolism_percent // Adjusts the mob's metabolic rate, which affects reagent processing. Won't affect mobs without reagent processing. + var/icon_scale_percent // Makes the holder's icon get scaled up or down. /datum/modifier/New(var/new_holder, var/new_origin) holder = new_holder @@ -62,6 +63,8 @@ holder.modifiers.Remove(src) if(mob_overlay_state) // We do this after removing ourselves from the list so that the overlay won't remain. holder.update_modifier_visuals() + if(icon_scale_percent) // Correct the scaling. + holder.update_transform() qdel(src) // Override this for special effects when it gets removed. @@ -117,6 +120,8 @@ modifiers.Add(mod) if(mod.mob_overlay_state) update_modifier_visuals() + if(mod.icon_scale_percent) + update_transform() return mod @@ -198,6 +203,8 @@ effects += "Your metabolism is [metabolism_percent > 1.0 ? "faster" : "slower"], \ causing reagents in your body to process, and hunger to occur [multipler_to_percentage(metabolism_percent, TRUE)] [metabolism_percent > 1.0 ? "faster" : "slower"]." + if(!isnull(icon_scale_percent)) + effects += "Your appearance is [multipler_to_percentage(icon_scale_percent, TRUE)] [icon_scale_percent > 1 ? "larger" : "smaller"]." return jointext(effects, "
") diff --git a/code/modules/mob/_modifiers/traits.dm b/code/modules/mob/_modifiers/traits.dm index 824343c41c4..3e9e8278e42 100644 --- a/code/modules/mob/_modifiers/traits.dm +++ b/code/modules/mob/_modifiers/traits.dm @@ -58,4 +58,28 @@ desc = "Your body's metabolism is slower than average." metabolism_percent = 0.5 - incoming_healing_percent = 0.6 \ No newline at end of file + incoming_healing_percent = 0.6 + +/datum/modifier/trait/larger + name = "Larger" + desc = "Your body is larger than average." + + icon_scale_percent = 1.2 + +/datum/modifier/trait/large + name = "Large" + desc = "Your body is a bit larger than average." + + icon_scale_percent = 1.1 + +/datum/modifier/trait/small + name = "Small" + desc = "Your body is a bit smaller than average." + + icon_scale_percent = 0.95 + +/datum/modifier/trait/smaller + name = "Smaller" + desc = "Your body is smaller than average." + + icon_scale_percent = 0.9 \ No newline at end of file diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 83bf7246076..52426454e22 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -201,6 +201,11 @@ Works together with spawning an observer, noted above. /mob/proc/ghostize(var/can_reenter_corpse = 1) if(key) + if(ishuman(src)) + var/mob/living/carbon/human/H = src + if(H.vr_holder && !can_reenter_corpse) + H.exit_vr() + return 0 var/mob/observer/dead/ghost = new(src) //Transfer safety to observer spawning proc. ghost.can_reenter_corpse = can_reenter_corpse ghost.timeofdeath = src.timeofdeath //BS12 EDIT @@ -243,9 +248,10 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp var/turf/location = get_turf(src) message_admins("[key_name_admin(usr)] has ghosted. (JMP)") log_game("[key_name_admin(usr)] has ghosted.") - var/mob/observer/dead/ghost = ghostize(0) //0 parameter is so we can never re-enter our body, "Charlie, you can never come baaaack~" :3 - ghost.timeofdeath = world.time // Because the living mob won't have a time of death and we want the respawn timer to work properly. - announce_ghost_joinleave(ghost) + var/mob/observer/dead/ghost = ghostize(0) // 0 parameter is so we can never re-enter our body, "Charlie, you can never come baaaack~" :3 + if(ghost) + ghost.timeofdeath = world.time // Because the living mob won't have a time of death and we want the respawn timer to work properly. + announce_ghost_joinleave(ghost) /mob/observer/dead/can_use_hands() return 0 /mob/observer/dead/is_active() return 0 @@ -310,19 +316,18 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp if(!client) return - var/mentor = is_eventM(usr.client) - if(!config.antag_hud_allowed && (!client.holder || mentor)) + if(!config.antag_hud_allowed && !client.holder) src << "Admins have disabled this for this round." return var/mob/observer/dead/M = src if(jobban_isbanned(M, "AntagHUD")) src << "You have been banned from using this feature" return - if(config.antag_hud_restricted && !M.has_enabled_antagHUD && (!client.holder || mentor)) + if(config.antag_hud_restricted && !M.has_enabled_antagHUD && !client.holder) var/response = alert(src, "If you turn this on, you will not be able to take any part in the round.","Are you sure you want to turn this feature on?","Yes","No") if(response == "No") return M.can_reenter_corpse = 0 - if(!M.has_enabled_antagHUD && (!client.holder || mentor)) + if(!M.has_enabled_antagHUD && !client.holder) M.has_enabled_antagHUD = 1 if(M.antagHUD) M.antagHUD = 0 diff --git a/code/modules/mob/living/carbon/alien/alien_attacks.dm b/code/modules/mob/living/carbon/alien/alien_attacks.dm index e201e851167..c120b9deefa 100644 --- a/code/modules/mob/living/carbon/alien/alien_attacks.dm +++ b/code/modules/mob/living/carbon/alien/alien_attacks.dm @@ -15,7 +15,7 @@ if (I_GRAB) if (M == src) return - var/obj/item/weapon/grab/G = new /obj/item/weapon/grab( M, M, src ) + var/obj/item/weapon/grab/G = new /obj/item/weapon/grab( M, src ) M.put_in_active_hand(G) @@ -56,4 +56,4 @@ for(var/mob/O in viewers(src, null)) if ((O.client && !( O.blinded ))) O.show_message(text("[] has attempted to punch []!", M, src), 1) - return \ No newline at end of file + return diff --git a/code/modules/mob/living/carbon/alien/diona/diona.dm b/code/modules/mob/living/carbon/alien/diona/diona.dm index ebcd4d7774f..8a2b24cf50f 100644 --- a/code/modules/mob/living/carbon/alien/diona/diona.dm +++ b/code/modules/mob/living/carbon/alien/diona/diona.dm @@ -37,4 +37,12 @@ return hat = new_hat new_hat.loc = src - update_icons() \ No newline at end of file + update_icons() + +/mob/living/carbon/alien/diona/proc/handle_npc(var/mob/living/carbon/alien/diona/D) + if(D.stat != CONSCIOUS) + return + if(prob(33) && D.canmove && isturf(D.loc) && !D.pulledby) //won't move if being pulled + step(D, pick(cardinal)) + if(prob(1)) + D.emote(pick("scratch","jump","chirp","roll")) diff --git a/code/modules/mob/living/carbon/alien/diona/diona_attacks.dm b/code/modules/mob/living/carbon/alien/diona/diona_attacks.dm index 9bf9e62dfb9..3adf6b34f02 100644 --- a/code/modules/mob/living/carbon/alien/diona/diona_attacks.dm +++ b/code/modules/mob/living/carbon/alien/diona/diona_attacks.dm @@ -14,10 +14,10 @@ /mob/living/carbon/alien/diona/attackby(var/obj/item/weapon/W, var/mob/user) if(user.a_intent == "help" && istype(W, /obj/item/clothing/head)) if(hat) - user << "\The [src] is already wearing \the [hat]." + to_chat(user, "\The [src] is already wearing \the [hat].") return user.unEquip(W) wear_hat(W) user.visible_message("\The [user] puts \the [W] on \the [src].") return - return ..() \ No newline at end of file + return ..() diff --git a/code/modules/mob/living/carbon/alien/diona/life.dm b/code/modules/mob/living/carbon/alien/diona/life.dm index fecf9b12c03..aa178f93c14 100644 --- a/code/modules/mob/living/carbon/alien/diona/life.dm +++ b/code/modules/mob/living/carbon/alien/diona/life.dm @@ -14,4 +14,8 @@ adjustBruteLoss(-1) adjustFireLoss(-1) adjustToxLoss(-1) - adjustOxyLoss(-1) \ No newline at end of file + adjustOxyLoss(-1) + + + if(!client) + handle_npc(src) diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 194864b7de5..233f0f020fb 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -109,20 +109,28 @@ playsound(loc, "sparks", 50, 1, -1) if (shock_damage > 15) src.visible_message( - "[src] was shocked by \the [source]!", \ - "You feel a powerful shock course through your body!", \ - "You hear a heavy electrical crack." \ + "[src] was electrocuted[source ? " by the [source]" : ""]!", \ + "You feel a powerful shock course through your body!", \ + "You hear a heavy electrical crack." \ ) - if(stun) - Stun(10)//This should work for now, more is really silly and makes you lay there forever - Weaken(10) else src.visible_message( - "[src] was mildly shocked by \the [source].", \ - "You feel a mild shock course through your body.", \ - "You hear a light zapping." \ + "[src] was shocked[source ? " by the [source]" : ""].", \ + "You feel a shock course through your body.", \ + "You hear a zapping sound." \ ) + if(stun) + switch(shock_damage) + if(16 to 20) + Stun(2) + if(21 to 25) + Weaken(2) + if(26 to 30) + Weaken(5) + if(31 to INFINITY) + Weaken(10) //This should work for now, more is really silly and makes you lay there forever + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread s.set_up(5, 1, loc) s.start() diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm index 66ba7ecd514..08d0c9384e7 100644 --- a/code/modules/mob/living/carbon/carbon_defense.dm +++ b/code/modules/mob/living/carbon/carbon_defense.dm @@ -25,7 +25,7 @@ weapon_edge = 0 hit_embed_chance = I.force/(I.w_class*3) - apply_damage(effective_force, I.damtype, hit_zone, blocked, sharp=weapon_sharp, edge=weapon_edge, used_weapon=I) + apply_damage(effective_force, I.damtype, hit_zone, blocked, soaked, sharp=weapon_sharp, edge=weapon_edge, used_weapon=I) //Melee weapon embedded object code. if (I && I.damtype == BRUTE && !I.anchored && !is_robot_module(I) && I.embed_chance > 0) diff --git a/code/modules/mob/living/carbon/human/appearance.dm b/code/modules/mob/living/carbon/human/appearance.dm index 101390b3d63..3b83f1e8c2e 100644 --- a/code/modules/mob/living/carbon/human/appearance.dm +++ b/code/modules/mob/living/carbon/human/appearance.dm @@ -95,7 +95,7 @@ return 1 /mob/living/carbon/human/proc/change_hair_color(var/red, var/green, var/blue) - if(red == r_eyes && green == g_eyes && blue == b_eyes) + if(red == r_hair && green == g_hair && blue == b_hair) return r_hair = red diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm index ffac791a1fd..8df0bd16052 100644 --- a/code/modules/mob/living/carbon/human/death.dm +++ b/code/modules/mob/living/carbon/human/death.dm @@ -1,5 +1,15 @@ /mob/living/carbon/human/gib() + if(vr_holder) + exit_vr() + // Delete the link, because this mob won't be around much longer + vr_holder.vr_link = null + + if(vr_link) + vr_link.exit_vr() + vr_link.vr_holder = null + vr_link = null + for(var/obj/item/organ/I in internal_organs) I.removed() if(istype(loc,/turf)) @@ -80,6 +90,20 @@ if(wearing_rig) wearing_rig.notify_ai("Warning: user death event. Mobility control passed to integrated intelligence system.") + // If the body is in VR, move the mind back to the real world + if(vr_holder) + src.exit_vr() + src.vr_holder.vr_link = null + for(var/obj/item/W in src) + src.drop_from_inventory(W) + + // If our mind is in VR, bring it back to the real world so it can die with its body + if(vr_link) + vr_link.exit_vr() + vr_link.vr_holder = null + vr_link = null + to_chat(src, "Everything abruptly stops.") + return ..(gibbed,species.get_death_message(src)) /mob/living/carbon/human/proc/ChangeToHusk() @@ -113,4 +137,4 @@ mutations.Add(SKELETON) status_flags |= DISFIGURED update_body(1) - return + return \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 615a3ecf533..81ea775ab9a 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -18,17 +18,9 @@ var/skiparms = 0 var/skipfeet = 0 - - var/cloaked = 0 // 0 for normal, 1 for cloaked close - - if(mind && mind.changeling && mind.changeling.cloaked && !istype(user, /mob/observer)) - var/distance = get_dist(user, src) - if(distance > 2) - src.loc.examine(user) - return - else - cloaked = 1 - + if(alpha <= 50) + src.loc.examine(user) + return var/looks_synth = looksSynthetic() @@ -97,8 +89,6 @@ if(skipjumpsuit && skipface) //big suits/masks/helmets make it hard to tell their gender T = gender_datums[PLURAL] - if(cloaked) - T = gender_datums[NEUTER] else if(species && species.ambiguous_genders) var/can_detect_gender = FALSE @@ -458,25 +448,18 @@ msg += "Medical records: \[View\] \[Add comment\]\n" - if(print_flavor_text() && !cloaked) + if(print_flavor_text()) msg += "[print_flavor_text()]\n" msg += "*---------*
" msg += applying_pressure - if (pose && !cloaked) + if (pose) if( findtext(pose,".",lentext(pose)) == 0 && findtext(pose,"!",lentext(pose)) == 0 && findtext(pose,"?",lentext(pose)) == 0 ) pose = addtext(pose,".") //Makes sure all emotes end with a period. msg += "[T.He] [pose]" user << jointext(msg, null) - -/mob/living/carbon/human/get_description_fluff() - if(mind && mind.changeling && mind.changeling.cloaked) - return "" - else - return ..() - //Helper procedure. Called by /mob/living/carbon/human/examine() and /mob/living/carbon/human/Topic() to determine HUD access to security and medical records. /proc/hasHUD(mob/M as mob, hudtype) if(istype(M, /mob/living/carbon/human)) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index ab16e58263d..d7e7f2a169b 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -15,6 +15,8 @@ var/spit_name = null //String var/last_spit = 0 //Timestamp. + var/can_defib = 1 //Horrible damage (like beheadings) will prevent defibbing organics. + /mob/living/carbon/human/New(var/new_loc, var/new_species = null) if(!dna) @@ -36,8 +38,12 @@ nutrition = rand(200,400) hud_list[HEALTH_HUD] = new /image/hud_overlay('icons/mob/hud_med.dmi', src, "100") - hud_list[STATUS_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudhealthy") - hud_list[LIFE_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudhealthy") + if(isSynthetic()) + hud_list[STATUS_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudrobo") + hud_list[LIFE_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudrobo") + else + hud_list[STATUS_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudhealthy") + hud_list[LIFE_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudhealthy") hud_list[ID_HUD] = new /image/hud_overlay(using_map.id_hud_icons, src, "hudunknown") hud_list[WANTED_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudblank") hud_list[IMPLOYAL_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudblank") @@ -318,15 +324,13 @@ //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( mind && mind.changeling && mind.changeling.cloaked) - return "Unknown" if( wear_mask && (wear_mask.flags_inv&HIDEFACE) ) //Wearing a mask which hides our face, use id-name if possible return get_id_name("Unknown") if( head && (head.flags_inv&HIDEFACE) ) return get_id_name("Unknown") //Likewise for hats var/face_name = get_face_name() var/id_name = get_id_name("") - if(id_name && (id_name != face_name)) + if((face_name == "Unknown") && id_name && (id_name != face_name)) return "[face_name] (as [id_name])" return face_name @@ -1136,6 +1140,9 @@ if(species.default_language) add_language(species.default_language) + if(species.icon_scale != 1) + update_transform() + if(species.base_color && default_colour) //Apply colour. r_skin = hex2num(copytext(species.base_color,2,4)) @@ -1523,4 +1530,55 @@ var/turf/T = get_turf(src) var/obj/item/clothing/accessory/permit/drone/permit = new(T) permit.set_name(real_name) - equip_to_appropriate_slot(permit) // If for some reason it can't find room, it'll still be on the floor. \ No newline at end of file + equip_to_appropriate_slot(permit) // If for some reason it can't find room, it'll still be on the floor. + +// enter_vr is called on the original mob, and puts the mind into the supplied vr mob +/mob/living/carbon/human/proc/enter_vr(var/mob/living/carbon/human/avatar) // Avatar is currently a human, because we have preexisting setup code for appearance manipulation, etc. + if(!istype(avatar)) + return + + // Link the two mobs for client transfer + avatar.vr_holder = src + src.teleop = avatar + src.vr_link = avatar // Can't reuse vr_holder so that death can automatically eject users from VR + + // Move the mind + avatar.Sleeping(1) + src.mind.transfer_to(avatar) + to_chat(avatar, "You have enterred Virtual Reality!\nAll normal gameplay rules still apply.\nWounds you suffer here won't persist when you leave VR, but some of the pain will.\nYou can leave VR at any time by using the \"Exit Virtual Reality\" verb in the Abilities tab, or by ghosting.\nYou can modify your appearance by using various \"Change \[X\]\" verbs in the Abilities tab.") + to_chat(avatar, " You black out for a moment, and wake to find yourself in a new body in virtual reality.") // So this is what VR feels like? + +// exit_vr is called on the vr mob, and puts the mind back into the original mob +/mob/living/carbon/human/verb/exit_vr() + set name = "Exit Virtual Reality" + set category = "Abilities" + + if(!vr_holder) + return + if(!mind) + return + + var/total_damage + // Tally human damage + if(ishuman(src)) + var/mob/living/carbon/human/H = src + total_damage = H.getBruteLoss() + H.getFireLoss() + H.getOxyLoss() + H.getToxLoss() + + // Move the mind back to the original mob +// vr_holder.Sleeping(1) + src.mind.transfer_to(vr_holder) + to_chat(vr_holder, "You black out for a moment, and wake to find yourself back in your own body.") + // Two-thirds damage is transferred as agony for /humans + // Getting hurt in VR doesn't damage the physical body, but you still got hurt. + if(ishuman(vr_holder) && total_damage) + var/mob/living/carbon/human/V = vr_holder + V.stun_effect_act(0, total_damage*2/3, null) // 200 damage leaves the user in paincrit for several seconds, agony reaches 0 after around 2m. + to_chat(vr_holder, "Pain from your time in VR lingers.") // 250 damage leaves the user unconscious for several seconds in addition to paincrit + + // Maintain a link with the mob, but don't use teleop + vr_holder.vr_link = src + vr_holder.teleop = null + + if(istype(vr_holder.loc, /obj/machinery/vr_sleeper)) + var/obj/machinery/vr_sleeper/V = vr_holder.loc + V.go_out() diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm index 7d0b2ea7fa5..45532aa1d48 100644 --- a/code/modules/mob/living/carbon/human/human_damage.dm +++ b/code/modules/mob/living/carbon/human/human_damage.dm @@ -425,9 +425,9 @@ This function restores all organs. zone = BP_HEAD return organs_by_name[zone] -/mob/living/carbon/human/apply_damage(var/damage = 0, var/damagetype = BRUTE, var/def_zone = null, var/blocked = 0, var/sharp = 0, var/edge = 0, var/obj/used_weapon = null) +/mob/living/carbon/human/apply_damage(var/damage = 0, var/damagetype = BRUTE, var/def_zone = null, var/blocked = 0, var/soaked = 0, var/sharp = 0, var/edge = 0, var/obj/used_weapon = null) if(Debug2) - world.log << "## DEBUG: human/apply_damage() was called on [src], with [damage] damage, and an armor value of [blocked]." + world.log << "## DEBUG: human/apply_damage() was called on [src], with [damage] damage, an armor value of [blocked], and a soak value of [soaked]." var/obj/item/organ/external/organ = null if(isorgan(def_zone)) @@ -442,7 +442,7 @@ This function restores all organs. if((damage > 25 && prob(20)) || (damage > 50 && prob(60))) if(organ && organ.organ_can_feel_pain()) emote("scream") - ..(damage, damagetype, def_zone, blocked) + ..(damage, damagetype, def_zone, blocked, soaked) return 1 //Handle BRUTE and BURN damage @@ -451,12 +451,18 @@ This function restores all organs. if(blocked >= 100) return 0 + if(soaked >= damage) + return 0 if(!organ) return 0 if(blocked) blocked = (100-blocked)/100 damage = (damage * blocked) + + if(soaked) + damage -= soaked + if(Debug2) world.log << "## DEBUG: [src] was hit for [damage]." diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index a09dad7dba3..fbb98c3f984 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -29,7 +29,6 @@ var/g_synth //Same as above var/b_synth //Same as above - var/size_multiplier = 1 //multiplier for the mob's icon size var/damage_multiplier = 1 //multiplies melee combat damage var/icon_update = 1 //whether icon updating shall take place @@ -103,3 +102,8 @@ var/step_count = 0 // Track how many footsteps have been taken to know when to play footstep sounds can_be_antagged = TRUE + +// Used by mobs in virtual reality to point back to the "real" mob the client belongs to. + var/mob/living/carbon/human/vr_holder = null + // Used by "real" mobs after they leave a VR session + var/mob/living/carbon/human/vr_link = null \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index bf43aadf6a0..684978e07de 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -1582,7 +1582,9 @@ if (BITTEST(hud_updateflag, LIFE_HUD)) var/image/holder = hud_list[LIFE_HUD] - if(stat == DEAD) + if(isSynthetic()) + holder.icon_state = "hudrobo" + else if(stat == DEAD) holder.icon_state = "huddead" else holder.icon_state = "hudhealthy" @@ -1597,7 +1599,9 @@ var/image/holder = hud_list[STATUS_HUD] var/image/holder2 = hud_list[STATUS_HUD_OOC] - if(stat == DEAD) + if (isSynthetic()) + holder.icon_state = "hudrobo" + else if(stat == DEAD) holder.icon_state = "huddead" holder2.icon_state = "huddead" else if(foundVirus) diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm index bb5d989e45a..61bded2e159 100644 --- a/code/modules/mob/living/carbon/human/species/species.dm +++ b/code/modules/mob/living/carbon/human/species/species.dm @@ -30,6 +30,8 @@ var/tail_animation // If set, the icon to obtain tail animation states from. var/tail_hair + var/icon_scale = 1 // Makes the icon larger/smaller. + var/race_key = 0 // Used for mob icon cache string. var/icon/icon_template // Used for mob icon generation for non-32x32 species. var/mob_size = MOB_MEDIUM @@ -275,11 +277,14 @@ var/t_him = "them" if(ishuman(target)) var/mob/living/carbon/human/T = target - switch(T.identifying_gender) - if(MALE) - t_him = "him" - if(FEMALE) - t_him = "her" + if(!T.species.ambiguous_genders || (T.species.ambiguous_genders && H.species == T.species)) + switch(T.identifying_gender) + if(MALE) + t_him = "him" + if(FEMALE) + t_him = "her" + else + t_him = "them" else switch(target.gender) if(MALE) diff --git a/code/modules/mob/living/carbon/human/species/species_shapeshift.dm b/code/modules/mob/living/carbon/human/species/species_shapeshift.dm index 1fb7b6c3009..f1f36322a23 100644 --- a/code/modules/mob/living/carbon/human/species/species_shapeshift.dm +++ b/code/modules/mob/living/carbon/human/species/species_shapeshift.dm @@ -148,9 +148,16 @@ var/list/wrapped_species_by_ref = list() last_special = world.time + 50 - var/new_species = input("Please select a species to emulate.", "Shapeshifter Body") as null|anything in species.get_valid_shapeshifter_forms(src) + var/new_species = null + new_species = input("Please select a species to emulate.", "Shapeshifter Body") as null|anything in species.get_valid_shapeshifter_forms(src) + if(!new_species || !all_species[new_species] || wrapped_species_by_ref["\ref[src]"] == new_species) return + shapeshifter_change_shape(new_species) + +/mob/living/carbon/human/proc/shapeshifter_change_shape(var/new_species = null) + if(!new_species) + return wrapped_species_by_ref["\ref[src]"] = new_species visible_message("\The [src] shifts and contorts, taking the form of \a [new_species]!") @@ -190,3 +197,30 @@ var/list/wrapped_species_by_ref = list() E.sync_colour_to_human(src) regenerate_icons() + +/mob/living/carbon/human/proc/shapeshifter_select_hair_colors() + + set name = "Select Hair Colors" + set category = "Abilities" + + if(stat || world.time < last_special) + return + + last_special = world.time + 50 + + var/new_hair = input("Please select a new hair color.", "Hair Colour") as color + if(!new_hair) + return + shapeshifter_set_hair_color(new_hair) + var/new_fhair = input("Please select a new facial hair color.", "Facial Hair Color") as color + if(!new_fhair) + return + shapeshifter_set_facial_color(new_fhair) + +/mob/living/carbon/human/proc/shapeshifter_set_hair_color(var/new_hair) + + change_hair_color(hex2num(copytext(new_hair, 2, 4)), hex2num(copytext(new_hair, 4, 6)), hex2num(copytext(new_hair, 6, 8))) + +/mob/living/carbon/human/proc/shapeshifter_set_facial_color(var/new_fhair) + + change_facial_hair_color(hex2num(copytext(new_fhair, 2, 4)), hex2num(copytext(new_fhair, 4, 6)), hex2num(copytext(new_fhair, 6, 8))) \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/species/station/prometheans.dm b/code/modules/mob/living/carbon/human/species/station/prometheans.dm index 5ab786f8f6f..7d1ed3bb0e8 100644 --- a/code/modules/mob/living/carbon/human/species/station/prometheans.dm +++ b/code/modules/mob/living/carbon/human/species/station/prometheans.dm @@ -81,12 +81,12 @@ var/datum/species/shapeshifter/promethean/prometheans /mob/living/carbon/human/proc/shapeshifter_select_shape, /mob/living/carbon/human/proc/shapeshifter_select_colour, /mob/living/carbon/human/proc/shapeshifter_select_hair, + /mob/living/carbon/human/proc/shapeshifter_select_hair_colors, /mob/living/carbon/human/proc/shapeshifter_select_gender, /mob/living/carbon/human/proc/regenerate ) - valid_transform_species = list("Human", "Unathi", "Tajara", "Skrell", "Diona", "Teshari", "Monkey") - monochromatic = 1 + valid_transform_species = list("Human", "Vatborn", "Unathi", "Tajara", "Skrell", "Diona", "Teshari", "Monkey") var/heal_rate = 0.5 // Temp. Regen per tick. diff --git a/code/modules/mob/living/carbon/human/species/station/station.dm b/code/modules/mob/living/carbon/human/species/station/station.dm index f07ff9b1197..372451808e2 100644 --- a/code/modules/mob/living/carbon/human/species/station/station.dm +++ b/code/modules/mob/living/carbon/human/species/station/station.dm @@ -39,6 +39,8 @@ burn_mod = 0.85 metabolic_rate = 0.85 item_slowdown_mod = 0.5 + mob_size = MOB_LARGE + blood_volume = 840 num_alternate_languages = 3 secondary_langs = list(LANGUAGE_UNATHI) name_language = LANGUAGE_UNATHI diff --git a/code/modules/mob/living/carbon/human/species/virtual_reality/avatar.dm b/code/modules/mob/living/carbon/human/species/virtual_reality/avatar.dm new file mode 100644 index 00000000000..8fbf47022d4 --- /dev/null +++ b/code/modules/mob/living/carbon/human/species/virtual_reality/avatar.dm @@ -0,0 +1,32 @@ +// ### Wooo, inheritance. Basically copying everything I don't need to edit from prometheans, because they mostly work already. +// ### Any and all of this is open to change for balance or whatever. +// ### +// ### +// Species definition follows. +/datum/species/shapeshifter/promethean/avatar + + name = "Virtual Reality Avatar" + name_plural = "Virtual Reality Avatars" + blurb = "A 3-dimensional representation of some sort of animate object used to display the presence and actions of some-one or -thing using a virtual reality program." + show_ssd = "eerily still" + death_message = "flickers briefly, their gear falling in a heap on the floor around their motionless body." + knockout_message = "has been knocked unconscious!" + + spawn_flags = SPECIES_IS_RESTRICTED + + speech_bubble_appearance = "cyber" + + male_cough_sounds = list('sound/effects/mob_effects/m_cougha.ogg','sound/effects/mob_effects/m_coughb.ogg', 'sound/effects/mob_effects/m_coughc.ogg') + female_cough_sounds = list('sound/effects/mob_effects/f_cougha.ogg','sound/effects/mob_effects/f_coughb.ogg') + male_sneeze_sound = 'sound/effects/mob_effects/sneeze.ogg' + female_sneeze_sound = 'sound/effects/mob_effects/f_sneeze.ogg' + + unarmed_types = list(/datum/unarmed_attack/stomp, /datum/unarmed_attack/kick, /datum/unarmed_attack/punch, /datum/unarmed_attack/bite) + has_organ = list(O_BRAIN = /obj/item/organ/internal/brain/slime, O_EYES = /obj/item/organ/internal/eyes) // Slime core. + heal_rate = 0 // Avatars don't naturally heal like prometheans, at least not for now + +/datum/species/shapeshifter/promethean/avatar/handle_death(var/mob/living/carbon/human/H) + return + +/datum/species/shapeshifter/promethean/avatar/handle_environment_special(var/mob/living/carbon/human/H) + return \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 0909ed25755..ebaa6866e01 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -159,16 +159,29 @@ Please contact me on #coderbus IRC. ~Carn x for(var/inner_entry in entry) overlays += inner_entry + update_transform() + +/mob/living/carbon/human/update_transform() + // First, get the correct size. + var/desired_scale = icon_scale + + desired_scale *= species.icon_scale + + for(var/datum/modifier/M in modifiers) + if(!isnull(M.icon_scale_percent)) + desired_scale *= M.icon_scale_percent + + // Regular stuff again. if(lying && !species.prone_icon) //Only rotate them if we're not drawing a specific icon for being prone. var/matrix/M = matrix() M.Turn(90) - M.Scale(size_multiplier) + M.Scale(desired_scale) M.Translate(1,-6) src.transform = M else var/matrix/M = matrix() - M.Scale(size_multiplier) - M.Translate(0, 16*(size_multiplier-1)) + M.Scale(desired_scale) + M.Translate(0, 16*(desired_scale-1)) src.transform = M var/global/list/damage_icon_parts = list() @@ -293,6 +306,8 @@ var/global/list/damage_icon_parts = list() base_icon = chest.get_icon() for(var/obj/item/organ/external/part in organs) + if(isnull(part) || part.is_stump()) + continue var/icon/temp = part.get_icon(skeleton) //That part makes left and right legs drawn topmost and lowermost when human looks WEST or EAST //And no change in rendering for other parts (they icon_position is 0, so goes to 'else' part) @@ -381,11 +396,13 @@ var/global/list/damage_icon_parts = list() face_standing.Blend(facial_s, ICON_OVERLAY) if(h_style && !(head && (head.flags_inv & BLOCKHEADHAIR))) - var/datum/sprite_accessory/hair_style = hair_styles_list[h_style] + var/datum/sprite_accessory/hair/hair_style = hair_styles_list[h_style] if(hair_style && (src.species.get_bodytype(src) in hair_style.species_allowed)) var/icon/hair_s = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s") + var/icon/hair_s_add = new/icon("icon" = hair_style.icon_add, "icon_state" = "[hair_style.icon_state]_s") if(hair_style.do_colouration) - hair_s.Blend(rgb(r_hair, g_hair, b_hair), ICON_ADD) + hair_s.Blend(rgb(r_hair, g_hair, b_hair), ICON_MULTIPLY) + hair_s.Blend(hair_s_add, ICON_ADD) face_standing.Blend(hair_s, ICON_OVERLAY) @@ -503,7 +520,16 @@ var/global/list/damage_icon_parts = list() //need to append _s to the icon state for legacy compatibility var/image/standing = image(icon = under_icon, icon_state = "[under_state]_s") - standing.color = w_uniform.color + + if(w_uniform.addblends) + var/icon/base = new/icon("icon" = standing.icon, "icon_state" = standing.icon_state) + var/addblend_icon = new/icon("icon" = standing.icon, "icon_state" = w_uniform.addblends) + if(w_uniform.color) + base.Blend(w_uniform.color, ICON_MULTIPLY) + base.Blend(addblend_icon, ICON_ADD) + standing = image(base) + else + standing.color = w_uniform.color //apply blood overlay if(w_uniform.blood_DNA) @@ -567,7 +593,15 @@ var/global/list/damage_icon_parts = list() bloodsies.color = gloves.blood_color standing.overlays += bloodsies gloves.screen_loc = ui_gloves - standing.color = gloves.color + if(gloves.addblends) + var/icon/base = new/icon("icon" = standing.icon, "icon_state" = standing.icon_state) + var/addblend_icon = new/icon("icon" = standing.icon, "icon_state" = gloves.addblends) + if(gloves.color) + base.Blend(gloves.color, ICON_MULTIPLY) + base.Blend(addblend_icon, ICON_ADD) + standing = image(base) + else + standing.color = gloves.color overlays_standing[GLOVES_LAYER] = standing else if(blood_DNA) @@ -588,7 +622,15 @@ var/global/list/damage_icon_parts = list() standing = image("icon" = glasses.sprite_sheets[species.get_bodytype(src)], "icon_state" = "[glasses.icon_state]") else standing = image("icon" = 'icons/mob/eyes.dmi', "icon_state" = "[glasses.icon_state]") - standing.color = glasses.color + if(glasses.addblends) + var/icon/base = new/icon("icon" = standing.icon, "icon_state" = standing.icon_state) + var/addblend_icon = new/icon("icon" = standing.icon, "icon_state" = glasses.addblends) + if(glasses.color) + base.Blend(glasses.color, ICON_MULTIPLY) + base.Blend(addblend_icon, ICON_ADD) + standing = image(base) + else + standing.color = glasses.color overlays_standing[GLASSES_LAYER] = standing else @@ -616,7 +658,15 @@ var/global/list/damage_icon_parts = list() standing = image("icon" = l_ear.sprite_sheets[species.get_bodytype(src)], "icon_state" = "[t_type]") else standing = image("icon" = 'icons/mob/ears.dmi', "icon_state" = "[t_type]") - standing.color = l_ear.color + if(l_ear.addblends) + var/icon/base = new/icon("icon" = standing.icon, "icon_state" = standing.icon_state) + var/addblend_icon = new/icon("icon" = standing.icon, "icon_state" = l_ear.addblends) + if(l_ear.color) + base.Blend(l_ear.color, ICON_MULTIPLY) + base.Blend(addblend_icon, ICON_ADD) + standing = image(base) + else + standing.color = l_ear.color both.overlays += standing if(r_ear) @@ -630,7 +680,15 @@ var/global/list/damage_icon_parts = list() standing = image("icon" = r_ear.sprite_sheets[species.get_bodytype(src)], "icon_state" = "[t_type]") else standing = image("icon" = 'icons/mob/ears.dmi', "icon_state" = "[t_type]") - standing.color = r_ear.color + if(r_ear.addblends) + var/icon/base = new/icon("icon" = standing.icon, "icon_state" = standing.icon_state) + var/addblend_icon = new/icon("icon" = standing.icon, "icon_state" = r_ear.addblends) + if(r_ear.color) + base.Blend(r_ear.color, ICON_MULTIPLY) + base.Blend(addblend_icon, ICON_ADD) + standing = image(base) + else + standing.color = r_ear.color both.overlays += standing overlays_standing[EARS_LAYER] = both @@ -664,8 +722,18 @@ var/global/list/damage_icon_parts = list() var/image/bloodsies = image("icon" = species.get_blood_mask(src), "icon_state" = "shoeblood") bloodsies.color = shoes.blood_color standing.overlays += bloodsies - standing.color = shoes.color + + if(shoes.addblends) + var/icon/base = new/icon("icon" = standing.icon, "icon_state" = standing.icon_state) + var/addblend_icon = new/icon("icon" = standing.icon, "icon_state" = shoes.addblends) + if(shoes.color) + base.Blend(shoes.color, ICON_MULTIPLY) + base.Blend(addblend_icon, ICON_ADD) + standing = image(base) + else + standing.color = shoes.color overlays_standing[shoe_layer] = standing + else if(feet_blood_DNA) var/image/bloodsies = image("icon" = species.get_blood_mask(src), "icon_state" = "shoeblood") @@ -731,7 +799,15 @@ var/global/list/damage_icon_parts = list() if(hat.on && light_overlay_cache[cache_key]) standing.overlays |= light_overlay_cache[cache_key] - standing.color = head.color + if(head.addblends) + var/icon/base = new/icon("icon" = standing.icon, "icon_state" = standing.icon_state) + var/addblend_icon = new/icon("icon" = standing.icon, "icon_state" = head.addblends) + if(head.color) + base.Blend(head.color, ICON_MULTIPLY) + base.Blend(addblend_icon, ICON_ADD) + standing = image(base) + else + standing.color = head.color overlays_standing[HEAD_LAYER] = standing else @@ -766,7 +842,15 @@ var/global/list/damage_icon_parts = list() if(!i_state) i_state = i.icon_state standing.overlays += image("icon" = 'icons/mob/belt.dmi', "icon_state" = "[i_state]") - standing.color = belt.color + if(belt.addblends) + var/icon/base = new/icon("icon" = standing.icon, "icon_state" = standing.icon_state) + var/addblend_icon = new/icon("icon" = standing.icon, "icon_state" = belt.addblends) + if(belt.color) + base.Blend(belt.color, ICON_MULTIPLY) + base.Blend(addblend_icon, ICON_ADD) + standing = image(base) + else + standing.color = belt.color overlays_standing[belt_layer] = standing else @@ -791,7 +875,16 @@ var/global/list/damage_icon_parts = list() t_icon = wear_suit.item_icons[slot_wear_suit_str] standing = image("icon" = t_icon, "icon_state" = "[wear_suit.icon_state]") - standing.color = wear_suit.color + + if(wear_suit.addblends) + var/icon/base = new/icon("icon" = standing.icon, "icon_state" = standing.icon_state) + var/addblend_icon = new/icon("icon" = standing.icon, "icon_state" = wear_suit.addblends) + if(wear_suit.color) + base.Blend(wear_suit.color, ICON_MULTIPLY) + base.Blend(addblend_icon, ICON_ADD) + standing = image(base) + else + standing.color = wear_suit.color if( istype(wear_suit, /obj/item/clothing/suit/straight_jacket) ) drop_from_inventory(handcuffed) @@ -841,7 +934,15 @@ var/global/list/damage_icon_parts = list() standing = image("icon" = wear_mask.sprite_sheets[species.get_bodytype(src)], "icon_state" = "[wear_mask.icon_state]") else standing = image("icon" = 'icons/mob/mask.dmi', "icon_state" = "[wear_mask.icon_state]") - standing.color = wear_mask.color + if(wear_mask.addblends) + var/icon/base = new/icon("icon" = standing.icon, "icon_state" = standing.icon_state) + var/addblend_icon = new/icon("icon" = standing.icon, "icon_state" = wear_mask.addblends) + if(wear_mask.color) + base.Blend(wear_mask.color, ICON_MULTIPLY) + base.Blend(addblend_icon, ICON_ADD) + standing = image(base) + else + standing.color = wear_mask.color if( !istype(wear_mask, /obj/item/clothing/mask/smokable/cigarette) && wear_mask.blood_DNA ) var/image/bloodsies = image("icon" = species.get_blood_mask(src), "icon_state" = "maskblood") @@ -883,7 +984,15 @@ var/global/list/damage_icon_parts = list() //apply color var/image/standing = image(icon = overlay_icon, icon_state = overlay_state) - standing.color = back.color + if(back.addblends) + var/icon/base = new/icon("icon" = standing.icon, "icon_state" = standing.icon_state) + var/addblend_icon = new/icon("icon" = standing.icon, "icon_state" = back.addblends) + if(back.color) + base.Blend(back.color, ICON_MULTIPLY) + base.Blend(addblend_icon, ICON_ADD) + standing = image(base) + else + standing.color = back.color //create the image overlays_standing[BACK_LAYER] = standing diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm index 22289c6b438..07997851ef3 100644 --- a/code/modules/mob/living/damage_procs.dm +++ b/code/modules/mob/living/damage_procs.dm @@ -34,6 +34,8 @@ adjustCloneLoss(damage * blocked) if(HALLOSS) adjustHalLoss(damage * blocked) + if(ELECTROCUTE) + electrocute_act(damage, used_weapon, 1.0, def_zone) flash_weak_pain() updatehealth() return 1 diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 5b2800b1305..01bb5244317 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -1002,3 +1002,17 @@ default behaviour is: // Called by job_controller. /mob/living/proc/equip_post_job() return + + +/mob/living/update_transform() + // First, get the correct size. + var/desired_scale = icon_scale + for(var/datum/modifier/M in modifiers) + if(!isnull(M.icon_scale_percent)) + desired_scale *= M.icon_scale_percent + + // Now for the regular stuff. + var/matrix/M = matrix() + M.Scale(desired_scale) + M.Translate(0, 16*(desired_scale-1)) + src.transform = M \ No newline at end of file diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index ad3a41fbc86..b48a1609d9e 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -17,10 +17,6 @@ var/list/ai_verbs_default = list( /mob/living/silicon/ai/proc/show_laws_verb, /mob/living/silicon/ai/proc/toggle_acceleration, /mob/living/silicon/ai/proc/toggle_hologram_movement, - /mob/living/silicon/ai/proc/toggle_hidden_verbs, -) - -var/list/ai_verbs_hidden = list( // For why this exists, refer to https://xkcd.com/1172/, /mob/living/silicon/ai/proc/ai_announcement, /mob/living/silicon/ai/proc/ai_call_shuttle, /mob/living/silicon/ai/proc/ai_camera_track, @@ -160,6 +156,7 @@ var/list/ai_verbs_hidden = list( // For why this exists, refer to https://xkcd.c add_language(LANGUAGE_EAL, 1) add_language(LANGUAGE_SCHECHI, 1) add_language(LANGUAGE_SIGN, 1) + add_language(LANGUAGE_ROOTLOCAL, 1) if(!safety)//Only used by AIize() to successfully spawn an AI. if (!B)//If there is no player/brain inside. @@ -794,16 +791,5 @@ var/list/ai_verbs_hidden = list( // For why this exists, refer to https://xkcd.c if(rig) rig.force_rest(src) -/mob/living/silicon/ai/proc/toggle_hidden_verbs() - set name = "Toggle Hidden Verbs" - set category = "AI Settings" - - if(/mob/living/silicon/ai/proc/ai_announcement in verbs) - src << "Extra verbs toggled off." - verbs -= ai_verbs_hidden - else - src << "Extra verbs toggled on." - verbs |= ai_verbs_hidden - #undef AI_CHECK_WIRELESS #undef AI_CHECK_RADIO diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm index 29e3e86caf2..1e0d9888358 100644 --- a/code/modules/mob/living/silicon/pai/pai.dm +++ b/code/modules/mob/living/silicon/pai/pai.dm @@ -430,7 +430,7 @@ user << "You add the access from the [W] to [src]." return if("Remove Access") - idcard.access = null + idcard.access = list() user << "You remove the access from [src]." return if("Cancel") @@ -442,7 +442,7 @@ /mob/living/silicon/pai/verb/allowmodification() set name = "Change Access Modifcation Permission" set category = "pAI Commands" - desc = "Allows people to modify your access or block people from modifying your access." + set desc = "Allows people to modify your access or block people from modifying your access." if(idaccessible == 0) idaccessible = 1 diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index f516486f026..6c3cd7f1dbd 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -9,7 +9,7 @@ health = 200 mob_bump_flag = ROBOT - mob_swap_flags = ROBOT|MONKEY|SLIME|SIMPLE_ANIMAL + mob_swap_flags = ~HEAVY mob_push_flags = ~HEAVY //trundle trundle var/lights_on = 0 // Is our integrated light on? @@ -394,6 +394,11 @@ C.toggled = 1 src << "You enable [C.name]." +/mob/living/silicon/robot/verb/spark_plug() //So you can still sparkle on demand without violence. + set category = "Robot Commands" + set name = "Emit Sparks" + spark_system.start() + // 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 @@ -637,7 +642,8 @@ else if( !(istype(W, /obj/item/device/robotanalyzer) || istype(W, /obj/item/device/healthanalyzer)) ) - spark_system.start() + if(W.force > 0) + spark_system.start() return ..() /mob/living/silicon/robot/attack_hand(mob/user) diff --git a/code/modules/mob/living/simple_animal/animals/giant_spider.dm b/code/modules/mob/living/simple_animal/animals/giant_spider.dm index 1ff56059469..cc655908e9b 100644 --- a/code/modules/mob/living/simple_animal/animals/giant_spider.dm +++ b/code/modules/mob/living/simple_animal/animals/giant_spider.dm @@ -55,6 +55,10 @@ /mob/living/simple_animal/hostile/giant_spider/proc/remove_eyes() overlays -= eye_layer +/* +Nurse Family +*/ + //nursemaids - these create webs and eggs /mob/living/simple_animal/hostile/giant_spider/nurse desc = "Furry and beige, it makes you shudder to look at it. This one has brilliant green eyes." @@ -95,7 +99,105 @@ old_x = -16 old_y = -16 +/mob/living/simple_animal/hostile/giant_spider/webslinger + desc = "Furry and green, it makes you shudder to look at it. This one has brilliant green eyes, and a cloak of web." + icon_state = "webslinger" + icon_living = "webslinger" + icon_dead = "webslinger_dead" + + maxHealth = 90 + health = 90 + + projectilesound = 'sound/weapons/thudswoosh.ogg' + projectiletype = /obj/item/projectile/bola + ranged = 1 + firing_lines = 1 + cooperative = 1 + shoot_range = 5 + + melee_damage_lower = 5 + melee_damage_upper = 10 + poison_per_bite = 2 + poison_type = "psilocybin" + + spattack_prob = 15 + spattack_min_range = 0 + spattack_max_range = 5 + +/mob/living/simple_animal/hostile/giant_spider/webslinger/AttackTarget() //One day. + var/mob/living/carbon/human/victim = null //Webslinger needs to know if its target is human later. + if(ishuman(target_mob)) + victim = target_mob + if(!victim.legcuffed) + projectiletype = /obj/item/projectile/bola + shoot_range = 7 + else + projectiletype = /obj/item/projectile/webball + shoot_range = 5 + else + projectiletype = /obj/item/projectile/webball + shoot_range = 5 + return ..() + +/mob/living/simple_animal/hostile/giant_spider/carrier + desc = "Furry, beige, and red, it makes you shudder to look at it. This one has luminous green eyes." + icon_state = "carrier" + icon_living = "carrier" + icon_dead = "carrier_dead" + + maxHealth = 100 + health = 100 + + melee_damage_lower = 5 + melee_damage_upper = 20 + + poison_per_bite = 3 + poison_type = "chloralhydrate" + + var/spiderling_count = 0 + var/spiderling_type = /obj/effect/spider/spiderling + var/swarmling_type = /mob/living/simple_animal/hostile/giant_spider/hunter + var/swarmling_faction = "spiders" + +/mob/living/simple_animal/hostile/giant_spider/carrier/New() + spiderling_count = rand(5,10) + adjust_scale(1.2) + ..() + +/mob/living/simple_animal/hostile/giant_spider/carrier/death() + visible_message("\The [src]'s abdomen splits as it rolls over, spiderlings crawling from the wound.") + spawn(1) + for(var/I = 1 to spiderling_count) + if(prob(10) && src) + var/mob/living/simple_animal/hostile/giant_spider/swarmling = new swarmling_type(src.loc) + var/swarm_health = Floor(swarmling.maxHealth * 0.4) + var/swarm_dam_lower = Floor(melee_damage_lower * 0.4) + var/swarm_dam_upper = Floor(melee_damage_upper * 0.4) + swarmling.name = "spiderling" + swarmling.maxHealth = swarm_health + swarmling.health = swarm_health + swarmling.melee_damage_lower = swarm_dam_lower + swarmling.melee_damage_upper = swarm_dam_upper + swarmling.faction = swarmling_faction + swarmling.adjust_scale(0.75) + else if(src) + var/obj/effect/spider/spiderling/child = new spiderling_type(src.loc) + child.skitter() + else + break + return ..() + +/mob/living/simple_animal/hostile/giant_spider/carrier/recursive + desc = "Furry, beige, and red, it makes you shudder to look at it. This one has luminous green eyes. You have a distinctly bad feeling about this." + + swarmling_type = /mob/living/simple_animal/hostile/giant_spider/carrier/recursive + +/* +Hunter Family +*/ + //hunters have the most poison and move the fastest, so they can find prey + /mob/living/simple_animal/hostile/giant_spider/hunter desc = "Furry and black, it makes you shudder to look at it. This one has sparkling purple eyes." icon_state = "hunter" @@ -111,6 +213,150 @@ poison_per_bite = 5 +/mob/living/simple_animal/hostile/giant_spider/lurker + desc = "Translucent and white, it makes you shudder to look at it. This one has incandescent red eyes." + icon_state = "lurker" + icon_living = "lurker" + icon_dead = "lurker_dead" + alpha = 45 + + maxHealth = 100 + health = 100 + move_to_delay = 4 + + melee_damage_lower = 5 + melee_damage_upper = 20 + + + poison_chance = 20 + poison_type = "cryptobiolin" + poison_per_bite = 2 + +/mob/living/simple_animal/hostile/giant_spider/lurker/death() + alpha = 255 + return ..() + +/mob/living/simple_animal/hostile/giant_spider/tunneler + desc = "Sandy and brown, it makes you shudder to look at it. This one has glittering yellow eyes." + icon_state = "tunneler" + icon_living = "tunneler" + icon_dead = "tunneler_dead" + + maxHealth = 120 + health = 120 + move_to_delay = 4 + + melee_damage_lower = 10 + melee_damage_upper = 20 + + poison_chance = 15 + poison_per_bite = 3 + poison_type = "serotrotium_v" + +/mob/living/simple_animal/hostile/giant_spider/tunneler/death() + spawn(1) + for(var/I = 1 to rand(3,6)) + if(src) + new/obj/item/weapon/ore/glass(src.loc) + else + break + return ..() + +/* +Guard Family +*/ + +/mob/living/simple_animal/hostile/giant_spider/pepper + desc = "Red and brown, it makes you shudder to look at it. This one has glinting red eyes." + icon_state = "pepper" + icon_living = "pepper" + icon_dead = "pepper_dead" + + maxHealth = 210 + health = 210 + + melee_damage_lower = 5 + melee_damage_upper = 10 + + poison_chance = 20 + poison_per_bite = 5 + poison_type = "condensedcapsaicin_v" + +/mob/living/simple_animal/hostile/giant_spider/pepper/New() + adjust_scale(1.1) + ..() + +/mob/living/simple_animal/hostile/giant_spider/thermic + desc = "Mirage-cloaked and orange, it makes you shudder to look at it. This one has simmering orange eyes." + icon_state = "pit" + icon_living = "pit" + icon_dead = "pit_dead" + + maxHealth = 175 + health = 175 + + melee_damage_lower = 5 + melee_damage_upper = 15 + + poison_chance = 30 + poison_per_bite = 1 + poison_type = "thermite_v" + +/mob/living/simple_animal/hostile/giant_spider/electric + desc = "Spined and yellow, it makes you shudder to look at it. This one has flickering gold eyes." + icon_state = "spark" + icon_living = "spark" + icon_dead = "spark_dead" + + maxHealth = 210 + health = 210 + taser_kill = 0 //It -is- the taser. + + melee_damage_lower = 5 + melee_damage_upper = 10 + + ranged = 1 + projectilesound = 'sound/weapons/taser2.ogg' + projectiletype = /obj/item/projectile/beam/stun/weak + firing_lines = 1 + cooperative = 1 + + poison_chance = 15 + poison_per_bite = 3 + poison_type = "stimm" + +/mob/living/simple_animal/hostile/giant_spider/phorogenic + desc = "Crystalline and purple, it makes you shudder to look at it. This one has haunting purple eyes." + icon_state = "phoron" + icon_living = "phoron" + icon_dead = "phoron_dead" + + maxHealth = 225 + health = 225 + taser_kill = 0 //You will need more than a peashooter to kill the juggernaut. + + melee_damage_lower = 10 + melee_damage_upper = 20 + + poison_chance = 30 + poison_per_bite = 0.5 + poison_type = "phoron" + + var/exploded = 0 + +/mob/living/simple_animal/hostile/giant_spider/phorogenic/New() + adjust_scale(1.25) + return ..() + +/mob/living/simple_animal/hostile/giant_spider/phorogenic/death() + visible_message("\The [src]'s body begins to rupture!") + spawn(rand(1,5)) + if(src && !exploded) + visible_message("\The [src]'s body detonates!") + exploded = 1 + explosion(src.loc, 1, 2, 4, 6) + return ..() + /mob/living/simple_animal/hostile/giant_spider/frost desc = "Icy and blue, it makes you shudder to look at it. This one has brilliant blue eyes." icon_state = "frost" @@ -126,6 +372,9 @@ poison_per_bite = 5 poison_type = "cryotoxin" +/* +Spider Procs +*/ /mob/living/simple_animal/hostile/giant_spider/New(var/location, var/atom/parent) get_light_and_color(parent) @@ -167,6 +416,16 @@ O.implants += eggs to_chat(H, "\The [src] injects something into your [O.name]!") +/mob/living/simple_animal/hostile/giant_spider/webslinger/DoPunch(var/atom/A) + . = ..() + if(.) // If we succeeded in hitting. + if(isliving(A)) + var/mob/living/L = A + var/obj/effect/spider/stickyweb/W = locate() in get_turf(L) + if(!W && prob(75)) + visible_message("\The [src] throws a layer of web at \the [L]!") + new /obj/effect/spider/stickyweb(L.loc) + /mob/living/simple_animal/hostile/giant_spider/handle_stance() . = ..() if(ai_inactive) return diff --git a/code/modules/mob/living/simple_animal/animals/mouse.dm b/code/modules/mob/living/simple_animal/animals/mouse.dm index 1b8f439f50c..87df9015277 100644 --- a/code/modules/mob/living/simple_animal/animals/mouse.dm +++ b/code/modules/mob/living/simple_animal/animals/mouse.dm @@ -79,7 +79,7 @@ icon_living = "mouse_[body_color]" icon_dead = "mouse_[body_color]_dead" icon_rest = "mouse_[body_color]_sleep" - desc = "It's a small [body_color] rodent, often seen hiding in maintenance areas and making a nuisance of itself." + desc = "A small [body_color] rodent, often seen hiding in maintenance areas and making a nuisance of itself." /mob/living/simple_animal/mouse/proc/splat() src.health = 0 @@ -95,13 +95,13 @@ if( ishuman(AM) ) if(!stat) var/mob/M = AM - M << "\icon[src] Squeek!" + M.visible_message("\icon[src] Squeek!") M << 'sound/effects/mouse_squeak.ogg' ..() /mob/living/simple_animal/mouse/death() layer = MOB_LAYER - playsound(src, 'sound/effects/mouse_squeak_loud.ogg', 50, 1) + playsound(src, 'sound/effects/mouse_squeak_loud.ogg', 35, 1) if(client) client.time_died_as_mouse = world.time ..() diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 32a5a9cb35d..231db2866a8 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -90,6 +90,7 @@ var/assist_distance = 25 // Radius in which I'll ask my comrades for help. var/supernatural = 0 // If the mob is supernatural (used in null-rod stuff for banishing?) var/grab_resist = 75 // Chance of me resisting a grab attempt. + var/taser_kill = 1 // Is the mob weak to tasers //Attack ranged settings var/ranged = 0 // Do I attack at range? @@ -107,7 +108,9 @@ var/friendly = "nuzzles" // What mobs do to people when they aren't really hostile var/attack_sound = null // Sound to play when I attack var/environment_smash = 0 // How much environment damage do I do when I hit stuff? - var/melee_miss_chance = 25 // percent chance to miss a melee attack. + var/melee_miss_chance = 15 // percent chance to miss a melee attack. + var/melee_attack_minDelay = 5 // How long between attacks at least + var/melee_attack_maxDelay = 10 // How long between attacks at most //Special attacks var/spattack_prob = 0 // Chance of the mob doing a special attack (0 for never) @@ -501,7 +504,10 @@ stun_effect_act(0, Proj.agony) if(!Proj.nodamage) - adjustBruteLoss(Proj.damage) + var/true_damage = Proj.damage + if(!Proj.SA_vulnerability || Proj.SA_vulnerability == intelligence_level) + true_damage += Proj.SA_bonus_damage + adjustBruteLoss(true_damage) if(Proj.firer) react_to_attack(Proj.firer) @@ -1168,7 +1174,7 @@ if(!Adjacent(target_mob)) return if(!client) - sleep(rand(8) + 8) + sleep(rand(melee_attack_minDelay, melee_attack_maxDelay)) if(isliving(target_mob)) var/mob/living/L = target_mob @@ -1437,16 +1443,30 @@ //Shot with taser/stunvolver /mob/living/simple_animal/stun_effect_act(var/stun_amount, var/agony_amount, var/def_zone, var/used_weapon=null) - var/stunDam = 0 - var/agonyDam = 0 + if(taser_kill) + var/stunDam = 0 + var/agonyDam = 0 - if(stun_amount) - stunDam += stun_amount * 0.5 - adjustFireLoss(stunDam) + if(stun_amount) + stunDam += stun_amount * 0.5 + adjustFireLoss(stunDam) - if(agony_amount) - agonyDam += agony_amount * 0.5 - adjustFireLoss(agonyDam) + if(agony_amount) + agonyDam += agony_amount * 0.5 + adjustFireLoss(agonyDam) + +/mob/living/simple_animal/emp_act(severity) + if(!isSynthetic()) + return + switch(severity) + if(1) + adjustFireLoss(rand(15, 25)) + if(2) + adjustFireLoss(rand(10, 18)) + if(3) + adjustFireLoss(rand(5, 12)) + if(4) + adjustFireLoss(rand(1, 6)) // Force it to target something /mob/living/simple_animal/proc/taunt(var/mob/living/new_target, var/forced = FALSE) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 92a8b3bdebc..6063526c897 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -534,6 +534,7 @@ if(M != usr) return if(usr == src) return if(!Adjacent(usr)) return + if(usr.incapacitated(INCAPACITATION_STUNNED | INCAPACITATION_FORCELYING | INCAPACITATION_KNOCKOUT | INCAPACITATION_RESTRAINED)) return //Incapacitated. if(istype(M,/mob/living/silicon/ai)) return show_inv(usr) diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 56104d34f44..b7fdd7714de 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -400,7 +400,7 @@ proc/is_blind(A) return // Can't talk in deadchat if you can't see it. for(var/mob/M in player_list) - if(M.client && ((!istype(M, /mob/new_player) && M.stat == DEAD) || (M.client.holder && !is_eventM(M.client))) && M.is_preference_enabled(/datum/client_preference/show_dsay)) + if(M.client && (!istype(M, /mob/new_player) && M.stat == DEAD) && M.is_preference_enabled(/datum/client_preference/show_dsay)) var/follow var/lname if(M.forbid_seeing_deadchat && !M.client.holder) diff --git a/code/modules/mob/new_player/preferences_setup.dm b/code/modules/mob/new_player/preferences_setup.dm index 5fa306b7b96..a96524f1f1b 100644 --- a/code/modules/mob/new_player/preferences_setup.dm +++ b/code/modules/mob/new_player/preferences_setup.dm @@ -258,7 +258,7 @@ mannequin.delete_inventory(TRUE) dress_preview_mob(mannequin) - preview_icon = icon('icons/effects/effects.dmi', "nothing") + preview_icon = icon('icons/effects/128x48.dmi', bgstate) preview_icon.Scale(48+32, 16+32) mannequin.dir = NORTH diff --git a/code/modules/mob/new_player/sprite_accessories.dm b/code/modules/mob/new_player/sprite_accessories.dm index 42bc1280e27..4b729f0a706 100644 --- a/code/modules/mob/new_player/sprite_accessories.dm +++ b/code/modules/mob/new_player/sprite_accessories.dm @@ -45,7 +45,8 @@ /datum/sprite_accessory/hair - icon = 'icons/mob/Human_face.dmi' // default icon for all hairs + icon = 'icons/mob/Human_face_m.dmi' // default icon for all hairs + var/icon_add = 'icons/mob/human_face.dmi' bald name = "Bald" @@ -323,7 +324,7 @@ name = "Overeye Long" icon_state = "hair_longovereye" - fag + flowhair name = "Flow Hair" icon_state = "hair_f" diff --git a/code/modules/organs/internal/appendix.dm b/code/modules/organs/internal/appendix.dm index f756b71efa4..01d7008a096 100644 --- a/code/modules/organs/internal/appendix.dm +++ b/code/modules/organs/internal/appendix.dm @@ -18,6 +18,8 @@ return 0 /obj/item/organ/internal/appendix/process() + ..() + if(!inflamed || !owner) return diff --git a/code/modules/organs/internal/brain.dm b/code/modules/organs/internal/brain.dm index 28fbf62f1ea..7dd2bd948ef 100644 --- a/code/modules/organs/internal/brain.dm +++ b/code/modules/organs/internal/brain.dm @@ -44,21 +44,6 @@ tmp_owner.internal_organs_by_name[organ_tag] = new replace_path(tmp_owner, 1) tmp_owner = null -/obj/item/organ/internal/pariah_brain - name = "brain remnants" - desc = "Did someone tread on this? It looks useless for cloning or cyborgification." - organ_tag = "brain" - parent_organ = BP_HEAD - icon = 'icons/mob/alien.dmi' - icon_state = "chitin" - vital = 1 - -/obj/item/organ/internal/brain/xeno - name = "thinkpan" - desc = "It looks kind of like an enormous wad of purple bubblegum." - icon = 'icons/mob/alien.dmi' - icon_state = "chitin" - /obj/item/organ/internal/brain/New() ..() health = config.default_brain_health @@ -127,6 +112,21 @@ target.key = brainmob.key ..() +/obj/item/organ/internal/pariah_brain + name = "brain remnants" + desc = "Did someone tread on this? It looks useless for cloning or cyborgification." + organ_tag = "brain" + parent_organ = BP_HEAD + icon = 'icons/mob/alien.dmi' + icon_state = "chitin" + vital = 1 + +/obj/item/organ/internal/brain/xeno + name = "thinkpan" + desc = "It looks kind of like an enormous wad of purple bubblegum." + icon = 'icons/mob/alien.dmi' + icon_state = "chitin" + /obj/item/organ/internal/brain/slime name = "slime core" desc = "A complex, organic knot of jelly and crystalline particles." diff --git a/code/modules/organs/internal/kidneys.dm b/code/modules/organs/internal/kidneys.dm index a547a2539fe..19652a6376d 100644 --- a/code/modules/organs/internal/kidneys.dm +++ b/code/modules/organs/internal/kidneys.dm @@ -9,6 +9,7 @@ /obj/item/organ/internal/kidneys/process() ..() + if(!owner) return // Coffee is really bad for you with busted kidneys. diff --git a/code/modules/organs/internal/organ_internal.dm b/code/modules/organs/internal/organ_internal.dm index a3fdc511fc4..43b3a4c4d7f 100644 --- a/code/modules/organs/internal/organ_internal.dm +++ b/code/modules/organs/internal/organ_internal.dm @@ -58,5 +58,7 @@ if (prob(3)) take_damage(1,silent=prob(30)) - //if(. >= 3 && antibiotics < 30) //INFECTION_LEVEL_THREE, others are handled on each specific organ - //Nothing that generic internal organs do for this + if(. >= 3 && antibiotics < 30) //INFECTION_LEVEL_THREE + if (prob(50)) + take_damage(1,silent=prob(15)) + diff --git a/code/modules/organs/organ.dm b/code/modules/organs/organ.dm index 915258e1125..77706b95176 100644 --- a/code/modules/organs/organ.dm +++ b/code/modules/organs/organ.dm @@ -91,6 +91,9 @@ var/list/organ_cache = list() if(owner && vital) owner.death() +/obj/item/organ/proc/adjust_germ_level(var/amount) // Unless you're setting germ level directly to 0, use this proc instead + germ_level = Clamp(germ_level + amount, 0, INFECTION_LEVEL_MAX) + /obj/item/organ/process() if(loc != owner) @@ -117,9 +120,9 @@ var/list/organ_cache = list() if(config.organs_decay) damage += rand(1,3) if(damage >= max_damage) damage = max_damage - germ_level += rand(2,6) + adjust_germ_level(rand(2,6)) if(germ_level >= INFECTION_LEVEL_TWO) - germ_level += rand(2,6) + adjust_germ_level(rand(2,6)) if(germ_level >= INFECTION_LEVEL_THREE) die() @@ -158,12 +161,12 @@ var/list/organ_cache = list() owner.adjustToxLoss(infection_damage) if (germ_level > 0 && germ_level < INFECTION_LEVEL_ONE/2 && prob(30)) - germ_level-- + adjust_germ_level(-1) if (germ_level >= INFECTION_LEVEL_ONE/2) //aiming for germ level to go from ambient to INFECTION_LEVEL_TWO in an average of 15 minutes if(antibiotics < 5 && prob(round(germ_level/6))) - germ_level++ + adjust_germ_level(1) if(germ_level >= INFECTION_LEVEL_ONE) . = 1 //Organ qualifies for effect-specific processing @@ -179,7 +182,7 @@ var/list/organ_cache = list() if (germ_level >= INFECTION_LEVEL_THREE && antibiotics < 30) . = 3 //Organ qualifies for effect-specific processing - germ_level++ //Germ_level increases without overdose of antibiotics + adjust_germ_level(rand(5,10)) //Germ_level increases without overdose of antibiotics /obj/item/organ/proc/handle_rejection() // Process unsuitable transplants. TODO: consider some kind of @@ -193,13 +196,13 @@ var/list/organ_cache = list() if(rejecting % 10 == 0) //Only fire every ten rejection ticks. switch(rejecting) if(1 to 50) - germ_level++ + adjust_germ_level(1) if(51 to 200) - germ_level += rand(1,2) + adjust_germ_level(rand(1,2)) if(201 to 500) - germ_level += rand(2,3) + adjust_germ_level(rand(2,3)) if(501 to INFINITY) - germ_level += rand(3,5) + adjust_germ_level(rand(3,5)) owner.reagents.add_reagent("toxin", rand(1,2)) /obj/item/organ/proc/receive_chem(chemical as obj) @@ -238,9 +241,11 @@ var/list/organ_cache = list() if (germ_level < INFECTION_LEVEL_ONE) germ_level = 0 //cure instantly else if (germ_level < INFECTION_LEVEL_TWO) - germ_level -= 6 //at germ_level == 500, this should cure the infection in a minute + adjust_germ_level(-6) //at germ_level < 500, this should cure the infection in a minute + else if (germ_level < INFECTION_LEVEL_THREE) + adjust_germ_level(-2) //at germ_level < 1000, this will cure the infection in 5 minutes else - germ_level -= 2 //at germ_level == 1000, this will cure the infection in 5 minutes + adjust_germ_level(-1) // You waited this long to get treated, you don't really deserve this organ //Adds autopsy data for used_weapon. /obj/item/organ/proc/add_autopsy_data(var/used_weapon, var/damage) diff --git a/code/modules/organs/organ_icon.dm b/code/modules/organs/organ_icon.dm index 48759ae1cff..3c986b16fd8 100644 --- a/code/modules/organs/organ_icon.dm +++ b/code/modules/organs/organ_icon.dm @@ -71,7 +71,7 @@ var/global/list/limb_icon_cache = list() overlays |= lip_icon mob_icon.Blend(lip_icon, ICON_OVERLAY) - //Head markings, duplicated (sadly) below. + //Head markings. for(var/M in markings) var/datum/sprite_accessory/marking/mark_style = markings[M]["datum"] var/icon/mark_s = new/icon("icon" = mark_style.icon, "icon_state" = "[mark_style.icon_state]-[organ_tag]") @@ -89,11 +89,13 @@ var/global/list/limb_icon_cache = list() overlays |= facial_s if(owner.h_style && !(owner.head && (owner.head.flags_inv & BLOCKHEADHAIR))) - var/datum/sprite_accessory/hair_style = hair_styles_list[owner.h_style] + var/datum/sprite_accessory/hair/hair_style = hair_styles_list[owner.h_style] if(hair_style && (species.get_bodytype(owner) in hair_style.species_allowed)) var/icon/hair_s = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s") + var/icon/hair_s_add = new/icon("icon" = hair_style.icon_add, "icon_state" = "[hair_style.icon_state]_s") if(hair_style.do_colouration && islist(h_col) && h_col.len >= 3) - hair_s.Blend(rgb(h_col[1], h_col[2], h_col[3]), ICON_ADD) + hair_s.Blend(rgb(h_col[1], h_col[2], h_col[3]), ICON_MULTIPLY) + hair_s.Blend(hair_s_add, ICON_ADD) overlays |= hair_s return mob_icon @@ -130,14 +132,15 @@ var/global/list/limb_icon_cache = list() mob_icon = new /icon(species.get_icobase(owner, (status & ORGAN_MUTATED)), "[icon_name][gender ? "_[gender]" : ""]") apply_colouration(mob_icon) - //Body markings, does not include head, duplicated (sadly) above. - for(var/M in markings) - var/datum/sprite_accessory/marking/mark_style = markings[M]["datum"] - var/icon/mark_s = new/icon("icon" = mark_style.icon, "icon_state" = "[mark_style.icon_state]-[organ_tag]") - mark_s.Blend(markings[M]["color"], ICON_ADD) - overlays |= mark_s //So when it's not on your body, it has icons - mob_icon.Blend(mark_s, ICON_OVERLAY) //So when it's on your body, it has icons - icon_cache_key += "[M][markings[M]["color"]]" + //Body markings, actually does not include head this time. Done separately above. + if(!istype(src,/obj/item/organ/external/head)) + for(var/M in markings) + var/datum/sprite_accessory/marking/mark_style = markings[M]["datum"] + var/icon/mark_s = new/icon("icon" = mark_style.icon, "icon_state" = "[mark_style.icon_state]-[organ_tag]") + mark_s.Blend(markings[M]["color"], ICON_ADD) + overlays |= mark_s //So when it's not on your body, it has icons + mob_icon.Blend(mark_s, ICON_OVERLAY) //So when it's on your body, it has icons + icon_cache_key += "[M][markings[M]["color"]]" if(body_hair && islist(h_col) && h_col.len >= 3) var/cache_key = "[body_hair]-[icon_name]-[h_col[1]][h_col[2]][h_col[3]]" diff --git a/code/modules/organs/subtypes/standard.dm b/code/modules/organs/subtypes/standard.dm index 90567f23635..d1eb81cc7f7 100644 --- a/code/modules/organs/subtypes/standard.dm +++ b/code/modules/organs/subtypes/standard.dm @@ -279,6 +279,8 @@ spawn(1) owner.update_hair() get_icon() + if(vital) //This is just in case we ever add something that both a) Doesn't need a head to live, and b) Can be defibbed + owner.can_defib = 0 ..() /obj/item/organ/external/head/take_damage(brute, burn, sharp, edge, used_weapon = null, list/forbidden_limbs = list()) diff --git a/code/modules/overmap/ships/computers/shuttle.dm b/code/modules/overmap/ships/computers/shuttle.dm index 5199b3e3eb0..05d1a6d8c6f 100644 --- a/code/modules/overmap/ships/computers/shuttle.dm +++ b/code/modules/overmap/ships/computers/shuttle.dm @@ -19,7 +19,7 @@ shuttle.area_offsite = shuttle.area_station shuttle_controller.shuttles[shuttle_tag] = shuttle shuttle_controller.process_shuttles += shuttle - testing("Exploration shuttle '[shuttle_tag]' at zlevel [z] successfully added.") + testing("Exploration shuttle '[shuttle_tag]' at z-level [z] successfully added.") //Sets destination to new sector. Can be null. /obj/machinery/computer/shuttle_control/explore/proc/update_destination(var/obj/effect/map/D) @@ -84,7 +84,7 @@ else shuttle_status = "Standing-by at offsite location." if(WAIT_LAUNCH, FORCE_LAUNCH) - shuttle_status = "Shuttle has recieved command and will depart shortly." + shuttle_status = "Shuttle has received command and will depart shortly." if(WAIT_ARRIVE) shuttle_status = "Proceeding to destination." if(WAIT_FINISH) diff --git a/code/modules/paperwork/adminpaper.dm b/code/modules/paperwork/adminpaper.dm index b17bdf29f28..6ed6ad93fc9 100644 --- a/code/modules/paperwork/adminpaper.dm +++ b/code/modules/paperwork/adminpaper.dm @@ -58,7 +58,7 @@ text = "
" text += "This transmission is intended only for the addressee and may contain confidential information. Any unauthorized disclosure is strictly prohibited.

" - text += "If this transmission is recieved in error, please notify both the sender and the office of [using_map.boss_name] Internal Affairs immediately so that corrective action may be taken." + text += "If this transmission is received in error, please notify both the sender and the office of [using_map.boss_name] Internal Affairs immediately so that corrective action may be taken." text += "Failure to comply is a breach of regulation and may be prosecuted to the fullest extent of the law, where applicable." text += "
" diff --git a/code/modules/paperwork/faxmachine.dm b/code/modules/paperwork/faxmachine.dm index 778abc4ee05..92076c0b150 100644 --- a/code/modules/paperwork/faxmachine.dm +++ b/code/modules/paperwork/faxmachine.dm @@ -80,7 +80,7 @@ var/list/adminfaxes = list() //cache for faxes that have been sent to admins if(copyitem) copyitem.loc = usr.loc usr.put_in_hands(copyitem) - usr << "You take \the [copyitem] out of \the [src]." + to_chat(usr, "You take \the [copyitem] out of \the [src].") copyitem = null if(href_list["scan"]) @@ -124,7 +124,7 @@ var/list/adminfaxes = list() //cache for faxes that have been sent to admins var/success = 0 for(var/obj/machinery/photocopier/faxmachine/F in allfaxes) if( F.department == destination ) - success = F.recievefax(copyitem) + success = F.receivefax(copyitem) if (success) visible_message("[src] beeps, \"Message transmitted successfully.\"") @@ -132,7 +132,7 @@ var/list/adminfaxes = list() //cache for faxes that have been sent to admins else visible_message("[src] beeps, \"Error transmitting message.\"") -/obj/machinery/photocopier/faxmachine/proc/recievefax(var/obj/item/incoming) +/obj/machinery/photocopier/faxmachine/proc/receivefax(var/obj/item/incoming) if(stat & (BROKEN|NOPOWER)) return 0 @@ -164,7 +164,7 @@ var/list/adminfaxes = list() //cache for faxes that have been sent to admins use_power(200) - //recieved copies should not use toner since it's being used by admins only. + //received copies should not use toner since it's being used by admins only. var/obj/item/rcvdcopy if (istype(copyitem, /obj/item/weapon/paper)) rcvdcopy = copy(copyitem, 0) diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index 0af97704348..bdea8fed709 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -35,6 +35,24 @@ var/const/signfont = "Times New Roman" var/const/crayonfont = "Comic Sans MS" +/obj/item/weapon/paper/alien + name = "alien tablet" + desc = "It looks highly advanced" + icon = 'icons/obj/abductor.dmi' + icon_state = "alienpaper" + +/obj/item/weapon/paper/alien/update_icon() + if(info) + icon_state = "alienpaper_words" + else + icon_state = "alienpaper" + +/obj/item/weapon/paper/alien/burnpaper() + return + +/obj/item/weapon/paper/alien/AltClick() // No airplanes for me. + return + //lipstick wiping is in code/game/objects/items/weapons/cosmetics.dm! /obj/item/weapon/paper/New() diff --git a/code/modules/paperwork/pen.dm b/code/modules/paperwork/pen.dm index 990c97b1c2b..1de92fe7430 100644 --- a/code/modules/paperwork/pen.dm +++ b/code/modules/paperwork/pen.dm @@ -119,8 +119,8 @@ /obj/item/weapon/pen/reagent/paralysis/New() ..() - reagents.add_reagent("zombiepowder", 10) - reagents.add_reagent("cryptobiolin", 15) + reagents.add_reagent("zombiepowder", 5) + reagents.add_reagent("cryptobiolin", 10) /* * Chameleon pen diff --git a/code/modules/planet/sif.dm b/code/modules/planet/sif.dm index dcb6d140ec0..1e84126fe74 100644 --- a/code/modules/planet/sif.dm +++ b/code/modules/planet/sif.dm @@ -195,8 +195,8 @@ datum/weather/sif /datum/weather/sif/blizzard name = "blizzard" icon_state = "snowfall_heavy" - temp_high = 233.15 // -40c - temp_low = 213.15 // -60c + temp_high = 243.15 // -30c + temp_low = 233.15 // -40c light_modifier = 0.3 flight_falure_modifier = 10 transition_chances = list( @@ -241,7 +241,7 @@ datum/weather/sif name = "storm" icon_state = "storm" temp_high = 243.15 // -30c - temp_low = 233.15 // -50c + temp_low = 233.15 // -40c light_modifier = 0.3 flight_falure_modifier = 10 transition_chances = list( diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index eb142aac1e0..39ce99d1881 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -681,13 +681,10 @@ else flick("apc-spark", src) if (do_after(user,6)) - if(prob(50)) - emagged = 1 - locked = 0 - to_chat(user,"You emag the APC interface.") - update_icon() - else - to_chat(user,"The APC interface refused to unlock.") + emagged = 1 + locked = 0 + to_chat(user,"You emag the APC interface.") + update_icon() return 1 /obj/machinery/power/apc/attack_hand(mob/user) diff --git a/code/modules/power/cell.dm b/code/modules/power/cell.dm index 2c1699c5f60..7a8c7c541fb 100644 --- a/code/modules/power/cell.dm +++ b/code/modules/power/cell.dm @@ -2,6 +2,28 @@ // charge from 0 to 100% // fits in APC to provide backup power +/obj/item/weapon/cell + name = "power cell" + desc = "A rechargable electrochemical power cell." + icon = 'icons/obj/power.dmi' + icon_state = "cell" + item_state = "cell" + origin_tech = list(TECH_POWER = 1) + force = 5.0 + throwforce = 5.0 + throw_speed = 3 + throw_range = 5 + w_class = ITEMSIZE_NORMAL + var/charge = 0 // note %age conveted to actual charge in New + var/maxcharge = 1000 + var/rigged = 0 // true if rigged to explode + var/minor_fault = 0 //If not 100% reliable, it will build up faults. + var/self_recharge = FALSE // If true, the cell will recharge itself. + var/charge_amount = 25 // How much power to give, if self_recharge is true. The number is in absolute cell charge, as it gets divided by CELLRATE later. + var/last_use = 0 // A tracker for use in self-charging + var/charge_delay = 0 // How long it takes for the cell to start recharging after last use + matter = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 50) + /obj/item/weapon/cell/New() ..() charge = maxcharge @@ -16,7 +38,8 @@ /obj/item/weapon/cell/process() if(self_recharge) - give(charge_amount) + if(world.time >= last_use + charge_delay) + give(charge_amount) else return PROCESS_KILL @@ -59,6 +82,7 @@ return 0 var/used = min(charge, amount) charge -= used + last_use = world.time update_icon() return used @@ -80,6 +104,8 @@ var/amount_used = min(maxcharge-charge,amount) charge += amount_used update_icon() + if(loc) + loc.update_icon() return amount_used @@ -112,7 +138,6 @@ S.reagents.clear_reagents() - /obj/item/weapon/cell/proc/explode() var/turf/T = get_turf(src.loc) /* @@ -207,3 +232,7 @@ return min(rand(10,20),rand(10,20)) else return 0 + +/obj/item/weapon/cell/suicide_act(mob/user) + viewers(user) << "\The [user] is licking the electrodes of \the [src]! It looks like \he's trying to commit suicide." + return (FIRELOSS) \ No newline at end of file diff --git a/code/modules/power/cells/device_cells.dm b/code/modules/power/cells/device_cells.dm new file mode 100644 index 00000000000..822370a6b14 --- /dev/null +++ b/code/modules/power/cells/device_cells.dm @@ -0,0 +1,50 @@ +//currently only used by energy-type guns, that may change in the future. +/obj/item/weapon/cell/device + name = "device power cell" + desc = "A small power cell designed to power handheld devices." + icon_state = "dcell" + item_state = "egg6" + w_class = ITEMSIZE_SMALL + force = 0 + throw_speed = 5 + throw_range = 7 + maxcharge = 480 + charge_amount = 5 + matter = list("metal" = 350, "glass" = 50) + preserve_item = 1 + +/obj/item/weapon/cell/device/weapon + name = "weapon power cell" + desc = "A small power cell designed to power handheld weaponry." + icon_state = "wcell" + maxcharge = 2400 + charge_amount = 20 + +/obj/item/weapon/cell/device/weapon/empty/initialize() + ..() + charge = 0 + update_icon() + +/obj/item/weapon/cell/device/weapon/recharge + name = "self-charging weapon power cell" + desc = "A small power cell designed to power handheld weaponry. This one recharges itself." +// icon_state = "wcell" //TODO: Different sprite + self_recharge = TRUE + charge_amount = 120 + charge_delay = 75 + +/obj/item/weapon/cell/device/weapon/recharge/captain + charge_amount = 160 //Recharges a lot more quickly... + charge_delay = 100 //... but it takes a while to get started + +/obj/item/weapon/cell/device/weapon/recharge/alien + name = "void cell" + desc = "An alien technology that produces energy seemingly out of nowhere. Its small, cylinderal shape means it might be able to be used with human technology, perhaps?" + icon = 'icons/obj/abductor.dmi' + icon_state = "cell" + charge_amount = 120 // 5%. + charge_delay = 50 // Every five seconds, bit faster than the default. + origin_tech = list(TECH_POWER = 8, TECH_ENGINEERING = 6) + +/obj/item/weapon/cell/device/weapon/recharge/alien/update_icon() + return // No overlays please. \ No newline at end of file diff --git a/code/game/objects/items/weapons/power_cells.dm b/code/modules/power/cells/power_cells.dm similarity index 59% rename from code/game/objects/items/weapons/power_cells.dm rename to code/modules/power/cells/power_cells.dm index 2b63fb79bd7..a9b92a9bb3d 100644 --- a/code/game/objects/items/weapons/power_cells.dm +++ b/code/modules/power/cells/power_cells.dm @@ -1,137 +1,93 @@ -/obj/item/weapon/cell - name = "power cell" - desc = "A rechargable electrochemical power cell." - icon = 'icons/obj/power.dmi' - icon_state = "cell" - item_state = "cell" - origin_tech = list(TECH_POWER = 1) - force = 5.0 - throwforce = 5.0 - throw_speed = 3 - throw_range = 5 - w_class = ITEMSIZE_NORMAL - var/charge = 0 // note %age conveted to actual charge in New - var/maxcharge = 1000 - var/rigged = 0 // true if rigged to explode - var/minor_fault = 0 //If not 100% reliable, it will build up faults. - var/self_recharge = FALSE // If true, the cell will recharge itself. - var/charge_amount = 25 // How much power to give, if self_recharge is true. The number is in absolute cell charge, as it gets divided by CELLRATE later. - matter = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 50) - - suicide_act(mob/user) - viewers(user) << "\The [user] is licking the electrodes of \the [src]! It looks like \he's trying to commit suicide." - return (FIRELOSS) - -//currently only used by energy-type guns, that may change in the future. -/obj/item/weapon/cell/device - name = "device power cell" - desc = "A small power cell designed to power handheld devices." - icon_state = "dcell" - item_state = "egg6" - w_class = ITEMSIZE_SMALL - force = 0 - throw_speed = 5 - throw_range = 7 - maxcharge = 480 - matter = list("metal" = 350, "glass" = 50) - preserve_item = 1 - -/obj/item/weapon/cell/device/weapon - name = "weapon power cell" - desc = "A small power cell designed to power handheld weaponry." - icon_state = "wcell" - maxcharge = 2400 - -/obj/item/weapon/cell/crap - name = "\improper rechargable AA battery" - desc = "You can't top the plasma top." //TOTALLY TRADEMARK INFRINGEMENT - origin_tech = list(TECH_POWER = 0) - maxcharge = 500 - matter = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 40) - -/obj/item/weapon/cell/crap/empty/New() - ..() - charge = 0 - -/obj/item/weapon/cell/secborg - name = "security borg rechargable D battery" - origin_tech = list(TECH_POWER = 0) - maxcharge = 600 //600 max charge / 100 charge per shot = six shots - matter = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 40) - -/obj/item/weapon/cell/secborg/empty/New() - ..() - charge = 0 - -/obj/item/weapon/cell/apc - name = "heavy-duty power cell" - origin_tech = list(TECH_POWER = 1) - maxcharge = 5000 - matter = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 50) - -/obj/item/weapon/cell/high - name = "high-capacity power cell" - origin_tech = list(TECH_POWER = 2) - icon_state = "hcell" - maxcharge = 10000 - matter = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 60) - -/obj/item/weapon/cell/high/empty/New() - ..() - charge = 0 - -/obj/item/weapon/cell/super - name = "super-capacity power cell" - origin_tech = list(TECH_POWER = 5) - icon_state = "scell" - maxcharge = 20000 - matter = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 70) - -/obj/item/weapon/cell/super/empty/New() - ..() - charge = 0 - -/obj/item/weapon/cell/hyper - name = "hyper-capacity power cell" - origin_tech = list(TECH_POWER = 6) - icon_state = "hpcell" - maxcharge = 30000 - matter = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 80) - -/obj/item/weapon/cell/hyper/empty/New() - ..() - charge = 0 - -/obj/item/weapon/cell/infinite - name = "infinite-capacity power cell!" - icon_state = "icell" - origin_tech = null - maxcharge = 30000 //determines how badly mobs get shocked - matter = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 80) - - check_charge() - return 1 - use() - return 1 - -/obj/item/weapon/cell/potato - name = "potato battery" - desc = "A rechargable starch based power cell." - origin_tech = list(TECH_POWER = 1) - icon = 'icons/obj/power.dmi' //'icons/obj/harvest.dmi' - icon_state = "potato_cell" //"potato_battery" - charge = 100 - maxcharge = 300 - minor_fault = 1 - - -/obj/item/weapon/cell/slime - name = "charged slime core" - desc = "A yellow slime core infused with phoron, it crackles with power." - origin_tech = list(TECH_POWER = 4, TECH_BIO = 5) - icon = 'icons/mob/slimes.dmi' //'icons/obj/harvest.dmi' - icon_state = "yellow slime extract" //"potato_battery" - description_info = "This 'cell' holds a max charge of 10k and self recharges over time." - maxcharge = 10000 - matter = null - self_recharge = TRUE +/obj/item/weapon/cell/crap + name = "\improper rechargable AA battery" + desc = "You can't top the plasma top." //TOTALLY TRADEMARK INFRINGEMENT + origin_tech = list(TECH_POWER = 0) + maxcharge = 500 + matter = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 40) + +/obj/item/weapon/cell/crap/empty/New() + ..() + charge = 0 + +/obj/item/weapon/cell/secborg + name = "security borg rechargable D battery" + origin_tech = list(TECH_POWER = 0) + maxcharge = 600 //600 max charge / 100 charge per shot = six shots + matter = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 40) + +/obj/item/weapon/cell/secborg/empty/New() + ..() + charge = 0 + +/obj/item/weapon/cell/apc + name = "heavy-duty power cell" + origin_tech = list(TECH_POWER = 1) + maxcharge = 5000 + matter = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 50) + +/obj/item/weapon/cell/high + name = "high-capacity power cell" + origin_tech = list(TECH_POWER = 2) + icon_state = "hcell" + maxcharge = 10000 + matter = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 60) + +/obj/item/weapon/cell/high/empty/New() + ..() + charge = 0 + +/obj/item/weapon/cell/super + name = "super-capacity power cell" + origin_tech = list(TECH_POWER = 5) + icon_state = "scell" + maxcharge = 20000 + matter = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 70) + +/obj/item/weapon/cell/super/empty/New() + ..() + charge = 0 + +/obj/item/weapon/cell/hyper + name = "hyper-capacity power cell" + origin_tech = list(TECH_POWER = 6) + icon_state = "hpcell" + maxcharge = 30000 + matter = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 80) + +/obj/item/weapon/cell/hyper/empty/New() + ..() + charge = 0 + +/obj/item/weapon/cell/infinite + name = "infinite-capacity power cell!" + icon_state = "icell" + origin_tech = null + maxcharge = 30000 //determines how badly mobs get shocked + matter = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 80) + +/obj/item/weapon/cell/infinite/check_charge() + return 1 + +/obj/item/weapon/cell/infinite/use() + return 1 + +/obj/item/weapon/cell/potato + name = "potato battery" + desc = "A rechargable starch based power cell." + origin_tech = list(TECH_POWER = 1) + icon = 'icons/obj/power.dmi' //'icons/obj/harvest.dmi' + icon_state = "potato_cell" //"potato_battery" + charge = 100 + maxcharge = 300 + minor_fault = 1 + +/obj/item/weapon/cell/slime + name = "charged slime core" + desc = "A yellow slime core infused with phoron, it crackles with power." + origin_tech = list(TECH_POWER = 4, TECH_BIO = 5) + icon = 'icons/mob/slimes.dmi' //'icons/obj/harvest.dmi' + icon_state = "yellow slime extract" //"potato_battery" + description_info = "This 'cell' holds a max charge of 10k and self recharges over time." + maxcharge = 10000 + matter = null + self_recharge = TRUE diff --git a/code/modules/power/grid_checker.dm b/code/modules/power/grid_checker.dm index b8a123e02fa..8127383651c 100644 --- a/code/modules/power/grid_checker.dm +++ b/code/modules/power/grid_checker.dm @@ -4,6 +4,8 @@ than the alternative." icon_state = "gridchecker_on" circuit = /obj/item/weapon/circuitboard/grid_checker + density = 1 + anchored = 1 var/power_failing = FALSE // Turns to TRUE when the grid check event is fired by the Game Master, or perhaps a cheeky antag. // Wire stuff below. var/datum/wires/grid_checker/wires diff --git a/code/modules/projectiles/ammunition/magazines.dm b/code/modules/projectiles/ammunition/magazines.dm index 342e10db840..9af8597c9ba 100644 --- a/code/modules/projectiles/ammunition/magazines.dm +++ b/code/modules/projectiles/ammunition/magazines.dm @@ -159,6 +159,34 @@ name = "ammo clip (.45 flash)" ammo_type = /obj/item/ammo_casing/a45f +/obj/item/ammo_magazine/s45 + name = "speedloader (.45)" + icon_state = "45s" + ammo_type = /obj/item/ammo_casing/a45 + matter = list(DEFAULT_WALL_MATERIAL = 525) //metal costs are very roughly based around 1 .45 casing = 75 metal + caliber = ".45" + max_ammo = 7 + multiple_sprites = 1 + +/obj/item/ammo_magazine/s45/empty + initial_ammo = 0 + +/obj/item/ammo_magazine/s45/rubber + name = "speedloader (.45 rubber)" + ammo_type = /obj/item/ammo_casing/a45r + +/obj/item/ammo_magazine/s45/practice + name = "speedloader (.45 practice)" + ammo_type = /obj/item/ammo_casing/a45p + +/obj/item/ammo_magazine/s45/flash + name = "speedloader (.45 flash)" + ammo_type = /obj/item/ammo_casing/a45f + +/obj/item/ammo_magazine/s45/ap + name = "speedloader (.45 AP)" + ammo_type = /obj/item/ammo_casing/a45ap + ///////// 9mm ///////// /obj/item/ammo_magazine/m9mm @@ -328,6 +356,14 @@ name = "extended magazine (5.45mm armor-piercing)" max_ammo = 30 +/obj/item/ammo_magazine/m545/hunter + name = "magazine (5.45mm hunting)" + ammo_type = /obj/item/ammo_casing/a545/hunter + +/obj/item/ammo_magazine/m545/hunter/ext + name = "extended magazine (5.45mm hunting)" + max_ammo = 30 + /obj/item/ammo_magazine/m545/small name = "reduced magazine (5.45mm)" icon_state = "m545-small" @@ -345,6 +381,10 @@ name = "magazine (5.45mm armor-piercing)" ammo_type = /obj/item/ammo_casing/a545/ap +/obj/item/ammo_magazine/m545/small/hunter + name = "magazine (5.45mm hunting)" + ammo_type = /obj/item/ammo_casing/a545/hunter + /obj/item/ammo_magazine/clip/c545 name = "ammo clip (5.45mm)" icon_state = "clip_rifle" @@ -358,6 +398,10 @@ name = "rifle clip (5.45mm armor-piercing)" ammo_type = /obj/item/ammo_casing/a545/ap +/obj/item/ammo_magazine/clip/c545/hunter + name = "rifle clip (5.45mm hunting)" + ammo_type = /obj/item/ammo_casing/a545/hunter + /obj/item/ammo_magazine/clip/c545/practice name = "rifle clip (5.45mm practice)" ammo_type = /obj/item/ammo_casing/a545 @@ -378,6 +422,10 @@ name = "magazine box (5.45mm armor-piercing)" ammo_type = /obj/item/ammo_casing/a545/ap +/obj/item/ammo_magazine/m545saw/hunter + name = "magazine box (5.45mm hunting)" + ammo_type = /obj/item/ammo_casing/a545/hunter + /obj/item/ammo_magazine/m545saw/empty initial_ammo = 0 @@ -477,6 +525,10 @@ name = "rifle clip (7.62mm practice)" ammo_type = /obj/item/ammo_casing/a762p +/obj/item/ammo_magazine/clip/c762/hunter + name = "rifle clip (7.62mm hunting)" + ammo_type = /obj/item/ammo_casing/a762/hunter + /obj/item/ammo_magazine/m762svd name = "\improper SVD magazine (7.62mm)" icon_state = "SVD" @@ -523,12 +575,12 @@ /obj/item/ammo_magazine/clip/c12g name = "ammo clip (12g slug)" - icon_state = "12gclipslug" //largely a codersprite, looks good enough. feel free to make a better one. + icon_state = "12gclipslug" // Still a placeholder sprite. Feel free to make a better one. desc = "A color-coded metal clip for holding and quickly loading shotgun shells. This one is loaded with slugs." caliber = "12g" ammo_type = /obj/item/ammo_casing/a12g - matter = list(DEFAULT_WALL_MATERIAL = 1790) // slugs shells x4 + 350 metal for the clip itself. - max_ammo = 4 + matter = list(DEFAULT_WALL_MATERIAL = 1070) // slugs shells x2 + 350 metal for the clip itself. + max_ammo = 2 multiple_sprites = 1 /obj/item/ammo_magazine/clip/c12g/pellet @@ -536,14 +588,14 @@ icon_state = "12gclipshell" desc = "A color-coded metal clip for holding and quickly loading shotgun shells. This one is loaded with buckshot." ammo_type = /obj/item/ammo_casing/a12g/pellet - matter = list(DEFAULT_WALL_MATERIAL = 1790) // buckshot and slugs cost the same + matter = list(DEFAULT_WALL_MATERIAL = 1070) // buckshot and slugs cost the same /obj/item/ammo_magazine/clip/c12g/beanbag name = "ammo clip (12g beanbag)" icon_state = "12gclipbean" desc = "A color-coded metal clip for holding and quickly loading shotgun shells. This one is loaded with beanbags." ammo_type = /obj/item/ammo_casing/a12g/beanbag - matter = list(DEFAULT_WALL_MATERIAL = 1070) //beanbags x4 + 350 metal + matter = list(DEFAULT_WALL_MATERIAL = 710) //beanbags x2 + 350 metal ///////// .75 Gyrojet ///////// diff --git a/code/modules/projectiles/ammunition/rounds.dm b/code/modules/projectiles/ammunition/rounds.dm index ed06df7cc26..330e11d89b2 100644 --- a/code/modules/projectiles/ammunition/rounds.dm +++ b/code/modules/projectiles/ammunition/rounds.dm @@ -258,6 +258,10 @@ desc = "A 7.62mm hollow-point bullet casing." projectile_type = /obj/item/projectile/bullet/rifle/a762/hollow +/obj/item/ammo_casing/a762/hunter + desc = "A 7.62mm hunting bullet casing." + projectile_type = /obj/item/projectile/bullet/rifle/a762/hunter + /* * 14.5mm (anti-materiel rifle round) */ @@ -298,6 +302,10 @@ desc = "A 5.45mm hollow-point bullet casing." projectile_type = /obj/item/projectile/bullet/rifle/a545/hollow +/obj/item/ammo_casing/a545/hunter + desc = "A 5.45mm hunting bullet casing." + projectile_type = /obj/item/projectile/bullet/rifle/a545/hunter + /* * Misc */ diff --git a/code/modules/projectiles/guns/energy.dm b/code/modules/projectiles/guns/energy.dm index 0bdf518a2cf..447eefe1b89 100644 --- a/code/modules/projectiles/guns/energy.dm +++ b/code/modules/projectiles/guns/energy.dm @@ -7,7 +7,7 @@ var/obj/item/weapon/cell/power_supply //What type of power cell this uses var/charge_cost = 240 //How much energy is needed to fire. - var/cell_type = null + var/cell_type = /obj/item/weapon/cell/device/weapon var/projectile_type = /obj/item/projectile/beam/practice var/modifystate var/charge_meter = 1 //if set, the icon state will be chosen based on the current charge @@ -34,12 +34,15 @@ /obj/item/weapon/gun/energy/New() ..() - if(cell_type) - power_supply = new cell_type(src) - else - power_supply = new /obj/item/weapon/cell/device/weapon(src) if(self_recharge) + power_supply = new /obj/item/weapon/cell/device/weapon(src) processing_objects.Add(src) + else + if(cell_type) + power_supply = new cell_type(src) + else + power_supply = null + update_icon() /obj/item/weapon/gun/energy/Destroy() diff --git a/code/modules/projectiles/guns/energy/laser.dm b/code/modules/projectiles/guns/energy/laser.dm index cb93992acc2..40e1f552770 100644 --- a/code/modules/projectiles/guns/energy/laser.dm +++ b/code/modules/projectiles/guns/energy/laser.dm @@ -52,6 +52,26 @@ self_recharge = 1 use_external_power = 1 +/obj/item/weapon/gun/energy/retro/empty + icon_state = "retro" + cell_type = null + + +/obj/item/weapon/gun/energy/alien + name = "alien pistol" + desc = "A weapon that works very similarly to a traditional energy weapon. How this came to be will likely be a mystery for the ages." + icon_state = "alienpistol" + item_state = "alienpistol" + fire_sound = 'sound/weapons/eLuger.ogg' + fire_delay = 10 // Handguns should be inferior to two-handed weapons. Even alien ones I suppose. + charge_cost = 480 // Five shots. + + projectile_type = /obj/item/projectile/beam/cyan + cell_type = /obj/item/weapon/cell/device/weapon/recharge/alien // Self charges. + origin_tech = list(TECH_COMBAT = 8, TECH_MAGNET = 7) + modifystate = "alienpistol" + + /obj/item/weapon/gun/energy/captain name = "antique laser gun" icon_state = "caplaser" @@ -65,9 +85,8 @@ origin_tech = null fire_delay = 10 //Old pistol charge_cost = 480 //to compensate a bit for self-recharging - self_recharge = 1 - recharge_time = 3 //Recharges a bit more quickly... - charge_delay = 100 //... but it takes a while to get started + cell_type = /obj/item/weapon/cell/device/weapon/recharge/captain + battery_lock = 1 /obj/item/weapon/gun/energy/lasercannon name = "laser cannon" @@ -87,7 +106,6 @@ accuracy = 3 charge_cost = 600 - /obj/item/weapon/gun/energy/lasercannon/mounted name = "mounted laser cannon" self_recharge = 1 @@ -145,10 +163,11 @@ item_state = "laser" desc = "Standard issue weapon of the Imperial Guard" origin_tech = list(TECH_COMBAT = 1, TECH_MAGNET = 2) - self_recharge = 1 matter = list(DEFAULT_WALL_MATERIAL = 2000) fire_sound = 'sound/weapons/Laser.ogg' projectile_type = /obj/item/projectile/beam/lastertag/blue + cell_type = /obj/item/weapon/cell/device/weapon/recharge + battery_lock = 1 var/required_vest /obj/item/weapon/gun/energy/lasertag/special_check(var/mob/living/carbon/human/M) diff --git a/code/modules/projectiles/guns/energy/nuclear.dm b/code/modules/projectiles/guns/energy/nuclear.dm index e7dd400f591..048dddfe3f9 100644 --- a/code/modules/projectiles/guns/energy/nuclear.dm +++ b/code/modules/projectiles/guns/energy/nuclear.dm @@ -56,7 +56,8 @@ force = 8 //looks heavier than a pistol w_class = ITEMSIZE_LARGE //Looks bigger than a pistol, too. fire_delay = 6 //This one's not a handgun, it should have the same fire delay as everything else - self_recharge = 1 + cell_type = /obj/item/weapon/cell/device/weapon/recharge + battery_lock = 1 modifystate = null // requires_two_hands = 1 diff --git a/code/modules/projectiles/guns/energy/special.dm b/code/modules/projectiles/guns/energy/special.dm index d613f1f2062..18a25e5daf3 100644 --- a/code/modules/projectiles/guns/energy/special.dm +++ b/code/modules/projectiles/guns/energy/special.dm @@ -43,7 +43,8 @@ projectile_type = /obj/item/projectile/energy/floramut origin_tech = list(TECH_MATERIAL = 2, TECH_BIO = 3, TECH_POWER = 3) modifystate = "floramut" - self_recharge = 1 + cell_type = /obj/item/weapon/cell/device/weapon/recharge + battery_lock = 1 var/decl/plantgene/gene = null firemodes = list( @@ -137,7 +138,8 @@ charge_cost = 480 projectile_type = /obj/item/projectile/change origin_tech = null - self_recharge = 1 + cell_type = /obj/item/weapon/cell/device/weapon/recharge + battery_lock = 1 charge_meter = 0 /obj/item/weapon/gun/energy/staff/special_check(var/mob/user) @@ -188,7 +190,8 @@ obj/item/weapon/gun/energy/staff/focus w_class = ITEMSIZE_HUGE charge_cost = 24 // 100 shots, it's a spray and pray (to RNGesus) weapon. projectile_type = /obj/item/projectile/energy/blue_pellet - self_recharge = 1 + cell_type = /obj/item/weapon/cell/device/weapon/recharge + battery_lock = 1 accuracy = 5 // Suppressive weapons don't work too well if there's no risk of being hit. burst_delay = 1 // Burst faster than average. origin_tech = list(TECH_COMBAT = 6, TECH_MAGNET = 6, TECH_ILLEGAL = 6) diff --git a/code/modules/projectiles/guns/energy/stun.dm b/code/modules/projectiles/guns/energy/stun.dm index c8bba190878..43bb9e16370 100644 --- a/code/modules/projectiles/guns/energy/stun.dm +++ b/code/modules/projectiles/guns/energy/stun.dm @@ -41,7 +41,8 @@ fire_sound = 'sound/weapons/Genhit.ogg' projectile_type = /obj/item/projectile/energy/bolt charge_cost = 480 - self_recharge = 1 + cell_type = /obj/item/weapon/cell/device/weapon/recharge + battery_lock = 1 charge_meter = 0 /obj/item/weapon/gun/energy/crossbow/ninja diff --git a/code/modules/projectiles/guns/projectile/boltaction.dm b/code/modules/projectiles/guns/projectile/boltaction.dm index 89165243449..bb6d14d1ee0 100644 --- a/code/modules/projectiles/guns/projectile/boltaction.dm +++ b/code/modules/projectiles/guns/projectile/boltaction.dm @@ -20,16 +20,12 @@ /obj/item/weapon/gun/projectile/shotgun/pump/rifle/ceremonial name = "ceremonial bolt-action rifle" desc = "A bolt-action rifle with a heavy, high-quality wood stock that has a beautiful finish. Clearly not intended to be used in combat. Uses 7.62mm rounds." + icon_state = "boltaction_c" + item_state = "boltaction_c" ammo_type = /obj/item/ammo_casing/a762/blank -/obj/item/weapon/gun/projectile/shotgun/pump/rifle/mosin - name = "\improper Mosin Nagant" - desc = "Despite its age, the Mosin Nagant continues to be a favorite weapon among colonists, conscripts, and militias across the cosmos. Most today are built by Chen-Iltchenko Firearms, but it's hard to say who built this particular gun, considering the design has been ripped off by just about every arms manufacturer in the galaxy. Uses 7.62mm rounds." - icon_state = "mosin" - item_state = "mosin" - // Stole hacky terrible code from doublebarrel shotgun. -Spades -/obj/item/weapon/gun/projectile/shotgun/pump/rifle/mosin/attackby(var/obj/item/A as obj, mob/user as mob) +/obj/item/weapon/gun/projectile/shotgun/pump/rifle/ceremonial/attackby(var/obj/item/A as obj, mob/user as mob) if(istype(A, /obj/item/weapon/surgical/circular_saw) || istype(A, /obj/item/weapon/melee/energy) || istype(A, /obj/item/weapon/pickaxe/plasmacutter) && w_class != ITEMSIZE_NORMAL) user << "You begin to shorten the barrel and stock of \the [src]." if(loaded.len) @@ -38,16 +34,16 @@ user.visible_message("[src] goes off!", "The rifle goes off in your face!") return if(do_after(user, 30)) - icon_state = "obrez" + icon_state = "sawnrifle" w_class = ITEMSIZE_NORMAL recoil = 2 // Owch accuracy = -1 // You know damn well why. item_state = "gun" slot_flags &= ~SLOT_BACK //you can't sling it on your back slot_flags |= (SLOT_BELT|SLOT_HOLSTER) //but you can wear it on your belt (poorly concealed under a trenchcoat, ideally) - or in a holster, why not. - name = "\improper Obrez" - desc = "The firepower of a Mosin, now the size of a pistol, with an effective combat range of about three feet. Uses 7.62mm rounds." - user << "You shorten the barrel and stock of \the [src]!" + name = "sawn-off rifle" + desc = "The firepower of a rifle, now the size of a pistol, with an effective combat range of about three feet. Uses 7.62mm rounds." + to_chat(user, "You shorten the barrel and stock of \the [src]!") else ..() diff --git a/code/modules/projectiles/guns/projectile/pistol.dm b/code/modules/projectiles/guns/projectile/pistol.dm index e545ebb8485..9a9f0b4bd69 100644 --- a/code/modules/projectiles/guns/projectile/pistol.dm +++ b/code/modules/projectiles/guns/projectile/pistol.dm @@ -23,7 +23,7 @@ icon_state = "[initial(icon_state)]-e" /obj/item/weapon/gun/projectile/colt/detective - desc = "A Martian recreation of an old Terran pistol. Uses .45 rounds." + desc = "A Martian recreation of an old pistol. Uses .45 rounds." magazine_type = /obj/item/ammo_magazine/m45/rubber /obj/item/weapon/gun/projectile/colt/detective/verb/rename_gun() @@ -60,7 +60,8 @@ options["H&K VP"] = "VP78" options["P08 Luger"] = "p08" options["P08 Luger, Brown"] = "p08b" - var/choice = input(M,"What do you want the gun's sprite to be?","Resprite Gun") in options + options["Glock 37"] = "enforcer_black" + var/choice = input(M,"Choose your sprite!","Resprite Gun") in options if(src && choice && !M.stat && in_range(M,src)) icon_state = options[choice] unique_reskin = options[choice] diff --git a/code/modules/projectiles/guns/projectile/revolver.dm b/code/modules/projectiles/guns/projectile/revolver.dm index 81355d10314..20671d6fd58 100644 --- a/code/modules/projectiles/guns/projectile/revolver.dm +++ b/code/modules/projectiles/guns/projectile/revolver.dm @@ -66,6 +66,58 @@ M << "You name the gun [input]. Say hello to your new friend." return 1 +/obj/item/weapon/gun/projectile/revolver/detective45 + name = ".45 revolver" + desc = "A fancy replica of an old revolver, modified for .45 rounds and a seven-shot cylinder." + icon_state = "detective" + caliber = ".45" + origin_tech = list(TECH_COMBAT = 2, TECH_MATERIAL = 2) + fire_sound = 'sound/weapons/gunshot_heavy.ogg' + ammo_type = /obj/item/ammo_casing/a45r + max_shells = 7 + + +obj/item/weapon/gun/projectile/revolver/detective45/verb/rename_gun() + set name = "Name Gun" + set category = "Object" + set desc = "Rename your gun. If you're the Detective." + + var/mob/M = usr + if(!M.mind) return 0 + var/job = M.mind.assigned_role + if(job != "Detective") + M << "You don't feel cool enough to name this gun, chump." + return 0 + + var/input = sanitizeSafe(input("What do you want to name the gun?", ,""), MAX_NAME_LEN) + + if(src && input && !M.stat && in_range(M,src)) + name = input + M << "You name the gun [input]. Say hello to your new friend." + return 1 + +/obj/item/weapon/gun/projectile/revolver/detective45/verb/reskin_gun() + set name = "Resprite gun" + set category = "Object" + set desc = "Click to choose a sprite for your gun." + + var/mob/M = usr + var/list/options = list() + options["Colt Detective Special"] = "detective" + options["Ruger GP100"] = "GP100" + options["Colt Single Action Army"] = "detective_peacemaker" + options["Colt Single Action Army, Dark"] = "detective_peacemaker_dark" + options["H&K PT"] = "detective_panther" + options["Vintage LeMat"] = "lemat_old" + options["Webley MKVI "] = "webley" + var/choice = input(M,"Choose your sprite!","Resprite Gun") in options + if(src && choice && !M.stat && in_range(M,src)) + icon_state = options[choice] + M << "Your gun is now sprited as [choice]. Say hello to your new friend." + return 1 + + + // Blade Runner pistol. /obj/item/weapon/gun/projectile/revolver/deckard name = "\improper Deckard .38" diff --git a/code/modules/projectiles/guns/vox.dm b/code/modules/projectiles/guns/vox.dm index d3a846ab08f..ecc8a1a9047 100644 --- a/code/modules/projectiles/guns/vox.dm +++ b/code/modules/projectiles/guns/vox.dm @@ -60,7 +60,8 @@ w_class = ITEMSIZE_HUGE charge_cost = 300 projectile_type = /obj/item/projectile/beam/stun/darkmatter - self_recharge = 1 + cell_type = /obj/item/weapon/cell/device/weapon/recharge + battery_lock = 1 accuracy = 2 firemodes = list( @@ -85,7 +86,7 @@ /obj/item/projectile/beam/darkmatter name = "dark matter bolt" icon_state = "darkb" - damage = 60 + damage = 35 armor_penetration = 35 damage_type = BRUTE check_armour = "energy" @@ -118,7 +119,8 @@ item_state = "noise" fire_sound = 'sound/effects/basscannon.ogg' w_class = ITEMSIZE_HUGE - self_recharge = 1 + cell_type = /obj/item/weapon/cell/device/weapon/recharge + battery_lock = 1 charge_cost = 600 projectile_type=/obj/item/projectile/sonic/weak diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index fdc5a445b98..2040b0a7784 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -38,6 +38,8 @@ var/damage = 10 var/damage_type = BRUTE //BRUTE, BURN, TOX, OXY, CLONE, HALLOSS are the only things that should be in here + var/SA_bonus_damage = 0 // Some bullets inflict extra damage on simple animals. + var/SA_vulnerability = null // What kind of simple animal the above bonus damage should be applied to. Set to null to apply to all SAs. var/nodamage = 0 //Determines if the projectile will skip any damage inflictions var/taser_effect = 0 //If set then the projectile will apply it's agony damage using stun_effect_act() to mobs it hits, and other damage will be ignored var/check_armour = "bullet" //Defines what armor to use when it hits things. Must be set to bullet, laser, energy,or bomb //Cael - bio and rad are also valid diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm index a271684f7cc..32dce8e3b9e 100644 --- a/code/modules/projectiles/projectile/beams.dm +++ b/code/modules/projectiles/projectile/beams.dm @@ -70,6 +70,16 @@ tracer_type = /obj/effect/projectile/xray/tracer impact_type = /obj/effect/projectile/xray/impact +/obj/item/projectile/beam/cyan + name = "cyan beam" + icon_state = "cyan" + damage = 40 + light_color = "#00C6FF" + + muzzle_type = /obj/effect/projectile/laser_omni/muzzle + tracer_type = /obj/effect/projectile/laser_omni/tracer + impact_type = /obj/effect/projectile/laser_omni/impact + /obj/item/projectile/beam/pulse name = "pulse" icon_state = "u_laser" diff --git a/code/modules/projectiles/projectile/bullets.dm b/code/modules/projectiles/projectile/bullets.dm index 283e487272b..a7132fa43ba 100644 --- a/code/modules/projectiles/projectile/bullets.dm +++ b/code/modules/projectiles/projectile/bullets.dm @@ -209,6 +209,11 @@ armor_penetration = -50 penetrating = 0 +/obj/item/projectile/bullet/rifle/a762/hunter // Optimized for killing simple animals and not people, because Balance. + damage = 20 + SA_bonus_damage = 50 // 70 total on animals. + SA_vulnerability = SA_ANIMAL + /obj/item/projectile/bullet/rifle/a545 damage = 25 @@ -221,6 +226,11 @@ armor_penetration = -50 penetrating = 0 +/obj/item/projectile/bullet/rifle/a545/hunter + damage = 15 + SA_bonus_damage = 35 // 50 total on animals. + SA_vulnerability = SA_ANIMAL + /obj/item/projectile/bullet/rifle/a145 damage = 80 stun = 3 diff --git a/code/modules/projectiles/projectile/special.dm b/code/modules/projectiles/projectile/special.dm index 049bdcaf783..8c5d2cd11aa 100644 --- a/code/modules/projectiles/projectile/special.dm +++ b/code/modules/projectiles/projectile/special.dm @@ -11,7 +11,7 @@ var/pulse_range = 1 - on_hit(var/atom/target, var/blocked = 0) +/obj/item/projectile/ion/on_hit(var/atom/target, var/blocked = 0) empulse(target, pulse_range, pulse_range, pulse_range, pulse_range) return 1 @@ -26,7 +26,7 @@ sharp = 1 edge = 1 - on_hit(var/atom/target, var/blocked = 0) +/obj/item/projectile/bullet/gyro/on_hit(var/atom/target, var/blocked = 0) explosion(target, -1, 0, 2) return 1 @@ -81,26 +81,26 @@ nodamage = 1 check_armour = "bullet" - Bump(atom/A as mob|obj|turf|area) - if(A == firer) - loc = A.loc - return +/obj/item/projectile/meteor/Bump(atom/A as mob|obj|turf|area) + if(A == firer) + loc = A.loc + return - sleep(-1) //Might not be important enough for a sleep(-1) but the sleep/spawn itself is necessary thanks to explosions and metoerhits + sleep(-1) //Might not be important enough for a sleep(-1) but the sleep/spawn itself is necessary thanks to explosions and metoerhits - if(src)//Do not add to this if() statement, otherwise the meteor won't delete them - if(A) + if(src)//Do not add to this if() statement, otherwise the meteor won't delete them + if(A) - A.ex_act(2) - playsound(src.loc, 'sound/effects/meteorimpact.ogg', 40, 1) + A.ex_act(2) + playsound(src.loc, 'sound/effects/meteorimpact.ogg', 40, 1) - for(var/mob/M in range(10, src)) - if(!M.stat && !istype(M, /mob/living/silicon/ai))\ - shake_camera(M, 3, 1) - qdel(src) - return 1 - else - return 0 + for(var/mob/M in range(10, src)) + if(!M.stat && !istype(M, /mob/living/silicon/ai))\ + shake_camera(M, 3, 1) + qdel(src) + return 1 + else + return 0 /obj/item/projectile/energy/floramut name = "alpha somatoray" @@ -113,36 +113,36 @@ light_power = 0.5 light_color = "#33CC00" - on_hit(var/atom/target, var/blocked = 0) - var/mob/living/M = target - if(ishuman(target)) - var/mob/living/carbon/human/H = M - if((H.species.flags & IS_PLANT) && (M.nutrition < 500)) - if(prob(15)) - M.apply_effect((rand(30,80)),IRRADIATE) - M.Weaken(5) - for (var/mob/V in viewers(src)) - V.show_message("[M] writhes in pain as \his vacuoles boil.", 3, "You hear the crunching of leaves.", 2) - if(prob(35)) - // for (var/mob/V in viewers(src)) //Public messages commented out to prevent possible metaish genetics experimentation and stuff. - Cheridan - // V.show_message("[M] is mutated by the radiation beam.", 3, " You hear the snapping of twigs.", 2) - if(prob(80)) - randmutb(M) - domutcheck(M,null) - else - randmutg(M) - domutcheck(M,null) +/obj/item/projectile/energy/floramut/on_hit(var/atom/target, var/blocked = 0) + var/mob/living/M = target + if(ishuman(target)) + var/mob/living/carbon/human/H = M + if((H.species.flags & IS_PLANT) && (M.nutrition < 500)) + if(prob(15)) + M.apply_effect((rand(30,80)),IRRADIATE) + M.Weaken(5) + for (var/mob/V in viewers(src)) + V.show_message("[M] writhes in pain as \his vacuoles boil.", 3, "You hear the crunching of leaves.", 2) + if(prob(35)) + // for (var/mob/V in viewers(src)) //Public messages commented out to prevent possible metaish genetics experimentation and stuff. - Cheridan + // V.show_message("[M] is mutated by the radiation beam.", 3, " You hear the snapping of twigs.", 2) + if(prob(80)) + randmutb(M) + domutcheck(M,null) else - M.adjustFireLoss(rand(5,15)) - M.show_message("The radiation beam singes you!") - // for (var/mob/V in viewers(src)) - // V.show_message("[M] is singed by the radiation beam.", 3, " You hear the crackle of burning leaves.", 2) - else if(istype(target, /mob/living/carbon/)) - // for (var/mob/V in viewers(src)) - // V.show_message("The radiation beam dissipates harmlessly through [M]", 3) - M.show_message("The radiation beam dissipates harmlessly through your body.") - else - return 1 + randmutg(M) + domutcheck(M,null) + else + M.adjustFireLoss(rand(5,15)) + M.show_message("The radiation beam singes you!") + // for (var/mob/V in viewers(src)) + // V.show_message("[M] is singed by the radiation beam.", 3, " You hear the crackle of burning leaves.", 2) + else if(istype(target, /mob/living/carbon/)) + // for (var/mob/V in viewers(src)) + // V.show_message("The radiation beam dissipates harmlessly through [M]", 3) + M.show_message("The radiation beam dissipates harmlessly through your body.") + else + return 1 /obj/item/projectile/energy/floramut/gene name = "gamma somatoray" @@ -164,25 +164,25 @@ light_power = 0.5 light_color = "#FFFFFF" - on_hit(var/atom/target, var/blocked = 0) - var/mob/M = target - if(ishuman(target)) //These rays make plantmen fat. - var/mob/living/carbon/human/H = M - if((H.species.flags & IS_PLANT) && (M.nutrition < 500)) - M.nutrition += 30 - else if (istype(target, /mob/living/carbon/)) - M.show_message("The radiation beam dissipates harmlessly through your body.") - else - return 1 +/obj/item/projectile/energy/florayield/on_hit(var/atom/target, var/blocked = 0) + var/mob/M = target + if(ishuman(target)) //These rays make plantmen fat. + var/mob/living/carbon/human/H = M + if((H.species.flags & IS_PLANT) && (M.nutrition < 500)) + M.nutrition += 30 + else if (istype(target, /mob/living/carbon/)) + M.show_message("The radiation beam dissipates harmlessly through your body.") + else + return 1 /obj/item/projectile/beam/mindflayer name = "flayer ray" - on_hit(var/atom/target, var/blocked = 0) - if(ishuman(target)) - var/mob/living/carbon/human/M = target - M.Confuse(rand(5,8)) +/obj/item/projectile/beam/mindflayer/on_hit(var/atom/target, var/blocked = 0) + if(ishuman(target)) + var/mob/living/carbon/human/M = target + M.Confuse(rand(5,8)) /obj/item/projectile/chameleon name = "bullet" @@ -192,3 +192,36 @@ nodamage = 1 damage_type = HALLOSS muzzle_type = /obj/effect/projectile/bullet/muzzle + +/obj/item/projectile/bola + name = "bola" + icon_state = "bola" + damage = 5 + embed_chance = 0 //Nada. + damage_type = HALLOSS + muzzle_type = null + +/obj/item/projectile/bola/on_hit(var/atom/target, var/blocked = 0) + if(ishuman(target)) + var/mob/living/carbon/human/M = target + var/obj/item/weapon/handcuffs/legcuffs/bola/B = new(src.loc) + if(!B.place_legcuffs(M,firer)) + if(B) + qdel(B) + ..() + +/obj/item/projectile/webball + name = "ball of web" + icon_state = "bola" + damage = 10 + embed_chance = 0 //Nada. + damage_type = BRUTE + muzzle_type = null + +/obj/item/projectile/webball/on_hit(var/atom/target, var/blocked = 0) + if(isturf(target.loc)) + var/obj/effect/spider/stickyweb/W = locate() in get_turf(target) + if(!W && prob(75)) + visible_message("\The [src] splatters a layer of web on \the [target]!") + new /obj/effect/spider/stickyweb(target.loc) + ..() diff --git a/code/modules/random_map/automata/caves.dm b/code/modules/random_map/automata/caves.dm index 4868e6d0684..e1f2092bdb9 100644 --- a/code/modules/random_map/automata/caves.dm +++ b/code/modules/random_map/automata/caves.dm @@ -2,6 +2,10 @@ iterations = 5 descriptor = "moon caves" var/list/ore_turfs = list() + var/make_cracked_turfs = TRUE + +/datum/random_map/automata/cave_system/no_cracks + make_cracked_turfs = FALSE /datum/random_map/automata/cave_system/get_appropriate_path(var/value) return @@ -47,7 +51,7 @@ if(map[current_cell] == FLOOR_CHAR) if(prob(90)) T.make_floor() - else + else if(make_cracked_turfs) T.ChangeTurf(/turf/space/cracked_asteroid) else T.make_wall() diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm index c71a7de362d..d61ace5b17f 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm @@ -298,6 +298,49 @@ power = 10 meltdose = 4 +/datum/reagent/thermite/venom + name = "Pyrotoxin" + id = "thermite_v" + description = "A biologically produced compound capable of melting steel or other metals, similarly to thermite." + taste_description = "sweet chalk" + reagent_state = SOLID + color = "#673910" + touch_met = 50 + +/datum/reagent/thermite/venom/affect_blood(var/mob/living/carbon/M, var/alien, var/removed) + M.adjustFireLoss(3 * removed) + if(M.fire_stacks <= 1.5) + M.adjust_fire_stacks(0.15) + if(alien == IS_DIONA) + return + if(prob(10)) + to_chat(M,"Your veins feel like they're on fire!") + M.adjust_fire_stacks(0.1) + else if(prob(5)) + M.IgniteMob() + to_chat(M,"Some of your veins rupture, the exposed blood igniting!") + +/datum/reagent/condensedcapsaicin/venom + name = "Irritant toxin" + id = "condensedcapsaicin_v" + description = "A biological agent that acts similarly to pepperspray. This compound seems to be particularly cruel, however, capable of permeating the barriers of blood vessels." + taste_description = "fire" + color = "#B31008" + +/datum/reagent/condensedcapsaicin/venom/affect_blood(var/mob/living/carbon/M, var/alien, var/removed) + if(alien == IS_DIONA) + return + if(prob(50)) + M.adjustToxLoss(0.5 * removed) + if(prob(50)) + M.apply_effect(4, AGONY, 0) + if(prob(20)) + to_chat(M,"You feel like your insides are burning!") + else if(prob(20)) + M.visible_message("[M] [pick("dry heaves!","coughs!","splutters!","rubs at their eyes!")]") + else + M.eye_blurry = max(M.eye_blurry, 10) + /datum/reagent/lexorin name = "Lexorin" id = "lexorin" @@ -542,6 +585,21 @@ M.emote(pick("twitch", "drool", "moan", "gasp")) return +/datum/reagent/serotrotium/venom + name = "Serotropic venom" + id = "serotrotium_v" + description = "A chemical compound that promotes concentrated production of the serotonin neurotransmitter in humans. This appears to be a biologically produced form, resulting in a specifically toxic nature." + taste_description = "chalky bitterness" + +/datum/reagent/serotrotium/venom/affect_blood(var/mob/living/carbon/M, var/alien, var/removed) + if(alien == IS_DIONA) + return + if(prob(30)) + if(prob(25)) + M.emote(pick("shiver", "blink_r")) + M.adjustBrainLoss(0.2 * removed) + return ..() + /datum/reagent/cryptobiolin name = "Cryptobiolin" id = "cryptobiolin" diff --git a/code/modules/reagents/reagent_containers/glass.dm b/code/modules/reagents/reagent_containers/glass.dm index 44dce0a7ad2..dbc6f17a5d6 100644 --- a/code/modules/reagents/reagent_containers/glass.dm +++ b/code/modules/reagents/reagent_containers/glass.dm @@ -54,62 +54,72 @@ if(!..(user, 2)) return if(reagents && reagents.reagent_list.len) - user << "It contains [reagents.total_volume] units of liquid." + to_chat(user, "It contains [reagents.total_volume] units of liquid.") else - user << "It is empty." + to_chat(user, "It is empty.") if(!is_open_container()) - user << "Airtight lid seals it completely." + to_chat(user, "Airtight lid seals it completely.") /obj/item/weapon/reagent_containers/glass/attack_self() ..() if(is_open_container()) - usr << "You put the lid on \the [src]." + to_chat(usr, "You put the lid on \the [src].") flags ^= OPENCONTAINER else - usr << "You take the lid off \the [src]." + to_chat(usr, "You take the lid off \the [src].") flags |= OPENCONTAINER update_icon() -/obj/item/weapon/reagent_containers/glass/do_surgery(mob/living/carbon/M, mob/living/user) - if(user.a_intent != I_HELP) //in case it is ever used as a surgery tool - return ..() - afterattack(M, user, 1) - return 1 +/obj/item/weapon/reagent_containers/glass/attack(mob/M as mob, mob/user as mob, def_zone) + if(force && !(flags & NOBLUDGEON) && user.a_intent == I_HURT) + return ..() + + if(standard_feed_mob(user, M)) + return + + return 0 + +/obj/item/weapon/reagent_containers/glass/standard_feed_mob(var/mob/user, var/mob/target) + if(!is_open_container()) + to_chat(user, "You need to open \the [src] first.") + return 1 + if(user.a_intent == I_HURT) + return 1 + return ..() + +/obj/item/weapon/reagent_containers/glass/self_feed_message(var/mob/user) + to_chat(user, "You swallow a gulp from \the [src].") /obj/item/weapon/reagent_containers/glass/afterattack(var/obj/target, var/mob/user, var/proximity) - if(!is_open_container() || !proximity) //Is the container open & are they next to whatever they're clicking? - return //If not, do nothing. - + return 1 //If not, do nothing. for(var/type in can_be_placed_into) //Is it something it can be placed into? if(istype(target, type)) - return - + return 1 if(standard_dispenser_refill(user, target)) //Are they clicking a water tank/some dispenser? - return - + return 1 if(standard_pour_into(user, target)) //Pouring into another beaker? return - - if(user.a_intent == I_HURT) //Harm intent? - if(standard_splash_mob(user, target)) //If harm intent and can splash a mob, go ahead. - return - if(reagents && reagents.total_volume) //Otherwise? Splash the floor. - user << "You splash the solution onto [target]." + if(user.a_intent == I_HURT) + if(standard_splash_mob(user,target)) + return 1 + if(reagents && reagents.total_volume) + to_chat(user, "You splash the solution onto [target].") //They are on harm intent, aka wanting to spill it. reagents.splash(target, reagents.total_volume) - return + return 1 + ..() /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)) var/tmp_label = sanitizeSafe(input(user, "Enter a label for [name]", "Label", label_text), MAX_NAME_LEN) if(length(tmp_label) > 50) - user << "The label can be at most 50 characters long." + to_chat(user, "The label can be at most 50 characters long.") else if(length(tmp_label) > 10) - user << "You set the label." + to_chat(user, "You set the label.") label_text = tmp_label update_name_label() else - user << "You set the label to \"[tmp_label]\"." + to_chat(user, "You set the label to \"[tmp_label]\".") label_text = tmp_label update_name_label() if(istype(W,/obj/item/weapon/storage/bag)) @@ -210,6 +220,7 @@ icon_state = "vial" matter = list("glass" = 250) volume = 30 + w_class = ITEMSIZE_TINY amount_per_transfer_from_this = 10 possible_transfer_amounts = list(5,10,15,25) flags = OPENCONTAINER @@ -254,10 +265,10 @@ return else if(istype(D, /obj/item/weapon/mop)) if(reagents.total_volume < 1) - user << "\The [src] is empty!" + to_chat(user, "\The [src] is empty!") else reagents.trans_to_obj(D, 5) - user << "You wet \the [D] in \the [src]." + to_chat(user, "You wet \the [D] in \the [src].") playsound(loc, 'sound/effects/slosh.ogg', 25, 1) return else @@ -295,10 +306,10 @@ obj/item/weapon/reagent_containers/glass/bucket/wood return else if(istype(D, /obj/item/weapon/mop)) if(reagents.total_volume < 1) - user << "\The [src] is empty!" + to_chat(user, "\The [src] is empty!") else reagents.trans_to_obj(D, 5) - user << "You wet \the [D] in \the [src]." + to_chat(user, "You wet \the [D] in \the [src].") playsound(loc, 'sound/effects/slosh.ogg', 25, 1) return else diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm index 5c5d0cc3a6a..604eaa6a3a6 100644 --- a/code/modules/reagents/reagent_containers/hypospray.dm +++ b/code/modules/reagents/reagent_containers/hypospray.dm @@ -60,7 +60,57 @@ used = !used return +//A vial-loaded hypospray. Cartridge-based! +/obj/item/weapon/reagent_containers/hypospray/vial + name = "hypospray mkII" + desc = "A new development from DeForest Medical, this new hypospray takes 30-unit vials as the drug supply for easy swapping." + var/obj/item/weapon/reagent_containers/glass/beaker/vial/loaded_vial //Wow, what a name. + volume = 0 +/obj/item/weapon/reagent_containers/hypospray/vial/New() + ..() + loaded_vial = new /obj/item/weapon/reagent_containers/glass/beaker/vial(src) //Comes with an empty vial + volume = loaded_vial.volume + reagents.maximum_volume = loaded_vial.reagents.maximum_volume + +/obj/item/weapon/reagent_containers/hypospray/vial/attack_hand(mob/user as mob) + if(user.get_inactive_hand() == src) + if(loaded_vial) + reagents.trans_to_holder(loaded_vial.reagents,volume) + reagents.maximum_volume = 0 + loaded_vial.update_icon() + user.put_in_hands(loaded_vial) + loaded_vial = null + user << "You remove the vial from the [src]." + update_icon() + playsound(src.loc, 'sound/weapons/flipblade.ogg', 50, 1) + return + ..() + else + return ..() + +/obj/item/weapon/reagent_containers/hypospray/vial/attackby(obj/item/weapon/W, mob/user as mob) + if(istype(W, /obj/item/weapon/reagent_containers/glass/beaker/vial)) + if(!loaded_vial) + user.visible_message("[user] begins loading [W] into \the [src].","You start loading [W] into \the [src].") + if(!do_after(user,30) || loaded_vial || !(W in user)) + return 0 + if(W.is_open_container()) + W.flags ^= OPENCONTAINER + W.update_icon() + user.drop_item() + W.loc = src + loaded_vial = W + reagents.maximum_volume = loaded_vial.reagents.maximum_volume + loaded_vial.reagents.trans_to_holder(reagents,volume) + user.visible_message("[user] has loaded [W] into \the [src].","You have loaded [W] into \the [src].") + update_icon() + playsound(src.loc, 'sound/weapons/empty.ogg', 50, 1) + else + user << "\The [src] already has a vial." + else + ..() + /obj/item/weapon/reagent_containers/hypospray/autoinjector name = "autoinjector" desc = "A rapid and safe way to administer small amounts of drugs by untrained or trained personnel." diff --git a/code/modules/reagents/reagent_dispenser.dm b/code/modules/reagents/reagent_dispenser.dm index 6312d08d84d..88b6d9d0640 100644 --- a/code/modules/reagents/reagent_dispenser.dm +++ b/code/modules/reagents/reagent_dispenser.dm @@ -76,6 +76,13 @@ ..() reagents.add_reagent("water",1000) +/obj/structure/reagent_dispensers/watertank/high/New() + name = "high-capacity water tank" + desc = "A highly-pressurized water tank made to hold vast amounts of water.." + icon_state = "watertank_high" + ..() + reagents.add_reagent("water",4000) + /obj/structure/reagent_dispensers/fueltank name = "fueltank" desc = "A fueltank." diff --git a/code/modules/research/designs.dm b/code/modules/research/designs.dm index 708cc4e0810..b7dd3701904 100644 --- a/code/modules/research/designs.dm +++ b/code/modules/research/designs.dm @@ -210,7 +210,7 @@ other types of metals and chemistry for reagents). build_type = PROTOLATHE | MECHFAB /datum/design/item/powercell/AssembleDesignName() - name = "Power cell model ([item_name])" + name = "Power Cell Model ([item_name])" /datum/design/item/powercell/AssembleDesignDesc() if(build_path) diff --git a/code/modules/research/mechfab_designs.dm b/code/modules/research/mechfab_designs.dm index 4d7149c1882..8efeec6c0d5 100644 --- a/code/modules/research/mechfab_designs.dm +++ b/code/modules/research/mechfab_designs.dm @@ -7,47 +7,47 @@ category = "Ripley" /datum/design/item/mechfab/ripley/chassis - name = "Ripley chassis" + name = "Ripley Chassis" id = "ripley_chassis" build_path = /obj/item/mecha_parts/chassis/ripley time = 10 materials = list(DEFAULT_WALL_MATERIAL = 15000) /datum/design/item/mechfab/ripley/chassis/firefighter - name = "Firefigher chassis" + name = "Firefigher Chassis" id = "firefighter_chassis" build_path = /obj/item/mecha_parts/chassis/firefighter /datum/design/item/mechfab/ripley/torso - name = "Ripley torso" + name = "Ripley Torso" id = "ripley_torso" build_path = /obj/item/mecha_parts/part/ripley_torso time = 20 materials = list(DEFAULT_WALL_MATERIAL = 30000, "glass" = 11250) /datum/design/item/mechfab/ripley/left_arm - name = "Ripley left arm" + name = "Ripley Left Arm" id = "ripley_left_arm" build_path = /obj/item/mecha_parts/part/ripley_left_arm time = 15 materials = list(DEFAULT_WALL_MATERIAL = 18750) /datum/design/item/mechfab/ripley/right_arm - name = "Ripley right arm" + name = "Ripley Right Arm" id = "ripley_right_arm" build_path = /obj/item/mecha_parts/part/ripley_right_arm time = 15 materials = list(DEFAULT_WALL_MATERIAL = 18750) /datum/design/item/mechfab/ripley/left_leg - name = "Ripley left leg" + name = "Ripley Left Leg" id = "ripley_left_leg" build_path = /obj/item/mecha_parts/part/ripley_left_leg time = 15 materials = list(DEFAULT_WALL_MATERIAL = 22500) /datum/design/item/mechfab/ripley/right_leg - name = "Ripley right leg" + name = "Ripley Right Leg" id = "ripley_right_leg" build_path = /obj/item/mecha_parts/part/ripley_right_leg time = 15 @@ -57,49 +57,49 @@ category = "Odysseus" /datum/design/item/mechfab/odysseus/chassis - name = "Odysseus chassis" + name = "Odysseus Chassis" id = "odysseus_chassis" build_path = /obj/item/mecha_parts/chassis/odysseus time = 10 materials = list(DEFAULT_WALL_MATERIAL = 15000) /datum/design/item/mechfab/odysseus/torso - name = "Odysseus torso" + name = "Odysseus Torso" id = "odysseus_torso" build_path = /obj/item/mecha_parts/part/odysseus_torso time = 18 materials = list(DEFAULT_WALL_MATERIAL = 18750) /datum/design/item/mechfab/odysseus/head - name = "Odysseus head" + name = "Odysseus Head" id = "odysseus_head" build_path = /obj/item/mecha_parts/part/odysseus_head time = 10 materials = list(DEFAULT_WALL_MATERIAL = 1500, "glass" = 7500) /datum/design/item/mechfab/odysseus/left_arm - name = "Odysseus left arm" + name = "Odysseus Left Arm" id = "odysseus_left_arm" build_path = /obj/item/mecha_parts/part/odysseus_left_arm time = 12 materials = list(DEFAULT_WALL_MATERIAL = 7500) /datum/design/item/mechfab/odysseus/right_arm - name = "Odysseus right arm" + name = "Odysseus Right Arm" id = "odysseus_right_arm" build_path = /obj/item/mecha_parts/part/odysseus_right_arm time = 12 materials = list(DEFAULT_WALL_MATERIAL = 7500) /datum/design/item/mechfab/odysseus/left_leg - name = "Odysseus left leg" + name = "Odysseus Left Leg" id = "odysseus_left_leg" build_path = /obj/item/mecha_parts/part/odysseus_left_leg time = 13 materials = list(DEFAULT_WALL_MATERIAL = 11250) /datum/design/item/mechfab/odysseus/right_leg - name = "Odysseus right leg" + name = "Odysseus Right Leg" id = "odysseus_right_leg" build_path = /obj/item/mecha_parts/part/odysseus_right_leg time = 13 @@ -109,56 +109,56 @@ category = "Gygax" /datum/design/item/mechfab/gygax/chassis - name = "Gygax chassis" + name = "Gygax Chassis" id = "gygax_chassis" build_path = /obj/item/mecha_parts/chassis/gygax time = 10 materials = list(DEFAULT_WALL_MATERIAL = 18750) /datum/design/item/mechfab/gygax/torso - name = "Gygax torso" + name = "Gygax Torso" id = "gygax_torso" build_path = /obj/item/mecha_parts/part/gygax_torso time = 30 materials = list(DEFAULT_WALL_MATERIAL = 37500, "glass" = 15000) /datum/design/item/mechfab/gygax/head - name = "Gygax head" + name = "Gygax Head" id = "gygax_head" build_path = /obj/item/mecha_parts/part/gygax_head time = 20 materials = list(DEFAULT_WALL_MATERIAL = 15000, "glass" = 7500) /datum/design/item/mechfab/gygax/left_arm - name = "Gygax left arm" + name = "Gygax Left Arm" id = "gygax_left_arm" build_path = /obj/item/mecha_parts/part/gygax_left_arm time = 20 materials = list(DEFAULT_WALL_MATERIAL = 22500) /datum/design/item/mechfab/gygax/right_arm - name = "Gygax right arm" + name = "Gygax Right Arm" id = "gygax_right_arm" build_path = /obj/item/mecha_parts/part/gygax_right_arm time = 20 materials = list(DEFAULT_WALL_MATERIAL = 22500) /datum/design/item/mechfab/gygax/left_leg - name = "Gygax left leg" + name = "Gygax Left Leg" id = "gygax_left_leg" build_path = /obj/item/mecha_parts/part/gygax_left_leg time = 20 materials = list(DEFAULT_WALL_MATERIAL = 26250) /datum/design/item/mechfab/gygax/right_leg - name = "Gygax right leg" + name = "Gygax Right Leg" id = "gygax_right_leg" build_path = /obj/item/mecha_parts/part/gygax_right_leg time = 20 materials = list(DEFAULT_WALL_MATERIAL = 26250) /datum/design/item/mechfab/gygax/armour - name = "Gygax armour plates" + name = "Gygax Armour Plates" id = "gygax_armour" build_path = /obj/item/mecha_parts/part/gygax_armour time = 60 @@ -168,56 +168,56 @@ category = "Durand" /datum/design/item/mechfab/durand/chassis - name = "Durand chassis" + name = "Durand Chassis" id = "durand_chassis" build_path = /obj/item/mecha_parts/chassis/durand time = 10 materials = list(DEFAULT_WALL_MATERIAL = 18750) /datum/design/item/mechfab/durand/torso - name = "Durand torso" + name = "Durand Torso" id = "durand_torso" build_path = /obj/item/mecha_parts/part/durand_torso time = 30 materials = list(DEFAULT_WALL_MATERIAL = 41250, "glass" = 15000, "silver" = 7500) /datum/design/item/mechfab/durand/head - name = "Durand head" + name = "Durand Head" id = "durand_head" build_path = /obj/item/mecha_parts/part/durand_head time = 20 materials = list(DEFAULT_WALL_MATERIAL = 18750, "glass" = 7500, "silver" = 2250) /datum/design/item/mechfab/durand/left_arm - name = "Durand left arm" + name = "Durand Left Arm" id = "durand_left_arm" build_path = /obj/item/mecha_parts/part/durand_left_arm time = 20 materials = list(DEFAULT_WALL_MATERIAL = 26250, "silver" = 2250) /datum/design/item/mechfab/durand/right_arm - name = "Durand right arm" + name = "Durand Right Arm" id = "durand_right_arm" build_path = /obj/item/mecha_parts/part/durand_right_arm time = 20 materials = list(DEFAULT_WALL_MATERIAL = 26250, "silver" = 2250) /datum/design/item/mechfab/durand/left_leg - name = "Durand left leg" + name = "Durand Left Leg" id = "durand_left_leg" build_path = /obj/item/mecha_parts/part/durand_left_leg time = 20 materials = list(DEFAULT_WALL_MATERIAL = 30000, "silver" = 2250) /datum/design/item/mechfab/durand/right_leg - name = "Durand right leg" + name = "Durand Right Leg" id = "durand_right_leg" build_path = /obj/item/mecha_parts/part/durand_right_leg time = 20 materials = list(DEFAULT_WALL_MATERIAL = 30000, "silver" = 2250) /datum/design/item/mechfab/durand/armour - name = "Durand armour plates" + name = "Durand Armour Plates" id = "durand_armour" build_path = /obj/item/mecha_parts/part/durand_armour time = 60 @@ -234,14 +234,14 @@ desc = "Allows for the construction of \a '[item_name]' exosuit module." /datum/design/item/mecha/tracking - name = "Exosuit tracking beacon" + name = "Exosuit Tracking Beacon" id = "mech_tracker" time = 5 materials = list(DEFAULT_WALL_MATERIAL = 375) build_path = /obj/item/mecha_parts/mecha_tracking /datum/design/item/mecha/hydraulic_clamp - name = "Hydraulic clamp" + name = "Hydraulic Clamp" id = "hydraulic_clamp" build_path = /obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp @@ -256,12 +256,12 @@ build_path = /obj/item/mecha_parts/mecha_equipment/tool/extinguisher /datum/design/item/mecha/cable_layer - name = "Cable layer" + name = "Cable Layer" id = "mech_cable_layer" build_path = /obj/item/mecha_parts/mecha_equipment/tool/cable_layer /datum/design/item/mecha/flaregun - name = "Flare launcher" + name = "Flare Launcher" id = "mecha_flare_gun" build_path = /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flare materials = list(DEFAULT_WALL_MATERIAL = 9375) @@ -273,30 +273,20 @@ materials = list(DEFAULT_WALL_MATERIAL = 3750, "glass" = 7500) /datum/design/item/mecha/syringe_gun - name = "Syringe gun" + name = "Syringe Gun" id = "mech_syringe_gun" build_path = /obj/item/mecha_parts/mecha_equipment/tool/syringe_gun time = 20 materials = list(DEFAULT_WALL_MATERIAL = 2250, "glass" = 1500) -/* -/datum/design/item/mecha/syringe_gun - desc = "Exosuit-mounted syringe gun and chemical synthesizer." - id = "mech_syringe_gun" - req_tech = list(TECH_MATERIAL = 3, TECH_BIO = 4, TECH_MAGNET = 4, TECH_DATA = 3) - build_path = /obj/item/mecha_parts/mecha_equipment/tool/syringe_gun - */ - /datum/design/item/mecha/passenger - name = "Passenger compartment" + name = "Passenger Compartment" id = "mech_passenger" build_path = /obj/item/mecha_parts/mecha_equipment/tool/passenger materials = list(DEFAULT_WALL_MATERIAL = 3750, "glass" = 3750) -//obj/item/mecha_parts/mecha_equipment/repair_droid, -//obj/item/mecha_parts/mecha_equipment/jetpack, //TODO MECHA JETPACK SPRITE MISSING /datum/design/item/mecha/taser - name = "PBT \"Pacifier\" mounted taser" + name = "PBT \"Pacifier\" Mounted Taser" id = "mech_taser" build_path = /obj/item/mecha_parts/mecha_equipment/weapon/energy/taser @@ -316,38 +306,38 @@ build_path = /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/scattershot /datum/design/item/mecha/weapon/laser - name = "CH-PS \"Immolator\" laser" + name = "CH-PS \"Immolator\" Laser" id = "mech_laser" req_tech = list(TECH_COMBAT = 3, TECH_MAGNET = 3) build_path = /obj/item/mecha_parts/mecha_equipment/weapon/energy/laser /datum/design/item/mecha/weapon/laser_rigged - name = "Jury-rigged welder-laser" + name = "Jury-Rigged Welder-Laser" desc = "Allows for the construction of a welder-laser assembly package for non-combat exosuits." id = "mech_laser_rigged" req_tech = list(TECH_COMBAT = 2, TECH_MAGNET = 2) build_path = /obj/item/mecha_parts/mecha_equipment/weapon/energy/riggedlaser /datum/design/item/mecha/weapon/laser_heavy - name = "CH-LC \"Solaris\" laser cannon" + name = "CH-LC \"Solaris\" Laser Cannon" id = "mech_laser_heavy" req_tech = list(TECH_COMBAT = 4, TECH_MAGNET = 4) build_path = /obj/item/mecha_parts/mecha_equipment/weapon/energy/laser/heavy /datum/design/item/mecha/weapon/ion - name = "mkIV ion heavy cannon" + name = "MK-IV Ion Heavy Cannon" id = "mech_ion" req_tech = list(TECH_COMBAT = 4, TECH_MAGNET = 4) build_path = /obj/item/mecha_parts/mecha_equipment/weapon/energy/ion /datum/design/item/mecha/weapon/grenade_launcher - name = "SGL-6 grenade launcher" + name = "SGL-6 Grenade Launcher" id = "mech_grenade_launcher" req_tech = list(TECH_COMBAT = 3) build_path = /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flashbang /datum/design/item/mecha/weapon/clusterbang_launcher - name = "SOP-6 grenade launcher" + name = "SOP-6 Grenade Launcher" desc = "A weapon that violates the Geneva Convention at 6 rounds per minute." id = "clusterbang_launcher" req_tech = list(TECH_COMBAT= 5, TECH_MATERIAL = 5, TECH_ILLEGAL = 3) @@ -380,7 +370,7 @@ // *** Nonweapon modules /datum/design/item/mecha/wormhole_gen - name = "Wormhole generator" + name = "Wormhole Generator" desc = "An exosuit module that can generate small quasi-stable wormholes." id = "mech_wormhole_gen" req_tech = list(TECH_BLUESPACE = 3, TECH_MAGNET = 2) @@ -403,36 +393,38 @@ build_path = /obj/item/mecha_parts/mecha_equipment/tool/rcd /datum/design/item/mecha/gravcatapult - name = "Gravitational catapult" + name = "Gravitational Catapult" desc = "An exosuit-mounted gravitational catapult." id = "mech_gravcatapult" req_tech = list(TECH_BLUESPACE = 2, TECH_MAGNET = 3, TECH_ENGINEERING = 3) build_path = /obj/item/mecha_parts/mecha_equipment/gravcatapult /datum/design/item/mecha/repair_droid - name = "Repair droid" + name = "Repair Droid" desc = "Automated repair droid, exosuits' best companion. BEEP BOOP" id = "mech_repair_droid" req_tech = list(TECH_MAGNET = 3, TECH_DATA = 3, TECH_ENGINEERING = 3) materials = list(DEFAULT_WALL_MATERIAL = 7500, "gold" = 750, "silver" = 1500, "glass" = 3750) build_path = /obj/item/mecha_parts/mecha_equipment/repair_droid +//obj/item/mecha_parts/mecha_equipment/jetpack, //TODO MECHA JETPACK SPRITE MISSING + /datum/design/item/mecha/phoron_generator - desc = "Phoron reactor." + desc = "Phoron Reactor" id = "mech_phoron_generator" req_tech = list(TECH_PHORON = 2, TECH_POWER= 2, TECH_ENGINEERING = 2) build_path = /obj/item/mecha_parts/mecha_equipment/generator materials = list(DEFAULT_WALL_MATERIAL = 7500, "silver" = 375, "glass" = 750) /datum/design/item/mecha/energy_relay - name = "Energy relay" + name = "Energy Relay" id = "mech_energy_relay" req_tech = list(TECH_MAGNET = 4, TECH_POWER = 3) materials = list(DEFAULT_WALL_MATERIAL = 7500, "gold" = 1500, "silver" = 2250, "glass" = 1500) build_path = /obj/item/mecha_parts/mecha_equipment/tesla_energy_relay /datum/design/item/mecha/ccw_armor - name = "CCW armor booster" + name = "CCW Armor Booster" desc = "Exosuit close-combat armor booster." id = "mech_ccw_armor" req_tech = list(TECH_MATERIAL = 5, TECH_COMBAT = 4) @@ -440,6 +432,7 @@ build_path = /obj/item/mecha_parts/mecha_equipment/anticcw_armor_booster /datum/design/item/mecha/proj_armor + name = "Ranged Armor Booster" desc = "Exosuit projectile armor booster." id = "mech_proj_armor" req_tech = list(TECH_MATERIAL = 5, TECH_COMBAT = 5, TECH_ENGINEERING = 3) @@ -447,7 +440,7 @@ build_path = /obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster /datum/design/item/mecha/diamond_drill - name = "Diamond drill" + name = "Diamond Drill" desc = "A diamond version of the exosuit drill. It's harder, better, faster, stronger." id = "mech_diamond_drill" req_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 3) @@ -455,7 +448,7 @@ build_path = /obj/item/mecha_parts/mecha_equipment/tool/drill/diamonddrill /datum/design/item/mecha/generator_nuclear - name = "Nuclear reactor" + name = "Nuclear Reactor" desc = "Exosuit-held nuclear reactor. Converts uranium and everyone's health to energy." id = "mech_generator_nuclear" req_tech = list(TECH_POWER= 3, TECH_ENGINEERING = 3, TECH_MATERIAL = 3) @@ -463,7 +456,7 @@ build_path = /obj/item/mecha_parts/mecha_equipment/generator/nuclear /datum/design/item/synthetic_flash - name = "Synthetic flash" + name = "Synthetic Flash" id = "sflash" req_tech = list(TECH_MAGNET = 3, TECH_COMBAT = 2) build_type = MECHFAB diff --git a/code/modules/research/prosfab_designs.dm b/code/modules/research/prosfab_designs.dm index 4f3c47efc79..7a191f489fc 100644 --- a/code/modules/research/prosfab_designs.dm +++ b/code/modules/research/prosfab_designs.dm @@ -63,7 +63,7 @@ var/gender = MALE /datum/design/item/prosfab/pros/torso/male - name = "FBP torso (M)" + name = "FBP Torso (M)" id = "pros_torso_m" build_path = /obj/item/organ/external/chest gender = MALE @@ -71,13 +71,13 @@ /obj/item/organ/external/chest/f //To satisfy Travis. :| /datum/design/item/prosfab/pros/torso/female - name = "FBP torso (F)" + name = "FBP Torso (F)" id = "pros_torso_f" build_path = /obj/item/organ/external/chest/f gender = FEMALE /datum/design/item/prosfab/pros/head - name = "Prosthetic head" + name = "Prosthetic Head" id = "pros_head" build_path = /obj/item/organ/external/head time = 30 @@ -85,103 +85,106 @@ // req_tech = list(TECH_ENGINEERING = 2, TECH_MATERIAL = 3, TECH_DATA = 3) //Saving the values just in case /datum/design/item/prosfab/pros/l_arm - name = "Prosthetic left arm" + name = "Prosthetic Left Arm" id = "pros_l_arm" build_path = /obj/item/organ/external/arm time = 20 materials = list(DEFAULT_WALL_MATERIAL = 10125) /datum/design/item/prosfab/pros/l_hand - name = "Prosthetic left hand" + name = "Prosthetic Left Hand" id = "pros_l_hand" build_path = /obj/item/organ/external/hand time = 15 materials = list(DEFAULT_WALL_MATERIAL = 3375) /datum/design/item/prosfab/pros/r_arm - name = "Prosthetic right arm" + name = "Prosthetic Right Arm" id = "pros_r_arm" build_path = /obj/item/organ/external/arm/right time = 20 materials = list(DEFAULT_WALL_MATERIAL = 10125) /datum/design/item/prosfab/pros/r_hand - name = "Prosthetic right hand" + name = "Prosthetic Right Hand" id = "pros_r_hand" build_path = /obj/item/organ/external/hand/right time = 15 materials = list(DEFAULT_WALL_MATERIAL = 3375) /datum/design/item/prosfab/pros/l_leg - name = "Prosthetic left leg" + name = "Prosthetic Left Leg" id = "pros_l_leg" build_path = /obj/item/organ/external/leg time = 20 materials = list(DEFAULT_WALL_MATERIAL = 8437) /datum/design/item/prosfab/pros/l_foot - name = "Prosthetic left foot" + name = "Prosthetic Left Foot" id = "pros_l_foot" build_path = /obj/item/organ/external/foot time = 15 materials = list(DEFAULT_WALL_MATERIAL = 2813) /datum/design/item/prosfab/pros/r_leg - name = "Prosthetic right leg" + name = "Prosthetic Right Leg" id = "pros_r_leg" build_path = /obj/item/organ/external/leg/right time = 20 materials = list(DEFAULT_WALL_MATERIAL = 8437) /datum/design/item/prosfab/pros/r_foot - name = "Prosthetic right foot" + name = "Prosthetic Right Foot" id = "pros_r_foot" build_path = /obj/item/organ/external/foot/right time = 15 materials = list(DEFAULT_WALL_MATERIAL = 2813) -/datum/design/item/prosfab/pros/cell - name = "Prosthetic powercell" +/datum/design/item/prosfab/pros/internal + category = "Prosthetics, Internal" + +/datum/design/item/prosfab/pros/internal/cell + name = "Prosthetic Powercell" id = "pros_cell" build_path = /obj/item/organ/internal/cell time = 15 materials = list(DEFAULT_WALL_MATERIAL = 7500, "glass" = 3000) // req_tech = list(TECH_ENGINEERING = 2, TECH_MATERIAL = 2) -/datum/design/item/prosfab/pros/eyes - name = "Prosthetic eyes" +/datum/design/item/prosfab/pros/internal/eyes + name = "Prosthetic Eyes" id = "pros_eyes" build_path = /obj/item/organ/internal/eyes/robot time = 15 materials = list(DEFAULT_WALL_MATERIAL = 5625, "glass" = 5625) // req_tech = list(TECH_ENGINEERING = 2, TECH_MATERIAL = 2) -/datum/design/item/prosfab/pros/heart - name = "Prosthetic heart" +/datum/design/item/prosfab/pros/internal/heart + name = "Prosthetic Heart" id = "pros_heart" build_path = /obj/item/organ/internal/heart time = 15 materials = list(DEFAULT_WALL_MATERIAL = 5625, "glass" = 1000) // req_tech = list(TECH_ENGINEERING = 2, TECH_MATERIAL = 2) -/datum/design/item/prosfab/pros/lungs - name = "Prosthetic lungs" +/datum/design/item/prosfab/pros/internal/lungs + name = "Prosthetic Lungs" id = "pros_lung" build_path = /obj/item/organ/internal/lungs time = 15 materials = list(DEFAULT_WALL_MATERIAL = 5625, "glass" = 1000) // req_tech = list(TECH_ENGINEERING = 2, TECH_MATERIAL = 2) -/datum/design/item/prosfab/pros/liver - name = "Prosthetic liver" +/datum/design/item/prosfab/pros/internal/liver + name = "Prosthetic Liver" id = "pros_liver" build_path = /obj/item/organ/internal/liver time = 15 materials = list(DEFAULT_WALL_MATERIAL = 5625, "glass" = 1000) // req_tech = list(TECH_ENGINEERING = 2, TECH_MATERIAL = 2) -/datum/design/item/prosfab/pros/kidneys - name = "Prosthetic liver" +/datum/design/item/prosfab/pros/internal/kidneys + name = "Prosthetic Kidneys" id = "pros_kidney" build_path = /obj/item/organ/internal/kidneys time = 15 @@ -195,49 +198,49 @@ materials = list(DEFAULT_WALL_MATERIAL = 3750) /datum/design/item/prosfab/cyborg/exoskeleton - name = "Robot exoskeleton" + name = "Robot Exoskeleton" id = "robot_exoskeleton" build_path = /obj/item/robot_parts/robot_suit time = 50 materials = list(DEFAULT_WALL_MATERIAL = 37500) /datum/design/item/prosfab/cyborg/torso - name = "Robot torso" + name = "Robot Torso" id = "robot_torso" build_path = /obj/item/robot_parts/chest time = 35 materials = list(DEFAULT_WALL_MATERIAL = 30000) /datum/design/item/prosfab/cyborg/head - name = "Robot head" + name = "Robot Head" id = "robot_head" build_path = /obj/item/robot_parts/head time = 35 materials = list(DEFAULT_WALL_MATERIAL = 18750) /datum/design/item/prosfab/cyborg/l_arm - name = "Robot left arm" + name = "Robot Left Arm" id = "robot_l_arm" build_path = /obj/item/robot_parts/l_arm time = 20 materials = list(DEFAULT_WALL_MATERIAL = 13500) /datum/design/item/prosfab/cyborg/r_arm - name = "Robot right arm" + name = "Robot Right Arm" id = "robot_r_arm" build_path = /obj/item/robot_parts/r_arm time = 20 materials = list(DEFAULT_WALL_MATERIAL = 13500) /datum/design/item/prosfab/cyborg/l_leg - name = "Robot left leg" + name = "Robot Left Leg" id = "robot_l_leg" build_path = /obj/item/robot_parts/l_leg time = 20 materials = list(DEFAULT_WALL_MATERIAL = 11250) /datum/design/item/prosfab/cyborg/r_leg - name = "Robot right leg" + name = "Robot Right Leg" id = "robot_r_leg" build_path = /obj/item/robot_parts/r_leg time = 20 @@ -252,7 +255,7 @@ materials = list(DEFAULT_WALL_MATERIAL = 7500) /datum/design/item/prosfab/cyborg/component/binary_communication_device - name = "Binary communication device" + name = "Binary Communication Device" id = "binary_communication_device" build_path = /obj/item/robot_parts/robot_component/binary_communication_device @@ -267,7 +270,7 @@ build_path = /obj/item/robot_parts/robot_component/actuator /datum/design/item/prosfab/cyborg/component/diagnosis_unit - name = "Diagnosis unit" + name = "Diagnosis Unit" id = "diagnosis_unit" build_path = /obj/item/robot_parts/robot_component/diagnosis_unit @@ -277,7 +280,7 @@ build_path = /obj/item/robot_parts/robot_component/camera /datum/design/item/prosfab/cyborg/component/armour - name = "Armour plating" + name = "Armour Plating" id = "armour" build_path = /obj/item/robot_parts/robot_component/armour @@ -290,47 +293,47 @@ materials = list(DEFAULT_WALL_MATERIAL = 7500) /datum/design/item/prosfab/robot_upgrade/rename - name = "Rename module" + name = "Rename Module" desc = "Used to rename a cyborg." id = "borg_rename_module" build_path = /obj/item/borg/upgrade/rename /datum/design/item/prosfab/robot_upgrade/reset - name = "Reset module" + name = "Reset Module" desc = "Used to reset a cyborg's module. Destroys any other upgrades applied to the robot." id = "borg_reset_module" build_path = /obj/item/borg/upgrade/reset /datum/design/item/prosfab/robot_upgrade/restart - name = "Emergency restart module" + name = "Emergency Restart Module" desc = "Used to force a restart of a disabled-but-repaired robot, bringing it back online." id = "borg_restart_module" materials = list(DEFAULT_WALL_MATERIAL = 45000, "glass" = 3750) build_path = /obj/item/borg/upgrade/restart /datum/design/item/prosfab/robot_upgrade/vtec - name = "VTEC module" + name = "VTEC Module" desc = "Used to kick in a robot's VTEC systems, increasing their speed." id = "borg_vtec_module" materials = list(DEFAULT_WALL_MATERIAL = 60000, "glass" = 4500, "gold" = 3750) build_path = /obj/item/borg/upgrade/vtec /datum/design/item/prosfab/robot_upgrade/tasercooler - name = "Rapid taser cooling module" + name = "Rapid Taser Cooling Module" desc = "Used to cool a mounted taser, increasing the potential current in it and thus its recharge rate." id = "borg_taser_module" materials = list(DEFAULT_WALL_MATERIAL = 60000, "glass" = 4500, "gold" = 1500, "diamond" = 375) build_path = /obj/item/borg/upgrade/tasercooler /datum/design/item/prosfab/robot_upgrade/jetpack - name = "Jetpack module" + name = "Jetpack Module" desc = "A carbon dioxide jetpack suitable for low-gravity mining operations." id = "borg_jetpack_module" materials = list(DEFAULT_WALL_MATERIAL = 7500, "phoron" = 11250, "uranium" = 15000) build_path = /obj/item/borg/upgrade/jetpack /datum/design/item/prosfab/robot_upgrade/syndicate - name = "Scrambled equipment module" + name = "Scrambled Equipment Module" desc = "Allows for the construction of lethal upgrades for cyborgs." id = "borg_syndicate_module" req_tech = list(TECH_COMBAT = 4, TECH_ILLEGAL = 3) @@ -338,7 +341,7 @@ build_path = /obj/item/borg/upgrade/syndicate /datum/design/item/prosfab/robot_upgrade/language - name = "language module" + name = "Language Module" desc = "Used to let cyborgs other than clerical or service speak a variety of languages." id = "borg_language_module" req_tech = list(TECH_DATA = 6, TECH_MATERIAL = 6) diff --git a/code/modules/shieldgen/shield_gen.dm b/code/modules/shieldgen/shield_gen.dm index fd8e3bf0cac..6100dda029e 100644 --- a/code/modules/shieldgen/shield_gen.dm +++ b/code/modules/shieldgen/shield_gen.dm @@ -5,7 +5,7 @@ icon_state = "generator0" var/active = 0 var/field_radius = 3 - var/max_field_radius = 100 + var/max_field_radius = 150 var/list/field = list() density = 1 var/locked = 0 @@ -323,4 +323,4 @@ T = locate(gen_turf.x + field_radius, gen_turf.y + y_offset, gen_turf.z) if (T) out += T - return out \ No newline at end of file + return out diff --git a/code/modules/shuttles/shuttle_emergency.dm b/code/modules/shuttles/shuttle_emergency.dm index 347243ae5cf..53d2570ca99 100644 --- a/code/modules/shuttles/shuttle_emergency.dm +++ b/code/modules/shuttles/shuttle_emergency.dm @@ -50,8 +50,8 @@ if (istype(user, /obj/machinery/computer/shuttle_control/emergency)) var/obj/machinery/computer/shuttle_control/emergency/C = user - //initiating or cancelling a launch ALWAYS requires authorization, but if we are already set to launch anyways than forcing does not. - //this is so that people can force launch if the docking controller cannot safely undock without needing X heads to swipe. + //Initiating or cancelling a launch ALWAYS requires authorization, but if we are already set to launch anyways than forcing does not. + //This is so that people can force launch if the docking controller cannot safely undock without needing X heads to swipe. if (!(process_state == WAIT_LAUNCH || C.has_authorization())) return 0 return ..() @@ -69,11 +69,11 @@ if (istype(user, /obj/machinery/computer/shuttle_control/emergency)) //if we were given a command by an emergency shuttle console if (emergency_shuttle.autopilot) emergency_shuttle.autopilot = 0 - world << "Alert: The shuttle autopilot has been overridden. Launch sequence initiated!" + to_chat(world, "Alert: The shuttle autopilot has been overridden. Launch sequence initiated!") if(usr) - log_admin("[key_name(usr)] has overridden the shuttle autopilot and activated launch sequence") - message_admins("[key_name_admin(usr)] has overridden the shuttle autopilot and activated launch sequence") + log_admin("[key_name(usr)] has overridden the departure shuttle's autopilot and activated the launch sequence.") + message_admins("[key_name_admin(usr)] has overridden the departure shuttle's autopilot and activated the launch sequence.") ..(user) @@ -83,11 +83,11 @@ if (istype(user, /obj/machinery/computer/shuttle_control/emergency)) //if we were given a command by an emergency shuttle console if (emergency_shuttle.autopilot) emergency_shuttle.autopilot = 0 - world << "Alert: The shuttle autopilot has been overridden. Bluespace drive engaged!" + to_chat(world, "Alert: The shuttle autopilot has been overridden. Bluespace drive engaged!") if(usr) - log_admin("[key_name(usr)] has overridden the shuttle autopilot and forced immediate launch") - message_admins("[key_name_admin(usr)] has overridden the shuttle autopilot and forced immediate launch") + log_admin("[key_name(usr)] has overridden the departure shuttle's autopilot and forced immediate launch.") + message_admins("[key_name_admin(usr)] has overridden the departure shuttle's autopilot and forced immediate launch.") ..(user) @@ -97,11 +97,11 @@ if (istype(user, /obj/machinery/computer/shuttle_control/emergency)) //if we were given a command by an emergency shuttle console if (emergency_shuttle.autopilot) emergency_shuttle.autopilot = 0 - world << "Alert: The shuttle autopilot has been overridden. Launch sequence aborted!" + to_chat(world, "Alert: The shuttle autopilot has been overridden. Launch sequence aborted!") if(usr) - log_admin("[key_name(usr)] has overridden the shuttle autopilot and cancelled launch sequence") - message_admins("[key_name_admin(usr)] has overridden the shuttle autopilot and cancelled launch sequence") + log_admin("[key_name(usr)] has overridden the departure shuttle's autopilot and cancelled the launch sequence.") + message_admins("[key_name_admin(usr)] has overridden the departure shuttle's autopilot and cancelled the launch sequence.") ..(user) @@ -117,7 +117,7 @@ return (authorized.len >= req_authorizations || emagged) /obj/machinery/computer/shuttle_control/emergency/proc/reset_authorization() - //no need to reset emagged status. If they really want to go back to the station they can. + //No need to reset emagged status. If they really want to go back to the station they can. authorized = initial(authorized) //returns 1 if the ID was accepted and a new authorization was added, 0 otherwise @@ -145,16 +145,19 @@ if (dna_hash in authorized) src.visible_message("\The [src] buzzes. That ID has already been scanned.") + playsound(src.loc, 'sound/machines/buzz-sigh.ogg', 50, 0) return 0 if (!(access_heads in access)) src.visible_message("\The [src] buzzes, rejecting [ident].") + playsound(src.loc, 'sound/machines/deniedbeep.ogg', 50, 0) return 0 src.visible_message("\The [src] beeps as it scans [ident].") + playsound(src.loc, 'sound/machines/twobeep.ogg', 50, 0) authorized[dna_hash] = auth_name if (req_authorizations - authorized.len) - world << "Alert: [req_authorizations - authorized.len] authorization\s needed to override the shuttle autopilot." + to_chat(world, "Alert: [req_authorizations - authorized.len] authorization\s needed to override the shuttle autopilot.") //TODO- Belsima, make this an announcement instead of magic. if(usr) log_admin("[key_name(usr)] has inserted [ID] into the shuttle control computer - [req_authorizations - authorized.len] authorisation\s needed") @@ -164,7 +167,7 @@ /obj/machinery/computer/shuttle_control/emergency/emag_act(var/remaining_charges, var/mob/user) if (!emagged) - user << "You short out \the [src]'s authorization protocols." + to_chat(user, "You short out \the [src]'s authorization protocols.") emagged = 1 return 1 @@ -190,11 +193,11 @@ if (shuttle.in_use) shuttle_status = "Busy." else if (!shuttle.location) - shuttle_status = "Standing-by at [station_name()]." + shuttle_status = "Standing by at [station_name()]." else - shuttle_status = "Standing-by at [using_map.dock_name]." + shuttle_status = "Standing by at [using_map.dock_name]." if(WAIT_LAUNCH, FORCE_LAUNCH) - shuttle_status = "Shuttle has recieved command and will depart shortly." + shuttle_status = "Shuttle has received command and will depart shortly." if(WAIT_ARRIVE) shuttle_status = "Proceeding to destination." if(WAIT_FINISH) diff --git a/code/modules/shuttles/shuttles_multi.dm b/code/modules/shuttles/shuttles_multi.dm index 85155f61198..043d066e809 100644 --- a/code/modules/shuttles/shuttles_multi.dm +++ b/code/modules/shuttles/shuttles_multi.dm @@ -174,7 +174,7 @@ return if (MS.moving_status != SHUTTLE_IDLE) - usr << "[shuttle_tag] vessel is moving." + to_chat(usr, "[shuttle_tag] vessel is moving.") return if(href_list["dock_command"]) @@ -187,11 +187,11 @@ if(href_list["start"]) if(MS.at_origin) - usr << "You are already at your home base." + to_chat(usr, "You are already at the home base.") return if((MS.last_move + MS.cooldown*10) > world.time) - usr << "The ship's drive is inoperable while the engines are charging." + to_chat(usr, "The ship's drive is inoperable while the engines are charging.") return if(!check_docking(MS)) @@ -214,11 +214,11 @@ if(!MS.can_cloak) return MS.cloaked = !MS.cloaked - usr << "Ship stealth systems have been [(MS.cloaked ? "activated. The station will not" : "deactivated. The station will")] be warned of our arrival." + to_chat(usr, "Ship stealth systems have been [(MS.cloaked ? "activated. The station will not" : "deactivated. The station will")] be warned of our arrival.") if(href_list["move_multi"]) if((MS.last_move + MS.cooldown*10) > world.time) - usr << "The ship's drive is inoperable while the engines are charging." + to_chat(usr, "The ship's drive is inoperable while the engines are charging.") return if(!check_docking(MS)) @@ -228,7 +228,7 @@ var/choice = input("Select a destination.") as null|anything in MS.destinations if(!choice) return - usr << "[shuttle_tag] main computer recieved message." + to_chat(usr, "[shuttle_tag] main computer received message.") if(MS.at_origin) MS.announce_arrival() diff --git a/code/modules/tables/presets.dm b/code/modules/tables/presets.dm index 688bff4def4..06fca651383 100644 --- a/code/modules/tables/presets.dm +++ b/code/modules/tables/presets.dm @@ -90,6 +90,23 @@ material = get_material_by_name("holowood") ..() +/obj/structure/table/alien + name = "alien table" + desc = "Advanced flat surface technology at work!" + icon_state = "alien_preview" + can_reinforce = FALSE + can_plate = FALSE + +/obj/structure/table/alien/New() + material = get_material_by_name("alium") + verbs -= /obj/structure/table/verb/do_flip + verbs -= /obj/structure/table/proc/do_put + ..() + +/obj/structure/table/alien/dismantle(obj/item/weapon/wrench/W, mob/user) + to_chat(user, "You cannot dismantle \the [src].") + return + //BENCH PRESETS /obj/structure/table/bench/standard icon_state = "plain_preview" diff --git a/code/modules/xenoarcheaology/tools/tools.dm b/code/modules/xenoarcheaology/tools/tools.dm index d3ab8d07d61..1d79a894497 100644 --- a/code/modules/xenoarcheaology/tools/tools.dm +++ b/code/modules/xenoarcheaology/tools/tools.dm @@ -1,17 +1,3 @@ -/obj/item/device/gps - name = "relay positioning device" - desc = "Triangulates the approximate co-ordinates using a nearby satellite network." - icon = 'icons/obj/device.dmi' - icon_state = "locator" - item_state = "locator" - origin_tech = list(TECH_MATERIAL = 2, TECH_DATA = 2, TECH_BLUESPACE = 2) - matter = list(DEFAULT_WALL_MATERIAL = 500) - w_class = ITEMSIZE_SMALL - -/obj/item/device/gps/attack_self(var/mob/user as mob) - var/turf/T = get_turf(src) - user << "\icon[src] \The [src] flashes [T.x]:[T.y]:[T.z]." - /obj/item/device/measuring_tape name = "measuring tape" desc = "A coiled metallic tape used to check dimensions and lengths." diff --git a/code/stylesheet.dm b/code/stylesheet.dm index 5b3cb80b151..f42f2dcf051 100644 --- a/code/stylesheet.dm +++ b/code/stylesheet.dm @@ -24,6 +24,7 @@ em {font-style: normal;font-weight: bold;} .ooc .moderator {color: #184880;} .ooc .developer {color: #1b521f;} .ooc .admin {color: #b82e00;} +.ooc .event_manager {color: #660033;} .ooc .aooc {color: #960018;} /* Admin: Private Messages */ @@ -36,7 +37,7 @@ em {font-style: normal;font-weight: bold;} .mod_channel {color: #735638; font-weight: bold;} .mod_channel .admin {color: #b82e00; font-weight: bold;} .admin_channel {color: #9611D4; font-weight: bold;} -.event_channel {color: #009933; font-weight: bold;} +.event_channel {color: #cc3399; font-weight: bold;} /* Radio: Misc */ .deadsay {color: #530FAD;} diff --git a/code/unit_tests/map_tests.dm b/code/unit_tests/map_tests.dm index f8f735f8676..25f6f7557a9 100644 --- a/code/unit_tests/map_tests.dm +++ b/code/unit_tests/map_tests.dm @@ -12,8 +12,9 @@ /area/holodeck, /area/supply/station, /area/mine, - /area/vacant/vacant_shop - ) + /area/vacant/vacant_shop, + /area/turbolift, + /area/submap ) var/list/exempt_from_atmos = typesof(/area/maintenance, /area/storage, @@ -33,6 +34,11 @@ /area/vacant/vacant_shop ) + // Some maps have areas specific to the map, so include those. + exempt_areas += using_map.unit_test_exempt_areas + exempt_from_atmos += using_map.unit_test_exempt_from_atmos + exempt_from_apc += using_map.unit_test_exempt_from_apc + for(var/area/A in world) if(A.z == 1 && !(A.type in exempt_areas)) area_test_count++ diff --git a/html/changelog.html b/html/changelog.html index cb2923c0f14..610d80aa387 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -53,6 +53,20 @@ -->
+

06 November 2017

+

Atermonera updated:

+ +

Woodrat updated:

+ +

24 September 2017

Belsima updated:

diff --git a/nano/templates/crew_monitor.tmpl b/nano/templates/crew_monitor.tmpl index 74467e4b0f2..bf02a98b8ea 100644 --- a/nano/templates/crew_monitor.tmpl +++ b/nano/templates/crew_monitor.tmpl @@ -26,7 +26,7 @@ Used In File(s): \code\game\machinery\computer\crew.dm {{else value.sensor_type == 2}} {{:value.name}} ({{:value.assignment}}){{:value.dead ? "Deceased" : "Living"}} ({{:value.oxy}}/{{:value.tox}}/{{:value.fire}}/{{:value.brute}})Not Available{{if data.isAI}}{{:helper.link('Track', null, {}, 'disabled')}}{{/if}} {{else value.sensor_type == 3}} - {{:value.name}} ({{:value.assignment}}){{:value.dead ? "Deceased" : "Living"}} ({{:value.oxy}}/{{:value.tox}}/{{:value.fire}}/{{:value.brute}}){{:value.area}}({{:value.x}}, {{:value.y}}){{if data.isAI}}{{:helper.link('Track', null, {'track' : value.ref})}}{{/if}} + {{:value.name}} ({{:value.assignment}}){{:value.dead ? "Deceased" : "Living"}} ({{:value.oxy}}/{{:value.tox}}/{{:value.fire}}/{{:value.brute}}){{:value.area}}({{:value.x}}, {{:value.y}}, {{:value.z}}){{if data.isAI}}{{:helper.link('Track', null, {'track' : value.ref})}}{{/if}} {{/if}} {{/for}} diff --git a/nano/templates/request_console.tmpl b/nano/templates/request_console.tmpl index f14e27190fa..bd94cf79878 100644 --- a/nano/templates/request_console.tmpl +++ b/nano/templates/request_console.tmpl @@ -73,7 +73,7 @@ Used In File(s): \code\game\machinery\requests_console.dm {{for data.message_log}}
{{:value}}
{{empty}} -
No messages have been recieved.
+
No messages have been received.
{{/for}}
{{:helper.link('Back', 'arrowreturnthick-1-w', { 'setScreen' : 0 })}}
diff --git a/polaris.dme b/polaris.dme index 72c09371d38..2047d7db605 100644 --- a/polaris.dme +++ b/polaris.dme @@ -11,6 +11,7 @@ // END_PREFERENCES // BEGIN_INCLUDE #include "code\_macros.dm" +#include "code\_map_tests.dm" #include "code\_unit_tests.dm" #include "code\global.dm" #include "code\hub.dm" @@ -402,6 +403,7 @@ #include "code\game\gamemodes\changeling\powers\enfeebling_string.dm" #include "code\game\gamemodes\changeling\powers\engorged_glands.dm" #include "code\game\gamemodes\changeling\powers\epinephrine_overdose.dm" +#include "code\game\gamemodes\changeling\powers\escape_restraints.dm" #include "code\game\gamemodes\changeling\powers\extract_dna_sting.dm" #include "code\game\gamemodes\changeling\powers\fabricate_clothing.dm" #include "code\game\gamemodes\changeling\powers\fake_death.dm" @@ -614,8 +616,10 @@ #include "code\game\machinery\supplybeacon.dm" #include "code\game\machinery\syndicatebeacon.dm" #include "code\game\machinery\teleporter.dm" +#include "code\game\machinery\transportpod.dm" #include "code\game\machinery\turret_control.dm" #include "code\game\machinery\vending.dm" +#include "code\game\machinery\vr_console.dm" #include "code\game\machinery\wall_frames.dm" #include "code\game\machinery\washing_machine.dm" #include "code\game\machinery\wishgranter.dm" @@ -804,6 +808,7 @@ #include "code\game\objects\items\contraband.dm" #include "code\game\objects\items\crayons.dm" #include "code\game\objects\items\glassjar.dm" +#include "code\game\objects\items\gunbox.dm" #include "code\game\objects\items\latexballoon.dm" #include "code\game\objects\items\paintkit.dm" #include "code\game\objects\items\shooting_range.dm" @@ -819,6 +824,7 @@ #include "code\game\objects\items\devices\flashlight.dm" #include "code\game\objects\items\devices\floor_painter.dm" #include "code\game\objects\items\devices\geiger.dm" +#include "code\game\objects\items\devices\gps.dm" #include "code\game\objects\items\devices\hacktool.dm" #include "code\game\objects\items\devices\lightreplacer.dm" #include "code\game\objects\items\devices\locker_painter.dm" @@ -885,7 +891,6 @@ #include "code\game\objects\items\weapons\paint.dm" #include "code\game\objects\items\weapons\paiwire.dm" #include "code\game\objects\items\weapons\policetape.dm" -#include "code\game\objects\items\weapons\power_cells.dm" #include "code\game\objects\items\weapons\RCD.dm" #include "code\game\objects\items\weapons\RSF.dm" #include "code\game\objects\items\weapons\scrolls.dm" @@ -984,6 +989,7 @@ #include "code\game\objects\items\weapons\tanks\tank_types.dm" #include "code\game\objects\items\weapons\tanks\tanks.dm" #include "code\game\objects\random\random.dm" +#include "code\game\objects\structures\alien_props.dm" #include "code\game\objects\structures\barsign.dm" #include "code\game\objects\structures\bedsheet_bin.dm" #include "code\game\objects\structures\catwalk.dm" @@ -993,6 +999,7 @@ #include "code\game\objects\structures\door_assembly.dm" #include "code\game\objects\structures\electricchair.dm" #include "code\game\objects\structures\extinguisher.dm" +#include "code\game\objects\structures\fitness.dm" #include "code\game\objects\structures\flora.dm" #include "code\game\objects\structures\girders.dm" #include "code\game\objects\structures\gravemarker.dm" @@ -1078,6 +1085,8 @@ #include "code\game\turfs\simulated\wall_types.dm" #include "code\game\turfs\simulated\walls.dm" #include "code\game\turfs\simulated\water.dm" +#include "code\game\turfs\simulated\dungeon\floor.dm" +#include "code\game\turfs\simulated\dungeon\wall.dm" #include "code\game\turfs\simulated\outdoors\dirt.dm" #include "code\game\turfs\simulated\outdoors\grass.dm" #include "code\game\turfs\simulated\outdoors\outdoors.dm" @@ -1731,6 +1740,7 @@ #include "code\modules\mob\living\carbon\human\species\station\prometheans.dm" #include "code\modules\mob\living\carbon\human\species\station\seromi.dm" #include "code\modules\mob\living\carbon\human\species\station\station.dm" +#include "code\modules\mob\living\carbon\human\species\virtual_reality\avatar.dm" #include "code\modules\mob\living\carbon\human\species\xenomorphs\alien_powers.dm" #include "code\modules\mob\living\carbon\human\species\xenomorphs\alien_species.dm" #include "code\modules\mob\living\carbon\human\species\xenomorphs\xenomorphs.dm" @@ -1959,6 +1969,8 @@ #include "code\modules\power\antimatter\containment_jar.dm" #include "code\modules\power\antimatter\control.dm" #include "code\modules\power\antimatter\shielding.dm" +#include "code\modules\power\cells\device_cells.dm" +#include "code\modules\power\cells\power_cells.dm" #include "code\modules\power\fusion\_setup.dm" #include "code\modules\power\fusion\fusion_circuits.dm" #include "code\modules\power\fusion\fusion_particle_catcher.dm" @@ -2334,7 +2346,7 @@ #include "code\ZAS\Zone.dm" #include "interface\interface.dm" #include "interface\skin.dmf" -#include "maps\northern_star\northern_star.dm" +#include "maps\southern_cross\southern_cross.dm" #include "maps\submaps\_readme.dm" #include "maps\submaps\cave_submaps\cave.dm" #include "maps\submaps\cave_submaps\cave_areas.dm" diff --git a/sound/effects/weightdrop.ogg b/sound/effects/weightdrop.ogg new file mode 100644 index 00000000000..07945daaf86 Binary files /dev/null and b/sound/effects/weightdrop.ogg differ diff --git a/sound/effects/weightlifter.ogg b/sound/effects/weightlifter.ogg new file mode 100644 index 00000000000..51a0d497854 Binary files /dev/null and b/sound/effects/weightlifter.ogg differ diff --git a/sound/items/geiger1.ogg b/sound/items/geiger1.ogg new file mode 100644 index 00000000000..b8220856594 Binary files /dev/null and b/sound/items/geiger1.ogg differ diff --git a/sound/items/geiger2.ogg b/sound/items/geiger2.ogg new file mode 100644 index 00000000000..4c0d734463c Binary files /dev/null and b/sound/items/geiger2.ogg differ diff --git a/sound/items/geiger3.ogg b/sound/items/geiger3.ogg new file mode 100644 index 00000000000..a9a5924d80c Binary files /dev/null and b/sound/items/geiger3.ogg differ diff --git a/sound/items/geiger4.ogg b/sound/items/geiger4.ogg new file mode 100644 index 00000000000..dfad69866cc Binary files /dev/null and b/sound/items/geiger4.ogg differ diff --git a/sound/items/geiger5.ogg b/sound/items/geiger5.ogg new file mode 100644 index 00000000000..1e5f20913cb Binary files /dev/null and b/sound/items/geiger5.ogg differ diff --git a/sound/items/geiger_weak1.ogg b/sound/items/geiger_weak1.ogg new file mode 100644 index 00000000000..cadfcde746c Binary files /dev/null and b/sound/items/geiger_weak1.ogg differ diff --git a/sound/items/geiger_weak2.ogg b/sound/items/geiger_weak2.ogg new file mode 100644 index 00000000000..12f54ae6698 Binary files /dev/null and b/sound/items/geiger_weak2.ogg differ diff --git a/sound/items/geiger_weak3.ogg b/sound/items/geiger_weak3.ogg new file mode 100644 index 00000000000..c935711aacf Binary files /dev/null and b/sound/items/geiger_weak3.ogg differ diff --git a/sound/items/geiger_weak4.ogg b/sound/items/geiger_weak4.ogg new file mode 100644 index 00000000000..2b17311a825 Binary files /dev/null and b/sound/items/geiger_weak4.ogg differ