diff --git a/.travis.yml b/.travis.yml index b6eb33966b..edd9984f84 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 4433478e32..7b28d52688 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 3c0e190427..2e14fb96eb 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 9419415e1c..13b1bfd795 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 0000000000..90a4004b79 --- /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 063d6d3fb9..f9fd57f788 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 5056e82e7b..4ca4bebf0a 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 e92a0447c8..d6f4b3c9c5 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 a79bf09d95..c52c904bc5 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 ab102d2a8b..afbd7278e0 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 cbe52301df..4ca0ae51d5 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 b4d51ed1b5..fef3f3e350 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 658ed5562f..dda9aa4ed4 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 d644a9eaa8..c0b7600aad 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 250d4b6412..558c922b46 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 596ac1451e..190488b38c 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 d9796432c0..08d411aec9 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 b7210f22a3..e4bd3b85ea 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 e54eb3c1cd..b0f19c3ba3 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 396e6faf34..0af67b22ed 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 139950e900..5ab724789b 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 0000000000..4e6ed4e5cf --- /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 ca1d5639e9..8db7a49255 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 38316a6c50..0885cdef60 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 48f0f02bfc..65ad3d7f01 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 e85af7e82b..f7233c1266 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 39d3f739d7..850f061250 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 05afae4a3b..f11c027566 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 c0012c991c..320374542d 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 e47b62c031..306de85043 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 e786134b4c..fa7b5f34b9 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 322a71f7d4..b63662cd86 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 f74b1d6185..a0ac2f646c 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 1aadf981c4..4f6b7df94f 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 4d29a56b89..f91ac2b677 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 acd7a446c1..87da7c7ac6 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 45501a3de7..434f7e64cb 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 1b181aebb5..fe0ebfdb2f 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 65ef3edc65..7a2aed9770 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 30a0743e09..7f76bc978c 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 3441b09cbb..0f58bd9a48 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 0000000000..96401c0908 --- /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 fdab318780..960ac923eb 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 0000000000..79fdf882fa --- /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 6aec830c89..38c3cffb30 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 547406aa1d..b8cb8006d2 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 94c0a7999f..4cc39d4e67 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 6b4a09c6a5..8b00612641 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 16e27006b4..a23abb5b06 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 cd1484548c..e4932793a1 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 dd10e80859..083f83c1c9 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 62cb9d9862..dbac918609 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 0000000000..18fc47b617 --- /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 35f41730df..8fd96981fc 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 53d647a4f0..ca4b8d8066 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 0000000000..add1530ca4 --- /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 dde2f168b0..d878dd74fe 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 95803696d4..63a0df6d32 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 6065d6a514..62f02816ed 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 fa48be65bb..b22c4ca649 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 0b4700ca6a..897ac43ff4 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 f075ea49f9..e0975361eb 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 9545504f84..7b6e6184f1 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 38130f2739..6d261a8b3f 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 db55e95b44..a3ca9a4601 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 8391c90434..ec3f3e2631 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 b991db0510..33ed9f96e1 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 2c56cd690b..045f910190 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 6a6d77521e..0312ca55f8 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 c15b454878..d23f18e9bb 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 0000000000..cb791ec54b --- /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 fe838a5291..0af7913df8 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 3a6b7ac045..8ebd9358b5 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 92bc2ab469..9e5f0b7815 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 d863aecd24..83aa687957 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 7d1810c46f..f63290c010 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 0000000000..3bb158a576 --- /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 7beba29caa..9eeefeee61 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 8271c3a0d5..42b7884169 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 daa6e8c94a..0d92af11b2 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 42ee6af2e3..c457e3ae2c 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 dacd1013c4..3b36cb0087 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 ea52ed3845..7000e39974 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 0e577bb36b..ad2ce1be82 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 0e6064785d..d1f2753e52 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 028e0af3dc..49f3bb8437 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 c23614942b..afeeaafcae 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 0000000000..743b497878 --- /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 0000000000..b6a8f53c27 --- /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 9a7fec800a..4bc4911f2e 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 e62ba0d7f4..723998d4da 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 6693c45874..1870f8bd81 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 e5c6465329..941aa5abc9 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 ce4451ff12..19264e23ba 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 8e32a004d9..6f2c606c0d 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 d34b210b99..10cee9b6b7 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 fa6dec5715..8fafb555a3 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 121e355d22..61f2d174ac 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 b6d0abbe1c..473770ac2b 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 2503c73abb..0b02b98ef3 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 1531790268..92536a6e05 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 63209f84b4..264e5ad64e 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 c14c74edd1..b80d95e3c1 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 b8bc38b291..da08c70c4a 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 c6500143f0..73d91129e7 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 6bc944552c..bf1796ea29 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 6f3115fd2f..860869883f 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 f7737c9dde..bbaca4c363 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 ba2d995b27..6b15fba5ea 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 0431ac611b..86b8ede6f7 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 94ed2c9f87..d7e0362272 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 66827de346..8527e8b501 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 cc3f276566..85f51e2cdd 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 4facc9fef7..299680b864 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 88206f4132..40dd1c7242 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 6b4b270f97..85ffb970b8 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 c1c833a308..8ee0ae2d32 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 075411cd29..31e08a9f35 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 31830fb275..3c5dc32e68 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 934d7407d9..dfc416aa69 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 ccba8986d5..245ebc5436 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 864ee369ba..97fc8721a8 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 602b854287..5819a5e065 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 1176b91089..b7b3b2b0b3 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 4392a26492..5d18858cc3 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 3f53c44392..bf40074a2a 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 f9a0a9ab37..ddfb109ef6 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 322115cc0b..c306d842d0 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 f99317b7d0..5ec18a4859 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 a2cc9aafb9..84a187ef91 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 edfa6b1a86..e31b26fbb1 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 c22d65e421..8621e2b7ed 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 6128418c1f..595a205318 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 08765b94e5..0f702be3de 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 c417c3e4fd..0a516e360a 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 7b5846eb8d..e490ccd27a 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 d752f0d5cd..8da4fad6d8 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 84e0724bb9..943141b071 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 fa4fd9ded6..40f617e62e 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 f528434129..e1e3f56c89 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 25a80c2a28..e6d65bd07a 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 3aaf324463..54b08c74d9 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 c0c1eecd9e..7408b692a7 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 0db3a1016e..1ce1eca2d8 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 ee6d914fa6..3facabe6f9 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 824343c41c..3e9e8278e4 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 83bf724607..52426454e2 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 e201e85116..c120b9deef 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 ebcd4d7774..8a2b24cf50 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 9bf9e62dfb..3adf6b34f0 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 fecf9b12c0..aa178f93c1 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 194864b7de..233f0f020f 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 66ba7ecd51..08d0c9384e 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 101390b3d6..3b83f1e8c2 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 ffac791a1f..8df0bd1605 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 615a3ecf53..81ea775ab9 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 ab16e58263..d7e7f2a169 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 7d0b2ea7fa..45532aa1d4 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 a09dad7dba..fbb98c3f98 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 bf43aadf6a..684978e07d 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 bb5d989e45..61bded2e15 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 1fb7b6c300..f1f36322a2 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 5ab786f8f6..7d1ed3bb0e 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 f07ff9b119..372451808e 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 0000000000..8fbf47022d --- /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 0909ed2575..ebaa6866e0 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 22289c6b43..07997851ef 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 5b2800b130..01bb524431 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 ad3a41fbc8..b48a1609d9 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 29e3e86caf..1e0d988835 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 f516486f02..6c3cd7f1db 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 1ff5605946..cc655908e9 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 1b8f439f50..87df901527 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 32a5a9cb35..231db2866a 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 92a8b3bdeb..6063526c89 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 56104d34f4..b7fdd7714d 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 5fa306b7b9..a96524f1f1 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 42bc1280e2..4b729f0a70 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 f756b71efa..01d7008a09 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 28fbf62f1e..7dd2bd948e 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 a547a2539f..19652a6376 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 a3fdc511fc..43b3a4c4d7 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 915258e112..77706b9517 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 48759ae1cf..3c986b16fd 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 90567f2363..d1eb81cc7f 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 5199b3e3eb..05d1a6d8c6 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 b17bdf29f2..6ed6ad93fc 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 778abc4ee0..92076c0b15 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 0af9770434..bdea8fed70 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 990c97b1c2..1de92fe743 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 dcb6d140ec..1e84126fe7 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 eb142aac1e..39ce99d188 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 2c1699c5f6..7a8c7c541f 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 0000000000..822370a6b1 --- /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 2b63fb79bd..a9b92a9bb3 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 b8a123e02f..8127383651 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 342e10db84..9af8597c9b 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 ed06df7cc2..330e11d89b 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 0bdf518a2c..447eefe1b8 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 cb93992acc..40e1f55277 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 e7dd400f59..048dddfe3f 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 d613f1f206..18a25e5daf 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 c8bba19087..43bb9e1637 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 8916524344..bb6d14d1ee 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 e545ebb848..9a9f0b4bd6 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 81355d1031..20671d6fd5 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 d3a846ab08..ecc8a1a904 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 fdc5a445b9..2040b0a778 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 a271684f7c..32dce8e3b9 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 283e487272..a7132fa43b 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 049bdcaf78..8c5d2cd11a 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 4868e6d068..e1f2092bdb 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 c71a7de362..d61ace5b17 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 44dce0a7ad..dbc6f17a5d 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 5c5d0cc3a6..604eaa6a3a 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 6312d08d84..88b6d9d064 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 708cc4e081..b7dd370190 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 4d7149c188..8efeec6c0d 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 4f3c47efc7..7a191f489f 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 fd8e3bf0ca..6100dda029 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 347243ae5c..53d2570ca9 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 85155f6119..043d066e80 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 688bff4def..06fca65138 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 d3ab8d07d6..1d79a89449 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 5b3cb80b15..f42f2dcf05 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 f8f735f867..25f6f7557a 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 cb2923c0f1..610d80aa38 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 74467e4b0f..bf02a98b8e 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 f14e27190f..bd94cf7987 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 72c09371d3..2047d7db60 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 0000000000..07945daaf8 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 0000000000..51a0d49785 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 0000000000..b822085659 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 0000000000..4c0d734463 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 0000000000..a9a5924d80 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 0000000000..dfad69866c 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 0000000000..1e5f20913c 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 0000000000..cadfcde746 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 0000000000..12f54ae669 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 0000000000..c935711aac 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 0000000000..2b17311a82 Binary files /dev/null and b/sound/items/geiger_weak4.ogg differ