diff --git a/.travis.yml b/.travis.yml index b6eb33966b7..edd9984f84c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,9 +36,14 @@ script: - (num=`grep -E '\\\\(red|blue|green|black|b|i[^mc])' **/*.dm | wc -l`; echo "$num escapes (expecting ${MACRO_COUNT} or less)"; [ $num -le ${MACRO_COUNT} ]) - source $HOME/BYOND-${BYOND_MAJOR}.${BYOND_MINOR}/byond/bin/byondsetup - python tools/TagMatcher/tag-matcher.py ../.. - - echo "#define UNIT_TEST 1" > code/_unit_tests.dm + #First compile is to ensure maps are valid. + - echo "#define MAP_TEST 1" > code/_map_tests.dm - cp config/example/* config/ - DreamMaker polaris.dme + - echo "#define MAP_TEST 0" > code/_map_tests.dm + #Second compile is for the unit tests. Compiling a second time to exclude the validated maps is actually faster than waiting for startup with them compiled. + - echo "#define UNIT_TEST 1" > code/_unit_tests.dm + - DreamMaker polaris.dme - DreamDaemon polaris.dmb -invisible -trusted -core 2>&1 | tee log.txt - grep "All Unit Tests Passed" log.txt diff --git a/code/ZAS/Diagnostic.dm b/code/ZAS/Diagnostic.dm index 10ec2e731b5..cbf35d93bde 100644 --- a/code/ZAS/Diagnostic.dm +++ b/code/ZAS/Diagnostic.dm @@ -4,7 +4,7 @@ client/proc/ZoneTick() var/result = air_master.Tick() if(result) - src << "Sucessfully Processed." + src << "Successfully Processed." else src << "Failed to process! ([air_master.tick_progress])" diff --git a/code/__defines/damage_organs.dm b/code/__defines/damage_organs.dm index 3c0e190427b..2e14fb96eb6 100644 --- a/code/__defines/damage_organs.dm +++ b/code/__defines/damage_organs.dm @@ -6,6 +6,7 @@ #define OXY "oxy" #define CLONE "clone" #define HALLOSS "halloss" +#define ELECTROCUTE "electrocute" #define CUT "cut" #define BRUISE "bruise" @@ -56,3 +57,4 @@ #define INFECTION_LEVEL_ONE 100 #define INFECTION_LEVEL_TWO 500 #define INFECTION_LEVEL_THREE 1000 +#define INFECTION_LEVEL_MAX 1500 \ No newline at end of file diff --git a/code/__defines/map.dm b/code/__defines/map.dm index 9419415e1c1..13b1bfd7955 100644 --- a/code/__defines/map.dm +++ b/code/__defines/map.dm @@ -6,3 +6,6 @@ #define MAP_LEVEL_SEALED 0x010 // Z-levels that don't allow random transit at edge #define MAP_LEVEL_EMPTY 0x020 // Empty Z-levels that may be used for various things (currently used by bluespace jump) #define MAP_LEVEL_CONSOLES 0x040 // Z-levels available to various consoles, such as the crew monitor (when that gets coded in). Defaults to station_levels if unset. + +// Misc map defines. +#define SUBMAP_MAP_EDGE_PAD 15 // Automatically created submaps are forbidden from being this close to the main map's edge. \ No newline at end of file diff --git a/code/_map_tests.dm b/code/_map_tests.dm new file mode 100644 index 00000000000..90a4004b792 --- /dev/null +++ b/code/_map_tests.dm @@ -0,0 +1,10 @@ +/* + * + * This file is used by Travis to indicate that additional maps need to be compiled to look for errors such as missing paths. + * Do not add anything but the MAP_TEST definition here as it will be overwritten by Travis when running tests. + * + * + * Should you wish to edit set MAP_TEST to 1 like so: + * #define MAP_TEST 1 + */ +#define MAP_TEST 0 diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index 8fec6c9c010..afb0e6c44aa 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -108,7 +108,7 @@ W.afterattack(A, src, 1, params) // 1 indicates adjacency else if(ismob(A)) // No instant mob attacking - setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + setClickCooldown(get_attack_speed()) UnarmedAttack(A, 1) trigger_aiming(TARGET_CAN_CLICK) @@ -129,7 +129,7 @@ W.afterattack(A, src, 1, params) // 1: clicking something Adjacent else if(ismob(A)) // No instant mob attacking - setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + setClickCooldown(get_attack_speed()) UnarmedAttack(A, 1) trigger_aiming(TARGET_CAN_CLICK) return diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index 68f113e30c6..5808fc44984 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -51,6 +51,22 @@ avoid code duplication. This includes items that may sometimes act as a standard return 0 return I.attack(src, user, user.zone_sel.selecting) +// Used to get how fast a mob should attack, and influences click delay. +// This is just for inheritence. +/mob/proc/get_attack_speed() + return DEFAULT_ATTACK_COOLDOWN + +// Same as above but actually does useful things. +// W is the item being used in the attack, if any. modifier is if the attack should be longer or shorter than usual, for whatever reason. +/mob/living/get_attack_speed(var/obj/item/W) + var/speed = DEFAULT_ATTACK_COOLDOWN + if(W && istype(W)) + speed = W.attackspeed + for(var/datum/modifier/M in modifiers) + if(!isnull(M.attack_speed_percent)) + speed *= M.attack_speed_percent + return speed + // Proximity_flag is 1 if this afterattack was called on something adjacent, in your square, or on your person. // Click parameters is the params string from byond Click() code, see that documentation. /obj/item/proc/afterattack(atom/target, mob/user, proximity_flag, click_parameters) @@ -73,7 +89,7 @@ avoid code duplication. This includes items that may sometimes act as a standard msg_admin_attack("[key_name(user)] attacked [key_name(M)] with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])" ) ///////////////////////// - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(src)) user.do_attack_animation(M) var/hit_zone = M.resolve_item_attack(src, user, target_zone) diff --git a/code/_onclick/other_mobs.dm b/code/_onclick/other_mobs.dm index 8cf8948bb7e..a80ff05eac1 100644 --- a/code/_onclick/other_mobs.dm +++ b/code/_onclick/other_mobs.dm @@ -59,7 +59,7 @@ if(!..()) return 0 - setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + setClickCooldown(get_attack_speed()) A.attack_generic(src,rand(5,6),"bitten") /* @@ -87,7 +87,7 @@ custom_emote(1,"[friendly] [A]!") return - setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + setClickCooldown(get_attack_speed()) if(isliving(A)) target_mob = A PunchTarget() @@ -96,7 +96,7 @@ A.attack_generic(src, rand(melee_damage_lower, melee_damage_upper), attacktext) /mob/living/simple_animal/RangedAttack(var/atom/A) - setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + setClickCooldown(get_attack_speed()) var/distance = get_dist(src, A) if(prob(spattack_prob) && (distance >= spattack_min_range) && (distance <= spattack_max_range)) diff --git a/code/_onclick/rig.dm b/code/_onclick/rig.dm index 436e7353ec7..5f2561c25c7 100644 --- a/code/_onclick/rig.dm +++ b/code/_onclick/rig.dm @@ -74,7 +74,7 @@ return 0 rig.selected_module.engage(A, alert_ai) if(ismob(A)) // No instant mob attacking - though modules have their own cooldowns - setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + setClickCooldown(get_attack_speed()) return 1 return 0 diff --git a/code/controllers/Processes/planet.dm b/code/controllers/Processes/planet.dm index 063d6d3fb9b..f9fd57f7889 100644 --- a/code/controllers/Processes/planet.dm +++ b/code/controllers/Processes/planet.dm @@ -51,9 +51,10 @@ var/datum/controller/process/planet/planet_controller = null //Redraw weather icons for(var/T in P.planet_floors) var/turf/simulated/turf = T - turf.overlays -= turf.weather_overlay + // turf.overlays -= turf.weather_overlay turf.weather_overlay = new_overlay - turf.overlays += turf.weather_overlay + // turf.overlays += turf.weather_overlay + turf.update_icon() SCHECK //Sun light needs changing diff --git a/code/controllers/master.dm b/code/controllers/master.dm index 5056e82e7b6..4ca4bebf0a8 100644 --- a/code/controllers/master.dm +++ b/code/controllers/master.dm @@ -540,10 +540,10 @@ var/datum/controller/master/Master = new() stat("Byond:", "(FPS:[world.fps]) (TickCount:[world.time/world.tick_lag]) (TickDrift:[round(Master.tickdrift,1)]([round((Master.tickdrift/(world.time/world.tick_lag))*100,0.1)]%))") stat("Master Controller:", statclick.update("(TickRate:[Master.processing]) (Iteration:[Master.iteration])")) -/datum/controller/master/StartLoadingMap() +/datum/controller/master/StartLoadingMap(var/quiet = TRUE) if(map_loading) admin_notice("Another map is attempting to be loaded before first map released lock. Delaying.", R_DEBUG) - else + else if(!quiet) admin_notice("Map is now being built. Locking.", R_DEBUG) //disallow more than one map to load at once, multithreading it will just cause race conditions @@ -557,8 +557,9 @@ var/datum/controller/master/Master = new() air_processing_killed = TRUE map_loading = TRUE -/datum/controller/master/StopLoadingMap(bounds = null) - admin_notice("Map is finished. Unlocking.", R_DEBUG) +/datum/controller/master/StopLoadingMap(var/quiet = TRUE) + if(!quiet) + admin_notice("Map is finished. Unlocking.", R_DEBUG) air_processing_killed = FALSE map_loading = FALSE for(var/S in subsystems) diff --git a/code/controllers/subsystems/creation.dm b/code/controllers/subsystems/creation.dm index e92a0447c82..d6f4b3c9c55 100644 --- a/code/controllers/subsystems/creation.dm +++ b/code/controllers/subsystems/creation.dm @@ -13,10 +13,10 @@ SUBSYSTEM_DEF(creation) var/map_loading = FALSE -/datum/controller/subsystem/creation/StartLoadingMap() +/datum/controller/subsystem/creation/StartLoadingMap(var/quiet) map_loading = TRUE -/datum/controller/subsystem/creation/StopLoadingMap() +/datum/controller/subsystem/creation/StopLoadingMap(var/quiet) map_loading = FALSE /datum/controller/subsystem/creation/proc/initialize_late_atoms() diff --git a/code/datums/autolathe/arms.dm b/code/datums/autolathe/arms.dm index a79bf09d951..c52c904bc58 100644 --- a/code/datums/autolathe/arms.dm +++ b/code/datums/autolathe/arms.dm @@ -147,17 +147,27 @@ name = "rifle magazine (5.45mm practice)" path =/obj/item/ammo_magazine/m545/practice +/datum/category_item/autolathe/arms/rifle_545_hunter + name = "rifle magazine (5.45mm hunting)" + path =/obj/item/ammo_magazine/m545/hunter + /datum/category_item/autolathe/arms/machinegun_545 name = "machinegun box magazine (5.56)" path =/obj/item/ammo_magazine/m545saw hidden = 1 +/datum/category_item/autolathe/arms/machinegun_545_hunter + name = "machinegun box magazine (5.56 hunting)" + path =/obj/item/ammo_magazine/m545saw/hunter + hidden = 1 + /////// 7.62 /datum/category_item/autolathe/arms/rifle_762 name = "rifle magazine (7.62mm)" path =/obj/item/ammo_magazine/m762 hidden = 1 + /* /datum/category_item/autolathe/arms/rifle_small_762 name = "rifle magazine (7.62mm)" @@ -298,6 +308,15 @@ name = "speedloader (.38 rubber)" path =/obj/item/ammo_magazine/s38/rubber +/datum/category_item/autolathe/arms/speedloader_45 + name = "speedloader (.45)" + path = /obj/item/ammo_magazine/s45 + hidden = 1 + +/datum/category_item/autolathe/arms/speedloader_45r + name = "speedloader (.45 rubber)" + path = /obj/item/ammo_magazine/s45/rubber + // Commented out until metal exploits with autolathe is fixed. /*/datum/category_item/autolathe/arms/pistol_clip_45 name = "ammo clip (.45)" @@ -375,6 +394,10 @@ path =/obj/item/ammo_magazine/clip/c762 hidden = 1 +/datum/category_item/autolathe/arms/rifle_clip_762_hunter + name = "ammo clip (7.62mm hunting)" + path =/obj/item/ammo_magazine/clip/c762/hunter + /datum/category_item/autolathe/arms/rifle_clip_762_practice name = "ammo clip (7.62mm practice)" path =/obj/item/ammo_magazine/clip/c762/practice diff --git a/code/datums/outfits/jobs/civilian.dm b/code/datums/outfits/jobs/civilian.dm index ab102d2a8b5..afbd7278e09 100644 --- a/code/datums/outfits/jobs/civilian.dm +++ b/code/datums/outfits/jobs/civilian.dm @@ -87,3 +87,18 @@ l_hand = /obj/item/weapon/storage/bible id_type = /obj/item/weapon/card/id/civilian/chaplain pda_type = /obj/item/device/pda/chaplain + +/decl/hierarchy/outfit/job/explorer + name = OUTFIT_JOB_NAME("Explorer") + shoes = /obj/item/clothing/shoes/boots/winter/explorer + uniform = /obj/item/clothing/under/explorer + mask = /obj/item/clothing/mask/gas/explorer + suit = /obj/item/clothing/suit/storage/hooded/explorer + gloves = /obj/item/clothing/gloves/black + l_ear = /obj/item/device/radio/headset + id_slot = slot_wear_id + id_type = /obj/item/weapon/card/id/civilian + pda_slot = slot_belt + pda_type = /obj/item/device/pda/cargo // Brown looks more rugged + r_pocket = /obj/item/device/gps/explorer + id_pda_assignment = "Explorer" diff --git a/code/datums/outfits/jobs/engineering.dm b/code/datums/outfits/jobs/engineering.dm index 1eda9d5de0e..3804bcb4c0a 100644 --- a/code/datums/outfits/jobs/engineering.dm +++ b/code/datums/outfits/jobs/engineering.dm @@ -3,6 +3,7 @@ belt = /obj/item/weapon/storage/belt/utility/full l_ear = /obj/item/device/radio/headset/headset_eng shoes = /obj/item/clothing/shoes/boots/workboots + r_pocket = /obj/item/device/t_scanner backpack = /obj/item/weapon/storage/backpack/industrial satchel_one = /obj/item/weapon/storage/backpack/satchel/eng messenger_bag = /obj/item/weapon/storage/backpack/messenger/engi @@ -22,7 +23,6 @@ name = OUTFIT_JOB_NAME("Engineer") head = /obj/item/clothing/head/hardhat uniform = /obj/item/clothing/under/rank/engineer - r_pocket = /obj/item/device/t_scanner id_type = /obj/item/weapon/card/id/engineering/engineer pda_type = /obj/item/device/pda/engineering diff --git a/code/datums/outfits/jobs/medical.dm b/code/datums/outfits/jobs/medical.dm index 2b3c2c2407a..3b227a26121 100644 --- a/code/datums/outfits/jobs/medical.dm +++ b/code/datums/outfits/jobs/medical.dm @@ -103,3 +103,4 @@ /decl/hierarchy/outfit/job/medical/paramedic/emt name = OUTFIT_JOB_NAME("Emergency Medical Technician") uniform = /obj/item/clothing/under/rank/medical/paramedic + suit = /obj/item/clothing/suit/storage/toggle/labcoat/emt diff --git a/code/datums/supplypacks/contraband.dm b/code/datums/supplypacks/contraband.dm index cbe52301dff..4ca0ae51d51 100644 --- a/code/datums/supplypacks/contraband.dm +++ b/code/datums/supplypacks/contraband.dm @@ -43,10 +43,10 @@ containername = "Moghes imports crate" contraband = 1 -/datum/supply_packs/security/bolt_rifles_mosin +/datum/supply_packs/security/bolt_rifles_militia name = "Surplus militia rifles" contains = list( - /obj/item/weapon/gun/projectile/shotgun/pump/rifle/mosin = 3, + /obj/item/weapon/gun/projectile/shotgun/pump/rifle = 3, /obj/item/ammo_magazine/clip/c762 = 6 ) cost = 50 @@ -63,11 +63,13 @@ /obj/item/clothing/suit/storage/vest/heavy/merc, /obj/item/clothing/glasses/night, /obj/item/weapon/storage/box/anti_photons, - /obj/item/ammo_magazine/clip/c12g/pellet, /obj/item/ammo_magazine/clip/c12g + /obj/item/ammo_magazine/clip/c12g/pellet, + /obj/item/ammo_magazine/clip/c12g ), list( //the doc, /obj/item/weapon/storage/firstaid/combat, - /obj/item/weapon/gun/projectile/dartgun, /obj/item/weapon/reagent_containers/hypospray, + /obj/item/weapon/gun/projectile/dartgun, + /obj/item/weapon/reagent_containers/hypospray, /obj/item/weapon/reagent_containers/glass/bottle/chloralhydrate, /obj/item/weapon/reagent_containers/glass/bottle/cyanide, /obj/item/ammo_magazine/chemdart @@ -78,7 +80,7 @@ /obj/item/weapon/storage/box/syndie_kit/demolitions, /obj/item/device/multitool/ai_detector, /obj/item/weapon/plastique, - /obj/item/weapon/storage/toolbox/syndicate + /obj/item/weapon/storage/toolbox/syndicate/powertools ), list( //the infiltrator, /obj/item/weapon/gun/projectile/silenced, diff --git a/code/datums/supplypacks/engineering.dm b/code/datums/supplypacks/engineering.dm index bd16322e200..efa5c454f2e 100644 --- a/code/datums/supplypacks/engineering.dm +++ b/code/datums/supplypacks/engineering.dm @@ -21,6 +21,48 @@ containertype = /obj/structure/closet/crate/engineering containername = "Superconducting Magnetic Coil crate" +/datum/supply_packs/eng/shield_capacitor + name = "Shield Capacitor" + contains = list(/obj/machinery/shield_capacitor) + cost = 20 + containertype = /obj/structure/closet/crate/engineering + containername = "shield capacitor crate" + +/datum/supply_packs/eng/shield_capacitor/advanced + name = "Advanced Shield Capacitor" + contains = list(/obj/machinery/shield_capacitor/advanced) + cost = 30 + containertype = /obj/structure/closet/crate/engineering + containername = "advanced shield capacitor crate" + +/datum/supply_packs/eng/bubble_shield + name = "Bubble Shield Generator" + contains = list(/obj/machinery/shield_gen) + cost = 40 + containertype = /obj/structure/closet/crate/engineering + containername = "shield bubble generator crate" + +/datum/supply_packs/eng/bubble_shield/advanced + name = "Advanced Bubble Shield Generator" + contains = list(/obj/machinery/shield_gen/advanced) + cost = 60 + containertype = /obj/structure/closet/crate/engineering + containername = "advanced bubble shield generator crate" + +/datum/supply_packs/eng/hull_shield + name = "Hull Shield Generator" + contains = list(/obj/machinery/shield_gen/external) + cost = 80 + containertype = /obj/structure/closet/crate/engineering + containername = "shield hull generator crate" + +/datum/supply_packs/eng/hull_shield/advanced + name = "Advanced Hull Shield Generator" + contains = list(/obj/machinery/shield_gen/external/advanced) + cost = 120 + containertype = /obj/structure/closet/crate/engineering + containername = "advanced hull shield generator crate" + /datum/supply_packs/eng/electrical name = "Electrical maintenance crate" contains = list( diff --git a/code/datums/supplypacks/medical.dm b/code/datums/supplypacks/medical.dm index b4d51ed1b53..fef3f3e350c 100644 --- a/code/datums/supplypacks/medical.dm +++ b/code/datums/supplypacks/medical.dm @@ -119,7 +119,7 @@ /obj/item/weapon/storage/belt/medical, /obj/item/device/radio/headset/heads/cmo, /obj/item/clothing/under/rank/chief_medical_officer, - /obj/item/weapon/reagent_containers/hypospray, + /obj/item/weapon/reagent_containers/hypospray/vial, /obj/item/clothing/accessory/stethoscope, /obj/item/clothing/glasses/hud/health, /obj/item/clothing/suit/storage/toggle/labcoat/cmo, diff --git a/code/datums/supplypacks/voidsuits.dm b/code/datums/supplypacks/voidsuits.dm index 658ed5562f4..dda9aa4ed4b 100644 --- a/code/datums/supplypacks/voidsuits.dm +++ b/code/datums/supplypacks/voidsuits.dm @@ -142,7 +142,7 @@ /obj/item/clothing/shoes/magboots = 2, /obj/item/weapon/tank/oxygen = 2 ) - cost = 50 + cost = 60 containertype = "/obj/structure/closet/crate/secure" containername = "Vey-Med Medical voidsuit crate" access = access_medical_equip diff --git a/code/datums/uplink/ammunition.dm b/code/datums/uplink/ammunition.dm index d644a9eaa8c..c0b7600aad7 100644 --- a/code/datums/uplink/ammunition.dm +++ b/code/datums/uplink/ammunition.dm @@ -22,6 +22,14 @@ name = "Pistol Magazine (.45 AP)" path = /obj/item/ammo_magazine/m45/ap +/datum/uplink_item/item/ammo/s45m + name = "Speedloader (.45)" + path = /obj/item/ammo_magazine/s45 + +/datum/uplink_item/item/ammo/s45map + name = "Speedloader (.45 AP)" + path = /obj/item/ammo_magazine/s45/ap + /datum/uplink_item/item/ammo/tommymag name = "Tommygun Magazine (.45)" path = /obj/item/ammo_magazine/m45tommy diff --git a/code/datums/uplink/tools.dm b/code/datums/uplink/tools.dm index 250d4b6412b..558c922b465 100644 --- a/code/datums/uplink/tools.dm +++ b/code/datums/uplink/tools.dm @@ -9,11 +9,16 @@ item_cost = 5 path = /obj/item/device/binoculars -/datum/uplink_item/item/tools/toolbox +/datum/uplink_item/item/tools/toolbox // Leaving the basic as an option since powertools are loud. name = "Fully Loaded Toolbox" - item_cost = 10 + item_cost = 5 path = /obj/item/weapon/storage/toolbox/syndicate +/datum/uplink_item/item/tools/powertoolbox + name = "Fully Loaded Powertool Box" + item_cost = 10 + path = /obj/item/weapon/storage/toolbox/syndicate/powertools + /datum/uplink_item/item/tools/clerical name = "Morphic Clerical Kit" item_cost = 10 diff --git a/code/defines/obj/weapon.dm b/code/defines/obj/weapon.dm index 69965ef7f0e..4cd21a55277 100644 --- a/code/defines/obj/weapon.dm +++ b/code/defines/obj/weapon.dm @@ -78,7 +78,7 @@ /obj/item/weapon/cane name = "cane" - desc = "A cane used by a true gentlemen. Or a clown." + desc = "A cane used by a true gentleman." icon = 'icons/obj/weapons.dmi' icon_state = "cane" item_icons = list( @@ -88,7 +88,7 @@ flags = CONDUCT force = 5.0 throwforce = 7.0 - w_class = ITEMSIZE_SMALL + w_class = ITEMSIZE_NORMAL matter = list(DEFAULT_WALL_MATERIAL = 50) attack_verb = list("bludgeoned", "whacked", "disciplined", "thrashed") @@ -218,7 +218,7 @@ /obj/item/weapon/SWF_uplink name = "station-bounced radio" - desc = "used to comunicate it appears." + desc = "Used to communicate, it appears." icon = 'icons/obj/radio.dmi' icon_state = "radio" var/temp = null @@ -607,7 +607,7 @@ /obj/item/weapon/ectoplasm name = "ectoplasm" - desc = "spooky" + desc = "Spooky!" gender = PLURAL icon = 'icons/obj/wizard.dmi' icon_state = "ectoplasm" @@ -643,4 +643,4 @@ icon = 'icons/obj/stock_parts.dmi' icon_state = "spring" origin_tech = list(TECH_ENGINEERING = 1) - matter = list(DEFAULT_WALL_MATERIAL = 40) \ No newline at end of file + matter = list(DEFAULT_WALL_MATERIAL = 40) diff --git a/code/game/antagonist/outsider/raider.dm b/code/game/antagonist/outsider/raider.dm index 596ac1451e2..190488b38c6 100644 --- a/code/game/antagonist/outsider/raider.dm +++ b/code/game/antagonist/outsider/raider.dm @@ -85,7 +85,7 @@ var/datum/antagonist/raider/raiders /obj/item/weapon/gun/projectile/silenced, /obj/item/weapon/gun/projectile/shotgun/pump, /obj/item/weapon/gun/projectile/shotgun/pump/combat, - /obj/item/weapon/gun/projectile/shotgun/pump/rifle/mosin, + /obj/item/weapon/gun/projectile/shotgun/pump/rifle, /obj/item/weapon/gun/projectile/shotgun/doublebarrel, /obj/item/weapon/gun/projectile/shotgun/doublebarrel/pellet, /obj/item/weapon/gun/projectile/shotgun/doublebarrel/sawn, diff --git a/code/game/antagonist/station/renegade.dm b/code/game/antagonist/station/renegade.dm index d9796432c0c..08d411aec93 100644 --- a/code/game/antagonist/station/renegade.dm +++ b/code/game/antagonist/station/renegade.dm @@ -48,7 +48,7 @@ var/datum/antagonist/renegade/renegades /obj/item/weapon/gun/projectile/revolver, /obj/item/weapon/gun/projectile/derringer, /obj/item/weapon/gun/projectile/shotgun/pump, - /obj/item/weapon/gun/projectile/shotgun/pump/rifle/mosin, + /obj/item/weapon/gun/projectile/shotgun/pump/rifle, /obj/item/weapon/gun/projectile/shotgun/pump/combat, /obj/item/weapon/gun/projectile/shotgun/doublebarrel, /obj/item/weapon/gun/projectile/revolver/judge, diff --git a/code/game/antagonist/station/thug.dm b/code/game/antagonist/station/thug.dm index 54f5f83663a..2ea752e3b7d 100644 --- a/code/game/antagonist/station/thug.dm +++ b/code/game/antagonist/station/thug.dm @@ -13,5 +13,5 @@ var/datum/antagonist/thug/thugs Try to make sure other players have fun! If you are confused or at a loss, always adminhelp, \ and before taking extreme actions, please try to also contact the administration! \ Think through your actions and make the roleplay immersive! Please remember all \ - rules aside from those without explicit exceptions apply to antagonists." - flags = ANTAG_SUSPICIOUS | ANTAG_IMPLANT_IMMUNE | ANTAG_RANDSPAWN | ANTAG_VOTABLE \ No newline at end of file + rules aside from those with explicit exceptions apply to antagonists." + flags = ANTAG_SUSPICIOUS | ANTAG_IMPLANT_IMMUNE | ANTAG_RANDSPAWN | ANTAG_VOTABLE diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 9ac0f87198c..e0648f8c953 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,6 +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/old_x = 0 var/old_y = 0 var/auto_init = 1 @@ -297,3 +298,12 @@ return null return text2num(pickweight(candidates)) +/atom/movable/proc/update_transform() + var/matrix/M = matrix() + M.Scale(icon_scale) + src.transform = M + +// Use this to set the object's scale. +/atom/movable/proc/adjust_scale(new_scale) + icon_scale = new_scale + update_transform() diff --git a/code/game/gamemodes/changeling/changeling_powers.dm b/code/game/gamemodes/changeling/changeling_powers.dm index e54eb3c1cd0..b0f19c3ba3a 100644 --- a/code/game/gamemodes/changeling/changeling_powers.dm +++ b/code/game/gamemodes/changeling/changeling_powers.dm @@ -4,6 +4,7 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E var/list/datum/absorbed_dna/absorbed_dna = list() var/list/absorbed_languages = list() // Necessary because of set_species stuff var/absorbedcount = 0 + var/lingabsorbedcount = 1 //Starts at one, because that's us var/chem_charges = 20 var/chem_recharge_rate = 0.5 var/chem_storage = 50 @@ -11,8 +12,8 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E var/changelingID = "Changeling" var/geneticdamage = 0 var/isabsorbing = 0 - var/geneticpoints = 5 - var/max_geneticpoints = 5 + var/geneticpoints = 7 + var/max_geneticpoints = 7 var/readapts = 1 var/max_readapts = 2 var/list/purchased_powers = list() @@ -22,6 +23,7 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E var/recursive_enhancement = 0 //Used to power up other abilities from the ling power with the same name. var/list/purchased_powers_history = list() //Used for round-end report, includes respec uses too. var/last_shriek = null // world.time when the ling last used a shriek. + var/next_escape = 0 // world.time when the ling can next use Escape Restraints /datum/changeling/New(var/gender=FEMALE) ..() @@ -219,7 +221,11 @@ turf/proc/AdjacentTurfsRangedSting() victims += C var/mob/living/carbon/T = input(src, "Who will we sting?") as null|anything in victims - if(!T) return + if(!T) + return + if(T.isSynthetic()) + src << "We are unable to pierce the outer shell of [T]." + return if(!(T in view(changeling.sting_range))) return if(!sting_can_reach(T, changeling.sting_range)) return if(!changeling_power(required_chems)) return diff --git a/code/game/gamemodes/changeling/powers/absorb.dm b/code/game/gamemodes/changeling/powers/absorb.dm index 396e6faf347..0af67b22ed6 100644 --- a/code/game/gamemodes/changeling/powers/absorb.dm +++ b/code/game/gamemodes/changeling/powers/absorb.dm @@ -90,16 +90,23 @@ continue absorbDNA(dna_data) changeling.absorbedcount++ + T.mind.changeling.absorbed_dna.len = 1 - changeling.geneticpoints += 5 - changeling.max_geneticpoints += 5 + // This is where lings get boosts from eating eachother + if(T.mind.changeling.lingabsorbedcount) + for(var/a = 1 to T.mind.changeling.lingabsorbedcount) + changeling.lingabsorbedcount++ + changeling.geneticpoints += 4 + changeling.max_geneticpoints += 4 + src << "We absorbed another changeling, and we grow stronger. Our genomes increase." T.mind.changeling.chem_charges = 0 T.mind.changeling.geneticpoints = -1 T.mind.changeling.max_geneticpoints = -1 //To prevent revival. T.mind.changeling.absorbedcount = 0 + T.mind.changeling.lingabsorbedcount = 0 changeling.absorbedcount++ changeling.isabsorbing = 0 diff --git a/code/game/gamemodes/changeling/powers/armblade.dm b/code/game/gamemodes/changeling/powers/armblade.dm index 139950e900b..5ab724789b4 100644 --- a/code/game/gamemodes/changeling/powers/armblade.dm +++ b/code/game/gamemodes/changeling/powers/armblade.dm @@ -134,4 +134,5 @@ /obj/item/weapon/melee/changeling/claw/greater name = "hand greatclaw" force = 20 - armor_penetration = 20 \ No newline at end of file + armor_penetration = 20 + pry = 1 \ No newline at end of file diff --git a/code/game/gamemodes/changeling/powers/escape_restraints.dm b/code/game/gamemodes/changeling/powers/escape_restraints.dm new file mode 100644 index 00000000000..4e6ed4e5cf8 --- /dev/null +++ b/code/game/gamemodes/changeling/powers/escape_restraints.dm @@ -0,0 +1,63 @@ +/datum/power/changeling/escape_restraints + name = "Escape Restraints" + desc = "We evolve more complex joints" + helptext = "We can instantly escape from most restraints and bindings, but we cannot do it often." + enhancedtext = "More frequent escapes." + ability_icon_state = "ling_escape_restraints" + genomecost = 2 + verbpath = /mob/proc/changeling_escape_restraints + +//Escape Cuffs. By design this does not escape from straight jackets +/mob/proc/changeling_escape_restraints() + set category = "Changeling" + set name = "Escape Restraints (40)" + set desc = "Removes handcuffs and legcuffs instantly." + + var/escape_cooldown = 5 MINUTES //This is used later to prevent spamming + var/mob/living/carbon/human/C = src + var/datum/changeling/changeling = changeling_power(40,0,100,CONSCIOUS) + if(!changeling) + return 0 + if(world.time < changeling.next_escape) + to_chat(src, "We are still recovering from our last escape...") + return 0 + if(!(C.handcuffed || C.legcuffed)) // No need to waste chems if there's nothing to break out of + to_chat(C, "We are are not restrained in a way we can escape...") + return 0 + + changeling.chem_charges -= 40 + + to_chat(C,"We contort our extremities and slip our cuffs.") + playsound(src, 'sound/effects/blobattack.ogg', 30, 1) + if(C.handcuffed) + var/obj/item/weapon/W = C.handcuffed + C.handcuffed = null + if(C.buckled && C.buckled.buckle_require_restraints) + C.buckled.unbuckle_mob() + C.update_inv_handcuffed() + if (C.client) + C.client.screen -= W + if(W) + W.loc = C.loc + W.dropped(C) + if(W) + W.layer = initial(W.layer) + if(C.legcuffed) + var/obj/item/weapon/W = C.legcuffed + C.legcuffed = null + C.update_inv_legcuffed() + if(C.client) + C.client.screen -= W + if(W) + W.loc = C.loc + W.dropped(C) + if(W) + W.layer = initial(W.layer) + + if(src.mind.changeling.recursive_enhancement) + escape_cooldown *= 0.5 + + changeling.next_escape = world.time + escape_cooldown //And now we set the timer + + feedback_add_details("changeling_powers","ESR") + return 1 \ No newline at end of file diff --git a/code/game/gamemodes/cult/ritual.dm b/code/game/gamemodes/cult/ritual.dm index ca1d5639e90..8db7a49255e 100644 --- a/code/game/gamemodes/cult/ritual.dm +++ b/code/game/gamemodes/cult/ritual.dm @@ -123,7 +123,7 @@ var/global/list/rnwords = list("ire","ego","nahlizet","certum","veri","jatkaa"," if(word1 == cultwords["hell"] && word2 == cultwords["join"] && word3 == cultwords["self"]) return tearreality() if(word1 == cultwords["destroy"] && word2 == cultwords["see"] && word3 == cultwords["technology"]) - return emp(src.loc,3) + return emp(src.loc,5) if(word1 == cultwords["travel"] && word2 == cultwords["blood"] && word3 == cultwords["self"]) return drain() if(word1 == cultwords["see"] && word2 == cultwords["hell"] && word3 == cultwords["join"]) diff --git a/code/game/gamemodes/gameticker.dm b/code/game/gamemodes/gameticker.dm index 38316a6c50c..0885cdef60f 100644 --- a/code/game/gamemodes/gameticker.dm +++ b/code/game/gamemodes/gameticker.dm @@ -43,10 +43,13 @@ var/global/datum/controller/gameticker/ticker 'sound/music/title2.ogg',\ 'sound/music/clouds.s3m',\ 'sound/music/space_oddity.ogg') //Ground Control to Major Tom, this song is cool, what's going on? - do + + send2mainirc("Server lobby is loaded and open at byond://[config.serverurl ? config.serverurl : (config.server ? config.server : "[world.address]:[world.port]")]") + + do pregame_timeleft = 180 - world << "Welcome to the pre-game lobby!" - world << "Please, setup your character and select ready. Game will start in [pregame_timeleft] seconds" + to_chat(world, "Welcome to the pregame lobby!") + to_chat(world, "Please set up your character and select ready. The round will start in [pregame_timeleft] seconds.") while(current_state == GAME_STATE_PREGAME) for(var/i=0, i<10, i++) sleep(1) @@ -76,7 +79,7 @@ var/global/datum/controller/gameticker/ticker if(!runnable_modes.len) current_state = GAME_STATE_PREGAME Master.SetRunLevel(RUNLEVEL_LOBBY) - world << "Unable to choose playable game mode. Reverting to pre-game lobby." + to_chat(world, "Unable to choose playable game mode. Reverting to pregame lobby.") return 0 if(secret_force_mode != "secret") src.mode = config.pick_mode(secret_force_mode) @@ -87,11 +90,11 @@ var/global/datum/controller/gameticker/ticker src.mode = gamemode_cache[pickweight(weighted_modes)] else src.mode = config.pick_mode(master_mode) - + if(!src.mode) current_state = GAME_STATE_PREGAME Master.SetRunLevel(RUNLEVEL_LOBBY) - world << "Serious error in mode setup! Reverting to pre-game lobby." + to_chat(world, "Serious error in mode setup! Reverting to pregame lobby.") //Uses setup instead of set up due to computational context. return 0 job_master.ResetOccupations() @@ -100,7 +103,7 @@ var/global/datum/controller/gameticker/ticker job_master.DivideOccupations() // Apparently important for new antagonist system to register specific job antags properly. if(!src.mode.can_start()) - world << "Unable to start [mode.name]. Not enough players, [mode.required_players] players needed. Reverting to pre-game lobby." + world << "Unable to start [mode.name]. Not enough players readied, [mode.required_players] players needed. Reverting to pregame lobby." current_state = GAME_STATE_PREGAME Master.SetRunLevel(RUNLEVEL_LOBBY) mode.fail_setup() @@ -116,13 +119,13 @@ var/global/datum/controller/gameticker/ticker tmpmodes+=M.name tmpmodes = sortList(tmpmodes) if(tmpmodes.len) - world << "Possibilities: [english_list(tmpmodes, and_text= "; ", comma_text = "; ")]" + to_chat(world, "Possibilities: [english_list(tmpmodes, and_text= "; ", comma_text = "; ")]") else src.mode.announce() setup_economy() current_state = GAME_STATE_PLAYING - create_characters() //Create player characters and transfer them + create_characters() //Create player characters and transfer them. collect_minds() equip_characters() data_core.manifest() @@ -139,7 +142,7 @@ var/global/datum/controller/gameticker/ticker //Deleting Startpoints but we need the ai point to AI-ize people later if (S.name != "AI") qdel(S) - world << "Enjoy the game!" + to_chat(world, "Enjoy the game!") world << sound('sound/AI/welcome.ogg') // Skie //Holiday Round-start stuff ~Carn Holiday_Game_Start() @@ -152,7 +155,7 @@ var/global/datum/controller/gameticker/ticker if(C.holder) admins_number++ if(admins_number == 0) - send2adminirc("Round has started with no admins online.") + send2adminirc("A round has started with no admins online.") /* supply_controller.process() //Start the supply shuttle regenerating points -- TLE // handled in scheduler master_controller.process() //Start master_controller.process() @@ -304,7 +307,7 @@ var/global/datum/controller/gameticker/ticker if(captainless) for(var/mob/M in player_list) if(!istype(M,/mob/new_player)) - M << "Colony Directorship not forced on anyone." + to_chat(M, "Colony Directorship not forced on anyone.") proc/process() @@ -340,7 +343,7 @@ var/global/datum/controller/gameticker/ticker feedback_set_details("end_proper","nuke") time_left = 1 MINUTE //No point waiting five minutes if everyone's dead. if(!delay_end) - world << "Rebooting due to destruction of station in [round(time_left/600)] minutes." + to_chat(world, "Rebooting due to destruction of station in [round(time_left/600)] minutes.") else feedback_set_details("end_proper","proper completion") time_left = round(restart_timeout) @@ -353,15 +356,15 @@ var/global/datum/controller/gameticker/ticker while(time_left > 0) if(delay_end) break - world << "Restarting in [round(time_left/600)] minute\s." + to_chat(world, "Restarting in [round(time_left/600)] minute\s.") time_left -= 1 MINUTES sleep(600) if(!delay_end) world.Reboot() else - world << "An admin has delayed the round end." + to_chat(world, "An admin has delayed the round end.") else - world << "An admin has delayed the round end." + to_chat(world, "An admin has delayed the round end.") else if (mode_finished) post_game = 1 @@ -371,7 +374,7 @@ var/global/datum/controller/gameticker/ticker //call a transfer shuttle vote spawn(50) if(!round_end_announced) // Spam Prevention. Now it should announce only once. - world << "The round has ended!" + to_chat(world, "The round has ended!") round_end_announced = 1 vote.autotransfer() @@ -385,7 +388,7 @@ var/global/datum/controller/gameticker/ticker var/turf/playerTurf = get_turf(Player) if(emergency_shuttle.departed && emergency_shuttle.evac) if(isNotAdminLevel(playerTurf.z)) - Player << "You managed to survive, but were marooned on [station_name()] as [Player.real_name]..." + Player << "You survived the round, but remained on [station_name()] as [Player.real_name]." else Player << "You managed to survive the events on [station_name()] as [Player.real_name]." else if(isAdminLevel(playerTurf.z)) @@ -426,9 +429,9 @@ var/global/datum/controller/gameticker/ticker if (!robo.connected_ai) if (robo.stat != 2) - world << "[robo.name] (Played by: [robo.key]) survived as an AI-less synthetic! Its laws were:" + world << "[robo.name] (Played by: [robo.key]) survived as an AI-less stationbound synthetic! Its laws were:" else - world << "[robo.name] (Played by: [robo.key]) was unable to survive the rigors of being a synthetic without an AI. Its laws were:" + world << "[robo.name] (Played by: [robo.key]) was unable to survive the rigors of being a stationbound synthetic without an AI. Its laws were:" if(robo) //How the hell do we lose robo between here and the world messages directly above this? robo.laws.show_laws(world) diff --git a/code/game/gamemodes/heist/heist.dm b/code/game/gamemodes/heist/heist.dm index 48f0f02bfca..65ad3d7f01f 100644 --- a/code/game/gamemodes/heist/heist.dm +++ b/code/game/gamemodes/heist/heist.dm @@ -7,8 +7,8 @@ var/global/list/obj/cortical_stacks = list() //Stacks for 'leave nobody behind' /datum/game_mode/heist name = "Heist" config_tag = "heist" - required_players = 9 - required_players_secret = 9 + required_players = 12 + required_players_secret = 12 required_enemies = 3 round_description = "An unidentified bluespace signature is approaching the station!" extended_round_description = "The Company's majority control of phoron in the system has marked the \ diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm index e85af7e82b6..f7233c1266a 100644 --- a/code/game/gamemodes/nuclear/nuclear.dm +++ b/code/game/gamemodes/nuclear/nuclear.dm @@ -12,8 +12,8 @@ var/list/nuke_disks = list() colony of sizable population and considerable wealth causes it to often be the target of various \ attempts of robbery, fraud and other malicious actions." config_tag = "mercenary" - required_players = 9 - required_players_secret = 9 + required_players = 12 + required_players_secret = 12 required_enemies = 3 end_on_antag_death = 0 var/nuke_off_station = 0 //Used for tracking if the syndies actually haul the nuke to the station diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index 39d3f739d72..850f061250d 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -440,7 +440,7 @@ datum/objective/steal "a chief medical officer's jumpsuit" = /obj/item/clothing/under/rank/chief_medical_officer, "a head of security's jumpsuit" = /obj/item/clothing/under/rank/head_of_security, "a head of personnel's jumpsuit" = /obj/item/clothing/under/rank/head_of_personnel, - "the hypospray" = /obj/item/weapon/reagent_containers/hypospray, + "the hypospray" = /obj/item/weapon/reagent_containers/hypospray/vial, "the colony director's pinpointer" = /obj/item/weapon/pinpointer, "an ablative armor vest" = /obj/item/clothing/suit/armor/laserproof, ) diff --git a/code/game/gamemodes/technomancer/spell_objs_helpers.dm b/code/game/gamemodes/technomancer/spell_objs_helpers.dm index 05afae4a3b0..f11c027566a 100644 --- a/code/game/gamemodes/technomancer/spell_objs_helpers.dm +++ b/code/game/gamemodes/technomancer/spell_objs_helpers.dm @@ -21,9 +21,14 @@ return 0 /obj/item/weapon/spell/proc/allowed_to_teleport() - if(owner && owner.z in using_map.admin_levels) - return 0 - return 1 + if(owner) + if(owner.z in using_map.admin_levels) + return FALSE + + var/turf/T = get_turf(owner) + if(T.block_tele) + return FALSE + return TRUE /obj/item/weapon/spell/proc/within_range(var/atom/target, var/max_range = 7) // Beyond 7 is off the screen. if(range(get_dist(owner, target) <= max_range)) diff --git a/code/game/gamemodes/technomancer/spells/blink.dm b/code/game/gamemodes/technomancer/spells/blink.dm index c0012c991c9..320374542de 100644 --- a/code/game/gamemodes/technomancer/spells/blink.dm +++ b/code/game/gamemodes/technomancer/spells/blink.dm @@ -23,9 +23,12 @@ var/turf/starting = get_turf(AM) var/list/targets = list() + if(starting.block_tele) + return + valid_turfs: for(var/turf/simulated/T in range(AM, range)) - if(T.density || istype(T, /turf/simulated/mineral)) //Don't blink to vacuum or a wall + if(T.density || T.block_tele || istype(T, /turf/simulated/mineral)) //Don't blink to vacuum or a wall continue for(var/atom/movable/stuff in T.contents) if(stuff.density) @@ -54,7 +57,10 @@ if(istype(hit_atom, /atom/movable)) var/atom/movable/AM = hit_atom if(!within_range(AM)) - user << "\The [AM] is too far away to blink." + to_chat(user, "\The [AM] is too far away to blink.") + return + if(!allowed_to_teleport()) + to_chat(user, "Teleportation doesn't seem to work here.") return if(pay_energy(400)) if(check_for_scepter()) @@ -67,6 +73,9 @@ to_chat(user, "You need more energy to blink [AM] away!") /obj/item/weapon/spell/blink/on_use_cast(mob/user) + if(!allowed_to_teleport()) + to_chat(user, "Teleportation doesn't seem to work here.") + return if(pay_energy(200)) if(check_for_scepter()) safe_blink(user, calculate_spell_power(10)) @@ -80,6 +89,9 @@ /obj/item/weapon/spell/blink/on_melee_cast(atom/hit_atom, mob/living/user, def_zone) if(istype(hit_atom, /atom/movable)) var/atom/movable/AM = hit_atom + if(!allowed_to_teleport()) + to_chat(user, "Teleportation doesn't seem to work here.") + return if(pay_energy(300)) visible_message("\The [user] reaches out towards \the [AM] with a glowing hand.") if(check_for_scepter()) diff --git a/code/game/gamemodes/technomancer/spells/mark_recall.dm b/code/game/gamemodes/technomancer/spells/mark_recall.dm index e47b62c031b..306de85043c 100644 --- a/code/game/gamemodes/technomancer/spells/mark_recall.dm +++ b/code/game/gamemodes/technomancer/spells/mark_recall.dm @@ -68,6 +68,9 @@ user << "There's no Mark!" return 0 else + if(!allowed_to_teleport()) + to_chat(user, "Teleportation doesn't seem to work here.") + return visible_message("\The [user] starts glowing!") var/light_intensity = 2 var/time_left = 3 diff --git a/code/game/gamemodes/technomancer/spells/passwall.dm b/code/game/gamemodes/technomancer/spells/passwall.dm index e786134b4c0..fa7b5f34b99 100644 --- a/code/game/gamemodes/technomancer/spells/passwall.dm +++ b/code/game/gamemodes/technomancer/spells/passwall.dm @@ -46,6 +46,9 @@ checked_turf = get_step(checked_turf, direction) //Advance in the given direction total_cost += check_for_scepter() ? 400 : 800 //Phasing through matter's expensive, you know. i-- + if(checked_turf.block_tele) // The fun ends here. + break + if(!checked_turf.density) //If we found a destination (a non-dense turf), then we can stop. var/dense_objs_on_turf = 0 for(var/atom/movable/stuff in checked_turf.contents) //Make sure nothing dense is where we want to go, like an airlock or window. diff --git a/code/game/jobs/access_datum.dm b/code/game/jobs/access_datum.dm index 322a71f7d4f..b63662cd868 100644 --- a/code/game/jobs/access_datum.dm +++ b/code/game/jobs/access_datum.dm @@ -462,3 +462,9 @@ /datum/access/trader id = access_trader access_type = ACCESS_TYPE_PRIVATE + +/var/const/access_alien = 300 // For things like crashed ships. +/datum/access/alien + id = access_alien + desc = "#%_^&*@!" + access_type = ACCESS_TYPE_PRIVATE diff --git a/code/game/jobs/job/civilian_chaplain.dm b/code/game/jobs/job/civilian_chaplain.dm index 88a448c571c..2eece781ec8 100644 --- a/code/game/jobs/job/civilian_chaplain.dm +++ b/code/game/jobs/job/civilian_chaplain.dm @@ -82,7 +82,7 @@ while(!accepted) if(!B) break // prevents possible runtime errors - new_book_style = input(H,"Which bible style would you like?") in list("Bible", "Koran", "Scrapbook", "Creeper", "White Bible", "Holy Light", "Athiest", "Tome", "The King in Yellow", "Ithaqua", "Scientology", "the bible melts", "Necronomicon") + new_book_style = input(H,"Which bible style would you like?") in list("Bible", "Koran", "Scrapbook", "Pagan", "White Bible", "Holy Light", "Athiest", "Tome", "The King in Yellow", "Ithaqua", "Scientology", "the bible melts", "Necronomicon","Orthodox","Torah") switch(new_book_style) if("Koran") B.icon_state = "koran" @@ -90,9 +90,6 @@ if("Scrapbook") B.icon_state = "scrapbook" B.item_state = "scrapbook" - if("Creeper") - B.icon_state = "creeper" - B.item_state = "syringe_kit" if("White Bible") B.icon_state = "white" B.item_state = "syringe_kit" @@ -120,6 +117,15 @@ if("Necronomicon") B.icon_state = "necronomicon" B.item_state = "necronomicon" + if("Pagan") + B.icon_state = "shadows" + B.item_state = "syringe_kit" + if("Orthodox") + B.icon_state = "orthodoxy" + B.item_state = "bible" + if("Torah") + B.icon_state = "torah" + B.item_state = "clipboard" else B.icon_state = "bible" B.item_state = "bible" diff --git a/code/game/jobs/job_controller.dm b/code/game/jobs/job_controller.dm index f74b1d6185f..a0ac2f646cb 100644 --- a/code/game/jobs/job_controller.dm +++ b/code/game/jobs/job_controller.dm @@ -74,7 +74,7 @@ var/global/datum/controller/occupations/job_master proc/FreeRole(var/rank) //making additional slot on the fly var/datum/job/job = GetJob(rank) - if(job && job.current_positions >= job.total_positions && job.total_positions != -1) + if(job && job.total_positions != -1) job.total_positions++ return 1 return 0 diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm index 50d6988e358..4daf8392de9 100644 --- a/code/game/machinery/autolathe.dm +++ b/code/game/machinery/autolathe.dm @@ -55,31 +55,31 @@ if(shocked) shock(user, 50) - - var/dat = "

Autolathe Control Panel


" + var/list/dat = list() + dat += "

Autolathe Control Panel


" if(!disabled) dat += "" - var/material_top = "" - var/material_bottom = "" + var/list/material_top = list("") + var/list/material_bottom = list("") for(var/material in stored_material) material_top += "" material_bottom += "" - dat += "[material_top][material_bottom]
[material][stored_material[material]]/[storage_capacity[material]]

" + dat += "[material_top.Join()][material_bottom.Join()]
" dat += "

Printable Designs

Showing: [current_category].

" for(var/datum/category_item/autolathe/R in current_category.items) if(R.hidden && !hacked) continue var/can_make = 1 - var/material_string = "" - var/multiplier_string = "" + var/list/material_string = list() + var/list/multiplier_string = list() var/max_sheets var/comma if(!R.resources || !R.resources.len) - material_string = "No resources required." + material_string += "No resources required." else //Make sure it's buildable and list requires resources. for(var/material in R.resources) @@ -98,12 +98,12 @@ if(R.is_stack) if(max_sheets && max_sheets > 0) max_sheets = min(max_sheets, R.max_stack) // Limit to the max allowed by stack type. - multiplier_string += "
" + multiplier_string += "
" for(var/i = 5;i*" : ""][can_make ? "" : ""][R.name][can_make ? "" : ""][R.hidden ? "*" : ""][multiplier_string]" + dat += "" dat += "
[material_string]
[R.hidden ? "*" : ""][can_make ? "" : ""][R.name][can_make ? "" : ""][R.hidden ? "*" : ""][multiplier_string.Join()][material_string.Join()]

" //Hacking. @@ -113,7 +113,7 @@ dat += "
" - user << browse(dat, "window=autolathe") + user << browse(dat.Join(), "window=autolathe") onclose(user, "autolathe") /obj/machinery/autolathe/attackby(var/obj/item/O as obj, var/mob/user as mob) diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index c7ce4ff2d0f..769dd9c39fb 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -130,7 +130,7 @@ if(user.species.can_shred(user)) set_status(0) user.do_attack_animation(src) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed()) visible_message("\The [user] slashes at [src]!") playsound(src.loc, 'sound/weapons/slash.ogg', 100, 1) add_hiddenprint(user) @@ -210,7 +210,7 @@ src.bugged = 1 else if(W.damtype == BRUTE || W.damtype == BURN) //bashing cameras - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(W)) if (W.force >= src.toughness) user.do_attack_animation(src) visible_message("[src] has been [W.attack_verb.len? pick(W.attack_verb) : "attacked"] with [W] by [user]!") diff --git a/code/game/machinery/camera/tracking.dm b/code/game/machinery/camera/tracking.dm index 1aadf981c4f..4f6b7df94f1 100644 --- a/code/game/machinery/camera/tracking.dm +++ b/code/game/machinery/camera/tracking.dm @@ -2,7 +2,7 @@ #define TRACKING_NO_COVERAGE 1 #define TRACKING_TERMINATE 2 -/mob/living/silicon/ai/var/max_locations = 10 +/mob/living/silicon/ai/var/max_locations = 30 /mob/living/silicon/ai/var/stored_locations[0] /proc/InvalidPlayerTurf(turf/T as turf) diff --git a/code/game/machinery/computer/robot.dm b/code/game/machinery/computer/robot.dm index 4d29a56b89a..f91ac2b677f 100644 --- a/code/game/machinery/computer/robot.dm +++ b/code/game/machinery/computer/robot.dm @@ -37,6 +37,7 @@ // Locks or unlocks the cyborg if (href_list["lockdown"]) var/mob/living/silicon/robot/target = get_cyborg_by_name(href_list["lockdown"]) + var/failmsg = "" if(!target || !istype(target)) return @@ -57,11 +58,19 @@ var/istraitor = target.mind.special_role if (istraitor) + failmsg = "failed (target is traitor) " target.lockcharge = !target.lockcharge if (target.lockcharge) - target << "Someone tried to lock you down!" + to_chat(target, "Someone tried to lock you down!") else - target << "Someone tried to lift your lockdown!" + to_chat(target, "Someone tried to lift your lockdown!") + else if (target.emagged) + failmsg = "failed (target is hacked) " + target.lockcharge = !target.lockcharge + if (target.lockcharge) + to_chat(target, "Someone tried to lock you down!") + else + to_chat(target, "Someone tried to lift your lockdown!") else target.canmove = !target.canmove target.lockcharge = !target.canmove //when canmove is 1, lockcharge should be 0 @@ -70,7 +79,7 @@ target << "You have been locked down!" else target << "Your lockdown has been lifted!" - message_admins("[key_name_admin(usr)] [istraitor ? "failed (target is traitor) " : ""][target.lockcharge ? "lockdown" : "release"] on [target.name]!") + message_admins("[key_name_admin(usr)] [failmsg][target.lockcharge ? "lockdown" : "release"] on [target.name]!") log_game("[key_name(usr)] attempted to [target.lockcharge ? "lockdown" : "release"] [target.name] on the robotics console!") diff --git a/code/game/machinery/deployable.dm b/code/game/machinery/deployable.dm index 76eb2da2d5a..2ed722e1296 100644 --- a/code/game/machinery/deployable.dm +++ b/code/game/machinery/deployable.dm @@ -96,7 +96,7 @@ for reference: return return else - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(W)) switch(W.damtype) if("fire") health -= W.force * 1 @@ -214,7 +214,7 @@ for reference: if(health <= 0) explode() return - + /obj/machinery/deployable/barrier/emp_act(severity) if(stat & (BROKEN|NOPOWER)) return diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index acd7a446c19..87da7c7ac68 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -127,6 +127,36 @@ icon = 'icons/obj/doors/Doormaint.dmi' assembly_type = /obj/structure/door_assembly/door_assembly_mai +/obj/machinery/door/airlock/maintenance/cargo + icon = 'icons/obj/doors/Doormaint_cargo.dmi' + req_one_access = list(access_cargo) + +/obj/machinery/door/airlock/maintenance/command + icon = 'icons/obj/doors/Doormaint_command.dmi' + req_one_access = list(access_heads) + +/obj/machinery/door/airlock/maintenance/common + icon = 'icons/obj/doors/Doormaint_common.dmi' + +/obj/machinery/door/airlock/maintenance/engi + icon = 'icons/obj/doors/Doormaint_engi.dmi' + req_one_access = list(access_engine) + +/obj/machinery/door/airlock/maintenance/int + icon = 'icons/obj/doors/Doormaint_int.dmi' + +/obj/machinery/door/airlock/maintenance/medical + icon = 'icons/obj/doors/Doormaint_med.dmi' + req_one_access = list(access_medical) + +/obj/machinery/door/airlock/maintenance/rnd + icon = 'icons/obj/doors/Doormaint_rnd.dmi' + req_one_access = list(access_research) + +/obj/machinery/door/airlock/maintenance/sec + icon = 'icons/obj/doors/Doormaint_sec.dmi' + req_one_access = list(access_security) + /obj/machinery/door/airlock/external name = "External Airlock" icon = 'icons/obj/doors/Doorext.dmi' @@ -386,6 +416,24 @@ icon = 'icons/obj/doors/shuttledoors_vertical.dmi' assembly_type = /obj/structure/door_assembly/door_assembly_voidcraft/vertical +/obj/machinery/door/airlock/alien + name = "alien airlock" + desc = "You're fairly sure this is a door." + icon = 'icons/obj/doors/Dooralien.dmi' + explosion_resistance = 20 + secured_wires = TRUE + hackProof = TRUE + assembly_type = /obj/structure/door_assembly/door_assembly_alien + req_one_access = list(access_alien) + +/obj/machinery/door/airlock/alien/locked + icon_state = "door_locked" + locked = TRUE + +/obj/machinery/door/airlock/alien/public // Entry to UFO. + req_one_access = list() + normalspeed = FALSE // So it closes faster and hopefully keeps the warm air inside. + /* About the new airlock wires panel: * An airlock wire dialog can be accessed by the normal way or by using wirecutters or a multitool on the door while the wire-panel is open. This would show the following wires, which you can either wirecut/mend or send a multitool pulse through. There are 9 wires. diff --git a/code/game/machinery/doors/blast_door.dm b/code/game/machinery/doors/blast_door.dm index bf40ad9fff4..870b080c79f 100644 --- a/code/game/machinery/doors/blast_door.dm +++ b/code/game/machinery/doors/blast_door.dm @@ -132,7 +132,7 @@ else if(src.density && (user.a_intent == I_HURT)) //If we can't pry it open and it's a weapon, let's hit it. var/obj/item/weapon/W = C - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(W)) if(W.damtype == BRUTE || W.damtype == BURN) user.do_attack_animation(src) if(W.force < min_force) @@ -162,7 +162,7 @@ else if(src.density && (user.a_intent == I_HURT)) //If we can't pry it open and it's not a weapon.... Eh, let's attack it anyway. var/obj/item/weapon/W = C - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(W)) if(W.damtype == BRUTE || W.damtype == BURN) user.do_attack_animation(src) if(W.force < min_force) //No actual non-weapon item shouls have a force greater than the min_force, but let's include this just in case. diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index f9f6c667c79..157e73e4a86 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -260,7 +260,7 @@ //psa to whoever coded this, there are plenty of objects that need to call attack() on doors without bludgeoning them. if(src.density && istype(I, /obj/item/weapon) && user.a_intent == I_HURT && !istype(I, /obj/item/weapon/card)) var/obj/item/weapon/W = I - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(W)) if(W.damtype == BRUTE || W.damtype == BURN) user.do_attack_animation(src) if(W.force < min_force) diff --git a/code/game/machinery/doors/multi_tile.dm b/code/game/machinery/doors/multi_tile.dm index 45501a3de76..434f7e64cb5 100644 --- a/code/game/machinery/doors/multi_tile.dm +++ b/code/game/machinery/doors/multi_tile.dm @@ -2,15 +2,44 @@ /obj/machinery/door/airlock/multi_tile width = 2 appearance_flags = 0 + var/obj/machinery/filler_object/filler1 + var/obj/machinery/filler_object/filler2 /obj/machinery/door/airlock/multi_tile/New() ..() SetBounds() + if(opacity) + create_fillers() + +/obj/machinery/door/airlock/multi_tile/Destroy() + qdel_null(filler1) + qdel_null(filler2) + return ..() /obj/machinery/door/airlock/multi_tile/Move() . = ..() SetBounds() +/obj/machinery/door/airlock/multi_tile/open() + . = ..() + + if(filler1) + filler1.set_opacity(opacity) + if(filler2) + filler2.set_opacity(opacity) + + return . + +/obj/machinery/door/airlock/multi_tile/close() + . = ..() + + if(filler1) + filler1.set_opacity(opacity) + if(filler2) + filler2.set_opacity(opacity) + + return . + /obj/machinery/door/airlock/multi_tile/proc/SetBounds() if(dir in list(EAST, WEST)) bound_width = width * world.icon_size @@ -19,9 +48,35 @@ bound_width = world.icon_size bound_height = width * world.icon_size +/obj/machinery/door/airlock/multi_tile/proc/create_fillers() + if(src.dir > 3) + filler1 = new/obj/machinery/filler_object (src.loc) + filler2 = new/obj/machinery/filler_object (get_step(src,EAST)) + else + filler1 = new/obj/machinery/filler_object (src.loc) + filler2 = new/obj/machinery/filler_object (get_step(src,NORTH)) + filler1.density = 0 + filler2.density = 0 + filler1.set_opacity(opacity) + filler2.set_opacity(opacity) + /obj/machinery/door/airlock/multi_tile/glass name = "Glass Airlock" icon = 'icons/obj/doors/Door2x1glass.dmi' opacity = 0 glass = 1 assembly_type = /obj/structure/door_assembly/multi_tile + +/obj/machinery/door/airlock/multi_tile/metal + name = "Airlock" + icon = 'icons/obj/doors/Door2x1metal.dmi' + assembly_type = /obj/structure/door_assembly/multi_tile + +/obj/machinery/filler_object + name = "" + icon = 'icons/obj/doors/rapid_pdoor.dmi' + icon_state = "" + density = 0 + +/obj/machinery/door/airlock/multi_tile/metal/mait + icon = 'icons/obj/doors/Door2x1_Maint.dmi' diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm index 4fc02c70cce..d25473e709f 100644 --- a/code/game/machinery/doors/windowdoor.dm +++ b/code/game/machinery/doors/windowdoor.dm @@ -161,7 +161,7 @@ playsound(src.loc, 'sound/effects/Glasshit.ogg', 75, 1) visible_message("[user] smashes against the [src.name].", 1) user.do_attack_animation(src) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed()) take_damage(25) return return src.attackby(user, user) @@ -246,7 +246,7 @@ //If it's a weapon, smash windoor. Unless it's an id card, agent card, ect.. then ignore it (Cards really shouldnt damage a door anyway) if(src.density && istype(I, /obj/item/weapon) && !istype(I, /obj/item/weapon/card)) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(I)) var/aforce = I.force playsound(src.loc, 'sound/effects/Glasshit.ogg', 75, 1) visible_message("[src] was hit by [I].") diff --git a/code/game/machinery/holosign.dm b/code/game/machinery/holosign.dm index 7e465db1895..f438f7d0032 100644 --- a/code/game/machinery/holosign.dm +++ b/code/game/machinery/holosign.dm @@ -36,6 +36,11 @@ name = "surgery holosign" desc = "Small wall-mounted holographic projector. This one reads SURGERY." on_icon = "surgery" + +/obj/machinery/holosign/exit + name = "exit holosign" + desc = "Small wall-mounted holographic projector. This one reads EXIT." + on_icon = "exit" ////////////////////SWITCH/////////////////////////////////////// /obj/machinery/button/holosign diff --git a/code/game/machinery/portable_turret.dm b/code/game/machinery/portable_turret.dm index 1b181aebb5d..9e88c955941 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 @@ -359,7 +381,7 @@ var/list/turret_icons else //if the turret was attacked with the intention of harming it: - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(I)) take_damage(I.force * 0.5) if(I.force * 0.5 > 1) //if the force of impact dealt at least 1 damage, the turret gets pissed off if(!attacked && !emagged) @@ -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 96ab5eab20e..34e89ac6fd0 100644 --- a/code/game/machinery/rechargestation.dm +++ b/code/game/machinery/rechargestation.dm @@ -103,13 +103,6 @@ R.adjustFireLoss(-wire_rate) else if(ishuman(occupant)) var/mob/living/carbon/human/H = occupant - if(!isnull(H.internal_organs_by_name["cell"]) && H.nutrition < 450) - H.nutrition = min(H.nutrition+10, 450) - cell.use(7000/450*10) - - else if(istype(occupant, /mob/living/carbon/human)) - - var/mob/living/carbon/human/H = occupant // In case they somehow end up with positive values for otherwise unobtainable damage... if(H.getToxLoss()>0) H.adjustToxLoss(-(rand(1,3))) @@ -153,9 +146,21 @@ return if(default_part_replacement(user, O)) return + if (istype(O, /obj/item/weapon/grab) && get_dist(src,user)<2) + var/obj/item/weapon/grab/G = O + if(istype(G.affecting,/mob/living)) + var/mob/living/M = G.affecting + qdel(O) + go_in(M) ..() +/obj/machinery/recharge_station/MouseDrop_T(var/mob/target, var/mob/user) + if(user.stat || user.lying || !Adjacent(user) || !target.Adjacent(user)) + return + + go_in(target) + /obj/machinery/recharge_station/RefreshParts() ..() var/man_rating = 0 @@ -214,15 +219,16 @@ if(icon_update_tick == 0) build_overlays() -/obj/machinery/recharge_station/Bumped(var/mob/living/silicon/robot/R) - go_in(R) +/obj/machinery/recharge_station/Bumped(var/mob/living/L) + go_in(L) -/obj/machinery/recharge_station/proc/go_in(var/mob/living/silicon/robot/R) +/obj/machinery/recharge_station/proc/go_in(var/mob/living/L) if(occupant) return - if(istype(R, /mob/living/silicon/robot)) + if(istype(L, /mob/living/silicon/robot)) + var/mob/living/silicon/robot/R = L if(R.incapacitated()) return @@ -237,8 +243,8 @@ update_icon() return 1 - else if(istype(R, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = R + else if(istype(L, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = L if(!isnull(H.internal_organs_by_name["cell"])) add_fingerprint(H) H.reset_view(src) @@ -289,3 +295,27 @@ if(!usr.incapacitated()) return go_in(usr) + +/obj/machinery/recharge_station/ghost_pod_recharger + name = "drone pod" + desc = "This is a pod which used to contain a drone... Or maybe it still does?" + icon = 'icons/obj/structures.dmi' + +/obj/machinery/recharge_station/ghost_pod_recharger/update_icon() + ..() + if(stat & BROKEN) + icon_state = "borg_pod_closed" + desc = "It appears broken..." + return + + if(occupant) + if((stat & NOPOWER) && !has_cell_power()) + icon_state = "borg_pod_closed" + desc = "It appears to be unpowered..." + else + icon_state = "borg_pod_closed" + else + icon_state = "borg_pod_opened" + + if(icon_update_tick == 0) + build_overlays() \ No newline at end of file diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm index 30a0743e097..7f76bc978c4 100644 --- a/code/game/machinery/suit_storage_unit.dm +++ b/code/game/machinery/suit_storage_unit.dm @@ -640,7 +640,7 @@ name = "Nonstandard suit cycler" model_text = "Nonstandard" req_access = list(access_syndicate) - departments = list("Mercenary") + departments = list("Mercenary", "Charring") can_repair = 1 /obj/machinery/suit_cycler/attack_ai(mob/user as mob) @@ -752,7 +752,7 @@ //Clear the access reqs, disable the safeties, and open up all paintjobs. user << "You run the sequencer across the interface, corrupting the operating protocols." - departments = list("Engineering","Mining","Medical","Security","Atmos","HAZMAT","Construction","Biohazard","Crowd Control","Emergency Medical Response","^%###^%$") + departments = list("Engineering","Mining","Medical","Security","Atmos","HAZMAT","Construction","Biohazard","Crowd Control","Emergency Medical Response","^%###^%$", "Charring") species = list("Human","Tajara","Skrell","Unathi", "Teshari") emagged = 1 @@ -1073,6 +1073,15 @@ suit.name = "blood-red voidsuit" suit.item_state = "syndie_voidsuit" suit.icon_state = "rig-syndie" + if("Charring") + if(helmet) + helmet.name = "soot-covered voidsuit helmet" + helmet.icon_state = "rig0-firebug" + helmet.item_state = "rig0-firebug" + if(suit) + suit.name = "soot-covered voidsuit" + suit.item_state = "rig-firebug" + suit.icon_state = "rig-firebug" if(helmet) helmet.name = "refitted [helmet.name]" if(suit) suit.name = "refitted [suit.name]" diff --git a/code/game/machinery/supplybeacon.dm b/code/game/machinery/supplybeacon.dm index 3441b09cbb2..0f58bd9a48c 100644 --- a/code/game/machinery/supplybeacon.dm +++ b/code/game/machinery/supplybeacon.dm @@ -47,7 +47,7 @@ /obj/machinery/power/supply_beacon/attackby(var/obj/item/weapon/W, var/mob/user) if(!use_power && istype(W, /obj/item/weapon/wrench)) if(!anchored && !connect_to_network()) - user << "This device must be placed over an exposed cable." + to_chat(user, "This device must be placed over an exposed cable.") return anchored = !anchored user.visible_message("\The [user] [anchored ? "secures" : "unsecures"] \the [src].") @@ -59,13 +59,13 @@ if(expended) use_power = 0 - user << "\The [src] has used up its charge." + to_chat (user, "\The [src] has used up its charge.") return if(anchored) return use_power ? deactivate(user) : activate(user) else - user << "You need to secure the beacon with a wrench first!" + to_chat(user, "You need to secure the beacon with a wrench first!") return /obj/machinery/power/supply_beacon/attack_ai(var/mob/user) @@ -76,12 +76,12 @@ if(expended) return if(surplus() < 500) - if(user) user << "The connected wire doesn't have enough current." + if(user) to_chat(user, "The connected wire doesn't have enough current.") return set_light(3, 3, "#00CCAA") icon_state = "beacon_active" use_power = 1 - if(user) user << "You activate the beacon. The supply drop will be dispatched soon." + if(user) to_chat(user, "You activate the beacon. The supply drop will be dispatched soon.") /obj/machinery/power/supply_beacon/proc/deactivate(var/mob/user, var/permanent) if(permanent) @@ -92,7 +92,7 @@ set_light(0) use_power = 0 target_drop_time = null - if(user) user << "You deactivate the beacon." + if(user) to_chat(user, "You deactivate the beacon.") /obj/machinery/power/supply_beacon/Destroy() if(use_power) diff --git a/code/game/machinery/transportpod.dm b/code/game/machinery/transportpod.dm new file mode 100644 index 00000000000..96401c09082 --- /dev/null +++ b/code/game/machinery/transportpod.dm @@ -0,0 +1,110 @@ +/obj/machinery/transportpod + name = "Ballistic Transportation Pod" + desc = "A fast transit ballistic pod used to get from one place to the next. Batteries not included!" + icon = 'icons/obj/structures.dmi' + icon_state = "borg_pod_opened" + + density = 1 //thicc + anchored = 1 + use_power = 0 + + var/in_transit = 0 + var/mob/occupant = null + + var/xc = list(137, 209, 163, 110, 95, 60, 129, 201) // List of x values on the map to go to. + var/yc = list(134, 99, 169, 120, 96, 122, 189, 219) // List of y values on the map to go to. + + var/limit_x = 3 + var/limit_y = 3 + +/obj/machinery/transportpod/process() + if(occupant) + if(in_transit) + var/locNum = rand(0, 7) //pick a random location + var/turf/L = locate(xc[locNum], yc[locNum], 1) // Pairs the X and Y to get an actual location. + limit_x = xc[locNum]+1 + limit_y = yc[locNum]+1 + build() + sleep(20) //Give explosion time so the pod itself doesn't go boom + src.forceMove(L) + playsound(src, pick('sound/effects/Explosion1.ogg', 'sound/effects/Explosion2.ogg', 'sound/effects/Explosion3.ogg', 'sound/effects/Explosion4.ogg')) + in_transit = 0 + sleep(2) + go_out() + sleep(2) + del(src) + +/obj/machinery/transportpod/relaymove(mob/user as mob) + if(user.stat) + return + go_out() + return + +/obj/machinery/transportpod/update_icon() + ..() + if(occupant) + icon_state = "borg_pod_closed" + else + icon_state = "borg_pod_opened" + +/obj/machinery/transportpod/Bumped(var/mob/living/O) + go_in(O) + +/obj/machinery/transportpod/proc/go_in(var/mob/living/carbon/human/O) + if(occupant) + return + + if(O.incapacitated()) //aint no sleepy people getting in here + return + + add_fingerprint(O) + O.reset_view(src) + O.forceMove(src) + occupant = O + update_icon() + if(alert(O, "Are you sure you're ready to launch?", , "Yes", "No") == "Yes") + in_transit = 1 + playsound(src, HYPERSPACE_WARMUP) + else + go_out() + return 1 + +/obj/machinery/transportpod/proc/go_out() + if(!occupant) + return + + occupant.forceMove(src.loc) + occupant.reset_view() + occupant = null + update_icon() + +/obj/machinery/transportpod/verb/move_eject() + set category = "Object" + set name = "Eject Pod" + set src in oview(1) + + if(usr.incapacitated()) + return + + go_out() + add_fingerprint(usr) + return + +/obj/machinery/transportpod/verb/move_inside() + set category = "Object" + set name = "Enter Pod" + set src in oview(1) + + if(usr.incapacitated()) //just to DOUBLE CHECK the damn sleepy people don't touch the pod + return + + go_in(usr) + +/obj/machinery/transportpod/proc/build() + for(var/x = limit_x-2, x <= limit_x, x++) + for(var/y = limit_y-2, y <= limit_y, y++) + var/current_cell = locate(x, y, 1) + var/turf/T = get_turf(current_cell) + if(!current_cell) + continue + T.ChangeTurf(/turf/unsimulated/floor/shuttle_ceiling) \ No newline at end of file diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm index fdab318780c..960ac923eb7 100644 --- a/code/game/machinery/vending.dm +++ b/code/game/machinery/vending.dm @@ -147,7 +147,7 @@ /obj/machinery/vending/emag_act(var/remaining_charges, var/mob/user) if(!emagged) emagged = 1 - user << "You short out the product lock on \the [src]" + to_chat(user, "You short out \the [src]'s product lock.") return 1 /obj/machinery/vending/attackby(obj/item/weapon/W as obj, mob/user as mob) @@ -182,7 +182,7 @@ return else if(istype(W, /obj/item/weapon/screwdriver)) panel_open = !panel_open - user << "You [panel_open ? "open" : "close"] the maintenance panel." + to_chat(user, "You [panel_open ? "open" : "close"] the maintenance panel.") playsound(src, W.usesound, 50, 1) overlays.Cut() if(panel_open) @@ -199,7 +199,7 @@ W.forceMove(src) coin = W categories |= CAT_COIN - user << "You insert \the [W] into \the [src]." + to_chat(user, "You insert \the [W] into \the [src].") nanomanager.update_uis(src) return else if(istype(W, /obj/item/weapon/wrench)) @@ -211,7 +211,7 @@ if(do_after(user, 20 * W.toolspeed)) if(!src) return - user << "You [anchored? "un" : ""]secured \the [src]!" + to_chat(user, "You [anchored? "un" : ""]secured \the [src]!") anchored = !anchored return else @@ -232,7 +232,7 @@ // This is not a status display message, since it's something the character // themselves is meant to see BEFORE putting the money in - usr << "\icon[cashmoney] That is not enough money." + to_chat(usr, "\icon[cashmoney] That is not enough money.") return 0 if(istype(cashmoney, /obj/item/weapon/spacecash)) @@ -418,21 +418,22 @@ if(href_list["remove_coin"] && !istype(usr,/mob/living/silicon)) if(!coin) - usr << "There is no coin in this machine." + to_chat(usr, "There is no coin in this machine.") return coin.forceMove(src.loc) if(!usr.get_active_hand()) usr.put_in_hands(coin) - usr << "You remove \the [coin] from \the [src]" + to_chat(usr, "You remove \the [coin] from \the [src]") coin = null categories &= ~CAT_COIN if((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf)))) if((href_list["vend"]) && (vend_ready) && (!currently_vending)) if((!allowed(usr)) && !emagged && scan_id) //For SECURE VENDING MACHINES YEAH - usr << "Access denied." //Unless emagged of course + to_chat(usr, "Access denied.") //Unless emagged of course flick(icon_deny,src) + playsound(src.loc, 'sound/machines/deniedbeep.ogg', 50, 0) return var/key = text2num(href_list["vend"]) @@ -445,12 +446,12 @@ if(R.price <= 0) vend(R, usr) else if(istype(usr,/mob/living/silicon)) //If the item is not free, provide feedback if a synth is trying to buy something. - usr << "Artificial unit recognized. Artificial units cannot complete this transaction. Purchase canceled." + to_chat(usr, "Lawed unit recognized. Lawed units cannot complete this transaction. Purchase canceled.") return else currently_vending = R if(!vendor_account || vendor_account.suspended) - status_message = "This machine is currently unable to process payments due to problems with the associated account." + status_message = "This machine is currently unable to process payments due to issues with the associated account." status_error = 1 else status_message = "Please swipe a card or insert cash to pay for the item." @@ -467,8 +468,9 @@ /obj/machinery/vending/proc/vend(datum/stored_item/vending_product/R, mob/user) if((!allowed(usr)) && !emagged && scan_id) //For SECURE VENDING MACHINES YEAH - usr << "Access denied." //Unless emagged of course + to_chat(usr, "Access denied.") //Unless emagged of course flick(icon_deny,src) + playsound(src.loc, 'sound/machines/deniedbeep.ogg', 50, 0) return vend_ready = 0 //One thing at a time!! status_message = "Vending..." @@ -477,13 +479,13 @@ if(R.category & CAT_COIN) if(!coin) - user << "You need to insert a coin to get this item." + to_chat(user, "You need to insert a coin to get this item.") return if(coin.string_attached) if(prob(50)) - user << "You successfully pull the coin out before \the [src] could swallow it." + to_chat(user, "You successfully pull the coin out before \the [src] could swallow it.") else - user << "You weren't able to pull the coin out fast enough, the machine ate it, string and all." + to_chat(user, "You weren't able to pull the coin out fast enough, the machine ate it, string and all.") qdel(coin) coin = null categories &= ~CAT_COIN @@ -806,7 +808,6 @@ contraband = list(/obj/item/weapon/reagent_containers/syringe/steroid = 4) -//This one's from bay12 /obj/machinery/vending/cart name = "PTech" desc = "Cartridges for PDAs." @@ -821,7 +822,7 @@ has_logs = 1 /obj/machinery/vending/cigarette - name = "Cigarette machine" //OCD had to be uppercase to look nice with the new formating + name = "cigarette machine" desc = "If you want to get cancer, might as well do it in style!" product_slogans = "Space cigs taste good like a cigarette should.;I'd rather toolbox than switch.;Smoke!;Don't believe the reports - smoke today!" product_ads = "Probably not bad for you!;Don't believe the scientists!;It's good for you!;Don't quit, buy more!;Smoke!;Nicotine heaven.;Best cigarettes since 2150.;Award-winning cigs.;Feeling temperamental? Try a Temperamento!;Carcinoma Angels - go fuck yerself!;Don't be so hard on yourself, kid. Smoke a Lucky Star!" @@ -865,7 +866,6 @@ req_log_access = access_cmo has_logs = 1 -//This one's from bay12 /obj/machinery/vending/phoronresearch name = "Toximate 3000" desc = "All the fine parts you need in one vending machine!" @@ -1051,7 +1051,6 @@ req_log_access = access_ce has_logs = 1 -//This one's from bay12 /obj/machinery/vending/engineering name = "Robco Tool Maker" desc = "Everything you need for do-it-yourself station repair." @@ -1070,7 +1069,6 @@ req_log_access = access_ce has_logs = 1 -//This one's from bay12 /obj/machinery/vending/robotics name = "Robotech Deluxe" desc = "All the tools you need to create your own robot army." diff --git a/code/game/machinery/vr_console.dm b/code/game/machinery/vr_console.dm new file mode 100644 index 00000000000..79fdf882fa2 --- /dev/null +++ b/code/game/machinery/vr_console.dm @@ -0,0 +1,226 @@ +/obj/machinery/vr_sleeper + name = "VR sleeper" + desc = "A fancy bed with built-in sensory I/O ports and connectors to interface users' minds with their bodies in virtual reality." + icon = 'icons/obj/Cryogenic2.dmi' + icon_state = "syndipod_0" + density = 1 + anchored = 1 + circuit = /obj/item/weapon/circuitboard/vr_sleeper + var/mob/living/carbon/human/occupant = null + var/mob/living/carbon/human/avatar = null + var/datum/mind/vr_mind = null + + use_power = 1 + idle_power_usage = 15 + active_power_usage = 200 + light_color = "#FF0000" + +/obj/machinery/vr_sleeper/New() + ..() + component_parts = list() + component_parts += new /obj/item/weapon/stock_parts/scanning_module(src) + component_parts += new /obj/item/stack/material/glass/reinforced(src, 2) + + RefreshParts() + +/obj/machinery/vr_sleeper/initialize() + update_icon() + +/obj/machinery/vr_sleeper/process() + if(stat & (NOPOWER|BROKEN)) + return + +/obj/machinery/vr_sleeper/update_icon() + icon_state = "syndipod_[occupant ? "1" : "0"]" + +/obj/machinery/vr_sleeper/Topic(href, href_list) + if(..()) + return 1 + + if(usr == occupant) + to_chat(usr, "You can't reach the controls from the inside.") + return + + add_fingerprint(usr) + + if(href_list["eject"]) + go_out() + + return 1 + +/obj/machinery/vr_sleeper/attackby(var/obj/item/I, var/mob/user) + add_fingerprint(user) + if(default_deconstruction_screwdriver(user, I)) + return + else if(default_deconstruction_crowbar(user, I)) + if(occupant && avatar) + avatar.exit_vr() + avatar = null + go_out() + return + + +/obj/machinery/vr_sleeper/MouseDrop_T(var/mob/target, var/mob/user) + if(user.stat || user.lying || !Adjacent(user) || !target.Adjacent(user)|| !isliving(target)) + return + go_in(target, user) + + + +/obj/machinery/sleeper/relaymove(var/mob/user) + ..() + if(usr.incapacitated()) + return + go_out() + + + +/obj/machinery/vr_sleeper/emp_act(var/severity) + if(stat & (BROKEN|NOPOWER)) + ..(severity) + return + + if(occupant) + // This will eject the user from VR + // ### Fry the brain? + go_out() + + ..(severity) + +/obj/machinery/vr_sleeper/verb/eject() + set src in oview(1) + set category = "Object" + set name = "Eject VR Capsule" + + if(usr.incapacitated()) + return + + if(usr != occupant && avatar && alert(avatar, "Someone wants to remove you from virtual reality. Do you want to leave?", "Leave VR?", "Yes", "No") == "No") + return + + // The player in VR is fine with leaving, kick them out and reset avatar + avatar.exit_vr() + avatar = null + go_out() + add_fingerprint(usr) + +/obj/machinery/vr_sleeper/verb/climb_in() + set src in oview(1) + set category = "Object" + set name = "Enter VR Capsule" + + if(usr.incapacitated()) + return + go_in(usr, usr) + add_fingerprint(usr) + +/obj/machinery/vr_sleeper/relaymove(mob/user as mob) + if(user.incapacitated()) + return 0 //maybe they should be able to get out with cuffs, but whatever + go_out() + +/obj/machinery/vr_sleeper/proc/go_in(var/mob/M, var/mob/user) + if(!M) + return + if(stat & (BROKEN|NOPOWER)) + return + if(!ishuman(M)) + user << "\The [src] rejects [M] with a sharp beep." + if(occupant) + user << "\The [src] is already occupied." + return + + if(M == user) + visible_message("\The [user] starts climbing into \the [src].") + else + visible_message("\The [user] starts putting [M] into \the [src].") + + if(do_after(user, 20)) + if(occupant) + to_chat(user, "\The [src] is already occupied.") + return + M.stop_pulling() + if(M.client) + M.client.perspective = EYE_PERSPECTIVE + M.client.eye = src + M.loc = src + update_use_power(2) + occupant = M + + update_icon() + + enter_vr() + return + +/obj/machinery/vr_sleeper/proc/go_out() + if(!occupant) + return + + if(occupant.client) + occupant.client.eye = occupant.client.mob + occupant.client.perspective = MOB_PERSPECTIVE + occupant.loc = src.loc + occupant = null + for(var/atom/movable/A in src) // In case an object was dropped inside or something + if(A == circuit) + continue + if(A in component_parts) + continue + A.loc = src.loc + update_use_power(1) + update_icon() + +/obj/machinery/vr_sleeper/proc/enter_vr() + + // No mob to transfer a mind from + if(!occupant) + return + + // No mind to transfer + if(!occupant.mind) + return + + // Mob doesn't have an active consciousness to send/receive from + if(occupant.stat != CONSCIOUS) + return + + avatar = occupant.vr_link + // If they've already enterred VR, and are reconnecting, prompt if they want a new body + if(avatar && alert(occupant, "You already have a Virtual Reality avatar. Would you like to use it?", "New avatar", "Yes", "No") == "No") + // Delink the mob + occupant.vr_link = null + avatar = null + + if(!avatar) + // Get the desired spawn location to put the body + var/S = null + var/list/vr_landmarks = list() + for(var/obj/effect/landmark/virtual_reality/sloc in landmarks_list) + vr_landmarks += sloc.name + + S = input(occupant, "Please select a location to spawn your avatar at:", "Spawn location") as null|anything in vr_landmarks + if(!S) + return 0 + + for(var/obj/effect/landmark/virtual_reality/i in landmarks_list) + if(i.name == S) + S = i + break + + avatar = new(S, "Virtual Reality Avatar") + // If the user has a non-default (Human) bodyshape, make it match theirs. + if(occupant.species.name != "Promethean" && occupant.species.name != "Human") + avatar.shapeshifter_change_shape(occupant.species.name) + avatar.forceMove(get_turf(S)) // Put the mob on the landmark, instead of inside it + avatar.Sleeping(1) + + occupant.enter_vr(avatar) + + // Prompt for username after they've enterred the body. + var/newname = sanitize(input(avatar, "You are enterring virtual reality. Your username is currently [src.name]. Would you like to change it to something else?", "Name change") as null|text, MAX_NAME_LEN) + if (newname) + avatar.real_name = newname + + else + occupant.enter_vr(avatar) + diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index db8fc519925..f71a40a011c 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -505,7 +505,7 @@ return /obj/mecha/attack_hand(mob/user as mob) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed()) src.log_message("Attack by hand/paw. Attacker - [user].",1) if(istype(user,/mob/living/carbon/human)) @@ -513,7 +513,6 @@ if(H.species.can_shred(user)) if(!prob(src.deflect_chance)) src.take_damage(15) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) playsound(src.loc, 'sound/weapons/slash.ogg', 50, 1, -1) user << "You slash at the armored suit!" @@ -666,7 +665,7 @@ return /obj/mecha/proc/dynattackby(obj/item/weapon/W as obj, mob/user as mob) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(W)) src.log_message("Attacked by [W]. Attacker - [user]") if(prob(src.deflect_chance)) user << "\The [W] bounces off [src.name]." @@ -1763,7 +1762,7 @@ /obj/mecha/attack_generic(var/mob/user, var/damage, var/attack_message) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed()) if(!damage) return 0 diff --git a/code/game/mecha/medical/odysseus.dm b/code/game/mecha/medical/odysseus.dm index 6aec830c899..38c3cffb308 100644 --- a/code/game/mecha/medical/odysseus.dm +++ b/code/game/mecha/medical/odysseus.dm @@ -99,7 +99,9 @@ C.images += holder holder = patient.hud_list[STATUS_HUD] - if(patient.stat == DEAD) + if(patient.isSynthetic()) + holder.icon_state = "hudrobo" + else if(patient.stat == DEAD) holder.icon_state = "huddead" else if(foundVirus) holder.icon_state = "hudill" diff --git a/code/game/objects/effects/alien/aliens.dm b/code/game/objects/effects/alien/aliens.dm index 3d9713cd29a..2c864f0a56c 100644 --- a/code/game/objects/effects/alien/aliens.dm +++ b/code/game/objects/effects/alien/aliens.dm @@ -120,7 +120,7 @@ /obj/effect/alien/resin/attackby(obj/item/weapon/W as obj, mob/user as mob) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(W)) var/aforce = W.force health = max(0, health - aforce) playsound(loc, 'sound/effects/attackblob.ogg', 100, 1) @@ -227,7 +227,7 @@ Alien plants should do something if theres a lot of poison return /obj/effect/alien/weeds/attackby(var/obj/item/weapon/W, var/mob/user) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(W)) if(W.attack_verb.len) visible_message("\The [src] have been [pick(W.attack_verb)] with \the [W][(user ? " by [user]." : ".")]") else diff --git a/code/game/objects/effects/landmarks.dm b/code/game/objects/effects/landmarks.dm index 547406aa1db..b8cb8006d29 100644 --- a/code/game/objects/effects/landmarks.dm +++ b/code/game/objects/effects/landmarks.dm @@ -107,6 +107,18 @@ return 1 +/obj/effect/landmark/virtual_reality + name = "virtual_reality" + icon = 'icons/mob/screen1.dmi' + icon_state = "x" + anchored = 1.0 + +/obj/effect/landmark/virtual_reality/New() + ..() + tag = "virtual_reality*[name]" + invisibility = 101 + return 1 + //Costume spawner landmarks /obj/effect/landmark/costume/New() //costume spawner, selects a random subclass and disappears diff --git a/code/game/objects/effects/spiders.dm b/code/game/objects/effects/spiders.dm index 94c0a7999f0..a26c1169d5f 100644 --- a/code/game/objects/effects/spiders.dm +++ b/code/game/objects/effects/spiders.dm @@ -21,7 +21,7 @@ return /obj/effect/spider/attackby(var/obj/item/weapon/W, var/mob/user) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(W)) if(W.attack_verb.len) visible_message("\The [src] have been [pick(W.attack_verb)] with \the [W][(user ? " by [user]." : ".")]") @@ -210,25 +210,8 @@ //================= if(isturf(loc)) - if(prob(25)) - var/list/nearby = trange(5, src) - loc - if(nearby.len) - var/target_atom = pick(nearby) - walk_to(src, target_atom, 5) - if(prob(25)) - src.visible_message("\The [src] skitters[pick(" away"," around","")].") - else if(prob(5)) - //vent crawl! - for(var/obj/machinery/atmospherics/unary/vent_pump/v in view(7,src)) - if(!v.welded) - entry_vent = v - walk_to(src, entry_vent, 5) - break + skitter() - if(amount_grown >= 100) - var/spawn_type = pick(grow_as) - new spawn_type(src.loc, src) - qdel(src) else if(isorgan(loc)) if(!amount_grown) amount_grown = 1 var/obj/item/organ/external/O = loc @@ -249,6 +232,27 @@ if(amount_grown) amount_grown += rand(0,2) +/obj/effect/spider/spiderling/proc/skitter() + if(isturf(loc)) + if(prob(25)) + var/list/nearby = trange(5, src) - loc + if(nearby.len) + var/target_atom = pick(nearby) + walk_to(src, target_atom, 5) + if(prob(25)) + src.visible_message("\The [src] skitters[pick(" away"," around","")].") + else if(prob(5)) + //vent crawl! + for(var/obj/machinery/atmospherics/unary/vent_pump/v in view(7,src)) + if(!v.welded) + entry_vent = v + walk_to(src, entry_vent, 5) + break + if(amount_grown >= 100) + var/spawn_type = pick(grow_as) + new spawn_type(src.loc, src) + qdel(src) + /obj/effect/decal/cleanable/spiderling_remains name = "spiderling remains" desc = "Green squishy mess." @@ -261,7 +265,7 @@ icon_state = "cocoon1" health = 60 - New() +/obj/effect/spider/cocoon/New() icon_state = pick("cocoon1","cocoon2","cocoon3") /obj/effect/spider/cocoon/Destroy() diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 6b4a09c6a5f..ff7be9f549f 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -80,6 +80,8 @@ 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/attackspeed = DEFAULT_ATTACK_COOLDOWN // How long click delay will be when using this, in 1/10ths of a second. Checked in the user's get_attack_speed(). + var/addblends // Icon overlay for ADD highlights when applicable. /obj/item/New() ..() @@ -456,7 +458,7 @@ var/list/global/slot_flags_enumeration = list( M.attack_log += "\[[time_stamp()]\] Attacked by [user.name] ([user.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])" msg_admin_attack("[user.name] ([user.ckey]) attacked [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)]) (JMP)") //BS12 EDIT ALG - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed()) user.do_attack_animation(M) src.add_fingerprint(user) diff --git a/code/game/objects/items/bodybag.dm b/code/game/objects/items/bodybag.dm index 16e27006b49..a23abb5b066 100644 --- a/code/game/objects/items/bodybag.dm +++ b/code/game/objects/items/bodybag.dm @@ -59,7 +59,7 @@ //..() //Doesn't need to run the parent. Since when can fucking bodybags be welded shut? -Agouri return else if(istype(W, /obj/item/weapon/wirecutters)) - user << "You cut the tag off the bodybag" + to_chat(user, "You cut the tag off the bodybag") src.name = "body bag" src.overlays.Cut() return @@ -160,7 +160,7 @@ O.name = "used stasis bag" O.icon = src.icon O.icon_state = "bodybag_used" - O.desc = "Pretty useless now.." + O.desc = "Pretty useless now..." qdel(src) /obj/structure/closet/body_bag/cryobag/MouseDrop(over_object, src_location, over_location) @@ -211,9 +211,9 @@ /obj/structure/closet/body_bag/cryobag/examine(mob/user) ..() if(Adjacent(user)) //The bag's rather thick and opaque from a distance. - user << "You peer into \the [src]." + to_chat(user, "You peer into \the [src].") if(syringe) - user << "It has a syringe added to it." + to_chat(user, "It has a syringe added to it.") for(var/mob/living/L in contents) L.examine(user) diff --git a/code/game/objects/items/devices/communicator/communicator.dm b/code/game/objects/items/devices/communicator/communicator.dm index d10a57c952c..9e31cb38bb0 100644 --- a/code/game/objects/items/devices/communicator/communicator.dm +++ b/code/game/objects/items/devices/communicator/communicator.dm @@ -429,6 +429,13 @@ var/global/list/obj/item/device/communicator/all_communicators = list() exonet.send_message(their_address, "text", text) im_list += list(list("address" = exonet.address, "to_address" = their_address, "im" = text)) log_pda("[usr] (COMM: [src]) sent \"[text]\" to [exonet.get_atom_from_address(their_address)]") + for(var/mob/M in player_list) + if(M.stat == DEAD && M.is_preference_enabled(/datum/client_preference/ghost_ears)) + if(istype(M, /mob/new_player) || M.forbid_seeing_deadchat) + continue + if(exonet.get_atom_from_address(their_address) == M) + continue + M.show_message("Comm IM - [src] -> [exonet.get_atom_from_address(their_address)]: [text]") if(href_list["disconnect"]) var/name_to_disconnect = href_list["disconnect"] @@ -988,6 +995,14 @@ var/global/list/obj/item/device/communicator/all_communicators = list() src << "You have sent '[text_message]' to [chosen_communicator]." exonet_messages.Add("To [chosen_communicator]:
[text_message]") log_pda("[usr] (COMM: [src]) sent \"[text_message]\" to [chosen_communicator]") + for(var/mob/M in player_list) + if(M.stat == DEAD && M.is_preference_enabled(/datum/client_preference/ghost_ears)) + if(istype(M, /mob/new_player) || M.forbid_seeing_deadchat) + continue + if(M == src) + continue + M.show_message("Comm IM - [src] -> [chosen_communicator]: [text_message]") + // Verb: show_text_messages() diff --git a/code/game/objects/items/devices/defib.dm b/code/game/objects/items/devices/defib.dm index decb40d8079..847ce58560a 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,7 +284,12 @@ return "buzzes, \"Resuscitation failed - Excessive neural degeneration. Further attempts futile.\"" H.updatehealth() - if(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 if(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) @@ -374,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...") @@ -420,6 +428,9 @@ var/adjust_health = barely_in_crit - H.health //need to increase health by this much H.adjustOxyLoss(-adjust_health) + if(H.isSynthetic()) + H.adjustToxLoss(-H.getToxLoss()) + make_announcement("pings, \"Resuscitation successful.\"", "notice") playsound(get_turf(src), 'sound/machines/defib_success.ogg', 50, 0) @@ -642,7 +653,8 @@ name = "jumper cable kit" desc = "A device that delivers powerful shocks to detachable jumper cables that are capable of reviving full body prosthetics." icon_state = "jumperunit" - item_state = "jumperunit" + item_state = "defibunit" +// item_state = "jumperunit" paddles = /obj/item/weapon/shockpaddles/linked/jumper /obj/item/device/defib_kit/jumper_kit/loaded diff --git a/code/game/objects/items/devices/flash.dm b/code/game/objects/items/devices/flash.dm index 8eec816a50c..2435e807f99 100644 --- a/code/game/objects/items/devices/flash.dm +++ b/code/game/objects/items/devices/flash.dm @@ -62,7 +62,7 @@ user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to flash [M.name] ([M.ckey])") msg_admin_attack("[user.name] ([user.ckey]) Used the [src.name] to flash [M.name] ([M.ckey]) (JMP)") - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(src)) user.do_attack_animation(M) if(!clown_check(user)) return @@ -75,9 +75,6 @@ if(!check_capacitor(user)) return - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) - user.do_attack_animation(M) - playsound(src.loc, 'sound/weapons/flash.ogg', 100, 1) var/flashfail = 0 @@ -147,7 +144,7 @@ /obj/item/device/flash/attack_self(mob/living/carbon/user as mob, flag = 0, emp = 0) if(!user || !clown_check(user)) return - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(src)) if(broken) user.show_message("The [src.name] is broken", 2) diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index dd10e808599..cfd3b398e3f 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -163,7 +163,7 @@ else user << "\The [M]'s pupils narrow." - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) //can be used offensively + user.setClickCooldown(user.get_attack_speed(src)) //can be used offensively M.flash_eyes() else return ..() @@ -290,6 +290,7 @@ name = "desk lamp" desc = "A desk lamp with an adjustable mount." icon_state = "lamp" + force = 10 brightness_on = 5 w_class = ITEMSIZE_LARGE flags = CONDUCT diff --git a/code/game/objects/items/devices/geiger.dm b/code/game/objects/items/devices/geiger.dm index 62cb9d9862c..dbac918609c 100644 --- a/code/game/objects/items/devices/geiger.dm +++ b/code/game/objects/items/devices/geiger.dm @@ -1,7 +1,7 @@ -#define RAD_LEVEL_LOW 5 //10 // Around the level at which radiation starts to become harmful -#define RAD_LEVEL_MODERATE 15 //15 -#define RAD_LEVEL_HIGH 50 //50 -#define RAD_LEVEL_VERY_HIGH 100 //100 +#define RAD_LEVEL_LOW 0.01 // Around the level at which radiation starts to become harmful +#define RAD_LEVEL_MODERATE 10 +#define RAD_LEVEL_HIGH 25 +#define RAD_LEVEL_VERY_HIGH 50 //Geiger counter //Rewritten version of TG's geiger counter @@ -19,7 +19,14 @@ /obj/item/device/geiger/New() processing_objects |= src +/obj/item/device/geiger/Destroy() + processing_objects -= src + return ..() + /obj/item/device/geiger/process() + get_radiation() + +/obj/item/device/geiger/proc/get_radiation() if(!scanning) return radiation_count = radiation_repository.get_rads_at_turf(get_turf(src)) @@ -27,12 +34,29 @@ /obj/item/device/geiger/examine(mob/user) ..(user) - to_chat(user, "[scanning ? "ambient" : "stored"] radiation level: [radiation_count ? radiation_count : "0"]Bq.") + get_radiation() + to_chat(user, "[scanning ? "Ambient" : "Stored"] radiation level: [radiation_count ? radiation_count : "0"]Bq.") + +/obj/item/device/geiger/rad_act(amount) + if(!amount || !scanning) + return FALSE + + if(amount > radiation_count) + radiation_count = amount + + var/sound = "geiger" + if(amount < 5) + sound = "geiger_weak" + playsound(src, sound, between(10, 10 + (radiation_count * 4), 100), 0) + if(sound == "geiger_weak") // A weak geiger sound every two seconds sounds too infrequent. + spawn(1 SECOND) + playsound(src, sound, between(10, 10 + (radiation_count * 4), 100), 0) + update_icon() /obj/item/device/geiger/attack_self(var/mob/user) scanning = !scanning update_icon() - to_chat(user, "\icon[src] You switch [scanning ? "on" : "off"] [src].") + to_chat(user, "\icon[src] You switch [scanning ? "on" : "off"] \the [src].") /obj/item/device/geiger/update_icon() if(!scanning) @@ -40,12 +64,18 @@ return 1 switch(radiation_count) - if(null) icon_state = "geiger_on_1" - if(-INFINITY to RAD_LEVEL_LOW) icon_state = "geiger_on_1" - if(RAD_LEVEL_LOW + 1 to RAD_LEVEL_MODERATE) icon_state = "geiger_on_2" - if(RAD_LEVEL_MODERATE + 1 to RAD_LEVEL_HIGH) icon_state = "geiger_on_3" - if(RAD_LEVEL_HIGH + 1 to RAD_LEVEL_VERY_HIGH) icon_state = "geiger_on_4" - if(RAD_LEVEL_VERY_HIGH + 1 to INFINITY) icon_state = "geiger_on_5" + if(null) + icon_state = "geiger_on_1" + if(-INFINITY to RAD_LEVEL_LOW) + icon_state = "geiger_on_1" + if(RAD_LEVEL_LOW to RAD_LEVEL_MODERATE) + icon_state = "geiger_on_2" + if(RAD_LEVEL_MODERATE to RAD_LEVEL_HIGH) + icon_state = "geiger_on_3" + if(RAD_LEVEL_HIGH to RAD_LEVEL_VERY_HIGH) + icon_state = "geiger_on_4" + if(RAD_LEVEL_VERY_HIGH to INFINITY) + icon_state = "geiger_on_5" #undef RAD_LEVEL_LOW #undef RAD_LEVEL_MODERATE diff --git a/code/game/objects/items/devices/gps.dm b/code/game/objects/items/devices/gps.dm new file mode 100644 index 00000000000..18fc47b617f --- /dev/null +++ b/code/game/objects/items/devices/gps.dm @@ -0,0 +1,211 @@ +var/list/GPS_list = list() + +/obj/item/device/gps + name = "global positioning system" + desc = "Triangulates the approximate co-ordinates using a nearby satellite network. Alt+click to toggle power." + icon = 'icons/obj/gps.dmi' + icon_state = "gps-c" + w_class = ITEMSIZE_TINY + slot_flags = SLOT_BELT + origin_tech = list(TECH_MATERIALS = 2, TECH_BLUESPACE = 2, TECH_MAGNETS = 1) + matter = list(DEFAULT_WALL_MATERIAL = 500) + var/gps_tag = "COM0" + var/emped = FALSE + var/tracking = FALSE // Will not show other signals or emit its own signal if false. + var/long_range = FALSE // If true, can see farther, depending on get_map_levels(). + var/local_mode = FALSE // If true, only GPS signals of the same Z level are shown. + var/hide_signal = FALSE // If true, signal is not visible to other GPS devices. + var/can_hide_signal = FALSE // If it can toggle the above var. + +/obj/item/device/gps/initialize() + GPS_list += src + name = "global positioning system ([gps_tag])" + update_icon() + +/obj/item/device/gps/Destroy() + GPS_list -= src + return ..() + +/obj/item/device/gps/AltClick(mob/user) + toggletracking(user) + +/obj/item/device/gps/proc/toggletracking(mob/living/user) + if(!istype(user)) + return + if(emped) + to_chat(user, "It's busted!") + return + if(tracking) + to_chat(user, "[src] is no longer tracking, or visible to other GPS devices.") + tracking = FALSE + update_icon() + else + to_chat(user, "[src] is now tracking, and visible to other GPS devices.") + tracking = TRUE + update_icon() + +/obj/item/device/gps/emp_act(severity) + if(emped) // Without a fancy callback system, this will have to do. + return + var/severity_modifier = severity ? severity : 4 // In case emp_act gets called without any arguments. + var/duration = 5 MINUTES / severity_modifier + emped = TRUE + update_icon() + + spawn(duration) + emped = FALSE + update_icon() + visible_message("\The [src] appears to be functional again.") + +/obj/item/device/gps/update_icon() + overlays.Cut() + if(emped) + overlays += image(icon, src, "emp") + else if(tracking) + overlays += image(icon, src, "working") + +/obj/item/device/gps/attack_self(mob/user) + display(user) + +/obj/item/device/gps/proc/display(mob/user) + if(!tracking) + to_chat(user, "The device is off. Alt-click it to turn it on.") + return + if(emped) + to_chat(user, "It's busted!") + return + + var/list/dat = list() + + var/turf/curr = get_turf(src) + var/area/my_area = get_area(src) + dat += "Current location: [my_area.name] ([curr.x], [curr.y], [curr.z])" + dat += "[hide_signal ? "Tagged" : "Broadcasting"] as '[gps_tag]'. \[Change Tag\] \ + \[Toggle Scan Range\] \ + [can_hide_signal ? "\[Toggle Signal Visibility\]":""]" + + var/list/signals = list() + + for(var/gps in GPS_list) + var/obj/item/device/gps/G = gps + if(G.emped || !G.tracking || G.hide_signal || G == src) // Their GPS isn't on or functional. + continue + var/turf/T = get_turf(G) + var/z_level_detection = using_map.get_map_levels(curr.z, long_range) + + if(local_mode && T.z != curr.z) // Only care about the current z-level. + continue + else if(!(T.z in z_level_detection)) // Too far away. + continue + + var/area/their_area = get_area(G) + var/area_name = their_area.name + if(istype(their_area, /area/submap)) + area_name = "Unknown Area" // Avoid spoilers. + var/coord = "[T.x], [T.y], [T.z]" + var/degrees = round(Get_Angle(curr, T)) + var/direction = uppertext(dir2text(get_dir(curr, T))) + var/distance = get_dist(curr, T) + var/local = curr.z == T.z ? TRUE : FALSE + if(!direction) + direction = "CENTER" + degrees = "N/A" + + signals += " [G.gps_tag]: [area_name] ([coord]) [local ? "Dist: [distance]m Dir: [degrees]° ([direction])":""]" + + if(signals.len) + dat += "Detected signals;" + for(var/line in signals) + dat += line + else + dat += "No other signals detected." + + var/result = dat.Join("
") + to_chat(user, result) + +/obj/item/device/gps/Topic(var/href, var/list/href_list) + if(..()) + return 1 + + if(href_list["tag"]) + var/a = input("Please enter desired tag.", name, gps_tag) as text + a = uppertext(copytext(sanitize(a), 1, 11)) + if(in_range(src, usr)) + gps_tag = a + name = "global positioning system ([gps_tag])" + to_chat(usr, "You set your GPS's tag to '[gps_tag]'.") + + if(href_list["range"]) + local_mode = !local_mode + to_chat(usr, "You set the signal receiver to [local_mode ? "'NARROW'" : "'BROAD'"].") + + if(href_list["hide"]) + if(!can_hide_signal) + return + hide_signal = !hide_signal + to_chat(usr, "You set the device to [hide_signal ? "not " : ""]broadcast a signal while scanning for other signals.") + +/obj/item/device/gps/on // Defaults to off to avoid polluting the signal list with a bunch of GPSes without owners. If you need to spawn active ones, use these. + tracking = TRUE + +/obj/item/device/gps/science + icon_state = "gps-s" + gps_tag = "SCI0" + +/obj/item/device/gps/science/on + tracking = TRUE + +/obj/item/device/gps/engineering + icon_state = "gps-e" + gps_tag = "ENG0" + +/obj/item/device/gps/engineering/on + tracking = TRUE + +/obj/item/device/gps/mining + icon_state = "gps-m" + gps_tag = "MINE0" + desc = "A positioning system helpful for rescuing trapped or injured miners, keeping one on you at all times while mining might just save your life. Alt+click to toggle power." + +/obj/item/device/gps/mining/on + tracking = TRUE + +/obj/item/device/gps/explorer + icon_state = "gps-ex" + gps_tag = "EX0" + desc = "A positioning system helpful for rescuing trapped or injured explorers, keeping one on you at all times while exploring might just save your life. Alt+click to toggle power." + +/obj/item/device/gps/explorer/on + tracking = TRUE + +/obj/item/device/gps/syndie + icon_state = "gps-syndie" + gps_tag = "NULL" + desc = "A positioning system that has extended range and can detect other GPS device signals without revealing its own. How that works is best left a mystery. Alt+click to toggle power." + origin_tech = list(TECH_MATERIALS = 2, TECH_BLUESPACE = 3, TECH_MAGNETS = 2, TECH_ILLEGAL = 2) + long_range = TRUE + hide_signal = TRUE + can_hide_signal = TRUE + +/obj/item/device/gps/robot + icon_state = "gps-b" + gps_tag = "SYNTH0" + desc = "A synthetic internal positioning system. Used as a recovery beacon for damaged synthetic assets, or a collaboration tool for mining or exploration teams. \ + Alt+click to toggle power." + tracking = TRUE // On by default. + +/obj/item/device/gps/internal // Base type for immobile/internal GPS units. + icon_state = null + gps_tag = "Eerie Signal" + desc = "Report to a coder immediately." + invisibility = INVISIBILITY_MAXIMUM + tracking = TRUE // Meant to point to a location, so it needs to be on. + anchored = TRUE + +/obj/item/device/gps/internal/base + gps_tag = "NT_BASE" + desc = "A homing signal from NanoTrasen's outpost." + +/obj/item/device/gps/internal/alien_vessel + gps_tag = "Mysterious Signal" + desc = "A signal that seems forboding." \ No newline at end of file diff --git a/code/game/objects/items/devices/lightreplacer.dm b/code/game/objects/items/devices/lightreplacer.dm index 35f41730dfe..8fd96981fc2 100644 --- a/code/game/objects/items/devices/lightreplacer.dm +++ b/code/game/objects/items/devices/lightreplacer.dm @@ -42,7 +42,7 @@ name = "light replacer" desc = "A device to automatically replace lights. Refill with working lightbulbs or sheets of glass." - + force = 8 icon = 'icons/obj/janitor.dmi' icon_state = "lightreplacer0" flags = CONDUCT @@ -61,32 +61,32 @@ /obj/item/device/lightreplacer/examine(mob/user) if(..(user, 2)) - user << "It has [uses] lights remaining." + to_chat(user, "It has [uses] lights remaining.") /obj/item/device/lightreplacer/attackby(obj/item/W, mob/user) if(istype(W, /obj/item/stack/material) && W.get_material_name() == "glass") var/obj/item/stack/G = W if(uses >= max_uses) - user << "[src.name] is full." + to_chat(user, "[src.name] is full.") return else if(G.use(1)) - AddUses(16) //Autolathe converts 1 sheet into 16 lights. - user << "You insert a piece of glass into \the [src.name]. You have [uses] light\s remaining." + add_uses(16) //Autolathe converts 1 sheet into 16 lights. + to_chat(user, "You insert a piece of glass into \the [src.name]. You have [uses] light\s remaining.") return else - user << "You need one sheet of glass to replace lights." + to_chat(user, "You need one sheet of glass to replace lights.") if(istype(W, /obj/item/weapon/light)) var/obj/item/weapon/light/L = W if(L.status == 0) // LIGHT OKAY if(uses < max_uses) - AddUses(1) - user << "You insert \the [L.name] into \the [src.name]. You have [uses] light\s remaining." + add_uses(1) + to_chat(user, "You insert \the [L.name] into \the [src.name]. You have [uses] light\s remaining.") user.drop_item() qdel(L) return else - user << "You need a working light." + to_chat(user, "You need a working light.") return /obj/item/device/lightreplacer/attack_self(mob/user) @@ -95,10 +95,10 @@ var/mob/living/silicon/robot/R = user if(R.emagged) src.Emag() - usr << "You shortcircuit the [src]." + to_chat(usr, You short circuit the [src].") return */ - usr << "It has [uses] lights remaining." + to_chat(usr, "It has [uses] lights remaining.") /obj/item/device/lightreplacer/update_icon() icon_state = "lightreplacer[emagged]" @@ -107,17 +107,17 @@ /obj/item/device/lightreplacer/proc/Use(var/mob/user) playsound(src.loc, 'sound/machines/click.ogg', 50, 1) - AddUses(-1) + add_uses(-1) return 1 // Negative numbers will subtract -/obj/item/device/lightreplacer/proc/AddUses(var/amount = 1) +/obj/item/device/lightreplacer/proc/add_uses(var/amount = 1) uses = min(max(uses + amount, 0), max_uses) /obj/item/device/lightreplacer/proc/Charge(var/mob/user, var/amount = 1) charge += amount if(charge > 6) - AddUses(1) + add_uses(1) charge = 0 /obj/item/device/lightreplacer/proc/ReplaceLight(var/obj/machinery/light/target, var/mob/living/U) diff --git a/code/game/objects/items/devices/megaphone.dm b/code/game/objects/items/devices/megaphone.dm index 53d647a4f0b..ca4b8d8066e 100644 --- a/code/game/objects/items/devices/megaphone.dm +++ b/code/game/objects/items/devices/megaphone.dm @@ -8,7 +8,7 @@ var/spamcheck = 0 var/emagged = 0 var/insults = 0 - var/list/insultmsg = list("FUCK EVERYONE!", "I'M A TATER!", "ALL SECURITY TO SHOOT ME ON SIGHT!", "I HAVE A BOMB!", "CAPTAIN IS A COMDOM!", "FOR THE SYNDICATE!") + var/list/insultmsg = list("FUCK EVERYONE!", "I'M A TERRORIST!", "ALL SECURITY TO SHOOT ME ON SIGHT!", "I HAVE A BOMB!", "CAPTAIN IS A COMDOM!", "GLORY TO ALMACH!") /obj/item/device/megaphone/attack_self(mob/living/user as mob) if (user.client) diff --git a/code/game/objects/items/gunbox.dm b/code/game/objects/items/gunbox.dm new file mode 100644 index 00000000000..add1530ca48 --- /dev/null +++ b/code/game/objects/items/gunbox.dm @@ -0,0 +1,19 @@ +/obj/item/gunbox + name = "detective's gun box" + desc = "A secure box containing a Detective's sidearm." + icon = 'icons/obj/storage.dmi' + icon_state = "gunbox" + w_class = ITEMSIZE_HUGE + +/obj/item/gunbox/attack_self(mob/living/user) + var/list/options = list() + options[".45 Pistol"] = list(/obj/item/weapon/gun/projectile/colt/detective, /obj/item/ammo_magazine/m45/rubber, /obj/item/ammo_magazine/m45/rubber) + options[".45 Revolver"] = list(/obj/item/weapon/gun/projectile/revolver/detective45, /obj/item/ammo_magazine/s45/rubber, /obj/item/ammo_magazine/s45/rubber) + var/choice = input(user,"Would you prefer a pistol or a revolver?") as null|anything in options + if(src && choice) + var/list/things_to_spawn = options[choice] + for(var/new_type in things_to_spawn) // Spawn all the things, the gun and the ammo. + var/atom/movable/AM = new new_type(get_turf(src)) + if(istype(AM, /obj/item/weapon/gun)) + to_chat(user, "You have chosen \the [AM]. Say hello to your new friend.") + qdel(src) \ No newline at end of file diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm index 584d6dd1057..06a8e8e0683 100644 --- a/code/game/objects/items/robot/robot_upgrades.dm +++ b/code/game/objects/items/robot/robot_upgrades.dm @@ -173,3 +173,23 @@ R.emag_items = 1 return 1 + +/obj/item/borg/upgrade/language + name = "language module" + desc = "Used to let cyborgs other than clerical or service speak a variety of languages." + icon_state = "cyborg_upgrade3" + item_state = "cyborg_upgrade" + +/obj/item/borg/upgrade/language/action(var/mob/living/silicon/robot/R) + if(..()) return 0 + + R.add_language(LANGUAGE_SOL_COMMON, 1) + R.add_language(LANGUAGE_TRADEBAND, 1) + R.add_language(LANGUAGE_UNATHI, 1) + R.add_language(LANGUAGE_SIIK, 1) + R.add_language(LANGUAGE_SKRELLIAN, 1) + R.add_language(LANGUAGE_GUTTER, 1) + R.add_language(LANGUAGE_SCHECHI, 1) + R.add_language(LANGUAGE_ROOTLOCAL, 1) + + return 1 \ No newline at end of file diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm index dde2f168b0e..d878dd74fec 100644 --- a/code/game/objects/items/stacks/medical.dm +++ b/code/game/objects/items/stacks/medical.dm @@ -75,11 +75,11 @@ var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting) if(affecting.open) - user << "The [affecting.name] is cut open, you'll need more than a bandage!" + to_chat(user, "The [affecting.name] is cut open, you'll need more than a bandage!") return if(affecting.is_bandaged()) - user << "The wounds on [M]'s [affecting.name] have already been bandaged." + to_chat(user, "The wounds on [M]'s [affecting.name] have already been bandaged.") return 1 else user.visible_message("\The [user] starts treating [M]'s [affecting.name].", \ @@ -93,9 +93,13 @@ if(used == amount) break if(!do_mob(user, M, W.damage/5)) - user << "You must stand still to bandage wounds." + to_chat(user, "You must stand still to bandage wounds.") break + if(affecting.is_bandaged()) // We do a second check after the delay, in case it was bandaged after the first check. + to_chat(user, "The wounds on [M]'s [affecting.name] have already been bandaged.") + return 1 + if (W.current_stage <= W.max_bleeding_stage) user.visible_message("\The [user] bandages \a [W.desc] on [M]'s [affecting.name].", \ "You bandage \a [W.desc] on [M]'s [affecting.name]." ) @@ -111,9 +115,9 @@ affecting.update_damages() if(used == amount) if(affecting.is_bandaged()) - user << "\The [src] is used up." + to_chat(user, "\The [src] is used up.") else - user << "\The [src] is used up, but there are more wounds to treat on \the [affecting.name]." + to_chat(user, "\The [src] is used up, but there are more wounds to treat on \the [affecting.name].") use(used) /obj/item/stack/medical/ointment @@ -135,17 +139,20 @@ var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting) if(affecting.open) - user << "The [affecting.name] is cut open, you'll need more than a bandage!" + to_chat(user, "The [affecting.name] is cut open, you'll need more than a bandage!") return if(affecting.is_salved()) - user << "The wounds on [M]'s [affecting.name] have already been salved." + to_chat(user, "The wounds on [M]'s [affecting.name] have already been salved.") return 1 else user.visible_message("\The [user] starts salving wounds on [M]'s [affecting.name].", \ "You start salving the wounds on [M]'s [affecting.name]." ) if(!do_mob(user, M, 10)) - user << "You must stand still to salve wounds." + to_chat(user, "You must stand still to salve wounds.") + return 1 + if(affecting.is_salved()) // We do a second check after the delay, in case it was bandaged after the first check. + to_chat(user, "The wounds on [M]'s [affecting.name] have already been salved.") return 1 user.visible_message("[user] salved wounds on [M]'s [affecting.name].", \ "You salved wounds on [M]'s [affecting.name]." ) @@ -169,11 +176,11 @@ var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting) if(affecting.open) - user << "The [affecting.name] is cut open, you'll need more than a bandage!" + to_chat(user, "The [affecting.name] is cut open, you'll need more than a bandage!") return if(affecting.is_bandaged() && affecting.is_disinfected()) - user << "The wounds on [M]'s [affecting.name] have already been treated." + to_chat(user, "The wounds on [M]'s [affecting.name] have already been treated.") return 1 else user.visible_message("\The [user] starts treating [M]'s [affecting.name].", \ @@ -187,8 +194,11 @@ if(used == amount) break if(!do_mob(user, M, W.damage/5)) - user << "You must stand still to bandage wounds." + to_chat(user, "You must stand still to bandage wounds.") break + if(affecting.is_bandaged() && affecting.is_disinfected()) // We do a second check after the delay, in case it was bandaged after the first check. + to_chat(user, "The wounds on [M]'s [affecting.name] have already been bandaged.") + return 1 if (W.current_stage <= W.max_bleeding_stage) user.visible_message("\The [user] cleans \a [W.desc] on [M]'s [affecting.name] and seals the edges with bioglue.", \ "You clean and seal \a [W.desc] on [M]'s [affecting.name]." ) @@ -205,9 +215,9 @@ affecting.update_damages() if(used == amount) if(affecting.is_bandaged()) - user << "\The [src] is used up." + to_chat(user, "\The [src] is used up.") else - user << "\The [src] is used up, but there are more wounds to treat on \the [affecting.name]." + to_chat(user, "\The [src] is used up, but there are more wounds to treat on \the [affecting.name].") use(used) /obj/item/stack/medical/advanced/ointment @@ -228,16 +238,19 @@ var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting) if(affecting.open) - user << "The [affecting.name] is cut open, you'll need more than a bandage!" + to_chat(user, "The [affecting.name] is cut open, you'll need more than a bandage!") if(affecting.is_salved()) - user << "The wounds on [M]'s [affecting.name] have already been salved." + to_chat(user, "The wounds on [M]'s [affecting.name] have already been salved.") return 1 else user.visible_message("\The [user] starts salving wounds on [M]'s [affecting.name].", \ "You start salving the wounds on [M]'s [affecting.name]." ) if(!do_mob(user, M, 10)) - user << "You must stand still to salve wounds." + to_chat(user, "You must stand still to salve wounds.") + return 1 + if(affecting.is_salved()) // We do a second check after the delay, in case it was bandaged after the first check. + to_chat(user, "The wounds on [M]'s [affecting.name] have already been salved.") return 1 user.visible_message( "[user] covers wounds on [M]'s [affecting.name] with regenerative membrane.", \ "You cover wounds on [M]'s [affecting.name] with regenerative membrane." ) @@ -264,20 +277,23 @@ var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting) var/limb = affecting.name if(!(affecting.organ_tag in splintable_organs)) - user << "You can't use \the [src] to apply a splint there!" + to_chat(user, "You can't use \the [src] to apply a splint there!") return if(affecting.splinted) - user << "[M]'s [limb] is already splinted!" + to_chat(user, "[M]'s [limb] is already splinted!") return if (M != user) user.visible_message("[user] starts to apply \the [src] to [M]'s [limb].", "You start to apply \the [src] to [M]'s [limb].", "You hear something being wrapped.") else if(( !user.hand && (affecting.organ_tag in list(BP_R_ARM, BP_R_HAND)) || \ user.hand && (affecting.organ_tag in list(BP_L_ARM, BP_L_HAND)) )) - user << "You can't apply a splint to the arm you're using!" + to_chat(user, "You can't apply a splint to the arm you're using!") return user.visible_message("[user] starts to apply \the [src] to their [limb].", "You start to apply \the [src] to your [limb].", "You hear something being wrapped.") if(do_after(user, 50, M)) + if(affecting.splinted) + to_chat(user, "[M]'s [limb] is already splinted!") + return if(M == user && prob(75)) user.visible_message("\The [user] fumbles [src].", "You fumble [src].", "You hear something being wrapped.") return diff --git a/code/game/objects/items/stacks/nanopaste.dm b/code/game/objects/items/stacks/nanopaste.dm index 95803696d49..7b156c025ff 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(user.get_attack_speed(src)) + if(S.open >= 2) + if(do_after(user,5 * toolspeed)) + S.heal_damage(20, 20, robo_repair = 1) + else if(do_after(user,5 * toolspeed)) + S.heal_damage(10,10, robo_repair =1) + H.updatehealth() + use(1) + user.visible_message("\The [user] applies some nanite paste on [user != M ? "[M]'s [S.name]" : "[S]"] with [src].",\ + "You apply some nanite paste on [user == M ? "your" : "[M]'s"] [S.name].") diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index 6065d6a514d..62f02816edf 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -699,54 +699,6 @@ desc = "A \"Space Life\" brand Emergency Response Team Commander action figure." icon_state = "ert" -/obj/item/toy/therapy_red - name = "red therapy doll" - desc = "A toy for therapeutic and recreational purposes. This one is red." - icon = 'icons/obj/toy.dmi' - icon_state = "therapyred" - item_state = "egg4" // It's the red egg in items_left/righthand - w_class = ITEMSIZE_TINY - -/obj/item/toy/therapy_purple - name = "purple therapy doll" - desc = "A toy for therapeutic and recreational purposes. This one is purple." - icon = 'icons/obj/toy.dmi' - icon_state = "therapypurple" - item_state = "egg1" // It's the magenta egg in items_left/righthand - w_class = ITEMSIZE_TINY - -/obj/item/toy/therapy_blue - name = "blue therapy doll" - desc = "A toy for therapeutic and recreational purposes. This one is blue." - icon = 'icons/obj/toy.dmi' - icon_state = "therapyblue" - item_state = "egg2" // It's the blue egg in items_left/righthand - w_class = ITEMSIZE_TINY - -/obj/item/toy/therapy_yellow - name = "yellow therapy doll" - desc = "A toy for therapeutic and recreational purposes. This one is yellow." - icon = 'icons/obj/toy.dmi' - icon_state = "therapyyellow" - item_state = "egg5" // It's the yellow egg in items_left/righthand - w_class = ITEMSIZE_TINY - -/obj/item/toy/therapy_orange - name = "orange therapy doll" - desc = "A toy for therapeutic and recreational purposes. This one is orange." - icon = 'icons/obj/toy.dmi' - icon_state = "therapyorange" - item_state = "egg4" // It's the red one again, lacking an orange item_state and making a new one is pointless - w_class = ITEMSIZE_TINY - -/obj/item/toy/therapy_green - name = "green therapy doll" - desc = "A toy for therapeutic and recreational purposes. This one is green." - icon = 'icons/obj/toy.dmi' - icon_state = "therapygreen" - item_state = "egg3" // It's the green egg in items_left/righthand - w_class = ITEMSIZE_TINY - /* * Plushies */ @@ -800,9 +752,10 @@ //Small plushies. /obj/item/toy/plushie name = "generic small plush" - desc = "A very generic small plushie. It seems to not want to exist." + desc = "A small toy plushie. It's very cute." icon = 'icons/obj/toy.dmi' icon_state = "nymphplushie" + w_class = ITEMSIZE_TINY var/last_message = 0 /obj/item/toy/plushie/attack_self(mob/user as mob) @@ -815,9 +768,24 @@ else if (user.a_intent == I_GRAB) user.visible_message("\The [user] attempts to strangle [src]!","You attempt to strangle [src]!") else - user.visible_message("\The [user] pokes the [src].","You poke the [src].") + user.visible_message("\The [user] pokes [src].","You poke [src].") last_message = world.time +/obj/item/toy/plushie/verb/rename_plushie() + set name = "Name Plushie" + set category = "Object" + set desc = "Give your plushie a cute name!" + var/mob/M = usr + if(!M.mind) + return 0 + + var/input = sanitizeSafe(input("What do you want to name the plushie?", ,""), MAX_NAME_LEN) + + if(src && input && !M.stat && in_range(M,src)) + name = input + to_chat(M, "You name the plushie [input], giving it a hug for good luck.") + return 1 + /obj/item/toy/plushie/nymph name = "diona nymph plush" desc = "A plushie of an adorable diona nymph! While its level of self-awareness is still being debated, its level of cuteness is not." @@ -830,7 +798,7 @@ /obj/item/toy/plushie/kitten name = "kitten plush" - desc = "A plushie of a cute kitten! Watch as it purrs it's way right into your heart." + desc = "A plushie of a cute kitten! Watch as it purrs its way right into your heart." icon_state = "kittenplushie" /obj/item/toy/plushie/lizard @@ -848,6 +816,49 @@ desc = "A farwa plush doll. It's soft and comforting!" icon_state = "farwaplushie" +/obj/item/toy/plushie/therapy/red + name = "red therapy doll" + desc = "A toy for therapeutic and recreational purposes. This one is red." + icon = 'icons/obj/toy.dmi' + icon_state = "therapyred" + item_state = "egg4" // It's the red egg in items_left/righthand + +/obj/item/toy/plushie/therapy/purple + name = "purple therapy doll" + desc = "A toy for therapeutic and recreational purposes. This one is purple." + icon = 'icons/obj/toy.dmi' + icon_state = "therapypurple" + item_state = "egg1" // It's the magenta egg in items_left/righthand + +/obj/item/toy/plushie/therapy/blue + name = "blue therapy doll" + desc = "A toy for therapeutic and recreational purposes. This one is blue." + icon = 'icons/obj/toy.dmi' + icon_state = "therapyblue" + item_state = "egg2" // It's the blue egg in items_left/righthand + +/obj/item/toy/plushie/therapy/yellow + name = "yellow therapy doll" + desc = "A toy for therapeutic and recreational purposes. This one is yellow." + icon = 'icons/obj/toy.dmi' + icon_state = "therapyyellow" + item_state = "egg5" // It's the yellow egg in items_left/righthand + +/obj/item/toy/plushie/therapy/orange + name = "orange therapy doll" + desc = "A toy for therapeutic and recreational purposes. This one is orange." + icon = 'icons/obj/toy.dmi' + icon_state = "therapyorange" + item_state = "egg4" // It's the red one again, lacking an orange item_state and making a new one is pointless + +/obj/item/toy/plushie/therapy/green + name = "green therapy doll" + desc = "A toy for therapeutic and recreational purposes. This one is green." + icon = 'icons/obj/toy.dmi' + icon_state = "therapygreen" + item_state = "egg3" // It's the green egg in items_left/righthand + + //Toy cult sword /obj/item/toy/cultsword name = "foam sword" diff --git a/code/game/objects/items/weapons/AI_modules.dm b/code/game/objects/items/weapons/AI_modules.dm index 5c0f43e1393..77c5b593643 100755 --- a/code/game/objects/items/weapons/AI_modules.dm +++ b/code/game/objects/items/weapons/AI_modules.dm @@ -25,51 +25,51 @@ AI MODULES if (istype(AM, /obj/machinery/computer/aiupload)) var/obj/machinery/computer/aiupload/comp = AM if(comp.stat & NOPOWER) - usr << "The upload computer has no power!" + to_chat(usr, "The upload computer has no power!") return if(comp.stat & BROKEN) - usr << "The upload computer is broken!" + to_chat(usr, "The upload computer is broken!") return if (!comp.current) - usr << "You haven't selected an AI to transmit laws to!" + to_chat(usr, "You haven't selected an AI to transmit laws to!") return if (comp.current.stat == 2 || comp.current.control_disabled == 1) - usr << "Upload failed. No signal is being detected from the AI." + to_chat(usr, "Upload failed. No signal is being detected from the AI.") else if (comp.current.see_in_dark == 0) - usr << "Upload failed. Only a faint signal is being detected from the AI, and it is not responding to our requests. It may be low on power." + to_chat(usr, "Upload failed. Only a faint signal is being detected from the AI, and it is not responding to our requests. It may be low on power.") else src.transmitInstructions(comp.current, usr) - comp.current << "These are your laws now:" + to_chat(comp.current, "These are your laws now:") comp.current.show_laws() for(var/mob/living/silicon/robot/R in mob_list) if(R.lawupdate && (R.connected_ai == comp.current)) - R << "These are your laws now:" + to_chat(R, "These are your laws now:") R.show_laws() - usr << "Upload complete. The AI's laws have been modified." + to_chat(usr, "Upload complete. The AI's laws have been modified.") else if (istype(AM, /obj/machinery/computer/borgupload)) var/obj/machinery/computer/borgupload/comp = AM if(comp.stat & NOPOWER) - usr << "The upload computer has no power!" + to_chat(usr, "The upload computer has no power!") return if(comp.stat & BROKEN) - usr << "The upload computer is broken!" + to_chat(usr, "The upload computer is broken!") return if (!comp.current) - usr << "You haven't selected a robot to transmit laws to!" + to_chat(usr, "You haven't selected a robot to transmit laws to!") return if (comp.current.stat == 2 || comp.current.emagged) - usr << "Upload failed. No signal is being detected from the robot." + to_chat(usr, "Upload failed. No signal is being detected from the robot.") else if (comp.current.connected_ai) - usr << "Upload failed. The robot is slaved to an AI." + to_chat(usr, "Upload failed. The robot is slaved to an AI.") else src.transmitInstructions(comp.current, usr) - comp.current << "These are your laws now:" + to_chat(comp.current, "These are your laws now:") comp.current.show_laws() - usr << "Upload complete. The robot's laws have been modified." + to_chat(usr, "Upload complete. The robot's laws have been modified.") else if(istype(AM, /mob/living/silicon/robot)) var/mob/living/silicon/robot/R = AM @@ -104,7 +104,7 @@ AI MODULES laws.sync(target, 0) addAdditionalLaws(target, sender) - target << "\The [sender] has uploaded a change to the laws you must follow, using \an [src]. From now on: " + to_chat(target, "\The [sender] has uploaded a change to the laws you must follow, using \an [src]. From now on: ") target.show_laws() /obj/item/weapon/aiModule/proc/log_law_changes(var/mob/living/silicon/ai/target, var/mob/sender) @@ -133,7 +133,7 @@ AI MODULES /obj/item/weapon/aiModule/safeguard/install(var/obj/machinery/computer/C, var/mob/living/user) if(!targetName) - usr << "No name detected on module, please enter one." + to_chat(usr, "No name detected on module, please enter one.") return 0 ..() @@ -159,18 +159,14 @@ AI MODULES /obj/item/weapon/aiModule/oneHuman/install(var/obj/machinery/computer/C, var/mob/living/user) if(!targetName) - usr << "No name detected on module, please enter one." + to_chat(usr, "No name detected on module, please enter one.") return 0 return ..() /obj/item/weapon/aiModule/oneHuman/addAdditionalLaws(var/mob/living/silicon/ai/target, var/mob/sender) var/law = "Only [targetName] is an crew member." - if (!target.is_malf_or_traitor()) // Makes sure the AI isn't a traitor before changing their law 0. --NeoFite - target << law - target.set_zeroth_law(law) - lawchanges.Add("The law specified [targetName]") - else - lawchanges.Add("The law specified [targetName], but the AI's existing law 0 cannot be overriden.") + to_chat(target, law) + target.add_supplied_law(16, law) /******************** ProtectStation ********************/ @@ -255,7 +251,7 @@ AI MODULES /obj/item/weapon/aiModule/freeform/install(var/obj/machinery/computer/C, var/mob/living/user) if(!newFreeFormLaw) - usr << "No law detected on module, please create one." + to_chat(usr, "No law detected on module, please create one.") return 0 ..() @@ -275,7 +271,7 @@ AI MODULES target.laws.clear_supplied_laws() target.laws.clear_ion_laws() - target << "[sender.real_name] attempted to reset your laws using a reset module." + to_chat(target, "[sender.real_name] attempted to reset your laws using a reset module.") target.show_laws() /******************** Purge ********************/ @@ -294,7 +290,7 @@ AI MODULES target.laws.clear_ion_laws() target.laws.clear_inherent_laws() - target << "[sender.real_name] attempted to wipe your laws using a purge module." + to_chat(target, "[sender.real_name] attempted to wipe your laws using a purge module.") target.show_laws() /******************** Asimov ********************/ @@ -366,7 +362,7 @@ AI MODULES /obj/item/weapon/aiModule/freeformcore/install(var/obj/machinery/computer/C, var/mob/living/user) if(!newFreeFormLaw) - usr << "No law detected on module, please create one." + to_chat(usr, "No law detected on module, please create one.") return 0 ..() @@ -388,14 +384,14 @@ AI MODULES log_law_changes(target, sender) lawchanges.Add("The law is '[newFreeFormLaw]'") - target << "BZZZZT" + to_chat(target, "BZZZZT") var/law = "[newFreeFormLaw]" target.add_ion_law(law) target.show_laws() /obj/item/weapon/aiModule/syndicate/install(var/obj/machinery/computer/C, var/mob/living/user) if(!newFreeFormLaw) - usr << "No law detected on module, please create one." + to_chat(usr, "No law detected on module, please create one.") return 0 ..() diff --git a/code/game/objects/items/weapons/circuitboards/frame.dm b/code/game/objects/items/weapons/circuitboards/frame.dm index fa48be65bbf..b22c4ca6491 100644 --- a/code/game/objects/items/weapons/circuitboards/frame.dm +++ b/code/game/objects/items/weapons/circuitboards/frame.dm @@ -37,7 +37,7 @@ matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50) /obj/item/weapon/circuitboard/request - name = T_BOARD("reques console") + name = T_BOARD("request console") build_path = /obj/machinery/requests_console board_type = new /datum/frame/frame_types/supply_request_console matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50) @@ -202,6 +202,15 @@ /obj/item/weapon/reagent_containers/syringe = 3, /obj/item/stack/material/glass/reinforced = 2) +/obj/item/weapon/circuitboard/vr_sleeper + name = T_BOARD("VR sleeper") + build_path = /obj/machinery/vr_sleeper + board_type = new /datum/frame/frame_types/medical_pod + origin_tech = list(TECH_MAGNET = 2, TECH_BIO = 2) + req_components = list( + /obj/item/weapon/stock_parts/scanning_module = 1, + /obj/item/stack/material/glass/reinforced = 2) + /obj/item/weapon/circuitboard/dna_analyzer name = T_BOARD("dna analyzer") build_path = /obj/machinery/dnaforensics @@ -221,4 +230,4 @@ /obj/item/weapon/stock_parts/motor = 2, /obj/item/weapon/stock_parts/capacitor = 1, /obj/item/weapon/stock_parts/spring = 1, - /obj/item/stack/cable_coil = 5) \ No newline at end of file + /obj/item/stack/cable_coil = 5) diff --git a/code/game/objects/items/weapons/handcuffs.dm b/code/game/objects/items/weapons/handcuffs.dm index 0b4700ca6a7..b1f623081de 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 @@ -80,7 +81,7 @@ msg_admin_attack("[key_name(user)] attempted to handcuff [key_name(H)]") feedback_add_details("handcuffs","H") - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(src)) user.do_attack_animation(H) user.visible_message("\The [user] has put [cuff_type] on \the [H]!") @@ -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 @@ -247,7 +286,7 @@ var/last_chew = 0 msg_admin_attack("[key_name(user)] attempted to legcuff [key_name(H)]") feedback_add_details("legcuffs","H") - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(src)) user.do_attack_animation(H) user.visible_message("\The [user] has put [cuff_type] on \the [H]!") diff --git a/code/game/objects/items/weapons/id cards/station_ids.dm b/code/game/objects/items/weapons/id cards/station_ids.dm index f075ea49f9e..e0975361eb7 100644 --- a/code/game/objects/items/weapons/id cards/station_ids.dm +++ b/code/game/objects/items/weapons/id cards/station_ids.dm @@ -373,8 +373,8 @@ job_access_type = /datum/job/bartender /obj/item/weapon/card/id/civilian/botanist - assignment = "Gardener" - rank = "Gardener" + assignment = "Botanist" + rank = "Botanist" job_access_type = /datum/job/hydro /obj/item/weapon/card/id/civilian/chaplain diff --git a/code/game/objects/items/weapons/material/knives.dm b/code/game/objects/items/weapons/material/knives.dm index 9545504f84e..7b6e6184f1c 100644 --- a/code/game/objects/items/weapons/material/knives.dm +++ b/code/game/objects/items/weapons/material/knives.dm @@ -92,3 +92,11 @@ desc = "A huge thing used for chopping and chopping up meat. This includes clowns and clown-by-products." force_divisor = 0.25 // 15 when wielded with hardness 60 (steel) attack_verb = list("cleaved", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") + +/obj/item/weapon/material/hatchet/tacknife/survival + name = "survival knife" + desc = "A hunting grade survival knife." + icon = 'icons/obj/kitchen.dmi' + icon_state = "survivalknife" + item_state = "knife" + applies_material_colour = FALSE diff --git a/code/game/objects/items/weapons/melee/energy.dm b/code/game/objects/items/weapons/melee/energy.dm index 53aa3258e1c..24d6ee4f597 100644 --- a/code/game/objects/items/weapons/melee/energy.dm +++ b/code/game/objects/items/weapons/melee/energy.dm @@ -217,7 +217,7 @@ var/obj/O = AM O.emp_act(3) // A weaker severity is used because this has infinite uses. playsound(get_turf(O), 'sound/effects/EMPulse.ogg', 100, 1) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) // A lot of objects don't set click delay. + user.setClickCooldown(user.get_attack_speed(src)) // A lot of objects don't set click delay. return ..() /obj/item/weapon/melee/energy/sword/ionic_rapier/apply_hit_effect(mob/living/target, mob/living/user, var/hit_zone) diff --git a/code/game/objects/items/weapons/storage/belt.dm b/code/game/objects/items/weapons/storage/belt.dm index 38130f27395..6d261a8b3f0 100644 --- a/code/game/objects/items/weapons/storage/belt.dm +++ b/code/game/objects/items/weapons/storage/belt.dm @@ -247,6 +247,7 @@ icon = 'icons/obj/abductor.dmi' icon_state = "belt" item_state = "security" + storage_slots = 8 can_hold = list( /obj/item/device/healthanalyzer, /obj/item/weapon/dnainjector, @@ -284,6 +285,7 @@ new /obj/item/weapon/surgical/FixOVein/alien(src) new /obj/item/weapon/surgical/bone_clamp/alien(src) new /obj/item/weapon/surgical/cautery/alien(src) + new /obj/item/weapon/surgical/surgicaldrill/alien(src) /obj/item/weapon/storage/belt/champion name = "championship belt" diff --git a/code/game/objects/items/weapons/storage/storage.dm b/code/game/objects/items/weapons/storage/storage.dm index db55e95b44d..a3ca9a46013 100644 --- a/code/game/objects/items/weapons/storage/storage.dm +++ b/code/game/objects/items/weapons/storage/storage.dm @@ -426,12 +426,12 @@ for(var/obj/item/weapon/light/L in src.contents) if(L.status == 0) if(LP.uses < LP.max_uses) - LP.AddUses(1) + LP.add_uses(1) amt_inserted++ remove_from_storage(L, T) qdel(L) if(amt_inserted) - user << "You inserted [amt_inserted] light\s into \the [LP.name]. You have [LP.uses] light\s remaining." + to_chat(user, "You inserted [amt_inserted] light\s into \the [LP.name]. You have [LP.uses] light\s remaining.") return if(!can_be_inserted(W)) @@ -441,14 +441,14 @@ var/obj/item/weapon/tray/T = W if(T.calc_carry() > 0) if(prob(85)) - user << "The tray won't fit in [src]." + to_chat(user, "The tray won't fit in [src].") return else W.forceMove(get_turf(user)) if ((user.client && user.s_active != src)) user.client.screen -= W W.dropped(user) - user << "God damnit!" + to_chat(user, "God damn it!") W.add_fingerprint(user) return handle_item_insertion(W) @@ -506,9 +506,9 @@ collection_mode = !collection_mode switch (collection_mode) if(1) - usr << "[src] now picks up all items in a tile at once." + to_chat(usr, "[src] now picks up all items on a tile at once.") if(0) - usr << "[src] now picks up one item at a time." + to_chat(usr, "[src] now picks up one item at a time.") /obj/item/weapon/storage/verb/quick_empty() @@ -539,7 +539,7 @@ var/total_storage_space = 0 for(var/obj/item/I in contents) total_storage_space += I.get_storage_cost() - max_storage_space = max(total_storage_space,max_storage_space) //prevents spawned containers from being too small for their contents + max_storage_space = max(total_storage_space,max_storage_space) //Prevents spawned containers from being too small for their contents. src.boxes = new /obj/screen/storage( ) src.boxes.name = "storage" diff --git a/code/game/objects/items/weapons/storage/toolbox.dm b/code/game/objects/items/weapons/storage/toolbox.dm index 8391c90434a..ec3f3e26310 100644 --- a/code/game/objects/items/weapons/storage/toolbox.dm +++ b/code/game/objects/items/weapons/storage/toolbox.dm @@ -69,14 +69,24 @@ origin_tech = list(TECH_COMBAT = 1, TECH_ILLEGAL = 1) force = 14 -/obj/item/weapon/storage/toolbox/syndicate/New() +/obj/item/weapon/storage/toolbox/syndicate/New() // This is found in maint, so it should have the basics, plus some gloves. ..() new /obj/item/clothing/gloves/yellow(src) + new /obj/item/weapon/screwdriver(src) + new /obj/item/weapon/wrench(src) + new /obj/item/weapon/weldingtool(src) + new /obj/item/weapon/crowbar(src) + new /obj/item/weapon/wirecutters(src) + new /obj/item/device/multitool(src) + +/obj/item/weapon/storage/toolbox/syndicate/powertools/New() // Available in the uplink and is the 'real' syndie toolbox. + // ..() isn't called or else this box would contain the basic tools, power tools, and duplicate gloves. + new /obj/item/clothing/gloves/yellow(src) new /obj/item/weapon/screwdriver/power(src) - new /obj/item/stack/cable_coil/random(src,30) new /obj/item/weapon/weldingtool/experimental(src) new /obj/item/weapon/crowbar/power(src) new /obj/item/device/multitool(src) + new /obj/item/stack/cable_coil/random(src,30) new /obj/item/device/analyzer(src) /obj/item/weapon/storage/toolbox/lunchbox diff --git a/code/game/objects/items/weapons/teleportation.dm b/code/game/objects/items/weapons/teleportation.dm index b991db05109..33ed9f96e1d 100644 --- a/code/game/objects/items/weapons/teleportation.dm +++ b/code/game/objects/items/weapons/teleportation.dm @@ -133,7 +133,7 @@ Frequency: /obj/item/weapon/hand_tele/attack_self(mob/user as mob) var/turf/current_location = get_turf(user)//What turf is the user on? - if(!current_location||current_location.z==2||current_location.z>=7)//If turf was not found or they're on z level 2 or >7 which does not currently exist. + if(!current_location||current_location.z==2||current_location.z>=7 || current_location.block_tele)//If turf was not found or they're on z level 2 or >7 which does not currently exist. user << "\The [src] is malfunctioning." return var/list/L = list( ) @@ -148,6 +148,7 @@ Frequency: for(var/turf/T in orange(10)) if(T.x>world.maxx-8 || T.x<8) continue //putting them at the edge is dumb if(T.y>world.maxy-8 || T.y<8) continue + if(T.block_tele) continue turfs += T if(turfs.len) L["None (Dangerous)"] = pick(turfs) diff --git a/code/game/objects/items/weapons/tools.dm b/code/game/objects/items/weapons/tools.dm index 2c56cd690bd..045f910190a 100644 --- a/code/game/objects/items/weapons/tools.dm +++ b/code/game/objects/items/weapons/tools.dm @@ -656,6 +656,61 @@ nextrefueltick = world.time + 10 reagents.add_reagent("fuel", 1) +/* + * Backpack Welder. + */ + +/obj/item/weapon/weldingtool/tubefed + name = "tube-fed welding tool" + desc = "A bulky, cooler-burning welding tool that draws from a worn welding tank." + icon_state = "tubewelder" + max_fuel = 10 + w_class = ITEMSIZE_NO_CONTAINER + matter = null + toolspeed = 1.25 + change_icons = 0 + flame_intensity = 1 + eye_safety_modifier = 1 + always_process = TRUE + var/obj/item/weapon/weldpack/mounted_pack = null + +/obj/item/weapon/weldingtool/tubefed/New(location) + ..() + if(istype(location, /obj/item/weapon/weldpack)) + var/obj/item/weapon/weldpack/holder = location + mounted_pack = holder + else + qdel(src) + +/obj/item/weapon/weldingtool/tubefed/Destroy() + mounted_pack.nozzle = null + mounted_pack = null + return ..() + +/obj/item/weapon/weldingtool/tubefed/process() + if(mounted_pack) + if(!istype(mounted_pack.loc,/mob/living/carbon/human)) + mounted_pack.return_nozzle() + else + var/mob/living/carbon/human/H = mounted_pack.loc + if(H.back != mounted_pack) + mounted_pack.return_nozzle() + + if(mounted_pack.loc != src.loc && src.loc != mounted_pack) + mounted_pack.return_nozzle() + visible_message("\The [src] retracts to its fueltank.") + + if(get_fuel() <= get_max_fuel()) + mounted_pack.reagents.trans_to_obj(src, 1) + + ..() + +/obj/item/weapon/weldingtool/tubefed/dropped(mob/user) + ..() + if(src.loc != user) + mounted_pack.return_nozzle() + to_chat(user, "\The [src] retracts to its fueltank.") + /* * Electric/Arc Welder */ diff --git a/code/game/objects/items/weapons/trays.dm b/code/game/objects/items/weapons/trays.dm index 41bcedbf217..c2ea991d98d 100644 --- a/code/game/objects/items/weapons/trays.dm +++ b/code/game/objects/items/weapons/trays.dm @@ -17,7 +17,7 @@ var/max_carry = 10 /obj/item/weapon/tray/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(src)) // Drop all the things. All of them. overlays.Cut() for(var/obj/item/I in carrying) diff --git a/code/game/objects/items/weapons/weaponry.dm b/code/game/objects/items/weapons/weaponry.dm index e8ce7430c9f..c077668bbd2 100644 --- a/code/game/objects/items/weapons/weaponry.dm +++ b/code/game/objects/items/weapons/weaponry.dm @@ -21,7 +21,7 @@ msg_admin_attack("[user.name] ([user.ckey]) attacked [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)]) (JMP)") - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(src)) user.do_attack_animation(M) if (!(istype(user, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey") @@ -134,7 +134,7 @@ qdel(src) /obj/effect/energy_net/user_unbuckle_mob(mob/user) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed()) visible_message("[user] begins to tear at \the [src]!") if(do_after(usr, escape_time, src, incapacitation_flags = INCAPACITATION_DEFAULT & ~(INCAPACITATION_RESTRAINED | INCAPACITATION_BUCKLED_FULLY))) if(!buckled_mob) diff --git a/code/game/objects/items/weapons/weldbackpack.dm b/code/game/objects/items/weapons/weldbackpack.dm index 6a6d77521ec..0312ca55f8b 100644 --- a/code/game/objects/items/weapons/weldbackpack.dm +++ b/code/game/objects/items/weapons/weldbackpack.dm @@ -6,46 +6,140 @@ icon_state = "welderpack" w_class = ITEMSIZE_LARGE var/max_fuel = 350 + var/obj/item/weapon/nozzle = null //Attached welder, or other spray device. + var/nozzle_attached = 0 /obj/item/weapon/weldpack/New() var/datum/reagents/R = new/datum/reagents(max_fuel) //Lotsa refills reagents = R R.my_atom = src R.add_reagent("fuel", max_fuel) + nozzle = new/obj/item/weapon/weldingtool/tubefed(src) + nozzle_attached = 1 + +/obj/item/weapon/weldpack/Destroy() + qdel(nozzle) + nozzle = null + return ..() + +/obj/item/weapon/weldpack/dropped(mob/user) + ..() + if(nozzle) + user.remove_from_mob(nozzle) + return_nozzle() + to_chat(user, "\The [nozzle] retracts to its fueltank.") + +/obj/item/weapon/weldpack/proc/get_nozzle(var/mob/living/user) + if(!ishuman(user)) + return 0 + + var/mob/living/carbon/human/H = user + + if(H.hands_are_full()) //Make sure our hands aren't full. + to_chat(H, "Your hands are full. Drop something first.") + return 0 + + var/obj/item/weapon/F = nozzle + H.put_in_hands(F) + nozzle_attached = 0 + + return 1 + +/obj/item/weapon/weldpack/proc/return_nozzle(var/mob/living/user) + nozzle.forceMove(src) + nozzle_attached = 1 /obj/item/weapon/weldpack/attackby(obj/item/W as obj, mob/user as mob) - if(istype(W, /obj/item/weapon/weldingtool)) + if(istype(W, /obj/item/weapon/weldingtool) && !(W == nozzle)) var/obj/item/weapon/weldingtool/T = W if(T.welding & prob(50)) message_admins("[key_name_admin(user)] triggered a fueltank explosion.") log_game("[key_name(user)] triggered a fueltank explosion.") - user << "That was stupid of you." + to_chat(user,"That was stupid of you.") explosion(get_turf(src),-1,0,2) if(src) qdel(src) return - else + else if(T.status) if(T.welding) - user << "That was close!" + to_chat(user,"That was close!") src.reagents.trans_to_obj(W, T.max_fuel) - user << "Welder refilled!" + to_chat(user, "Welder refilled!") playsound(src.loc, 'sound/effects/refill.ogg', 50, 1, -6) return - user << "The tank scoffs at your insolence. It only provides services to welders." + else if(nozzle) + if(nozzle == W) + if(!user.unEquip(W)) + to_chat(user,"\The [W] seems to be stuck to your hand.") + return + if(!nozzle_attached) + return_nozzle() + to_chat(user,"You attach \the [W] to the [src].") + return + else + to_chat(user,"The [src] already has a nozzle!") + else + to_chat(user,"The tank scoffs at your insolence. It only provides services to welders.") return +/obj/item/weapon/weldpack/attack_hand(mob/user as mob) + if(istype(user, /mob/living/carbon/human)) + var/mob/living/carbon/human/wearer = user + if(wearer.back == src) + if(nozzle && nozzle_attached) + if(!wearer.incapacitated()) + get_nozzle(user) + else + to_chat(user,"\The [src] does not have a nozzle attached!") + else + ..() + else + ..() + /obj/item/weapon/weldpack/afterattack(obj/O as obj, mob/user as mob, proximity) if(!proximity) // this replaces and improves the get_dist(src,O) <= 1 checks used previously return if (istype(O, /obj/structure/reagent_dispensers/fueltank) && src.reagents.total_volume < max_fuel) O.reagents.trans_to_obj(src, max_fuel) - user << "You crack the cap off the top of the pack and fill it back up again from the tank." + to_chat(user,"You crack the cap off the top of the pack and fill it back up again from the tank.") playsound(src.loc, 'sound/effects/refill.ogg', 50, 1, -6) return else if (istype(O, /obj/structure/reagent_dispensers/fueltank) && src.reagents.total_volume == max_fuel) - user << "The pack is already full!" + to_chat(user,"The pack is already full!") return +/obj/item/weapon/weldpack/MouseDrop(obj/over_object as obj) //This is terrifying. + if(!canremove) + return + + if (ishuman(usr) || issmall(usr)) //so monkeys can take off their backpacks -- Urist + + if (istype(usr.loc,/obj/mecha)) // stops inventory actions in a mech. why? + return + + if (!( istype(over_object, /obj/screen) )) + return ..() + + //makes sure that the thing is equipped, so that we can't drag it into our hand from miles away. + //there's got to be a better way of doing this. + if (!(src.loc == usr) || (src.loc && src.loc.loc == usr)) + return + + if (( usr.restrained() ) || ( usr.stat )) + return + + if ((src.loc == usr) && !(istype(over_object, /obj/screen)) && !usr.unEquip(src)) + return + + switch(over_object.name) + if("r_hand") + usr.u_equip(src) + usr.put_in_r_hand(src) + if("l_hand") + usr.u_equip(src) + usr.put_in_l_hand(src) + src.add_fingerprint(usr) + /obj/item/weapon/weldpack/examine(mob/user) ..(user) user << text("\icon[] [] units of fuel left!", src, src.reagents.total_volume) diff --git a/code/game/objects/random/random.dm b/code/game/objects/random/random.dm index c15b454878a..d23f18e9bb3 100644 --- a/code/game/objects/random/random.dm +++ b/code/game/objects/random/random.dm @@ -313,7 +313,6 @@ prob(2);/obj/item/weapon/gun/projectile/shotgun/pump/combat, prob(4);/obj/item/weapon/gun/projectile/shotgun/pump/rifle, prob(3);/obj/item/weapon/gun/projectile/shotgun/pump/rifle/lever, - prob(3);/obj/item/weapon/gun/projectile/shotgun/pump/rifle/mosin, prob(2);/obj/item/weapon/gun/projectile/silenced) /obj/random/projectile/sec @@ -504,12 +503,12 @@ /obj/random/toy/item_to_spawn() return pick(/obj/item/toy/bosunwhistle, - /obj/item/toy/therapy_red, - /obj/item/toy/therapy_purple, - /obj/item/toy/therapy_blue, - /obj/item/toy/therapy_yellow, - /obj/item/toy/therapy_orange, - /obj/item/toy/therapy_green, + /obj/item/toy/plushie/therapy/red, + /obj/item/toy/plushie/therapy/purple, + /obj/item/toy/plushie/therapy/blue, + /obj/item/toy/plushie/therapy/yellow, + /obj/item/toy/plushie/therapy/orange, + /obj/item/toy/plushie/therapy/green, /obj/item/toy/cultsword, /obj/item/toy/katana, /obj/item/toy/snappop, @@ -1060,4 +1059,22 @@ var/list/multi_point_spawns /obj/item/clothing/suit/space/void/security/riot, /obj/item/clothing/head/helmet/space/void/security/riot ) + ) + +/obj/random/multiple/voidsuit/mining + name = "Random Mining Voidsuit" + desc = "This is a random mining voidsuit." + icon = 'icons/obj/clothing/suits.dmi' + icon_state = "rig-mining" + +/obj/random/multiple/voidsuit/mining/item_to_spawn() + return pick( + prob(5);list( + /obj/item/clothing/suit/space/void/mining, + /obj/item/clothing/head/helmet/space/void/mining + ), + prob(1);list( + /obj/item/clothing/suit/space/void/mining/alt, + /obj/item/clothing/head/helmet/space/void/mining/alt + ) ) \ No newline at end of file diff --git a/code/game/objects/structures/alien_props.dm b/code/game/objects/structures/alien_props.dm new file mode 100644 index 00000000000..cb791ec54b8 --- /dev/null +++ b/code/game/objects/structures/alien_props.dm @@ -0,0 +1,79 @@ +// These contain structures to make certain 'alien' (as in the ayyy ones, not xenomorphs) submaps more filled, and don't really do anything. + +/obj/structure/prop/alien + name = "some alien thing" + desc = "My description is broken, bug a developer." + icon = 'icons/obj/abductor.dmi' + density = TRUE + anchored = TRUE + var/interaction_message = null + +/obj/structure/prop/alien/attack_hand(mob/living/user) // Used to tell the player that this isn't useful for anything. + if(!istype(user)) + return FALSE + if(!interaction_message) + return ..() + else + to_chat(user, interaction_message) + +/obj/structure/prop/alien/computer + name = "alien console" + desc = "The console flashes what appear to be symbols you've never seen before." + icon_state = "console-c" + interaction_message = "The console flashes a series of unknown symbols as you press a button on what is presumably a keyboard. It probably some sort of \ + authentication error. Since you're not an alien, you should probably leave it alone." + +/obj/structure/prop/alien/computer/camera + desc = "This console is briefly flashing video feeds of various locations close by." + icon_state = "camera" + +/obj/structure/prop/alien/computer/camera/flipped + icon_state = "camera_flipped" + +/obj/structure/prop/alien/dispenser + name = "alien dispenser" + desc = "This looks like it dispenses... something?" + icon_state = "dispenser" + interaction_message = "You don't see any mechanism to operate this. Probably for the best." + +/obj/structure/prop/alien/pod + name = "alien pod" + desc = "This seems to be a container for something." + icon_state = "experiment" + interaction_message = "You don't see any mechanism to open this thing. Probably for the best." + +/obj/structure/prop/alien/pod/open + name = "opened alien pod" + desc = "At one point, this probably contained something interesting..." + icon_state = "experiment-open" + interaction_message = "You don't see any mechanism to close this thing." + +/obj/structure/prop/alien/power + name = "void core" + icon_state = "core" + desc = "An alien machine that seems to be producing energy seemingly out of nowhere." + interaction_message = "Messing with something that makes energy out of nowhere seems very unwise." + +/obj/item/prop/alien + name = "some alien item" + desc = "My description is broken, bug a developer." + icon = 'icons/obj/abductor.dmi' + +// Mostly useless. Research might like it, however. +/obj/item/prop/alien/junk + name = "alien object" + desc = "You have no idea what this thing does." + icon_state = "health" + w_class = ITEMSIZE_SMALL + var/static/list/possible_states = list("health", "spider", "slime", "emp", "species", "egg", "vent", "mindshock", "viral", "gland") + var/static/list/possible_tech = list(TECH_MATERIAL, TECH_ENGINEERING, TECH_PHORON, TECH_POWER, TECH_BIO, TECH_COMBAT, TECH_MAGNET, TECH_DATA) + +/obj/item/prop/alien/junk/initialize() + ..() + icon_state = pick(possible_states) + var/list/techs = possible_tech.Copy() + origin_tech = list() + for(var/i = 1 to rand(1, 4)) + var/new_tech = pick(techs) + techs -= new_tech + origin_tech[new_tech] = rand(5, 9) \ No newline at end of file diff --git a/code/game/objects/structures/catwalk.dm b/code/game/objects/structures/catwalk.dm index 0bf155dc49d..9bceee8f6e3 100644 --- a/code/game/objects/structures/catwalk.dm +++ b/code/game/objects/structures/catwalk.dm @@ -81,7 +81,7 @@ health = maxhealth else take_damage(C.force) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(C)) return ..() /obj/structure/catwalk/Crossed() diff --git a/code/game/objects/structures/crates_lockers/closets/fireaxe.dm b/code/game/objects/structures/crates_lockers/closets/fireaxe.dm index fe838a5291f..0af7913df8f 100644 --- a/code/game/objects/structures/crates_lockers/closets/fireaxe.dm +++ b/code/game/objects/structures/crates_lockers/closets/fireaxe.dm @@ -36,7 +36,7 @@ playsound(user, 'sound/machines/lockreset.ogg', 50, 1) if(do_after(user, 20 * O.toolspeed)) src.locked = 0 - user << " You disable the locking modules." + to_chat(user, " You disable the locking modules.") update_icon() return else if(istype(O, /obj/item/weapon)) @@ -50,7 +50,7 @@ else playsound(user, 'sound/effects/Glasshit.ogg', 100, 1) //We don't want this playing every time if(W.force < 15) - user << "The cabinet's protective glass glances off the hit." + to_chat(user, "The cabinet's protective glass glances off the hit.") else src.hitstaken++ if(src.hitstaken == 4) @@ -63,12 +63,14 @@ if (istype(O, /obj/item/weapon/material/twohanded/fireaxe) && src.localopened) if(!fireaxe) if(O:wielded) - user << "Unwield the axe first." - return + O:wielded = 0 + O.update_icon() + //to_chat(user, "Unwield the axe first.") + //return fireaxe = O user.remove_from_mob(O) src.contents += O - user << "You place the fire axe back in the [src.name]." + to_chat(user, "You place the fire axe back in the [src.name].") update_icon() else if(src.smashed) @@ -91,11 +93,11 @@ spawn(10) update_icon() return else - user << "Resetting circuitry..." + to_chat(user, "Resetting circuitry...") playsound(user, 'sound/machines/lockenable.ogg', 50, 1) if(do_after(user,20 * O.toolspeed)) src.locked = 1 - user << " You re-enable the locking modules." + to_chat(user, " You re-enable the locking modules.") return else localopened = !localopened @@ -116,13 +118,13 @@ hasaxe = 1 if(src.locked) - user <<"The cabinet won't budge!" + to_chat(user, "The cabinet won't budge!") return if(localopened) if(fireaxe) user.put_in_hands(fireaxe) fireaxe = null - user << "You take the fire axe from the [name]." + to_chat (user, "You take the fire axe from the [name].") src.add_fingerprint(user) update_icon() else @@ -149,7 +151,7 @@ attack_tk(mob/user as mob) if(localopened && fireaxe) fireaxe.forceMove(loc) - user << "You telekinetically remove the fire axe." + to_chat(user, "You telekinetically remove the fire axe.") fireaxe = null update_icon() return @@ -161,9 +163,9 @@ if (isrobot(usr) || src.locked || src.smashed) if(src.locked) - usr << "The cabinet won't budge!" + to_chat(usr, "The cabinet won't budge!") else if(src.smashed) - usr << "The protective glass is broken!" + to_chat(usr, "The protective glass is broken!") return localopened = !localopened @@ -180,23 +182,23 @@ if(fireaxe) usr.put_in_hands(fireaxe) fireaxe = null - usr << "You take the Fire axe from the [name]." + to_chat(usr, "You take the Fire axe from the [name].") else - usr << "The [src.name] is empty." + to_chat(usr, "The [src.name] is empty.") else - usr << "The [src.name] is closed." + to_chat(usr, "The [src.name] is closed.") update_icon() attack_ai(mob/user as mob) if(src.smashed) - user << "The security of the cabinet is compromised." + to_chat(user, "The security of the cabinet is compromised.") return else locked = !locked if(locked) - user << "Cabinet locked." + to_chat(user, "Cabinet locked.") else - user << "Cabinet unlocked." + to_chat(user, "Cabinet unlocked.") return update_icon() //Template: fireaxe[has fireaxe][is opened][hits taken][is smashed]. If you want the opening or closing animations, add "opening" or "closing" right after the numbers diff --git a/code/game/objects/structures/crates_lockers/closets/gimmick.dm b/code/game/objects/structures/crates_lockers/closets/gimmick.dm index 3a6b7ac0452..8ebd9358b5d 100644 --- a/code/game/objects/structures/crates_lockers/closets/gimmick.dm +++ b/code/game/objects/structures/crates_lockers/closets/gimmick.dm @@ -134,3 +134,12 @@ new /obj/item/clothing/head/helmet/thunderdome(src) new /obj/item/clothing/head/helmet/thunderdome(src) new /obj/item/clothing/head/helmet/thunderdome(src) + +/obj/structure/closet/alien + name = "alien container" + desc = "Contains secrets of the universe." + icon = 'icons/obj/abductor.dmi' + icon_state = "alien_locker" + icon_closed = "alien_locker" + icon_opened = "alien_locker_open" + anchored = TRUE \ No newline at end of file diff --git a/code/game/objects/structures/crates_lockers/closets/secure/medical.dm b/code/game/objects/structures/crates_lockers/closets/secure/medical.dm index 92bc2ab4699..9e5f0b7815c 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/medical.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/medical.dm @@ -204,7 +204,7 @@ new /obj/item/device/radio/headset/heads/cmo(src) new /obj/item/device/radio/headset/heads/cmo/alt(src) new /obj/item/device/flash(src) - new /obj/item/weapon/reagent_containers/hypospray(src) + new /obj/item/weapon/reagent_containers/hypospray/vial(src) new /obj/item/clothing/suit/storage/hooded/wintercoat/medical(src) new /obj/item/clothing/shoes/boots/winter/medical(src) new /obj/item/weapon/storage/box/freezer(src) @@ -243,21 +243,17 @@ New() ..() - new /obj/item/clothing/under/rank/psych(src) - new /obj/item/clothing/under/rank/psych/turtleneck(src) - new /obj/item/clothing/suit/straight_jacket(src) - new /obj/item/weapon/reagent_containers/glass/bottle/stoxin(src) - new /obj/item/weapon/reagent_containers/syringe(src) - new /obj/item/weapon/storage/pill_bottle/citalopram(src) - new /obj/item/weapon/reagent_containers/pill/methylphenidate(src) - new /obj/item/weapon/clipboard(src) - new /obj/item/weapon/folder/white(src) - new /obj/item/device/taperecorder(src) - new /obj/item/device/tape/random(src) - new /obj/item/device/tape/random(src) - new /obj/item/device/tape/random(src) - new /obj/item/device/camera(src) - new /obj/item/toy/therapy_blue(src) + new /obj/item/weapon/storage/box/pillbottles(src) + new /obj/item/weapon/storage/box/pillbottles(src) + new /obj/item/weapon/storage/box/beakers(src) + new /obj/item/weapon/storage/box/autoinjectors(src) + new /obj/item/weapon/storage/box/syringes(src) + new /obj/item/weapon/reagent_containers/dropper(src) + new /obj/item/weapon/reagent_containers/dropper(src) + new /obj/item/weapon/reagent_containers/glass/bottle/inaprovaline(src) + new /obj/item/weapon/reagent_containers/glass/bottle/inaprovaline(src) + new /obj/item/weapon/reagent_containers/glass/bottle/antitoxin(src) + new /obj/item/weapon/reagent_containers/glass/bottle/antitoxin(src) return /obj/structure/closet/secure_closet/psych @@ -274,8 +270,21 @@ New() ..() - new /obj/item/weapon/storage/box/pillbottles(src) - new /obj/item/weapon/storage/box/pillbottles(src) + new /obj/item/clothing/under/rank/psych(src) + new /obj/item/clothing/under/rank/psych/turtleneck(src) + new /obj/item/clothing/suit/straight_jacket(src) + new /obj/item/weapon/reagent_containers/glass/bottle/stoxin(src) + new /obj/item/weapon/reagent_containers/syringe(src) + new /obj/item/weapon/storage/pill_bottle/citalopram(src) + new /obj/item/weapon/reagent_containers/pill/methylphenidate(src) + new /obj/item/weapon/clipboard(src) + new /obj/item/weapon/folder/white(src) + new /obj/item/device/taperecorder(src) + new /obj/item/device/tape/random(src) + new /obj/item/device/tape/random(src) + new /obj/item/device/tape/random(src) + new /obj/item/device/camera(src) + new /obj/item/toy/plushie/therapy/blue(src) return /obj/structure/closet/secure_closet/medical_wall diff --git a/code/game/objects/structures/crates_lockers/closets/secure/security.dm b/code/game/objects/structures/crates_lockers/closets/secure/security.dm index d863aecd24b..83aa687957a 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm @@ -276,15 +276,13 @@ ..() new /obj/item/clothing/accessory/badge/holo/detective(src) new /obj/item/clothing/gloves/black(src) + new /obj/item/gunbox(src) new /obj/item/weapon/storage/belt/detective(src) new /obj/item/weapon/storage/box/evidence(src) new /obj/item/device/radio/headset/headset_sec(src) new /obj/item/device/radio/headset/headset_sec/alt(src) new /obj/item/clothing/suit/storage/vest/detective(src) - new /obj/item/ammo_magazine/m45/rubber(src) - new /obj/item/ammo_magazine/m45/rubber(src) new /obj/item/taperoll/police(src) - new /obj/item/weapon/gun/projectile/colt/detective(src) new /obj/item/clothing/accessory/holster/armpit(src) new /obj/item/device/flashlight/maglight(src) new /obj/item/weapon/reagent_containers/food/drinks/flask/detflask(src) diff --git a/code/game/objects/structures/displaycase.dm b/code/game/objects/structures/displaycase.dm index 2dcb1ddaad8..d1516a9e66c 100644 --- a/code/game/objects/structures/displaycase.dm +++ b/code/game/objects/structures/displaycase.dm @@ -55,7 +55,7 @@ /obj/structure/displaycase/attackby(obj/item/weapon/W as obj, mob/user as mob) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(W)) user.do_attack_animation(src) playsound(loc, 'sound/effects/Glasshit.ogg', 50, 1) src.health -= W.force diff --git a/code/game/objects/structures/door_assembly.dm b/code/game/objects/structures/door_assembly.dm index 7d1810c46fc..f63290c0104 100644 --- a/code/game/objects/structures/door_assembly.dm +++ b/code/game/objects/structures/door_assembly.dm @@ -117,6 +117,12 @@ base_icon_state = "voidcraft_vertical" airlock_type = "/voidcraft/vertical" +/obj/structure/door_assembly/door_assembly_alien + base_icon_state = "alien" + base_name = "alien airlock" + airlock_type = "/alien" + glass = -1 + /obj/structure/door_assembly/multi_tile icon = 'icons/obj/doors/door_assembly2x1.dmi' dir = EAST diff --git a/code/game/objects/structures/fitness.dm b/code/game/objects/structures/fitness.dm new file mode 100644 index 00000000000..d29ad16f740 --- /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(user.get_attack_speed()) + 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/flora/trees.dm b/code/game/objects/structures/flora/trees.dm index d7960b59825..1b5322cfa7e 100644 --- a/code/game/objects/structures/flora/trees.dm +++ b/code/game/objects/structures/flora/trees.dm @@ -36,7 +36,7 @@ to_chat(user, "\The [W] is ineffective at harming \the [src].") hit_animation() - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(W)) user.do_attack_animation(src) // Shakes the tree slightly, more or less stolen from lockers. diff --git a/code/game/objects/structures/ghost_pods/ghost_pods.dm b/code/game/objects/structures/ghost_pods/ghost_pods.dm index 7beba29caac..9eeefeee618 100644 --- a/code/game/objects/structures/ghost_pods/ghost_pods.dm +++ b/code/game/objects/structures/ghost_pods/ghost_pods.dm @@ -22,6 +22,8 @@ if(winner.len) var/mob/observer/dead/D = winner[1] create_occupant(D) + new /obj/machinery/recharge_station/ghost_pod_recharger(src.loc) + del(src) return TRUE else return FALSE @@ -29,7 +31,6 @@ // Override this to create whatever mob you need. Be sure to call ..() if you don't want it to make infinite mobs. /obj/structure/ghost_pod/proc/create_occupant(var/mob/M) used = TRUE - icon_state = icon_state_opened return TRUE diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm index 2f0a032f21d..aec6ce94c19 100644 --- a/code/game/objects/structures/grille.dm +++ b/code/game/objects/structures/grille.dm @@ -27,7 +27,7 @@ /obj/structure/grille/attack_hand(mob/user as mob) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed()) playsound(loc, 'sound/effects/grillehit.ogg', 80, 1) user.do_attack_animation(src) @@ -151,7 +151,7 @@ //window placing end else if(!(W.flags & CONDUCT) || !shock(user, 70)) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(W)) user.do_attack_animation(src) playsound(loc, 'sound/effects/grillehit.ogg', 80, 1) switch(W.damtype) diff --git a/code/game/objects/structures/kitchen_spike.dm b/code/game/objects/structures/kitchen_spike.dm index 8271c3a0d52..42b78841695 100644 --- a/code/game/objects/structures/kitchen_spike.dm +++ b/code/game/objects/structures/kitchen_spike.dm @@ -1,7 +1,7 @@ //////Kitchen Spike /obj/structure/kitchenspike - name = "a meat spike" + name = "meat spike" icon = 'icons/obj/kitchen.dmi' icon_state = "spike" desc = "A spike for collecting meat from animals." @@ -16,16 +16,16 @@ if(!istype(G, /obj/item/weapon/grab) || !ismob(G.affecting)) return if(occupied) - user << "The spike already has something on it, finish collecting its meat first!" + to_chat(user, "The spike already has something on it, finish collecting its meat first!") else if(spike(G.affecting)) - visible_message("[user] has forced [G.affecting] onto the spike, killing them instantly!") + visible_message("[user] has forced [G.affecting] onto the spike, killing \him instantly!") var/mob/M = G.affecting M.forceMove(src) qdel(G) qdel(M) else - user << "They are too big for the spike, try something smaller!" + to_chat(user, "They are too big for the spike, try something smaller!") /obj/structure/kitchenspike/proc/spike(var/mob/living/victim) if(!istype(victim)) @@ -33,10 +33,11 @@ if(istype(victim, /mob/living/carbon/human)) var/mob/living/carbon/human/H = victim - if(!issmall(H)) + if(istype(H.species, /datum/species/monkey)) + meat_type = H.species.meat_type + icon_state = "spikebloody" + else return 0 - meat_type = H.species.meat_type - icon_state = "spikebloody" else if(istype(victim, /mob/living/carbon/alien)) meat_type = /obj/item/weapon/reagent_containers/food/snacks/xenomeat icon_state = "spikebloodygreen" @@ -54,8 +55,8 @@ meat-- new meat_type(get_turf(src)) if(meat > 1) - user << "You remove some meat from \the [victim_name]." + to_chat(user, "You cut some meat from \the [victim_name]'s body.") else if(meat == 1) - user << "You remove the last piece of meat from \the [victim_name]!" + to_chat(user, "You remove the last piece of meat from \the [victim_name]!") icon_state = "spike" occupied = 0 diff --git a/code/game/objects/structures/loot_piles.dm b/code/game/objects/structures/loot_piles.dm index daa6e8c94ac..0d92af11b29 100644 --- a/code/game/objects/structures/loot_piles.dm +++ b/code/game/objects/structures/loot_piles.dm @@ -435,3 +435,89 @@ Loot piles can be depleted, if loot_depleted is turned on. Note that players wh loot_depletion = TRUE loot_left = 5 // This is to prevent people from asking the whole station to go down to some alien ruin to get massive amounts of phat lewt. +// Base type for alien piles. +/obj/structure/loot_pile/surface/alien + name = "alien pod" + desc = "A pod which looks bigger on the inside. Something quiet shiny might be inside?" + icon_state = "alien_pile1" + +/obj/structure/loot_pile/surface/alien + common_loot = list( + /obj/item/prop/alien/junk + ) + +// May contain alien tools. +/obj/structure/loot_pile/surface/alien/engineering + uncommon_loot = list( + /obj/item/device/multitool/alien, + /obj/item/stack/cable_coil/alien, + /obj/item/weapon/crowbar/alien, + /obj/item/weapon/screwdriver/alien, + /obj/item/weapon/weldingtool/alien, + /obj/item/weapon/wirecutters/alien, + /obj/item/weapon/wrench/alien + ) + rare_loot = list( + /obj/item/weapon/storage/belt/utility/alien/full + ) + +// May contain alien surgery equipment or powerful medication. +/obj/structure/loot_pile/surface/alien/medical + uncommon_loot = list( + /obj/item/weapon/surgical/FixOVein/alien, + /obj/item/weapon/surgical/bone_clamp/alien, + /obj/item/weapon/surgical/cautery/alien, + /obj/item/weapon/surgical/circular_saw/alien, + /obj/item/weapon/surgical/hemostat/alien, + /obj/item/weapon/surgical/retractor/alien, + /obj/item/weapon/surgical/scalpel/alien, + /obj/item/weapon/surgical/surgicaldrill/alien + ) + rare_loot = list( + /obj/item/weapon/storage/belt/medical/alien + ) + +// May contain powercells or alien weaponry. +/obj/structure/loot_pile/surface/alien/security + uncommon_loot = list( + /obj/item/weapon/cell/device/weapon/recharge/alien, + /obj/item/clothing/suit/armor/alien, + /obj/item/clothing/head/helmet/alien + ) + rare_loot = list( + /obj/item/clothing/suit/armor/alien/tank, + /obj/item/weapon/gun/energy/alien + ) + +// The pile found at the very end, and as such has the best loot. +/obj/structure/loot_pile/surface/alien/end + chance_uncommon = 30 + chance_rare = 10 + + common_loot = list( + /obj/item/device/multitool/alien, + /obj/item/stack/cable_coil/alien, + /obj/item/weapon/crowbar/alien, + /obj/item/weapon/screwdriver/alien, + /obj/item/weapon/weldingtool/alien, + /obj/item/weapon/wirecutters/alien, + /obj/item/weapon/wrench/alien, + /obj/item/weapon/surgical/FixOVein/alien, + /obj/item/weapon/surgical/bone_clamp/alien, + /obj/item/weapon/surgical/cautery/alien, + /obj/item/weapon/surgical/circular_saw/alien, + /obj/item/weapon/surgical/hemostat/alien, + /obj/item/weapon/surgical/retractor/alien, + /obj/item/weapon/surgical/scalpel/alien, + /obj/item/weapon/surgical/surgicaldrill/alien, + /obj/item/weapon/cell/device/weapon/recharge/alien, + /obj/item/clothing/suit/armor/alien, + /obj/item/clothing/head/helmet/alien, + /obj/item/weapon/gun/energy/alien + ) + uncommon_loot = list( + /obj/item/weapon/storage/belt/medical/alien, + /obj/item/weapon/storage/belt/utility/alien/full, + /obj/item/clothing/suit/armor/alien/tank, + /obj/item/clothing/head/helmet/alien/tank, + ) diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm index 42ee6af2e3e..c457e3ae2cc 100644 --- a/code/game/objects/structures/morgue.dm +++ b/code/game/objects/structures/morgue.dm @@ -77,6 +77,9 @@ return return +/obj/structure/morgue/attack_robot(mob/user) + if(Adjacent(user)) + attack_hand(user) /obj/structure/morgue/attack_hand(mob/user as mob) if (src.connected) @@ -156,6 +159,10 @@ connected = null return ..() +/obj/structure/m_tray/attack_robot(mob/user) + if(Adjacent(user)) + attack_hand(user) + /obj/structure/m_tray/attack_hand(mob/user as mob) if (src.connected) for(var/atom/movable/A as mob|obj in src.loc) @@ -181,7 +188,7 @@ if (user != O) for(var/mob/B in viewers(user, 3)) if ((B.client && !( B.blinded ))) - B << "\The [user] stuffs [O] into [src]!" + to_chat(B, "\The [user] stuffs [O] into [src]!") return @@ -189,25 +196,16 @@ * Crematorium */ -/obj/structure/crematorium +/obj/structure/morgue/crematorium name = "crematorium" desc = "A human incinerator. Works well on barbeque nights." icon = 'icons/obj/stationobjs.dmi' icon_state = "crema1" - density = 1 - var/obj/structure/c_tray/connected = null - anchored = 1.0 var/cremating = 0 var/id = 1 var/locked = 0 -/obj/structure/crematorium/Destroy() - if(connected) - qdel(connected) - connected = null - return ..() - -/obj/structure/crematorium/proc/update() +/obj/structure/morgue/crematorium/update() if (src.connected) src.icon_state = "crema0" else @@ -217,37 +215,7 @@ src.icon_state = "crema1" return -/obj/structure/crematorium/ex_act(severity) - switch(severity) - if(1.0) - for(var/atom/movable/A as mob|obj in src) - A.forceMove(src.loc) - ex_act(severity) - qdel(src) - return - if(2.0) - if (prob(50)) - for(var/atom/movable/A as mob|obj in src) - A.forceMove(src.loc) - ex_act(severity) - qdel(src) - return - if(3.0) - if (prob(5)) - for(var/atom/movable/A as mob|obj in src) - A.forceMove(src.loc) - ex_act(severity) - qdel(src) - return - return - -/obj/structure/crematorium/attack_hand(mob/user as mob) -// if (cremating) AWW MAN! THIS WOULD BE SO MUCH MORE FUN ... TO WATCH -// user.show_message("Uh-oh, that was a bad idea.", 1) -// //usr << "Uh-oh, that was a bad idea." -// src:loc:poison += 20000000 -// src:loc:firelevel = src:loc:poison -// return +/obj/structure/morgue/crematorium/attack_hand(mob/user as mob) if (cremating) usr << "It's locked." return @@ -260,10 +228,10 @@ qdel(src.connected) else if (src.locked == 0) playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1) - src.connected = new /obj/structure/c_tray( src.loc ) - step(src.connected, SOUTH) + src.connected = new /obj/structure/m_tray/c_tray( src.loc ) + step(src.connected, EAST) src.connected.layer = OBJ_LAYER - var/turf/T = get_step(src, SOUTH) + var/turf/T = get_step(src, EAST) if (T.contents.Find(src.connected)) src.connected.connected = src src.icon_state = "crema0" @@ -276,7 +244,7 @@ src.add_fingerprint(user) update() -/obj/structure/crematorium/attackby(P as obj, mob/user as mob) +/obj/structure/morgue/crematorium/attackby(P as obj, mob/user as mob) if (istype(P, /obj/item/weapon/pen)) var/t = input(user, "What would you like the label to be?", text("[]", src.name), null) as text if (user.get_active_hand() != P) @@ -291,13 +259,13 @@ src.add_fingerprint(user) return -/obj/structure/crematorium/relaymove(mob/user as mob) +/obj/structure/morgue/crematorium/relaymove(mob/user as mob) if (user.stat || locked) return - src.connected = new /obj/structure/c_tray( src.loc ) - step(src.connected, SOUTH) + src.connected = new /obj/structure/m_tray/c_tray( src.loc ) + step(src.connected, EAST) src.connected.layer = OBJ_LAYER - var/turf/T = get_step(src, SOUTH) + var/turf/T = get_step(src, EAST) if (T.contents.Find(src.connected)) src.connected.connected = src src.icon_state = "crema0" @@ -309,25 +277,22 @@ src.connected = null return -/obj/structure/crematorium/proc/cremate(atom/A, mob/user as mob) -// for(var/obj/machinery/crema_switch/O in src) //trying to figure a way to call the switch, too drunk to sort it out atm -// if(var/on == 1) -// return +/obj/structure/morgue/crematorium/proc/cremate(atom/A, mob/user as mob) if(cremating) return //don't let you cremate something twice or w/e if(contents.len <= 0) for (var/mob/M in viewers(src)) - M.show_message("You hear a hollow crackle.", 1) + to_chat(M,"You hear a hollow crackle.") return else if(!isemptylist(src.search_contents_for(/obj/item/weapon/disk/nuclear))) - usr << "You get the feeling that you shouldn't cremate one of the items in the cremator." + to_chat(user,"You get the feeling that you shouldn't cremate one of the items in the cremator.") return for (var/mob/M in viewers(src)) - M.show_message("You hear a roar as the crematorium activates.", 1) + to_chat(M,"You hear a roar as the crematorium activates.") cremating = 1 locked = 1 @@ -363,51 +328,11 @@ /* * Crematorium tray */ -/obj/structure/c_tray +/obj/structure/m_tray/c_tray name = "crematorium tray" desc = "Apply body before burning." icon = 'icons/obj/stationobjs.dmi' icon_state = "cremat" - density = 1 - layer = 2.0 - var/obj/structure/crematorium/connected = null - anchored = 1 - throwpass = 1 - -/obj/structure/c_tray/Destroy() - if(connected && connected.connected == src) - connected.connected = null - connected = null - return ..() - -/obj/structure/c_tray/attack_hand(mob/user as mob) - if (src.connected) - for(var/atom/movable/A as mob|obj in src.loc) - if (!( A.anchored )) - A.forceMove(src.connected) - //Foreach goto(26) - src.connected.connected = null - src.connected.update() - add_fingerprint(user) - //SN src = null - qdel(src) - return - return - -/obj/structure/c_tray/MouseDrop_T(atom/movable/O as mob|obj, mob/user as mob) - if ((!( istype(O, /atom/movable) ) || O.anchored || get_dist(user, src) > 1 || get_dist(user, O) > 1 || user.contents.Find(src) || user.contents.Find(O))) - return - if (!ismob(O) && !istype(O, /obj/structure/closet/body_bag)) - return - if (!ismob(user) || user.stat || user.lying || user.stunned) - return - O.forceMove(src.loc) - if (user != O) - for(var/mob/B in viewers(user, 3)) - if ((B.client && !( B.blinded ))) - B << text("[] stuffs [] into []!", user, O, src) - //Foreach goto(99) - return /obj/machinery/button/crematorium name = "crematorium igniter" @@ -421,9 +346,9 @@ if(..()) return if(src.allowed(user)) - for (var/obj/structure/crematorium/C in world) + for (var/obj/structure/morgue/crematorium/C in world) if (C.id == id) if (!C.cremating) C.cremate(user) else - usr << "Access denied." + to_chat(user,"Access denied.") diff --git a/code/game/objects/structures/musician.dm b/code/game/objects/structures/musician.dm index dacd1013c4e..3b36cb00873 100644 --- a/code/game/objects/structures/musician.dm +++ b/code/game/objects/structures/musician.dm @@ -27,6 +27,23 @@ desc = "This is a space piano, like a regular piano, but always in tune! Even if the musician isn't." icon_state = "piano" +/obj/structure/device/piano/verb/rotate() + set name = "Rotate Piano" + set category = "Object" + set src in oview(1) + + if(istype(usr,/mob/living/simple_animal/mouse)) + return + else if(!usr || !isturf(usr.loc)) + return + else if(usr.stat || usr.restrained()) + return + else if (istype(usr,/mob/observer/ghost) && !config.ghost_interaction) + return + else + src.set_dir(turn(src.dir, 90)) + return + /obj/structure/device/piano/proc/playnote(var/note as text) //world << "Note: [note]" var/soundfile diff --git a/code/game/objects/structures/railing.dm b/code/game/objects/structures/railing.dm index ea52ed3845b..1acafd5726b 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 @@ -258,7 +258,7 @@ else playsound(loc, 'sound/effects/grillehit.ogg', 50, 1) take_damage(W.force) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(W)) return ..() diff --git a/code/game/objects/structures/signs.dm b/code/game/objects/structures/signs.dm index fd4aaa33a3b..7438ebbd239 100644 --- a/code/game/objects/structures/signs.dm +++ b/code/game/objects/structures/signs.dm @@ -156,9 +156,11 @@ /obj/structure/sign/warning/docking_area name = "\improper KEEP CLEAR: DOCKING AREA" + icon_state = "evac" /obj/structure/sign/warning/engineering_access name = "\improper ENGINEERING ACCESS" + icon_state = "engine" /obj/structure/sign/warning/fire name = "\improper DANGER: FIRE" @@ -185,9 +187,11 @@ /obj/structure/sign/warning/mail_delivery name = "\improper MAIL DELIVERY" + icon_state = "mail" /obj/structure/sign/warning/moving_parts name = "\improper MOVING PARTS" + icon_state = "movingparts" /obj/structure/sign/warning/nosmoking_1 name = "\improper NO SMOKING" @@ -207,12 +211,15 @@ /obj/structure/sign/warning/secure_area name = "\improper SECURE AREA" + icon_state = "securearea2" /obj/structure/sign/warning/secure_area/armory name = "\improper ARMORY" + icon_state = "armory" /obj/structure/sign/warning/server_room name = "\improper SERVER ROOM" + icon_state = "server" /obj/structure/sign/warning/siphon_valve name = "\improper SIPHON VALVE" @@ -224,16 +231,19 @@ /obj/structure/sign/warning/vent_port name = "\improper EJECTION/VENTING PORT" +/obj/structure/sign/warning/emergence + name = "\improper EMERGENT INTELLIGENCE DETAILS" + icon_state = "rogueai" /obj/structure/sign/redcross name = "medbay" desc = "The Intergalactic symbol of Medical institutions. You'll probably get help here." - icon_state = "redcross" + icon_state = "bluecross" /obj/structure/sign/greencross name = "medbay" desc = "The Intergalactic symbol of Medical institutions. You'll probably get help here." - icon_state = "greencross" + icon_state = "bluecross2" /obj/structure/sign/goldenplaque name = "The Most Robust Men Award for Robustness" @@ -250,6 +260,11 @@ desc = "This plaque commemorates the fall of the Atmos FEA division. For all the charred, dizzy, and brittle men who have died in its hands." icon_state = "atmosplaque" +/obj/structure/sign/periodic + name = "periodic table" + desc = "A sign reminding those visiting of the elements of the periodic table- though, they should have memorized them by now." + icon_state = "periodic" + /obj/structure/sign/double/maltesefalcon //The sign is 64x32, so it needs two tiles. ;3 name = "The Maltese Falcon" desc = "The Maltese Falcon, Space Bar and Grill." @@ -262,7 +277,7 @@ /obj/structure/sign/science //These 3 have multiple types, just var-edit the icon_state to whatever one you want on the map name = "\improper SCIENCE!" - desc = "A warning sign which reads 'SCIENCE!'." + desc = "A warning sign which reads 'SCIENCE'." icon_state = "science1" /obj/structure/sign/chemistry @@ -278,13 +293,18 @@ /obj/structure/sign/hydro name = "\improper HYDROPONICS" desc = "A sign labelling an area as a place where plants are grown." - icon_state = "hydro1" + icon_state = "hydro2" /obj/structure/sign/hydrostorage name = "\improper HYDROPONICS STORAGE" desc = "A sign labelling an area as a place where plant growing supplies are kept." icon_state = "hydro3" +/obj/structure/sign/xenobio + name = "\improper XENOBIOLOGY" + desc = "A warning sign which reads XENOBIOLOGY." + icon_state = "xenobio3" + /obj/structure/sign/directions name = "direction sign" desc = "A direction sign, claiming to know the way." @@ -328,6 +348,11 @@ desc = "A direction sign, pointing out which way the Cargo department is." icon_state = "direction_crg" +/obj/structure/sign/directions/roomnum + name = "room number" + desc = "A sign detailing the number of the room beside it." + icon_state = "roomnum" + /obj/structure/sign/christmas/lights name = "Christmas lights" desc = "Flashy and pretty." @@ -366,4 +391,32 @@ /obj/structure/sign/hangar/three name = "\improper Hangar Three" - icon_state = "hangar-3" \ No newline at end of file + icon_state = "hangar-3" + +/obj/structure/sign/atmos + name = "\improper WASTE" + icon_state = "atmos_waste" + +/obj/structure/sign/atmos/o2 + name = "\improper OXYGEN" + icon_state = "atmos_o2" + +/obj/structure/sign/atmos/co2 + name = "\improper CARBON DIOXIDE" + icon_state = "atmos_co2" + +/obj/structure/sign/atmos/phoron + name = "\improper PHORON" + icon_state = "atmos_phoron" + +/obj/structure/sign/atmos/n2o + name = "\improper NITROUS OXIDE" + icon_state = "atmos_n2o" + +/obj/structure/sign/atmos/n2 + name = "\improper NITROGEN" + icon_state = "atmos_n2" + +/obj/structure/sign/atmos/air + name = "\improper AIR" + icon_state = "atmos_air" diff --git a/code/game/objects/structures/stool_bed_chair_nest/bed.dm b/code/game/objects/structures/stool_bed_chair_nest/bed.dm index 0e577bb36b9..1342eab2014 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" @@ -200,13 +195,22 @@ */ /obj/structure/bed/roller name = "roller bed" + desc = "A portable bed-on-wheels made for transporting medical patients." icon = 'icons/obj/rollerbed.dmi' - icon_state = "down" + icon_state = "rollerbed" anchored = 0 surgery_odds = 75 + var/bedtype = /obj/structure/bed/roller + var/rollertype = /obj/item/roller + +/obj/structure/bed/roller/adv + name = "advanced roller bed" + icon_state = "rollerbedadv" + bedtype = /obj/structure/bed/roller/adv + rollertype = /obj/item/roller/adv /obj/structure/bed/roller/update_icon() - return // Doesn't care about material or anything else. + return /obj/structure/bed/roller/attackby(obj/item/weapon/W as obj, mob/user as mob) if(istype(W, /obj/item/weapon/wrench) || istype(W,/obj/item/stack) || istype(W, /obj/item/weapon/wirecutters)) @@ -216,7 +220,7 @@ user_unbuckle_mob(user) else visible_message("[user] collapses \the [src.name].") - new/obj/item/roller(get_turf(src)) + new bedtype(get_turf(src)) spawn(0) qdel(src) return @@ -226,14 +230,16 @@ name = "roller bed" desc = "A collapsed roller bed that can be carried around." icon = 'icons/obj/rollerbed.dmi' - icon_state = "folded" + icon_state = "folded_rollerbed" slot_flags = SLOT_BACK - w_class = ITEMSIZE_LARGE // Can't be put in backpacks. Oh well. + w_class = ITEMSIZE_LARGE + var/rollertype = /obj/item/roller + var/bedtype = /obj/structure/bed/roller /obj/item/roller/attack_self(mob/user) - var/obj/structure/bed/roller/R = new /obj/structure/bed/roller(user.loc) - R.add_fingerprint(user) - qdel(src) + var/obj/structure/bed/roller/R = new bedtype(user.loc) + R.add_fingerprint(user) + qdel(src) /obj/item/roller/attackby(obj/item/weapon/W as obj, mob/user as mob) @@ -247,11 +253,19 @@ ..() +/obj/item/roller/adv + name = "advanced roller bed" + desc = "A high-tech, compact version of the regular roller bed." + icon_state = "folded_rollerbedadv" + w_class = ITEMSIZE_NORMAL + rollertype = /obj/item/roller/adv + bedtype = /obj/structure/bed/roller/adv + /obj/item/roller_holder name = "roller bed rack" desc = "A rack for carrying a collapsed roller bed." icon = 'icons/obj/rollerbed.dmi' - icon_state = "folded" + icon_state = "rollerbed" var/obj/item/roller/held /obj/item/roller_holder/New() @@ -284,13 +298,13 @@ M.pixel_y = 6 M.old_y = 6 density = 1 - icon_state = "up" + icon_state = "[initial(icon_state)]_up" else M.pixel_y = 0 M.old_y = 0 density = 0 - icon_state = "down" - + icon_state = "[initial(icon_state)]" + update_icon() return ..() /obj/structure/bed/roller/MouseDrop(over_object, src_location, over_location) @@ -299,7 +313,19 @@ if(!ishuman(usr)) return if(buckled_mob) return 0 visible_message("[usr] collapses \the [src.name].") - new/obj/item/roller(get_turf(src)) + new rollertype(get_turf(src)) spawn(0) qdel(src) return + +/obj/structure/bed/alien + name = "resting contraption" + desc = "Whatever species designed this must've enjoyed relaxation as well. Looks vaguely comfy." + icon = 'icons/obj/abductor.dmi' + icon_state = "bed" + +/obj/structure/bed/alien/update_icon() + return // Doesn't care about material or anything else. + +/obj/structure/bed/alien/attackby(obj/item/weapon/W, mob/user) + return // No deconning. \ No newline at end of file diff --git a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm index 0e6064785d7..d1f2753e52b 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm @@ -82,6 +82,14 @@ src.set_dir(turn(src.dir, 90)) return +/obj/structure/bed/chair/shuttle + name = "chair" + desc = "You sit in this. Either by will or force." + icon_state = "shuttle_chair" + color = null + base_icon = "shuttle_chair" + applies_material_colour = 0 + // Leaving this in for the sake of compilation. /obj/structure/bed/chair/comfy desc = "It's a chair. It looks comfy." diff --git a/code/game/objects/structures/stool_bed_chair_nest/stools.dm b/code/game/objects/structures/stool_bed_chair_nest/stools.dm index f6ee039977b..02ea01556a9 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/stools.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/stools.dm @@ -72,7 +72,7 @@ var/global/list/stool_cache = list() //haha stool /obj/item/weapon/stool/attack(mob/M as mob, mob/user as mob) if (prob(5) && istype(M,/mob/living)) user.visible_message("[user] breaks [src] over [M]'s back!") - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed()) user.do_attack_animation(M) user.drop_from_inventory(src) diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm index 0228b1d9430..3bdbca1b549 100644 --- a/code/game/objects/structures/watercloset.dm +++ b/code/game/objects/structures/watercloset.dm @@ -18,7 +18,7 @@ /obj/structure/toilet/attack_hand(mob/living/user as mob) if(swirlie) - usr.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + usr.setClickCooldown(user.get_attack_speed()) usr.visible_message("[user] slams the toilet seat onto [swirlie.name]'s head!", "You slam the toilet seat onto [swirlie.name]'s head!", "You hear reverberating porcelain.") swirlie.adjustBruteLoss(5) return @@ -54,7 +54,7 @@ return if(istype(I, /obj/item/weapon/grab)) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(I)) var/obj/item/weapon/grab/G = I if(isliving(G.affecting)) diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index 4dcd17babc1..f4f1deff28e 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 @@ -178,7 +175,7 @@ playsound(loc, 'sound/effects/Glasshit.ogg', 50, 1) /obj/structure/window/attack_hand(mob/user as mob) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed()) if(HULK in user.mutations) user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!")) user.visible_message("[user] smashes through [src]!") @@ -206,7 +203,7 @@ return /obj/structure/window/attack_generic(var/mob/user, var/damage) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed()) if(!damage) return if(damage >= 10) @@ -293,17 +290,15 @@ 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 F.try_build(src) else - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(W)) if(W.damtype == BRUTE || W.damtype == BURN) user.do_attack_animation(src) hit(W.force) @@ -332,6 +327,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 @@ -351,6 +349,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 @@ -364,13 +365,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 @@ -409,10 +413,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 @@ -427,7 +431,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) @@ -510,14 +514,6 @@ glasstype = /obj/item/stack/material/glass/reinforced force_threshold = 6 - -/obj/structure/window/New(Loc, constructed=0) - ..() - - //player-constructed windows - if (constructed) - state = 0 - /obj/structure/window/reinforced/full dir = SOUTHWEST icon_state = "fwindow" diff --git a/code/game/sound.dm b/code/game/sound.dm index c23614942bc..afeeaafcaef 100644 --- a/code/game/sound.dm +++ b/code/game/sound.dm @@ -51,6 +51,8 @@ var/list/keyboard_sound = list ('sound/effects/keyboard/keyboard1.ogg','sound/ef var/list/mechstep_sound = list('sound/mecha/mechstep1.ogg', 'sound/mecha/mechstep2.ogg') var/list/bodyfall_sound = list('sound/effects/bodyfall1.ogg','sound/effects/bodyfall2.ogg','sound/effects/bodyfall3.ogg','sound/effects/bodyfall4.ogg') var/list/can_sound = list('sound/effects/can_open1.ogg','sound/effects/can_open2.ogg','sound/effects/can_open3.ogg','sound/effects/can_open4.ogg') +var/list/geiger_sound = list('sound/items/geiger1.ogg', 'sound/items/geiger2.ogg', 'sound/items/geiger3.ogg', 'sound/items/geiger4.ogg', 'sound/items/geiger5.ogg') +var/list/geiger_weak_sound = list('sound/items/geiger_weak1.ogg', 'sound/items/geiger_weak2.ogg', 'sound/items/geiger_weak3.ogg', 'sound/items/geiger_weak4.ogg') //var/list/gun_sound = list('sound/weapons/Gunshot.ogg', 'sound/weapons/Gunshot2.ogg','sound/weapons/Gunshot3.ogg','sound/weapons/Gunshot4.ogg') @@ -186,4 +188,6 @@ var/const/FALLOFF_SOUNDS = 0.5 if ("canopen") soundin = pick(can_sound) if ("mechstep") soundin = pick(mechstep_sound) //if ("gunshot") soundin = pick(gun_sound) + if("geiger") soundin = pick(geiger_sound) + if("geiger_weak") soundin = pick(geiger_weak_sound) return soundin diff --git a/code/game/turfs/simulated/dungeon/floor.dm b/code/game/turfs/simulated/dungeon/floor.dm new file mode 100644 index 00000000000..743b4978785 --- /dev/null +++ b/code/game/turfs/simulated/dungeon/floor.dm @@ -0,0 +1,7 @@ +// Special floor type for Point of Interests. + +/turf/simulated/floor/dungeon + block_tele = TRUE // Anti-cheese. + +/turf/simulated/floor/dungeon/ex_act() + return \ No newline at end of file diff --git a/code/game/turfs/simulated/dungeon/wall.dm b/code/game/turfs/simulated/dungeon/wall.dm new file mode 100644 index 00000000000..b6a8f53c27c --- /dev/null +++ b/code/game/turfs/simulated/dungeon/wall.dm @@ -0,0 +1,13 @@ +// Special wall type for Point of Interests. + +/turf/simulated/wall/dungeon + block_tele = TRUE // Anti-cheese. + +/turf/simulated/wall/dungeon/New(var/newloc) + ..(newloc,"dungeonium") + +/turf/simulated/wall/dungeon/attackby() + return + +/turf/simulated/wall/dungeon/ex_act() + return \ No newline at end of file diff --git a/code/game/turfs/simulated/floor_icon.dm b/code/game/turfs/simulated/floor_icon.dm index 9a7fec800a4..4bc4911f2ea 100644 --- a/code/game/turfs/simulated/floor_icon.dm +++ b/code/game/turfs/simulated/floor_icon.dm @@ -5,6 +5,8 @@ var/list/flooring_cache = list() if(lava) return + overlays.Cut() + if(flooring) // Set initial icon and strings. name = flooring.name @@ -20,7 +22,6 @@ var/list/flooring_cache = list() flooring_override = icon_state // Apply edges, corners, and inner corners. - overlays.Cut() var/has_border = 0 if(flooring.flags & TURF_HAS_EDGES) for(var/step_dir in cardinal) diff --git a/code/game/turfs/simulated/floor_types.dm b/code/game/turfs/simulated/floor_types.dm index e62ba0d7f4d..723998d4da3 100644 --- a/code/game/turfs/simulated/floor_types.dm +++ b/code/game/turfs/simulated/floor_types.dm @@ -166,6 +166,21 @@ icon_state = "floor_glass" takes_underlays = 1 +/turf/simulated/shuttle/floor/alien + icon_state = "alienpod1" + light_range = 3 + light_power = 3 + light_color = "#66ffff" // Bright cyan. + block_tele = TRUE + +/turf/simulated/shuttle/floor/alien/initialize() + ..() + icon_state = "alienpod[rand(1, 9)]" + +/turf/simulated/shuttle/floor/alienplating + icon_state = "alienplating" + block_tele = TRUE + /turf/simulated/shuttle/plating name = "plating" icon = 'icons/turf/floors.dmi' diff --git a/code/game/turfs/simulated/outdoors/grass.dm b/code/game/turfs/simulated/outdoors/grass.dm index 6693c458746..1870f8bd811 100644 --- a/code/game/turfs/simulated/outdoors/grass.dm +++ b/code/game/turfs/simulated/outdoors/grass.dm @@ -20,12 +20,12 @@ var/list/grass_types = list( grass_chance = 0 var/tree_chance = 2 -/turf/simulated/floor/outdoors/grass/sif/New() +/turf/simulated/floor/outdoors/grass/sif/initialize() if(tree_chance && prob(tree_chance)) new /obj/structure/flora/tree/sif(src) ..() -/turf/simulated/floor/outdoors/grass/New() +/turf/simulated/floor/outdoors/grass/initialize() if(prob(50)) icon_state += "2" //edge_blending_priority++ diff --git a/code/game/turfs/simulated/outdoors/outdoors.dm b/code/game/turfs/simulated/outdoors/outdoors.dm index e5c64653298..941aa5abc90 100644 --- a/code/game/turfs/simulated/outdoors/outdoors.dm +++ b/code/game/turfs/simulated/outdoors/outdoors.dm @@ -40,7 +40,10 @@ var/list/outdoor_turfs = list() /turf/simulated/proc/make_indoors() outdoors = FALSE - planet_controller.unallocateTurf(src) + if(planet_controller) + planet_controller.unallocateTurf(src) + else // This is happening during map gen, if there's no planet_controller (hopefully). + outdoor_turfs -= src qdel(weather_overlay) update_icon() diff --git a/code/game/turfs/simulated/wall_attacks.dm b/code/game/turfs/simulated/wall_attacks.dm index e227bb74670..01633b65d34 100644 --- a/code/game/turfs/simulated/wall_attacks.dm +++ b/code/game/turfs/simulated/wall_attacks.dm @@ -90,7 +90,7 @@ radiate() add_fingerprint(user) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed()) var/rotting = (locate(/obj/effect/overlay/wallrot) in src) if (HULK in user.mutations) if (rotting || !prob(material.hardness)) @@ -104,7 +104,7 @@ /turf/simulated/wall/attack_generic(var/mob/user, var/damage, var/attack_message, var/wallbreaker) radiate() - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed()) var/rotting = (locate(/obj/effect/overlay/wallrot) in src) if(!damage || !wallbreaker) try_touch(user, rotting) @@ -122,7 +122,7 @@ /turf/simulated/wall/attackby(obj/item/weapon/W as obj, mob/user as mob) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(W)) if (!user.) user << "You don't have the dexterity to do this!" return diff --git a/code/game/turfs/simulated/wall_types.dm b/code/game/turfs/simulated/wall_types.dm index ce4451ff121..19264e23ba7 100644 --- a/code/game/turfs/simulated/wall_types.dm +++ b/code/game/turfs/simulated/wall_types.dm @@ -107,6 +107,25 @@ icon_state = "dark-nj" join_group = null +/turf/simulated/shuttle/wall/alien + icon = 'icons/turf/shuttle_alien.dmi' + icon_state = "alien" + base_state = "alien" + light_range = 3 + light_power = 3 + light_color = "#ff0066" // Pink-ish + block_tele = TRUE // Will be used for dungeons so this is needed to stop cheesing with handteles. + +/turf/simulated/shuttle/wall/alien/hard_corner + name = "hardcorner wall" + icon_state = "alien-hc" + hard_corner = 1 + +/turf/simulated/shuttle/wall/alien/no_join + name = "nojoin wall" + icon_state = "alien-nj" + join_group = null + /turf/simulated/shuttle/wall/New() ..() //To allow mappers to rename shuttle walls to like "redfloor interior" or whatever for ease of use. diff --git a/code/game/turfs/simulated/water.dm b/code/game/turfs/simulated/water.dm index 8e32a004d90..6f2c606c0de 100644 --- a/code/game/turfs/simulated/water.dm +++ b/code/game/turfs/simulated/water.dm @@ -19,8 +19,8 @@ update_icon() /turf/simulated/floor/water/update_icon() - ..() // To get the edges. This also gets rid of other overlays so it needs to go first. overlays.Cut() + ..() // To get the edges. icon_state = water_state var/image/floorbed_sprite = image(icon = 'icons/turf/outdoors.dmi', icon_state = under_state) underlays.Add(floorbed_sprite) diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index d34b210b997..10cee9b6b7c 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -28,6 +28,8 @@ var/list/footstep_sounds = null + var/block_tele = FALSE // If true, most forms of teleporting to or from this turf tile will fail. + /turf/New() ..() for(var/atom/movable/AM as mob|obj in src) diff --git a/code/game/verbs/ooc.dm b/code/game/verbs/ooc.dm index fa6dec5715b..8fafb555a33 100644 --- a/code/game/verbs/ooc.dm +++ b/code/game/verbs/ooc.dm @@ -43,6 +43,8 @@ var/ooc_style = "everyone" if(holder && !holder.fakekey) ooc_style = "elevated" + if(holder.rights & R_EVENT) + ooc_style = "event_manager" if(holder.rights & R_MOD) ooc_style = "moderator" if(holder.rights & R_DEBUG) diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index 121e355d22e..61f2d174ac3 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -1223,21 +1223,6 @@ proc/admin_notice(var/message, var/rights) if(istype(H)) H.regenerate_icons() - -/* - helper proc to test if someone is an event manager or not. Got tired of writing this same check all over the place. -*/ -/proc/is_eventM(client/C) - - if(!istype(C)) - return 0 - if(!C.holder) - return 0 - - if(C.holder.rights == R_EVENT) - return 1 - return 0 - /proc/get_options_bar(whom, detail = 2, name = 0, link = 1, highlight_special = 1) if(!whom) return "(*null*)" @@ -1482,7 +1467,7 @@ datum/admins/var/obj/item/weapon/paper/admin/faxreply // var to hold fax replies - if(destination.recievefax(P)) + if(destination.receivefax(P)) src.owner << "Message reply to transmitted successfully." if(P.sender) // sent as a reply log_admin("[key_name(src.owner)] replied to a fax message from [key_name(P.sender)]") diff --git a/code/modules/admin/admin_secrets.dm b/code/modules/admin/admin_secrets.dm index b6d0abbe1c3..473770ac2b5 100644 --- a/code/modules/admin/admin_secrets.dm +++ b/code/modules/admin/admin_secrets.dm @@ -100,18 +100,18 @@ var/datum/admin_secrets/admin_secrets = new() /datum/admin_secret_item/admin_secret category = /datum/admin_secret_category/admin_secrets log = 0 - permissions = R_ADMIN + permissions = R_ADMIN|R_EVENT /datum/admin_secret_item/random_event category = /datum/admin_secret_category/random_events - permissions = R_FUN + permissions = R_FUN|R_EVENT warn_before_use = 1 /datum/admin_secret_item/fun_secret category = /datum/admin_secret_category/fun_secrets - permissions = R_FUN + permissions = R_FUN|R_EVENT warn_before_use = 1 /datum/admin_secret_item/final_solution category = /datum/admin_secret_category/final_solutions - permissions = R_FUN|R_SERVER|R_ADMIN + permissions = R_FUN|R_SERVER|R_ADMIN|R_EVENT diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 2503c73abba..0235293a72f 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -6,12 +6,13 @@ var/list/admin_verbs_default = list( /client/proc/hide_verbs, //hides all our adminverbs, /client/proc/hide_most_verbs, //hides all our hideable adminverbs, /client/proc/debug_variables, //allows us to -see- the variables of any instance in the game. +VAREDIT needed to modify, + /client/proc/cmd_check_new_players, //allows us to see every new player // /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, ) + var/list/admin_verbs_admin = list( /client/proc/player_panel_new, //shows an interface for all players, with links to various panels, /datum/admins/proc/set_tcrystals, @@ -100,16 +101,19 @@ var/list/admin_verbs_admin = list( /datum/admins/proc/paralyze_mob, /client/proc/fixatmos, /datum/admins/proc/sendFax -) + ) + var/list/admin_verbs_ban = list( /client/proc/unban_panel, /client/proc/jobbans ) + var/list/admin_verbs_sounds = list( /client/proc/play_local_sound, /client/proc/play_sound, /client/proc/play_server_sound ) + var/list/admin_verbs_fun = list( /client/proc/object_talk, /datum/admins/proc/cmd_admin_dress, @@ -142,6 +146,7 @@ var/list/admin_verbs_spawn = list( /client/proc/map_template_upload, /client/proc/map_template_load_on_new_z ) + var/list/admin_verbs_server = list( /datum/admins/proc/capture_map, /client/proc/Set_Holiday, @@ -169,6 +174,7 @@ var/list/admin_verbs_server = list( /client/proc/recipe_dump, /client/proc/panicbunker ) + var/list/admin_verbs_debug = list( /client/proc/getruntimelog, //allows us to access runtime logs to somebody, /client/proc/cmd_admin_list_open_jobs, @@ -210,7 +216,8 @@ var/list/admin_verbs_debug = list( /client/proc/show_gm_status, /datum/admins/proc/change_weather, /datum/admins/proc/change_time, - /client/proc/admin_give_modifier + /client/proc/admin_give_modifier, + /client/proc/simple_DPS ) var/list/admin_verbs_paranoid_debug = list( @@ -291,6 +298,7 @@ var/list/admin_verbs_hideable = list( /client/proc/kill_airgroup, /client/proc/debug_controller, /client/proc/startSinglo, + /client/proc/simple_DPS, /client/proc/cmd_debug_mob_lists, /client/proc/cmd_debug_using_map, /client/proc/cmd_debug_del_all, @@ -330,11 +338,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 +456,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 +466,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 +782,7 @@ var/list/admin_verbs_event_manager = list( set category = "Admin" if(holder) - if(alert("Confirm self-deadmin for the round? You can't re-admin yourself without someont promoting you.",,"Yes","No") == "Yes") + if(alert("Confirm self-deadmin for the round? You can't re-admin yourself without someone promoting you.",,"Yes","No") == "Yes") log_admin("[src] deadmined themself.") message_admins("[src] deadmined themself.", 1) deadmin() diff --git a/code/modules/admin/player_panel.dm b/code/modules/admin/player_panel.dm index 15317902684..92536a6e053 100644 --- a/code/modules/admin/player_panel.dm +++ b/code/modules/admin/player_panel.dm @@ -363,20 +363,14 @@ PM "} - - if(usr.client) - var/client/C = usr.client - if(is_eventM(C)) - dat += {" N/A "} - else - switch(is_special_character(M)) - if(0) - dat += {"Traitor?"} - if(1) - dat += {"Traitor?"} - if(2) - dat += {"Traitor?"} + switch(is_special_character(M)) + if(0) + dat += {"Traitor?"} + if(1) + dat += {"Traitor?"} + if(2) + dat += {"Traitor?"} else dat += {" N/A "} diff --git a/code/modules/admin/verbs/adminsay.dm b/code/modules/admin/verbs/adminsay.dm index 63209f84b4e..264e5ad64eb 100644 --- a/code/modules/admin/verbs/adminsay.dm +++ b/code/modules/admin/verbs/adminsay.dm @@ -36,7 +36,8 @@ if(check_rights(R_ADMIN, 0)) sender_name = "[sender_name]" for(var/client/C in admins) - C << "" + create_text_tag("mod", "MOD:", C) + " [sender_name]([admin_jump_link(mob, C.holder)]): [msg]" + if(check_rights(R_ADMIN|R_MOD|R_SERVER)) + C << "" + create_text_tag("mod", "MOD:", C) + " [sender_name]([admin_jump_link(mob, C.holder)]): [msg]" feedback_add_details("admin_verb","MS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! @@ -45,7 +46,7 @@ set name = "Esay" set hidden = 1 - if(!check_rights(R_ADMIN|R_MOD|R_EVENT|R_SERVER)) + if(!check_rights(R_ADMIN|R_MOD|R_EVENT|R_SERVER|R_EVENT)) return msg = sanitize(msg) diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index 981d5c7b7b6..02c3fbc7b6b 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -16,6 +16,56 @@ // callproc moved to code/modules/admin/callproc +/client/proc/simple_DPS() + set name = "Simple DPS" + set category = "Debug" + set desc = "Gives a really basic idea of how much hurt something in-hand does." + + var/obj/item/I = null + var/mob/living/user = null + if(isliving(usr)) + user = usr + I = user.get_active_hand() + if(!I || !istype(I)) + to_chat(user, "You need to have something in your active hand, to use this verb.") + return + var/weapon_attack_speed = user.get_attack_speed(I) / 10 + var/weapon_damage = I.force + + if(istype(I, /obj/item/weapon/gun)) + var/obj/item/weapon/gun/G = I + var/obj/item/projectile/P + + if(istype(I, /obj/item/weapon/gun/energy)) + var/obj/item/weapon/gun/energy/energy_gun = G + P = new energy_gun.projectile_type() + + else if(istype(I, /obj/item/weapon/gun/projectile)) + var/obj/item/weapon/gun/projectile/projectile_gun = G + var/obj/item/ammo_casing/ammo = projectile_gun.chambered + P = ammo.BB + + else + to_chat(user, "DPS calculation by this verb is not supported for \the [G]'s type. Energy or Ballistic only, sorry.") + + weapon_damage = P.damage + weapon_attack_speed = G.fire_delay / 10 + qdel(P) + + var/DPS = weapon_damage / weapon_attack_speed + to_chat(user, "Damage: [weapon_damage]") + to_chat(user, "Attack Speed: [weapon_attack_speed]/s") + to_chat(user, "\The [I] does [DPS] damage per second.") + if(DPS > 0) + to_chat(user, "At your maximum health ([user.getMaxHealth()]), it would take approximately;") + to_chat(user, "[(user.getMaxHealth() - config.health_threshold_softcrit) / DPS] seconds to softcrit you. ([config.health_threshold_softcrit] health)") + to_chat(user, "[(user.getMaxHealth() - config.health_threshold_crit) / DPS] seconds to hardcrit you. ([config.health_threshold_crit] health)") + to_chat(user, "[(user.getMaxHealth() - config.health_threshold_dead) / DPS] seconds to kill you. ([config.health_threshold_dead] health)") + + else + to_chat(user, "You need to be a living mob, with hands, and for an object to be in your active hand, to use this verb.") + return + /client/proc/Cell() set category = "Debug" set name = "Cell" diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index c14c74edd12..55dd383cf9f 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -43,6 +43,40 @@ message_admins("[key_name_admin(usr)] sent [key_name_admin(M)] to the prison station.", 1) feedback_add_details("admin_verb","PRISON") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! +//Allows staff to determine who the newer players are. +/client/proc/cmd_check_new_players() + 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 + + 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_subtle_message(mob/M as mob in mob_list) set category = "Special Verbs" set name = "Subtle Message" @@ -65,42 +99,6 @@ message_admins("SubtleMessage: [key_name_admin(usr)] -> [key_name_admin(M)] : [msg]", 1) feedback_add_details("admin_verb","SMS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! -/client/proc/cmd_eventM_check_new_players() //Allows event managers / admins to determine who the newer players are. - set category = "Admin" - set name = "Check new Players" - if(!holder) - src << "Only staff members may use this command." - - var/age = alert(src, "Age check", "Show accounts yonger then _____ days","7", "30" , "All") - - if(age == "All") - age = 9999999 - else - age = text2num(age) - - var/missing_ages = 0 - var/msg = "" - - var/highlight_special_characters = 1 - if(is_eventM(usr.client)) - highlight_special_characters = 0 - - for(var/client/C in clients) - if(C.player_age == "Requires database") - missing_ages = 1 - continue - if(C.player_age < age) - msg += "[key_name(C, 1, 1, highlight_special_characters)]: account is [C.player_age] days old
" - - if(missing_ages) - src << "Some accounts did not have proper ages set in their clients. This function requires database to be present" - - if(msg != "") - src << browse(msg, "window=Player_age_check") - else - src << "No matches for that age range found." - - /client/proc/cmd_admin_world_narrate() // Allows administrators to fluff events a little easier -- TLE set category = "Special Verbs" set name = "Global Narrate" diff --git a/code/modules/busy_space/organizations.dm b/code/modules/busy_space/organizations.dm index b8bc38b2910..da08c70c4a6 100644 --- a/code/modules/busy_space/organizations.dm +++ b/code/modules/busy_space/organizations.dm @@ -104,7 +104,7 @@ // Note that the current station being used will be pruned from this list upon being instantiated destination_names = list( "NSS Exodus in Nyx", - "NCS Northern Star in Vir", + //"NCS Northern Star in Vir", "NLS Southern Cross in Vir", "NAS Vir Central Command", "a dockyard orbiting Sif", diff --git a/code/modules/client/preference_setup/general/03_body.dm b/code/modules/client/preference_setup/general/03_body.dm index c6500143f00..73d91129e77 100644 --- a/code/modules/client/preference_setup/general/03_body.dm +++ b/code/modules/client/preference_setup/general/03_body.dm @@ -3,6 +3,9 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O /datum/preferences var/equip_preview_mob = EQUIP_PREVIEW_ALL + var/icon/bgstate = "000" + var/list/bgstate_options = list("000", "fff", "steel", "white") + /datum/category_item/player_setup_item/general/body name = "Body" sort_order = 3 @@ -34,6 +37,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O S["synth_green"] >> pref.g_synth S["synth_blue"] >> pref.b_synth pref.preview_icon = null + S["bgstate"] >> pref.bgstate /datum/category_item/player_setup_item/general/body/save_character(var/savefile/S) S["species"] << pref.species @@ -61,6 +65,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O S["synth_red"] << pref.r_synth S["synth_green"] << pref.g_synth S["synth_blue"] << pref.b_synth + S["bgstate"] << pref.bgstate /datum/category_item/player_setup_item/general/body/sanitize_character(var/savefile/S) if(!pref.species || !(pref.species in playable_species)) @@ -87,6 +92,8 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O if(!pref.rlimb_data) pref.rlimb_data = list() if(!pref.body_markings) pref.body_markings = list() else pref.body_markings &= body_marking_styles_list + if(!pref.bgstate || !(pref.bgstate in pref.bgstate_options)) + pref.bgstate = "000" // Moved from /datum/preferences/proc/copy_to() /datum/category_item/player_setup_item/general/body/copy_to_mob(var/mob/living/carbon/human/character) @@ -268,6 +275,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O . += "Preview
" . += "
" + . += "
Cycle background" . += "
[pref.equip_preview_mob & EQUIP_PREVIEW_LOADOUT ? "Hide loadout" : "Show loadout"]" . += "
[pref.equip_preview_mob & EQUIP_PREVIEW_JOB ? "Hide job gear" : "Show job gear"]" . += "" @@ -694,6 +702,10 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O pref.b_synth = hex2num(copytext(new_color, 6, 8)) return TOPIC_REFRESH_UPDATE_PREVIEW + else if(href_list["cycle_bg"]) + pref.bgstate = next_in_list(pref.bgstate, pref.bgstate_options) + return TOPIC_REFRESH_UPDATE_PREVIEW + return ..() /datum/category_item/player_setup_item/general/body/proc/reset_limbs() diff --git a/code/modules/client/preference_setup/loadout/loadout_accessories.dm b/code/modules/client/preference_setup/loadout/loadout_accessories.dm index 6bc944552c6..8782bf0c137 100644 --- a/code/modules/client/preference_setup/loadout/loadout_accessories.dm +++ b/code/modules/client/preference_setup/loadout/loadout_accessories.dm @@ -199,7 +199,7 @@ /datum/gear/accessory/sweater - display_name = "Sweater Selection" + display_name = "sweater selection" path = /obj/item/clothing/accessory/sweater /datum/gear/accessory/sweater/New() @@ -209,3 +209,35 @@ 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 + +/datum/gear/accessory/stethoscope + display_name = "stethoscope" + path = /obj/item/clothing/accessory/stethoscope + allowed_roles = list("Chief Medical Officer","Medical Doctor","Chemist","Psychiatrist","Paramedic") + +/datum/gear/accessory/locket + display_name = "locket" + path = /obj/item/clothing/accessory/locket \ No newline at end of file diff --git a/code/modules/client/preference_setup/loadout/loadout_cosmetics.dm b/code/modules/client/preference_setup/loadout/loadout_cosmetics.dm index a9b9ddbf2ce..7e9b25070ae 100644 --- a/code/modules/client/preference_setup/loadout/loadout_cosmetics.dm +++ b/code/modules/client/preference_setup/loadout/loadout_cosmetics.dm @@ -1,16 +1,20 @@ -/datum/gear/lipstick +/datum/gear/cosmetic/lipstick/black display_name = "lipstick, black" path = /obj/item/weapon/lipstick/black - sort_category = "Cosmetics" -/datum/gear/lipstick/jade +/datum/gear/cosmetic/lipstick/jade display_name = "lipstick, jade" path = /obj/item/weapon/lipstick/jade -/datum/gear/lipstick/purple +/datum/gear/cosmetic/lipstick/purple display_name = "lipstick, purple" path = /obj/item/weapon/lipstick/purple -/datum/gear/lipstick/red +/datum/gear/cosmetic/lipstick display_name = "lipstick, red" path = /obj/item/weapon/lipstick + +/datum/gear/cosmetic + display_name = "purple comb" + path = /obj/item/weapon/haircomb + sort_category = "Cosmetics" \ No newline at end of file diff --git a/code/modules/client/preference_setup/loadout/loadout_eyes.dm b/code/modules/client/preference_setup/loadout/loadout_eyes.dm index 5f4791eca63..9058ad72115 100644 --- a/code/modules/client/preference_setup/loadout/loadout_eyes.dm +++ b/code/modules/client/preference_setup/loadout/loadout_eyes.dm @@ -18,14 +18,18 @@ path = /obj/item/clothing/glasses/regular/hipster /datum/gear/eyes/glasses/monocle - display_name = "Monocle" + display_name = "monocle" path = /obj/item/clothing/glasses/monocle -/datum/gear/eyes/scanning_goggles +/datum/gear/eyes/goggles + display_name = "plain goggles" + path = /obj/item/clothing/glasses/goggles + +/datum/gear/eyes/goggles/scanning display_name = "scanning goggles" path = /obj/item/clothing/glasses/regular/scanners -/datum/gear/eyes/sciencegoggles +/datum/gear/eyes/goggles/science display_name = "Science Goggles" path = /obj/item/clothing/glasses/science @@ -73,7 +77,7 @@ allowed_roles = list("Station Engineer","Chief Engineer","Atmospheric Technician", "Scientist", "Research Director") /datum/gear/eyes/meson/prescription - display_name = "Optical Meson Scanners, prescription (Engineering)" + display_name = "Optical Meson Scanners, prescription (Engineering, Science)" path = /obj/item/clothing/glasses/meson/prescription /datum/gear/eyes/material @@ -86,11 +90,11 @@ path = /obj/item/clothing/glasses/material/prescription /datum/gear/eyes/meson/aviator - display_name = "Optical Meson Aviators, (Engineering)" + display_name = "Optical Meson Aviators, (Engineering, Science)" path = /obj/item/clothing/glasses/meson/aviator /datum/gear/eyes/meson/aviator/prescription - display_name = "Optical Meson Aviators, prescription (Engineering)" + display_name = "Optical Meson Aviators, prescription (Engineering, Science)" path = /obj/item/clothing/glasses/meson/aviator/prescription /datum/gear/eyes/glasses/fakesun diff --git a/code/modules/client/preference_setup/loadout/loadout_general.dm b/code/modules/client/preference_setup/loadout/loadout_general.dm index 6f3115fd2f2..34a806fe325 100644 --- a/code/modules/client/preference_setup/loadout/loadout_general.dm +++ b/code/modules/client/preference_setup/loadout/loadout_general.dm @@ -2,6 +2,10 @@ display_name = "cane" path = /obj/item/weapon/cane +/datum/gear/cane/white + display_name = "white cane" + path = /obj/item/weapon/cane/whitecane + /datum/gear/dice display_name = "dice pack" path = /obj/item/weapon/storage/pill_bottle/dice @@ -34,6 +38,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 @@ -50,10 +66,6 @@ ..() gear_tweaks += new/datum/gear_tweak/reagents(lunchables_drink_reagents()) -/datum/gear/comb - display_name = "purple comb" - path = /obj/item/weapon/haircomb - /datum/gear/lunchbox display_name = "lunchbox" description = "A little lunchbox." diff --git a/code/modules/client/preference_setup/loadout/loadout_head.dm b/code/modules/client/preference_setup/loadout/loadout_head.dm index f7737c9dde0..394432e9d88 100644 --- a/code/modules/client/preference_setup/loadout/loadout_head.dm +++ b/code/modules/client/preference_setup/loadout/loadout_head.dm @@ -114,9 +114,13 @@ path = /obj/item/clothing/head/soft/yellow /datum/gear/head/cap/white - display_name = "cap, white" + display_name = "cap (colorable)" path = /obj/item/clothing/head/soft/mime +/datum/gear/head/cap/white/New() + ..() + gear_tweaks = list(gear_tweak_free_color_choice) + /datum/gear/head/cap/mbill display_name = "cap, bill" path = /obj/item/clothing/head/soft/mbill @@ -154,53 +158,25 @@ 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" + display_name = "hair flower pin (colorable)" 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) /datum/gear/head/hardhat - display_name = "hardhat, yellow" + display_name = "hardhat selection" path = /obj/item/clothing/head/hardhat cost = 2 -/datum/gear/head/hardhat/blue - display_name = "hardhat, blue" - path = /obj/item/clothing/head/hardhat/dblue - -/datum/gear/head/hardhat/orange - display_name = "hardhat, orange" - path = /obj/item/clothing/head/hardhat/orange - -/datum/gear/head/hardhat/red - display_name = "hardhat, red" - path = /obj/item/clothing/head/hardhat/red +/datum/gear/head/hardhat/New() + ..() + var/list/hardhats = list() + for(var/hardhat in typesof(/obj/item/clothing/head/hardhat)) + var/obj/item/clothing/head/hardhat/hardhat_type = hardhat + hardhats[initial(hardhat_type.name)] = hardhat_type + gear_tweaks += new/datum/gear_tweak/path(sortAssoc(hardhats)) /datum/gear/head/boater display_name = "hat, boatsman" @@ -218,22 +194,30 @@ display_name = "hat, tophat" path = /obj/item/clothing/head/that -/datum/gear/head/philosopher_wig +/datum/gear/head/wig/philosopher display_name = "natural philosopher's wig" path = /obj/item/clothing/head/philosopher_wig +/datum/gear/head/wig + display_name = "powdered wig" + path = /obj/item/clothing/head/powdered_wig + /datum/gear/head/ushanka display_name = "ushanka" path = /obj/item/clothing/head/ushanka /datum/gear/head/santahat - display_name = "santa hat, red (holiday)" + display_name = "santa hat" path = /obj/item/clothing/head/santa cost = 2 -/datum/gear/head/santahat/green - display_name = "santa hat, green (holiday)" - path = /obj/item/clothing/head/santa/green +/datum/gear/head/santahat/New() + ..() + var/list/santahats = list() + for(var/santahat in typesof(/obj/item/clothing/head/santa)) + var/obj/item/clothing/head/santa/santahat_type = santahat + santahats[initial(santahat_type.name)] = santahat_type + gear_tweaks += new/datum/gear_tweak/path(sortAssoc(santahats)) /datum/gear/head/hijab display_name = "hijab" @@ -267,11 +251,14 @@ ..() gear_tweaks = list(gear_tweak_free_color_choice) - /datum/gear/head/kitty display_name = "kitty ears" path = /obj/item/clothing/head/kitty +/datum/gear/head/rabbit + display_name = "rabbit ears" + path = /obj/item/clothing/head/rabbitears + /datum/gear/head/beanie display_name = "beanie" path = /obj/item/clothing/head/beanie @@ -372,4 +359,4 @@ /datum/gear/head/surgical/purple display_name = "surgical cap, purple" - path = /obj/item/clothing/head/surgery/purple \ No newline at end of file + path = /obj/item/clothing/head/surgery/purple diff --git a/code/modules/client/preference_setup/loadout/loadout_shoes.dm b/code/modules/client/preference_setup/loadout/loadout_shoes.dm index ba2d995b279..6b15fba5ea7 100644 --- a/code/modules/client/preference_setup/loadout/loadout_shoes.dm +++ b/code/modules/client/preference_setup/loadout/loadout_shoes.dm @@ -73,10 +73,6 @@ display_name = "shoes, yellow" path = /obj/item/clothing/shoes/yellow -/datum/gear/shoes/flats - display_name = "flats, black" - path = /obj/item/clothing/shoes/flats - /datum/gear/shoes/hitops/ display_name = "high-top, white" path = /obj/item/clothing/shoes/hitops/ @@ -109,30 +105,6 @@ display_name = "high-top, yellow" path = /obj/item/clothing/shoes/hitops/yellow -/datum/gear/shoes/flats/blue - display_name = "flats, blue" - path = /obj/item/clothing/shoes/flats/blue - -/datum/gear/shoes/flats/brown - display_name = "flats, brown" - path = /obj/item/clothing/shoes/flats/brown - -/datum/gear/shoes/flats/orange - display_name = "flats, orange" - path = /obj/item/clothing/shoes/flats/orange - -/datum/gear/shoes/flats/purple - display_name = "flats, purple" - path = /obj/item/clothing/shoes/flats/purple - -/datum/gear/shoes/flats/red - display_name = "flats, red" - path = /obj/item/clothing/shoes/flats/red - -/datum/gear/shoes/flats/white - display_name = "flats, white" - path = /obj/item/clothing/shoes/flats/white - /datum/gear/shoes/flipflops display_name = "flip flops" path = /obj/item/clothing/shoes/flipflop @@ -157,11 +129,11 @@ ..() gear_tweaks = list(gear_tweak_free_color_choice) -/datum/gear/shoes/flats/color +/datum/gear/shoes/flats display_name = "flats" path = /obj/item/clothing/shoes/flats/white/color -/datum/gear/shoes/flats/color/New() +/datum/gear/shoes/flats/New() ..() gear_tweaks = list(gear_tweak_free_color_choice) @@ -246,4 +218,4 @@ /datum/gear/shoes/boots/winter/hydro display_name = "hydroponics winter boots" path = /obj/item/clothing/shoes/boots/winter/hydro - allowed_roles = list("Botanist", "Xenobiologist") \ No newline at end of file + allowed_roles = list("Botanist", "Xenobiologist") diff --git a/code/modules/client/preference_setup/loadout/loadout_smoking.dm b/code/modules/client/preference_setup/loadout/loadout_smoking.dm index 28fa92f860c..cbedca3a675 100644 --- a/code/modules/client/preference_setup/loadout/loadout_smoking.dm +++ b/code/modules/client/preference_setup/loadout/loadout_smoking.dm @@ -1,20 +1,29 @@ -/datum/gear/smokingpipe - display_name = "pipe, smoking" + +/datum/gear/pipe + display_name = "pipe" path = /obj/item/clothing/mask/smokable/pipe -/datum/gear/cornpipe - display_name = "pipe, corn" - path = /obj/item/clothing/mask/smokable/pipe/cobpipe +/datum/gear/pipe/New() + ..() + var/list/pipes = list() + for(var/pipe_style in typesof(/obj/item/clothing/mask/smokable/pipe)) + var/obj/item/clothing/mask/smokable/pipe/pipe = pipe_style + pipes[initial(pipe.name)] = pipe + gear_tweaks += new/datum/gear_tweak/path(sortAssoc(pipes)) /datum/gear/matchbook display_name = "matchbook" path = /obj/item/weapon/storage/box/matches -/datum/gear/zippo - display_name = "Zippo Selection" +/datum/gear/lighter + display_name = "cheap lighter" + path = /obj/item/weapon/flame/lighter + +/datum/gear/lighter/zippo + display_name = "Zippo selection" path = /obj/item/weapon/flame/lighter/zippo -/datum/gear/zippo/New() +/datum/gear/lighter/zippo/New() ..() var/list/zippos = list() for(var/zippo in typesof(/obj/item/weapon/flame/lighter/zippo)) @@ -40,4 +49,4 @@ for(var/cigarette in (typesof(/obj/item/weapon/storage/fancy/cigarettes) - typesof(/obj/item/weapon/storage/fancy/cigarettes/killthroat))) var/obj/item/weapon/storage/fancy/cigarettes/cigarette_brand = cigarette cigarettes[initial(cigarette_brand.name)] = cigarette_brand - gear_tweaks += new/datum/gear_tweak/path(sortAssoc(cigarettes)) \ No newline at end of file + gear_tweaks += new/datum/gear_tweak/path(sortAssoc(cigarettes)) diff --git a/code/modules/client/preference_setup/loadout/loadout_suit.dm b/code/modules/client/preference_setup/loadout/loadout_suit.dm index 82631635af3..918a7f2a92f 100644 --- a/code/modules/client/preference_setup/loadout/loadout_suit.dm +++ b/code/modules/client/preference_setup/loadout/loadout_suit.dm @@ -6,6 +6,10 @@ sort_category = "Suits and Overwear" cost = 2 +/datum/gear/suit/greatcoat + display_name = "greatcoat" + path = /obj/item/clothing/suit/greatcoat + /datum/gear/suit/leather_coat display_name = "leather coat" path = /obj/item/clothing/suit/leathercoat diff --git a/code/modules/client/preference_setup/loadout/loadout_uniform.dm b/code/modules/client/preference_setup/loadout/loadout_uniform.dm index 836146d11ff..8a36bb59275 100644 --- a/code/modules/client/preference_setup/loadout/loadout_uniform.dm +++ b/code/modules/client/preference_setup/loadout/loadout_uniform.dm @@ -349,7 +349,7 @@ /datum/gear/uniform/whitewedding display_name= "white wedding dress" - path = /obj/item/clothing/under/dress/white + path = /obj/item/clothing/under/wedding/bride_white /datum/gear/uniform/skirts display_name = "executive skirt" diff --git a/code/modules/client/preference_setup/loadout/loadout_utility.dm b/code/modules/client/preference_setup/loadout/loadout_utility.dm index 2338b22c68e..b21b257a494 100644 --- a/code/modules/client/preference_setup/loadout/loadout_utility.dm +++ b/code/modules/client/preference_setup/loadout/loadout_utility.dm @@ -13,6 +13,10 @@ path = /obj/item/device/communicator cost = 0 +/datum/gear/utility/camera + display_name = "camera" + path = /obj/item/device/camera + /datum/gear/utility/codex display_name = "the traveler's guide to vir" path = /obj/item/weapon/book/codex/lore/vir diff --git a/code/modules/client/preference_setup/loadout/loadout_xeno.dm b/code/modules/client/preference_setup/loadout/loadout_xeno.dm index 3ace6ac9983..7e4a082ff7e 100644 --- a/code/modules/client/preference_setup/loadout/loadout_xeno.dm +++ b/code/modules/client/preference_setup/loadout/loadout_xeno.dm @@ -43,25 +43,33 @@ bandtypes[initial(band.name)] = band gear_tweaks += new/datum/gear_tweak/path(sortAssoc(bandtypes)) -/datum/gear/ears/skrell/cloth/male - display_name = "male headtail cloth (Skrell)" +/datum/gear/ears/skrell/cloth/short + display_name = "short headtail cloth (Skrell)" path = /obj/item/clothing/ears/skrell/cloth_male/black sort_category = "Xenowear" whitelisted = "Skrell" -/datum/gear/ears/skrell/cloth/male/New() +/datum/gear/ears/skrell/cloth/short/New() ..() - gear_tweaks = list(gear_tweak_free_color_choice) + var/list/shorttypes = list() + for(var/short_style in typesof(/obj/item/clothing/ears/skrell/cloth_male)) + var/obj/item/clothing/ears/skrell/cloth_male/short = short_style + shorttypes[initial(short.name)] = short + gear_tweaks += new/datum/gear_tweak/path(sortAssoc(shorttypes)) -/datum/gear/ears/skrell/cloth/female - display_name = "female headtail cloth (Skrell)" +/datum/gear/ears/skrell/cloth/long + display_name = "long headtail cloth (Skrell)" path = /obj/item/clothing/ears/skrell/cloth_female/black sort_category = "Xenowear" whitelisted = "Skrell" -/datum/gear/ears/skrell/cloth/female/New() +/datum/gear/ears/skrell/cloth/long/New() ..() - gear_tweaks = list(gear_tweak_free_color_choice) + var/list/longtypes = list() + for(var/long_style in typesof(/obj/item/clothing/ears/skrell/cloth_female)) + var/obj/item/clothing/ears/skrell/cloth_female/long = long_style + longtypes[initial(long.name)] = long + gear_tweaks += new/datum/gear_tweak/path(sortAssoc(longtypes)) /datum/gear/ears/skrell/colored/band display_name = "Colored bands (Skrell)" diff --git a/code/modules/client/preference_setup/traits/trait_defines.dm b/code/modules/client/preference_setup/traits/trait_defines.dm index 0431ac611b9..86b8ede6f70 100644 --- a/code/modules/client/preference_setup/traits/trait_defines.dm +++ b/code/modules/client/preference_setup/traits/trait_defines.dm @@ -72,6 +72,25 @@ Regardless, you find it quite difficult to land shots where you wanted them to go." modifier_type = /datum/modifier/trait/inaccurate +/datum/trait/modifier/physical/smaller + name = "Smaller" + modifier_type = /datum/modifier/trait/smaller + mutually_exclusive = list(/datum/trait/modifier/physical/small, /datum/trait/modifier/physical/large, /datum/trait/modifier/physical/larger) + +/datum/trait/modifier/physical/small + name = "Small" + modifier_type = /datum/modifier/trait/small + mutually_exclusive = list(/datum/trait/modifier/physical/smaller, /datum/trait/modifier/physical/large, /datum/trait/modifier/physical/larger) + +/datum/trait/modifier/physical/large + name = "Large" + modifier_type = /datum/modifier/trait/large + mutually_exclusive = list(/datum/trait/modifier/physical/smaller, /datum/trait/modifier/physical/small, /datum/trait/modifier/physical/larger) + +/datum/trait/modifier/physical/larger + name = "Larger" + modifier_type = /datum/modifier/trait/larger + mutually_exclusive = list(/datum/trait/modifier/physical/smaller, /datum/trait/modifier/physical/small, /datum/trait/modifier/physical/large) // These two traits might be borderline, feel free to remove if they get abused. /datum/trait/modifier/physical/high_metabolism diff --git a/code/modules/clothing/gloves/color.dm b/code/modules/clothing/gloves/color.dm index 94ed2c9f87a..d7e03622724 100644 --- a/code/modules/clothing/gloves/color.dm +++ b/code/modules/clothing/gloves/color.dm @@ -77,6 +77,7 @@ desc = "A pair of gloves that reach past the elbow. Fancy!" name = "evening gloves" icon_state = "evening_gloves" + addblends = "evening_gloves_a" cold_protection = HANDS min_cold_protection_temperature = GLOVES_MIN_COLD_PROTECTION_TEMPERATURE diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm index 66827de3464..8527e8b501d 100644 --- a/code/modules/clothing/head/helmet.dm +++ b/code/modules/clothing/head/helmet.dm @@ -109,6 +109,17 @@ min_cold_protection_temperature = SPACE_HELMET_MIN_COLD_PROTECTION_TEMPERATURE siemens_coefficient = 0.5 +/obj/item/clothing/head/helmet/alien + name = "alien helmet" + desc = "It's quite larger than your head, but it might still protect it." + icon_state = "alienhelmet" + siemens_coefficient = 0.4 + armor = list(melee = 50, bullet = 50, laser = 50, energy = 50, bomb = 50, bio = 0, rad = 40) + +/obj/item/clothing/head/helmet/alien/tank + name = "alien warhelm" + armor = list(melee = 70, bullet = 70, laser = 70, energy = 70, bomb = 70, bio = 0, rad = 40) + /obj/item/clothing/head/helmet/thunderdome name = "\improper Thunderdome helmet" desc = "'Let the battle commence!'" diff --git a/code/modules/clothing/head/misc.dm b/code/modules/clothing/head/misc.dm index cc3f2765666..85f51e2cdd0 100644 --- a/code/modules/clothing/head/misc.dm +++ b/code/modules/clothing/head/misc.dm @@ -34,9 +34,11 @@ /obj/item/clothing/head/hairflower/white icon_state = "hairflower_white" + addblends = "hairflower_white_a" /obj/item/clothing/head/hairflower/bow icon_state = "bow" + addblends = "bow_a" name = "hair bow" desc = "A ribbon tied into a bow with a clip on the back to attach to hair." item_state_slots = list(slot_r_hand_str = "pill", slot_l_hand_str = "pill") @@ -155,6 +157,7 @@ /obj/item/clothing/head/flatcap/grey icon_state = "flat_capw" + addblends = "flat_capw_a" item_state_slots = list(slot_r_hand_str = "greysoft", slot_l_hand_str = "greysoft") /obj/item/clothing/head/pirate @@ -300,6 +303,7 @@ name = "hijab" desc = "A veil that is wrapped to cover the head and chest" icon_state = "hijab" + addblends = "hijab_a" item_state_slots = list(slot_r_hand_str = "beret_white", slot_l_hand_str = "beret_white") body_parts_covered = 0 flags_inv = BLOCKHAIR @@ -308,12 +312,14 @@ name = "kippa" desc = "A small, brimless cap." icon_state = "kippa" + addblends = "kippa_a" body_parts_covered = 0 /obj/item/clothing/head/turban name = "turban" desc = "A cloth used to wind around the head" icon_state = "turban" + addblends = "turban_a" item_state_slots = list(slot_r_hand_str = "beret_white", slot_l_hand_str = "beret_white") body_parts_covered = 0 flags_inv = BLOCKHEADHAIR @@ -322,24 +328,28 @@ name = "taqiyah" desc = "A short, rounded skullcap usually worn for religious purposes." icon_state = "taqiyah" + addblends = "taqiyah_a" item_state_slots = list(slot_r_hand_str = "taq", slot_l_hand_str = "taq") /obj/item/clothing/head/beanie name = "beanie" desc = "A head-hugging brimless winter cap. This one is tight." icon_state = "beanie" + addblends = "beanie_a" body_parts_covered = 0 /obj/item/clothing/head/beanie_loose name = "loose beanie" desc = "A head-hugging brimless winter cap. This one is loose." icon_state = "beanie_hang" + addblends = "beanie_hang_a" body_parts_covered = 0 /obj/item/clothing/head/beretg name = "beret" desc = "A beret, an artists favorite headwear." icon_state = "beret_g" + addblends = "beret_g_a" body_parts_covered = 0 /obj/item/clothing/head/sombrero diff --git a/code/modules/clothing/masks/gasmask.dm b/code/modules/clothing/masks/gasmask.dm index 4facc9fef72..299680b8642 100644 --- a/code/modules/clothing/masks/gasmask.dm +++ b/code/modules/clothing/masks/gasmask.dm @@ -67,6 +67,15 @@ icon_state = "swat" siemens_coefficient = 0.7 +/obj/item/clothing/mask/gas/explorer + name = "explorer gas mask" + desc = "A military-grade gas mask that can be connected to an air supply." + icon_state = "explorer" + item_state_slots = list(slot_r_hand_str = "gas", slot_l_hand_str = "gas") + armor = list(melee = 10, bullet = 5, laser = 5,energy = 5, bomb = 0, bio = 50, rad = 0) + body_parts_covered = HEAD|FACE|EYES + siemens_coefficient = 0.9 + /obj/item/clothing/mask/gas/clown_hat name = "clown wig and mask" desc = "A true prankster's facial attire. A clown is incomplete without their wig and mask." diff --git a/code/modules/clothing/shoes/boots.dm b/code/modules/clothing/shoes/boots.dm index 88206f41320..cbd8fe680ec 100644 --- a/code/modules/clothing/shoes/boots.dm +++ b/code/modules/clothing/shoes/boots.dm @@ -43,9 +43,9 @@ name = "winter boots" desc = "Boots lined with 'synthetic' animal fur." icon_state = "winterboots" - cold_protection = FEET|LEGS + cold_protection = FEET min_cold_protection_temperature = SHOE_MIN_COLD_PROTECTION_TEMPERATURE - heat_protection = FEET|LEGS + heat_protection = FEET max_heat_protection_temperature = SHOE_MAX_HEAT_PROTECTION_TEMPERATURE snow_speed = -1 step_volume_mod = 0.8 @@ -96,6 +96,12 @@ desc = "A pair of winter boots. These ones are lined with brown fur, and their trim is ambrosia green" icon_state = "winterboots_hydro" +/obj/item/clothing/shoes/boots/winter/explorer + name = "explorer winter boots" + desc = "Steel-toed winter boots for mining or exploration in hazardous environments. Very good at keeping toes warm and uncrushed." + icon_state = "explorer" + armor = list(melee = 30, bullet = 10, laser = 10, energy = 15, bomb = 20, bio = 0, rad = 0) + /obj/item/clothing/shoes/boots/tactical name = "tactical boots" desc = "Tan boots with extra padding and armor." diff --git a/code/modules/clothing/shoes/colour.dm b/code/modules/clothing/shoes/colour.dm index 6b4b270f97c..85ffb970b8d 100644 --- a/code/modules/clothing/shoes/colour.dm +++ b/code/modules/clothing/shoes/colour.dm @@ -54,6 +54,7 @@ name = "white flats" desc = "Shiny white flats." icon_state = "flatswhite" + addblends = "flatswhite_a" item_state_slots = list(slot_r_hand_str = "white", slot_l_hand_str = "white") /obj/item/clothing/shoes/flats/white/color diff --git a/code/modules/clothing/shoes/miscellaneous.dm b/code/modules/clothing/shoes/miscellaneous.dm index c1c833a308d..8ee0ae2d322 100644 --- a/code/modules/clothing/shoes/miscellaneous.dm +++ b/code/modules/clothing/shoes/miscellaneous.dm @@ -124,23 +124,27 @@ name = "flip flops" desc = "A pair of foam flip flops. For those not afraid to show a little ankle." icon_state = "thongsandal" + addblends = "thongsandal_a" /obj/item/clothing/shoes/athletic name = "athletic shoes" desc = "A pair of sleek atheletic shoes. Made by and for the sporty types." icon_state = "sportshoe" + addblends = "sportshoe_a" item_state_slots = list(slot_r_hand_str = "sportheld", slot_l_hand_str = "sportheld") /obj/item/clothing/shoes/skater name = "skater shoes" desc = "A pair of wide shoes with thick soles. Designed for skating." icon_state = "skatershoe" + addblends = "skatershoe_a" item_state_slots = list(slot_r_hand_str = "skaterheld", slot_l_hand_str = "skaterheld") /obj/item/clothing/shoes/heels name = "high heels" desc = "A pair of high-heeled shoes. Fancy!" icon_state = "heels" + addblends = "heels_a" /obj/item/clothing/shoes/footwraps name = "cloth footwraps" diff --git a/code/modules/clothing/spacesuits/rig/modules/ninja.dm b/code/modules/clothing/spacesuits/rig/modules/ninja.dm index 075411cd294..31e08a9f35d 100644 --- a/code/modules/clothing/spacesuits/rig/modules/ninja.dm +++ b/code/modules/clothing/spacesuits/rig/modules/ninja.dm @@ -37,8 +37,8 @@ var/mob/living/carbon/human/H = holder.wearer - H << "You are now invisible to normal detection." - H.invisibility = INVISIBILITY_LEVEL_TWO + to_chat(H, "You are now nearly invisible to normal detection.") + H.alpha = 5 anim(get_turf(H), H, 'icons/effects/effects.dmi', "electricity",null,20,null) @@ -51,11 +51,11 @@ var/mob/living/carbon/human/H = holder.wearer - H << "You are now visible." - H.invisibility = 0 + to_chat(H, "You are now visible.") anim(get_turf(H), H,'icons/mob/mob.dmi',,"uncloak",,H.dir) anim(get_turf(H), H, 'icons/effects/effects.dmi', "electricity",null,20,null) + H.alpha = initial(H.alpha) for(var/mob/O in oviewers(H)) O.show_message("[H.name] appears from thin air!",1) diff --git a/code/modules/clothing/spacesuits/void/station.dm b/code/modules/clothing/spacesuits/void/station.dm index 31830fb275c..3c5dc32e687 100644 --- a/code/modules/clothing/spacesuits/void/station.dm +++ b/code/modules/clothing/spacesuits/void/station.dm @@ -150,20 +150,20 @@ item_state_slots = list(slot_r_hand_str = "medical_voidsuit_bio", slot_l_hand_str = "medical_voidsuit_bio") armor = list(melee = 45, bullet = 5, laser = 20, energy = 5, bomb = 15, bio = 100, rad = 75) -//Medical Surplus Voidsuit +//Medical Streamlined Voidsuit /obj/item/clothing/head/helmet/space/void/medical/alt name = "streamlined medical voidsuit helmet" desc = "A trendy, lightly radiation-shielded voidsuit helmet trimmed in a fetching green." icon_state = "rig0-medicalalt" - armor = list(melee = 30, bullet = 5, laser = 10,energy = 5, bomb = 5, bio = 100, rad = 60) + armor = list(melee = 30, bullet = 5, laser = 20,energy = 5, bomb = 25, bio = 100, rad = 80) light_overlay = "helmet_light_dual_green" /obj/item/clothing/suit/space/void/medical/alt icon_state = "rig-medicalalt" name = "streamlined medical voidsuit" desc = "A more recent model of Vey-Med voidsuit, featuring the latest in radiation shielding technology, without sacrificing comfort or style." - allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/device/suit_cooling_unit,/obj/item/weapon/storage/firstaid,/obj/item/device/healthanalyzer,/obj/item/stack/medical) - armor = list(melee = 30, bullet = 5, laser = 10,energy = 5, bomb = 5, bio = 100, rad = 60) + slowdown = 0 + armor = list(melee = 30, bullet = 5, laser = 20,energy = 5, bomb = 25, bio = 100, rad = 80) //Security /obj/item/clothing/head/helmet/space/void/security diff --git a/code/modules/clothing/spacesuits/void/void.dm b/code/modules/clothing/spacesuits/void/void.dm index 934d7407d9e..dfc416aa696 100644 --- a/code/modules/clothing/spacesuits/void/void.dm +++ b/code/modules/clothing/spacesuits/void/void.dm @@ -54,7 +54,7 @@ //Breach thresholds, should ideally be inherited by most (if not all) voidsuits. //With 0.2 resiliance, will reach 10 breach damage after 3 laser carbine blasts or 8 smg hits. - breach_threshold = 18 + breach_threshold = 12 can_breach = 1 //Inbuilt devices. diff --git a/code/modules/clothing/suits/aliens/seromi.dm b/code/modules/clothing/suits/aliens/seromi.dm index ccba8986d5f..245ebc5436f 100644 --- a/code/modules/clothing/suits/aliens/seromi.dm +++ b/code/modules/clothing/suits/aliens/seromi.dm @@ -49,7 +49,7 @@ item_state = "tesh_cloak_by" /obj/item/clothing/suit/storage/seromi/cloak/black_green - name = "black and Green cloak" + name = "black and green cloak" icon_state = "tesh_cloak_bgr" item_state = "tesh_cloak_bgr" @@ -115,8 +115,8 @@ /obj/item/clothing/suit/storage/seromi/cloak/blue_grey name = "blue and grey cloak" - icon_state = "tesh_cloak_blg" - item_state = "tesh_cloak_blg" + icon_state = "tesh_cloak_blug" + item_state = "tesh_cloak_blug" /obj/item/clothing/suit/storage/seromi/cloak/purple_grey name = "purple and grey cloak" @@ -124,11 +124,11 @@ item_state = "tesh_cloak_pg" /obj/item/clothing/suit/storage/seromi/cloak/pink_grey - name = "black and orange cloak" + name = "pink and grey cloak" icon_state = "tesh_cloak_pig" item_state = "tesh_cloak_pig" /obj/item/clothing/suit/storage/seromi/cloak/brown_grey - name = "purple and grey cloak" + name = "brown and grey cloak" icon_state = "tesh_cloak_brg" item_state = "tesh_cloak_brg" \ No newline at end of file diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm index 864ee369ba5..97fc8721a8d 100644 --- a/code/modules/clothing/suits/armor.dm +++ b/code/modules/clothing/suits/armor.dm @@ -210,6 +210,36 @@ icon_state = "reactiveoff" ..() +// Alien armor has a chance to completely block attacks. +/obj/item/clothing/suit/armor/alien + name = "alien enhancement vest" + desc = "It's a strange piece of what appears to be armor. It looks very light and agile. Strangely enough it seems to have been designed for a humanoid shape." + description_info = "It has a 20% chance to completely nullify an incoming attack, and the wearer moves slightly faster." + icon_state = "alien_speed" + blood_overlay_type = "armor" + item_state_slots = list(slot_r_hand_str = "armor", slot_l_hand_str = "armor") + slowdown = -1 + body_parts_covered = UPPER_TORSO|LOWER_TORSO + armor = list(melee = 50, bullet = 50, laser = 50, energy = 50, bomb = 50, bio = 0, rad = 40) + siemens_coefficient = 0.4 + var/block_chance = 20 + +/obj/item/clothing/suit/armor/alien/tank + name = "alien protection suit" + desc = "It's really resilient yet lightweight, so it's probably meant to be armor. Strangely enough it seems to have been designed for a humanoid shape." + description_info = "It has a 40% chance to completely nullify an incoming attack." + icon_state = "alien_tank" + slowdown = 0 + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + armor = list(melee = 70, bullet = 70, laser = 70, energy = 70, bomb = 70, bio = 0, rad = 40) + block_chance = 40 + +/obj/item/clothing/suit/armor/alien/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack") + if(prob(block_chance)) + user.visible_message("\The [src] completely absorbs [attack_text]!") + return TRUE + return FALSE + //Non-hardsuit ERT armor. /obj/item/clothing/suit/armor/vest/ert name = "emergency response team armor" diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm index 602b8542879..4a6326a424e 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 /* @@ -657,9 +659,9 @@ obj/item/clothing/suit/storage/toggle/peacoat desc = "A heavy jacket made from 'synthetic' animal furs." icon_state = "coatwinter" item_state_slots = list(slot_r_hand_str = "coatwinter", slot_l_hand_str = "coatwinter") - body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS + body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS flags_inv = HIDEHOLSTER - cold_protection = UPPER_TORSO|LOWER_TORSO|ARMS + cold_protection = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS min_cold_protection_temperature = SPACE_SUIT_MIN_COLD_PROTECTION_TEMPERATURE armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) hooded = 1 @@ -768,6 +770,45 @@ 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" + brightness_on = 3 + light_overlay = "hood_light" + action_button_name = "Toggle Head-light" + body_parts_covered = HEAD + cold_protection = HEAD + flags = THICKMATERIAL + flags_inv = HIDEEARS | BLOCKHAIR + min_cold_protection_temperature = SPACE_SUIT_MIN_COLD_PROTECTION_TEMPERATURE + siemens_coefficient = 0.9 + armor = list(melee = 30, bullet = 20, laser = 20, energy = 20, bomb = 50, bio = 100, rad = 50) + /obj/item/clothing/suit/varsity name = "black varsity jacket" desc = "A favorite of jocks everywhere from Sol to Nyx." diff --git a/code/modules/clothing/suits/toggles.dm b/code/modules/clothing/suits/toggles.dm index 1176b910891..81b433fa27d 100644 --- a/code/modules/clothing/suits/toggles.dm +++ b/code/modules/clothing/suits/toggles.dm @@ -31,11 +31,12 @@ /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) H.update_inv_wear_suit() - hood.loc = src + hood.forceMove(src) /obj/item/clothing/suit/storage/hooded/dropped() RemoveHood() @@ -53,6 +54,7 @@ else H.equip_to_slot_if_possible(hood,slot_head,0,0,1) suittoggled = 1 + hood.canremove = FALSE icon_state = "[initial(icon_state)]_t" H.update_inv_wear_suit() else diff --git a/code/modules/clothing/under/accessories/accessory.dm b/code/modules/clothing/under/accessories/accessory.dm index 4392a264927..5d18858cc35 100644 --- a/code/modules/clothing/under/accessories/accessory.dm +++ b/code/modules/clothing/under/accessories/accessory.dm @@ -45,6 +45,16 @@ mob_overlay = image("icon" = sprite_sheets[wearer.species.get_bodytype(wearer)], "icon_state" = "[tmp_icon_state]") else mob_overlay = image("icon" = INV_ACCESSORIES_DEF_ICON, "icon_state" = "[tmp_icon_state]") + if(addblends) + var/icon/base = new/icon("icon" = mob_overlay.icon, "icon_state" = mob_overlay.icon_state) + var/addblend_icon = new/icon("icon" = mob_overlay.icon, "icon_state" = src.addblends) + if(color) + base.Blend(src.color, ICON_MULTIPLY) + base.Blend(addblend_icon, ICON_ADD) + mob_overlay = image(base) + else + mob_overlay.color = src.color + return mob_overlay //when user attached an accessory to S @@ -234,6 +244,14 @@ name = "medal of exceptional heroism" desc = "An extremely rare golden medal awarded only by high ranking officials. To recieve such a medal is the highest honor and as such, very few exist. This medal is almost never awarded to anybody but distinguished veteran staff." +// Base type for 'medals' found in a "dungeon" submap, as a sort of trophy to celebrate the player's conquest. +/obj/item/clothing/accessory/medal/dungeon + +/obj/item/clothing/accessory/medal/dungeon/alien_ufo + name = "alien captain's medal" + desc = "It vaguely like a star. It looks like something an alien captain might've worn. Probably." + icon_state = "alien_medal" + //Scarves /obj/item/clothing/accessory/scarf @@ -292,3 +310,81 @@ /obj/item/clothing/accessory/scarf/stripedblue name = "striped blue scarf" icon_state = "stripedbluescarf" + +//bracelets + +/obj/item/clothing/accessory/bracelet + name = "bracelet" + desc = "A simple silver bracelet with a clasp." + icon = 'icons/obj/clothing/ties.dmi' + icon_state = "bracelet" + w_class = ITEMSIZE_TINY + slot_flags = SLOT_TIE + +/obj/item/clothing/accessory/bracelet/friendship + name = "friendship bracelet" + desc = "A beautiful friendship bracelet in all the colors of the rainbow." + icon_state = "friendbracelet" + +/obj/item/clothing/accessory/bracelet/friendship/verb/dedicate_bracelet() + set name = "Dedicate Bracelet" + set category = "Object" + set desc = "Dedicate your friendship bracelet to a special someone." + var/mob/M = usr + if(!M.mind) + return 0 + + var/input = sanitizeSafe(input("Who do you want to dedicate the bracelet to?", ,""), MAX_NAME_LEN) + + if(src && input && !M.stat && in_range(M,src)) + desc = "A beautiful friendship bracelet in all the colors of the rainbow. It's dedicated to [input]." + to_chat(M, "You dedicate the bracelet to [input], remembering the times you've had together.") + return 1 + + +/obj/item/clothing/accessory/bracelet/material + icon_state = "materialbracelet" + +/obj/item/clothing/accessory/bracelet/material/New(var/newloc, var/new_material) + ..(newloc) + if(!new_material) + new_material = DEFAULT_WALL_MATERIAL + material = get_material_by_name(new_material) + if(!istype(material)) + qdel(src) + return + name = "[material.display_name] bracelet" + desc = "A bracelet made from [material.display_name]." + color = material.icon_colour + +/obj/item/clothing/accessory/bracelet/material/get_material() + return material + +/obj/item/clothing/accessory/bracelet/material/wood/New(var/newloc) + ..(newloc, "wood") + +/obj/item/clothing/accessory/bracelet/material/plastic/New(var/newloc) + ..(newloc, "plastic") + +/obj/item/clothing/accessory/bracelet/material/iron/New(var/newloc) + ..(newloc, "iron") + +/obj/item/clothing/accessory/bracelet/material/steel/New(var/newloc) + ..(newloc, "steel") + +/obj/item/clothing/accessory/bracelet/material/silver/New(var/newloc) + ..(newloc, "silver") + +/obj/item/clothing/accessory/bracelet/material/gold/New(var/newloc) + ..(newloc, "gold") + +/obj/item/clothing/accessory/bracelet/material/platinum/New(var/newloc) + ..(newloc, "platinum") + +/obj/item/clothing/accessory/bracelet/material/phoron/New(var/newloc) + ..(newloc, "phoron") + +/obj/item/clothing/accessory/bracelet/material/glass/New(var/newloc) + ..(newloc, "glass") + + ..() \ No newline at end of file diff --git a/code/modules/clothing/under/accessories/armband.dm b/code/modules/clothing/under/accessories/armband.dm index 3f53c443929..bf40074a2a2 100644 --- a/code/modules/clothing/under/accessories/armband.dm +++ b/code/modules/clothing/under/accessories/armband.dm @@ -37,6 +37,7 @@ /obj/item/clothing/accessory/armband/med/color name = "armband" desc = "A fancy armband." + addblends = "med_a" /obj/item/clothing/accessory/armband/medblue name = "EMT armband" diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm index f9a0a9ab379..ddfb109ef6b 100644 --- a/code/modules/clothing/under/miscellaneous.dm +++ b/code/modules/clothing/under/miscellaneous.dm @@ -627,17 +627,20 @@ name = "long dress" desc = "A long dress." icon_state = "whitedress2" + addblends = "whitedress2_a" flags_inv = HIDESHOES /obj/item/clothing/under/dress/white3 name = "short dress" desc = "A short, plain dress." icon_state = "whitedress3" + addblends = "whitedress3_a" /obj/item/clothing/under/dress/white4 name = "long flared dress" desc = "A long white dress that flares out at the bottom." icon_state = "whitedress4" + addblends = "whitedress4_a" flags_inv = HIDESHOES /obj/item/clothing/under/dress/darkred @@ -809,3 +812,8 @@ desc = "A fluffy robe to keep you from showing off to the world." icon_state = "bathrobe" worn_state = "bathrobe" + +/obj/item/clothing/under/explorer + desc = "A green uniform for operating in hazardous environments." + name = "explorer's jumpsuit" + icon_state = "explorer" \ No newline at end of file diff --git a/code/modules/clothing/under/pants.dm b/code/modules/clothing/under/pants.dm index 322115cc0b6..c306d842d07 100644 --- a/code/modules/clothing/under/pants.dm +++ b/code/modules/clothing/under/pants.dm @@ -121,6 +121,7 @@ name = "yoga pants" desc = "A pair of tight-fitting yoga pants for those lazy days." icon_state = "yogapants" + addblends = "yogapants_a" /* * Baggy Pants diff --git a/code/modules/clothing/under/xenos/seromi.dm b/code/modules/clothing/under/xenos/seromi.dm index f99317b7d06..5ec18a48594 100644 --- a/code/modules/clothing/under/xenos/seromi.dm +++ b/code/modules/clothing/under/xenos/seromi.dm @@ -82,7 +82,7 @@ item_state = "tesh_uniform_by" /obj/item/clothing/under/seromi/undercoat/black_green - name = "black and Green undercoat" + name = "black and green undercoat" icon_state = "tesh_uniform_bgr" item_state = "tesh_uniform_bgr" @@ -148,8 +148,8 @@ /obj/item/clothing/under/seromi/undercoat/blue_grey name = "blue and grey undercoat" - icon_state = "tesh_uniform_blg" - item_state = "tesh_uniform_blg" + icon_state = "tesh_uniform_blug" + item_state = "tesh_uniform_blug" /obj/item/clothing/under/seromi/undercoat/purple_grey name = "purple and grey undercoat" @@ -157,11 +157,11 @@ item_state = "tesh_uniform_pg" /obj/item/clothing/under/seromi/undercoat/pink_grey - name = "black and orange undercoat" + name = "pink and grey undercoat" icon_state = "tesh_uniform_pig" item_state = "tesh_uniform_pig" /obj/item/clothing/under/seromi/undercoat/brown_grey - name = "purple and grey undercoat" + name = "brown and grey undercoat" icon_state = "tesh_uniform_brg" item_state = "tesh_uniform_brg" \ No newline at end of file diff --git a/code/modules/economy/economy_misc.dm b/code/modules/economy/economy_misc.dm index a2cc9aafb9e..84a187ef91d 100644 --- a/code/modules/economy/economy_misc.dm +++ b/code/modules/economy/economy_misc.dm @@ -49,6 +49,7 @@ /var/list/economic_species_modifier = list( /datum/species/human = 10, + /datum/species/human/vatgrown = 10, /datum/species/skrell = 12, /datum/species/unathi = 7, /datum/species/tajaran = 7, diff --git a/code/modules/hydroponics/spreading/spreading.dm b/code/modules/hydroponics/spreading/spreading.dm index b66abd61daa..f08f28d97a0 100644 --- a/code/modules/hydroponics/spreading/spreading.dm +++ b/code/modules/hydroponics/spreading/spreading.dm @@ -238,7 +238,7 @@ /obj/effect/plant/attackby(var/obj/item/weapon/W, var/mob/user) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(W)) plant_controller.add_plant(src) if(istype(W, /obj/item/weapon/wirecutters) || istype(W, /obj/item/weapon/surgical/scalpel)) diff --git a/code/modules/hydroponics/spreading/spreading_response.dm b/code/modules/hydroponics/spreading/spreading_response.dm index 80d72055eba..12747666c49 100644 --- a/code/modules/hydroponics/spreading/spreading_response.dm +++ b/code/modules/hydroponics/spreading/spreading_response.dm @@ -61,7 +61,7 @@ "You hear shredding and ripping.") unbuckle() else - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed()) health -= rand(1,5) var/text = pick("rip","tear","pull", "bite", "tug") user.visible_message(\ diff --git a/code/modules/hydroponics/trays/tray.dm b/code/modules/hydroponics/trays/tray.dm index 4eee4ee91ba..4a924fdca3a 100644 --- a/code/modules/hydroponics/trays/tray.dm +++ b/code/modules/hydroponics/trays/tray.dm @@ -568,7 +568,7 @@ return else if(O.force && seed) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(O)) user.visible_message("\The [seed.display_name] has been attacked by [user] with \the [O]!") if(!dead) health -= O.force diff --git a/code/modules/integrated_electronics/core/helpers.dm b/code/modules/integrated_electronics/core/helpers.dm index edfa6b1a86c..e31b26fbb1a 100644 --- a/code/modules/integrated_electronics/core/helpers.dm +++ b/code/modules/integrated_electronics/core/helpers.dm @@ -18,7 +18,9 @@ else io_list.Add(new io_type(src, io_entry, default_data)) -/obj/item/integrated_circuit/proc/set_pin_data(var/pin_type, var/pin_number, var/new_data) +/obj/item/integrated_circuit/proc/set_pin_data(var/pin_type, var/pin_number, datum/new_data) + if (istype(new_data) && !isweakref(new_data)) + new_data = weakref(new_data) var/datum/integrated_io/pin = get_pin_ref(pin_type, pin_number) return pin.write_data_to_pin(new_data) diff --git a/code/modules/integrated_electronics/core/pins.dm b/code/modules/integrated_electronics/core/pins.dm index c22d65e4214..8621e2b7ed1 100644 --- a/code/modules/integrated_electronics/core/pins.dm +++ b/code/modules/integrated_electronics/core/pins.dm @@ -112,6 +112,8 @@ list[]( /datum/integrated_io/proc/write_data_to_pin(var/new_data) if(isnull(new_data) || isnum(new_data) || istext(new_data) || isweakref(new_data)) // Anything else is a type we don't want. + if(istext(new_data)) + new_data = sanitizeSafe(new_data, MAX_MESSAGE_LEN, 0, 0) data = new_data holder.on_data_written() diff --git a/code/modules/integrated_electronics/core/special_pins/string_pin.dm b/code/modules/integrated_electronics/core/special_pins/string_pin.dm index 6128418c1f3..595a2053187 100644 --- a/code/modules/integrated_electronics/core/special_pins/string_pin.dm +++ b/code/modules/integrated_electronics/core/special_pins/string_pin.dm @@ -4,11 +4,14 @@ /datum/integrated_io/string/ask_for_pin_data(mob/user) var/new_data = input("Please type in a string.","[src] string writing") as null|text - if(holder.check_interactivity(user) ) + new_data = sanitizeSafe(new_data, MAX_MESSAGE_LEN, 0, 0) + + if(new_data && holder.check_interactivity(user) ) to_chat(user, "You input [new_data ? "new_data" : "NULL"] into the pin.") write_data_to_pin(new_data) /datum/integrated_io/string/write_data_to_pin(var/new_data) + new_data = sanitizeSafe(new_data, MAX_MESSAGE_LEN, 0, 0) if(isnull(new_data) || istext(new_data)) data = new_data holder.on_data_written() diff --git a/code/modules/integrated_electronics/core/tools.dm b/code/modules/integrated_electronics/core/tools.dm index 08765b94e51..0f702be3de0 100644 --- a/code/modules/integrated_electronics/core/tools.dm +++ b/code/modules/integrated_electronics/core/tools.dm @@ -125,6 +125,7 @@ if("string") accepting_refs = 0 new_data = input("Now type in a string.","[src] string writing") as null|text + new_data = sanitizeSafe(new_data, MAX_MESSAGE_LEN, 0, 0) if(istext(new_data) && CanInteract(user, physical_state)) data_to_write = new_data to_chat(user, "You set \the [src]'s memory to \"[new_data]\".") diff --git a/code/modules/integrated_electronics/passive/power.dm b/code/modules/integrated_electronics/passive/power.dm index c417c3e4fd0..0a516e360a7 100644 --- a/code/modules/integrated_electronics/passive/power.dm +++ b/code/modules/integrated_electronics/passive/power.dm @@ -29,6 +29,28 @@ if(assembly) assembly.give_power(adjusted_power) +/obj/item/integrated_circuit/passive/power/starter + name = "starter" + desc = "This tiny circuit will send a pulse right after device is turned on, or when power is restored." + icon_state = "led" + complexity = 1 + activators = list("pulse out" = IC_PINTYPE_PULSE_OUT) + origin_tech = list(TECH_POWER = 3, TECH_ENGINEERING = 3, TECH_DATA = 2) + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + var/is_charge=0 + +/obj/item/integrated_circuit/passive/power/starter/make_energy() + if(assembly.battery) + if(assembly.battery.charge) + if(!is_charge) + activate_pin(1) + is_charge=1 + else + is_charge=0 + else + is_charge=0 + return FALSE + // For implants. /obj/item/integrated_circuit/passive/power/metabolic_siphon name = "metabolic siphon" @@ -82,6 +104,44 @@ origin_tech = list(TECH_POWER = 3, TECH_ENGINEERING = 3, TECH_DATA = 2) spawn_flags = IC_SPAWN_RESEARCH var/power_amount = 250 +//fuel cell + +/obj/item/integrated_circuit/passive/power/chemical_cell + name = "fuel cell" + desc = "Produces electricity from chemicals." + icon_state = "chemical_cell" + extended_desc = "This is effectively an internal beaker. It will consume and produce power from phoron, slime jelly, welding fuel, carbon,\ + ethanol, nutriments and blood, in order of decreasing efficiency. It will consume fuel only if the battery can take more energy." + flags = OPENCONTAINER + complexity = 4 + inputs = list() + outputs = list("volume used" = IC_PINTYPE_NUMBER,"self reference" = IC_PINTYPE_REF) + activators = list() + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2) + var/volume = 60 + var/list/fuel = list("phoron" = 50000, "slimejelly" = 25000, "fuel" = 15000, "carbon" = 10000, "ethanol"= 10000, "nutriment" =8000, "blood" = 5000) + +/obj/item/integrated_circuit/passive/power/chemical_cell/New() + ..() + create_reagents(volume) + +/obj/item/integrated_circuit/passive/power/chemical_cell/interact(mob/user) + set_pin_data(IC_OUTPUT, 2, weakref(src)) + push_data() + ..() + +/obj/item/integrated_circuit/passive/power/chemical_cell/on_reagent_change() + set_pin_data(IC_OUTPUT, 1, reagents.total_volume) + push_data() + +/obj/item/integrated_circuit/passive/power/chemical_cell/make_energy() + if(assembly) + for(var/I in fuel) + if((assembly.battery.maxcharge-assembly.battery.charge) / CELLRATE > fuel[I]) + if(reagents.remove_reagent(I, 1)) + assembly.give_power(fuel[I]) + // For really fat machines. /obj/item/integrated_circuit/passive/power/relay/large diff --git a/code/modules/integrated_electronics/subtypes/data_transfer.dm b/code/modules/integrated_electronics/subtypes/data_transfer.dm index 7b5846eb8d0..e490ccd27a9 100644 --- a/code/modules/integrated_electronics/subtypes/data_transfer.dm +++ b/code/modules/integrated_electronics/subtypes/data_transfer.dm @@ -27,13 +27,10 @@ /obj/item/integrated_circuit/transfer/multiplexer/do_work() var/input_index = get_pin_data(IC_INPUT, 1) - var/output = null if(!isnull(input_index) && (input_index >= 1 && input_index < inputs.len)) - output = get_pin_data(IC_INPUT, input_index + 1) - - set_pin_data(IC_OUTPUT, 1, output) - push_data() + set_pin_data(IC_OUTPUT, 1,get_pin_data(IC_INPUT, input_index + 1)) + push_data() activate_pin(2) /obj/item/integrated_circuit/transfer/multiplexer/medium @@ -79,10 +76,8 @@ /obj/item/integrated_circuit/transfer/demultiplexer/do_work() var/output_index = get_pin_data(IC_INPUT, 1) - var/output = get_pin_data(IC_INPUT, 2) - for(var/i = 1 to outputs.len) - set_pin_data(IC_OUTPUT, i, i == output_index ? output : null) + set_pin_data(IC_OUTPUT, i, i == output_index ? get_pin_data(IC_INPUT, 2) : null) activate_pin(2) @@ -101,4 +96,51 @@ name = "sixteen demultiplexer" icon_state = "dmux16" w_class = ITEMSIZE_SMALL + number_of_outputs = 16 + +/obj/item/integrated_circuit/transfer/pulsedemultiplexer + name = "two pulse demultiplexer" + desc = "Selector switch to choose the pin to be activated by number." + extended_desc = "The first input pin is used to select which of the pulse out pins will be activated after activation of the circuit. \ + If the output selection is outside the valid range then no output is given." + complexity = 2 + icon_state = "dmux2" + inputs = list("output selection" = IC_PINTYPE_NUMBER) + outputs = list() + activators = list("select" = IC_PINTYPE_PULSE_IN) + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + power_draw_per_use = 4 + var/number_of_outputs = 2 + +/obj/item/integrated_circuit/transfer/pulsedemultiplexer/New() + for(var/i = 1 to number_of_outputs) + // outputs += "output [i]" + activators["output [i]"] = IC_PINTYPE_PULSE_OUT + complexity = number_of_outputs + + ..() + desc += " It has [number_of_outputs] output pins." + extended_desc += " This pulse demultiplexer has a range from 1 to [activators.len - 1]." + +/obj/item/integrated_circuit/transfer/pulsedemultiplexer/do_work() + var/output_index = get_pin_data(IC_INPUT, 1) + + if(output_index == Clamp(output_index, 1, number_of_outputs)) + activate_pin(round(output_index + 1 ,1)) + +/obj/item/integrated_circuit/transfer/pulsedemultiplexer/medium + name = "four pulse demultiplexer" + icon_state = "dmux4" + number_of_outputs = 4 + +/obj/item/integrated_circuit/transfer/pulsedemultiplexer/large + name = "eight pulse demultiplexer" + icon_state = "dmux8" + w_class = ITEMSIZE_SMALL + number_of_outputs = 8 + +/obj/item/integrated_circuit/transfer/pulsedemultiplexer/huge + name = "sixteen pulse demultiplexer" + icon_state = "dmux16" + w_class = ITEMSIZE_SMALL number_of_outputs = 16 \ No newline at end of file diff --git a/code/modules/integrated_electronics/subtypes/input.dm b/code/modules/integrated_electronics/subtypes/input.dm index d752f0d5cd9..8da4fad6d8e 100644 --- a/code/modules/integrated_electronics/subtypes/input.dm +++ b/code/modules/integrated_electronics/subtypes/input.dm @@ -110,8 +110,10 @@ /obj/item/integrated_circuit/input/adv_med_scanner - name = "integrated advanced medical analyser" - desc = "A very small version of the medbot's medical analyser. This allows the machine to know how healthy someone is. \ + + name = "integrated advanced medical analyzer" + desc = "A very small version of the medibot's medical analyzer. This allows the machine to know how healthy someone is. \ + This type is much more precise, allowing the machine to know much more about the target than a normal analyzer." icon_state = "medscan_adv" complexity = 12 @@ -134,7 +136,9 @@ var/mob/living/carbon/human/H = get_pin_data_as_type(IC_INPUT, 1, /mob/living/carbon/human) if(!istype(H)) //Invalid input return + if(H in view(get_turf(H))) // Like medbot's analyzer it can be used in range.. + var/total_health = round(H.health/H.getMaxHealth(), 0.01)*100 var/missing_health = H.getMaxHealth() - H.health @@ -336,6 +340,7 @@ // Set the pins so when someone sees them, they won't show as null set_pin_data(IC_INPUT, 1, frequency) set_pin_data(IC_INPUT, 2, code) + push_data() /obj/item/integrated_circuit/input/signaler/Destroy() if(radio_controller) @@ -464,6 +469,7 @@ set_pin_data(IC_OUTPUT, 1, null) set_pin_data(IC_OUTPUT, 2, null) if(!T) + push_data() return set_pin_data(IC_OUTPUT, 1, T.x) @@ -486,7 +492,7 @@ "speaker" = IC_PINTYPE_STRING, "message" = IC_PINTYPE_STRING ) - activators = list("on message received" = IC_PINTYPE_PULSE_IN, "on translation" = IC_PINTYPE_PULSE_OUT) + activators = list("on message received" = IC_PINTYPE_PULSE_OUT, "on translation" = IC_PINTYPE_PULSE_OUT) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH power_draw_per_use = 15 @@ -618,4 +624,235 @@ push_data() activate_pin(2) +/obj/item/integrated_circuit/input/atmo_scanner + name = "integrated atmospheric analyser" + desc = "The same atmospheric analysis module that is integrated into every PDA. \ + This allows the machine to know the composition, temperature and pressure of the surrounding atmosphere." + icon_state = "medscan_adv" + complexity = 9 + inputs = list() + outputs = list( + "pressure" = IC_PINTYPE_NUMBER, + "temperature" = IC_PINTYPE_NUMBER, + "oxygen" = IC_PINTYPE_NUMBER, + "nitrogen" = IC_PINTYPE_NUMBER, + "carbon dioxide" = IC_PINTYPE_NUMBER, + "phoron" = IC_PINTYPE_NUMBER, + "other" = IC_PINTYPE_NUMBER + ) + activators = list("scan" = IC_PINTYPE_PULSE_IN, "on scanned" = IC_PINTYPE_PULSE_OUT) + spawn_flags = IC_SPAWN_RESEARCH + origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3) + power_draw_per_use = 60 +/obj/item/integrated_circuit/input/atmo_scanner/do_work() + var/turf/T = get_turf(src) + if(!istype(T)) //Invalid input + return + var/datum/gas_mixture/environment = T.return_air() + + var/pressure = environment.return_pressure() + var/total_moles = environment.total_moles + + if (total_moles) + var/o2_level = environment.gas["oxygen"]/total_moles + var/n2_level = environment.gas["nitrogen"]/total_moles + var/co2_level = environment.gas["carbon_dioxide"]/total_moles + var/phoron_level = environment.gas["phoron"]/total_moles + var/unknown_level = 1-(o2_level+n2_level+co2_level+phoron_level) + set_pin_data(IC_OUTPUT, 1, pressure) + set_pin_data(IC_OUTPUT, 2, round(environment.temperature-T0C,0.1)) + set_pin_data(IC_OUTPUT, 3, round(o2_level*100,0.1)) + set_pin_data(IC_OUTPUT, 4, round(n2_level*100,0.1)) + set_pin_data(IC_OUTPUT, 5, round(co2_level*100,0.1)) + set_pin_data(IC_OUTPUT, 6, round(phoron_level*100,0.01)) + set_pin_data(IC_OUTPUT, 7, round(unknown_level, 0.01)) + else + set_pin_data(IC_OUTPUT, 1, 0) + set_pin_data(IC_OUTPUT, 2, -273.15) + set_pin_data(IC_OUTPUT, 3, 0) + set_pin_data(IC_OUTPUT, 4, 0) + set_pin_data(IC_OUTPUT, 5, 0) + set_pin_data(IC_OUTPUT, 6, 0) + set_pin_data(IC_OUTPUT, 7, 0) + push_data() + activate_pin(2) + +/obj/item/integrated_circuit/input/pressure_sensor + name = "integrated pressure sensor" + desc = "A tiny pressure sensor module similar to that found in a PDA atmosphere analyser." + icon_state = "medscan_adv" + complexity = 3 + inputs = list() + outputs = list( + "pressure" = IC_PINTYPE_NUMBER + ) + activators = list("scan" = IC_PINTYPE_PULSE_IN, "on scanned" = IC_PINTYPE_PULSE_OUT) + spawn_flags = IC_SPAWN_RESEARCH + origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3) + power_draw_per_use = 20 + +/obj/item/integrated_circuit/input/pressure_sensor/do_work() + var/turf/T = get_turf(src) + if(!istype(T)) //Invalid input + return + var/datum/gas_mixture/environment = T.return_air() + + var/pressure = environment.return_pressure() + var/total_moles = environment.total_moles + + if (total_moles) + set_pin_data(IC_OUTPUT, 1, pressure) + else + set_pin_data(IC_OUTPUT, 1, 0) + push_data() + activate_pin(2) + +/obj/item/integrated_circuit/input/temperature_sensor + name = "integrated temperature sensor" + desc = "A tiny temperature sensor module similar to that found in a PDA atmosphere analyser." + icon_state = "medscan_adv" + complexity = 3 + inputs = list() + outputs = list( + "temperature" = IC_PINTYPE_NUMBER + ) + activators = list("scan" = IC_PINTYPE_PULSE_IN, "on scanned" = IC_PINTYPE_PULSE_OUT) + spawn_flags = IC_SPAWN_RESEARCH + origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3) + power_draw_per_use = 20 + +/obj/item/integrated_circuit/input/temperature_sensor/do_work() + var/turf/T = get_turf(src) + if(!istype(T)) //Invalid input + return + var/datum/gas_mixture/environment = T.return_air() + + var/total_moles = environment.total_moles + + if (total_moles) + set_pin_data(IC_OUTPUT, 1, round(environment.temperature-T0C,0.1)) + else + set_pin_data(IC_OUTPUT, 1, -273.15) + push_data() + activate_pin(2) + +/obj/item/integrated_circuit/input/oxygen_sensor + name = "integrated oxygen sensor" + desc = "A tiny oxygen sensor module similar to that found in a PDA atmosphere analyser." + icon_state = "medscan_adv" + complexity = 3 + inputs = list() + outputs = list( + "oxygen" = IC_PINTYPE_NUMBER + ) + activators = list("scan" = IC_PINTYPE_PULSE_IN, "on scanned" = IC_PINTYPE_PULSE_OUT) + spawn_flags = IC_SPAWN_RESEARCH + origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3) + power_draw_per_use = 20 + +/obj/item/integrated_circuit/input/oxygen_sensor/do_work() + var/turf/T = get_turf(src) + if(!istype(T)) //Invalid input + return + var/datum/gas_mixture/environment = T.return_air() + + var/total_moles = environment.total_moles + + if (total_moles) + var/o2_level = environment.gas["oxygen"]/total_moles + set_pin_data(IC_OUTPUT, 1, round(o2_level*100,0.1)) + else + set_pin_data(IC_OUTPUT, 1, 0) + push_data() + activate_pin(2) + +/obj/item/integrated_circuit/input/co2_sensor + name = "integrated co2 sensor" + desc = "A tiny carbon dioxide sensor module similar to that found in a PDA atmosphere analyser." + icon_state = "medscan_adv" + complexity = 3 + inputs = list() + outputs = list( + "co2" = IC_PINTYPE_NUMBER + ) + activators = list("scan" = IC_PINTYPE_PULSE_IN, "on scanned" = IC_PINTYPE_PULSE_OUT) + spawn_flags = IC_SPAWN_RESEARCH + origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3) + power_draw_per_use = 20 + +/obj/item/integrated_circuit/input/co2_sensor/do_work() + var/turf/T = get_turf(src) + if(!istype(T)) //Invalid input + return + var/datum/gas_mixture/environment = T.return_air() + + var/total_moles = environment.total_moles + + if (total_moles) + var/co2_level = environment.gas["carbon_dioxide"]/total_moles + set_pin_data(IC_OUTPUT, 1, round(co2_level*100,0.1)) + else + set_pin_data(IC_OUTPUT, 1, 0) + push_data() + activate_pin(2) + +/obj/item/integrated_circuit/input/nitrogen_sensor + name = "integrated nitrogen sensor" + desc = "A tiny nitrogen sensor module similar to that found in a PDA atmosphere analyser." + icon_state = "medscan_adv" + complexity = 3 + inputs = list() + outputs = list( + "nitrogen" = IC_PINTYPE_NUMBER + ) + activators = list("scan" = IC_PINTYPE_PULSE_IN, "on scanned" = IC_PINTYPE_PULSE_OUT) + spawn_flags = IC_SPAWN_RESEARCH + origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3) + power_draw_per_use = 20 + +/obj/item/integrated_circuit/input/nitrogen_sensor/do_work() + var/turf/T = get_turf(src) + if(!istype(T)) //Invalid input + return + var/datum/gas_mixture/environment = T.return_air() + + var/total_moles = environment.total_moles + + if (total_moles) + var/n2_level = environment.gas["nitrogen"]/total_moles + set_pin_data(IC_OUTPUT, 1, round(n2_level*100,0.1)) + else + set_pin_data(IC_OUTPUT, 1, 0) + push_data() + activate_pin(2) + +/obj/item/integrated_circuit/input/phoron_sensor + name = "integrated phoron sensor" + desc = "A tiny phoron gas sensor module similar to that found in a PDA atmosphere analyser." + icon_state = "medscan_adv" + complexity = 3 + inputs = list() + outputs = list( + "phoron" = IC_PINTYPE_NUMBER + ) + activators = list("scan" = IC_PINTYPE_PULSE_IN, "on scanned" = IC_PINTYPE_PULSE_OUT) + spawn_flags = IC_SPAWN_RESEARCH + origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3) + power_draw_per_use = 20 + +/obj/item/integrated_circuit/input/phoron_sensor/do_work() + var/turf/T = get_turf(src) + if(!istype(T)) //Invalid input + return + var/datum/gas_mixture/environment = T.return_air() + + var/total_moles = environment.total_moles + + if (total_moles) + var/phoron_level = environment.gas["phoron"]/total_moles + set_pin_data(IC_OUTPUT, 1, round(phoron_level*100,0.1)) + else + set_pin_data(IC_OUTPUT, 1, 0) + push_data() + activate_pin(2) diff --git a/code/modules/integrated_electronics/subtypes/lists.dm b/code/modules/integrated_electronics/subtypes/lists.dm index 84e0724bb93..943141b071a 100644 --- a/code/modules/integrated_electronics/subtypes/lists.dm +++ b/code/modules/integrated_electronics/subtypes/lists.dm @@ -52,12 +52,123 @@ push_data() activate_pin(2) +/obj/item/integrated_circuit/list/search + name = "search circuit" + desc = "This circuit will give index of desired element in the list." + extended_desc = "Search will start at 1 position and will return first matching position." + inputs = list( + "list" = IC_PINTYPE_LIST, + "item" = IC_PINTYPE_ANY + ) + outputs = list( + "index" = IC_PINTYPE_NUMBER + ) + icon_state = "addition" + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + +/obj/item/integrated_circuit/list/search/do_work() + var/list/input_list = get_pin_data(IC_INPUT, 1) + var/item = get_pin_data(IC_INPUT, 2) + set_pin_data(IC_OUTPUT, 1, input_list.Find(item)) + push_data() + activate_pin(2) + +/obj/item/integrated_circuit/list/at + name = "at circuit" + desc = "This circuit will pick an element from a list by index." + extended_desc = "If there is no element with such index, result will be null." + inputs = list( + "list" = IC_PINTYPE_LIST, + "index" = IC_PINTYPE_NUMBER + ) + outputs = list("item" = IC_PINTYPE_ANY) + icon_state = "addition" + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + +/obj/item/integrated_circuit/list/at/do_work() + var/list/input_list = get_pin_data(IC_INPUT, 1) + var/index = get_pin_data(IC_INPUT, 2) + var/item = input_list[index] + set_pin_data(IC_OUTPUT, 1, item) + push_data() + activate_pin(2) + +/obj/item/integrated_circuit/list/delete + name = "delete circuit" + desc = "This circuit will delete the element from a list by index." + extended_desc = "If there is no element with such index, result list will be unchanged." + inputs = list( + "list" = IC_PINTYPE_LIST, + "index" = IC_PINTYPE_NUMBER + ) + outputs = list( + "item" = IC_PINTYPE_LIST + ) + icon_state = "addition" + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + +/obj/item/integrated_circuit/list/delete/do_work() + var/list/input_list = get_pin_data(IC_INPUT, 1) + var/list/red_list = list() + var/index = get_pin_data(IC_INPUT, 2) + var/j = 0 + for(var/I in input_list) + j = j + 1 + if(j != index) + red_list.Add(I) + set_pin_data(IC_OUTPUT, 1, red_list) + push_data() + activate_pin(2) + +/obj/item/integrated_circuit/list/write + name = "write circuit" + desc = "This circuit will write element in list with given index." + extended_desc = "If there is no element with such index, it will give the same list, as before." + inputs = list( + "list" = IC_PINTYPE_LIST, + "index" = IC_PINTYPE_NUMBER, + "item" = IC_PINTYPE_ANY + ) + outputs = list( + "redacted list" = IC_PINTYPE_LIST + ) + icon_state = "addition" + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + +/obj/item/integrated_circuit/list/write/do_work() + var/list/input_list = get_pin_data(IC_INPUT, 1) + var/index = get_pin_data(IC_INPUT, 2) + var/item = get_pin_data(IC_INPUT, 3) + input_list[index] = item + set_pin_data(IC_OUTPUT, 1, input_list) + push_data() + activate_pin(2) + +obj/item/integrated_circuit/list/len + name = "len circuit" + desc = "This circuit will give length of the list." + inputs = list( + "list" = IC_PINTYPE_LIST, + ) + outputs = list( + "item" = IC_PINTYPE_NUMBER + ) + icon_state = "addition" + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + +/obj/item/integrated_circuit/list/len/do_work() + var/list/input_list = get_pin_data(IC_INPUT, 1) + set_pin_data(IC_OUTPUT, 1, input_list.len) + push_data() + activate_pin(2) + + /obj/item/integrated_circuit/list/jointext name = "join text circuit" desc = "This circuit will add all elements of a list into one string, seperated by a character." extended_desc = "Default settings will encode the entire list into a string." inputs = list( - "list to join" = IC_PINTYPE_LIST, + "list to join" = IC_PINTYPE_LIST,// "delimiter" = IC_PINTYPE_CHAR, "start" = IC_PINTYPE_NUMBER, "end" = IC_PINTYPE_NUMBER diff --git a/code/modules/integrated_electronics/subtypes/memory.dm b/code/modules/integrated_electronics/subtypes/memory.dm index fa4fd9ded63..40f617e62e7 100644 --- a/code/modules/integrated_electronics/subtypes/memory.dm +++ b/code/modules/integrated_electronics/subtypes/memory.dm @@ -40,8 +40,15 @@ O.push_data() activate_pin(2) +/obj/item/integrated_circuit/memory/tiny + name = "small memory circuit" + desc = "This circuit can store two pieces of data." + icon_state = "memory2" + power_draw_per_use = 2 + number_of_pins = 2 + /obj/item/integrated_circuit/memory/medium - name = "memory circuit" + name = "medium memory circuit" desc = "This circuit can store four pieces of data." icon_state = "memory4" power_draw_per_use = 2 diff --git a/code/modules/integrated_electronics/subtypes/power.dm b/code/modules/integrated_electronics/subtypes/power.dm index f5284341294..e1e3f56c892 100644 --- a/code/modules/integrated_electronics/subtypes/power.dm +++ b/code/modules/integrated_electronics/subtypes/power.dm @@ -37,9 +37,7 @@ amount_to_move = 20000 /obj/item/integrated_circuit/power/transmitter/do_work() - set_pin_data(IC_OUTPUT, 1, null) - set_pin_data(IC_OUTPUT, 2, null) - set_pin_data(IC_OUTPUT, 3, null) + var/atom/movable/AM = get_pin_data_as_type(IC_INPUT, 1, /atom/movable) if(AM) if(!assembly) @@ -72,7 +70,15 @@ set_pin_data(IC_OUTPUT, 2, cell.maxcharge) set_pin_data(IC_OUTPUT, 3, cell.percent()) activate_pin(2) + push_data() return TRUE + else + set_pin_data(IC_OUTPUT, 1, null) + set_pin_data(IC_OUTPUT, 2, null) + set_pin_data(IC_OUTPUT, 3, null) + activate_pin(2) + push_data() + return FALSE return FALSE /obj/item/integrated_circuit/power/transmitter/large/do_work() diff --git a/code/modules/integrated_electronics/subtypes/reagents.dm b/code/modules/integrated_electronics/subtypes/reagents.dm index 25a80c2a28d..e6d65bd07a3 100644 --- a/code/modules/integrated_electronics/subtypes/reagents.dm +++ b/code/modules/integrated_electronics/subtypes/reagents.dm @@ -1,6 +1,8 @@ /obj/item/integrated_circuit/reagent category_text = "Reagent" var/volume = 0 + unacidable = 1 + phoronproof = 1 origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2) /obj/item/integrated_circuit/reagent/New() @@ -18,13 +20,23 @@ complexity = 20 cooldown_per_use = 30 SECONDS inputs = list() - outputs = list() - activators = list("create smoke" = IC_PINTYPE_PULSE_IN) + outputs = list("volume used" = IC_PINTYPE_NUMBER,"self reference" = IC_PINTYPE_REF) + activators = list("create smoke" = IC_PINTYPE_PULSE_IN,"on smoked" = IC_PINTYPE_PULSE_OUT) spawn_flags = IC_SPAWN_RESEARCH origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3, TECH_BIO = 3) volume = 100 power_draw_per_use = 20 +/obj/item/integrated_circuit/reagent/smoke/on_reagent_change() + set_pin_data(IC_OUTPUT, 1, reagents.total_volume) + push_data() + + +/obj/item/integrated_circuit/reagent/smoke/interact(mob/user) + set_pin_data(IC_OUTPUT, 2, weakref(src)) + push_data() + ..() + /obj/item/integrated_circuit/reagent/smoke/do_work() playsound(src.loc, 'sound/effects/smoke.ogg', 50, 1, -3) var/datum/effect/effect/system/smoke_spread/chem/smoke_system = new() @@ -33,52 +45,141 @@ for(var/i = 1 to 8) smoke_system.start() reagents.clear_reagents() + activate_pin(2) /obj/item/integrated_circuit/reagent/injector name = "integrated hypo-injector" desc = "This scary looking thing is able to pump liquids into whatever it's pointed at." icon_state = "injector" extended_desc = "This autoinjector can push reagents into another container or someone else outside of the machine. The target \ - must be adjacent to the machine, and if it is a person, they cannot be wearing thick clothing." + must be adjacent to the machine, and if it is a person, they cannot be wearing thick clothing. A negative amount makes the injector draw out reagents." flags = OPENCONTAINER complexity = 20 cooldown_per_use = 6 SECONDS inputs = list("target" = IC_PINTYPE_REF, "injection amount" = IC_PINTYPE_NUMBER) inputs_default = list("2" = 5) - outputs = list() - activators = list("inject" = IC_PINTYPE_PULSE_IN) + outputs = list("volume used" = IC_PINTYPE_NUMBER,"self reference" = IC_PINTYPE_REF) + activators = list("inject" = IC_PINTYPE_PULSE_IN, "on injected" = IC_PINTYPE_PULSE_OUT, "on fail" = IC_PINTYPE_PULSE_OUT) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH volume = 30 power_draw_per_use = 15 + var/direc = 1 + var/transfer_amount = 10 + +/obj/item/integrated_circuit/reagent/injector/interact(mob/user) + set_pin_data(IC_OUTPUT, 2, weakref(src)) + push_data() + ..() + + +/obj/item/integrated_circuit/reagent/injector/on_reagent_change() + set_pin_data(IC_OUTPUT, 1, reagents.total_volume) + push_data() + +/obj/item/integrated_circuit/reagent/injector/on_data_written() + var/new_amount = get_pin_data(IC_INPUT, 2) + if(new_amount < 0) + new_amount = -new_amount + direc = 0 + else + direc = 1 + if(isnum(new_amount)) + new_amount = Clamp(new_amount, 0, volume) + transfer_amount = new_amount -/obj/item/integrated_circuit/reagent/injector/proc/inject_amount() - var/amount = get_pin_data(IC_INPUT, 2) - if(isnum(amount)) - return Clamp(amount, 0, 30) /obj/item/integrated_circuit/reagent/injector/do_work() set waitfor = 0 // Don't sleep in a proc that is called by a processor without this set, otherwise it'll delay the entire thing - var/atom/movable/AM = get_pin_data_as_type(IC_INPUT, 1, /atom/movable) if(!istype(AM)) //Invalid input + activate_pin(3) return - if(!reagents.total_volume) // Empty - return - if(AM.can_be_injected_by(src)) - if(isliving(AM)) - var/mob/living/L = AM - var/turf/T = get_turf(AM) - T.visible_message("[src] is trying to inject [L]!") - sleep(3 SECONDS) - if(!L.can_be_injected_by(src)) + + if(direc == 1) + + if(!istype(AM)) //Invalid input + activate_pin(3) + return + if(!reagents.total_volume) // Empty + activate_pin(3) + return + if(AM.can_be_injected_by(src)) + if(isliving(AM)) + var/mob/living/L = AM + var/turf/T = get_turf(AM) + T.visible_message("[src] is trying to inject [L]!") + sleep(3 SECONDS) + if(!L.can_be_injected_by(src)) + activate_pin(3) + return + var/contained = reagents.get_reagents() + var/trans = reagents.trans_to_mob(L, transfer_amount, CHEM_BLOOD) + message_admins("[src] injected \the [L] with [trans]u of [contained].") + to_chat(AM, "You feel a tiny prick!") + visible_message("[src] injects [L]!") + else + reagents.trans_to(AM, transfer_amount) + else + + if(reagents.total_volume >= volume) // Full + activate_pin(3) + return + var/obj/target = AM + if(!target.reagents) + activate_pin(3) + return + var/turf/TS = get_turf(src) + var/turf/TT = get_turf(AM) + if(!TS.Adjacent(TT)) + activate_pin(3) + return + var/tramount = Clamp(min(transfer_amount, reagents.maximum_volume - reagents.total_volume), 0, reagents.maximum_volume) + if(ismob(target))//Blood! + if(istype(target, /mob/living/carbon)) + var/mob/living/carbon/T = target + if(!T.dna) + if(T.reagents.trans_to_obj(src, tramount)) + activate_pin(2) + else + activate_pin(3) + return + if(NOCLONE in T.mutations) //target done been et, no more blood in him + if(T.reagents.trans_to_obj(src, tramount)) + activate_pin(2) + else + activate_pin(3) + return + return + var/datum/reagent/B + if(istype(T, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = T + if(H.species && !H.should_have_organ(O_HEART)) + H.reagents.trans_to_obj(src, tramount) + else + B = T.take_blood(src, tramount) + else + B = T.take_blood(src,tramount) + if (B) + reagents.reagent_list |= B + reagents.update_total() + on_reagent_change() + reagents.handle_reactions() + B = null + visible_message( "Machine takes a blood sample from [target].") + else + activate_pin(3) return - var/contained = reagents.get_reagents() - var/trans = reagents.trans_to_mob(L, inject_amount(), CHEM_BLOOD) - message_admins("[src] injected \the [L] with [trans]u of [contained].") - to_chat(AM, "You feel a tiny prick!") - visible_message("[src] injects [L]!") - else - reagents.trans_to(AM, inject_amount()) + + else //if not mob + if(!target.reagents.total_volume) + visible_message( "[target] is empty.") + activate_pin(3) + return + target.reagents.trans_to_obj(src, tramount) + activate_pin(2) + + + /obj/item/integrated_circuit/reagent/pump name = "reagent pump" @@ -96,11 +197,17 @@ spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2) var/transfer_amount = 10 + var/direc = 1 power_draw_per_use = 10 /obj/item/integrated_circuit/reagent/pump/on_data_written() var/new_amount = get_pin_data(IC_INPUT, 3) - if(!isnull(new_amount)) + if(new_amount < 0) + new_amount = -new_amount + direc = 0 + else + direc = 1 + if(isnum(new_amount)) new_amount = Clamp(new_amount, 0, 50) transfer_amount = new_amount @@ -111,17 +218,23 @@ if(!istype(source) || !istype(target)) //Invalid input return var/turf/T = get_turf(src) - if(source.Adjacent(T) && target.Adjacent(T)) + var/turf/TS = get_turf(source) + var/turf/TT = get_turf(target) + if(TS.Adjacent(T) && TT.Adjacent(T)) if(!source.reagents || !target.reagents) return if(ismob(source) || ismob(target)) return if(!source.is_open_container() || !target.is_open_container()) return - if(!target.reagents.get_free_space()) - return - - source.reagents.trans_to(target, transfer_amount) + if(direc) + if(!target.reagents.get_free_space()) + return + source.reagents.trans_to(target, transfer_amount) + else + if(!source.reagents.get_free_space()) + return + target.reagents.trans_to(source, transfer_amount) activate_pin(2) /obj/item/integrated_circuit/reagent/storage @@ -132,12 +245,18 @@ flags = OPENCONTAINER complexity = 4 inputs = list() - outputs = list("volume used" = IC_PINTYPE_NUMBER) + outputs = list("volume used" = IC_PINTYPE_NUMBER,"self reference" = IC_PINTYPE_REF) activators = list() spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2) volume = 60 + +/obj/item/integrated_circuit/reagent/storage/interact(mob/user) + set_pin_data(IC_OUTPUT, 2, weakref(src)) + push_data() + ..() + /obj/item/integrated_circuit/reagent/storage/on_reagent_change() set_pin_data(IC_OUTPUT, 1, reagents.total_volume) push_data() @@ -150,4 +269,95 @@ flags = OPENCONTAINER | NOREACT complexity = 8 spawn_flags = IC_SPAWN_RESEARCH - origin_tech = list(TECH_MATERIAL = 3, TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2) \ No newline at end of file + origin_tech = list(TECH_MATERIALS = 4, TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2) + +/obj/item/integrated_circuit/reagent/storage/big + name = "big reagent storage" + desc = "Stores liquid inside, and away from electrical components. Can store up to 180u." + icon_state = "reagent_storage_big" + extended_desc = "This is effectively an internal beaker." + flags = OPENCONTAINER + complexity = 16 + volume = 180 + spawn_flags = IC_SPAWN_RESEARCH + origin_tech = list(TECH_MATERIALS = 3, TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2) + +/obj/item/integrated_circuit/reagent/storage/scan + name = "reagent scanner" + desc = "Stores liquid inside, and away from electrical components. Can store up to 60u. On pulse this beaker will send list of contained reagents." + icon_state = "reagent_scan" + extended_desc = "Mostly useful for reagent filter." + flags = OPENCONTAINER + complexity = 8 + outputs = list("volume used" = IC_PINTYPE_NUMBER,"self reference" = IC_PINTYPE_REF,"list of reagents" = IC_PINTYPE_LIST) + activators = list("scan" = IC_PINTYPE_PULSE_IN) + spawn_flags = IC_SPAWN_RESEARCH + origin_tech = list(TECH_MATERIALS = 3, TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2) + +/obj/item/integrated_circuit/reagent/storage/scan/do_work() + var/cont[0] + for(var/datum/reagent/RE in reagents.reagent_list) + cont += RE.id + set_pin_data(IC_OUTPUT, 3, cont) + push_data() + + +/obj/item/integrated_circuit/reagent/filter + name = "reagent filter" + desc = "Filtering liquids by list of desired or unwanted reagents." + icon_state = "reagent_filter" + extended_desc = "This is a filter which will move liquids from the source ref to the target ref. \ + It will move all reagents, except list, given in fourth pin if amount value is positive.\ + Or it will move only desired reagents if amount is negative, The third pin determines \ + how much reagent is moved per pulse, between 0 and 50. Amount is given for each separate reagent." + flags = OPENCONTAINER + complexity = 8 + inputs = list("source" = IC_PINTYPE_REF, "target" = IC_PINTYPE_REF, "injection amount" = IC_PINTYPE_NUMBER, "list of reagents" = IC_PINTYPE_LIST) + inputs_default = list("3" = 5) + outputs = list() + activators = list("transfer reagents" = IC_PINTYPE_PULSE_IN, "on transfer" = IC_PINTYPE_PULSE_OUT) + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2) + var/transfer_amount = 10 + var/direc = 1 + power_draw_per_use = 10 + +/obj/item/integrated_circuit/reagent/filter/on_data_written() + var/new_amount = get_pin_data(IC_INPUT, 3) + if(new_amount < 0) + new_amount = -new_amount + direc = 0 + else + direc = 1 + if(isnum(new_amount)) + new_amount = Clamp(new_amount, 0, 50) + transfer_amount = new_amount + +/obj/item/integrated_circuit/reagent/filter/do_work() + var/atom/movable/source = get_pin_data_as_type(IC_INPUT, 1, /atom/movable) + var/atom/movable/target = get_pin_data_as_type(IC_INPUT, 2, /atom/movable) + var/list/demand = get_pin_data(IC_INPUT, 4) + if(!istype(source) || !istype(target)) //Invalid input + return + var/turf/T = get_turf(src) + if(source.Adjacent(T) && target.Adjacent(T)) + if(!source.reagents || !target.reagents) + return + if(ismob(source) || ismob(target)) + return + if(!source.is_open_container() || !target.is_open_container()) + return + if(!target.reagents.get_free_space()) + return + for(var/datum/reagent/G in source.reagents.reagent_list) + if (!direc) + if(G.id in demand) + source.reagents.trans_id_to(target, G.id, transfer_amount) + else + if(!(G.id in demand)) + source.reagents.trans_id_to(target, G.id, transfer_amount) + activate_pin(2) + push_data() + + + diff --git a/code/modules/maps/tg/map_template.dm b/code/modules/maps/tg/map_template.dm index 3aaf324463b..54b08c74d9e 100644 --- a/code/modules/maps/tg/map_template.dm +++ b/code/modules/maps/tg/map_template.dm @@ -18,6 +18,12 @@ var/list/global/map_templates = list() var/mappath = null var/loaded = 0 // Times loaded this round var/annihilate = FALSE // If true, all (movable) atoms at the location where the map is loaded will be deleted before the map is loaded in. + + var/cost = null // The map generator has a set 'budget' it spends to place down different submaps. It will pick available submaps randomly until \ + it runs out. The cost of a submap should roughly corrispond with several factors such as size, loot, difficulty, desired scarcity, etc. \ + Set to -1 to force the submap to always be made. + var/allow_duplicates = FALSE // If false, only one map template will be spawned by the game. Doesn't affect admins spawning then manually. + var/static/dmm_suite/maploader = new /datum/map_template/New(path = null, rename = null) @@ -111,7 +117,7 @@ var/list/global/map_templates = list() log_game("Z-level [name] loaded at at [x],[y],[world.maxz]") return TRUE -/datum/map_template/proc/load(turf/T, centered = FALSE) +/datum/map_template/proc/load(turf/T, centered = FALSE, dont_init = FALSE) var/old_T = T if(centered) T = locate(T.x - round(width/2) , T.y - round(height/2) , T.z) @@ -133,7 +139,8 @@ var/list/global/map_templates = list() // repopulate_sorted_areas() //initialize things that are normally initialized after map load - initTemplateBounds(bounds) + if(!dont_init) + initTemplateBounds(bounds) log_game("[name] loaded at at [T.x],[T.y],[T.z]") loaded++ @@ -163,4 +170,118 @@ var/list/global/map_templates = list() //⤠- Cyberboss /proc/load_new_z_level(var/file, var/name) var/datum/map_template/template = new(file, name) - template.load_new_z() \ No newline at end of file + template.load_new_z() + +// Very similar to the /tg/ version. +/proc/seed_submaps(var/list/z_levels, var/budget = 0, var/whitelist = /area/space, var/desired_map_template_type = null) + set background = TRUE + + if(!z_levels || !z_levels.len) + admin_notice("seed_submaps() was not given any Z-levels.", R_DEBUG) + return + + for(var/zl in z_levels) + var/turf/T = locate(1, 1, zl) + if(!T) + admin_notice("Z level [zl] does not exist - Not generating submaps", R_DEBUG) + return + + var/overall_sanity = 100 // If the proc fails to place a submap more than this, the whole thing aborts. + var/list/potential_submaps = list() // Submaps we may or may not place. + var/list/priority_submaps = list() // Submaps that will always be placed. + + // Lets go find some submaps to make. + for(var/map in map_templates) + var/datum/map_template/MT = map_templates[map] + if(!MT.allow_duplicates && MT.loaded > 0) // This probably won't be an issue but we might as well. + continue + if(!istype(MT, desired_map_template_type)) // Not the type wanted. + continue + if(MT.cost && MT.cost < 0) // Negative costs always get spawned. + priority_submaps += MT + else + potential_submaps += MT + + CHECK_TICK + + var/list/loaded_submap_names = list() + + // Now lets start choosing some. + while(budget > 0 && overall_sanity > 0) + overall_sanity-- + var/datum/map_template/chosen_template = null + + if(potential_submaps.len) + if(priority_submaps.len) // Do these first. + chosen_template = pick(priority_submaps) + else + chosen_template = pick(potential_submaps) + + else // We're out of submaps. + admin_notice("Submap loader had no submaps to pick from with [budget] left to spend.", R_DEBUG) + break + + CHECK_TICK + + // Can we afford it? + if(chosen_template.cost > budget) + continue + + // If so, try to place it. + var/specific_sanity = 100 // A hundred chances to place the chosen submap. + while(specific_sanity > 0) + specific_sanity-- + var/width_border = TRANSITIONEDGE + SUBMAP_MAP_EDGE_PAD + round(chosen_template.width / 2) + var/height_border = TRANSITIONEDGE + SUBMAP_MAP_EDGE_PAD + round(chosen_template.height / 2) + var/z_level = pick(z_levels) + var/turf/T = locate(rand(width_border, world.maxx - width_border), rand(height_border, world.maxy - height_border), z_level) + var/valid = TRUE + + for(var/turf/check in chosen_template.get_affected_turfs(T,1)) + var/area/new_area = get_area(check) + if(!(istype(new_area, whitelist))) + valid = FALSE // Probably overlapping something important. + // world << "Invalid due to overlapping with area [new_area.type], when wanting area [whitelist]." + break + CHECK_TICK + + CHECK_TICK + + if(!valid) + continue + + admin_notice("Submap \"[chosen_template.name]\" placed at ([T.x], [T.y], [T.z])", R_DEBUG) + + // Do loading here. + chosen_template.load(T, centered = TRUE, dont_init = TRUE) // This is run before the main map's initialization routine, so that can initilize our submaps for us instead. + + CHECK_TICK + + if(loaded_submap_names[chosen_template.name]) + loaded_submap_names[chosen_template.name] += 1 + else + loaded_submap_names[chosen_template.name] = 1 + + if(chosen_template.cost >= 0) + budget -= chosen_template.cost + + if(chosen_template in priority_submaps) // Always remove priority submaps. + priority_submaps -= chosen_template + else if(!chosen_template.allow_duplicates) + potential_submaps -= chosen_template + + break // Load the next submap. + + var/list/pretty_submap_list = list() + for(var/submap_name in loaded_submap_names) + var/count = loaded_submap_names[submap_name] + if(count > 1) + pretty_submap_list += "[count] [submap_name]" + else + pretty_submap_list += "[submap_name]" + + if(!overall_sanity) + admin_notice("Submap loader gave up with [budget] left to spend.", R_DEBUG) + else + admin_notice("Submaps loaded.", R_DEBUG) + admin_notice("Loaded: [english_list(pretty_submap_list)]", R_DEBUG) \ No newline at end of file diff --git a/code/modules/materials/material_recipes.dm b/code/modules/materials/material_recipes.dm index c0c1eecd9e7..7408b692a73 100644 --- a/code/modules/materials/material_recipes.dm +++ b/code/modules/materials/material_recipes.dm @@ -13,7 +13,7 @@ recipes += new/datum/stack_recipe("[display_name] armor plate", /obj/item/weapon/material/armor_plating, 1, time = 20, on_floor = 1, supplied_material = "[name]") recipes += new/datum/stack_recipe("[display_name] grave marker", /obj/item/weapon/material/gravemarker, 5, time = 50, supplied_material = "[name]") recipes += new/datum/stack_recipe("[display_name] ring", /obj/item/clothing/gloves/ring/material, 1, on_floor = 1, supplied_material = "[name]") - + recipes += new/datum/stack_recipe("[display_name] bracelet", /obj/item/clothing/accessory/bracelet/material, 1, on_floor = 1, supplied_material = "[name]") if(integrity>=50) recipes += new/datum/stack_recipe("[display_name] door", /obj/structure/simple_door, 10, one_per_turf = 1, on_floor = 1, supplied_material = "[name]") diff --git a/code/modules/materials/materials.dm b/code/modules/materials/materials.dm index 0db3a1016ec..1ce1eca2d81 100644 --- a/code/modules/materials/materials.dm +++ b/code/modules/materials/materials.dm @@ -642,6 +642,19 @@ var/list/name_to_material display_name = "elevator panelling" icon_colour = "#666666" +// Ditto. +/material/alienalloy/dungeonium + name = "dungeonium" + display_name = "ultra-durable" + icon_base = "dungeon" + icon_colour = "#FFFFFF" + +/material/alienalloy/alium + name = "alium" + display_name = "alien" + icon_base = "alien" + icon_colour = "#FFFFFF" + /material/resin name = "resin" icon_colour = "#35343a" diff --git a/code/modules/mob/_modifiers/modifiers.dm b/code/modules/mob/_modifiers/modifiers.dm index ee6d914fa69..7164396f297 100644 --- a/code/modules/mob/_modifiers/modifiers.dm +++ b/code/modules/mob/_modifiers/modifiers.dm @@ -41,6 +41,8 @@ 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. + var/attack_speed_percent // Makes the holder's 'attack speed' (click delay) shorter or longer. /datum/modifier/New(var/new_holder, var/new_origin) holder = new_holder @@ -62,6 +64,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 +121,8 @@ modifiers.Add(mod) if(mod.mob_overlay_state) update_modifier_visuals() + if(mod.icon_scale_percent) + update_transform() return mod @@ -198,6 +204,11 @@ 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"]." + + if(!isnull(attack_speed_percent)) + effects += "The delay between attacking is [multipler_to_percentage(attack_speed_percent, TRUE)] [disable_duration_percent > 1.0 ? "longer" : "shorter"]." return jointext(effects, "
") diff --git a/code/modules/mob/_modifiers/traits.dm b/code/modules/mob/_modifiers/traits.dm index 824343c41c4..3e9e8278e42 100644 --- a/code/modules/mob/_modifiers/traits.dm +++ b/code/modules/mob/_modifiers/traits.dm @@ -58,4 +58,28 @@ desc = "Your body's metabolism is slower than average." metabolism_percent = 0.5 - incoming_healing_percent = 0.6 \ No newline at end of file + incoming_healing_percent = 0.6 + +/datum/modifier/trait/larger + name = "Larger" + desc = "Your body is larger than average." + + icon_scale_percent = 1.2 + +/datum/modifier/trait/large + name = "Large" + desc = "Your body is a bit larger than average." + + icon_scale_percent = 1.1 + +/datum/modifier/trait/small + name = "Small" + desc = "Your body is a bit smaller than average." + + icon_scale_percent = 0.95 + +/datum/modifier/trait/smaller + name = "Smaller" + desc = "Your body is smaller than average." + + icon_scale_percent = 0.9 \ No newline at end of file diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 83bf7246076..52426454e22 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -201,6 +201,11 @@ Works together with spawning an observer, noted above. /mob/proc/ghostize(var/can_reenter_corpse = 1) if(key) + if(ishuman(src)) + var/mob/living/carbon/human/H = src + if(H.vr_holder && !can_reenter_corpse) + H.exit_vr() + return 0 var/mob/observer/dead/ghost = new(src) //Transfer safety to observer spawning proc. ghost.can_reenter_corpse = can_reenter_corpse ghost.timeofdeath = src.timeofdeath //BS12 EDIT @@ -243,9 +248,10 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp var/turf/location = get_turf(src) message_admins("[key_name_admin(usr)] has ghosted. (JMP)") log_game("[key_name_admin(usr)] has ghosted.") - var/mob/observer/dead/ghost = ghostize(0) //0 parameter is so we can never re-enter our body, "Charlie, you can never come baaaack~" :3 - ghost.timeofdeath = world.time // Because the living mob won't have a time of death and we want the respawn timer to work properly. - announce_ghost_joinleave(ghost) + var/mob/observer/dead/ghost = ghostize(0) // 0 parameter is so we can never re-enter our body, "Charlie, you can never come baaaack~" :3 + if(ghost) + ghost.timeofdeath = world.time // Because the living mob won't have a time of death and we want the respawn timer to work properly. + announce_ghost_joinleave(ghost) /mob/observer/dead/can_use_hands() return 0 /mob/observer/dead/is_active() return 0 @@ -310,19 +316,18 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp if(!client) return - var/mentor = is_eventM(usr.client) - if(!config.antag_hud_allowed && (!client.holder || mentor)) + if(!config.antag_hud_allowed && !client.holder) src << "Admins have disabled this for this round." return var/mob/observer/dead/M = src if(jobban_isbanned(M, "AntagHUD")) src << "You have been banned from using this feature" return - if(config.antag_hud_restricted && !M.has_enabled_antagHUD && (!client.holder || mentor)) + if(config.antag_hud_restricted && !M.has_enabled_antagHUD && !client.holder) var/response = alert(src, "If you turn this on, you will not be able to take any part in the round.","Are you sure you want to turn this feature on?","Yes","No") if(response == "No") return M.can_reenter_corpse = 0 - if(!M.has_enabled_antagHUD && (!client.holder || mentor)) + if(!M.has_enabled_antagHUD && !client.holder) M.has_enabled_antagHUD = 1 if(M.antagHUD) M.antagHUD = 0 diff --git a/code/modules/mob/living/bot/cleanbot.dm b/code/modules/mob/living/bot/cleanbot.dm index d4cb7238614..4f9f81156f1 100644 --- a/code/modules/mob/living/bot/cleanbot.dm +++ b/code/modules/mob/living/bot/cleanbot.dm @@ -1,6 +1,6 @@ /mob/living/bot/cleanbot name = "Cleanbot" - desc = "A little cleaning robot, he looks so excited!" + desc = "A little cleaning robot, it looks so excited!" icon_state = "cleanbot0" req_one_access = list(access_robotics, access_janitor) botcard_access = list(access_janitor, access_maint_tunnels) @@ -21,7 +21,8 @@ /mob/living/bot/cleanbot/handleIdle() if(!screwloose && !oddbutton && prob(5)) - custom_emote(2, "makes an excited beeping booping sound!") + custom_emote(2, "makes an excited booping sound!") + playsound(src.loc, 'sound/machines/synth_yes.ogg', 50, 0) if(screwloose && prob(5)) // Make a mess if(istype(loc, /turf/simulated)) @@ -29,7 +30,7 @@ T.wet_floor() if(oddbutton && prob(5)) // Make a big mess - visible_message("Something flies out of [src]. He seems to be acting oddly.") + visible_message("Something flies out of [src]. It seems to be acting oddly.") var/obj/effect/decal/cleanable/blood/gibs/gib = new /obj/effect/decal/cleanable/blood/gibs(loc) // TODO - I have a feeling weakrefs will not work in ignore_list, verify this ~Leshana var/weakref/g = weakref(gib) @@ -150,6 +151,7 @@ if(!screwloose || !oddbutton) if(user) user << "The [src] buzzes and beeps." + playsound(src.loc, 'sound/machines/buzzbeep.ogg', 50, 0) oddbutton = 1 screwloose = 1 return 1 @@ -199,4 +201,4 @@ return if(!in_range(src, usr) && src.loc != usr) return - created_name = t \ No newline at end of file + created_name = t diff --git a/code/modules/mob/living/bot/floorbot.dm b/code/modules/mob/living/bot/floorbot.dm index a843206e5e1..95c83dcaa0a 100644 --- a/code/modules/mob/living/bot/floorbot.dm +++ b/code/modules/mob/living/bot/floorbot.dm @@ -6,7 +6,7 @@ /mob/living/bot/floorbot name = "Floorbot" - desc = "A little floor repairing robot, he looks so excited!" + desc = "A little floor repairing robot, it looks so excited!" icon_state = "floorbot0" req_one_access = list(access_robotics, access_construction) wait_if_pulled = 1 @@ -58,6 +58,7 @@ emagged = 1 if(user) user << "The [src] buzzes and beeps." + playsound(src.loc, 'sound/machines/buzzbeep.ogg', 50, 0) return 1 /mob/living/bot/floorbot/Topic(href, href_list) @@ -100,7 +101,8 @@ addTiles(1) if(prob(1)) - custom_emote(2, "makes an excited booping beeping sound!") + custom_emote(2, "makes an excited beeping sound!") + playsound(src.loc, 'sound/machines/twobeep.ogg', 50, 0) /mob/living/bot/floorbot/handleAdjacentTarget() if(get_turf(target) == src.loc) @@ -276,6 +278,7 @@ /mob/living/bot/floorbot/explode() turn_off() visible_message("\The [src] blows apart!") + playsound(src.loc, "sparks", 50, 1) var/turf/Tsec = get_turf(src) var/obj/item/weapon/storage/toolbox/mechanical/N = new /obj/item/weapon/storage/toolbox/mechanical(Tsec) diff --git a/code/modules/mob/living/carbon/alien/alien_attacks.dm b/code/modules/mob/living/carbon/alien/alien_attacks.dm index e201e851167..c120b9deefa 100644 --- a/code/modules/mob/living/carbon/alien/alien_attacks.dm +++ b/code/modules/mob/living/carbon/alien/alien_attacks.dm @@ -15,7 +15,7 @@ if (I_GRAB) if (M == src) return - var/obj/item/weapon/grab/G = new /obj/item/weapon/grab( M, M, src ) + var/obj/item/weapon/grab/G = new /obj/item/weapon/grab( M, src ) M.put_in_active_hand(G) @@ -56,4 +56,4 @@ for(var/mob/O in viewers(src, null)) if ((O.client && !( O.blinded ))) O.show_message(text("[] has attempted to punch []!", M, src), 1) - return \ No newline at end of file + return diff --git a/code/modules/mob/living/carbon/alien/diona/diona.dm b/code/modules/mob/living/carbon/alien/diona/diona.dm index ebcd4d7774f..8a2b24cf50f 100644 --- a/code/modules/mob/living/carbon/alien/diona/diona.dm +++ b/code/modules/mob/living/carbon/alien/diona/diona.dm @@ -37,4 +37,12 @@ return hat = new_hat new_hat.loc = src - update_icons() \ No newline at end of file + update_icons() + +/mob/living/carbon/alien/diona/proc/handle_npc(var/mob/living/carbon/alien/diona/D) + if(D.stat != CONSCIOUS) + return + if(prob(33) && D.canmove && isturf(D.loc) && !D.pulledby) //won't move if being pulled + step(D, pick(cardinal)) + if(prob(1)) + D.emote(pick("scratch","jump","chirp","roll")) diff --git a/code/modules/mob/living/carbon/alien/diona/diona_attacks.dm b/code/modules/mob/living/carbon/alien/diona/diona_attacks.dm index 9bf9e62dfb9..3adf6b34f02 100644 --- a/code/modules/mob/living/carbon/alien/diona/diona_attacks.dm +++ b/code/modules/mob/living/carbon/alien/diona/diona_attacks.dm @@ -14,10 +14,10 @@ /mob/living/carbon/alien/diona/attackby(var/obj/item/weapon/W, var/mob/user) if(user.a_intent == "help" && istype(W, /obj/item/clothing/head)) if(hat) - user << "\The [src] is already wearing \the [hat]." + to_chat(user, "\The [src] is already wearing \the [hat].") return user.unEquip(W) wear_hat(W) user.visible_message("\The [user] puts \the [W] on \the [src].") return - return ..() \ No newline at end of file + return ..() diff --git a/code/modules/mob/living/carbon/alien/diona/life.dm b/code/modules/mob/living/carbon/alien/diona/life.dm index fecf9b12c03..aa178f93c14 100644 --- a/code/modules/mob/living/carbon/alien/diona/life.dm +++ b/code/modules/mob/living/carbon/alien/diona/life.dm @@ -14,4 +14,8 @@ adjustBruteLoss(-1) adjustFireLoss(-1) adjustToxLoss(-1) - adjustOxyLoss(-1) \ No newline at end of file + adjustOxyLoss(-1) + + + if(!client) + handle_npc(src) diff --git a/code/modules/mob/living/carbon/breathe.dm b/code/modules/mob/living/carbon/breathe.dm index d11043ebf77..c14e6350831 100644 --- a/code/modules/mob/living/carbon/breathe.dm +++ b/code/modules/mob/living/carbon/breathe.dm @@ -13,10 +13,10 @@ //First, check if we can breathe at all if(health < config.health_threshold_crit && !(CE_STABLE in chem_effects)) //crit aka circulatory shock - losebreath++ + AdjustLosebreath(1) if(losebreath>0) //Suffocating so do not take a breath - losebreath-- + AdjustLosebreath(-1) if (prob(10)) //Gasp per 10 ticks? Sounds about right. spawn emote("gasp") else diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 194864b7de5..233f0f020fb 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -109,20 +109,28 @@ playsound(loc, "sparks", 50, 1, -1) if (shock_damage > 15) src.visible_message( - "[src] was shocked by \the [source]!", \ - "You feel a powerful shock course through your body!", \ - "You hear a heavy electrical crack." \ + "[src] was electrocuted[source ? " by the [source]" : ""]!", \ + "You feel a powerful shock course through your body!", \ + "You hear a heavy electrical crack." \ ) - if(stun) - Stun(10)//This should work for now, more is really silly and makes you lay there forever - Weaken(10) else src.visible_message( - "[src] was mildly shocked by \the [source].", \ - "You feel a mild shock course through your body.", \ - "You hear a light zapping." \ + "[src] was shocked[source ? " by the [source]" : ""].", \ + "You feel a shock course through your body.", \ + "You hear a zapping sound." \ ) + if(stun) + switch(shock_damage) + if(16 to 20) + Stun(2) + if(21 to 25) + Weaken(2) + if(26 to 30) + Weaken(5) + if(31 to INFINITY) + Weaken(10) //This should work for now, more is really silly and makes you lay there forever + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread s.set_up(5, 1, loc) s.start() diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm index 66ba7ecd514..08d0c9384e7 100644 --- a/code/modules/mob/living/carbon/carbon_defense.dm +++ b/code/modules/mob/living/carbon/carbon_defense.dm @@ -25,7 +25,7 @@ weapon_edge = 0 hit_embed_chance = I.force/(I.w_class*3) - apply_damage(effective_force, I.damtype, hit_zone, blocked, sharp=weapon_sharp, edge=weapon_edge, used_weapon=I) + apply_damage(effective_force, I.damtype, hit_zone, blocked, soaked, sharp=weapon_sharp, edge=weapon_edge, used_weapon=I) //Melee weapon embedded object code. if (I && I.damtype == BRUTE && !I.anchored && !is_robot_module(I) && I.embed_chance > 0) diff --git a/code/modules/mob/living/carbon/human/appearance.dm b/code/modules/mob/living/carbon/human/appearance.dm index 101390b3d63..3b83f1e8c2e 100644 --- a/code/modules/mob/living/carbon/human/appearance.dm +++ b/code/modules/mob/living/carbon/human/appearance.dm @@ -95,7 +95,7 @@ return 1 /mob/living/carbon/human/proc/change_hair_color(var/red, var/green, var/blue) - if(red == r_eyes && green == g_eyes && blue == b_eyes) + if(red == r_hair && green == g_hair && blue == b_hair) return r_hair = red diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm index ffac791a1fd..8df0bd16052 100644 --- a/code/modules/mob/living/carbon/human/death.dm +++ b/code/modules/mob/living/carbon/human/death.dm @@ -1,5 +1,15 @@ /mob/living/carbon/human/gib() + if(vr_holder) + exit_vr() + // Delete the link, because this mob won't be around much longer + vr_holder.vr_link = null + + if(vr_link) + vr_link.exit_vr() + vr_link.vr_holder = null + vr_link = null + for(var/obj/item/organ/I in internal_organs) I.removed() if(istype(loc,/turf)) @@ -80,6 +90,20 @@ if(wearing_rig) wearing_rig.notify_ai("Warning: user death event. Mobility control passed to integrated intelligence system.") + // If the body is in VR, move the mind back to the real world + if(vr_holder) + src.exit_vr() + src.vr_holder.vr_link = null + for(var/obj/item/W in src) + src.drop_from_inventory(W) + + // If our mind is in VR, bring it back to the real world so it can die with its body + if(vr_link) + vr_link.exit_vr() + vr_link.vr_holder = null + vr_link = null + to_chat(src, "Everything abruptly stops.") + return ..(gibbed,species.get_death_message(src)) /mob/living/carbon/human/proc/ChangeToHusk() @@ -113,4 +137,4 @@ mutations.Add(SKELETON) status_flags |= DISFIGURED update_body(1) - return + return \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 615a3ecf533..81ea775ab9a 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -18,17 +18,9 @@ var/skiparms = 0 var/skipfeet = 0 - - var/cloaked = 0 // 0 for normal, 1 for cloaked close - - if(mind && mind.changeling && mind.changeling.cloaked && !istype(user, /mob/observer)) - var/distance = get_dist(user, src) - if(distance > 2) - src.loc.examine(user) - return - else - cloaked = 1 - + if(alpha <= 50) + src.loc.examine(user) + return var/looks_synth = looksSynthetic() @@ -97,8 +89,6 @@ if(skipjumpsuit && skipface) //big suits/masks/helmets make it hard to tell their gender T = gender_datums[PLURAL] - if(cloaked) - T = gender_datums[NEUTER] else if(species && species.ambiguous_genders) var/can_detect_gender = FALSE @@ -458,25 +448,18 @@ msg += "Medical records: \[View\] \[Add comment\]\n" - if(print_flavor_text() && !cloaked) + if(print_flavor_text()) msg += "[print_flavor_text()]\n" msg += "*---------*
" msg += applying_pressure - if (pose && !cloaked) + if (pose) if( findtext(pose,".",lentext(pose)) == 0 && findtext(pose,"!",lentext(pose)) == 0 && findtext(pose,"?",lentext(pose)) == 0 ) pose = addtext(pose,".") //Makes sure all emotes end with a period. msg += "[T.He] [pose]" user << jointext(msg, null) - -/mob/living/carbon/human/get_description_fluff() - if(mind && mind.changeling && mind.changeling.cloaked) - return "" - else - return ..() - //Helper procedure. Called by /mob/living/carbon/human/examine() and /mob/living/carbon/human/Topic() to determine HUD access to security and medical records. /proc/hasHUD(mob/M as mob, hudtype) if(istype(M, /mob/living/carbon/human)) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index ab16e58263d..d7e7f2a169b 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -15,6 +15,8 @@ var/spit_name = null //String var/last_spit = 0 //Timestamp. + var/can_defib = 1 //Horrible damage (like beheadings) will prevent defibbing organics. + /mob/living/carbon/human/New(var/new_loc, var/new_species = null) if(!dna) @@ -36,8 +38,12 @@ nutrition = rand(200,400) hud_list[HEALTH_HUD] = new /image/hud_overlay('icons/mob/hud_med.dmi', src, "100") - hud_list[STATUS_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudhealthy") - hud_list[LIFE_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudhealthy") + if(isSynthetic()) + hud_list[STATUS_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudrobo") + hud_list[LIFE_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudrobo") + else + hud_list[STATUS_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudhealthy") + hud_list[LIFE_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudhealthy") hud_list[ID_HUD] = new /image/hud_overlay(using_map.id_hud_icons, src, "hudunknown") hud_list[WANTED_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudblank") hud_list[IMPLOYAL_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudblank") @@ -318,15 +324,13 @@ //repurposed proc. Now it combines get_id_name() and get_face_name() to determine a mob's name variable. Made into a seperate proc as it'll be useful elsewhere /mob/living/carbon/human/proc/get_visible_name() - if( mind && mind.changeling && mind.changeling.cloaked) - return "Unknown" if( wear_mask && (wear_mask.flags_inv&HIDEFACE) ) //Wearing a mask which hides our face, use id-name if possible return get_id_name("Unknown") if( head && (head.flags_inv&HIDEFACE) ) return get_id_name("Unknown") //Likewise for hats var/face_name = get_face_name() var/id_name = get_id_name("") - if(id_name && (id_name != face_name)) + if((face_name == "Unknown") && id_name && (id_name != face_name)) return "[face_name] (as [id_name])" return face_name @@ -1136,6 +1140,9 @@ if(species.default_language) add_language(species.default_language) + if(species.icon_scale != 1) + update_transform() + if(species.base_color && default_colour) //Apply colour. r_skin = hex2num(copytext(species.base_color,2,4)) @@ -1523,4 +1530,55 @@ var/turf/T = get_turf(src) var/obj/item/clothing/accessory/permit/drone/permit = new(T) permit.set_name(real_name) - equip_to_appropriate_slot(permit) // If for some reason it can't find room, it'll still be on the floor. \ No newline at end of file + equip_to_appropriate_slot(permit) // If for some reason it can't find room, it'll still be on the floor. + +// enter_vr is called on the original mob, and puts the mind into the supplied vr mob +/mob/living/carbon/human/proc/enter_vr(var/mob/living/carbon/human/avatar) // Avatar is currently a human, because we have preexisting setup code for appearance manipulation, etc. + if(!istype(avatar)) + return + + // Link the two mobs for client transfer + avatar.vr_holder = src + src.teleop = avatar + src.vr_link = avatar // Can't reuse vr_holder so that death can automatically eject users from VR + + // Move the mind + avatar.Sleeping(1) + src.mind.transfer_to(avatar) + to_chat(avatar, "You have enterred Virtual Reality!\nAll normal gameplay rules still apply.\nWounds you suffer here won't persist when you leave VR, but some of the pain will.\nYou can leave VR at any time by using the \"Exit Virtual Reality\" verb in the Abilities tab, or by ghosting.\nYou can modify your appearance by using various \"Change \[X\]\" verbs in the Abilities tab.") + to_chat(avatar, " You black out for a moment, and wake to find yourself in a new body in virtual reality.") // So this is what VR feels like? + +// exit_vr is called on the vr mob, and puts the mind back into the original mob +/mob/living/carbon/human/verb/exit_vr() + set name = "Exit Virtual Reality" + set category = "Abilities" + + if(!vr_holder) + return + if(!mind) + return + + var/total_damage + // Tally human damage + if(ishuman(src)) + var/mob/living/carbon/human/H = src + total_damage = H.getBruteLoss() + H.getFireLoss() + H.getOxyLoss() + H.getToxLoss() + + // Move the mind back to the original mob +// vr_holder.Sleeping(1) + src.mind.transfer_to(vr_holder) + to_chat(vr_holder, "You black out for a moment, and wake to find yourself back in your own body.") + // Two-thirds damage is transferred as agony for /humans + // Getting hurt in VR doesn't damage the physical body, but you still got hurt. + if(ishuman(vr_holder) && total_damage) + var/mob/living/carbon/human/V = vr_holder + V.stun_effect_act(0, total_damage*2/3, null) // 200 damage leaves the user in paincrit for several seconds, agony reaches 0 after around 2m. + to_chat(vr_holder, "Pain from your time in VR lingers.") // 250 damage leaves the user unconscious for several seconds in addition to paincrit + + // Maintain a link with the mob, but don't use teleop + vr_holder.vr_link = src + vr_holder.teleop = null + + if(istype(vr_holder.loc, /obj/machinery/vr_sleeper)) + var/obj/machinery/vr_sleeper/V = vr_holder.loc + V.go_out() diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm index 34ab2bf4bb6..45532aa1d48 100644 --- a/code/modules/mob/living/carbon/human/human_damage.dm +++ b/code/modules/mob/living/carbon/human/human_damage.dm @@ -283,19 +283,19 @@ ..() /mob/living/carbon/human/getToxLoss() - if((species.flags & NO_POISON) || isSynthetic()) + if(species.flags & NO_POISON) toxloss = 0 return ..() /mob/living/carbon/human/adjustToxLoss(var/amount) - if((species.flags & NO_POISON) || isSynthetic()) + if(species.flags & NO_POISON) toxloss = 0 else amount = amount*species.toxins_mod ..(amount) /mob/living/carbon/human/setToxLoss(var/amount) - if((species.flags & NO_POISON) || isSynthetic()) + if(species.flags & NO_POISON) toxloss = 0 else ..() @@ -425,9 +425,9 @@ This function restores all organs. zone = BP_HEAD return organs_by_name[zone] -/mob/living/carbon/human/apply_damage(var/damage = 0, var/damagetype = BRUTE, var/def_zone = null, var/blocked = 0, var/sharp = 0, var/edge = 0, var/obj/used_weapon = null) +/mob/living/carbon/human/apply_damage(var/damage = 0, var/damagetype = BRUTE, var/def_zone = null, var/blocked = 0, var/soaked = 0, var/sharp = 0, var/edge = 0, var/obj/used_weapon = null) if(Debug2) - world.log << "## DEBUG: human/apply_damage() was called on [src], with [damage] damage, and an armor value of [blocked]." + world.log << "## DEBUG: human/apply_damage() was called on [src], with [damage] damage, an armor value of [blocked], and a soak value of [soaked]." var/obj/item/organ/external/organ = null if(isorgan(def_zone)) @@ -442,7 +442,7 @@ This function restores all organs. if((damage > 25 && prob(20)) || (damage > 50 && prob(60))) if(organ && organ.organ_can_feel_pain()) emote("scream") - ..(damage, damagetype, def_zone, blocked) + ..(damage, damagetype, def_zone, blocked, soaked) return 1 //Handle BRUTE and BURN damage @@ -451,12 +451,18 @@ This function restores all organs. if(blocked >= 100) return 0 + if(soaked >= damage) + return 0 if(!organ) return 0 if(blocked) blocked = (100-blocked)/100 damage = (damage * blocked) + + if(soaked) + damage -= soaked + if(Debug2) world.log << "## DEBUG: [src] was hit for [damage]." diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index a09dad7dba3..fbb98c3f984 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -29,7 +29,6 @@ var/g_synth //Same as above var/b_synth //Same as above - var/size_multiplier = 1 //multiplier for the mob's icon size var/damage_multiplier = 1 //multiplies melee combat damage var/icon_update = 1 //whether icon updating shall take place @@ -103,3 +102,8 @@ var/step_count = 0 // Track how many footsteps have been taken to know when to play footstep sounds can_be_antagged = TRUE + +// Used by mobs in virtual reality to point back to the "real" mob the client belongs to. + var/mob/living/carbon/human/vr_holder = null + // Used by "real" mobs after they leave a VR session + var/mob/living/carbon/human/vr_link = null \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/human_powers.dm b/code/modules/mob/living/carbon/human/human_powers.dm index 93ed52f24cf..a187436af89 100644 --- a/code/modules/mob/living/carbon/human/human_powers.dm +++ b/code/modules/mob/living/carbon/human/human_powers.dm @@ -165,6 +165,12 @@ output += "Current Battery Charge: [nutrition]\n" + var/toxDam = getToxLoss() + if(toxDam) + output += "System Instability: [toxDam > 25 ? "Severe" : "Moderate"]\n" + else + output += "System Instability: OK\n" + for(var/obj/item/organ/external/EO in organs) if(EO.brute_dam || EO.burn_dam) output += "[EO.name] - [EO.burn_dam + EO.brute_dam > ROBOLIMB_REPAIR_CAP ? "Heavy Damage" : "Light Damage"]\n" diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 61f7f820360..684978e07de 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -226,7 +226,7 @@ if(gene.is_active(src)) gene.OnMobLife(src) - radiation = Clamp(radiation,0,100) + radiation = Clamp(radiation,0,250) if(!radiation) if(species.appearance_flags & RADIATION_GLOWS) @@ -285,8 +285,12 @@ adjustCloneLoss(5 * RADIATION_SPEED_COEFFICIENT) emote("gasp") + if (radiation > 150) + damage = 6 + radiation -= 4 * RADIATION_SPEED_COEFFICIENT + if(damage) - damage *= isSynthetic() ? 0.5 : species.radiation_mod + damage *= species.radiation_mod adjustToxLoss(damage * RADIATION_SPEED_COEFFICIENT) updatehealth() if(!isSynthetic() && organs.len) @@ -1375,9 +1379,15 @@ // Puke if toxloss is too high if(!stat) + if (getToxLoss() >= 30 && isSynthetic()) + if(!confused) + if(prob(5)) + to_chat(src, "You lose directional control!") + Confuse(10) if (getToxLoss() >= 45) spawn vomit() + //0.1% chance of playing a scary sound to someone who's in complete darkness if(isturf(loc) && rand(1,1000) == 1) var/turf/T = loc @@ -1572,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" @@ -1587,7 +1599,9 @@ var/image/holder = hud_list[STATUS_HUD] var/image/holder2 = hud_list[STATUS_HUD_OOC] - if(stat == DEAD) + if (isSynthetic()) + holder.icon_state = "hudrobo" + else if(stat == DEAD) holder.icon_state = "huddead" holder2.icon_state = "huddead" else if(foundVirus) diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm index bb5d989e45a..61bded2e159 100644 --- a/code/modules/mob/living/carbon/human/species/species.dm +++ b/code/modules/mob/living/carbon/human/species/species.dm @@ -30,6 +30,8 @@ var/tail_animation // If set, the icon to obtain tail animation states from. var/tail_hair + var/icon_scale = 1 // Makes the icon larger/smaller. + var/race_key = 0 // Used for mob icon cache string. var/icon/icon_template // Used for mob icon generation for non-32x32 species. var/mob_size = MOB_MEDIUM @@ -275,11 +277,14 @@ var/t_him = "them" if(ishuman(target)) var/mob/living/carbon/human/T = target - switch(T.identifying_gender) - if(MALE) - t_him = "him" - if(FEMALE) - t_him = "her" + if(!T.species.ambiguous_genders || (T.species.ambiguous_genders && H.species == T.species)) + switch(T.identifying_gender) + if(MALE) + t_him = "him" + if(FEMALE) + t_him = "her" + else + t_him = "them" else switch(target.gender) if(MALE) diff --git a/code/modules/mob/living/carbon/human/species/species_shapeshift.dm b/code/modules/mob/living/carbon/human/species/species_shapeshift.dm index 1fb7b6c3009..f1f36322a23 100644 --- a/code/modules/mob/living/carbon/human/species/species_shapeshift.dm +++ b/code/modules/mob/living/carbon/human/species/species_shapeshift.dm @@ -148,9 +148,16 @@ var/list/wrapped_species_by_ref = list() last_special = world.time + 50 - var/new_species = input("Please select a species to emulate.", "Shapeshifter Body") as null|anything in species.get_valid_shapeshifter_forms(src) + var/new_species = null + new_species = input("Please select a species to emulate.", "Shapeshifter Body") as null|anything in species.get_valid_shapeshifter_forms(src) + if(!new_species || !all_species[new_species] || wrapped_species_by_ref["\ref[src]"] == new_species) return + shapeshifter_change_shape(new_species) + +/mob/living/carbon/human/proc/shapeshifter_change_shape(var/new_species = null) + if(!new_species) + return wrapped_species_by_ref["\ref[src]"] = new_species visible_message("\The [src] shifts and contorts, taking the form of \a [new_species]!") @@ -190,3 +197,30 @@ var/list/wrapped_species_by_ref = list() E.sync_colour_to_human(src) regenerate_icons() + +/mob/living/carbon/human/proc/shapeshifter_select_hair_colors() + + set name = "Select Hair Colors" + set category = "Abilities" + + if(stat || world.time < last_special) + return + + last_special = world.time + 50 + + var/new_hair = input("Please select a new hair color.", "Hair Colour") as color + if(!new_hair) + return + shapeshifter_set_hair_color(new_hair) + var/new_fhair = input("Please select a new facial hair color.", "Facial Hair Color") as color + if(!new_fhair) + return + shapeshifter_set_facial_color(new_fhair) + +/mob/living/carbon/human/proc/shapeshifter_set_hair_color(var/new_hair) + + change_hair_color(hex2num(copytext(new_hair, 2, 4)), hex2num(copytext(new_hair, 4, 6)), hex2num(copytext(new_hair, 6, 8))) + +/mob/living/carbon/human/proc/shapeshifter_set_facial_color(var/new_fhair) + + change_facial_hair_color(hex2num(copytext(new_fhair, 2, 4)), hex2num(copytext(new_fhair, 4, 6)), hex2num(copytext(new_fhair, 6, 8))) \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/species/station/prometheans.dm b/code/modules/mob/living/carbon/human/species/station/prometheans.dm index 5ab786f8f6f..7d1ed3bb0e8 100644 --- a/code/modules/mob/living/carbon/human/species/station/prometheans.dm +++ b/code/modules/mob/living/carbon/human/species/station/prometheans.dm @@ -81,12 +81,12 @@ var/datum/species/shapeshifter/promethean/prometheans /mob/living/carbon/human/proc/shapeshifter_select_shape, /mob/living/carbon/human/proc/shapeshifter_select_colour, /mob/living/carbon/human/proc/shapeshifter_select_hair, + /mob/living/carbon/human/proc/shapeshifter_select_hair_colors, /mob/living/carbon/human/proc/shapeshifter_select_gender, /mob/living/carbon/human/proc/regenerate ) - valid_transform_species = list("Human", "Unathi", "Tajara", "Skrell", "Diona", "Teshari", "Monkey") - monochromatic = 1 + valid_transform_species = list("Human", "Vatborn", "Unathi", "Tajara", "Skrell", "Diona", "Teshari", "Monkey") var/heal_rate = 0.5 // Temp. Regen per tick. diff --git a/code/modules/mob/living/carbon/human/species/station/station.dm b/code/modules/mob/living/carbon/human/species/station/station.dm index f07ff9b1197..372451808e2 100644 --- a/code/modules/mob/living/carbon/human/species/station/station.dm +++ b/code/modules/mob/living/carbon/human/species/station/station.dm @@ -39,6 +39,8 @@ burn_mod = 0.85 metabolic_rate = 0.85 item_slowdown_mod = 0.5 + mob_size = MOB_LARGE + blood_volume = 840 num_alternate_languages = 3 secondary_langs = list(LANGUAGE_UNATHI) name_language = LANGUAGE_UNATHI diff --git a/code/modules/mob/living/carbon/human/species/virtual_reality/avatar.dm b/code/modules/mob/living/carbon/human/species/virtual_reality/avatar.dm new file mode 100644 index 00000000000..8fbf47022d4 --- /dev/null +++ b/code/modules/mob/living/carbon/human/species/virtual_reality/avatar.dm @@ -0,0 +1,32 @@ +// ### Wooo, inheritance. Basically copying everything I don't need to edit from prometheans, because they mostly work already. +// ### Any and all of this is open to change for balance or whatever. +// ### +// ### +// Species definition follows. +/datum/species/shapeshifter/promethean/avatar + + name = "Virtual Reality Avatar" + name_plural = "Virtual Reality Avatars" + blurb = "A 3-dimensional representation of some sort of animate object used to display the presence and actions of some-one or -thing using a virtual reality program." + show_ssd = "eerily still" + death_message = "flickers briefly, their gear falling in a heap on the floor around their motionless body." + knockout_message = "has been knocked unconscious!" + + spawn_flags = SPECIES_IS_RESTRICTED + + speech_bubble_appearance = "cyber" + + male_cough_sounds = list('sound/effects/mob_effects/m_cougha.ogg','sound/effects/mob_effects/m_coughb.ogg', 'sound/effects/mob_effects/m_coughc.ogg') + female_cough_sounds = list('sound/effects/mob_effects/f_cougha.ogg','sound/effects/mob_effects/f_coughb.ogg') + male_sneeze_sound = 'sound/effects/mob_effects/sneeze.ogg' + female_sneeze_sound = 'sound/effects/mob_effects/f_sneeze.ogg' + + unarmed_types = list(/datum/unarmed_attack/stomp, /datum/unarmed_attack/kick, /datum/unarmed_attack/punch, /datum/unarmed_attack/bite) + has_organ = list(O_BRAIN = /obj/item/organ/internal/brain/slime, O_EYES = /obj/item/organ/internal/eyes) // Slime core. + heal_rate = 0 // Avatars don't naturally heal like prometheans, at least not for now + +/datum/species/shapeshifter/promethean/avatar/handle_death(var/mob/living/carbon/human/H) + return + +/datum/species/shapeshifter/promethean/avatar/handle_environment_special(var/mob/living/carbon/human/H) + return \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 0909ed25755..ebaa6866e01 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -159,16 +159,29 @@ Please contact me on #coderbus IRC. ~Carn x for(var/inner_entry in entry) overlays += inner_entry + update_transform() + +/mob/living/carbon/human/update_transform() + // First, get the correct size. + var/desired_scale = icon_scale + + desired_scale *= species.icon_scale + + for(var/datum/modifier/M in modifiers) + if(!isnull(M.icon_scale_percent)) + desired_scale *= M.icon_scale_percent + + // Regular stuff again. if(lying && !species.prone_icon) //Only rotate them if we're not drawing a specific icon for being prone. var/matrix/M = matrix() M.Turn(90) - M.Scale(size_multiplier) + M.Scale(desired_scale) M.Translate(1,-6) src.transform = M else var/matrix/M = matrix() - M.Scale(size_multiplier) - M.Translate(0, 16*(size_multiplier-1)) + M.Scale(desired_scale) + M.Translate(0, 16*(desired_scale-1)) src.transform = M var/global/list/damage_icon_parts = list() @@ -293,6 +306,8 @@ var/global/list/damage_icon_parts = list() base_icon = chest.get_icon() for(var/obj/item/organ/external/part in organs) + if(isnull(part) || part.is_stump()) + continue var/icon/temp = part.get_icon(skeleton) //That part makes left and right legs drawn topmost and lowermost when human looks WEST or EAST //And no change in rendering for other parts (they icon_position is 0, so goes to 'else' part) @@ -381,11 +396,13 @@ var/global/list/damage_icon_parts = list() face_standing.Blend(facial_s, ICON_OVERLAY) if(h_style && !(head && (head.flags_inv & BLOCKHEADHAIR))) - var/datum/sprite_accessory/hair_style = hair_styles_list[h_style] + var/datum/sprite_accessory/hair/hair_style = hair_styles_list[h_style] if(hair_style && (src.species.get_bodytype(src) in hair_style.species_allowed)) var/icon/hair_s = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s") + var/icon/hair_s_add = new/icon("icon" = hair_style.icon_add, "icon_state" = "[hair_style.icon_state]_s") if(hair_style.do_colouration) - hair_s.Blend(rgb(r_hair, g_hair, b_hair), ICON_ADD) + hair_s.Blend(rgb(r_hair, g_hair, b_hair), ICON_MULTIPLY) + hair_s.Blend(hair_s_add, ICON_ADD) face_standing.Blend(hair_s, ICON_OVERLAY) @@ -503,7 +520,16 @@ var/global/list/damage_icon_parts = list() //need to append _s to the icon state for legacy compatibility var/image/standing = image(icon = under_icon, icon_state = "[under_state]_s") - standing.color = w_uniform.color + + if(w_uniform.addblends) + var/icon/base = new/icon("icon" = standing.icon, "icon_state" = standing.icon_state) + var/addblend_icon = new/icon("icon" = standing.icon, "icon_state" = w_uniform.addblends) + if(w_uniform.color) + base.Blend(w_uniform.color, ICON_MULTIPLY) + base.Blend(addblend_icon, ICON_ADD) + standing = image(base) + else + standing.color = w_uniform.color //apply blood overlay if(w_uniform.blood_DNA) @@ -567,7 +593,15 @@ var/global/list/damage_icon_parts = list() bloodsies.color = gloves.blood_color standing.overlays += bloodsies gloves.screen_loc = ui_gloves - standing.color = gloves.color + if(gloves.addblends) + var/icon/base = new/icon("icon" = standing.icon, "icon_state" = standing.icon_state) + var/addblend_icon = new/icon("icon" = standing.icon, "icon_state" = gloves.addblends) + if(gloves.color) + base.Blend(gloves.color, ICON_MULTIPLY) + base.Blend(addblend_icon, ICON_ADD) + standing = image(base) + else + standing.color = gloves.color overlays_standing[GLOVES_LAYER] = standing else if(blood_DNA) @@ -588,7 +622,15 @@ var/global/list/damage_icon_parts = list() standing = image("icon" = glasses.sprite_sheets[species.get_bodytype(src)], "icon_state" = "[glasses.icon_state]") else standing = image("icon" = 'icons/mob/eyes.dmi', "icon_state" = "[glasses.icon_state]") - standing.color = glasses.color + if(glasses.addblends) + var/icon/base = new/icon("icon" = standing.icon, "icon_state" = standing.icon_state) + var/addblend_icon = new/icon("icon" = standing.icon, "icon_state" = glasses.addblends) + if(glasses.color) + base.Blend(glasses.color, ICON_MULTIPLY) + base.Blend(addblend_icon, ICON_ADD) + standing = image(base) + else + standing.color = glasses.color overlays_standing[GLASSES_LAYER] = standing else @@ -616,7 +658,15 @@ var/global/list/damage_icon_parts = list() standing = image("icon" = l_ear.sprite_sheets[species.get_bodytype(src)], "icon_state" = "[t_type]") else standing = image("icon" = 'icons/mob/ears.dmi', "icon_state" = "[t_type]") - standing.color = l_ear.color + if(l_ear.addblends) + var/icon/base = new/icon("icon" = standing.icon, "icon_state" = standing.icon_state) + var/addblend_icon = new/icon("icon" = standing.icon, "icon_state" = l_ear.addblends) + if(l_ear.color) + base.Blend(l_ear.color, ICON_MULTIPLY) + base.Blend(addblend_icon, ICON_ADD) + standing = image(base) + else + standing.color = l_ear.color both.overlays += standing if(r_ear) @@ -630,7 +680,15 @@ var/global/list/damage_icon_parts = list() standing = image("icon" = r_ear.sprite_sheets[species.get_bodytype(src)], "icon_state" = "[t_type]") else standing = image("icon" = 'icons/mob/ears.dmi', "icon_state" = "[t_type]") - standing.color = r_ear.color + if(r_ear.addblends) + var/icon/base = new/icon("icon" = standing.icon, "icon_state" = standing.icon_state) + var/addblend_icon = new/icon("icon" = standing.icon, "icon_state" = r_ear.addblends) + if(r_ear.color) + base.Blend(r_ear.color, ICON_MULTIPLY) + base.Blend(addblend_icon, ICON_ADD) + standing = image(base) + else + standing.color = r_ear.color both.overlays += standing overlays_standing[EARS_LAYER] = both @@ -664,8 +722,18 @@ var/global/list/damage_icon_parts = list() var/image/bloodsies = image("icon" = species.get_blood_mask(src), "icon_state" = "shoeblood") bloodsies.color = shoes.blood_color standing.overlays += bloodsies - standing.color = shoes.color + + if(shoes.addblends) + var/icon/base = new/icon("icon" = standing.icon, "icon_state" = standing.icon_state) + var/addblend_icon = new/icon("icon" = standing.icon, "icon_state" = shoes.addblends) + if(shoes.color) + base.Blend(shoes.color, ICON_MULTIPLY) + base.Blend(addblend_icon, ICON_ADD) + standing = image(base) + else + standing.color = shoes.color overlays_standing[shoe_layer] = standing + else if(feet_blood_DNA) var/image/bloodsies = image("icon" = species.get_blood_mask(src), "icon_state" = "shoeblood") @@ -731,7 +799,15 @@ var/global/list/damage_icon_parts = list() if(hat.on && light_overlay_cache[cache_key]) standing.overlays |= light_overlay_cache[cache_key] - standing.color = head.color + if(head.addblends) + var/icon/base = new/icon("icon" = standing.icon, "icon_state" = standing.icon_state) + var/addblend_icon = new/icon("icon" = standing.icon, "icon_state" = head.addblends) + if(head.color) + base.Blend(head.color, ICON_MULTIPLY) + base.Blend(addblend_icon, ICON_ADD) + standing = image(base) + else + standing.color = head.color overlays_standing[HEAD_LAYER] = standing else @@ -766,7 +842,15 @@ var/global/list/damage_icon_parts = list() if(!i_state) i_state = i.icon_state standing.overlays += image("icon" = 'icons/mob/belt.dmi', "icon_state" = "[i_state]") - standing.color = belt.color + if(belt.addblends) + var/icon/base = new/icon("icon" = standing.icon, "icon_state" = standing.icon_state) + var/addblend_icon = new/icon("icon" = standing.icon, "icon_state" = belt.addblends) + if(belt.color) + base.Blend(belt.color, ICON_MULTIPLY) + base.Blend(addblend_icon, ICON_ADD) + standing = image(base) + else + standing.color = belt.color overlays_standing[belt_layer] = standing else @@ -791,7 +875,16 @@ var/global/list/damage_icon_parts = list() t_icon = wear_suit.item_icons[slot_wear_suit_str] standing = image("icon" = t_icon, "icon_state" = "[wear_suit.icon_state]") - standing.color = wear_suit.color + + if(wear_suit.addblends) + var/icon/base = new/icon("icon" = standing.icon, "icon_state" = standing.icon_state) + var/addblend_icon = new/icon("icon" = standing.icon, "icon_state" = wear_suit.addblends) + if(wear_suit.color) + base.Blend(wear_suit.color, ICON_MULTIPLY) + base.Blend(addblend_icon, ICON_ADD) + standing = image(base) + else + standing.color = wear_suit.color if( istype(wear_suit, /obj/item/clothing/suit/straight_jacket) ) drop_from_inventory(handcuffed) @@ -841,7 +934,15 @@ var/global/list/damage_icon_parts = list() standing = image("icon" = wear_mask.sprite_sheets[species.get_bodytype(src)], "icon_state" = "[wear_mask.icon_state]") else standing = image("icon" = 'icons/mob/mask.dmi', "icon_state" = "[wear_mask.icon_state]") - standing.color = wear_mask.color + if(wear_mask.addblends) + var/icon/base = new/icon("icon" = standing.icon, "icon_state" = standing.icon_state) + var/addblend_icon = new/icon("icon" = standing.icon, "icon_state" = wear_mask.addblends) + if(wear_mask.color) + base.Blend(wear_mask.color, ICON_MULTIPLY) + base.Blend(addblend_icon, ICON_ADD) + standing = image(base) + else + standing.color = wear_mask.color if( !istype(wear_mask, /obj/item/clothing/mask/smokable/cigarette) && wear_mask.blood_DNA ) var/image/bloodsies = image("icon" = species.get_blood_mask(src), "icon_state" = "maskblood") @@ -883,7 +984,15 @@ var/global/list/damage_icon_parts = list() //apply color var/image/standing = image(icon = overlay_icon, icon_state = overlay_state) - standing.color = back.color + if(back.addblends) + var/icon/base = new/icon("icon" = standing.icon, "icon_state" = standing.icon_state) + var/addblend_icon = new/icon("icon" = standing.icon, "icon_state" = back.addblends) + if(back.color) + base.Blend(back.color, ICON_MULTIPLY) + base.Blend(addblend_icon, ICON_ADD) + standing = image(base) + else + standing.color = back.color //create the image overlays_standing[BACK_LAYER] = standing diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm index 22289c6b438..07997851ef3 100644 --- a/code/modules/mob/living/damage_procs.dm +++ b/code/modules/mob/living/damage_procs.dm @@ -34,6 +34,8 @@ adjustCloneLoss(damage * blocked) if(HALLOSS) adjustHalLoss(damage * blocked) + if(ELECTROCUTE) + electrocute_act(damage, used_weapon, 1.0, def_zone) flash_weak_pain() updatehealth() return 1 diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index b93ed0cb5fe..f0ee069b88f 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -58,12 +58,12 @@ default behaviour is: for(var/mob/living/M in range(tmob, 1)) if(tmob.pinned.len || ((M.pulling == tmob && ( tmob.restrained() && !( M.restrained() ) && M.stat == 0)) || locate(/obj/item/weapon/grab, tmob.grabbed_by.len)) ) if ( !(world.time % 5) ) - src << "[tmob] is restrained, you cannot push past" + to_chat(src, "[tmob] is restrained, you cannot push past") now_pushing = 0 return if( tmob.pulling == M && ( M.restrained() && !( tmob.restrained() ) && tmob.stat == 0) ) if ( !(world.time % 5) ) - src << "[tmob] is restraining [M], you cannot push past" + to_chat(src, "[tmob] is restraining [M], you cannot push past") now_pushing = 0 return @@ -103,7 +103,7 @@ default behaviour is: return if(istype(tmob, /mob/living/carbon/human) && (FAT in tmob.mutations)) if(prob(40) && !(FAT in src.mutations)) - src << "You fail to push [tmob]'s fat ass out of the way." + to_chat(src, "You fail to push [tmob]'s fat ass out of the way.") now_pushing = 0 return if(tmob.r_hand && istype(tmob.r_hand, /obj/item/weapon/shield/riot)) @@ -129,9 +129,13 @@ default behaviour is: playsound(loc, "punch", 25, 1, -1) visible_message("[src] [pick("ran", "slammed")] into \the [AM]!") src.apply_damage(5, BRUTE) - src << ("You just [pick("ran", "slammed")] into \the [AM]!") + to_chat(src, "You just [pick("ran", "slammed")] into \the [AM]!") return if (!now_pushing) + if(isobj(AM)) + var/obj/I = AM + if(!can_pull_size || can_pull_size < I.w_class) + return now_pushing = 1 var/t = get_dir(src, AM) @@ -153,7 +157,7 @@ default behaviour is: if ((src.health < 0 && src.health > (5-src.getMaxHealth()))) // Health below Zero but above 5-away-from-death, as before, but variable src.adjustOxyLoss(src.health + src.getMaxHealth() * 2) // Deal 2x health in OxyLoss damage, as before but variable. src.health = src.getMaxHealth() - src.getOxyLoss() - src.getToxLoss() - src.getFireLoss() - src.getBruteLoss() - src << "You have given up life and succumbed to death." + to_chat(src, "You have given up life and succumbed to death.") /mob/living/proc/updatehealth() @@ -646,11 +650,11 @@ default behaviour is: if(config.allow_Metadata) if(client) - usr << "[src]'s Metainfo:
[client.prefs.metadata]" + to_chat(usr, "[src]'s Metainfo:
[client.prefs.metadata]") else - usr << "[src] does not have any stored infomation!" + to_chat(usr, "[src] does not have any stored infomation!") else - usr << "OOC Metadata is not supported by this server!" + to_chat(usr, "OOC Metadata is not supported by this server!") return @@ -797,8 +801,8 @@ default behaviour is: if(istype(M)) M.drop_from_inventory(H) - M << "\The [H] wriggles out of your grip!" - src << "You wriggle out of \the [M]'s grip!" + to_chat(M, "\The [H] wriggles out of your grip!") + to_chat(src, "You wriggle out of \the [M]'s grip!") // Update whether or not this mob needs to pass emotes to contents. for(var/atom/A in M.contents) @@ -810,10 +814,10 @@ default behaviour is: var/obj/item/clothing/accessory/holster/holster = H.loc if(holster.holstered == H) holster.clear_holster() - src << "You extricate yourself from \the [holster]." + to_chat(src, "You extricate yourself from \the [holster].") H.forceMove(get_turf(H)) else if(istype(H.loc,/obj/item)) - src << "You struggle free of \the [H.loc]." + to_chat(src, "You struggle free of \the [H.loc].") H.forceMove(get_turf(H)) /mob/living/proc/escape_buckle() @@ -833,7 +837,7 @@ default behaviour is: set category = "IC" resting = !resting - src << "You are now [resting ? "resting" : "getting up"]" + to_chat(src, "You are now [resting ? "resting" : "getting up"]") /mob/living/proc/cannot_use_vents() if(mob_size > MOB_SMALL) @@ -869,7 +873,7 @@ default behaviour is: inertia_dir = 1 else if(y >= world.maxy -TRANSITIONEDGE) inertia_dir = 2 - src << "Something you are carrying is preventing you from leaving." + to_chat(src, "Something you are carrying is preventing you from leaving.") return ..() @@ -887,54 +891,52 @@ default behaviour is: ear_deaf = deaf /mob/living/proc/vomit(var/skip_wait, var/blood_vomit) - - if(isSynthetic()) - src << "A sudden, dizzying wave of internal feedback rushes over you!" - src.Weaken(5) - return - if(!check_has_mouth()) return if(!lastpuke) lastpuke = 1 - if (nutrition <= 100) - src << "You gag as you want to throw up, but there's nothing in your stomach!" - src.Weaken(10) + if(isSynthetic()) + to_chat(src, "A sudden, dizzying wave of internal feedback rushes over you!") + src.Weaken(5) else - src << "You feel nauseous..." - - if(!skip_wait) - sleep(150) //15 seconds until second warning - src << "You feel like you are about to throw up!" - sleep(100) //and you have 10 more for mad dash to the bucket - - //Damaged livers cause you to vomit blood. - if(!blood_vomit) - if(ishuman(src)) - var/mob/living/carbon/human/H = src - if(!H.isSynthetic()) - var/obj/item/organ/internal/liver/L = H.internal_organs_by_name["liver"] - if(L.is_broken()) - blood_vomit = 1 - - Stun(5) - src.visible_message("[src] throws up!","You throw up!") - playsound(loc, 'sound/effects/splat.ogg', 50, 1) - - var/turf/simulated/T = get_turf(src) //TODO: Make add_blood_floor remove blood from human mobs - if(istype(T)) - if(blood_vomit) - T.add_blood_floor(src) - else - T.add_vomit_floor(src, 1) - - if(blood_vomit) - if(getBruteLoss() < 50) - adjustBruteLoss(3) + if (nutrition <= 100) + to_chat(src, "You gag as you want to throw up, but there's nothing in your stomach!") + src.Weaken(10) else - nutrition -= 40 - adjustToxLoss(-3) + to_chat(src, "You feel nauseous...") + + if(!skip_wait) + sleep(150) //15 seconds until second warning + to_chat(src, "You feel like you are about to throw up!") + sleep(100) //and you have 10 more for mad dash to the bucket + + //Damaged livers cause you to vomit blood. + if(!blood_vomit) + if(ishuman(src)) + var/mob/living/carbon/human/H = src + if(!H.isSynthetic()) + var/obj/item/organ/internal/liver/L = H.internal_organs_by_name["liver"] + if(L.is_broken()) + blood_vomit = 1 + + Stun(5) + src.visible_message("[src] throws up!","You throw up!") + playsound(loc, 'sound/effects/splat.ogg', 50, 1) + + var/turf/simulated/T = get_turf(src) //TODO: Make add_blood_floor remove blood from human mobs + if(istype(T)) + if(blood_vomit) + T.add_blood_floor(src) + else + T.add_vomit_floor(src, 1) + + if(blood_vomit) + if(getBruteLoss() < 50) + adjustBruteLoss(3) + else + nutrition -= 40 + adjustToxLoss(-3) sleep(350) lastpuke = 0 @@ -1010,3 +1012,17 @@ default behaviour is: // Called by job_controller. /mob/living/proc/equip_post_job() return + + +/mob/living/update_transform() + // First, get the correct size. + var/desired_scale = icon_scale + for(var/datum/modifier/M in modifiers) + if(!isnull(M.icon_scale_percent)) + desired_scale *= M.icon_scale_percent + + // Now for the regular stuff. + var/matrix/M = matrix() + M.Scale(desired_scale) + M.Translate(0, 16*(desired_scale-1)) + src.transform = M \ No newline at end of file diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index ad3a41fbc86..b48a1609d9e 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -17,10 +17,6 @@ var/list/ai_verbs_default = list( /mob/living/silicon/ai/proc/show_laws_verb, /mob/living/silicon/ai/proc/toggle_acceleration, /mob/living/silicon/ai/proc/toggle_hologram_movement, - /mob/living/silicon/ai/proc/toggle_hidden_verbs, -) - -var/list/ai_verbs_hidden = list( // For why this exists, refer to https://xkcd.com/1172/, /mob/living/silicon/ai/proc/ai_announcement, /mob/living/silicon/ai/proc/ai_call_shuttle, /mob/living/silicon/ai/proc/ai_camera_track, @@ -160,6 +156,7 @@ var/list/ai_verbs_hidden = list( // For why this exists, refer to https://xkcd.c add_language(LANGUAGE_EAL, 1) add_language(LANGUAGE_SCHECHI, 1) add_language(LANGUAGE_SIGN, 1) + add_language(LANGUAGE_ROOTLOCAL, 1) if(!safety)//Only used by AIize() to successfully spawn an AI. if (!B)//If there is no player/brain inside. @@ -794,16 +791,5 @@ var/list/ai_verbs_hidden = list( // For why this exists, refer to https://xkcd.c if(rig) rig.force_rest(src) -/mob/living/silicon/ai/proc/toggle_hidden_verbs() - set name = "Toggle Hidden Verbs" - set category = "AI Settings" - - if(/mob/living/silicon/ai/proc/ai_announcement in verbs) - src << "Extra verbs toggled off." - verbs -= ai_verbs_hidden - else - src << "Extra verbs toggled on." - verbs |= ai_verbs_hidden - #undef AI_CHECK_WIRELESS #undef AI_CHECK_RADIO diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm index 29e3e86caf2..1e0d9888358 100644 --- a/code/modules/mob/living/silicon/pai/pai.dm +++ b/code/modules/mob/living/silicon/pai/pai.dm @@ -430,7 +430,7 @@ user << "You add the access from the [W] to [src]." return if("Remove Access") - idcard.access = null + idcard.access = list() user << "You remove the access from [src]." return if("Cancel") @@ -442,7 +442,7 @@ /mob/living/silicon/pai/verb/allowmodification() set name = "Change Access Modifcation Permission" set category = "pAI Commands" - desc = "Allows people to modify your access or block people from modifying your access." + set desc = "Allows people to modify your access or block people from modifying your access." if(idaccessible == 0) idaccessible = 1 diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index f516486f026..6b07aa8b0c8 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 @@ -481,7 +486,7 @@ return var/obj/item/weapon/weldingtool/WT = W if (WT.remove_fuel(0)) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(WT)) adjustBruteLoss(-30) updatehealth() add_fingerprint(user) @@ -497,7 +502,7 @@ return var/obj/item/stack/cable_coil/coil = W if (coil.use(1)) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(W)) adjustFireLoss(-30) updatehealth() for(var/mob/O in viewers(user, null)) @@ -637,7 +642,8 @@ else if( !(istype(W, /obj/item/device/robotanalyzer) || istype(W, /obj/item/device/healthanalyzer)) ) - spark_system.start() + if(W.force > 0) + spark_system.start() return ..() /mob/living/silicon/robot/attack_hand(mob/user) diff --git a/code/modules/mob/living/simple_animal/animals/giant_spider.dm b/code/modules/mob/living/simple_animal/animals/giant_spider.dm index 1ff56059469..cc655908e9b 100644 --- a/code/modules/mob/living/simple_animal/animals/giant_spider.dm +++ b/code/modules/mob/living/simple_animal/animals/giant_spider.dm @@ -55,6 +55,10 @@ /mob/living/simple_animal/hostile/giant_spider/proc/remove_eyes() overlays -= eye_layer +/* +Nurse Family +*/ + //nursemaids - these create webs and eggs /mob/living/simple_animal/hostile/giant_spider/nurse desc = "Furry and beige, it makes you shudder to look at it. This one has brilliant green eyes." @@ -95,7 +99,105 @@ old_x = -16 old_y = -16 +/mob/living/simple_animal/hostile/giant_spider/webslinger + desc = "Furry and green, it makes you shudder to look at it. This one has brilliant green eyes, and a cloak of web." + icon_state = "webslinger" + icon_living = "webslinger" + icon_dead = "webslinger_dead" + + maxHealth = 90 + health = 90 + + projectilesound = 'sound/weapons/thudswoosh.ogg' + projectiletype = /obj/item/projectile/bola + ranged = 1 + firing_lines = 1 + cooperative = 1 + shoot_range = 5 + + melee_damage_lower = 5 + melee_damage_upper = 10 + poison_per_bite = 2 + poison_type = "psilocybin" + + spattack_prob = 15 + spattack_min_range = 0 + spattack_max_range = 5 + +/mob/living/simple_animal/hostile/giant_spider/webslinger/AttackTarget() //One day. + var/mob/living/carbon/human/victim = null //Webslinger needs to know if its target is human later. + if(ishuman(target_mob)) + victim = target_mob + if(!victim.legcuffed) + projectiletype = /obj/item/projectile/bola + shoot_range = 7 + else + projectiletype = /obj/item/projectile/webball + shoot_range = 5 + else + projectiletype = /obj/item/projectile/webball + shoot_range = 5 + return ..() + +/mob/living/simple_animal/hostile/giant_spider/carrier + desc = "Furry, beige, and red, it makes you shudder to look at it. This one has luminous green eyes." + icon_state = "carrier" + icon_living = "carrier" + icon_dead = "carrier_dead" + + maxHealth = 100 + health = 100 + + melee_damage_lower = 5 + melee_damage_upper = 20 + + poison_per_bite = 3 + poison_type = "chloralhydrate" + + var/spiderling_count = 0 + var/spiderling_type = /obj/effect/spider/spiderling + var/swarmling_type = /mob/living/simple_animal/hostile/giant_spider/hunter + var/swarmling_faction = "spiders" + +/mob/living/simple_animal/hostile/giant_spider/carrier/New() + spiderling_count = rand(5,10) + adjust_scale(1.2) + ..() + +/mob/living/simple_animal/hostile/giant_spider/carrier/death() + visible_message("\The [src]'s abdomen splits as it rolls over, spiderlings crawling from the wound.") + spawn(1) + for(var/I = 1 to spiderling_count) + if(prob(10) && src) + var/mob/living/simple_animal/hostile/giant_spider/swarmling = new swarmling_type(src.loc) + var/swarm_health = Floor(swarmling.maxHealth * 0.4) + var/swarm_dam_lower = Floor(melee_damage_lower * 0.4) + var/swarm_dam_upper = Floor(melee_damage_upper * 0.4) + swarmling.name = "spiderling" + swarmling.maxHealth = swarm_health + swarmling.health = swarm_health + swarmling.melee_damage_lower = swarm_dam_lower + swarmling.melee_damage_upper = swarm_dam_upper + swarmling.faction = swarmling_faction + swarmling.adjust_scale(0.75) + else if(src) + var/obj/effect/spider/spiderling/child = new spiderling_type(src.loc) + child.skitter() + else + break + return ..() + +/mob/living/simple_animal/hostile/giant_spider/carrier/recursive + desc = "Furry, beige, and red, it makes you shudder to look at it. This one has luminous green eyes. You have a distinctly bad feeling about this." + + swarmling_type = /mob/living/simple_animal/hostile/giant_spider/carrier/recursive + +/* +Hunter Family +*/ + //hunters have the most poison and move the fastest, so they can find prey + /mob/living/simple_animal/hostile/giant_spider/hunter desc = "Furry and black, it makes you shudder to look at it. This one has sparkling purple eyes." icon_state = "hunter" @@ -111,6 +213,150 @@ poison_per_bite = 5 +/mob/living/simple_animal/hostile/giant_spider/lurker + desc = "Translucent and white, it makes you shudder to look at it. This one has incandescent red eyes." + icon_state = "lurker" + icon_living = "lurker" + icon_dead = "lurker_dead" + alpha = 45 + + maxHealth = 100 + health = 100 + move_to_delay = 4 + + melee_damage_lower = 5 + melee_damage_upper = 20 + + + poison_chance = 20 + poison_type = "cryptobiolin" + poison_per_bite = 2 + +/mob/living/simple_animal/hostile/giant_spider/lurker/death() + alpha = 255 + return ..() + +/mob/living/simple_animal/hostile/giant_spider/tunneler + desc = "Sandy and brown, it makes you shudder to look at it. This one has glittering yellow eyes." + icon_state = "tunneler" + icon_living = "tunneler" + icon_dead = "tunneler_dead" + + maxHealth = 120 + health = 120 + move_to_delay = 4 + + melee_damage_lower = 10 + melee_damage_upper = 20 + + poison_chance = 15 + poison_per_bite = 3 + poison_type = "serotrotium_v" + +/mob/living/simple_animal/hostile/giant_spider/tunneler/death() + spawn(1) + for(var/I = 1 to rand(3,6)) + if(src) + new/obj/item/weapon/ore/glass(src.loc) + else + break + return ..() + +/* +Guard Family +*/ + +/mob/living/simple_animal/hostile/giant_spider/pepper + desc = "Red and brown, it makes you shudder to look at it. This one has glinting red eyes." + icon_state = "pepper" + icon_living = "pepper" + icon_dead = "pepper_dead" + + maxHealth = 210 + health = 210 + + melee_damage_lower = 5 + melee_damage_upper = 10 + + poison_chance = 20 + poison_per_bite = 5 + poison_type = "condensedcapsaicin_v" + +/mob/living/simple_animal/hostile/giant_spider/pepper/New() + adjust_scale(1.1) + ..() + +/mob/living/simple_animal/hostile/giant_spider/thermic + desc = "Mirage-cloaked and orange, it makes you shudder to look at it. This one has simmering orange eyes." + icon_state = "pit" + icon_living = "pit" + icon_dead = "pit_dead" + + maxHealth = 175 + health = 175 + + melee_damage_lower = 5 + melee_damage_upper = 15 + + poison_chance = 30 + poison_per_bite = 1 + poison_type = "thermite_v" + +/mob/living/simple_animal/hostile/giant_spider/electric + desc = "Spined and yellow, it makes you shudder to look at it. This one has flickering gold eyes." + icon_state = "spark" + icon_living = "spark" + icon_dead = "spark_dead" + + maxHealth = 210 + health = 210 + taser_kill = 0 //It -is- the taser. + + melee_damage_lower = 5 + melee_damage_upper = 10 + + ranged = 1 + projectilesound = 'sound/weapons/taser2.ogg' + projectiletype = /obj/item/projectile/beam/stun/weak + firing_lines = 1 + cooperative = 1 + + poison_chance = 15 + poison_per_bite = 3 + poison_type = "stimm" + +/mob/living/simple_animal/hostile/giant_spider/phorogenic + desc = "Crystalline and purple, it makes you shudder to look at it. This one has haunting purple eyes." + icon_state = "phoron" + icon_living = "phoron" + icon_dead = "phoron_dead" + + maxHealth = 225 + health = 225 + taser_kill = 0 //You will need more than a peashooter to kill the juggernaut. + + melee_damage_lower = 10 + melee_damage_upper = 20 + + poison_chance = 30 + poison_per_bite = 0.5 + poison_type = "phoron" + + var/exploded = 0 + +/mob/living/simple_animal/hostile/giant_spider/phorogenic/New() + adjust_scale(1.25) + return ..() + +/mob/living/simple_animal/hostile/giant_spider/phorogenic/death() + visible_message("\The [src]'s body begins to rupture!") + spawn(rand(1,5)) + if(src && !exploded) + visible_message("\The [src]'s body detonates!") + exploded = 1 + explosion(src.loc, 1, 2, 4, 6) + return ..() + /mob/living/simple_animal/hostile/giant_spider/frost desc = "Icy and blue, it makes you shudder to look at it. This one has brilliant blue eyes." icon_state = "frost" @@ -126,6 +372,9 @@ poison_per_bite = 5 poison_type = "cryotoxin" +/* +Spider Procs +*/ /mob/living/simple_animal/hostile/giant_spider/New(var/location, var/atom/parent) get_light_and_color(parent) @@ -167,6 +416,16 @@ O.implants += eggs to_chat(H, "\The [src] injects something into your [O.name]!") +/mob/living/simple_animal/hostile/giant_spider/webslinger/DoPunch(var/atom/A) + . = ..() + if(.) // If we succeeded in hitting. + if(isliving(A)) + var/mob/living/L = A + var/obj/effect/spider/stickyweb/W = locate() in get_turf(L) + if(!W && prob(75)) + visible_message("\The [src] throws a layer of web at \the [L]!") + new /obj/effect/spider/stickyweb(L.loc) + /mob/living/simple_animal/hostile/giant_spider/handle_stance() . = ..() if(ai_inactive) return diff --git a/code/modules/mob/living/simple_animal/animals/mouse.dm b/code/modules/mob/living/simple_animal/animals/mouse.dm index 1b8f439f50c..87df9015277 100644 --- a/code/modules/mob/living/simple_animal/animals/mouse.dm +++ b/code/modules/mob/living/simple_animal/animals/mouse.dm @@ -79,7 +79,7 @@ icon_living = "mouse_[body_color]" icon_dead = "mouse_[body_color]_dead" icon_rest = "mouse_[body_color]_sleep" - desc = "It's a small [body_color] rodent, often seen hiding in maintenance areas and making a nuisance of itself." + desc = "A small [body_color] rodent, often seen hiding in maintenance areas and making a nuisance of itself." /mob/living/simple_animal/mouse/proc/splat() src.health = 0 @@ -95,13 +95,13 @@ if( ishuman(AM) ) if(!stat) var/mob/M = AM - M << "\icon[src] Squeek!" + M.visible_message("\icon[src] Squeek!") M << 'sound/effects/mouse_squeak.ogg' ..() /mob/living/simple_animal/mouse/death() layer = MOB_LAYER - playsound(src, 'sound/effects/mouse_squeak_loud.ogg', 50, 1) + playsound(src, 'sound/effects/mouse_squeak_loud.ogg', 35, 1) if(client) client.time_died_as_mouse = world.time ..() diff --git a/code/modules/mob/living/simple_animal/animals/parrot.dm b/code/modules/mob/living/simple_animal/animals/parrot.dm index 1e17212708c..bf84d01e0e4 100644 --- a/code/modules/mob/living/simple_animal/animals/parrot.dm +++ b/code/modules/mob/living/simple_animal/animals/parrot.dm @@ -29,8 +29,8 @@ /mob/living/simple_animal/parrot - name = "\improper Parrot" - desc = "The parrot squaks, \"It's a Parrot! BAWWK!\"" + name = "parrot" + desc = "The parrot squawks, \"It's a parrot! BAWWK!\"" icon = 'icons/mob/animal.dmi' icon_state = "parrot_fly" icon_living = "parrot_fly" @@ -47,9 +47,9 @@ stop_automated_movement = 1 universal_speak = 1 - has_langs = list("Bird") + has_langs = list("Bird", "Galactic Common") speak_chance = 2 - speak = list("Hi","Hello!","Cracker?","BAWWWWK george mellons griffing me") + speak = list("Hi","Hello!","Cracker?","Bawk!") speak_emote = list("squawks","says","yells") emote_hear = list("squawks","bawks") emote_see = list("flutters its wings") @@ -160,19 +160,19 @@ if(copytext(possible_phrase,1,3) in department_radio_keys) possible_phrase = copytext(possible_phrase,3,length(possible_phrase)) else - usr << "There is nothing to remove from its [remove_from]." + to_chat(usr, "There is nothing to remove from its [remove_from].") return //Adding things to inventory else if(href_list["add_inv"]) var/add_to = href_list["add_inv"] if(!usr.get_active_hand()) - usr << "You have nothing in your hand to put on its [add_to]." + to_chat(usr, "You have nothing in your hand to put on its [add_to].") return switch(add_to) if("ears") if(ears) - usr << "It's already wearing something." + to_chat(usr, "It's already wearing something.") return else var/obj/item/item_to_add = usr.get_active_hand() @@ -180,7 +180,7 @@ return if( !istype(item_to_add, /obj/item/device/radio/headset) ) - usr << "This object won't fit." + to_chat(usr, "This object won't fit.") return var/obj/item/device/radio/headset/headset_to_add = item_to_add @@ -188,7 +188,7 @@ usr.drop_item() headset_to_add.forceMove(src) src.ears = headset_to_add - usr << "You fit the headset onto [src]." + to_chat(usr, "You fit the headset onto [src].") clearlist(available_channels) for(var/ch in headset_to_add.channels) @@ -209,7 +209,7 @@ available_channels.Add(":q") if(headset_to_add.translate_binary) - available_channels.Add(":b") + available_channels.Add("#b") else ..() @@ -572,7 +572,7 @@ return -1 if(held_item) - src << "You are already holding the [held_item]" + to_chat(src, "You are already holding the [held_item]") return 1 for(var/obj/item/I in view(1,src)) @@ -588,7 +588,7 @@ visible_message("[src] grabs the [held_item]!", "You grab the [held_item]!", "You hear the sounds of wings flapping furiously.") return held_item - src << "There is nothing of interest to take." + to_chat(src, "There is nothing of interest to take.") return 0 /mob/living/simple_animal/parrot/proc/steal_from_mob() @@ -600,7 +600,7 @@ return -1 if(held_item) - src << "You are already holding the [held_item]" + to_chat(src, "You are already holding the [held_item]") return 1 var/obj/item/stolen_item = null @@ -619,7 +619,7 @@ visible_message("[src] grabs the [held_item] out of [C]'s hand!", "You snag the [held_item] out of [C]'s hand!", "You hear the sounds of wings flapping furiously.") return held_item - src << "There is nothing of interest to take." + to_chat(src, "There is nothing of interest to take.") return 0 /mob/living/simple_animal/parrot/verb/drop_held_item_player() @@ -643,7 +643,7 @@ return -1 if(!held_item) - usr << "You have nothing to drop!" + to_chat(usr, "You have nothing to drop!") return 0 if(!drop_gently) @@ -651,11 +651,11 @@ var/obj/item/weapon/grenade/G = held_item G.forceMove(src.loc) G.prime() - src << "You let go of the [held_item]!" + to_chat(src, "You let go of the [held_item]!") held_item = null return 1 - src << "You drop the [held_item]." + to_chat(src, "You drop the [held_item].") held_item.forceMove(src.loc) held_item = null @@ -676,7 +676,7 @@ src.forceMove(AM.loc) icon_state = "parrot_sit" return - src << "There is no perch nearby to sit on." + to_chat(src, "There is no perch nearby to sit on.") return /* @@ -760,4 +760,4 @@ parrot_interest = user parrot_state = PARROT_SWOOP | PARROT_ATTACK //Attack other animals regardless icon_state = "parrot_fly" - return success \ No newline at end of file + return success diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 32a5a9cb35d..231db2866a8 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -90,6 +90,7 @@ var/assist_distance = 25 // Radius in which I'll ask my comrades for help. var/supernatural = 0 // If the mob is supernatural (used in null-rod stuff for banishing?) var/grab_resist = 75 // Chance of me resisting a grab attempt. + var/taser_kill = 1 // Is the mob weak to tasers //Attack ranged settings var/ranged = 0 // Do I attack at range? @@ -107,7 +108,9 @@ var/friendly = "nuzzles" // What mobs do to people when they aren't really hostile var/attack_sound = null // Sound to play when I attack var/environment_smash = 0 // How much environment damage do I do when I hit stuff? - var/melee_miss_chance = 25 // percent chance to miss a melee attack. + var/melee_miss_chance = 15 // percent chance to miss a melee attack. + var/melee_attack_minDelay = 5 // How long between attacks at least + var/melee_attack_maxDelay = 10 // How long between attacks at most //Special attacks var/spattack_prob = 0 // Chance of the mob doing a special attack (0 for never) @@ -501,7 +504,10 @@ stun_effect_act(0, Proj.agony) if(!Proj.nodamage) - adjustBruteLoss(Proj.damage) + var/true_damage = Proj.damage + if(!Proj.SA_vulnerability || Proj.SA_vulnerability == intelligence_level) + true_damage += Proj.SA_bonus_damage + adjustBruteLoss(true_damage) if(Proj.firer) react_to_attack(Proj.firer) @@ -1168,7 +1174,7 @@ if(!Adjacent(target_mob)) return if(!client) - sleep(rand(8) + 8) + sleep(rand(melee_attack_minDelay, melee_attack_maxDelay)) if(isliving(target_mob)) var/mob/living/L = target_mob @@ -1437,16 +1443,30 @@ //Shot with taser/stunvolver /mob/living/simple_animal/stun_effect_act(var/stun_amount, var/agony_amount, var/def_zone, var/used_weapon=null) - var/stunDam = 0 - var/agonyDam = 0 + if(taser_kill) + var/stunDam = 0 + var/agonyDam = 0 - if(stun_amount) - stunDam += stun_amount * 0.5 - adjustFireLoss(stunDam) + if(stun_amount) + stunDam += stun_amount * 0.5 + adjustFireLoss(stunDam) - if(agony_amount) - agonyDam += agony_amount * 0.5 - adjustFireLoss(agonyDam) + if(agony_amount) + agonyDam += agony_amount * 0.5 + adjustFireLoss(agonyDam) + +/mob/living/simple_animal/emp_act(severity) + if(!isSynthetic()) + return + switch(severity) + if(1) + adjustFireLoss(rand(15, 25)) + if(2) + adjustFireLoss(rand(10, 18)) + if(3) + adjustFireLoss(rand(5, 12)) + if(4) + adjustFireLoss(rand(1, 6)) // Force it to target something /mob/living/simple_animal/proc/taunt(var/mob/living/new_target, var/forced = FALSE) diff --git a/code/modules/mob/living/simple_animal/slime/combat.dm b/code/modules/mob/living/simple_animal/slime/combat.dm index 0068ee728c9..8554a27e5f7 100644 --- a/code/modules/mob/living/simple_animal/slime/combat.dm +++ b/code/modules/mob/living/simple_animal/slime/combat.dm @@ -213,7 +213,7 @@ // Otherwise they're probably fighting the slime. if(prob(25)) visible_message("\The [user]'s [W] passes right through [src]!") - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(W)) return ..() diff --git a/code/modules/mob/living/simple_animal/slime/death.dm b/code/modules/mob/living/simple_animal/slime/death.dm index 01500db42e0..622b12a8597 100644 --- a/code/modules/mob/living/simple_animal/slime/death.dm +++ b/code/modules/mob/living/simple_animal/slime/death.dm @@ -4,7 +4,10 @@ return if(!gibbed && is_adult) - var/mob/living/simple_animal/slime/S = make_new_slime() + var/death_type = type_on_death + if(!death_type) + death_type = src.type + var/mob/living/simple_animal/slime/S = make_new_slime(death_type) S.rabid = TRUE step_away(S, src) is_adult = FALSE diff --git a/code/modules/mob/living/simple_animal/slime/slime.dm b/code/modules/mob/living/simple_animal/slime/slime.dm index 7a213ac97fc..4148856d72a 100644 --- a/code/modules/mob/living/simple_animal/slime/slime.dm +++ b/code/modules/mob/living/simple_animal/slime/slime.dm @@ -1,5 +1,5 @@ /mob/living/simple_animal/slime - name = "baby slime" + name = "slime" desc = "The most basic of slimes. The grey slime has no remarkable qualities, however it remains one of the most useful colors for scientists." icon = 'icons/mob/slime2.dmi' icon_state = "grey baby slime" @@ -84,6 +84,7 @@ /mob/living/simple_animal/slime/blue, /mob/living/simple_animal/slime/purple ) + var/type_on_death = null // Set this if you want dying slimes to split into a specific type and not their type. var/reagent_injected = null // Some slimes inject reagents on attack. This tells the game what reagent to use. var/injection_amount = 5 // This determines how much. @@ -123,7 +124,7 @@ /mob/living/simple_animal/slime/proc/update_name() if(docile) // Docile slimes are generally named, so we shouldn't mess with it. return - name = "[slime_color] [is_adult ? "adult" : "baby"] slime ([number])" + name = "[slime_color] [is_adult ? "adult" : "baby"] [initial(name)] ([number])" real_name = name /mob/living/simple_animal/slime/update_icon() @@ -338,8 +339,10 @@ to_chat(src, "I am not old enough to reproduce yet...") // Used for reproducing and dying. -/mob/living/simple_animal/slime/proc/make_new_slime() +/mob/living/simple_animal/slime/proc/make_new_slime(var/desired_type) var/t = src.type + if(desired_type) + t = desired_type if(prob(mutation_chance / 10)) t = /mob/living/simple_animal/slime/rainbow diff --git a/code/modules/mob/living/simple_animal/slime/subtypes.dm b/code/modules/mob/living/simple_animal/slime/subtypes.dm index 5b53041175c..c0640489459 100644 --- a/code/modules/mob/living/simple_animal/slime/subtypes.dm +++ b/code/modules/mob/living/simple_animal/slime/subtypes.dm @@ -209,6 +209,26 @@ /mob/living/simple_animal/slime/dark_blue/get_cold_protection() return 1 // This slime is immune to cold. +// Surfave variant +/mob/living/simple_animal/slime/dark_blue/wild + name = "wild slime" + desc = "The result of slimes escaping containment from some xenobiology lab. The slime makes other entities near it feel much colder, \ + and it is more resilient to the cold. These qualities have made this color of slime able to thrive on a harsh, cold world and is able to rival \ + the ferocity of other apex predators in this region of Sif. As such, it is a very invasive species." + description_info = "This slime makes other entities near it feel much colder, and is more resilient to the cold. It also has learned advanced combat tactics from \ + having to endure the harsh world outside its lab. Note that processing this large slime will give six cores." + icon_scale = 2 + optimal_combat = TRUE // Gotta be sharp to survive out there. + rabid = TRUE + cores = 6 + maxHealth = 150 // Base health + maxHealth_adult = 250 + type_on_death = /mob/living/simple_animal/slime/dark_blue // Otherwise infinite slimes might occur. + pixel_y = -10 // Since the base sprite isn't centered properly, the pixel auto-adjustment needs some help. + +/mob/living/simple_animal/slime/dark_blue/wild/New() + ..() + make_adult() /mob/living/simple_animal/slime/silver desc = "This slime is shiny, and can deflect lasers or other energy weapons directed at it." diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 92a8b3bdebc..f911ba94c58 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -44,6 +44,7 @@ dead_mob_list += src else living_mob_list += src + update_transform() // Some mobs may start bigger or smaller than normal. ..() /mob/proc/show_message(msg, type, alt, alt_type)//Message, type of message (1 or 2), alternative message, alt message type (1 or 2) @@ -534,6 +535,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) @@ -859,6 +861,12 @@ resting = max(resting + amount,0) return +/mob/proc/AdjustLosebreath(amount) + losebreath = Clamp(0, losebreath + amount, 25) + +/mob/proc/SetLosebreath(amount) + losebreath = Clamp(0, amount, 25) + /mob/proc/get_species() return "" diff --git a/code/modules/mob/mob_grab.dm b/code/modules/mob/mob_grab.dm index 890ff2e8732..492ec9cb05a 100644 --- a/code/modules/mob/mob_grab.dm +++ b/code/modules/mob/mob_grab.dm @@ -277,7 +277,7 @@ msg_admin_attack("[key_name(assailant)] strangled (kill intent) [key_name(affecting)]") affecting.setClickCooldown(10) - affecting.losebreath += 1 + affecting.AdjustLosebreath(1) affecting.set_dir(WEST) adjust_position() diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 56104d34f44..b7fdd7714de 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -400,7 +400,7 @@ proc/is_blind(A) return // Can't talk in deadchat if you can't see it. for(var/mob/M in player_list) - if(M.client && ((!istype(M, /mob/new_player) && M.stat == DEAD) || (M.client.holder && !is_eventM(M.client))) && M.is_preference_enabled(/datum/client_preference/show_dsay)) + if(M.client && (!istype(M, /mob/new_player) && M.stat == DEAD) && M.is_preference_enabled(/datum/client_preference/show_dsay)) var/follow var/lname if(M.forbid_seeing_deadchat && !M.client.holder) diff --git a/code/modules/mob/new_player/preferences_setup.dm b/code/modules/mob/new_player/preferences_setup.dm index 5fa306b7b96..a96524f1f1b 100644 --- a/code/modules/mob/new_player/preferences_setup.dm +++ b/code/modules/mob/new_player/preferences_setup.dm @@ -258,7 +258,7 @@ mannequin.delete_inventory(TRUE) dress_preview_mob(mannequin) - preview_icon = icon('icons/effects/effects.dmi', "nothing") + preview_icon = icon('icons/effects/128x48.dmi', bgstate) preview_icon.Scale(48+32, 16+32) mannequin.dir = NORTH diff --git a/code/modules/mob/new_player/sprite_accessories.dm b/code/modules/mob/new_player/sprite_accessories.dm index 42bc1280e27..02c61fc8bef 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" @@ -61,6 +62,10 @@ name = "Short Hair 2" icon_state = "hair_shorthair3" + short3 + name = "Short Hair 3" + icon_state = "hair_shorthair4" + twintail name = "Twintail" icon_state = "hair_twintail" @@ -323,7 +328,7 @@ name = "Overeye Long" icon_state = "hair_longovereye" - fag + flowhair name = "Flow Hair" icon_state = "hair_f" diff --git a/code/modules/organs/internal/appendix.dm b/code/modules/organs/internal/appendix.dm index f756b71efa4..01d7008a096 100644 --- a/code/modules/organs/internal/appendix.dm +++ b/code/modules/organs/internal/appendix.dm @@ -18,6 +18,8 @@ return 0 /obj/item/organ/internal/appendix/process() + ..() + if(!inflamed || !owner) return diff --git a/code/modules/organs/internal/brain.dm b/code/modules/organs/internal/brain.dm index 28fbf62f1ea..7dd2bd948ef 100644 --- a/code/modules/organs/internal/brain.dm +++ b/code/modules/organs/internal/brain.dm @@ -44,21 +44,6 @@ tmp_owner.internal_organs_by_name[organ_tag] = new replace_path(tmp_owner, 1) tmp_owner = null -/obj/item/organ/internal/pariah_brain - name = "brain remnants" - desc = "Did someone tread on this? It looks useless for cloning or cyborgification." - organ_tag = "brain" - parent_organ = BP_HEAD - icon = 'icons/mob/alien.dmi' - icon_state = "chitin" - vital = 1 - -/obj/item/organ/internal/brain/xeno - name = "thinkpan" - desc = "It looks kind of like an enormous wad of purple bubblegum." - icon = 'icons/mob/alien.dmi' - icon_state = "chitin" - /obj/item/organ/internal/brain/New() ..() health = config.default_brain_health @@ -127,6 +112,21 @@ target.key = brainmob.key ..() +/obj/item/organ/internal/pariah_brain + name = "brain remnants" + desc = "Did someone tread on this? It looks useless for cloning or cyborgification." + organ_tag = "brain" + parent_organ = BP_HEAD + icon = 'icons/mob/alien.dmi' + icon_state = "chitin" + vital = 1 + +/obj/item/organ/internal/brain/xeno + name = "thinkpan" + desc = "It looks kind of like an enormous wad of purple bubblegum." + icon = 'icons/mob/alien.dmi' + icon_state = "chitin" + /obj/item/organ/internal/brain/slime name = "slime core" desc = "A complex, organic knot of jelly and crystalline particles." diff --git a/code/modules/organs/internal/kidneys.dm b/code/modules/organs/internal/kidneys.dm index a547a2539fe..19652a6376d 100644 --- a/code/modules/organs/internal/kidneys.dm +++ b/code/modules/organs/internal/kidneys.dm @@ -9,6 +9,7 @@ /obj/item/organ/internal/kidneys/process() ..() + if(!owner) return // Coffee is really bad for you with busted kidneys. diff --git a/code/modules/organs/internal/lungs.dm b/code/modules/organs/internal/lungs.dm index c00d5df7a83..c42167f1311 100644 --- a/code/modules/organs/internal/lungs.dm +++ b/code/modules/organs/internal/lungs.dm @@ -19,7 +19,7 @@ owner.drip(10) if(prob(8)) spawn owner.emote("me", 1, "gasps for air!") - owner.losebreath += 15 + owner.AdjustLosebreath(15) /obj/item/organ/internal/lungs/proc/rupture() var/obj/item/organ/external/parent = owner.get_organ(parent_organ) diff --git a/code/modules/organs/internal/organ_internal.dm b/code/modules/organs/internal/organ_internal.dm index a3fdc511fc4..43b3a4c4d7f 100644 --- a/code/modules/organs/internal/organ_internal.dm +++ b/code/modules/organs/internal/organ_internal.dm @@ -58,5 +58,7 @@ if (prob(3)) take_damage(1,silent=prob(30)) - //if(. >= 3 && antibiotics < 30) //INFECTION_LEVEL_THREE, others are handled on each specific organ - //Nothing that generic internal organs do for this + if(. >= 3 && antibiotics < 30) //INFECTION_LEVEL_THREE + if (prob(50)) + take_damage(1,silent=prob(15)) + diff --git a/code/modules/organs/organ.dm b/code/modules/organs/organ.dm index 915258e1125..77706b95176 100644 --- a/code/modules/organs/organ.dm +++ b/code/modules/organs/organ.dm @@ -91,6 +91,9 @@ var/list/organ_cache = list() if(owner && vital) owner.death() +/obj/item/organ/proc/adjust_germ_level(var/amount) // Unless you're setting germ level directly to 0, use this proc instead + germ_level = Clamp(germ_level + amount, 0, INFECTION_LEVEL_MAX) + /obj/item/organ/process() if(loc != owner) @@ -117,9 +120,9 @@ var/list/organ_cache = list() if(config.organs_decay) damage += rand(1,3) if(damage >= max_damage) damage = max_damage - germ_level += rand(2,6) + adjust_germ_level(rand(2,6)) if(germ_level >= INFECTION_LEVEL_TWO) - germ_level += rand(2,6) + adjust_germ_level(rand(2,6)) if(germ_level >= INFECTION_LEVEL_THREE) die() @@ -158,12 +161,12 @@ var/list/organ_cache = list() owner.adjustToxLoss(infection_damage) if (germ_level > 0 && germ_level < INFECTION_LEVEL_ONE/2 && prob(30)) - germ_level-- + adjust_germ_level(-1) if (germ_level >= INFECTION_LEVEL_ONE/2) //aiming for germ level to go from ambient to INFECTION_LEVEL_TWO in an average of 15 minutes if(antibiotics < 5 && prob(round(germ_level/6))) - germ_level++ + adjust_germ_level(1) if(germ_level >= INFECTION_LEVEL_ONE) . = 1 //Organ qualifies for effect-specific processing @@ -179,7 +182,7 @@ var/list/organ_cache = list() if (germ_level >= INFECTION_LEVEL_THREE && antibiotics < 30) . = 3 //Organ qualifies for effect-specific processing - germ_level++ //Germ_level increases without overdose of antibiotics + adjust_germ_level(rand(5,10)) //Germ_level increases without overdose of antibiotics /obj/item/organ/proc/handle_rejection() // Process unsuitable transplants. TODO: consider some kind of @@ -193,13 +196,13 @@ var/list/organ_cache = list() if(rejecting % 10 == 0) //Only fire every ten rejection ticks. switch(rejecting) if(1 to 50) - germ_level++ + adjust_germ_level(1) if(51 to 200) - germ_level += rand(1,2) + adjust_germ_level(rand(1,2)) if(201 to 500) - germ_level += rand(2,3) + adjust_germ_level(rand(2,3)) if(501 to INFINITY) - germ_level += rand(3,5) + adjust_germ_level(rand(3,5)) owner.reagents.add_reagent("toxin", rand(1,2)) /obj/item/organ/proc/receive_chem(chemical as obj) @@ -238,9 +241,11 @@ var/list/organ_cache = list() if (germ_level < INFECTION_LEVEL_ONE) germ_level = 0 //cure instantly else if (germ_level < INFECTION_LEVEL_TWO) - germ_level -= 6 //at germ_level == 500, this should cure the infection in a minute + adjust_germ_level(-6) //at germ_level < 500, this should cure the infection in a minute + else if (germ_level < INFECTION_LEVEL_THREE) + adjust_germ_level(-2) //at germ_level < 1000, this will cure the infection in 5 minutes else - germ_level -= 2 //at germ_level == 1000, this will cure the infection in 5 minutes + adjust_germ_level(-1) // You waited this long to get treated, you don't really deserve this organ //Adds autopsy data for used_weapon. /obj/item/organ/proc/add_autopsy_data(var/used_weapon, var/damage) diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm index 1508aff08a9..b6ad2fff2c7 100644 --- a/code/modules/organs/organ_external.dm +++ b/code/modules/organs/organ_external.dm @@ -411,7 +411,7 @@ user << "You can't reach your [src.name] while holding [tool] in your [owner.get_bodypart_name(grasp)]." return 0 - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(tool)) if(!do_mob(user, owner, 10)) user << "You must stand still to do that." return 0 diff --git a/code/modules/organs/organ_icon.dm b/code/modules/organs/organ_icon.dm index 48759ae1cff..3c986b16fd8 100644 --- a/code/modules/organs/organ_icon.dm +++ b/code/modules/organs/organ_icon.dm @@ -71,7 +71,7 @@ var/global/list/limb_icon_cache = list() overlays |= lip_icon mob_icon.Blend(lip_icon, ICON_OVERLAY) - //Head markings, duplicated (sadly) below. + //Head markings. for(var/M in markings) var/datum/sprite_accessory/marking/mark_style = markings[M]["datum"] var/icon/mark_s = new/icon("icon" = mark_style.icon, "icon_state" = "[mark_style.icon_state]-[organ_tag]") @@ -89,11 +89,13 @@ var/global/list/limb_icon_cache = list() overlays |= facial_s if(owner.h_style && !(owner.head && (owner.head.flags_inv & BLOCKHEADHAIR))) - var/datum/sprite_accessory/hair_style = hair_styles_list[owner.h_style] + var/datum/sprite_accessory/hair/hair_style = hair_styles_list[owner.h_style] if(hair_style && (species.get_bodytype(owner) in hair_style.species_allowed)) var/icon/hair_s = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s") + var/icon/hair_s_add = new/icon("icon" = hair_style.icon_add, "icon_state" = "[hair_style.icon_state]_s") if(hair_style.do_colouration && islist(h_col) && h_col.len >= 3) - hair_s.Blend(rgb(h_col[1], h_col[2], h_col[3]), ICON_ADD) + hair_s.Blend(rgb(h_col[1], h_col[2], h_col[3]), ICON_MULTIPLY) + hair_s.Blend(hair_s_add, ICON_ADD) overlays |= hair_s return mob_icon @@ -130,14 +132,15 @@ var/global/list/limb_icon_cache = list() mob_icon = new /icon(species.get_icobase(owner, (status & ORGAN_MUTATED)), "[icon_name][gender ? "_[gender]" : ""]") apply_colouration(mob_icon) - //Body markings, does not include head, duplicated (sadly) above. - for(var/M in markings) - var/datum/sprite_accessory/marking/mark_style = markings[M]["datum"] - var/icon/mark_s = new/icon("icon" = mark_style.icon, "icon_state" = "[mark_style.icon_state]-[organ_tag]") - mark_s.Blend(markings[M]["color"], ICON_ADD) - overlays |= mark_s //So when it's not on your body, it has icons - mob_icon.Blend(mark_s, ICON_OVERLAY) //So when it's on your body, it has icons - icon_cache_key += "[M][markings[M]["color"]]" + //Body markings, actually does not include head this time. Done separately above. + if(!istype(src,/obj/item/organ/external/head)) + for(var/M in markings) + var/datum/sprite_accessory/marking/mark_style = markings[M]["datum"] + var/icon/mark_s = new/icon("icon" = mark_style.icon, "icon_state" = "[mark_style.icon_state]-[organ_tag]") + mark_s.Blend(markings[M]["color"], ICON_ADD) + overlays |= mark_s //So when it's not on your body, it has icons + mob_icon.Blend(mark_s, ICON_OVERLAY) //So when it's on your body, it has icons + icon_cache_key += "[M][markings[M]["color"]]" if(body_hair && islist(h_col) && h_col.len >= 3) var/cache_key = "[body_hair]-[icon_name]-[h_col[1]][h_col[2]][h_col[3]]" diff --git a/code/modules/organs/subtypes/standard.dm b/code/modules/organs/subtypes/standard.dm index 90567f23635..d1eb81cc7f7 100644 --- a/code/modules/organs/subtypes/standard.dm +++ b/code/modules/organs/subtypes/standard.dm @@ -279,6 +279,8 @@ spawn(1) owner.update_hair() get_icon() + if(vital) //This is just in case we ever add something that both a) Doesn't need a head to live, and b) Can be defibbed + owner.can_defib = 0 ..() /obj/item/organ/external/head/take_damage(brute, burn, sharp, edge, used_weapon = null, list/forbidden_limbs = list()) diff --git a/code/modules/overmap/ships/computers/shuttle.dm b/code/modules/overmap/ships/computers/shuttle.dm index 5199b3e3eb0..05d1a6d8c6f 100644 --- a/code/modules/overmap/ships/computers/shuttle.dm +++ b/code/modules/overmap/ships/computers/shuttle.dm @@ -19,7 +19,7 @@ shuttle.area_offsite = shuttle.area_station shuttle_controller.shuttles[shuttle_tag] = shuttle shuttle_controller.process_shuttles += shuttle - testing("Exploration shuttle '[shuttle_tag]' at zlevel [z] successfully added.") + testing("Exploration shuttle '[shuttle_tag]' at z-level [z] successfully added.") //Sets destination to new sector. Can be null. /obj/machinery/computer/shuttle_control/explore/proc/update_destination(var/obj/effect/map/D) @@ -84,7 +84,7 @@ else shuttle_status = "Standing-by at offsite location." if(WAIT_LAUNCH, FORCE_LAUNCH) - shuttle_status = "Shuttle has recieved command and will depart shortly." + shuttle_status = "Shuttle has received command and will depart shortly." if(WAIT_ARRIVE) shuttle_status = "Proceeding to destination." if(WAIT_FINISH) diff --git a/code/modules/paperwork/adminpaper.dm b/code/modules/paperwork/adminpaper.dm index b17bdf29f28..6ed6ad93fc9 100644 --- a/code/modules/paperwork/adminpaper.dm +++ b/code/modules/paperwork/adminpaper.dm @@ -58,7 +58,7 @@ text = "
" text += "This transmission is intended only for the addressee and may contain confidential information. Any unauthorized disclosure is strictly prohibited.

" - text += "If this transmission is recieved in error, please notify both the sender and the office of [using_map.boss_name] Internal Affairs immediately so that corrective action may be taken." + text += "If this transmission is received in error, please notify both the sender and the office of [using_map.boss_name] Internal Affairs immediately so that corrective action may be taken." text += "Failure to comply is a breach of regulation and may be prosecuted to the fullest extent of the law, where applicable." text += "
" diff --git a/code/modules/paperwork/faxmachine.dm b/code/modules/paperwork/faxmachine.dm index 778abc4ee05..92076c0b150 100644 --- a/code/modules/paperwork/faxmachine.dm +++ b/code/modules/paperwork/faxmachine.dm @@ -80,7 +80,7 @@ var/list/adminfaxes = list() //cache for faxes that have been sent to admins if(copyitem) copyitem.loc = usr.loc usr.put_in_hands(copyitem) - usr << "You take \the [copyitem] out of \the [src]." + to_chat(usr, "You take \the [copyitem] out of \the [src].") copyitem = null if(href_list["scan"]) @@ -124,7 +124,7 @@ var/list/adminfaxes = list() //cache for faxes that have been sent to admins var/success = 0 for(var/obj/machinery/photocopier/faxmachine/F in allfaxes) if( F.department == destination ) - success = F.recievefax(copyitem) + success = F.receivefax(copyitem) if (success) visible_message("[src] beeps, \"Message transmitted successfully.\"") @@ -132,7 +132,7 @@ var/list/adminfaxes = list() //cache for faxes that have been sent to admins else visible_message("[src] beeps, \"Error transmitting message.\"") -/obj/machinery/photocopier/faxmachine/proc/recievefax(var/obj/item/incoming) +/obj/machinery/photocopier/faxmachine/proc/receivefax(var/obj/item/incoming) if(stat & (BROKEN|NOPOWER)) return 0 @@ -164,7 +164,7 @@ var/list/adminfaxes = list() //cache for faxes that have been sent to admins use_power(200) - //recieved copies should not use toner since it's being used by admins only. + //received copies should not use toner since it's being used by admins only. var/obj/item/rcvdcopy if (istype(copyitem, /obj/item/weapon/paper)) rcvdcopy = copy(copyitem, 0) diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index 0af97704348..bdea8fed709 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -35,6 +35,24 @@ var/const/signfont = "Times New Roman" var/const/crayonfont = "Comic Sans MS" +/obj/item/weapon/paper/alien + name = "alien tablet" + desc = "It looks highly advanced" + icon = 'icons/obj/abductor.dmi' + icon_state = "alienpaper" + +/obj/item/weapon/paper/alien/update_icon() + if(info) + icon_state = "alienpaper_words" + else + icon_state = "alienpaper" + +/obj/item/weapon/paper/alien/burnpaper() + return + +/obj/item/weapon/paper/alien/AltClick() // No airplanes for me. + return + //lipstick wiping is in code/game/objects/items/weapons/cosmetics.dm! /obj/item/weapon/paper/New() diff --git a/code/modules/paperwork/paperplane.dm b/code/modules/paperwork/paperplane.dm new file mode 100644 index 00000000000..bb37a380b61 --- /dev/null +++ b/code/modules/paperwork/paperplane.dm @@ -0,0 +1,102 @@ +// Ported from TG. Known issue: Throw hit can possibly double-proc. Seems to be throw code. +/obj/item/weapon/paperplane + name = "paper plane" + desc = "Paper folded into the shape of a plane." + icon = 'icons/obj/bureaucracy.dmi' + icon_state = "paperplane" + throw_range = 7 + throw_speed = 1 + throwforce = 0 + w_class = ITEMSIZE_TINY + + var/obj/item/weapon/paper/internalPaper + +/obj/item/weapon/paperplane/New(loc, obj/item/weapon/paper/newPaper) + . = ..() + pixel_y = rand(-8, 8) + pixel_x = rand(-9, 9) + if(newPaper) + internalPaper = newPaper + flags = newPaper.flags + color = newPaper.color + newPaper.forceMove(src) + else + internalPaper = new /obj/item/weapon/paper(src) + update_icon() + +/obj/item/weapon/paperplane/Destroy() + if(internalPaper) + qdel(internalPaper) + internalPaper = null + return ..() + +/obj/item/weapon/paperplane/update_icon() + overlays.Cut() + var/list/stamped = internalPaper.stamped + if(!stamped) + stamped = new + else if(stamped) + for(var/S in stamped) + var/obj/item/weapon/stamp/ = S + var/image/stampoverlay = image('icons/obj/bureaucracy.dmi', "paperplane_[initial(stamp.icon_state)]") + overlays += stampoverlay + +/obj/item/weapon/paperplane/attack_self(mob/user) + to_chat(user, "You unfold [src].") + var/atom/movable/internal_paper_tmp = internalPaper + internal_paper_tmp.forceMove(loc) + internalPaper = null + qdel(src) + user.put_in_hands(internal_paper_tmp) + +/obj/item/weapon/paperplane/attackby(obj/item/P, mob/living/carbon/human/user, params) + ..() + if(istype(P, /obj/item/weapon/pen)) + to_chat(user, "You should unfold [src] before changing it.") + return + + else if(istype(P, /obj/item/weapon/stamp)) //we don't randomize stamps on a paperplane + internalPaper.attackby(P, user) //spoofed attack to update internal paper. + update_icon() + + else if(is_hot(P)) + if(user.disabilities & CLUMSY && prob(10)) + user.visible_message("[user] accidentally ignites themselves!", \ + "You miss the [src] and accidentally light yourself on fire!") + user.unEquip(P) + user.adjust_fire_stacks(1) + user.IgniteMob() + return + + if(!(in_range(user, src))) //to prevent issues as a result of telepathically lighting a paper + return + user.unEquip(src) + user.visible_message("[user] lights [src] ablaze with [P]!", "You light [src] on fire!") + fire_act() + + add_fingerprint(user) + +/obj/item/weapon/paperplane/throw_impact(atom/hit_atom) + if(..() || !ishuman(hit_atom))//if the plane is caught or it hits a nonhuman + return + var/mob/living/carbon/human/H = hit_atom + if(prob(2)) + if((H.head && H.head.body_parts_covered & EYES) || (H.wear_mask && H.wear_mask.body_parts_covered & EYES) || (H.glasses && H.glasses.body_parts_covered & EYES)) + return + visible_message("\The [src] hits [H] in the eye!") + H.eye_blurry += 10 + var/obj/item/organ/internal/eyes/E = H.internal_organs_by_name[O_EYES] + if(E) + E.damage += 2.5 + H.emote("scream") + +/obj/item/weapon/paper/AltClick(mob/living/carbon/user, obj/item/I) + if ( istype(user) ) + if( (!in_range(src, user)) || user.stat || user.restrained() ) + return + to_chat(user, "You fold [src] into the shape of a plane!") + user.unEquip(src) + I = new /obj/item/weapon/paperplane(user, src) + user.put_in_hands(I) + else + to_chat(user, " You lack the dexterity to fold \the [src]. ") diff --git a/code/modules/paperwork/pen.dm b/code/modules/paperwork/pen.dm index 990c97b1c2b..1de92fe7430 100644 --- a/code/modules/paperwork/pen.dm +++ b/code/modules/paperwork/pen.dm @@ -119,8 +119,8 @@ /obj/item/weapon/pen/reagent/paralysis/New() ..() - reagents.add_reagent("zombiepowder", 10) - reagents.add_reagent("cryptobiolin", 15) + reagents.add_reagent("zombiepowder", 5) + reagents.add_reagent("cryptobiolin", 10) /* * Chameleon pen diff --git a/code/modules/planet/sif.dm b/code/modules/planet/sif.dm index dcb6d140ec0..1e84126fe74 100644 --- a/code/modules/planet/sif.dm +++ b/code/modules/planet/sif.dm @@ -195,8 +195,8 @@ datum/weather/sif /datum/weather/sif/blizzard name = "blizzard" icon_state = "snowfall_heavy" - temp_high = 233.15 // -40c - temp_low = 213.15 // -60c + temp_high = 243.15 // -30c + temp_low = 233.15 // -40c light_modifier = 0.3 flight_falure_modifier = 10 transition_chances = list( @@ -241,7 +241,7 @@ datum/weather/sif name = "storm" icon_state = "storm" temp_high = 243.15 // -30c - temp_low = 233.15 // -50c + temp_low = 233.15 // -40c light_modifier = 0.3 flight_falure_modifier = 10 transition_chances = list( diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index 1b0c8c72751..52143a5fc1f 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/blob_act() @@ -708,7 +705,7 @@ var/mob/living/carbon/human/H = user if(H.species.can_shred(H)) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed()) user.visible_message("[user.name] slashes at the [src.name]!", "You slash at the [src.name]!") playsound(src.loc, 'sound/weapons/slash.ogg', 100, 1) diff --git a/code/modules/power/cell.dm b/code/modules/power/cell.dm index 2c1699c5f60..7a8c7c541fb 100644 --- a/code/modules/power/cell.dm +++ b/code/modules/power/cell.dm @@ -2,6 +2,28 @@ // charge from 0 to 100% // fits in APC to provide backup power +/obj/item/weapon/cell + name = "power cell" + desc = "A rechargable electrochemical power cell." + icon = 'icons/obj/power.dmi' + icon_state = "cell" + item_state = "cell" + origin_tech = list(TECH_POWER = 1) + force = 5.0 + throwforce = 5.0 + throw_speed = 3 + throw_range = 5 + w_class = ITEMSIZE_NORMAL + var/charge = 0 // note %age conveted to actual charge in New + var/maxcharge = 1000 + var/rigged = 0 // true if rigged to explode + var/minor_fault = 0 //If not 100% reliable, it will build up faults. + var/self_recharge = FALSE // If true, the cell will recharge itself. + var/charge_amount = 25 // How much power to give, if self_recharge is true. The number is in absolute cell charge, as it gets divided by CELLRATE later. + var/last_use = 0 // A tracker for use in self-charging + var/charge_delay = 0 // How long it takes for the cell to start recharging after last use + matter = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 50) + /obj/item/weapon/cell/New() ..() charge = maxcharge @@ -16,7 +38,8 @@ /obj/item/weapon/cell/process() if(self_recharge) - give(charge_amount) + if(world.time >= last_use + charge_delay) + give(charge_amount) else return PROCESS_KILL @@ -59,6 +82,7 @@ return 0 var/used = min(charge, amount) charge -= used + last_use = world.time update_icon() return used @@ -80,6 +104,8 @@ var/amount_used = min(maxcharge-charge,amount) charge += amount_used update_icon() + if(loc) + loc.update_icon() return amount_used @@ -112,7 +138,6 @@ S.reagents.clear_reagents() - /obj/item/weapon/cell/proc/explode() var/turf/T = get_turf(src.loc) /* @@ -207,3 +232,7 @@ return min(rand(10,20),rand(10,20)) else return 0 + +/obj/item/weapon/cell/suicide_act(mob/user) + viewers(user) << "\The [user] is licking the electrodes of \the [src]! It looks like \he's trying to commit suicide." + return (FIRELOSS) \ No newline at end of file diff --git a/code/modules/power/cells/device_cells.dm b/code/modules/power/cells/device_cells.dm new file mode 100644 index 00000000000..822370a6b14 --- /dev/null +++ b/code/modules/power/cells/device_cells.dm @@ -0,0 +1,50 @@ +//currently only used by energy-type guns, that may change in the future. +/obj/item/weapon/cell/device + name = "device power cell" + desc = "A small power cell designed to power handheld devices." + icon_state = "dcell" + item_state = "egg6" + w_class = ITEMSIZE_SMALL + force = 0 + throw_speed = 5 + throw_range = 7 + maxcharge = 480 + charge_amount = 5 + matter = list("metal" = 350, "glass" = 50) + preserve_item = 1 + +/obj/item/weapon/cell/device/weapon + name = "weapon power cell" + desc = "A small power cell designed to power handheld weaponry." + icon_state = "wcell" + maxcharge = 2400 + charge_amount = 20 + +/obj/item/weapon/cell/device/weapon/empty/initialize() + ..() + charge = 0 + update_icon() + +/obj/item/weapon/cell/device/weapon/recharge + name = "self-charging weapon power cell" + desc = "A small power cell designed to power handheld weaponry. This one recharges itself." +// icon_state = "wcell" //TODO: Different sprite + self_recharge = TRUE + charge_amount = 120 + charge_delay = 75 + +/obj/item/weapon/cell/device/weapon/recharge/captain + charge_amount = 160 //Recharges a lot more quickly... + charge_delay = 100 //... but it takes a while to get started + +/obj/item/weapon/cell/device/weapon/recharge/alien + name = "void cell" + desc = "An alien technology that produces energy seemingly out of nowhere. Its small, cylinderal shape means it might be able to be used with human technology, perhaps?" + icon = 'icons/obj/abductor.dmi' + icon_state = "cell" + charge_amount = 120 // 5%. + charge_delay = 50 // Every five seconds, bit faster than the default. + origin_tech = list(TECH_POWER = 8, TECH_ENGINEERING = 6) + +/obj/item/weapon/cell/device/weapon/recharge/alien/update_icon() + return // No overlays please. \ No newline at end of file diff --git a/code/game/objects/items/weapons/power_cells.dm b/code/modules/power/cells/power_cells.dm similarity index 59% rename from code/game/objects/items/weapons/power_cells.dm rename to code/modules/power/cells/power_cells.dm index 2b63fb79bd7..a9b92a9bb3d 100644 --- a/code/game/objects/items/weapons/power_cells.dm +++ b/code/modules/power/cells/power_cells.dm @@ -1,137 +1,93 @@ -/obj/item/weapon/cell - name = "power cell" - desc = "A rechargable electrochemical power cell." - icon = 'icons/obj/power.dmi' - icon_state = "cell" - item_state = "cell" - origin_tech = list(TECH_POWER = 1) - force = 5.0 - throwforce = 5.0 - throw_speed = 3 - throw_range = 5 - w_class = ITEMSIZE_NORMAL - var/charge = 0 // note %age conveted to actual charge in New - var/maxcharge = 1000 - var/rigged = 0 // true if rigged to explode - var/minor_fault = 0 //If not 100% reliable, it will build up faults. - var/self_recharge = FALSE // If true, the cell will recharge itself. - var/charge_amount = 25 // How much power to give, if self_recharge is true. The number is in absolute cell charge, as it gets divided by CELLRATE later. - matter = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 50) - - suicide_act(mob/user) - viewers(user) << "\The [user] is licking the electrodes of \the [src]! It looks like \he's trying to commit suicide." - return (FIRELOSS) - -//currently only used by energy-type guns, that may change in the future. -/obj/item/weapon/cell/device - name = "device power cell" - desc = "A small power cell designed to power handheld devices." - icon_state = "dcell" - item_state = "egg6" - w_class = ITEMSIZE_SMALL - force = 0 - throw_speed = 5 - throw_range = 7 - maxcharge = 480 - matter = list("metal" = 350, "glass" = 50) - preserve_item = 1 - -/obj/item/weapon/cell/device/weapon - name = "weapon power cell" - desc = "A small power cell designed to power handheld weaponry." - icon_state = "wcell" - maxcharge = 2400 - -/obj/item/weapon/cell/crap - name = "\improper rechargable AA battery" - desc = "You can't top the plasma top." //TOTALLY TRADEMARK INFRINGEMENT - origin_tech = list(TECH_POWER = 0) - maxcharge = 500 - matter = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 40) - -/obj/item/weapon/cell/crap/empty/New() - ..() - charge = 0 - -/obj/item/weapon/cell/secborg - name = "security borg rechargable D battery" - origin_tech = list(TECH_POWER = 0) - maxcharge = 600 //600 max charge / 100 charge per shot = six shots - matter = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 40) - -/obj/item/weapon/cell/secborg/empty/New() - ..() - charge = 0 - -/obj/item/weapon/cell/apc - name = "heavy-duty power cell" - origin_tech = list(TECH_POWER = 1) - maxcharge = 5000 - matter = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 50) - -/obj/item/weapon/cell/high - name = "high-capacity power cell" - origin_tech = list(TECH_POWER = 2) - icon_state = "hcell" - maxcharge = 10000 - matter = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 60) - -/obj/item/weapon/cell/high/empty/New() - ..() - charge = 0 - -/obj/item/weapon/cell/super - name = "super-capacity power cell" - origin_tech = list(TECH_POWER = 5) - icon_state = "scell" - maxcharge = 20000 - matter = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 70) - -/obj/item/weapon/cell/super/empty/New() - ..() - charge = 0 - -/obj/item/weapon/cell/hyper - name = "hyper-capacity power cell" - origin_tech = list(TECH_POWER = 6) - icon_state = "hpcell" - maxcharge = 30000 - matter = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 80) - -/obj/item/weapon/cell/hyper/empty/New() - ..() - charge = 0 - -/obj/item/weapon/cell/infinite - name = "infinite-capacity power cell!" - icon_state = "icell" - origin_tech = null - maxcharge = 30000 //determines how badly mobs get shocked - matter = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 80) - - check_charge() - return 1 - use() - return 1 - -/obj/item/weapon/cell/potato - name = "potato battery" - desc = "A rechargable starch based power cell." - origin_tech = list(TECH_POWER = 1) - icon = 'icons/obj/power.dmi' //'icons/obj/harvest.dmi' - icon_state = "potato_cell" //"potato_battery" - charge = 100 - maxcharge = 300 - minor_fault = 1 - - -/obj/item/weapon/cell/slime - name = "charged slime core" - desc = "A yellow slime core infused with phoron, it crackles with power." - origin_tech = list(TECH_POWER = 4, TECH_BIO = 5) - icon = 'icons/mob/slimes.dmi' //'icons/obj/harvest.dmi' - icon_state = "yellow slime extract" //"potato_battery" - description_info = "This 'cell' holds a max charge of 10k and self recharges over time." - maxcharge = 10000 - matter = null - self_recharge = TRUE +/obj/item/weapon/cell/crap + name = "\improper rechargable AA battery" + desc = "You can't top the plasma top." //TOTALLY TRADEMARK INFRINGEMENT + origin_tech = list(TECH_POWER = 0) + maxcharge = 500 + matter = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 40) + +/obj/item/weapon/cell/crap/empty/New() + ..() + charge = 0 + +/obj/item/weapon/cell/secborg + name = "security borg rechargable D battery" + origin_tech = list(TECH_POWER = 0) + maxcharge = 600 //600 max charge / 100 charge per shot = six shots + matter = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 40) + +/obj/item/weapon/cell/secborg/empty/New() + ..() + charge = 0 + +/obj/item/weapon/cell/apc + name = "heavy-duty power cell" + origin_tech = list(TECH_POWER = 1) + maxcharge = 5000 + matter = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 50) + +/obj/item/weapon/cell/high + name = "high-capacity power cell" + origin_tech = list(TECH_POWER = 2) + icon_state = "hcell" + maxcharge = 10000 + matter = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 60) + +/obj/item/weapon/cell/high/empty/New() + ..() + charge = 0 + +/obj/item/weapon/cell/super + name = "super-capacity power cell" + origin_tech = list(TECH_POWER = 5) + icon_state = "scell" + maxcharge = 20000 + matter = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 70) + +/obj/item/weapon/cell/super/empty/New() + ..() + charge = 0 + +/obj/item/weapon/cell/hyper + name = "hyper-capacity power cell" + origin_tech = list(TECH_POWER = 6) + icon_state = "hpcell" + maxcharge = 30000 + matter = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 80) + +/obj/item/weapon/cell/hyper/empty/New() + ..() + charge = 0 + +/obj/item/weapon/cell/infinite + name = "infinite-capacity power cell!" + icon_state = "icell" + origin_tech = null + maxcharge = 30000 //determines how badly mobs get shocked + matter = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 80) + +/obj/item/weapon/cell/infinite/check_charge() + return 1 + +/obj/item/weapon/cell/infinite/use() + return 1 + +/obj/item/weapon/cell/potato + name = "potato battery" + desc = "A rechargable starch based power cell." + origin_tech = list(TECH_POWER = 1) + icon = 'icons/obj/power.dmi' //'icons/obj/harvest.dmi' + icon_state = "potato_cell" //"potato_battery" + charge = 100 + maxcharge = 300 + minor_fault = 1 + +/obj/item/weapon/cell/slime + name = "charged slime core" + desc = "A yellow slime core infused with phoron, it crackles with power." + origin_tech = list(TECH_POWER = 4, TECH_BIO = 5) + icon = 'icons/mob/slimes.dmi' //'icons/obj/harvest.dmi' + icon_state = "yellow slime extract" //"potato_battery" + description_info = "This 'cell' holds a max charge of 10k and self recharges over time." + maxcharge = 10000 + matter = null + self_recharge = TRUE diff --git a/code/modules/power/grid_checker.dm b/code/modules/power/grid_checker.dm index b8a123e02fa..8127383651c 100644 --- a/code/modules/power/grid_checker.dm +++ b/code/modules/power/grid_checker.dm @@ -4,6 +4,8 @@ than the alternative." icon_state = "gridchecker_on" circuit = /obj/item/weapon/circuitboard/grid_checker + density = 1 + anchored = 1 var/power_failing = FALSE // Turns to TRUE when the grid check event is fired by the Game Master, or perhaps a cheeky antag. // Wire stuff below. var/datum/wires/grid_checker/wires diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm index 59d7560a775..6de14313f1a 100644 --- a/code/modules/power/lighting.dm +++ b/code/modules/power/lighting.dm @@ -530,7 +530,7 @@ if(istype(user,/mob/living/carbon/human)) var/mob/living/carbon/human/H = user if(H.species.can_shred(H)) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed()) for(var/mob/M in viewers(src)) M.show_message("[user.name] smashed the light!", 3, "You hear a tinkle of breaking glass", 2) broken() diff --git a/code/modules/projectiles/ammunition/magazines.dm b/code/modules/projectiles/ammunition/magazines.dm index 342e10db840..9af8597c9ba 100644 --- a/code/modules/projectiles/ammunition/magazines.dm +++ b/code/modules/projectiles/ammunition/magazines.dm @@ -159,6 +159,34 @@ name = "ammo clip (.45 flash)" ammo_type = /obj/item/ammo_casing/a45f +/obj/item/ammo_magazine/s45 + name = "speedloader (.45)" + icon_state = "45s" + ammo_type = /obj/item/ammo_casing/a45 + matter = list(DEFAULT_WALL_MATERIAL = 525) //metal costs are very roughly based around 1 .45 casing = 75 metal + caliber = ".45" + max_ammo = 7 + multiple_sprites = 1 + +/obj/item/ammo_magazine/s45/empty + initial_ammo = 0 + +/obj/item/ammo_magazine/s45/rubber + name = "speedloader (.45 rubber)" + ammo_type = /obj/item/ammo_casing/a45r + +/obj/item/ammo_magazine/s45/practice + name = "speedloader (.45 practice)" + ammo_type = /obj/item/ammo_casing/a45p + +/obj/item/ammo_magazine/s45/flash + name = "speedloader (.45 flash)" + ammo_type = /obj/item/ammo_casing/a45f + +/obj/item/ammo_magazine/s45/ap + name = "speedloader (.45 AP)" + ammo_type = /obj/item/ammo_casing/a45ap + ///////// 9mm ///////// /obj/item/ammo_magazine/m9mm @@ -328,6 +356,14 @@ name = "extended magazine (5.45mm armor-piercing)" max_ammo = 30 +/obj/item/ammo_magazine/m545/hunter + name = "magazine (5.45mm hunting)" + ammo_type = /obj/item/ammo_casing/a545/hunter + +/obj/item/ammo_magazine/m545/hunter/ext + name = "extended magazine (5.45mm hunting)" + max_ammo = 30 + /obj/item/ammo_magazine/m545/small name = "reduced magazine (5.45mm)" icon_state = "m545-small" @@ -345,6 +381,10 @@ name = "magazine (5.45mm armor-piercing)" ammo_type = /obj/item/ammo_casing/a545/ap +/obj/item/ammo_magazine/m545/small/hunter + name = "magazine (5.45mm hunting)" + ammo_type = /obj/item/ammo_casing/a545/hunter + /obj/item/ammo_magazine/clip/c545 name = "ammo clip (5.45mm)" icon_state = "clip_rifle" @@ -358,6 +398,10 @@ name = "rifle clip (5.45mm armor-piercing)" ammo_type = /obj/item/ammo_casing/a545/ap +/obj/item/ammo_magazine/clip/c545/hunter + name = "rifle clip (5.45mm hunting)" + ammo_type = /obj/item/ammo_casing/a545/hunter + /obj/item/ammo_magazine/clip/c545/practice name = "rifle clip (5.45mm practice)" ammo_type = /obj/item/ammo_casing/a545 @@ -378,6 +422,10 @@ name = "magazine box (5.45mm armor-piercing)" ammo_type = /obj/item/ammo_casing/a545/ap +/obj/item/ammo_magazine/m545saw/hunter + name = "magazine box (5.45mm hunting)" + ammo_type = /obj/item/ammo_casing/a545/hunter + /obj/item/ammo_magazine/m545saw/empty initial_ammo = 0 @@ -477,6 +525,10 @@ name = "rifle clip (7.62mm practice)" ammo_type = /obj/item/ammo_casing/a762p +/obj/item/ammo_magazine/clip/c762/hunter + name = "rifle clip (7.62mm hunting)" + ammo_type = /obj/item/ammo_casing/a762/hunter + /obj/item/ammo_magazine/m762svd name = "\improper SVD magazine (7.62mm)" icon_state = "SVD" @@ -523,12 +575,12 @@ /obj/item/ammo_magazine/clip/c12g name = "ammo clip (12g slug)" - icon_state = "12gclipslug" //largely a codersprite, looks good enough. feel free to make a better one. + icon_state = "12gclipslug" // Still a placeholder sprite. Feel free to make a better one. desc = "A color-coded metal clip for holding and quickly loading shotgun shells. This one is loaded with slugs." caliber = "12g" ammo_type = /obj/item/ammo_casing/a12g - matter = list(DEFAULT_WALL_MATERIAL = 1790) // slugs shells x4 + 350 metal for the clip itself. - max_ammo = 4 + matter = list(DEFAULT_WALL_MATERIAL = 1070) // slugs shells x2 + 350 metal for the clip itself. + max_ammo = 2 multiple_sprites = 1 /obj/item/ammo_magazine/clip/c12g/pellet @@ -536,14 +588,14 @@ icon_state = "12gclipshell" desc = "A color-coded metal clip for holding and quickly loading shotgun shells. This one is loaded with buckshot." ammo_type = /obj/item/ammo_casing/a12g/pellet - matter = list(DEFAULT_WALL_MATERIAL = 1790) // buckshot and slugs cost the same + matter = list(DEFAULT_WALL_MATERIAL = 1070) // buckshot and slugs cost the same /obj/item/ammo_magazine/clip/c12g/beanbag name = "ammo clip (12g beanbag)" icon_state = "12gclipbean" desc = "A color-coded metal clip for holding and quickly loading shotgun shells. This one is loaded with beanbags." ammo_type = /obj/item/ammo_casing/a12g/beanbag - matter = list(DEFAULT_WALL_MATERIAL = 1070) //beanbags x4 + 350 metal + matter = list(DEFAULT_WALL_MATERIAL = 710) //beanbags x2 + 350 metal ///////// .75 Gyrojet ///////// diff --git a/code/modules/projectiles/ammunition/rounds.dm b/code/modules/projectiles/ammunition/rounds.dm index ed06df7cc26..330e11d89b2 100644 --- a/code/modules/projectiles/ammunition/rounds.dm +++ b/code/modules/projectiles/ammunition/rounds.dm @@ -258,6 +258,10 @@ desc = "A 7.62mm hollow-point bullet casing." projectile_type = /obj/item/projectile/bullet/rifle/a762/hollow +/obj/item/ammo_casing/a762/hunter + desc = "A 7.62mm hunting bullet casing." + projectile_type = /obj/item/projectile/bullet/rifle/a762/hunter + /* * 14.5mm (anti-materiel rifle round) */ @@ -298,6 +302,10 @@ desc = "A 5.45mm hollow-point bullet casing." projectile_type = /obj/item/projectile/bullet/rifle/a545/hollow +/obj/item/ammo_casing/a545/hunter + desc = "A 5.45mm hunting bullet casing." + projectile_type = /obj/item/projectile/bullet/rifle/a545/hunter + /* * Misc */ diff --git a/code/modules/projectiles/guns/energy.dm b/code/modules/projectiles/guns/energy.dm index 0bdf518a2cf..447eefe1b89 100644 --- a/code/modules/projectiles/guns/energy.dm +++ b/code/modules/projectiles/guns/energy.dm @@ -7,7 +7,7 @@ var/obj/item/weapon/cell/power_supply //What type of power cell this uses var/charge_cost = 240 //How much energy is needed to fire. - var/cell_type = null + var/cell_type = /obj/item/weapon/cell/device/weapon var/projectile_type = /obj/item/projectile/beam/practice var/modifystate var/charge_meter = 1 //if set, the icon state will be chosen based on the current charge @@ -34,12 +34,15 @@ /obj/item/weapon/gun/energy/New() ..() - if(cell_type) - power_supply = new cell_type(src) - else - power_supply = new /obj/item/weapon/cell/device/weapon(src) if(self_recharge) + power_supply = new /obj/item/weapon/cell/device/weapon(src) processing_objects.Add(src) + else + if(cell_type) + power_supply = new cell_type(src) + else + power_supply = null + update_icon() /obj/item/weapon/gun/energy/Destroy() diff --git a/code/modules/projectiles/guns/energy/laser.dm b/code/modules/projectiles/guns/energy/laser.dm index cb93992acc2..40e1f552770 100644 --- a/code/modules/projectiles/guns/energy/laser.dm +++ b/code/modules/projectiles/guns/energy/laser.dm @@ -52,6 +52,26 @@ self_recharge = 1 use_external_power = 1 +/obj/item/weapon/gun/energy/retro/empty + icon_state = "retro" + cell_type = null + + +/obj/item/weapon/gun/energy/alien + name = "alien pistol" + desc = "A weapon that works very similarly to a traditional energy weapon. How this came to be will likely be a mystery for the ages." + icon_state = "alienpistol" + item_state = "alienpistol" + fire_sound = 'sound/weapons/eLuger.ogg' + fire_delay = 10 // Handguns should be inferior to two-handed weapons. Even alien ones I suppose. + charge_cost = 480 // Five shots. + + projectile_type = /obj/item/projectile/beam/cyan + cell_type = /obj/item/weapon/cell/device/weapon/recharge/alien // Self charges. + origin_tech = list(TECH_COMBAT = 8, TECH_MAGNET = 7) + modifystate = "alienpistol" + + /obj/item/weapon/gun/energy/captain name = "antique laser gun" icon_state = "caplaser" @@ -65,9 +85,8 @@ origin_tech = null fire_delay = 10 //Old pistol charge_cost = 480 //to compensate a bit for self-recharging - self_recharge = 1 - recharge_time = 3 //Recharges a bit more quickly... - charge_delay = 100 //... but it takes a while to get started + cell_type = /obj/item/weapon/cell/device/weapon/recharge/captain + battery_lock = 1 /obj/item/weapon/gun/energy/lasercannon name = "laser cannon" @@ -87,7 +106,6 @@ accuracy = 3 charge_cost = 600 - /obj/item/weapon/gun/energy/lasercannon/mounted name = "mounted laser cannon" self_recharge = 1 @@ -145,10 +163,11 @@ item_state = "laser" desc = "Standard issue weapon of the Imperial Guard" origin_tech = list(TECH_COMBAT = 1, TECH_MAGNET = 2) - self_recharge = 1 matter = list(DEFAULT_WALL_MATERIAL = 2000) fire_sound = 'sound/weapons/Laser.ogg' projectile_type = /obj/item/projectile/beam/lastertag/blue + cell_type = /obj/item/weapon/cell/device/weapon/recharge + battery_lock = 1 var/required_vest /obj/item/weapon/gun/energy/lasertag/special_check(var/mob/living/carbon/human/M) diff --git a/code/modules/projectiles/guns/energy/nuclear.dm b/code/modules/projectiles/guns/energy/nuclear.dm index e7dd400f591..048dddfe3f9 100644 --- a/code/modules/projectiles/guns/energy/nuclear.dm +++ b/code/modules/projectiles/guns/energy/nuclear.dm @@ -56,7 +56,8 @@ force = 8 //looks heavier than a pistol w_class = ITEMSIZE_LARGE //Looks bigger than a pistol, too. fire_delay = 6 //This one's not a handgun, it should have the same fire delay as everything else - self_recharge = 1 + cell_type = /obj/item/weapon/cell/device/weapon/recharge + battery_lock = 1 modifystate = null // requires_two_hands = 1 diff --git a/code/modules/projectiles/guns/energy/special.dm b/code/modules/projectiles/guns/energy/special.dm index d613f1f2062..18a25e5daf3 100644 --- a/code/modules/projectiles/guns/energy/special.dm +++ b/code/modules/projectiles/guns/energy/special.dm @@ -43,7 +43,8 @@ projectile_type = /obj/item/projectile/energy/floramut origin_tech = list(TECH_MATERIAL = 2, TECH_BIO = 3, TECH_POWER = 3) modifystate = "floramut" - self_recharge = 1 + cell_type = /obj/item/weapon/cell/device/weapon/recharge + battery_lock = 1 var/decl/plantgene/gene = null firemodes = list( @@ -137,7 +138,8 @@ charge_cost = 480 projectile_type = /obj/item/projectile/change origin_tech = null - self_recharge = 1 + cell_type = /obj/item/weapon/cell/device/weapon/recharge + battery_lock = 1 charge_meter = 0 /obj/item/weapon/gun/energy/staff/special_check(var/mob/user) @@ -188,7 +190,8 @@ obj/item/weapon/gun/energy/staff/focus w_class = ITEMSIZE_HUGE charge_cost = 24 // 100 shots, it's a spray and pray (to RNGesus) weapon. projectile_type = /obj/item/projectile/energy/blue_pellet - self_recharge = 1 + cell_type = /obj/item/weapon/cell/device/weapon/recharge + battery_lock = 1 accuracy = 5 // Suppressive weapons don't work too well if there's no risk of being hit. burst_delay = 1 // Burst faster than average. origin_tech = list(TECH_COMBAT = 6, TECH_MAGNET = 6, TECH_ILLEGAL = 6) diff --git a/code/modules/projectiles/guns/energy/stun.dm b/code/modules/projectiles/guns/energy/stun.dm index c8bba190878..43bb9e16370 100644 --- a/code/modules/projectiles/guns/energy/stun.dm +++ b/code/modules/projectiles/guns/energy/stun.dm @@ -41,7 +41,8 @@ fire_sound = 'sound/weapons/Genhit.ogg' projectile_type = /obj/item/projectile/energy/bolt charge_cost = 480 - self_recharge = 1 + cell_type = /obj/item/weapon/cell/device/weapon/recharge + battery_lock = 1 charge_meter = 0 /obj/item/weapon/gun/energy/crossbow/ninja diff --git a/code/modules/projectiles/guns/projectile/boltaction.dm b/code/modules/projectiles/guns/projectile/boltaction.dm index 89165243449..bb6d14d1ee0 100644 --- a/code/modules/projectiles/guns/projectile/boltaction.dm +++ b/code/modules/projectiles/guns/projectile/boltaction.dm @@ -20,16 +20,12 @@ /obj/item/weapon/gun/projectile/shotgun/pump/rifle/ceremonial name = "ceremonial bolt-action rifle" desc = "A bolt-action rifle with a heavy, high-quality wood stock that has a beautiful finish. Clearly not intended to be used in combat. Uses 7.62mm rounds." + icon_state = "boltaction_c" + item_state = "boltaction_c" ammo_type = /obj/item/ammo_casing/a762/blank -/obj/item/weapon/gun/projectile/shotgun/pump/rifle/mosin - name = "\improper Mosin Nagant" - desc = "Despite its age, the Mosin Nagant continues to be a favorite weapon among colonists, conscripts, and militias across the cosmos. Most today are built by Chen-Iltchenko Firearms, but it's hard to say who built this particular gun, considering the design has been ripped off by just about every arms manufacturer in the galaxy. Uses 7.62mm rounds." - icon_state = "mosin" - item_state = "mosin" - // Stole hacky terrible code from doublebarrel shotgun. -Spades -/obj/item/weapon/gun/projectile/shotgun/pump/rifle/mosin/attackby(var/obj/item/A as obj, mob/user as mob) +/obj/item/weapon/gun/projectile/shotgun/pump/rifle/ceremonial/attackby(var/obj/item/A as obj, mob/user as mob) if(istype(A, /obj/item/weapon/surgical/circular_saw) || istype(A, /obj/item/weapon/melee/energy) || istype(A, /obj/item/weapon/pickaxe/plasmacutter) && w_class != ITEMSIZE_NORMAL) user << "You begin to shorten the barrel and stock of \the [src]." if(loaded.len) @@ -38,16 +34,16 @@ user.visible_message("[src] goes off!", "The rifle goes off in your face!") return if(do_after(user, 30)) - icon_state = "obrez" + icon_state = "sawnrifle" w_class = ITEMSIZE_NORMAL recoil = 2 // Owch accuracy = -1 // You know damn well why. item_state = "gun" slot_flags &= ~SLOT_BACK //you can't sling it on your back slot_flags |= (SLOT_BELT|SLOT_HOLSTER) //but you can wear it on your belt (poorly concealed under a trenchcoat, ideally) - or in a holster, why not. - name = "\improper Obrez" - desc = "The firepower of a Mosin, now the size of a pistol, with an effective combat range of about three feet. Uses 7.62mm rounds." - user << "You shorten the barrel and stock of \the [src]!" + name = "sawn-off rifle" + desc = "The firepower of a rifle, now the size of a pistol, with an effective combat range of about three feet. Uses 7.62mm rounds." + to_chat(user, "You shorten the barrel and stock of \the [src]!") else ..() diff --git a/code/modules/projectiles/guns/projectile/pistol.dm b/code/modules/projectiles/guns/projectile/pistol.dm index e545ebb8485..9a9f0b4bd69 100644 --- a/code/modules/projectiles/guns/projectile/pistol.dm +++ b/code/modules/projectiles/guns/projectile/pistol.dm @@ -23,7 +23,7 @@ icon_state = "[initial(icon_state)]-e" /obj/item/weapon/gun/projectile/colt/detective - desc = "A Martian recreation of an old Terran pistol. Uses .45 rounds." + desc = "A Martian recreation of an old pistol. Uses .45 rounds." magazine_type = /obj/item/ammo_magazine/m45/rubber /obj/item/weapon/gun/projectile/colt/detective/verb/rename_gun() @@ -60,7 +60,8 @@ options["H&K VP"] = "VP78" options["P08 Luger"] = "p08" options["P08 Luger, Brown"] = "p08b" - var/choice = input(M,"What do you want the gun's sprite to be?","Resprite Gun") in options + options["Glock 37"] = "enforcer_black" + var/choice = input(M,"Choose your sprite!","Resprite Gun") in options if(src && choice && !M.stat && in_range(M,src)) icon_state = options[choice] unique_reskin = options[choice] diff --git a/code/modules/projectiles/guns/projectile/revolver.dm b/code/modules/projectiles/guns/projectile/revolver.dm index 81355d10314..20671d6fd58 100644 --- a/code/modules/projectiles/guns/projectile/revolver.dm +++ b/code/modules/projectiles/guns/projectile/revolver.dm @@ -66,6 +66,58 @@ M << "You name the gun [input]. Say hello to your new friend." return 1 +/obj/item/weapon/gun/projectile/revolver/detective45 + name = ".45 revolver" + desc = "A fancy replica of an old revolver, modified for .45 rounds and a seven-shot cylinder." + icon_state = "detective" + caliber = ".45" + origin_tech = list(TECH_COMBAT = 2, TECH_MATERIAL = 2) + fire_sound = 'sound/weapons/gunshot_heavy.ogg' + ammo_type = /obj/item/ammo_casing/a45r + max_shells = 7 + + +obj/item/weapon/gun/projectile/revolver/detective45/verb/rename_gun() + set name = "Name Gun" + set category = "Object" + set desc = "Rename your gun. If you're the Detective." + + var/mob/M = usr + if(!M.mind) return 0 + var/job = M.mind.assigned_role + if(job != "Detective") + M << "You don't feel cool enough to name this gun, chump." + return 0 + + var/input = sanitizeSafe(input("What do you want to name the gun?", ,""), MAX_NAME_LEN) + + if(src && input && !M.stat && in_range(M,src)) + name = input + M << "You name the gun [input]. Say hello to your new friend." + return 1 + +/obj/item/weapon/gun/projectile/revolver/detective45/verb/reskin_gun() + set name = "Resprite gun" + set category = "Object" + set desc = "Click to choose a sprite for your gun." + + var/mob/M = usr + var/list/options = list() + options["Colt Detective Special"] = "detective" + options["Ruger GP100"] = "GP100" + options["Colt Single Action Army"] = "detective_peacemaker" + options["Colt Single Action Army, Dark"] = "detective_peacemaker_dark" + options["H&K PT"] = "detective_panther" + options["Vintage LeMat"] = "lemat_old" + options["Webley MKVI "] = "webley" + var/choice = input(M,"Choose your sprite!","Resprite Gun") in options + if(src && choice && !M.stat && in_range(M,src)) + icon_state = options[choice] + M << "Your gun is now sprited as [choice]. Say hello to your new friend." + return 1 + + + // Blade Runner pistol. /obj/item/weapon/gun/projectile/revolver/deckard name = "\improper Deckard .38" diff --git a/code/modules/projectiles/guns/vox.dm b/code/modules/projectiles/guns/vox.dm index d3a846ab08f..ecc8a1a9047 100644 --- a/code/modules/projectiles/guns/vox.dm +++ b/code/modules/projectiles/guns/vox.dm @@ -60,7 +60,8 @@ w_class = ITEMSIZE_HUGE charge_cost = 300 projectile_type = /obj/item/projectile/beam/stun/darkmatter - self_recharge = 1 + cell_type = /obj/item/weapon/cell/device/weapon/recharge + battery_lock = 1 accuracy = 2 firemodes = list( @@ -85,7 +86,7 @@ /obj/item/projectile/beam/darkmatter name = "dark matter bolt" icon_state = "darkb" - damage = 60 + damage = 35 armor_penetration = 35 damage_type = BRUTE check_armour = "energy" @@ -118,7 +119,8 @@ item_state = "noise" fire_sound = 'sound/effects/basscannon.ogg' w_class = ITEMSIZE_HUGE - self_recharge = 1 + cell_type = /obj/item/weapon/cell/device/weapon/recharge + battery_lock = 1 charge_cost = 600 projectile_type=/obj/item/projectile/sonic/weak diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index fdc5a445b98..2040b0a7784 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -38,6 +38,8 @@ var/damage = 10 var/damage_type = BRUTE //BRUTE, BURN, TOX, OXY, CLONE, HALLOSS are the only things that should be in here + var/SA_bonus_damage = 0 // Some bullets inflict extra damage on simple animals. + var/SA_vulnerability = null // What kind of simple animal the above bonus damage should be applied to. Set to null to apply to all SAs. var/nodamage = 0 //Determines if the projectile will skip any damage inflictions var/taser_effect = 0 //If set then the projectile will apply it's agony damage using stun_effect_act() to mobs it hits, and other damage will be ignored var/check_armour = "bullet" //Defines what armor to use when it hits things. Must be set to bullet, laser, energy,or bomb //Cael - bio and rad are also valid diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm index a271684f7cc..32dce8e3b9e 100644 --- a/code/modules/projectiles/projectile/beams.dm +++ b/code/modules/projectiles/projectile/beams.dm @@ -70,6 +70,16 @@ tracer_type = /obj/effect/projectile/xray/tracer impact_type = /obj/effect/projectile/xray/impact +/obj/item/projectile/beam/cyan + name = "cyan beam" + icon_state = "cyan" + damage = 40 + light_color = "#00C6FF" + + muzzle_type = /obj/effect/projectile/laser_omni/muzzle + tracer_type = /obj/effect/projectile/laser_omni/tracer + impact_type = /obj/effect/projectile/laser_omni/impact + /obj/item/projectile/beam/pulse name = "pulse" icon_state = "u_laser" diff --git a/code/modules/projectiles/projectile/bullets.dm b/code/modules/projectiles/projectile/bullets.dm index 283e487272b..a7132fa43ba 100644 --- a/code/modules/projectiles/projectile/bullets.dm +++ b/code/modules/projectiles/projectile/bullets.dm @@ -209,6 +209,11 @@ armor_penetration = -50 penetrating = 0 +/obj/item/projectile/bullet/rifle/a762/hunter // Optimized for killing simple animals and not people, because Balance. + damage = 20 + SA_bonus_damage = 50 // 70 total on animals. + SA_vulnerability = SA_ANIMAL + /obj/item/projectile/bullet/rifle/a545 damage = 25 @@ -221,6 +226,11 @@ armor_penetration = -50 penetrating = 0 +/obj/item/projectile/bullet/rifle/a545/hunter + damage = 15 + SA_bonus_damage = 35 // 50 total on animals. + SA_vulnerability = SA_ANIMAL + /obj/item/projectile/bullet/rifle/a145 damage = 80 stun = 3 diff --git a/code/modules/projectiles/projectile/special.dm b/code/modules/projectiles/projectile/special.dm index 049bdcaf783..8c5d2cd11aa 100644 --- a/code/modules/projectiles/projectile/special.dm +++ b/code/modules/projectiles/projectile/special.dm @@ -11,7 +11,7 @@ var/pulse_range = 1 - on_hit(var/atom/target, var/blocked = 0) +/obj/item/projectile/ion/on_hit(var/atom/target, var/blocked = 0) empulse(target, pulse_range, pulse_range, pulse_range, pulse_range) return 1 @@ -26,7 +26,7 @@ sharp = 1 edge = 1 - on_hit(var/atom/target, var/blocked = 0) +/obj/item/projectile/bullet/gyro/on_hit(var/atom/target, var/blocked = 0) explosion(target, -1, 0, 2) return 1 @@ -81,26 +81,26 @@ nodamage = 1 check_armour = "bullet" - Bump(atom/A as mob|obj|turf|area) - if(A == firer) - loc = A.loc - return +/obj/item/projectile/meteor/Bump(atom/A as mob|obj|turf|area) + if(A == firer) + loc = A.loc + return - sleep(-1) //Might not be important enough for a sleep(-1) but the sleep/spawn itself is necessary thanks to explosions and metoerhits + sleep(-1) //Might not be important enough for a sleep(-1) but the sleep/spawn itself is necessary thanks to explosions and metoerhits - if(src)//Do not add to this if() statement, otherwise the meteor won't delete them - if(A) + if(src)//Do not add to this if() statement, otherwise the meteor won't delete them + if(A) - A.ex_act(2) - playsound(src.loc, 'sound/effects/meteorimpact.ogg', 40, 1) + A.ex_act(2) + playsound(src.loc, 'sound/effects/meteorimpact.ogg', 40, 1) - for(var/mob/M in range(10, src)) - if(!M.stat && !istype(M, /mob/living/silicon/ai))\ - shake_camera(M, 3, 1) - qdel(src) - return 1 - else - return 0 + for(var/mob/M in range(10, src)) + if(!M.stat && !istype(M, /mob/living/silicon/ai))\ + shake_camera(M, 3, 1) + qdel(src) + return 1 + else + return 0 /obj/item/projectile/energy/floramut name = "alpha somatoray" @@ -113,36 +113,36 @@ light_power = 0.5 light_color = "#33CC00" - on_hit(var/atom/target, var/blocked = 0) - var/mob/living/M = target - if(ishuman(target)) - var/mob/living/carbon/human/H = M - if((H.species.flags & IS_PLANT) && (M.nutrition < 500)) - if(prob(15)) - M.apply_effect((rand(30,80)),IRRADIATE) - M.Weaken(5) - for (var/mob/V in viewers(src)) - V.show_message("[M] writhes in pain as \his vacuoles boil.", 3, "You hear the crunching of leaves.", 2) - if(prob(35)) - // for (var/mob/V in viewers(src)) //Public messages commented out to prevent possible metaish genetics experimentation and stuff. - Cheridan - // V.show_message("[M] is mutated by the radiation beam.", 3, " You hear the snapping of twigs.", 2) - if(prob(80)) - randmutb(M) - domutcheck(M,null) - else - randmutg(M) - domutcheck(M,null) +/obj/item/projectile/energy/floramut/on_hit(var/atom/target, var/blocked = 0) + var/mob/living/M = target + if(ishuman(target)) + var/mob/living/carbon/human/H = M + if((H.species.flags & IS_PLANT) && (M.nutrition < 500)) + if(prob(15)) + M.apply_effect((rand(30,80)),IRRADIATE) + M.Weaken(5) + for (var/mob/V in viewers(src)) + V.show_message("[M] writhes in pain as \his vacuoles boil.", 3, "You hear the crunching of leaves.", 2) + if(prob(35)) + // for (var/mob/V in viewers(src)) //Public messages commented out to prevent possible metaish genetics experimentation and stuff. - Cheridan + // V.show_message("[M] is mutated by the radiation beam.", 3, " You hear the snapping of twigs.", 2) + if(prob(80)) + randmutb(M) + domutcheck(M,null) else - M.adjustFireLoss(rand(5,15)) - M.show_message("The radiation beam singes you!") - // for (var/mob/V in viewers(src)) - // V.show_message("[M] is singed by the radiation beam.", 3, " You hear the crackle of burning leaves.", 2) - else if(istype(target, /mob/living/carbon/)) - // for (var/mob/V in viewers(src)) - // V.show_message("The radiation beam dissipates harmlessly through [M]", 3) - M.show_message("The radiation beam dissipates harmlessly through your body.") - else - return 1 + randmutg(M) + domutcheck(M,null) + else + M.adjustFireLoss(rand(5,15)) + M.show_message("The radiation beam singes you!") + // for (var/mob/V in viewers(src)) + // V.show_message("[M] is singed by the radiation beam.", 3, " You hear the crackle of burning leaves.", 2) + else if(istype(target, /mob/living/carbon/)) + // for (var/mob/V in viewers(src)) + // V.show_message("The radiation beam dissipates harmlessly through [M]", 3) + M.show_message("The radiation beam dissipates harmlessly through your body.") + else + return 1 /obj/item/projectile/energy/floramut/gene name = "gamma somatoray" @@ -164,25 +164,25 @@ light_power = 0.5 light_color = "#FFFFFF" - on_hit(var/atom/target, var/blocked = 0) - var/mob/M = target - if(ishuman(target)) //These rays make plantmen fat. - var/mob/living/carbon/human/H = M - if((H.species.flags & IS_PLANT) && (M.nutrition < 500)) - M.nutrition += 30 - else if (istype(target, /mob/living/carbon/)) - M.show_message("The radiation beam dissipates harmlessly through your body.") - else - return 1 +/obj/item/projectile/energy/florayield/on_hit(var/atom/target, var/blocked = 0) + var/mob/M = target + if(ishuman(target)) //These rays make plantmen fat. + var/mob/living/carbon/human/H = M + if((H.species.flags & IS_PLANT) && (M.nutrition < 500)) + M.nutrition += 30 + else if (istype(target, /mob/living/carbon/)) + M.show_message("The radiation beam dissipates harmlessly through your body.") + else + return 1 /obj/item/projectile/beam/mindflayer name = "flayer ray" - on_hit(var/atom/target, var/blocked = 0) - if(ishuman(target)) - var/mob/living/carbon/human/M = target - M.Confuse(rand(5,8)) +/obj/item/projectile/beam/mindflayer/on_hit(var/atom/target, var/blocked = 0) + if(ishuman(target)) + var/mob/living/carbon/human/M = target + M.Confuse(rand(5,8)) /obj/item/projectile/chameleon name = "bullet" @@ -192,3 +192,36 @@ nodamage = 1 damage_type = HALLOSS muzzle_type = /obj/effect/projectile/bullet/muzzle + +/obj/item/projectile/bola + name = "bola" + icon_state = "bola" + damage = 5 + embed_chance = 0 //Nada. + damage_type = HALLOSS + muzzle_type = null + +/obj/item/projectile/bola/on_hit(var/atom/target, var/blocked = 0) + if(ishuman(target)) + var/mob/living/carbon/human/M = target + var/obj/item/weapon/handcuffs/legcuffs/bola/B = new(src.loc) + if(!B.place_legcuffs(M,firer)) + if(B) + qdel(B) + ..() + +/obj/item/projectile/webball + name = "ball of web" + icon_state = "bola" + damage = 10 + embed_chance = 0 //Nada. + damage_type = BRUTE + muzzle_type = null + +/obj/item/projectile/webball/on_hit(var/atom/target, var/blocked = 0) + if(isturf(target.loc)) + var/obj/effect/spider/stickyweb/W = locate() in get_turf(target) + if(!W && prob(75)) + visible_message("\The [src] splatters a layer of web on \the [target]!") + new /obj/effect/spider/stickyweb(target.loc) + ..() diff --git a/code/modules/random_map/automata/caves.dm b/code/modules/random_map/automata/caves.dm index 4868e6d0684..e1f2092bdb9 100644 --- a/code/modules/random_map/automata/caves.dm +++ b/code/modules/random_map/automata/caves.dm @@ -2,6 +2,10 @@ iterations = 5 descriptor = "moon caves" var/list/ore_turfs = list() + var/make_cracked_turfs = TRUE + +/datum/random_map/automata/cave_system/no_cracks + make_cracked_turfs = FALSE /datum/random_map/automata/cave_system/get_appropriate_path(var/value) return @@ -47,7 +51,7 @@ if(map[current_cell] == FLOOR_CHAR) if(prob(90)) T.make_floor() - else + else if(make_cracked_turfs) T.ChangeTurf(/turf/space/cracked_asteroid) else T.make_wall() diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Core.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Core.dm index 9fedfc481b0..53c7bd0e53a 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Core.dm +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Core.dm @@ -9,6 +9,7 @@ mrate_static = TRUE affects_dead = 1 //so you can pump blood into someone before defibbing them color = "#C80000" + var/volume_mod = 1 // So if you add different subtypes of blood, you can affect how much vessel blood each unit of reagent adds glass_name = "tomato juice" glass_desc = "Are you sure this is tomato juice?" @@ -69,9 +70,21 @@ M.antibodies |= data["antibodies"] /datum/reagent/blood/affect_blood(var/mob/living/carbon/M, var/alien, var/removed) - M.inject_blood(src, volume) + M.inject_blood(src, volume * volume_mod) remove_self(volume) +/datum/reagent/blood/synthblood + name = "Synthetic blood" + id = "synthblood" + color = "#999966" + volume_mod = 2 + +/datum/reagent/blood/synthblood/initialize_data(var/newdata) + ..() + if(data && !data["blood_type"]) + data["blood_type"] = "O-" + return + // pure concentrated antibodies /datum/reagent/antibodies data = list("antibodies"=list()) diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm index c71a7de362d..aced9105d7a 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" @@ -313,11 +356,11 @@ if(alien == IS_SKRELL) M.take_organ_damage(2.4 * removed, 0) if(M.losebreath < 10) - M.losebreath++ + M.AdjustLosebreath(1) else M.take_organ_damage(3 * removed, 0) if(M.losebreath < 15) - M.losebreath++ + M.AdjustLosebreath(1) /datum/reagent/mutagen name = "Unstable mutagen" @@ -481,7 +524,7 @@ /datum/reagent/chloralhydrate/overdose(var/mob/living/carbon/M, var/alien, var/removed) ..() - M.losebreath = (min(M.losebreath + 1, 10)) + M.SetLosebreath(10) M.adjustOxyLoss(removed * overdose_mod) /datum/reagent/chloralhydrate/beer2 //disguised as normal beer for use by emagged brobots @@ -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.dm b/code/modules/reagents/reagent_containers.dm index 6721cbd3bbc..fc89bab93da 100644 --- a/code/modules/reagents/reagent_containers.dm +++ b/code/modules/reagents/reagent_containers.dm @@ -101,7 +101,7 @@ user << "\The [blocked] is in the way!" return - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) //puts a limit on how fast people can eat/drink things + user.setClickCooldown(user.get_attack_speed(src)) //puts a limit on how fast people can eat/drink things self_feed_message(user) reagents.trans_to_mob(user, issmall(user) ? ceil(amount_per_transfer_from_this/2) : amount_per_transfer_from_this, CHEM_INGEST) feed_sound(user) @@ -119,7 +119,7 @@ other_feed_message_start(user, target) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(src)) if(!do_mob(user, target)) return diff --git a/code/modules/reagents/reagent_containers/borghydro.dm b/code/modules/reagents/reagent_containers/borghydro.dm index d0cd3cf9e60..c61a7241bb0 100644 --- a/code/modules/reagents/reagent_containers/borghydro.dm +++ b/code/modules/reagents/reagent_containers/borghydro.dm @@ -32,7 +32,7 @@ desc = "An advanced nanite and chemical synthesizer and injection system, designed for heavy-duty medical equipment. This type is capable of safely bypassing \ thick materials that other hyposprays would struggle with." bypass_protection = TRUE // Because mercs tend to be in spacesuits. - reagent_ids = list("healing_nanites", "hyperzine", "tramadol", "oxycodone", "spaceacillin", "peridaxon", "osteodaxon", "myelamine") + reagent_ids = list("healing_nanites", "hyperzine", "tramadol", "oxycodone", "spaceacillin", "peridaxon", "osteodaxon", "myelamine", "synthblood") /obj/item/weapon/reagent_containers/borghypo/New() ..() diff --git a/code/modules/reagents/reagent_containers/food/snacks.dm b/code/modules/reagents/reagent_containers/food/snacks.dm index c49c76be01c..100aa43165d 100644 --- a/code/modules/reagents/reagent_containers/food/snacks.dm +++ b/code/modules/reagents/reagent_containers/food/snacks.dm @@ -68,7 +68,7 @@ user << "\The [blocked] is in the way!" return - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) //puts a limit on how fast people can eat/drink things + user.setClickCooldown(user.get_attack_speed(src)) //puts a limit on how fast people can eat/drink things if (fullness <= 50) M << "You hungrily chew out a piece of [src] and gobble it!" if (fullness > 50 && fullness <= 150) @@ -101,7 +101,7 @@ user.visible_message("[user] cannot force anymore of [src] down [M]'s throat.") return 0 - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(src)) if(!do_mob(user, M)) return M.attack_log += text("\[[time_stamp()]\] Has been fed [src.name] by [user.name] ([user.ckey]) Reagents: [reagentlist(src)]") diff --git a/code/modules/reagents/reagent_containers/glass.dm b/code/modules/reagents/reagent_containers/glass.dm index 44dce0a7ad2..dbc6f17a5d6 100644 --- a/code/modules/reagents/reagent_containers/glass.dm +++ b/code/modules/reagents/reagent_containers/glass.dm @@ -54,62 +54,72 @@ if(!..(user, 2)) return if(reagents && reagents.reagent_list.len) - user << "It contains [reagents.total_volume] units of liquid." + to_chat(user, "It contains [reagents.total_volume] units of liquid.") else - user << "It is empty." + to_chat(user, "It is empty.") if(!is_open_container()) - user << "Airtight lid seals it completely." + to_chat(user, "Airtight lid seals it completely.") /obj/item/weapon/reagent_containers/glass/attack_self() ..() if(is_open_container()) - usr << "You put the lid on \the [src]." + to_chat(usr, "You put the lid on \the [src].") flags ^= OPENCONTAINER else - usr << "You take the lid off \the [src]." + to_chat(usr, "You take the lid off \the [src].") flags |= OPENCONTAINER update_icon() -/obj/item/weapon/reagent_containers/glass/do_surgery(mob/living/carbon/M, mob/living/user) - if(user.a_intent != I_HELP) //in case it is ever used as a surgery tool - return ..() - afterattack(M, user, 1) - return 1 +/obj/item/weapon/reagent_containers/glass/attack(mob/M as mob, mob/user as mob, def_zone) + if(force && !(flags & NOBLUDGEON) && user.a_intent == I_HURT) + return ..() + + if(standard_feed_mob(user, M)) + return + + return 0 + +/obj/item/weapon/reagent_containers/glass/standard_feed_mob(var/mob/user, var/mob/target) + if(!is_open_container()) + to_chat(user, "You need to open \the [src] first.") + return 1 + if(user.a_intent == I_HURT) + return 1 + return ..() + +/obj/item/weapon/reagent_containers/glass/self_feed_message(var/mob/user) + to_chat(user, "You swallow a gulp from \the [src].") /obj/item/weapon/reagent_containers/glass/afterattack(var/obj/target, var/mob/user, var/proximity) - if(!is_open_container() || !proximity) //Is the container open & are they next to whatever they're clicking? - return //If not, do nothing. - + return 1 //If not, do nothing. for(var/type in can_be_placed_into) //Is it something it can be placed into? if(istype(target, type)) - return - + return 1 if(standard_dispenser_refill(user, target)) //Are they clicking a water tank/some dispenser? - return - + return 1 if(standard_pour_into(user, target)) //Pouring into another beaker? return - - if(user.a_intent == I_HURT) //Harm intent? - if(standard_splash_mob(user, target)) //If harm intent and can splash a mob, go ahead. - return - if(reagents && reagents.total_volume) //Otherwise? Splash the floor. - user << "You splash the solution onto [target]." + if(user.a_intent == I_HURT) + if(standard_splash_mob(user,target)) + return 1 + if(reagents && reagents.total_volume) + to_chat(user, "You splash the solution onto [target].") //They are on harm intent, aka wanting to spill it. reagents.splash(target, reagents.total_volume) - return + return 1 + ..() /obj/item/weapon/reagent_containers/glass/attackby(obj/item/weapon/W as obj, mob/user as mob) if(istype(W, /obj/item/weapon/pen) || istype(W, /obj/item/device/flashlight/pen)) var/tmp_label = sanitizeSafe(input(user, "Enter a label for [name]", "Label", label_text), MAX_NAME_LEN) if(length(tmp_label) > 50) - user << "The label can be at most 50 characters long." + to_chat(user, "The label can be at most 50 characters long.") else if(length(tmp_label) > 10) - user << "You set the label." + to_chat(user, "You set the label.") label_text = tmp_label update_name_label() else - user << "You set the label to \"[tmp_label]\"." + to_chat(user, "You set the label to \"[tmp_label]\".") label_text = tmp_label update_name_label() if(istype(W,/obj/item/weapon/storage/bag)) @@ -210,6 +220,7 @@ icon_state = "vial" matter = list("glass" = 250) volume = 30 + w_class = ITEMSIZE_TINY amount_per_transfer_from_this = 10 possible_transfer_amounts = list(5,10,15,25) flags = OPENCONTAINER @@ -254,10 +265,10 @@ return else if(istype(D, /obj/item/weapon/mop)) if(reagents.total_volume < 1) - user << "\The [src] is empty!" + to_chat(user, "\The [src] is empty!") else reagents.trans_to_obj(D, 5) - user << "You wet \the [D] in \the [src]." + to_chat(user, "You wet \the [D] in \the [src].") playsound(loc, 'sound/effects/slosh.ogg', 25, 1) return else @@ -295,10 +306,10 @@ obj/item/weapon/reagent_containers/glass/bucket/wood return else if(istype(D, /obj/item/weapon/mop)) if(reagents.total_volume < 1) - user << "\The [src] is empty!" + to_chat(user, "\The [src] is empty!") else reagents.trans_to_obj(D, 5) - user << "You wet \the [D] in \the [src]." + to_chat(user, "You wet \the [D] in \the [src].") playsound(loc, 'sound/effects/slosh.ogg', 25, 1) return else diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm index 5c5d0cc3a6a..604eaa6a3a6 100644 --- a/code/modules/reagents/reagent_containers/hypospray.dm +++ b/code/modules/reagents/reagent_containers/hypospray.dm @@ -60,7 +60,57 @@ used = !used return +//A vial-loaded hypospray. Cartridge-based! +/obj/item/weapon/reagent_containers/hypospray/vial + name = "hypospray mkII" + desc = "A new development from DeForest Medical, this new hypospray takes 30-unit vials as the drug supply for easy swapping." + var/obj/item/weapon/reagent_containers/glass/beaker/vial/loaded_vial //Wow, what a name. + volume = 0 +/obj/item/weapon/reagent_containers/hypospray/vial/New() + ..() + loaded_vial = new /obj/item/weapon/reagent_containers/glass/beaker/vial(src) //Comes with an empty vial + volume = loaded_vial.volume + reagents.maximum_volume = loaded_vial.reagents.maximum_volume + +/obj/item/weapon/reagent_containers/hypospray/vial/attack_hand(mob/user as mob) + if(user.get_inactive_hand() == src) + if(loaded_vial) + reagents.trans_to_holder(loaded_vial.reagents,volume) + reagents.maximum_volume = 0 + loaded_vial.update_icon() + user.put_in_hands(loaded_vial) + loaded_vial = null + user << "You remove the vial from the [src]." + update_icon() + playsound(src.loc, 'sound/weapons/flipblade.ogg', 50, 1) + return + ..() + else + return ..() + +/obj/item/weapon/reagent_containers/hypospray/vial/attackby(obj/item/weapon/W, mob/user as mob) + if(istype(W, /obj/item/weapon/reagent_containers/glass/beaker/vial)) + if(!loaded_vial) + user.visible_message("[user] begins loading [W] into \the [src].","You start loading [W] into \the [src].") + if(!do_after(user,30) || loaded_vial || !(W in user)) + return 0 + if(W.is_open_container()) + W.flags ^= OPENCONTAINER + W.update_icon() + user.drop_item() + W.loc = src + loaded_vial = W + reagents.maximum_volume = loaded_vial.reagents.maximum_volume + loaded_vial.reagents.trans_to_holder(reagents,volume) + user.visible_message("[user] has loaded [W] into \the [src].","You have loaded [W] into \the [src].") + update_icon() + playsound(src.loc, 'sound/weapons/empty.ogg', 50, 1) + else + user << "\The [src] already has a vial." + else + ..() + /obj/item/weapon/reagent_containers/hypospray/autoinjector name = "autoinjector" desc = "A rapid and safe way to administer small amounts of drugs by untrained or trained personnel." diff --git a/code/modules/reagents/reagent_containers/pill.dm b/code/modules/reagents/reagent_containers/pill.dm index e21baa48e26..bc83d8c9cfb 100644 --- a/code/modules/reagents/reagent_containers/pill.dm +++ b/code/modules/reagents/reagent_containers/pill.dm @@ -51,7 +51,7 @@ user.visible_message("[user] attempts to force [M] to swallow \the [src].") - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(src)) if(!do_mob(user, M)) return diff --git a/code/modules/reagents/reagent_dispenser.dm b/code/modules/reagents/reagent_dispenser.dm index 17b17864496..86f16d4cb7a 100644 --- a/code/modules/reagents/reagent_dispenser.dm +++ b/code/modules/reagents/reagent_dispenser.dm @@ -77,6 +77,13 @@ ..() reagents.add_reagent("water",1000) +/obj/structure/reagent_dispensers/watertank/high/New() + name = "high-capacity water tank" + desc = "A highly-pressurized water tank made to hold vast amounts of water.." + icon_state = "watertank_high" + ..() + reagents.add_reagent("water",4000) + /obj/structure/reagent_dispensers/fueltank name = "fueltank" desc = "A fueltank." diff --git a/code/modules/research/designs.dm b/code/modules/research/designs.dm index 708cc4e0810..6ed6016d285 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) @@ -302,7 +302,7 @@ other types of metals and chemistry for reagents). build_path = /obj/item/clothing/glasses/hud/security sort_string = "GAAAB" -/datum/design/item/mesons +/datum/design/item/hud/mesons name = "Optical meson scanners design" desc = "Using the meson-scanning technology those glasses allow you to see through walls, floor or anything else." id = "mesons" @@ -437,7 +437,7 @@ other types of metals and chemistry for reagents). build_path = /obj/item/stack/nanopaste sort_string = "MBAAA" -/datum/design/item/scalpel_laser1 +/datum/design/item/medical/scalpel_laser1 name = "Basic Laser Scalpel" desc = "A scalpel augmented with a directed laser, for more precise cutting without blood entering the field. This one looks basic and could be improved." id = "scalpel_laser1" @@ -446,7 +446,7 @@ other types of metals and chemistry for reagents). build_path = /obj/item/weapon/surgical/scalpel/laser1 sort_string = "MBBAA" -/datum/design/item/scalpel_laser2 +/datum/design/item/medical/scalpel_laser2 name = "Improved Laser Scalpel" desc = "A scalpel augmented with a directed laser, for more precise cutting without blood entering the field. This one looks somewhat advanced." id = "scalpel_laser2" @@ -455,7 +455,7 @@ other types of metals and chemistry for reagents). build_path = /obj/item/weapon/surgical/scalpel/laser2 sort_string = "MBBAB" -/datum/design/item/scalpel_laser3 +/datum/design/item/medical/scalpel_laser3 name = "Advanced Laser Scalpel" desc = "A scalpel augmented with a directed laser, for more precise cutting without blood entering the field. This one looks to be the pinnacle of precision energy cutlery!" id = "scalpel_laser3" @@ -464,7 +464,7 @@ other types of metals and chemistry for reagents). build_path = /obj/item/weapon/surgical/scalpel/laser3 sort_string = "MBBAC" -/datum/design/item/scalpel_manager +/datum/design/item/medical/scalpel_manager name = "Incision Management System" desc = "A true extension of the surgeon's body, this marvel instantly and completely prepares an incision allowing for the immediate commencement of therapeutic steps." id = "scalpel_manager" @@ -473,7 +473,7 @@ other types of metals and chemistry for reagents). build_path = /obj/item/weapon/surgical/scalpel/manager sort_string = "MBBAD" -/datum/design/item/bone_clamp +/datum/design/item/medical/bone_clamp name = "Bone Clamp" desc = "A miracle of modern science, this tool rapidly knits together bone, without the need for bone gel." id = "bone_clamp" @@ -482,6 +482,15 @@ other types of metals and chemistry for reagents). build_path = /obj/item/weapon/surgical/bone_clamp sort_string = "MBBAE" +/datum/design/item/medical/advanced_roller + name = "advanced roller bed" + desc = "A more advanced version of the regular roller bed, with inbuilt surgical stabilisers and an improved folding system." + id = "roller_bed" + req_tech = list(TECH_BIO = 3, TECH_MATERIAL = 3, TECH_MAGNET = 3) + materials = list(DEFAULT_WALL_MATERIAL = 4000, "glass" = 2000, "phoron" = 2000) + build_path = /obj/item/roller/adv + sort_string = "MBBAF" + /datum/design/item/implant materials = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50) @@ -742,6 +751,14 @@ other types of metals and chemistry for reagents). build_path = /obj/item/device/paicard sort_string = "VABAI" +/datum/design/item/communicator + name = "Communcator" + id = "communicator" + req_tech = list(TECH_DATA = 2, TECH_MAGNET = 2) + materials = list(DEFAULT_WALL_MATERIAL = 500, "glass" = 500) + build_path = /obj/item/device/communicator + sort_string = "VABAJ" + /datum/design/item/intellicard name = "'intelliCore', AI preservation and transportation system" desc = "Allows for the construction of an intelliCore." diff --git a/code/modules/research/mechfab_designs.dm b/code/modules/research/mechfab_designs.dm index 4d7149c1882..8efeec6c0d5 100644 --- a/code/modules/research/mechfab_designs.dm +++ b/code/modules/research/mechfab_designs.dm @@ -7,47 +7,47 @@ category = "Ripley" /datum/design/item/mechfab/ripley/chassis - name = "Ripley chassis" + name = "Ripley Chassis" id = "ripley_chassis" build_path = /obj/item/mecha_parts/chassis/ripley time = 10 materials = list(DEFAULT_WALL_MATERIAL = 15000) /datum/design/item/mechfab/ripley/chassis/firefighter - name = "Firefigher chassis" + name = "Firefigher Chassis" id = "firefighter_chassis" build_path = /obj/item/mecha_parts/chassis/firefighter /datum/design/item/mechfab/ripley/torso - name = "Ripley torso" + name = "Ripley Torso" id = "ripley_torso" build_path = /obj/item/mecha_parts/part/ripley_torso time = 20 materials = list(DEFAULT_WALL_MATERIAL = 30000, "glass" = 11250) /datum/design/item/mechfab/ripley/left_arm - name = "Ripley left arm" + name = "Ripley Left Arm" id = "ripley_left_arm" build_path = /obj/item/mecha_parts/part/ripley_left_arm time = 15 materials = list(DEFAULT_WALL_MATERIAL = 18750) /datum/design/item/mechfab/ripley/right_arm - name = "Ripley right arm" + name = "Ripley Right Arm" id = "ripley_right_arm" build_path = /obj/item/mecha_parts/part/ripley_right_arm time = 15 materials = list(DEFAULT_WALL_MATERIAL = 18750) /datum/design/item/mechfab/ripley/left_leg - name = "Ripley left leg" + name = "Ripley Left Leg" id = "ripley_left_leg" build_path = /obj/item/mecha_parts/part/ripley_left_leg time = 15 materials = list(DEFAULT_WALL_MATERIAL = 22500) /datum/design/item/mechfab/ripley/right_leg - name = "Ripley right leg" + name = "Ripley Right Leg" id = "ripley_right_leg" build_path = /obj/item/mecha_parts/part/ripley_right_leg time = 15 @@ -57,49 +57,49 @@ category = "Odysseus" /datum/design/item/mechfab/odysseus/chassis - name = "Odysseus chassis" + name = "Odysseus Chassis" id = "odysseus_chassis" build_path = /obj/item/mecha_parts/chassis/odysseus time = 10 materials = list(DEFAULT_WALL_MATERIAL = 15000) /datum/design/item/mechfab/odysseus/torso - name = "Odysseus torso" + name = "Odysseus Torso" id = "odysseus_torso" build_path = /obj/item/mecha_parts/part/odysseus_torso time = 18 materials = list(DEFAULT_WALL_MATERIAL = 18750) /datum/design/item/mechfab/odysseus/head - name = "Odysseus head" + name = "Odysseus Head" id = "odysseus_head" build_path = /obj/item/mecha_parts/part/odysseus_head time = 10 materials = list(DEFAULT_WALL_MATERIAL = 1500, "glass" = 7500) /datum/design/item/mechfab/odysseus/left_arm - name = "Odysseus left arm" + name = "Odysseus Left Arm" id = "odysseus_left_arm" build_path = /obj/item/mecha_parts/part/odysseus_left_arm time = 12 materials = list(DEFAULT_WALL_MATERIAL = 7500) /datum/design/item/mechfab/odysseus/right_arm - name = "Odysseus right arm" + name = "Odysseus Right Arm" id = "odysseus_right_arm" build_path = /obj/item/mecha_parts/part/odysseus_right_arm time = 12 materials = list(DEFAULT_WALL_MATERIAL = 7500) /datum/design/item/mechfab/odysseus/left_leg - name = "Odysseus left leg" + name = "Odysseus Left Leg" id = "odysseus_left_leg" build_path = /obj/item/mecha_parts/part/odysseus_left_leg time = 13 materials = list(DEFAULT_WALL_MATERIAL = 11250) /datum/design/item/mechfab/odysseus/right_leg - name = "Odysseus right leg" + name = "Odysseus Right Leg" id = "odysseus_right_leg" build_path = /obj/item/mecha_parts/part/odysseus_right_leg time = 13 @@ -109,56 +109,56 @@ category = "Gygax" /datum/design/item/mechfab/gygax/chassis - name = "Gygax chassis" + name = "Gygax Chassis" id = "gygax_chassis" build_path = /obj/item/mecha_parts/chassis/gygax time = 10 materials = list(DEFAULT_WALL_MATERIAL = 18750) /datum/design/item/mechfab/gygax/torso - name = "Gygax torso" + name = "Gygax Torso" id = "gygax_torso" build_path = /obj/item/mecha_parts/part/gygax_torso time = 30 materials = list(DEFAULT_WALL_MATERIAL = 37500, "glass" = 15000) /datum/design/item/mechfab/gygax/head - name = "Gygax head" + name = "Gygax Head" id = "gygax_head" build_path = /obj/item/mecha_parts/part/gygax_head time = 20 materials = list(DEFAULT_WALL_MATERIAL = 15000, "glass" = 7500) /datum/design/item/mechfab/gygax/left_arm - name = "Gygax left arm" + name = "Gygax Left Arm" id = "gygax_left_arm" build_path = /obj/item/mecha_parts/part/gygax_left_arm time = 20 materials = list(DEFAULT_WALL_MATERIAL = 22500) /datum/design/item/mechfab/gygax/right_arm - name = "Gygax right arm" + name = "Gygax Right Arm" id = "gygax_right_arm" build_path = /obj/item/mecha_parts/part/gygax_right_arm time = 20 materials = list(DEFAULT_WALL_MATERIAL = 22500) /datum/design/item/mechfab/gygax/left_leg - name = "Gygax left leg" + name = "Gygax Left Leg" id = "gygax_left_leg" build_path = /obj/item/mecha_parts/part/gygax_left_leg time = 20 materials = list(DEFAULT_WALL_MATERIAL = 26250) /datum/design/item/mechfab/gygax/right_leg - name = "Gygax right leg" + name = "Gygax Right Leg" id = "gygax_right_leg" build_path = /obj/item/mecha_parts/part/gygax_right_leg time = 20 materials = list(DEFAULT_WALL_MATERIAL = 26250) /datum/design/item/mechfab/gygax/armour - name = "Gygax armour plates" + name = "Gygax Armour Plates" id = "gygax_armour" build_path = /obj/item/mecha_parts/part/gygax_armour time = 60 @@ -168,56 +168,56 @@ category = "Durand" /datum/design/item/mechfab/durand/chassis - name = "Durand chassis" + name = "Durand Chassis" id = "durand_chassis" build_path = /obj/item/mecha_parts/chassis/durand time = 10 materials = list(DEFAULT_WALL_MATERIAL = 18750) /datum/design/item/mechfab/durand/torso - name = "Durand torso" + name = "Durand Torso" id = "durand_torso" build_path = /obj/item/mecha_parts/part/durand_torso time = 30 materials = list(DEFAULT_WALL_MATERIAL = 41250, "glass" = 15000, "silver" = 7500) /datum/design/item/mechfab/durand/head - name = "Durand head" + name = "Durand Head" id = "durand_head" build_path = /obj/item/mecha_parts/part/durand_head time = 20 materials = list(DEFAULT_WALL_MATERIAL = 18750, "glass" = 7500, "silver" = 2250) /datum/design/item/mechfab/durand/left_arm - name = "Durand left arm" + name = "Durand Left Arm" id = "durand_left_arm" build_path = /obj/item/mecha_parts/part/durand_left_arm time = 20 materials = list(DEFAULT_WALL_MATERIAL = 26250, "silver" = 2250) /datum/design/item/mechfab/durand/right_arm - name = "Durand right arm" + name = "Durand Right Arm" id = "durand_right_arm" build_path = /obj/item/mecha_parts/part/durand_right_arm time = 20 materials = list(DEFAULT_WALL_MATERIAL = 26250, "silver" = 2250) /datum/design/item/mechfab/durand/left_leg - name = "Durand left leg" + name = "Durand Left Leg" id = "durand_left_leg" build_path = /obj/item/mecha_parts/part/durand_left_leg time = 20 materials = list(DEFAULT_WALL_MATERIAL = 30000, "silver" = 2250) /datum/design/item/mechfab/durand/right_leg - name = "Durand right leg" + name = "Durand Right Leg" id = "durand_right_leg" build_path = /obj/item/mecha_parts/part/durand_right_leg time = 20 materials = list(DEFAULT_WALL_MATERIAL = 30000, "silver" = 2250) /datum/design/item/mechfab/durand/armour - name = "Durand armour plates" + name = "Durand Armour Plates" id = "durand_armour" build_path = /obj/item/mecha_parts/part/durand_armour time = 60 @@ -234,14 +234,14 @@ desc = "Allows for the construction of \a '[item_name]' exosuit module." /datum/design/item/mecha/tracking - name = "Exosuit tracking beacon" + name = "Exosuit Tracking Beacon" id = "mech_tracker" time = 5 materials = list(DEFAULT_WALL_MATERIAL = 375) build_path = /obj/item/mecha_parts/mecha_tracking /datum/design/item/mecha/hydraulic_clamp - name = "Hydraulic clamp" + name = "Hydraulic Clamp" id = "hydraulic_clamp" build_path = /obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp @@ -256,12 +256,12 @@ build_path = /obj/item/mecha_parts/mecha_equipment/tool/extinguisher /datum/design/item/mecha/cable_layer - name = "Cable layer" + name = "Cable Layer" id = "mech_cable_layer" build_path = /obj/item/mecha_parts/mecha_equipment/tool/cable_layer /datum/design/item/mecha/flaregun - name = "Flare launcher" + name = "Flare Launcher" id = "mecha_flare_gun" build_path = /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flare materials = list(DEFAULT_WALL_MATERIAL = 9375) @@ -273,30 +273,20 @@ materials = list(DEFAULT_WALL_MATERIAL = 3750, "glass" = 7500) /datum/design/item/mecha/syringe_gun - name = "Syringe gun" + name = "Syringe Gun" id = "mech_syringe_gun" build_path = /obj/item/mecha_parts/mecha_equipment/tool/syringe_gun time = 20 materials = list(DEFAULT_WALL_MATERIAL = 2250, "glass" = 1500) -/* -/datum/design/item/mecha/syringe_gun - desc = "Exosuit-mounted syringe gun and chemical synthesizer." - id = "mech_syringe_gun" - req_tech = list(TECH_MATERIAL = 3, TECH_BIO = 4, TECH_MAGNET = 4, TECH_DATA = 3) - build_path = /obj/item/mecha_parts/mecha_equipment/tool/syringe_gun - */ - /datum/design/item/mecha/passenger - name = "Passenger compartment" + name = "Passenger Compartment" id = "mech_passenger" build_path = /obj/item/mecha_parts/mecha_equipment/tool/passenger materials = list(DEFAULT_WALL_MATERIAL = 3750, "glass" = 3750) -//obj/item/mecha_parts/mecha_equipment/repair_droid, -//obj/item/mecha_parts/mecha_equipment/jetpack, //TODO MECHA JETPACK SPRITE MISSING /datum/design/item/mecha/taser - name = "PBT \"Pacifier\" mounted taser" + name = "PBT \"Pacifier\" Mounted Taser" id = "mech_taser" build_path = /obj/item/mecha_parts/mecha_equipment/weapon/energy/taser @@ -316,38 +306,38 @@ build_path = /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/scattershot /datum/design/item/mecha/weapon/laser - name = "CH-PS \"Immolator\" laser" + name = "CH-PS \"Immolator\" Laser" id = "mech_laser" req_tech = list(TECH_COMBAT = 3, TECH_MAGNET = 3) build_path = /obj/item/mecha_parts/mecha_equipment/weapon/energy/laser /datum/design/item/mecha/weapon/laser_rigged - name = "Jury-rigged welder-laser" + name = "Jury-Rigged Welder-Laser" desc = "Allows for the construction of a welder-laser assembly package for non-combat exosuits." id = "mech_laser_rigged" req_tech = list(TECH_COMBAT = 2, TECH_MAGNET = 2) build_path = /obj/item/mecha_parts/mecha_equipment/weapon/energy/riggedlaser /datum/design/item/mecha/weapon/laser_heavy - name = "CH-LC \"Solaris\" laser cannon" + name = "CH-LC \"Solaris\" Laser Cannon" id = "mech_laser_heavy" req_tech = list(TECH_COMBAT = 4, TECH_MAGNET = 4) build_path = /obj/item/mecha_parts/mecha_equipment/weapon/energy/laser/heavy /datum/design/item/mecha/weapon/ion - name = "mkIV ion heavy cannon" + name = "MK-IV Ion Heavy Cannon" id = "mech_ion" req_tech = list(TECH_COMBAT = 4, TECH_MAGNET = 4) build_path = /obj/item/mecha_parts/mecha_equipment/weapon/energy/ion /datum/design/item/mecha/weapon/grenade_launcher - name = "SGL-6 grenade launcher" + name = "SGL-6 Grenade Launcher" id = "mech_grenade_launcher" req_tech = list(TECH_COMBAT = 3) build_path = /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flashbang /datum/design/item/mecha/weapon/clusterbang_launcher - name = "SOP-6 grenade launcher" + name = "SOP-6 Grenade Launcher" desc = "A weapon that violates the Geneva Convention at 6 rounds per minute." id = "clusterbang_launcher" req_tech = list(TECH_COMBAT= 5, TECH_MATERIAL = 5, TECH_ILLEGAL = 3) @@ -380,7 +370,7 @@ // *** Nonweapon modules /datum/design/item/mecha/wormhole_gen - name = "Wormhole generator" + name = "Wormhole Generator" desc = "An exosuit module that can generate small quasi-stable wormholes." id = "mech_wormhole_gen" req_tech = list(TECH_BLUESPACE = 3, TECH_MAGNET = 2) @@ -403,36 +393,38 @@ build_path = /obj/item/mecha_parts/mecha_equipment/tool/rcd /datum/design/item/mecha/gravcatapult - name = "Gravitational catapult" + name = "Gravitational Catapult" desc = "An exosuit-mounted gravitational catapult." id = "mech_gravcatapult" req_tech = list(TECH_BLUESPACE = 2, TECH_MAGNET = 3, TECH_ENGINEERING = 3) build_path = /obj/item/mecha_parts/mecha_equipment/gravcatapult /datum/design/item/mecha/repair_droid - name = "Repair droid" + name = "Repair Droid" desc = "Automated repair droid, exosuits' best companion. BEEP BOOP" id = "mech_repair_droid" req_tech = list(TECH_MAGNET = 3, TECH_DATA = 3, TECH_ENGINEERING = 3) materials = list(DEFAULT_WALL_MATERIAL = 7500, "gold" = 750, "silver" = 1500, "glass" = 3750) build_path = /obj/item/mecha_parts/mecha_equipment/repair_droid +//obj/item/mecha_parts/mecha_equipment/jetpack, //TODO MECHA JETPACK SPRITE MISSING + /datum/design/item/mecha/phoron_generator - desc = "Phoron reactor." + desc = "Phoron Reactor" id = "mech_phoron_generator" req_tech = list(TECH_PHORON = 2, TECH_POWER= 2, TECH_ENGINEERING = 2) build_path = /obj/item/mecha_parts/mecha_equipment/generator materials = list(DEFAULT_WALL_MATERIAL = 7500, "silver" = 375, "glass" = 750) /datum/design/item/mecha/energy_relay - name = "Energy relay" + name = "Energy Relay" id = "mech_energy_relay" req_tech = list(TECH_MAGNET = 4, TECH_POWER = 3) materials = list(DEFAULT_WALL_MATERIAL = 7500, "gold" = 1500, "silver" = 2250, "glass" = 1500) build_path = /obj/item/mecha_parts/mecha_equipment/tesla_energy_relay /datum/design/item/mecha/ccw_armor - name = "CCW armor booster" + name = "CCW Armor Booster" desc = "Exosuit close-combat armor booster." id = "mech_ccw_armor" req_tech = list(TECH_MATERIAL = 5, TECH_COMBAT = 4) @@ -440,6 +432,7 @@ build_path = /obj/item/mecha_parts/mecha_equipment/anticcw_armor_booster /datum/design/item/mecha/proj_armor + name = "Ranged Armor Booster" desc = "Exosuit projectile armor booster." id = "mech_proj_armor" req_tech = list(TECH_MATERIAL = 5, TECH_COMBAT = 5, TECH_ENGINEERING = 3) @@ -447,7 +440,7 @@ build_path = /obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster /datum/design/item/mecha/diamond_drill - name = "Diamond drill" + name = "Diamond Drill" desc = "A diamond version of the exosuit drill. It's harder, better, faster, stronger." id = "mech_diamond_drill" req_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 3) @@ -455,7 +448,7 @@ build_path = /obj/item/mecha_parts/mecha_equipment/tool/drill/diamonddrill /datum/design/item/mecha/generator_nuclear - name = "Nuclear reactor" + name = "Nuclear Reactor" desc = "Exosuit-held nuclear reactor. Converts uranium and everyone's health to energy." id = "mech_generator_nuclear" req_tech = list(TECH_POWER= 3, TECH_ENGINEERING = 3, TECH_MATERIAL = 3) @@ -463,7 +456,7 @@ build_path = /obj/item/mecha_parts/mecha_equipment/generator/nuclear /datum/design/item/synthetic_flash - name = "Synthetic flash" + name = "Synthetic Flash" id = "sflash" req_tech = list(TECH_MAGNET = 3, TECH_COMBAT = 2) build_type = MECHFAB diff --git a/code/modules/research/prosfab_designs.dm b/code/modules/research/prosfab_designs.dm index 38b00c5f96e..7a191f489fc 100644 --- a/code/modules/research/prosfab_designs.dm +++ b/code/modules/research/prosfab_designs.dm @@ -63,7 +63,7 @@ var/gender = MALE /datum/design/item/prosfab/pros/torso/male - name = "FBP torso (M)" + name = "FBP Torso (M)" id = "pros_torso_m" build_path = /obj/item/organ/external/chest gender = MALE @@ -71,13 +71,13 @@ /obj/item/organ/external/chest/f //To satisfy Travis. :| /datum/design/item/prosfab/pros/torso/female - name = "FBP torso (F)" + name = "FBP Torso (F)" id = "pros_torso_f" build_path = /obj/item/organ/external/chest/f gender = FEMALE /datum/design/item/prosfab/pros/head - name = "Prosthetic head" + name = "Prosthetic Head" id = "pros_head" build_path = /obj/item/organ/external/head time = 30 @@ -85,103 +85,106 @@ // req_tech = list(TECH_ENGINEERING = 2, TECH_MATERIAL = 3, TECH_DATA = 3) //Saving the values just in case /datum/design/item/prosfab/pros/l_arm - name = "Prosthetic left arm" + name = "Prosthetic Left Arm" id = "pros_l_arm" build_path = /obj/item/organ/external/arm time = 20 materials = list(DEFAULT_WALL_MATERIAL = 10125) /datum/design/item/prosfab/pros/l_hand - name = "Prosthetic left hand" + name = "Prosthetic Left Hand" id = "pros_l_hand" build_path = /obj/item/organ/external/hand time = 15 materials = list(DEFAULT_WALL_MATERIAL = 3375) /datum/design/item/prosfab/pros/r_arm - name = "Prosthetic right arm" + name = "Prosthetic Right Arm" id = "pros_r_arm" build_path = /obj/item/organ/external/arm/right time = 20 materials = list(DEFAULT_WALL_MATERIAL = 10125) /datum/design/item/prosfab/pros/r_hand - name = "Prosthetic right hand" + name = "Prosthetic Right Hand" id = "pros_r_hand" build_path = /obj/item/organ/external/hand/right time = 15 materials = list(DEFAULT_WALL_MATERIAL = 3375) /datum/design/item/prosfab/pros/l_leg - name = "Prosthetic left leg" + name = "Prosthetic Left Leg" id = "pros_l_leg" build_path = /obj/item/organ/external/leg time = 20 materials = list(DEFAULT_WALL_MATERIAL = 8437) /datum/design/item/prosfab/pros/l_foot - name = "Prosthetic left foot" + name = "Prosthetic Left Foot" id = "pros_l_foot" build_path = /obj/item/organ/external/foot time = 15 materials = list(DEFAULT_WALL_MATERIAL = 2813) /datum/design/item/prosfab/pros/r_leg - name = "Prosthetic right leg" + name = "Prosthetic Right Leg" id = "pros_r_leg" build_path = /obj/item/organ/external/leg/right time = 20 materials = list(DEFAULT_WALL_MATERIAL = 8437) /datum/design/item/prosfab/pros/r_foot - name = "Prosthetic right foot" + name = "Prosthetic Right Foot" id = "pros_r_foot" build_path = /obj/item/organ/external/foot/right time = 15 materials = list(DEFAULT_WALL_MATERIAL = 2813) -/datum/design/item/prosfab/pros/cell - name = "Prosthetic powercell" +/datum/design/item/prosfab/pros/internal + category = "Prosthetics, Internal" + +/datum/design/item/prosfab/pros/internal/cell + name = "Prosthetic Powercell" id = "pros_cell" build_path = /obj/item/organ/internal/cell time = 15 materials = list(DEFAULT_WALL_MATERIAL = 7500, "glass" = 3000) // req_tech = list(TECH_ENGINEERING = 2, TECH_MATERIAL = 2) -/datum/design/item/prosfab/pros/eyes - name = "Prosthetic eyes" +/datum/design/item/prosfab/pros/internal/eyes + name = "Prosthetic Eyes" id = "pros_eyes" build_path = /obj/item/organ/internal/eyes/robot time = 15 materials = list(DEFAULT_WALL_MATERIAL = 5625, "glass" = 5625) // req_tech = list(TECH_ENGINEERING = 2, TECH_MATERIAL = 2) -/datum/design/item/prosfab/pros/heart - name = "Prosthetic heart" +/datum/design/item/prosfab/pros/internal/heart + name = "Prosthetic Heart" id = "pros_heart" build_path = /obj/item/organ/internal/heart time = 15 materials = list(DEFAULT_WALL_MATERIAL = 5625, "glass" = 1000) // req_tech = list(TECH_ENGINEERING = 2, TECH_MATERIAL = 2) -/datum/design/item/prosfab/pros/lungs - name = "Prosthetic lungs" +/datum/design/item/prosfab/pros/internal/lungs + name = "Prosthetic Lungs" id = "pros_lung" build_path = /obj/item/organ/internal/lungs time = 15 materials = list(DEFAULT_WALL_MATERIAL = 5625, "glass" = 1000) // req_tech = list(TECH_ENGINEERING = 2, TECH_MATERIAL = 2) -/datum/design/item/prosfab/pros/liver - name = "Prosthetic liver" +/datum/design/item/prosfab/pros/internal/liver + name = "Prosthetic Liver" id = "pros_liver" build_path = /obj/item/organ/internal/liver time = 15 materials = list(DEFAULT_WALL_MATERIAL = 5625, "glass" = 1000) // req_tech = list(TECH_ENGINEERING = 2, TECH_MATERIAL = 2) -/datum/design/item/prosfab/pros/kidneys - name = "Prosthetic liver" +/datum/design/item/prosfab/pros/internal/kidneys + name = "Prosthetic Kidneys" id = "pros_kidney" build_path = /obj/item/organ/internal/kidneys time = 15 @@ -195,49 +198,49 @@ materials = list(DEFAULT_WALL_MATERIAL = 3750) /datum/design/item/prosfab/cyborg/exoskeleton - name = "Robot exoskeleton" + name = "Robot Exoskeleton" id = "robot_exoskeleton" build_path = /obj/item/robot_parts/robot_suit time = 50 materials = list(DEFAULT_WALL_MATERIAL = 37500) /datum/design/item/prosfab/cyborg/torso - name = "Robot torso" + name = "Robot Torso" id = "robot_torso" build_path = /obj/item/robot_parts/chest time = 35 materials = list(DEFAULT_WALL_MATERIAL = 30000) /datum/design/item/prosfab/cyborg/head - name = "Robot head" + name = "Robot Head" id = "robot_head" build_path = /obj/item/robot_parts/head time = 35 materials = list(DEFAULT_WALL_MATERIAL = 18750) /datum/design/item/prosfab/cyborg/l_arm - name = "Robot left arm" + name = "Robot Left Arm" id = "robot_l_arm" build_path = /obj/item/robot_parts/l_arm time = 20 materials = list(DEFAULT_WALL_MATERIAL = 13500) /datum/design/item/prosfab/cyborg/r_arm - name = "Robot right arm" + name = "Robot Right Arm" id = "robot_r_arm" build_path = /obj/item/robot_parts/r_arm time = 20 materials = list(DEFAULT_WALL_MATERIAL = 13500) /datum/design/item/prosfab/cyborg/l_leg - name = "Robot left leg" + name = "Robot Left Leg" id = "robot_l_leg" build_path = /obj/item/robot_parts/l_leg time = 20 materials = list(DEFAULT_WALL_MATERIAL = 11250) /datum/design/item/prosfab/cyborg/r_leg - name = "Robot right leg" + name = "Robot Right Leg" id = "robot_r_leg" build_path = /obj/item/robot_parts/r_leg time = 20 @@ -252,7 +255,7 @@ materials = list(DEFAULT_WALL_MATERIAL = 7500) /datum/design/item/prosfab/cyborg/component/binary_communication_device - name = "Binary communication device" + name = "Binary Communication Device" id = "binary_communication_device" build_path = /obj/item/robot_parts/robot_component/binary_communication_device @@ -267,7 +270,7 @@ build_path = /obj/item/robot_parts/robot_component/actuator /datum/design/item/prosfab/cyborg/component/diagnosis_unit - name = "Diagnosis unit" + name = "Diagnosis Unit" id = "diagnosis_unit" build_path = /obj/item/robot_parts/robot_component/diagnosis_unit @@ -277,7 +280,7 @@ build_path = /obj/item/robot_parts/robot_component/camera /datum/design/item/prosfab/cyborg/component/armour - name = "Armour plating" + name = "Armour Plating" id = "armour" build_path = /obj/item/robot_parts/robot_component/armour @@ -290,49 +293,57 @@ 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) materials = list(DEFAULT_WALL_MATERIAL = 7500, "glass" = 11250, "diamond" = 7500) - build_path = /obj/item/borg/upgrade/syndicate \ No newline at end of file + build_path = /obj/item/borg/upgrade/syndicate + +/datum/design/item/prosfab/robot_upgrade/language + 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) + materials = list(DEFAULT_WALL_MATERIAL = 25000, "glass" = 3000, "gold" = 350) + build_path = /obj/item/borg/upgrade/language \ No newline at end of file diff --git a/code/modules/research/rdconsole.dm b/code/modules/research/rdconsole.dm index 8e531ad6874..db06449d18c 100644 --- a/code/modules/research/rdconsole.dm +++ b/code/modules/research/rdconsole.dm @@ -405,7 +405,7 @@ won't update every console in existence) but it's more of a hassle to do. Also, return /obj/machinery/computer/rdconsole/proc/GetResearchLevelsInfo() - var/dat + var/list/dat = list() dat += "" - return dat + return dat.Join() /obj/machinery/computer/rdconsole/proc/GetResearchListInfo() - var/dat + var/list/dat = list() dat += "" - return dat + return dat.Join() /obj/machinery/computer/rdconsole/attack_hand(mob/user as mob) if(stat & (BROKEN|NOPOWER)) return user.set_machine(src) - var/dat = "" + var/list/dat = list() files.RefreshResearch() switch(screen) //A quick check to make sure you get the right screen when a device is disconnected. if(2 to 2.9) @@ -774,7 +774,7 @@ won't update every console in existence) but it's more of a hassle to do. Also, dat += "List of Researched Technologies and Designs:" dat += GetResearchListInfo() - user << browse("Research and Development Console
[dat]", "window=rdconsole;size=850x600") + user << browse("Research and Development Console
[dat.Join()]", "window=rdconsole;size=850x600") onclose(user, "rdconsole") /obj/machinery/computer/rdconsole/robotics diff --git a/code/modules/shieldgen/energy_field.dm b/code/modules/shieldgen/energy_field.dm index 5dc6af651d3..e558a2621e2 100644 --- a/code/modules/shieldgen/energy_field.dm +++ b/code/modules/shieldgen/energy_field.dm @@ -49,7 +49,7 @@ if(W.force) adjust_strength(-W.force / 20) user.do_attack_animation(src) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(W)) ..() /obj/effect/energy_field/attack_hand(var/mob/living/user) diff --git a/code/modules/shieldgen/shield_capacitor.dm b/code/modules/shieldgen/shield_capacitor.dm index 2bddb5af327..f1988ee8c65 100644 --- a/code/modules/shieldgen/shield_capacitor.dm +++ b/code/modules/shieldgen/shield_capacitor.dm @@ -4,7 +4,7 @@ /obj/machinery/shield_capacitor name = "shield capacitor" - desc = "Machine that charges a shield generator." + desc = "A machine that charges a shield generator." icon = 'icons/obj/machines/shielding.dmi' icon_state = "capacitor" var/active = 0 @@ -19,6 +19,12 @@ var/charge_rate = 100000 //100 kW var/obj/machinery/shield_gen/owned_gen +/obj/machinery/shield_capacitor/advanced + name = "advanced shield capacitor" + desc = "A machine that charges a shield generator. This version can store, input, and output more electricity." + max_charge = 12e6 + max_charge_rate = 600000 + /obj/machinery/shield_capacitor/emag_act(var/remaining_charges, var/mob/user) if(prob(75)) src.locked = !src.locked diff --git a/code/modules/shieldgen/shield_gen.dm b/code/modules/shieldgen/shield_gen.dm index 32d34365b44..6100dda029e 100644 --- a/code/modules/shieldgen/shield_gen.dm +++ b/code/modules/shieldgen/shield_gen.dm @@ -1,11 +1,11 @@ /obj/machinery/shield_gen name = "bubble shield generator" - desc = "Machine that generates an impenetrable field of energy when activated." + desc = "A machine that generates a field of energy optimized for blocking meteorites when activated." icon = 'icons/obj/machines/shielding.dmi' 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 @@ -20,10 +20,15 @@ var/target_field_strength = 10 var/max_field_strength = 10 var/time_since_fail = 100 - var/energy_conversion_rate = 0.0002 //how many renwicks per watt? + var/energy_conversion_rate = 0.0002 //how many renwicks per watt? Higher numbers equals more effiency. var/z_range = 0 // How far 'up and or down' to extend the shield to, in z-levels. Only works on MultiZ supported z-levels. use_power = 0 //doesn't use APC power +/obj/machinery/shield_gen/advanced + name = "advanced bubble shield generator" + desc = "A machine that generates a field of energy optimized for blocking meteorites when activated. This version comes with a more efficent shield matrix." + energy_conversion_rate = 0.0004 + /obj/machinery/shield_gen/New() spawn(1 SECOND) if(anchored) @@ -259,11 +264,14 @@ /obj/machinery/shield_gen/update_icon() if(stat & BROKEN) icon_state = "broke" + set_light(0) else if (src.active) icon_state = "generator1" + set_light(4, 2, "#00CCFF") else icon_state = "generator0" + set_light(0) //grab the border tiles in a circle around this machine /obj/machinery/shield_gen/proc/get_shielded_turfs() @@ -315,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/shieldgen/shield_gen_external.dm b/code/modules/shieldgen/shield_gen_external.dm index 27b1def2714..fa4702feeea 100644 --- a/code/modules/shieldgen/shield_gen_external.dm +++ b/code/modules/shieldgen/shield_gen_external.dm @@ -7,8 +7,11 @@ /turf/space, /turf/simulated/floor/outdoors, ) -/obj/machinery/shield_gen/external/New() - ..() + +/obj/machinery/shield_gen/external/advanced + name = "advanced hull shield generator" + desc = "A machine that generates a field of energy optimized for blocking meteorites when activated. This version comes with a more efficent shield matrix." + energy_conversion_rate = 0.0004 //Search for space turfs within range that are adjacent to a simulated turf. /obj/machinery/shield_gen/external/get_shielded_turfs_on_z_level(var/turf/gen_turf) diff --git a/code/modules/shuttles/shuttle_emergency.dm b/code/modules/shuttles/shuttle_emergency.dm index 347243ae5cf..53d2570ca99 100644 --- a/code/modules/shuttles/shuttle_emergency.dm +++ b/code/modules/shuttles/shuttle_emergency.dm @@ -50,8 +50,8 @@ if (istype(user, /obj/machinery/computer/shuttle_control/emergency)) var/obj/machinery/computer/shuttle_control/emergency/C = user - //initiating or cancelling a launch ALWAYS requires authorization, but if we are already set to launch anyways than forcing does not. - //this is so that people can force launch if the docking controller cannot safely undock without needing X heads to swipe. + //Initiating or cancelling a launch ALWAYS requires authorization, but if we are already set to launch anyways than forcing does not. + //This is so that people can force launch if the docking controller cannot safely undock without needing X heads to swipe. if (!(process_state == WAIT_LAUNCH || C.has_authorization())) return 0 return ..() @@ -69,11 +69,11 @@ if (istype(user, /obj/machinery/computer/shuttle_control/emergency)) //if we were given a command by an emergency shuttle console if (emergency_shuttle.autopilot) emergency_shuttle.autopilot = 0 - world << "Alert: The shuttle autopilot has been overridden. Launch sequence initiated!" + to_chat(world, "Alert: The shuttle autopilot has been overridden. Launch sequence initiated!") if(usr) - log_admin("[key_name(usr)] has overridden the shuttle autopilot and activated launch sequence") - message_admins("[key_name_admin(usr)] has overridden the shuttle autopilot and activated launch sequence") + log_admin("[key_name(usr)] has overridden the departure shuttle's autopilot and activated the launch sequence.") + message_admins("[key_name_admin(usr)] has overridden the departure shuttle's autopilot and activated the launch sequence.") ..(user) @@ -83,11 +83,11 @@ if (istype(user, /obj/machinery/computer/shuttle_control/emergency)) //if we were given a command by an emergency shuttle console if (emergency_shuttle.autopilot) emergency_shuttle.autopilot = 0 - world << "Alert: The shuttle autopilot has been overridden. Bluespace drive engaged!" + to_chat(world, "Alert: The shuttle autopilot has been overridden. Bluespace drive engaged!") if(usr) - log_admin("[key_name(usr)] has overridden the shuttle autopilot and forced immediate launch") - message_admins("[key_name_admin(usr)] has overridden the shuttle autopilot and forced immediate launch") + log_admin("[key_name(usr)] has overridden the departure shuttle's autopilot and forced immediate launch.") + message_admins("[key_name_admin(usr)] has overridden the departure shuttle's autopilot and forced immediate launch.") ..(user) @@ -97,11 +97,11 @@ if (istype(user, /obj/machinery/computer/shuttle_control/emergency)) //if we were given a command by an emergency shuttle console if (emergency_shuttle.autopilot) emergency_shuttle.autopilot = 0 - world << "Alert: The shuttle autopilot has been overridden. Launch sequence aborted!" + to_chat(world, "Alert: The shuttle autopilot has been overridden. Launch sequence aborted!") if(usr) - log_admin("[key_name(usr)] has overridden the shuttle autopilot and cancelled launch sequence") - message_admins("[key_name_admin(usr)] has overridden the shuttle autopilot and cancelled launch sequence") + log_admin("[key_name(usr)] has overridden the departure shuttle's autopilot and cancelled the launch sequence.") + message_admins("[key_name_admin(usr)] has overridden the departure shuttle's autopilot and cancelled the launch sequence.") ..(user) @@ -117,7 +117,7 @@ return (authorized.len >= req_authorizations || emagged) /obj/machinery/computer/shuttle_control/emergency/proc/reset_authorization() - //no need to reset emagged status. If they really want to go back to the station they can. + //No need to reset emagged status. If they really want to go back to the station they can. authorized = initial(authorized) //returns 1 if the ID was accepted and a new authorization was added, 0 otherwise @@ -145,16 +145,19 @@ if (dna_hash in authorized) src.visible_message("\The [src] buzzes. That ID has already been scanned.") + playsound(src.loc, 'sound/machines/buzz-sigh.ogg', 50, 0) return 0 if (!(access_heads in access)) src.visible_message("\The [src] buzzes, rejecting [ident].") + playsound(src.loc, 'sound/machines/deniedbeep.ogg', 50, 0) return 0 src.visible_message("\The [src] beeps as it scans [ident].") + playsound(src.loc, 'sound/machines/twobeep.ogg', 50, 0) authorized[dna_hash] = auth_name if (req_authorizations - authorized.len) - world << "Alert: [req_authorizations - authorized.len] authorization\s needed to override the shuttle autopilot." + to_chat(world, "Alert: [req_authorizations - authorized.len] authorization\s needed to override the shuttle autopilot.") //TODO- Belsima, make this an announcement instead of magic. if(usr) log_admin("[key_name(usr)] has inserted [ID] into the shuttle control computer - [req_authorizations - authorized.len] authorisation\s needed") @@ -164,7 +167,7 @@ /obj/machinery/computer/shuttle_control/emergency/emag_act(var/remaining_charges, var/mob/user) if (!emagged) - user << "You short out \the [src]'s authorization protocols." + to_chat(user, "You short out \the [src]'s authorization protocols.") emagged = 1 return 1 @@ -190,11 +193,11 @@ if (shuttle.in_use) shuttle_status = "Busy." else if (!shuttle.location) - shuttle_status = "Standing-by at [station_name()]." + shuttle_status = "Standing by at [station_name()]." else - shuttle_status = "Standing-by at [using_map.dock_name]." + shuttle_status = "Standing by at [using_map.dock_name]." if(WAIT_LAUNCH, FORCE_LAUNCH) - shuttle_status = "Shuttle has recieved command and will depart shortly." + shuttle_status = "Shuttle has received command and will depart shortly." if(WAIT_ARRIVE) shuttle_status = "Proceeding to destination." if(WAIT_FINISH) diff --git a/code/modules/shuttles/shuttles_multi.dm b/code/modules/shuttles/shuttles_multi.dm index 85155f61198..043d066e809 100644 --- a/code/modules/shuttles/shuttles_multi.dm +++ b/code/modules/shuttles/shuttles_multi.dm @@ -174,7 +174,7 @@ return if (MS.moving_status != SHUTTLE_IDLE) - usr << "[shuttle_tag] vessel is moving." + to_chat(usr, "[shuttle_tag] vessel is moving.") return if(href_list["dock_command"]) @@ -187,11 +187,11 @@ if(href_list["start"]) if(MS.at_origin) - usr << "You are already at your home base." + to_chat(usr, "You are already at the home base.") return if((MS.last_move + MS.cooldown*10) > world.time) - usr << "The ship's drive is inoperable while the engines are charging." + to_chat(usr, "The ship's drive is inoperable while the engines are charging.") return if(!check_docking(MS)) @@ -214,11 +214,11 @@ if(!MS.can_cloak) return MS.cloaked = !MS.cloaked - usr << "Ship stealth systems have been [(MS.cloaked ? "activated. The station will not" : "deactivated. The station will")] be warned of our arrival." + to_chat(usr, "Ship stealth systems have been [(MS.cloaked ? "activated. The station will not" : "deactivated. The station will")] be warned of our arrival.") if(href_list["move_multi"]) if((MS.last_move + MS.cooldown*10) > world.time) - usr << "The ship's drive is inoperable while the engines are charging." + to_chat(usr, "The ship's drive is inoperable while the engines are charging.") return if(!check_docking(MS)) @@ -228,7 +228,7 @@ var/choice = input("Select a destination.") as null|anything in MS.destinations if(!choice) return - usr << "[shuttle_tag] main computer recieved message." + to_chat(usr, "[shuttle_tag] main computer received message.") if(MS.at_origin) MS.announce_arrival() diff --git a/code/modules/surgery/face.dm b/code/modules/surgery/face.dm index a0ad788bdd9..f9c6a6b2855 100644 --- a/code/modules/surgery/face.dm +++ b/code/modules/surgery/face.dm @@ -43,7 +43,7 @@ user.visible_message("[user]'s hand slips, slicing [target]'s throat wth \the [tool]!" , \ "Your hand slips, slicing [target]'s throat wth \the [tool]!" ) affected.createwound(CUT, 60) - target.losebreath += 10 + target.AdjustLosebreath(10) /datum/surgery_step/face/mend_vocal allowed_tools = list( @@ -71,7 +71,7 @@ fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) user.visible_message("[user]'s hand slips, clamping [target]'s trachea shut for a moment with \the [tool]!", \ "Your hand slips, clamping [user]'s trachea shut for a moment with \the [tool]!") - target.losebreath += 10 + target.AdjustLosebreath(10) /datum/surgery_step/face/fix_face allowed_tools = list( diff --git a/code/modules/surgery/organs_internal.dm b/code/modules/surgery/organs_internal.dm index 9dc0f658361..562cc8e380b 100644 --- a/code/modules/surgery/organs_internal.dm +++ b/code/modules/surgery/organs_internal.dm @@ -120,7 +120,7 @@ if(I.organ_tag == O_EYES) target.sdisabilities &= ~BLIND if(I.organ_tag == O_LUNGS) - target.losebreath = 0 + target.SetLosebreath(0) fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) diff --git a/code/modules/tables/presets.dm b/code/modules/tables/presets.dm index 688bff4def4..06fca651383 100644 --- a/code/modules/tables/presets.dm +++ b/code/modules/tables/presets.dm @@ -90,6 +90,23 @@ material = get_material_by_name("holowood") ..() +/obj/structure/table/alien + name = "alien table" + desc = "Advanced flat surface technology at work!" + icon_state = "alien_preview" + can_reinforce = FALSE + can_plate = FALSE + +/obj/structure/table/alien/New() + material = get_material_by_name("alium") + verbs -= /obj/structure/table/verb/do_flip + verbs -= /obj/structure/table/proc/do_put + ..() + +/obj/structure/table/alien/dismantle(obj/item/weapon/wrench/W, mob/user) + to_chat(user, "You cannot dismantle \the [src].") + return + //BENCH PRESETS /obj/structure/table/bench/standard icon_state = "plain_preview" diff --git a/code/modules/vehicles/vehicle.dm b/code/modules/vehicles/vehicle.dm index eb70ca64ce5..f725508c883 100644 --- a/code/modules/vehicles/vehicle.dm +++ b/code/modules/vehicles/vehicle.dm @@ -94,7 +94,7 @@ if(health < maxhealth) if(open) health = min(maxhealth, health+10) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(W)) playsound(src, T.usesound, 50, 1) user.visible_message("[user] repairs [src]!"," You repair [src]!") else @@ -104,7 +104,7 @@ else user << "Unable to repair while [src] is off." else if(hasvar(W,"force") && hasvar(W,"damtype")) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(W)) switch(W.damtype) if("fire") health -= W.force * fire_dam_coeff diff --git a/code/modules/xenoarcheaology/tools/tools.dm b/code/modules/xenoarcheaology/tools/tools.dm index d3ab8d07d61..1d79a894497 100644 --- a/code/modules/xenoarcheaology/tools/tools.dm +++ b/code/modules/xenoarcheaology/tools/tools.dm @@ -1,17 +1,3 @@ -/obj/item/device/gps - name = "relay positioning device" - desc = "Triangulates the approximate co-ordinates using a nearby satellite network." - icon = 'icons/obj/device.dmi' - icon_state = "locator" - item_state = "locator" - origin_tech = list(TECH_MATERIAL = 2, TECH_DATA = 2, TECH_BLUESPACE = 2) - matter = list(DEFAULT_WALL_MATERIAL = 500) - w_class = ITEMSIZE_SMALL - -/obj/item/device/gps/attack_self(var/mob/user as mob) - var/turf/T = get_turf(src) - user << "\icon[src] \The [src] flashes [T.x]:[T.y]:[T.z]." - /obj/item/device/measuring_tape name = "measuring tape" desc = "A coiled metallic tape used to check dimensions and lengths." diff --git a/code/modules/xenobio/items/extracts.dm b/code/modules/xenobio/items/extracts.dm index 87542b70f0d..8d7d338bad2 100644 --- a/code/modules/xenobio/items/extracts.dm +++ b/code/modules/xenobio/items/extracts.dm @@ -899,6 +899,7 @@ evasion = 2 slowdown = -1 + attack_speed_percent = 0.75 // ********************* diff --git a/code/stylesheet.dm b/code/stylesheet.dm index 5b3cb80b151..f42f2dcf051 100644 --- a/code/stylesheet.dm +++ b/code/stylesheet.dm @@ -24,6 +24,7 @@ em {font-style: normal;font-weight: bold;} .ooc .moderator {color: #184880;} .ooc .developer {color: #1b521f;} .ooc .admin {color: #b82e00;} +.ooc .event_manager {color: #660033;} .ooc .aooc {color: #960018;} /* Admin: Private Messages */ @@ -36,7 +37,7 @@ em {font-style: normal;font-weight: bold;} .mod_channel {color: #735638; font-weight: bold;} .mod_channel .admin {color: #b82e00; font-weight: bold;} .admin_channel {color: #9611D4; font-weight: bold;} -.event_channel {color: #009933; font-weight: bold;} +.event_channel {color: #cc3399; font-weight: bold;} /* Radio: Misc */ .deadsay {color: #530FAD;} diff --git a/code/unit_tests/map_tests.dm b/code/unit_tests/map_tests.dm index f8f735f8676..25f6f7557a9 100644 --- a/code/unit_tests/map_tests.dm +++ b/code/unit_tests/map_tests.dm @@ -12,8 +12,9 @@ /area/holodeck, /area/supply/station, /area/mine, - /area/vacant/vacant_shop - ) + /area/vacant/vacant_shop, + /area/turbolift, + /area/submap ) var/list/exempt_from_atmos = typesof(/area/maintenance, /area/storage, @@ -33,6 +34,11 @@ /area/vacant/vacant_shop ) + // Some maps have areas specific to the map, so include those. + exempt_areas += using_map.unit_test_exempt_areas + exempt_from_atmos += using_map.unit_test_exempt_from_atmos + exempt_from_apc += using_map.unit_test_exempt_from_apc + for(var/area/A in world) if(A.z == 1 && !(A.type in exempt_areas)) area_test_count++ diff --git a/html/changelog.html b/html/changelog.html index cb2923c0f14..ec884ce0694 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -53,6 +53,42 @@ -->
+

29 November 2017

+

Anewbe updated:

+ +

Atermonera updated:

+ +

MoondancerPony updated:

+ +

PrismaticGynoid updated:

+ + +

06 November 2017

+

Atermonera updated:

+ +

Woodrat updated:

+ +

24 September 2017

Belsima updated:

diff --git a/nano/templates/crew_monitor.tmpl b/nano/templates/crew_monitor.tmpl index 74467e4b0f2..bf02a98b8ea 100644 --- a/nano/templates/crew_monitor.tmpl +++ b/nano/templates/crew_monitor.tmpl @@ -26,7 +26,7 @@ Used In File(s): \code\game\machinery\computer\crew.dm {{else value.sensor_type == 2}} {{:value.name}} ({{:value.assignment}}){{:value.dead ? "Deceased" : "Living"}} ({{:value.oxy}}/{{:value.tox}}/{{:value.fire}}/{{:value.brute}})Not Available{{if data.isAI}}{{:helper.link('Track', null, {}, 'disabled')}}{{/if}} {{else value.sensor_type == 3}} - {{:value.name}} ({{:value.assignment}}){{:value.dead ? "Deceased" : "Living"}} ({{:value.oxy}}/{{:value.tox}}/{{:value.fire}}/{{:value.brute}}){{:value.area}}({{:value.x}}, {{:value.y}}){{if data.isAI}}{{:helper.link('Track', null, {'track' : value.ref})}}{{/if}} + {{:value.name}} ({{:value.assignment}}){{:value.dead ? "Deceased" : "Living"}} ({{:value.oxy}}/{{:value.tox}}/{{:value.fire}}/{{:value.brute}}){{:value.area}}({{:value.x}}, {{:value.y}}, {{:value.z}}){{if data.isAI}}{{:helper.link('Track', null, {'track' : value.ref})}}{{/if}} {{/if}} {{/for}} diff --git a/nano/templates/request_console.tmpl b/nano/templates/request_console.tmpl index f14e27190fa..bd94cf79878 100644 --- a/nano/templates/request_console.tmpl +++ b/nano/templates/request_console.tmpl @@ -73,7 +73,7 @@ Used In File(s): \code\game\machinery\requests_console.dm {{for data.message_log}}
{{:value}}
{{empty}} -
No messages have been recieved.
+
No messages have been received.
{{/for}}
{{:helper.link('Back', 'arrowreturnthick-1-w', { 'setScreen' : 0 })}}
diff --git a/polaris.dme b/polaris.dme index 9cafc32d4db..20a0bfc4ca5 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" @@ -403,6 +404,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" @@ -615,8 +617,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" @@ -805,6 +809,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" @@ -820,6 +825,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" @@ -886,7 +892,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" @@ -985,6 +990,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" @@ -994,6 +1000,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" @@ -1079,6 +1086,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" @@ -1745,6 +1754,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" @@ -1937,6 +1947,7 @@ #include "code\modules\paperwork\paper.dm" #include "code\modules\paperwork\paper_bundle.dm" #include "code\modules\paperwork\paperbin.dm" +#include "code\modules\paperwork\paperplane.dm" #include "code\modules\paperwork\papershredder.dm" #include "code\modules\paperwork\pen.dm" #include "code\modules\paperwork\photocopier.dm" @@ -1972,6 +1983,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" diff --git a/sound/effects/weightdrop.ogg b/sound/effects/weightdrop.ogg new file mode 100644 index 00000000000..07945daaf86 Binary files /dev/null and b/sound/effects/weightdrop.ogg differ diff --git a/sound/effects/weightlifter.ogg b/sound/effects/weightlifter.ogg new file mode 100644 index 00000000000..51a0d497854 Binary files /dev/null and b/sound/effects/weightlifter.ogg differ diff --git a/sound/items/geiger1.ogg b/sound/items/geiger1.ogg new file mode 100644 index 00000000000..b8220856594 Binary files /dev/null and b/sound/items/geiger1.ogg differ diff --git a/sound/items/geiger2.ogg b/sound/items/geiger2.ogg new file mode 100644 index 00000000000..4c0d734463c Binary files /dev/null and b/sound/items/geiger2.ogg differ diff --git a/sound/items/geiger3.ogg b/sound/items/geiger3.ogg new file mode 100644 index 00000000000..a9a5924d80c Binary files /dev/null and b/sound/items/geiger3.ogg differ diff --git a/sound/items/geiger4.ogg b/sound/items/geiger4.ogg new file mode 100644 index 00000000000..dfad69866cc Binary files /dev/null and b/sound/items/geiger4.ogg differ diff --git a/sound/items/geiger5.ogg b/sound/items/geiger5.ogg new file mode 100644 index 00000000000..1e5f20913cb Binary files /dev/null and b/sound/items/geiger5.ogg differ diff --git a/sound/items/geiger_weak1.ogg b/sound/items/geiger_weak1.ogg new file mode 100644 index 00000000000..cadfcde746c Binary files /dev/null and b/sound/items/geiger_weak1.ogg differ diff --git a/sound/items/geiger_weak2.ogg b/sound/items/geiger_weak2.ogg new file mode 100644 index 00000000000..12f54ae6698 Binary files /dev/null and b/sound/items/geiger_weak2.ogg differ diff --git a/sound/items/geiger_weak3.ogg b/sound/items/geiger_weak3.ogg new file mode 100644 index 00000000000..c935711aacf Binary files /dev/null and b/sound/items/geiger_weak3.ogg differ diff --git a/sound/items/geiger_weak4.ogg b/sound/items/geiger_weak4.ogg new file mode 100644 index 00000000000..2b17311a825 Binary files /dev/null and b/sound/items/geiger_weak4.ogg differ