From 8b9ef1e400c8940aaa1044a85c6b614fcd4d5a08 Mon Sep 17 00:00:00 2001 From: Poojawa Date: Tue, 11 Sep 2018 04:06:45 -0500 Subject: [PATCH] Game folder --- code/game/area/Space_Station_13_areas.dm | 24 +- code/game/area/areas.dm | 48 +- code/game/area/areas/shuttles.dm | 36 +- code/game/atoms.dm | 115 ++- code/game/atoms_movable.dm | 144 +++- code/game/data_huds.dm | 4 +- code/game/gamemodes/clock_cult/clock_cult.dm | 10 +- .../game/gamemodes/clown_ops/clown_weapons.dm | 8 +- code/game/gamemodes/cult/cult.dm | 6 +- code/game/gamemodes/game_mode.dm | 13 +- code/game/gamemodes/meteor/meteors.dm | 6 +- code/game/gamemodes/nuclear/nuclear.dm | 16 +- code/game/gamemodes/objective.dm | 8 +- code/game/gamemodes/overthrow/objective.dm | 152 ++++ code/game/gamemodes/overthrow/overthrow.dm | 76 ++ code/game/gamemodes/revolution/revolution.dm | 2 +- code/game/gamemodes/traitor/double_agents.dm | 3 +- code/game/gamemodes/traitor/traitor.dm | 2 +- code/game/machinery/PDApainter.dm | 2 +- code/game/machinery/Sleeper.dm | 18 +- code/game/machinery/_machinery.dm | 24 +- code/game/machinery/aug_manipulator.dm | 3 +- code/game/machinery/camera/camera.dm | 3 + code/game/machinery/camera/camera_assembly.dm | 3 + code/game/machinery/camera/motion.dm | 1 + code/game/machinery/cell_charger.dm | 1 + code/game/machinery/computer/Operating.dm | 41 +- code/game/machinery/computer/_computer.dm | 17 +- code/game/machinery/computer/apc_control.dm | 5 +- code/game/machinery/computer/arcade.dm | 13 +- code/game/machinery/computer/atmos_control.dm | 2 +- .../game/machinery/computer/buildandrepair.dm | 2 +- code/game/machinery/computer/camera.dm | 1 + .../machinery/computer/camera_advanced.dm | 29 +- code/game/machinery/computer/cloning.dm | 1 + .../game/machinery/computer/communications.dm | 43 +- code/game/machinery/computer/medical.dm | 1 + code/game/machinery/computer/prisoner.dm | 2 +- code/game/machinery/computer/security.dm | 1 + code/game/machinery/defibrillator_mount.dm | 2 +- code/game/machinery/dish_drive.dm | 1 + code/game/machinery/doors/airlock.dm | 48 +- .../machinery/doors/airlock_electronics.dm | 6 + code/game/machinery/doors/door.dm | 14 +- code/game/machinery/doors/firedoor.dm | 2 +- code/game/machinery/doors/passworddoor.dm | 2 +- code/game/machinery/doors/poddoor.dm | 4 +- code/game/machinery/doors/unpowered.dm | 2 +- code/game/machinery/doors/windowdoor.dm | 35 +- code/game/machinery/doppler_array.dm | 2 +- code/game/machinery/droneDispenser.dm | 2 +- code/game/machinery/firealarm.dm | 37 + code/game/machinery/flasher.dm | 6 +- code/game/machinery/harvester.dm | 184 +++++ code/game/machinery/launch_pad.dm | 82 +- code/game/machinery/newscaster.dm | 67 +- code/game/machinery/pipe/construction.dm | 4 + .../machinery/porta_turret/portable_turret.dm | 13 +- code/game/machinery/quantum_pad.dm | 37 +- code/game/machinery/recharger.dm | 28 +- code/game/machinery/recycler.dm | 4 +- code/game/machinery/requests_console.dm | 2 +- code/game/machinery/shieldgen.dm | 11 +- code/game/machinery/spaceheater.dm | 7 +- code/game/machinery/status_display.dm | 508 ++++++------ code/game/machinery/suit_storage_unit.dm | 3 +- code/game/machinery/telecomms/broadcasting.dm | 16 + .../machinery/telecomms/computers/message.dm | 2 +- .../machinery/telecomms/machines/allinone.dm | 2 +- .../telecomms/machines/message_server.dm | 2 +- code/game/machinery/teleporter.dm | 2 +- code/game/machinery/transformer.dm | 2 +- code/game/machinery/washing_machine.dm | 23 +- code/game/mecha/combat/honker.dm | 12 + code/game/mecha/equipment/mecha_equipment.dm | 8 +- .../mecha/equipment/tools/medical_tools.dm | 4 +- .../mecha/equipment/tools/mining_tools.dm | 4 +- .../game/mecha/equipment/tools/other_tools.dm | 2 +- code/game/mecha/equipment/tools/work_tools.dm | 10 +- code/game/mecha/mech_fabricator.dm | 2 +- code/game/mecha/mecha.dm | 9 +- code/game/mecha/mecha_actions.dm | 2 +- code/game/mecha/mecha_construction_paths.dm | 120 +-- code/game/mecha/mecha_defense.dm | 24 +- code/game/mecha/mecha_topic.dm | 2 +- code/game/mecha/medical/odysseus.dm | 2 +- code/game/objects/effects/anomalies.dm | 10 +- code/game/objects/effects/bump_teleporter.dm | 2 +- code/game/objects/effects/contraband.dm | 1 - code/game/objects/effects/countdown.dm | 2 +- code/game/objects/effects/decals/cleanable.dm | 7 +- .../effects/decals/cleanable/aliens.dm | 3 +- .../effects/decals/cleanable/humans.dm | 11 +- .../objects/effects/decals/cleanable/misc.dm | 37 +- .../effects/decals/cleanable/robots.dm | 6 +- code/game/objects/effects/decals/decal.dm | 2 +- .../effects/decals/turfdecal/tilecoloring.dm | 217 +---- .../effects/effect_system/effects_foam.dm | 6 - .../effects/effect_system/effects_other.dm | 12 - .../effects/effect_system/effects_smoke.dm | 46 +- .../effects/effect_system/effects_sparks.dm | 6 +- .../effects/effect_system/effects_water.dm | 2 +- code/game/objects/effects/mines.dm | 4 +- code/game/objects/effects/overlays.dm | 6 + code/game/objects/effects/portals.dm | 6 +- code/game/objects/effects/proximity.dm | 2 +- .../game/objects/effects/spawners/lootdrop.dm | 23 +- .../effects/spawners/xeno_egg_delivery.dm | 2 +- code/game/objects/effects/spiders.dm | 10 +- .../objects/effects/temporary_visuals/cult.dm | 2 +- .../temporary_visuals/projectiles/tracer.dm | 2 + code/game/objects/items.dm | 11 +- code/game/objects/items/AI_modules.dm | 39 + code/game/objects/items/RCD.dm | 24 +- code/game/objects/items/RCL.dm | 2 +- code/game/objects/items/RPD.dm | 4 +- code/game/objects/items/RSF.dm | 2 + code/game/objects/items/apc_frame.dm | 2 +- code/game/objects/items/bodybag.dm | 1 + code/game/objects/items/cards_ids.dm | 29 +- code/game/objects/items/chrono_eraser.dm | 20 +- code/game/objects/items/cigs_lighters.dm | 9 +- .../items/circuitboards/circuitboard.dm | 11 + .../circuitboards/computer_circuitboards.dm | 12 +- .../circuitboards/machine_circuitboards.dm | 14 +- code/game/objects/items/clown_items.dm | 3 +- code/game/objects/items/control_wand.dm | 4 +- code/game/objects/items/crayons.dm | 12 +- code/game/objects/items/defib.dm | 23 +- code/game/objects/items/devices/PDA/PDA.dm | 29 +- code/game/objects/items/devices/PDA/cart.dm | 18 + .../objects/items/devices/PDA/virus_cart.dm | 6 +- code/game/objects/items/devices/aicard.dm | 15 +- code/game/objects/items/devices/camera_bug.dm | 15 +- .../objects/items/devices/chameleonproj.dm | 3 +- .../devices/electroadaptive_pseudocircuit.dm | 1 + code/game/objects/items/devices/flashlight.dm | 5 +- .../items/devices/forcefieldprojector.dm | 21 +- .../objects/items/devices/geiger_counter.dm | 7 +- .../game/objects/items/devices/instruments.dm | 44 + .../objects/items/devices/laserpointer.dm | 9 +- .../objects/items/devices/lightreplacer.dm | 1 + code/game/objects/items/devices/megaphone.dm | 2 +- code/game/objects/items/devices/multitool.dm | 98 ++- .../objects/items/devices/pipe_painter.dm | 1 + .../objects/items/devices/radio/intercom.dm | 1 + code/game/objects/items/devices/scanners.dm | 17 +- .../objects/items/devices/taperecorder.dm | 4 +- .../objects/items/devices/traitordevices.dm | 4 +- code/game/objects/items/dna_injector.dm | 10 +- code/game/objects/items/extinguisher.dm | 111 +-- code/game/objects/items/flamethrower.dm | 3 +- code/game/objects/items/gift.dm | 4 +- code/game/objects/items/granters.dm | 4 +- .../objects/items/grenades/chem_grenade.dm | 36 +- code/game/objects/items/grenades/plastic.dm | 44 +- .../objects/items/grenades/spawnergrenade.dm | 7 + code/game/objects/items/handcuffs.dm | 10 +- code/game/objects/items/his_grace.dm | 52 +- code/game/objects/items/holosign_creator.dm | 9 + code/game/objects/items/holy_weapons.dm | 15 +- code/game/objects/items/hot_potato.dm | 7 +- code/game/objects/items/implants/implant.dm | 4 +- .../items/implants/implant_mindshield.dm | 8 +- .../objects/items/implants/implant_stealth.dm | 19 +- code/game/objects/items/implants/implanter.dm | 2 +- code/game/objects/items/manuals.dm | 771 +++--------------- code/game/objects/items/melee/misc.dm | 15 +- code/game/objects/items/mop.dm | 1 + code/game/objects/items/paint.dm | 2 + code/game/objects/items/pinpointer.dm | 6 - code/game/objects/items/plushes.dm | 6 +- code/game/objects/items/pneumaticCannon.dm | 26 +- code/game/objects/items/powerfist.dm | 2 +- code/game/objects/items/religion.dm | 3 +- code/game/objects/items/robot/ai_upgrades.dm | 2 + code/game/objects/items/robot/robot_items.dm | 4 +- code/game/objects/items/robot/robot_parts.dm | 4 + .../objects/items/robot/robot_upgrades.dm | 63 +- code/game/objects/items/singularityhammer.dm | 1 + .../game/objects/items/stacks/sheets/glass.dm | 1 + .../objects/items/stacks/sheets/leather.dm | 11 +- .../objects/items/stacks/sheets/mineral.dm | 14 + .../items/stacks/sheets/sheet_types.dm | 6 +- code/game/objects/items/stacks/stack.dm | 8 +- code/game/objects/items/stacks/telecrystal.dm | 3 +- .../objects/items/stacks/tiles/tile_types.dm | 3 + code/game/objects/items/stacks/wrap.dm | 3 +- code/game/objects/items/storage/bags.dm | 2 +- code/game/objects/items/storage/book.dm | 19 +- code/game/objects/items/storage/boxes.dm | 25 +- code/game/objects/items/storage/toolbox.dm | 15 +- .../game/objects/items/storage/uplink_kits.dm | 8 + code/game/objects/items/stunbaton.dm | 2 +- code/game/objects/items/tanks/jetpack.dm | 32 + code/game/objects/items/tanks/tanks.dm | 3 +- code/game/objects/items/tanks/watertank.dm | 9 +- code/game/objects/items/taster.dm | 1 + code/game/objects/items/teleportation.dm | 7 +- code/game/objects/items/theft_tools.dm | 1 + code/game/objects/items/tools/weldingtool.dm | 1 + code/game/objects/items/toys.dm | 11 +- code/game/objects/items/twohanded.dm | 71 +- code/game/objects/items/weaponry.dm | 14 +- code/game/objects/obj_defense.dm | 9 +- code/game/objects/objs.dm | 2 +- code/game/objects/structures.dm | 2 +- code/game/objects/structures/aliens.dm | 6 +- code/game/objects/structures/artstuff.dm | 11 +- code/game/objects/structures/barsigns.dm | 24 +- .../objects/structures/beds_chairs/bed.dm | 1 + .../objects/structures/beds_chairs/chair.dm | 18 +- code/game/objects/structures/bedsheet_bin.dm | 2 +- .../structures/crates_lockers/closets.dm | 17 +- .../crates_lockers/closets/cardboardbox.dm | 3 +- .../crates_lockers/closets/secure/cargo.dm | 1 + .../closets/secure/supplypod.dm | 4 +- .../structures/crates_lockers/crates.dm | 2 +- .../crates_lockers/crates/secure.dm | 5 +- code/game/objects/structures/displaycase.dm | 4 +- code/game/objects/structures/door_assembly.dm | 2 + code/game/objects/structures/extinguisher.dm | 1 + code/game/objects/structures/false_walls.dm | 5 - code/game/objects/structures/flora.dm | 3 - .../objects/structures/ghost_role_spawners.dm | 9 +- code/game/objects/structures/girders.dm | 3 + code/game/objects/structures/grille.dm | 3 +- code/game/objects/structures/guillotine.dm | 6 +- code/game/objects/structures/holosign.dm | 47 +- code/game/objects/structures/janicart.dm | 2 + code/game/objects/structures/manned_turret.dm | 2 +- code/game/objects/structures/mineral_doors.dm | 7 +- code/game/objects/structures/mop_bucket.dm | 12 +- code/game/objects/structures/morgue.dm | 8 +- code/game/objects/structures/plasticflaps.dm | 6 +- code/game/objects/structures/safe.dm | 12 +- code/game/objects/structures/showcase.dm | 4 - code/game/objects/structures/signs/_signs.dm | 3 +- code/game/objects/structures/spirit_board.dm | 2 +- code/game/objects/structures/statues.dm | 16 +- code/game/objects/structures/tables_racks.dm | 55 +- .../structures/transit_tubes/station.dm | 4 +- code/game/objects/structures/watercloset.dm | 5 + .../objects/structures/windoor_assembly.dm | 2 +- code/game/objects/structures/window.dm | 2 +- code/game/say.dm | 6 +- code/game/shuttle_engines.dm | 1 - code/game/sound.dm | 57 +- code/game/turfs/closed.dm | 3 + code/game/turfs/open.dm | 15 + code/game/turfs/simulated/floor.dm | 4 + .../game/turfs/simulated/floor/fancy_floor.dm | 12 + .../game/turfs/simulated/floor/light_floor.dm | 1 + .../turfs/simulated/floor/mineral_floor.dm | 56 +- code/game/turfs/simulated/floor/misc_floor.dm | 6 +- .../turfs/simulated/floor/plasteel_floor.dm | 295 +------ code/game/turfs/simulated/floor/plating.dm | 2 + .../turfs/simulated/floor/plating/asteroid.dm | 2 + .../turfs/simulated/floor/plating/dirt.dm | 2 + .../simulated/floor/plating/misc_plating.dm | 10 + .../game/turfs/simulated/floor/reinf_floor.dm | 5 +- code/game/turfs/simulated/lava.dm | 2 + code/game/turfs/simulated/minerals.dm | 2 +- code/game/turfs/simulated/reebe_void.dm | 1 + .../turfs/simulated/wall/mineral_walls.dm | 6 +- code/game/turfs/simulated/walls.dm | 2 +- code/game/turfs/simulated/water.dm | 4 +- code/game/turfs/space/space.dm | 2 +- code/game/turfs/turf.dm | 68 +- code/game/world.dm | 27 +- 270 files changed, 3120 insertions(+), 2523 deletions(-) create mode 100644 code/game/gamemodes/overthrow/objective.dm create mode 100644 code/game/gamemodes/overthrow/overthrow.dm create mode 100644 code/game/machinery/harvester.dm diff --git a/code/game/area/Space_Station_13_areas.dm b/code/game/area/Space_Station_13_areas.dm index 1bd30a77f5..8a40fc8b56 100644 --- a/code/game/area/Space_Station_13_areas.dm +++ b/code/game/area/Space_Station_13_areas.dm @@ -499,18 +499,18 @@ NOTE: there are two lists of areas in the end of this file: centcom and station icon_state = "Theatre" /area/library - name = "Library" - icon_state = "library" - flags_1 = NONE + name = "Library" + icon_state = "library" + flags_1 = NONE /area/library/lounge - name = "Library Lounge" - icon_state = "library" + name = "Library Lounge" + icon_state = "library" /area/library/abandoned - name = "Abandoned Library" - icon_state = "library" - flags_1 = NONE + name = "Abandoned Library" + icon_state = "library" + flags_1 = NONE /area/chapel icon_state = "chapel" @@ -559,9 +559,9 @@ NOTE: there are two lists of areas in the end of this file: centcom and station icon_state = "engine" /area/engine/atmos - name = "Atmospherics" - icon_state = "atmos" - flags_1 = NONE + name = "Atmospherics" + icon_state = "atmos" + flags_1 = NONE /area/engine/atmospherics_engine name = "Atmospherics Engine" @@ -1297,7 +1297,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station clockwork_warp_allowed = FALSE clockwork_warp_fail = "For safety reasons, warping here is disallowed; the radio and bluespace noise could cause catastrophic results." ambientsounds = list('sound/ambience/ambisin2.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/ambigen10.ogg', 'sound/ambience/ambitech.ogg',\ - 'sound/ambience/ambitech2.ogg', 'sound/ambience/ambitech3.ogg', 'sound/ambience/ambimystery.ogg') + 'sound/ambience/ambitech2.ogg', 'sound/ambience/ambitech3.ogg', 'sound/ambience/ambimystery.ogg') /area/tcommsat/entrance name = "Telecomms Teleporter" diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index 8aa910b2e2..10650153d6 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -29,8 +29,6 @@ var/outdoors = FALSE //For space, the asteroid, lavaland, etc. Used with blueprints to determine if we are adding a new area (vs editing a station room) - var/totalbeauty = 0 //All beauty in this area combined, only includes indoor area. - var/beauty = 0 // Beauty average per open turf in the area var/areasize = 0 //Size of the area in open turfs, only calculated for indoors areas. var/power_equip = TRUE @@ -48,6 +46,8 @@ var/noteleport = FALSE //Are you forbidden from teleporting to the area? (centcom, mobs, wizard, hand teleporter) var/hidden = FALSE //Hides area from player Teleport function. var/safe = FALSE //Is the area teleport-safe: no space / radiation / aggresive mobs / other dangers + /// If false, loading multiple maps with this area type will create multiple instances. + var/unique = TRUE var/no_air = null @@ -84,6 +84,12 @@ GLOBAL_LIST_EMPTY(teleportlocs) // === +/area/New() + // This interacts with the map loader, so it needs to be set immediately + // rather than waiting for atoms to initialize. + if (unique) + GLOB.areas_by_type[type] = src + return ..() /area/Initialize() icon_state = "" @@ -135,9 +141,10 @@ GLOBAL_LIST_EMPTY(teleportlocs) /area/LateInitialize() power_change() // all machines set to current power level, also updates icon - update_beauty() /area/Destroy() + if(GLOB.areas_by_type[type] == src) + GLOB.areas_by_type[type] = null STOP_PROCESSING(SSobj, src) return ..() @@ -448,26 +455,22 @@ GLOBAL_LIST_EMPTY(teleportlocs) if(!T) return 0 - //Gravity forced on the atom - var/datum/component/forced_gravity/FG = GetComponent(/datum/component/forced_gravity) - if(FG) - if(!FG.ignore_space && isspaceturf(T)) - return 0 - else - return FG.gravity + var/list/forced_gravity = list() + SEND_SIGNAL(src, COMSIG_ATOM_HAS_GRAVITY, T, forced_gravity) + if(!forced_gravity.len) + SEND_SIGNAL(T, COMSIG_TURF_HAS_GRAVITY, src, forced_gravity) + if(forced_gravity.len) + var/max_grav + for(var/i in forced_gravity) + max_grav = max(max_grav, i) + if(max_grav) + return max_grav - //Gravity forced on the turf - FG = T.GetComponent(/datum/component/forced_gravity) - if(FG) - if(!FG.ignore_space && isspaceturf(T)) - return 0 - else - return FG.gravity - - var/area/A = get_area(T) if(isspaceturf(T)) // Turf never has gravity return 0 - else if(A.has_gravity) // Areas which always has gravity + + var/area/A = get_area(T) + if(A.has_gravity) // Areas which always has gravity return A.has_gravity else // There's a gravity generator on our z level @@ -488,11 +491,6 @@ GLOBAL_LIST_EMPTY(teleportlocs) blob_allowed = FALSE addSorted() -/area/proc/update_beauty() - if(!areasize) - return FALSE - beauty = totalbeauty / areasize - /area/proc/update_areasize() if(outdoors) return FALSE diff --git a/code/game/area/areas/shuttles.dm b/code/game/area/areas/shuttles.dm index 8e23614db0..ab4fa10d44 100644 --- a/code/game/area/areas/shuttles.dm +++ b/code/game/area/areas/shuttles.dm @@ -10,6 +10,8 @@ always_unpowered = FALSE valid_territory = FALSE icon_state = "shuttle" + // Loading the same shuttle map at a different time will produce distinct area instances. + unique = FALSE /area/shuttle/Initialize() if(!canSmoothWithAreas) @@ -62,6 +64,35 @@ name = "Pirate Shuttle Vault" requires_power = FALSE +////////////////////////////White Ship//////////////////////////// + +/area/shuttle/abandoned + name = "Abandoned Ship" + blob_allowed = FALSE + requires_power = TRUE + canSmoothWithAreas = /area/shuttle/abandoned + +/area/shuttle/abandoned/bridge + name = "Abandoned Ship Bridge" + +/area/shuttle/abandoned/engine + name = "Abandoned Ship Engine" + +/area/shuttle/abandoned/bar + name = "Abandoned Ship Bar" + +/area/shuttle/abandoned/crew + name = "Abandoned Ship Crew Quarters" + +/area/shuttle/abandoned/cargo + name = "Abandoned Ship Cargo Bay" + +/area/shuttle/abandoned/medbay + name = "Abandoned Ship Medbay" + +/area/shuttle/abandoned/pod + name = "Abandoned Ship Pod" + ////////////////////////////Single-area shuttles//////////////////////////// /area/shuttle/transit @@ -74,6 +105,7 @@ /area/shuttle/arrival name = "Arrival Shuttle" + unique = TRUE // SSjob refers to this area for latejoiners /area/shuttle/pod_1 name = "Escape Pod One" @@ -125,10 +157,6 @@ name = "Steel Rain" blob_allowed = FALSE -/area/shuttle/abandoned - name = "Abandoned Ship" - blob_allowed = FALSE - /area/shuttle/sbc_starfury name = "SBC Starfury" blob_allowed = FALSE diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 68089905b6..c036127fac 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -24,6 +24,8 @@ var/list/remove_overlays // a very temporary list of overlays to remove var/list/add_overlays // a very temporary list of overlays to add + var/list/managed_vis_overlays //vis overlays managed by SSvis_overlays to automaticaly turn them like other overlays + var/datum/proximity_monitor/proximity_monitor var/buckle_message_cooldown = 0 var/fingerprintslast @@ -45,10 +47,6 @@ //we were deleted return - var/list/created = SSatoms.created_atoms - if(created) - created += src - //Called after New if the map is being loaded. mapload = TRUE //Called from base of New if the map is not being loaded. mapload = FALSE //This base must be called or derivatives must set initialized to TRUE @@ -157,7 +155,7 @@ SEND_SIGNAL(src, COMSIG_ATOM_HULK_ATTACK, user) if(does_attack_animation) user.changeNext_move(CLICK_CD_MELEE) - add_logs(user, src, "punched", "hulk powers") + log_combat(user, src, "punched", "hulk powers") user.do_attack_animation(src, ATTACK_EFFECT_SMASH) /atom/proc/CheckParts(list/parts_list) @@ -191,10 +189,8 @@ /atom/proc/check_eye(mob/user) return - -/atom/proc/CollidedWith(atom/movable/AM) +/atom/proc/Bumped(atom/movable/AM) set waitfor = FALSE - return // Convenience procs to see if a container is open for chemistry handling /atom/proc/is_open_container() @@ -571,7 +567,7 @@ return /atom/proc/screwdriver_act(mob/living/user, obj/item/I) - return + SEND_SIGNAL(src, COMSIG_ATOM_SCREWDRIVER_ACT, user, I) /atom/proc/wrench_act(mob/living/user, obj/item/I) return @@ -588,6 +584,99 @@ /atom/proc/GenerateTag() return +// Generic logging helper +/atom/proc/log_message(message, message_type, color=null, log_globally=TRUE) + if(!log_globally) + return + + var/log_text = "[key_name(src)] [message] [loc_name(src)]" + switch(message_type) + if(LOG_ATTACK) + log_attack(log_text) + if(LOG_SAY) + log_say(log_text) + if(LOG_WHISPER) + log_whisper(log_text) + if(LOG_EMOTE) + log_emote(log_text) + if(LOG_SUBTLE) + log_subtle(log_text) + if(LOG_DSAY) + log_dsay(log_text) + if(LOG_PDA) + log_pda(log_text) + if(LOG_CHAT) + log_chat(log_text) + if(LOG_COMMENT) + log_comment(log_text) + if(LOG_TELECOMMS) + log_telecomms(log_text) + if(LOG_OOC) + log_ooc(log_text) + if(LOG_LOOC) + log_looc(log_text) + if(LOG_ADMIN) + log_admin(log_text) + if(LOG_ADMIN_PRIVATE) + log_admin_private(log_text) + if(LOG_ASAY) + log_adminsay(log_text) + if(LOG_OWNERSHIP) + log_game(log_text) + if(LOG_GAME) + log_game(log_text) + else + stack_trace("Invalid individual logging type: [message_type]. Defaulting to [LOG_GAME] (LOG_GAME).") + log_game(log_text) + +// Helper for logging chat messages or other logs with arbitrary inputs (e.g. announcements) +/atom/proc/log_talk(message, message_type, tag=null, log_globally=TRUE, forced_by=null) + var/prefix = tag ? "([tag]) " : "" + var/suffix = forced_by ? " FORCED by [forced_by]" : "" + log_message("[prefix]\"[message]\"[suffix]", message_type, log_globally=log_globally) + +// Helper for logging of messages with only one sender and receiver +/proc/log_directed_talk(atom/source, atom/target, message, message_type, tag) + if(!tag) + stack_trace("Unspecified tag for private message") + tag = "UNKNOWN" + + source.log_talk(message, message_type, tag="[tag] to [key_name(target)]") + if(source != target) + target.log_talk(message, message_type, tag="[tag] from [key_name(source)]", log_globally=FALSE) + +/* +Proc for attack log creation, because really why not +1 argument is the actor performing the action +2 argument is the target of the action +3 is a verb describing the action (e.g. punched, throwed, kicked, etc.) +4 is a tool with which the action was made (usually an item) +5 is any additional text, which will be appended to the rest of the log line +*/ + +/proc/log_combat(atom/user, atom/target, what_done, atom/object=null, addition=null) + var/ssource = key_name(user) + var/starget = key_name(target) + + var/mob/living/living_target = target + var/hp = istype(living_target) ? " (NEWHP: [living_target.health]) " : "" + + var/sobject = "" + if(object) + sobject = " with [key_name(object)]" + var/saddition = "" + if(addition) + saddition = " [addition]" + + var/postfix = "[sobject][saddition][hp]" + + var/message = "has [what_done] [starget][postfix]" + user.log_message(message, LOG_ATTACK, color="red") + + if(user != target) + var/reverse_message = "has been [what_done] by [ssource][postfix]" + target.log_message(reverse_message, LOG_ATTACK, color="orange", log_globally=FALSE) + // Filter stuff /atom/movable/proc/add_filter(name,priority,list/params) if(!filter_data) @@ -608,10 +697,4 @@ /atom/movable/proc/get_filter(name) if(filter_data && filter_data[name]) - return filters[filter_data.Find(name)] - -/atom/movable/proc/remove_filter(name) - if(filter_data[name]) - filter_data -= name - update_filters() - return TRUE \ No newline at end of file + return filters[filter_data.Find(name)] \ No newline at end of file diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 366e1ad539..ba840d0771 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -1,6 +1,7 @@ /atom/movable layer = OBJ_LAYER var/last_move = null + var/last_move_time = 0 var/anchored = FALSE var/datum/thrownthing/throwing = null var/throw_speed = 2 //How many tiles to move per ds when being thrown. Float values are fully supported @@ -58,9 +59,12 @@ return TRUE return FALSE if("loc") - if(var_value == null || istype(var_value, /atom)) + if(istype(var_value, /atom)) forceMove(var_value) return TRUE + else if(isnull(var_value)) + moveToNullspace() + return TRUE return FALSE return ..() @@ -84,14 +88,14 @@ return TRUE stop_pulling() if(AM.pulledby) - add_logs(AM, AM.pulledby, "pulled from", src) + log_combat(AM, AM.pulledby, "pulled from", src) AM.pulledby.stop_pulling() //an object can't be pulled by two mobs at once. pulling = AM AM.pulledby = src grab_state = gs if(ismob(AM)) var/mob/M = AM - add_logs(src, M, "grabbed", addition="passive grab") + log_combat(src, M, "grabbed", addition="passive grab") visible_message("[src] has grabbed [M] passively!") return TRUE @@ -139,10 +143,54 @@ stop_pulling() return +//////////////////////////////////////// +// Here's where we rewrite how byond handles movement except slightly different +// To be removed on step_ conversion +// All this work to prevent a second bump +/atom/movable/Move(atom/newloc, direct=0) + . = FALSE + if(!newloc || newloc == loc) + return + if(!direct) + direct = get_dir(src, newloc) + setDir(direct) + if(!loc.Exit(src, newloc)) + return -/atom/movable/Move(atom/newloc, direct = 0) + if(!newloc.Enter(src, src.loc)) + return + + // Past this is the point of no return + var/atom/oldloc = loc + var/area/oldarea = get_area(oldloc) + var/area/newarea = get_area(newloc) + loc = newloc + . = TRUE + oldloc.Exited(src, newloc) + if(oldarea != newarea) + oldarea.Exited(src, newloc) + + for(var/i in oldloc) + if(i == src) // Multi tile objects + continue + var/atom/movable/thing = i + thing.Uncrossed(src) + + newloc.Entered(src, oldloc) + if(oldarea != newarea) + newarea.Entered(src, oldloc) + + for(var/i in loc) + if(i == src) // Multi tile objects + continue + var/atom/movable/thing = i + thing.Crossed(src) +// +//////////////////////////////////////// + +/atom/movable/Move(atom/newloc, direct) var/atom/movable/pullee = pulling var/turf/T = loc if(pulling) @@ -163,7 +211,7 @@ moving_diagonally = FIRST_DIAG_STEP var/first_step_dir // The `&& moving_diagonally` checks are so that a forceMove taking - // place due to a Crossed, Collided, etc. call will interrupt + // place due to a Crossed, Bumped, etc. call will interrupt // the second half of the diagonal movement, or the second attempt // at a first half if step() fails because we hit something. if (direct & NORTH) @@ -257,7 +305,6 @@ return 1 /atom/movable/Destroy(force) - QDEL_NULL(proximity_monitor) QDEL_NULL(language_holder) @@ -265,6 +312,10 @@ . = ..() if(loc) + //Restore air flow if we were blocking it (movables with ATMOS_PASS_PROC will need to do this manually if necessary) + if(((CanAtmosPass == ATMOS_PASS_DENSITY && density) || CanAtmosPass == ATMOS_PASS_NO) && isturf(loc)) + CanAtmosPass = ATMOS_PASS_YES + air_update_turf(TRUE) loc.handle_atom_del(src) for(var/atom/movable/AM in contents) qdel(AM) @@ -273,28 +324,38 @@ if(pulledby) pulledby.stop_pulling() +// Make sure you know what you're doing if you call this, this is intended to only be called by byond directly. +// You probably want CanPass() +/atom/movable/Cross(atom/movable/AM) + . = TRUE + SEND_SIGNAL(src, COMSIG_MOVABLE_CROSS, AM) + return CanPass(AM, AM.loc, TRUE) -// Previously known as HasEntered() -// This is automatically called when something enters your square //oldloc = old location on atom, inserted when forceMove is called and ONLY when forceMove is called! /atom/movable/Crossed(atom/movable/AM, oldloc) SEND_SIGNAL(src, COMSIG_MOVABLE_CROSSED, AM) +/atom/movable/Uncross(atom/movable/AM, atom/newloc) + . = ..() + if(SEND_SIGNAL(src, COMSIG_MOVABLE_UNCROSS, AM) & COMPONENT_MOVABLE_BLOCK_UNCROSS) + return FALSE + if(isturf(newloc) && !CheckExit(AM, newloc)) + return FALSE + /atom/movable/Uncrossed(atom/movable/AM) SEND_SIGNAL(src, COMSIG_MOVABLE_UNCROSSED, AM) -//This is tg's equivalent to the byond bump, it used to be called bump with a second arg -//to differentiate it, naturally everyone forgot about this immediately and so some things -//would bump twice, so now it's called Collide -/atom/movable/proc/Collide(atom/A) - SEND_SIGNAL(src, COMSIG_MOVABLE_COLLIDE, A) - if(A) - if(throwing) - throwing.hit_atom(A) - . = TRUE - if(!A || QDELETED(A)) - return - A.CollidedWith(src) +/atom/movable/Bump(atom/A) + if(!A) + CRASH("Bump was called with no argument.") + SEND_SIGNAL(src, COMSIG_MOVABLE_BUMP, A) + . = ..() + if(!QDELETED(throwing)) + throwing.hit_atom(A) + . = TRUE + if(QDELETED(A)) + return + A.Bumped(src) /atom/movable/proc/forceMove(atom/destination) . = FALSE @@ -322,8 +383,10 @@ if(!same_loc) if(oldloc) oldloc.Exited(src, destination) - if(old_area) + if(old_area && old_area != destarea) old_area.Exited(src, destination) + for(var/atom/movable/AM in oldloc) + AM.Uncrossed(src) var/turf/oldturf = get_turf(oldloc) var/turf/destturf = get_turf(destination) var/old_z = (oldturf ? oldturf.z : null) @@ -413,6 +476,9 @@ if (!target || speed <= 0) return + if(SEND_SIGNAL(src, COMSIG_MOVABLE_PRE_THROW, args) & COMPONENT_CANCEL_THROW) + return + if (pulledby) pulledby.stop_pulling() @@ -482,12 +548,11 @@ if(spin) SpinAnimation(5, 1) - SEND_SIGNAL(src, COMSIG_MOVABLE_PRE_THROW, TT, spin) //CITADEL - THIS IS BORKED. PENDING SYNC. + SEND_SIGNAL(src, COMSIG_MOVABLE_POST_THROW, TT, spin) SSthrowing.processing[src] = TT if (SSthrowing.state == SS_PAUSED && length(SSthrowing.currentrun)) SSthrowing.currentrun[src] = TT TT.tick() - SEND_SIGNAL(src, COMSIG_MOVABLE_POST_THROW, TT, spin) /atom/movable/proc/handle_buckled_mob_movement(newloc,direct) for(var/m in buckled_mobs) @@ -721,3 +786,36 @@ if(anchored || throwing) return FALSE return TRUE + + +/obj/item/proc/do_pickup_animation(atom/target) + set waitfor = FALSE + if(!istype(loc, /turf)) + return + var/image/I = image(icon = src, loc = loc, layer = layer + 0.1) + I.plane = GAME_PLANE + I.transform *= 0.75 + I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA + var/turf/T = get_turf(src) + var/direction + var/to_x = 0 + var/to_y = 0 + + if(!QDELETED(T) && !QDELETED(target)) + direction = get_dir(T, target) + if(direction & NORTH) + to_y = 32 + else if(direction & SOUTH) + to_y = -32 + if(direction & EAST) + to_x = 32 + else if(direction & WEST) + to_x = -32 + if(!direction) + to_y = 16 + flick_overlay(I, GLOB.clients, 6) + var/matrix/M = new + M.Turn(pick(-30, 30)) + animate(I, alpha = 175, pixel_x = to_x, pixel_y = to_y, time = 3, transform = M, easing = CUBIC_EASING) + sleep(1) + animate(I, alpha = 0, transform = matrix(), time = 1) diff --git a/code/game/data_huds.dm b/code/game/data_huds.dm index d372986569..7a341ad69a 100644 --- a/code/game/data_huds.dm +++ b/code/game/data_huds.dm @@ -65,7 +65,7 @@ /datum/atom_hud/sentient_disease hud_icons = list(SENTIENT_DISEASE_HUD) -/* + /datum/atom_hud/ai_detector hud_icons = list(AI_DETECT_HUD) @@ -74,7 +74,7 @@ if(M && (hudusers.len == 1)) for(var/V in GLOB.aiEyes) var/mob/camera/aiEye/E = V - E.update_ai_detect_hud()*/ + E.update_ai_detect_hud() /* MED/SEC/DIAG HUD HOOKS */ diff --git a/code/game/gamemodes/clock_cult/clock_cult.dm b/code/game/gamemodes/clock_cult/clock_cult.dm index 1403990c65..f0ccf235ae 100644 --- a/code/game/gamemodes/clock_cult/clock_cult.dm +++ b/code/game/gamemodes/clock_cult/clock_cult.dm @@ -4,11 +4,11 @@ GLOBAL_VAR_INIT(servants_active, FALSE) //This var controls whether or not a lot CLOCKWORK CULT: Based off of the failed pull requests from /vg/ -While Nar-Sie is the oldest and most prominent of the elder gods, there are other forces at work in the universe. -Ratvar, the Clockwork Justiciar, a homage to Nar-Sie granted sentience by its own power, is one such other force. +While Nar'Sie is the oldest and most prominent of the elder gods, there are other forces at work in the universe. +Ratvar, the Clockwork Justiciar, a homage to Nar'Sie granted sentience by its own power, is one such other force. Imprisoned within a massive construct known as the Celestial Derelict - or Reebe - an intense hatred of the Blood God festers. Ratvar, unable to act in the mortal plane, seeks to return and forms covenants with mortals in order to bolster his influence. -Due to his mechanical nature, Ratvar is also capable of influencing silicon-based lifeforms, unlike Nar-Sie, who can only influence natural life. +Due to his mechanical nature, Ratvar is also capable of influencing silicon-based lifeforms, unlike Nar'Sie, who can only influence natural life. This is a team-based gamemode, and the team's objective is shared by all cultists. Their goal is to defend an object called the Ark on a separate z-level. @@ -148,11 +148,13 @@ Credit where due: /datum/game_mode/clockwork_cult/pre_setup() var/list/errorList = list() - SSmapping.LoadGroup(errorList, "Reebe", "map_files/generic", "City_of_Cogs.dmm", default_traits = ZTRAITS_REEBE, silent = TRUE) + var/list/reebes = SSmapping.LoadGroup(errorList, "Reebe", "map_files/generic", "City_of_Cogs.dmm", default_traits = ZTRAITS_REEBE, silent = TRUE) if(errorList.len) // reebe failed to load message_admins("Reebe failed to load!") log_game("Reebe failed to load!") return FALSE + for(var/datum/parsed_map/PM in reebes) + PM.initTemplateBounds() if(CONFIG_GET(flag/protect_roles_from_antagonist)) restricted_jobs += protected_jobs if(CONFIG_GET(flag/protect_assistant_from_antagonist)) diff --git a/code/game/gamemodes/clown_ops/clown_weapons.dm b/code/game/gamemodes/clown_ops/clown_weapons.dm index bf401e5ad2..a3440fad39 100644 --- a/code/game/gamemodes/clown_ops/clown_weapons.dm +++ b/code/game/gamemodes/clown_ops/clown_weapons.dm @@ -74,7 +74,7 @@ . = ..() AddComponent(/datum/component/slippery, 60, GALOSHES_DONT_HELP) GET_COMPONENT(slipper, /datum/component/slippery) - slipper.enabled = active + slipper.signal_enabled = active /obj/item/melee/transforming/energy/sword/bananium/attack(mob/living/M, mob/living/user) ..() @@ -99,7 +99,7 @@ /obj/item/melee/transforming/energy/sword/bananium/transform_weapon(mob/living/user, supress_message_text) ..() GET_COMPONENT(slipper, /datum/component/slippery) - slipper.enabled = active + slipper.signal_enabled = active /obj/item/melee/transforming/energy/sword/bananium/ignition_effect(atom/A, mob/user) return "" @@ -131,12 +131,12 @@ . = ..() AddComponent(/datum/component/slippery, 60, GALOSHES_DONT_HELP) GET_COMPONENT(slipper, /datum/component/slippery) - slipper.enabled = active + slipper.signal_enabled = active /obj/item/shield/energy/bananium/attack_self(mob/living/carbon/human/user) ..() GET_COMPONENT(slipper, /datum/component/slippery) - slipper.enabled = active + slipper.signal_enabled = active /obj/item/shield/energy/bananium/throw_at(atom/target, range, speed, mob/thrower, spin=1) if(active) diff --git a/code/game/gamemodes/cult/cult.dm b/code/game/gamemodes/cult/cult.dm index 9d828fb662..13ceff2451 100644 --- a/code/game/gamemodes/cult/cult.dm +++ b/code/game/gamemodes/cult/cult.dm @@ -43,8 +43,8 @@ enemy_minimum_age = 14 announce_span = "cult" - announce_text = "Some crew members are trying to start a cult to Nar-Sie!\n\ - Cultists: Carry out Nar-Sie's will.\n\ + announce_text = "Some crew members are trying to start a cult to Nar'Sie!\n\ + Cultists: Carry out Nar'Sie's will.\n\ Crew: Prevent the cult from expanding and drive it out." var/finished = 0 @@ -158,7 +158,7 @@ /datum/game_mode/cult/generate_report() return "Some stations in your sector have reported evidence of blood sacrifice and strange magic. Ties to the Wizards' Federation have been proven not to exist, and many employees \ have disappeared; even Central Command employees light-years away have felt strange presences and at times hysterical compulsions. Interrogations point towards this being the work of \ - the cult of Nar-Sie. If evidence of this cult is discovered aboard your station, extreme caution and extreme vigilance must be taken going forward, and all resources should be \ + the cult of Nar'Sie. If evidence of this cult is discovered aboard your station, extreme caution and extreme vigilance must be taken going forward, and all resources should be \ devoted to stopping this cult. Note that holy water seems to weaken and eventually return the minds of cultists that ingest it, and mindshield implants will prevent conversion \ altogether." diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 85c2ddd877..d16cbebb2a 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -47,9 +47,8 @@ var/allow_persistence_save = TRUE var/gamemode_ready = FALSE //Is the gamemode all set up and ready to start checking for ending conditions. - - var/flipseclevel = FALSE //CIT CHANGE - adds a 10% chance for the alert level to be the opposite of what the gamemode is supposed to have var/setup_error //What stopepd setting up the mode. + var/flipseclevel = FALSE //CIT CHANGE - adds a 10% chance for the alert level to be the opposite of what the gamemode is supposed to have /datum/game_mode/proc/announce() //Shows the gamemode's name and a fast description. to_chat(world, "The gamemode is: [name]!") @@ -87,7 +86,6 @@ if(prob(20)) //CIT CHANGE - adds a 20% chance for the security level to be the opposite of what it normally is flipseclevel = TRUE - if(SSdbcore.Connect()) var/sql if(SSticker.mode) @@ -181,12 +179,13 @@ round_converted = 0 return //somewhere between 1 and 3 minutes from now - if(!CONFIG_GET(keyed_flag_list/midround_antag)[SSticker.mode.config_tag]) + if(!CONFIG_GET(keyed_list/midround_antag)[SSticker.mode.config_tag]) round_converted = 0 return 1 for(var/mob/living/carbon/human/H in antag_candidates) if(H.client) replacementmode.make_antag_chance(H) + replacementmode.gamemode_ready = TRUE //Awful but we're not doing standard setup here. round_converted = 2 message_admins("-- IMPORTANT: The roundtype has been converted to [replacementmode.name], antagonists may have been created! --") @@ -209,8 +208,8 @@ return TRUE if(station_was_nuked) return TRUE - var/list/continuous = CONFIG_GET(keyed_flag_list/continuous) - var/list/midround_antag = CONFIG_GET(keyed_flag_list/midround_antag) + var/list/continuous = CONFIG_GET(keyed_list/continuous) + var/list/midround_antag = CONFIG_GET(keyed_list/midround_antag) if(!round_converted && (!continuous[config_tag] || (continuous[config_tag] && midround_antag[config_tag]))) //Non-continuous or continous with replacement antags if(!continuous_sanity_checked) //make sure we have antags to be checking in the first place for(var/mob/Player in GLOB.mob_list) @@ -226,7 +225,7 @@ return 0 - if(living_antag_player && living_antag_player.mind && isliving(living_antag_player) && living_antag_player.stat != DEAD && !isnewplayer(living_antag_player) &&!isbrain(living_antag_player)) + if(living_antag_player && living_antag_player.mind && isliving(living_antag_player) && living_antag_player.stat != DEAD && !isnewplayer(living_antag_player) &&!isbrain(living_antag_player) && (living_antag_player.mind.special_role || LAZYLEN(living_antag_player.mind.antag_datums))) return 0 //A resource saver: once we find someone who has to die for all antags to be dead, we can just keep checking them, cycling over everyone only when we lose our mark. for(var/mob/Player in GLOB.alive_mob_list) diff --git a/code/game/gamemodes/meteor/meteors.dm b/code/game/gamemodes/meteor/meteors.dm index b68d55f9dd..426d23b4ab 100644 --- a/code/game/gamemodes/meteor/meteors.dm +++ b/code/game/gamemodes/meteor/meteors.dm @@ -132,7 +132,7 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event timerid = QDEL_IN(src, lifetime) chase_target(target) -/obj/effect/meteor/Collide(atom/A) +/obj/effect/meteor/Bump(atom/A) if(A) ram_turf(get_turf(A)) playsound(src.loc, meteorsound, 40, 1) @@ -301,7 +301,7 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event if(!isspaceturf(T)) new /obj/effect/decal/cleanable/blood(T) -/obj/effect/meteor/meaty/Collide(atom/A) +/obj/effect/meteor/meaty/Bump(atom/A) A.ex_act(hitpwr) get_hit() @@ -340,7 +340,7 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event ..() explosion(src.loc, 5, 10, 15, 20, 0) -/obj/effect/meteor/tunguska/Collide() +/obj/effect/meteor/tunguska/Bump() ..() if(prob(20)) explosion(src.loc,2,4,6,8) diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm index 4eb5dc1c6e..b269a5abe5 100644 --- a/code/game/gamemodes/nuclear/nuclear.dm +++ b/code/game/gamemodes/nuclear/nuclear.dm @@ -64,17 +64,13 @@ return FALSE return TRUE -/datum/game_mode/nuclear/check_finished() //to be called by SSticker - if(replacementmode && round_converted == 2) - return replacementmode.check_finished() - if((SSshuttle.emergency.mode == SHUTTLE_ENDGAME) || station_was_nuked) - return TRUE +/datum/game_mode/nuclear/check_finished() + //Keep the round going if ops are dead but bomb is ticking. if(nuke_team.operatives_dead()) - var/obj/machinery/nuclearbomb/N - pass(N) //suppress unused warning - if(N.bomb_set) //snaaaaaaaaaake! It's not over yet! - return FALSE //its a static var btw - ..() + for(var/obj/machinery/nuclearbomb/N in GLOB.nuke_list) + if(N.proper_bomb && (N.timing || N.exploding)) + return FALSE + return ..() /datum/game_mode/nuclear/set_round_result() ..() diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index b32460dabc..41e429319c 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -25,12 +25,14 @@ GLOBAL_LIST_EMPTY(objectives) /datum/objective/proc/considered_escaped(datum/mind/M) if(!considered_alive(M)) return FALSE + if(M.force_escaped) + return TRUE if(SSticker.force_ending || SSticker.mode.station_was_nuked) // Just let them win. return TRUE if(SSshuttle.emergency.mode != SHUTTLE_ENDGAME) return FALSE var/turf/location = get_turf(M.current) - if(!location || istype(location, /turf/open/floor/plasteel/shuttle/red) || istype(location, /turf/open/floor/mineral/plastitanium/brig)) // Fails if they are in the shuttle brig + if(!location || istype(location, /turf/open/floor/plasteel/shuttle/red) || istype(location, /turf/open/floor/mineral/plastitanium/red/brig)) // Fails if they are in the shuttle brig return FALSE return location.onCentCom() || location.onSyndieBase() @@ -161,7 +163,7 @@ GLOBAL_LIST_EMPTY(objectives) if(!target || !considered_alive(target) || considered_afk(target)) return TRUE var/turf/T = get_turf(target.current) - return T && !is_station_level(T.z) + return !T || !is_station_level(T.z) /datum/objective/mutiny/update_explanation_text() ..() @@ -546,7 +548,7 @@ GLOBAL_LIST_EMPTY(possible_items_special) /datum/objective/capture/check_completion()//Basically runs through all the mobs in the area to determine how much they are worth. var/captured_amount = 0 - var/area/centcom/holding/A = locate() in GLOB.sortedAreas + var/area/centcom/holding/A = GLOB.areas_by_type[/area/centcom/holding] for(var/mob/living/carbon/human/M in A)//Humans. if(M.stat == DEAD)//Dead folks are worth less. captured_amount+=0.5 diff --git a/code/game/gamemodes/overthrow/objective.dm b/code/game/gamemodes/overthrow/objective.dm new file mode 100644 index 0000000000..75b7f9f3b8 --- /dev/null +++ b/code/game/gamemodes/overthrow/objective.dm @@ -0,0 +1,152 @@ +// This is a point based objective. You can only lose if you fail to even handle one single command personnel, else you win. But, if you win, you're given a certain number of points, +// based on the role of the head (Captain, HoP/HoS, other heads, warden, security officers) and whether you converted them, exiled or just killed (applying a modifier of 1.5, 1 and 0.5 respectively) +// because this is meant for the overthrow gamemode, which is a bloodless coup, unlike revs. + +// Point system: +// Base points for each role: +// AI, Captain = 5; +// Head of Personnel, Head of Security, target = 4; +// Chief Engineer, Chief Medical Officer, Research Director = 3; + +// Modifiers: +// Converting: 1.5 for the converting team, 1 for all the other ones; +// Exiling: 1; +// Killing: 0.5 + +#define CAPPTS 5 +#define AIPTS 5 +#define HOPPTS 4 +#define HOSPTS 4 +#define TARGETPTS 4 +#define CEPTS 3 +#define CMOPTS 3 +#define RDPTS 3 + +#define CONVERTED_OURS 1.5 +#define CONVERTED 1 +#define EXILED 1 +#define KILLED 0.5 + +// Parent type holding the get_points proc used for round end log. +/datum/objective/overthrow + +/datum/objective/overthrow/check_completion() + return get_points() ? TRUE : FALSE + +/datum/objective/overthrow/proc/get_points() + return 0 // int, not bool + +/datum/objective/overthrow/proc/result_points(datum/mind/the_dude, base_points) // App + var/initial_points = base_points + if(the_dude) + var/datum/antagonist/overthrow/O = the_dude.has_antag_datum(/datum/antagonist/overthrow) + if(!the_dude.current || the_dude.current.stat == DEAD) + initial_points *= KILLED + else if(!is_station_level(the_dude.current.z) && !is_centcom_level(the_dude.current.z)) // exiled. + initial_points *= EXILED + else if(O) + initial_points *= CONVERTED + if(team == O.team) + initial_points *= CONVERTED_OURS + else + initial_points = 0 + else + initial_points = 0 + return initial_points + +// Heads overthrow objective. This targets the heads only, assigning points based on the rank of the head, captain being the highest target. +/datum/objective/overthrow/heads + var/list/targets = list() // We want one objective for all the heads, instead of 1 objective per head like how it's done for revs, because you don't lose if you get atleast one head. + // Also, this is an associative list, target = role. Modifiers (defines) are applied on points calculation at round end. + +/datum/objective/overthrow/heads/proc/find_targets() + var/list/datum/mind/owners = get_owners() + for(var/datum/mind/possible_target in get_crewmember_minds()) // i would use SSjob.get_all_heads() but jesus christ that proc's shit, i ain't using it + if(!(possible_target in owners) && ishuman(possible_target.current)) + if(possible_target.assigned_role in GLOB.command_positions) + targets[possible_target] = possible_target.assigned_role + update_explanation_text() + +/datum/objective/overthrow/heads/update_explanation_text() + if(targets.len) + explanation_text = "Work with your team to convert, exile or kill " + explanation_text += english_list(targets) + explanation_text += ". Converting to your team will give you more points, whereas killing will give you the least. Syndicates don't want to stir up too many troubles." + else + explanation_text = "Wait until any heads arrive. Once that happens, check your objectives again to see the updated objective. It may require around [OBJECTIVE_UPDATING_TIME] seconds to update." + +/datum/objective/overthrow/heads/check_completion() + if(!targets.len) + return TRUE + . = ..() + +// Amount of points = foreach head, result += head basepoints * modifier. +/datum/objective/overthrow/heads/get_points() + var/base_points = 0 + for(var/i in targets) + var/datum/mind/M = i + if(M) + var/target_points + var/role = targets[M] + switch(role) + if("Captain") + target_points = CAPPTS + if("Head of Personnel") + target_points = HOPPTS + if("Head of Security") + target_points = HOSPTS + if("Chief Engineer") + target_points = CEPTS + if("Research Director") + target_points = RDPTS + if("Chief Medical Officer") + target_points = CMOPTS + base_points += result_points(M, target_points) + return base_points + +// AI converting objective. The team who managed to convert the AI with the overthrow module gets the normal 1.5x boost. +/datum/objective/overthrow/AI + explanation_text = "Enslave the AIs to your team using the special AI module board in your storage implant. It is required you use said module." + +/datum/objective/overthrow/AI/get_points() // If you simply kill the Ai you get nothing, you need it to overthrow the heads. + . = 0 // Support for multiple AIs. More AIs means more control over the station. + for(var/i in GLOB.ai_list) + var/mob/living/silicon/ai/AI = i + if(AI.mind) + var/datum/mind/M = AI.mind + var/datum/antagonist/overthrow/O = M.has_antag_datum(/datum/antagonist/overthrow) + if(M) + . += (O.team == team) ? AIPTS*CONVERTED_OURS : AIPTS + +/datum/objective/overthrow/AI/update_explanation_text() + if(!GLOB.ai_list.len) + explanation_text = "Nothing." + else + explanation_text = "Enslave the AIs to your team using the special AI module board in your storage implant. It is required you use said module." + +/datum/objective/overthrow/AI/check_completion() + if(!GLOB.ai_list.len) + return TRUE + . = ..() + +// Overthrow target objective. A crewmember in particular has a certain bond with some centcom officials, and the Syndicate want you to target him in particular, even though he's not a head. +/datum/objective/overthrow/target + +/datum/objective/overthrow/target/update_explanation_text() + if(target) + explanation_text = "Work with your team to convert, exile or kill [target.name], the [target.assigned_role]. Converting to your team will give you more points, whereas killing will give you the least. Syndicates don't want to stir up too many troubles." + else + explanation_text = "Nothing." + +/datum/objective/overthrow/target/is_unique_objective(datum/mind/possible_target) + if(possible_target.assigned_role in GLOB.command_positions) + return FALSE + return TRUE + +/datum/objective/overthrow/target/check_completion() + if(!target) + return TRUE + . = ..() + +/datum/objective/overthrow/target/get_points() + return result_points(target, TARGETPTS) diff --git a/code/game/gamemodes/overthrow/overthrow.dm b/code/game/gamemodes/overthrow/overthrow.dm new file mode 100644 index 0000000000..1548556515 --- /dev/null +++ b/code/game/gamemodes/overthrow/overthrow.dm @@ -0,0 +1,76 @@ +// Overthrow gamemode, based on the sleeping agent antagonist. +/datum/game_mode/overthrow + name = "overthrow" + config_tag = "overthrow" + antag_flag = ROLE_OVERTHROW + restricted_jobs = list("Security Officer", "Warden", "Detective", "AI", "Cyborg","Captain", "Head of Personnel", "Head of Security", "Chief Engineer", "Research Director", "Chief Medical Officer") + required_players = 20 // the core idea is of a swift, bloodless coup, so it shouldn't be as chaotic as revs. + required_enemies = 2 // minimum two teams, otherwise it's just nerfed revs. + recommended_enemies = 4 + + announce_span = "danger" + announce_text = "There are sleeping Syndicate agents on the station who are trying to stage a coup!\n\ + Agents: Accomplish your objectives, convert heads and targets, take control of the AI.\n\ + Crew: Do not let the agents succeed!" + var/list/initial_agents = list() // Why doesn't this exist at /game_mode level? Literally every gamemode has some sort of version for this, what the fuck + +/datum/game_mode/overthrow/pre_setup() + + if(CONFIG_GET(flag/protect_roles_from_antagonist)) + restricted_jobs += protected_jobs + + if(CONFIG_GET(flag/protect_assistant_from_antagonist)) + restricted_jobs += "Assistant" + + var/sleeping_agents = required_enemies + round(num_players()*0.05) // At 100 players, it'd be 2 + 5 = 7 teams existing. + + for (var/i in 1 to sleeping_agents) + if (!antag_candidates.len) + break + var/datum/mind/sleeping_agent = antag_pick(antag_candidates) + antag_candidates -= sleeping_agent + initial_agents += sleeping_agent + sleeping_agent.restricted_roles = restricted_jobs + sleeping_agent.special_role = ROLE_OVERTHROW + + if(initial_agents.len < required_enemies) + setup_error = "Not enough initial sleeping agents candidates" + return FALSE + return TRUE + +/datum/game_mode/overthrow/post_setup() + for(var/i in initial_agents) // each agent will have its own team. + var/datum/mind/agent = i + var/datum/antagonist/overthrow/O = agent.add_antag_datum(/datum/antagonist/overthrow) // create_team called on_gain will create the team + O.equip_initial_overthrow_agent() + return ..() + +/datum/game_mode/overthrow/generate_report() + return "Some sleeping agents have managed to get aboard. Their objective is to stage a coup and take over the station stealthly." + +// Calculates points for each team and displays the winners. +/datum/game_mode/overthrow/special_report() // so many for loops, I am deeply sorry + var/list/teams = list() + for(var/datum/antagonist/overthrow/I in GLOB.antagonists) + var/datum/team/overthrow/Oteam = I.team + if(istype(Oteam)) // same + teams |= Oteam + var/max_points = 0 // the maximum amount of points reached + for(var/j in teams) + var/datum/team/T = j + var/points = 0 // Sum of points of all the objectives done + for(var/k in T.objectives) + var/datum/objective/overthrow/obj = k + if(istype(obj)) + points += obj.get_points() + if(max_points < points) + max_points = points + teams[T] = points + // Now we will have a list of team=points and a max_points var. Let's fetch all the teams with points=maxpoints and display them as winner. This code allows multiple teams to win if they both achieved + // the same amount of points and they got the most points out of all the teams. + var/list/winners = list() + for(var/l in teams) + var/datum/team/Tagain = l + if(teams[Tagain] == max_points) + winners += Tagain.name + return "The [english_list(winners)] team[winners.len > 1 ? "s tied" : " won"] with [max_points] points!" diff --git a/code/game/gamemodes/revolution/revolution.dm b/code/game/gamemodes/revolution/revolution.dm index bf8f5903b5..b0eee4e912 100644 --- a/code/game/gamemodes/revolution/revolution.dm +++ b/code/game/gamemodes/revolution/revolution.dm @@ -133,7 +133,7 @@ //Checks if the round is over// /////////////////////////////// /datum/game_mode/revolution/check_finished() - if(CONFIG_GET(keyed_flag_list/continuous)["revolution"]) + if(CONFIG_GET(keyed_list/continuous)["revolution"]) if(finished) SSshuttle.clearHostileEnvironment(src) return ..() diff --git a/code/game/gamemodes/traitor/double_agents.dm b/code/game/gamemodes/traitor/double_agents.dm index 4d8b57536e..3811fa9562 100644 --- a/code/game/gamemodes/traitor/double_agents.dm +++ b/code/game/gamemodes/traitor/double_agents.dm @@ -11,6 +11,7 @@ recommended_enemies = 8 reroll_friendly = 0 traitor_name = "Nanotrasen Internal Affairs Agent" + antag_flag = ROLE_INTERNAL_AFFAIRS traitors_possible = 10 //hard limit on traitors if scaling is turned off num_modifier = 4 // Four additional traitors @@ -28,7 +29,7 @@ i++ if(i + 1 > pre_traitors.len) i = 0 - target_list[traitor] = pre_traitors[i+1] + target_list[traitor] = pre_traitors[i+1] ..() diff --git a/code/game/gamemodes/traitor/traitor.dm b/code/game/gamemodes/traitor/traitor.dm index b5b5e7a706..789737ec0f 100644 --- a/code/game/gamemodes/traitor/traitor.dm +++ b/code/game/gamemodes/traitor/traitor.dm @@ -84,7 +84,7 @@ if((SSticker.mode.traitors.len + pre_traitors.len) >= traitorcap) //Upper cap for number of latejoin antagonists return if((SSticker.mode.traitors.len + pre_traitors.len) <= (traitorcap - 2) || prob(100 / (tsc * 2))) - if(ROLE_TRAITOR in character.client.prefs.be_special) + if(antag_flag in character.client.prefs.be_special) if(!jobban_isbanned(character, ROLE_TRAITOR) && !QDELETED(character) && !jobban_isbanned(character, ROLE_SYNDICATE) && !QDELETED(character)) if(age_check(character.client)) if(!(character.job in restricted_jobs)) diff --git a/code/game/machinery/PDApainter.dm b/code/game/machinery/PDApainter.dm index d5cf016816..53aebc53dc 100644 --- a/code/game/machinery/PDApainter.dm +++ b/code/game/machinery/PDApainter.dm @@ -130,7 +130,7 @@ set category = "Object" set src in oview(1) - if(usr.stat || usr.restrained() || !usr.canmove) + if(usr.stat || usr.restrained()) return if(storedpda) diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm index f167fa0b38..4d3fd006d8 100644 --- a/code/game/machinery/Sleeper.dm +++ b/code/game/machinery/Sleeper.dm @@ -28,6 +28,7 @@ /obj/machinery/sleeper/Initialize() . = ..() + occupant_typecache = GLOB.typecache_living update_icon() reset_chem_buttons() @@ -147,7 +148,7 @@ data["occupant"]["cloneLoss"] = mob_occupant.getCloneLoss() data["occupant"]["brainLoss"] = mob_occupant.getBrainLoss() data["occupant"]["reagents"] = list() - if(occupant.reagents.reagent_list.len) + if(mob_occupant.reagents && mob_occupant.reagents.reagent_list.len) for(var/datum/reagent/R in mob_occupant.reagents.reagent_list) data["occupant"]["reagents"] += list(list("name" = R.name, "volume" = R.volume)) return data @@ -183,12 +184,12 @@ if((chem in available_chems) && chem_allowed(chem)) occupant.reagents.add_reagent(chem_buttons[chem], 10) //emag effect kicks in here so that the "intended" chem is used for all checks, for extra FUUU if(user) - add_logs(user, occupant, "injected [chem] into", addition = "via [src]") + log_combat(user, occupant, "injected [chem] into", addition = "via [src]") return TRUE /obj/machinery/sleeper/proc/chem_allowed(chem) var/mob/living/mob_occupant = occupant - if(!mob_occupant) + if(!mob_occupant || !mob_occupant.reagents) return var/amount = mob_occupant.reagents.get_reagent_amount(chem) + 10 <= 20 * efficiency var/occ_health = mob_occupant.health > min_health || chem == "epinephrine" @@ -211,6 +212,17 @@ icon_state = "sleeper_s" controls_inside = TRUE +/obj/machinery/sleeper/syndie/fullupgrade/Initialize() + . = ..() + component_parts = list() + component_parts += new /obj/item/circuitboard/machine/sleeper(null) + component_parts += new /obj/item/stock_parts/matter_bin/bluespace(null) + component_parts += new /obj/item/stock_parts/manipulator/femto(null) + component_parts += new /obj/item/stack/sheet/glass(null) + component_parts += new /obj/item/stack/sheet/glass(null) + component_parts += new /obj/item/stack/cable_coil(null) + RefreshParts() + /obj/machinery/sleeper/clockwork name = "soothing sleeper" desc = "A large cryogenics unit built from brass. Its surface is pleasantly cool the touch." diff --git a/code/game/machinery/_machinery.dm b/code/game/machinery/_machinery.dm index b7de63a2d0..69edfcd5ec 100644 --- a/code/game/machinery/_machinery.dm +++ b/code/game/machinery/_machinery.dm @@ -120,7 +120,7 @@ Class Procs: armor = list("melee" = 25, "bullet" = 10, "laser" = 10, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 70) . = ..() GLOB.machines += src - + if(ispath(circuit, /obj/item/circuitboard)) circuit = new circuit circuit.apply_default_parts(src) @@ -130,7 +130,7 @@ Class Procs: else START_PROCESSING(SSfastprocess, src) power_change() - AddComponent(/datum/component/redirect, list(COMSIG_ENTER_AREA), CALLBACK(src, .proc/power_change)) + AddComponent(/datum/component/redirect, list(COMSIG_ENTER_AREA = CALLBACK(src, .proc/power_change))) if (occupant_typecache) occupant_typecache = typecacheof(occupant_typecache) @@ -218,10 +218,17 @@ Class Procs: if(panel_open && !(interaction_flags_machine & INTERACT_MACHINE_OPEN)) if(!silicon || !(interaction_flags_machine & INTERACT_MACHINE_OPEN_SILICON)) return FALSE - if(!silicon && (interaction_flags_machine & INTERACT_MACHINE_REQUIRES_SILICON)) - return FALSE - else if(silicon && !(interaction_flags_machine & INTERACT_MACHINE_ALLOW_SILICON)) - return FALSE + + if(silicon) + if(!(interaction_flags_machine & INTERACT_MACHINE_ALLOW_SILICON)) + return FALSE + else + if(interaction_flags_machine & INTERACT_MACHINE_REQUIRES_SILICON) + return FALSE + if(!Adjacent(user)) + var/mob/living/carbon/H = user + if(!(istype(H) && H.has_dna() && H.dna.check_mutation(TK))) + return FALSE return TRUE //////////////////////////////////////////////////////////////////////////////////////////// @@ -232,11 +239,6 @@ Class Procs: user.set_machine(src) . = ..() -/obj/machinery/ui_status(mob/user) - if(can_interact(user)) - return ..() - return UI_CLOSE - /obj/machinery/ui_act(action, params) add_fingerprint(usr) return ..() diff --git a/code/game/machinery/aug_manipulator.dm b/code/game/machinery/aug_manipulator.dm index a168cdd4d5..99200e510e 100644 --- a/code/game/machinery/aug_manipulator.dm +++ b/code/game/machinery/aug_manipulator.dm @@ -12,7 +12,8 @@ /obj/machinery/aug_manipulator/examine(mob/user) ..() - to_chat(user, "Alt-click to eject the limb.") + if(storedpart) + to_chat(user, "Alt-click to eject the limb.") /obj/machinery/aug_manipulator/Initialize() initial_icon_state = initial(icon_state) diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index 3e8e3afc98..a3e766d404 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -83,6 +83,7 @@ if(bug.current == src) bug.current = null bug = null + cancelCameraAlarm() return ..() /obj/machinery/camera/emp_act(severity) @@ -139,6 +140,8 @@ // Construction/Deconstruction /obj/machinery/camera/screwdriver_act(mob/living/user, obj/item/I) + if(..()) + return TRUE panel_open = !panel_open to_chat(user, "You screw the camera's panel [panel_open ? "open" : "closed"].") I.play_tool_sound(src) diff --git a/code/game/machinery/camera/camera_assembly.dm b/code/game/machinery/camera/camera_assembly.dm index 47bd250091..b120720992 100644 --- a/code/game/machinery/camera/camera_assembly.dm +++ b/code/game/machinery/camera/camera_assembly.dm @@ -87,6 +87,9 @@ return TRUE /obj/structure/camera_assembly/screwdriver_act(mob/user, obj/item/tool) + . = ..() + if(.) + return TRUE if(state != 3) return FALSE diff --git a/code/game/machinery/camera/motion.dm b/code/game/machinery/camera/motion.dm index 45f0268a00..6c134417bb 100644 --- a/code/game/machinery/camera/motion.dm +++ b/code/game/machinery/camera/motion.dm @@ -42,6 +42,7 @@ localMotionTargets = null if(istype(A)) A.motioncameras -= src + cancelAlarm() return ..() /obj/machinery/camera/proc/lostTargetRef(datum/weakref/R) diff --git a/code/game/machinery/cell_charger.dm b/code/game/machinery/cell_charger.dm index 9a59d4aea5..fb384d55ae 100644 --- a/code/game/machinery/cell_charger.dm +++ b/code/game/machinery/cell_charger.dm @@ -8,6 +8,7 @@ active_power_usage = 60 power_channel = EQUIP circuit = /obj/item/circuitboard/machine/cell_charger + pass_flags = PASSTABLE var/obj/item/stock_parts/cell/charging = null var/chargelevel = -1 var/charge_rate = 500 diff --git a/code/game/machinery/computer/Operating.dm b/code/game/machinery/computer/Operating.dm index f5ad3843a5..73fdcd5e8b 100644 --- a/code/game/machinery/computer/Operating.dm +++ b/code/game/machinery/computer/Operating.dm @@ -1,3 +1,6 @@ +#define MENU_OPERATION 1 +#define MENU_SURGERIES 2 + /obj/machinery/computer/operating name = "operating computer" desc = "Monitors patient vitals and displays surgery steps. Can be loaded with surgery disks to perform experimental procedures." @@ -7,10 +10,13 @@ var/mob/living/carbon/human/patient var/obj/structure/table/optable/table var/list/advanced_surgeries = list() + var/datum/techweb/linked_techweb + var/menu = MENU_OPERATION light_color = LIGHT_COLOR_BLUE /obj/machinery/computer/operating/Initialize() . = ..() + linked_techweb = SSresearch.science_tech find_table() /obj/machinery/computer/operating/attackby(obj/item/O, mob/user, params) @@ -24,6 +30,13 @@ return TRUE return ..() +/obj/machinery/computer/operating/proc/sync_surgeries() + for(var/i in linked_techweb.researched_designs) + var/datum/design/surgery/D = linked_techweb.researched_designs[i] + if(!istype(D)) + continue + advanced_surgeries |= D.surgery + /obj/machinery/computer/operating/proc/find_table() for(var/direction in GLOB.cardinals) table = locate(/obj/structure/table/optable, get_step(src, direction)) @@ -41,6 +54,17 @@ var/list/data = list() data["table"] = table if(table) + data["menu"] = menu + + var/list/surgeries = list() + for(var/X in advanced_surgeries) + var/datum/surgery/S = X + var/list/surgery = list() + surgery["name"] = initial(S.name) + surgery["desc"] = initial(S.desc) + surgeries += list(surgery) + data["surgeries"] = surgeries + data["patient"] = list() if(table.check_patient()) patient = table.patient @@ -86,4 +110,19 @@ "alternative_step" = alternative_step, "alt_chems_needed" = alt_chems_needed )) - return data \ No newline at end of file + return data + +/obj/machinery/computer/operating/ui_act(action, params) + if(..()) + return + switch(action) + if("change_menu") + menu = text2num(params["menu"]) + . = TRUE + if("sync") + sync_surgeries() + . = TRUE + . = TRUE + +#undef MENU_OPERATION +#undef MENU_SURGERIES \ No newline at end of file diff --git a/code/game/machinery/computer/_computer.dm b/code/game/machinery/computer/_computer.dm index 74e117356d..3c3f0e7f0f 100644 --- a/code/game/machinery/computer/_computer.dm +++ b/code/game/machinery/computer/_computer.dm @@ -9,7 +9,7 @@ max_integrity = 200 integrity_failure = 100 armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 40, "acid" = 20) - var/brightness_on = 2 + var/brightness_on = 1 var/icon_keyboard = "generic_key" var/icon_screen = "generic" var/clockwork = FALSE @@ -49,14 +49,19 @@ /obj/machinery/computer/update_icon() cut_overlays() + SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays) if(stat & NOPOWER) add_overlay("[icon_keyboard]_off") return add_overlay(icon_keyboard) + + // This whole block lets screens ignore lighting and be visible even in the darkest room + // We can't do this for many things that emit light unfortunately because it layers over things that would be on top of it + var/overlay_state = icon_screen if(stat & BROKEN) - add_overlay("[icon_state]_broken") - else - add_overlay(icon_screen) + overlay_state = "[icon_state]_broken" + SSvis_overlays.add_vis_overlay(src, icon, overlay_state, layer, plane, dir) + SSvis_overlays.add_vis_overlay(src, icon, overlay_state, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir, alpha=128) /obj/machinery/computer/power_change() ..() @@ -68,6 +73,8 @@ return /obj/machinery/computer/screwdriver_act(mob/living/user, obj/item/I) + if(..()) + return TRUE if(circuit && !(flags_1&NODECONSTRUCT_1)) to_chat(user, "You start to disconnect the monitor...") if(I.use_tool(src, user, 20, volume=50)) @@ -109,7 +116,7 @@ if(!(flags_1 & NODECONSTRUCT_1)) if(circuit) //no circuit, no computer frame var/obj/structure/frame/computer/A = new /obj/structure/frame/computer(src.loc) - A.dir = dir + A.setDir(dir) A.circuit = circuit A.setAnchored(TRUE) if(stat & BROKEN) diff --git a/code/game/machinery/computer/apc_control.dm b/code/game/machinery/computer/apc_control.dm index 30574fdae4..8615af205b 100644 --- a/code/game/machinery/computer/apc_control.dm +++ b/code/game/machinery/computer/apc_control.dm @@ -28,6 +28,7 @@ playsound(active_apc, 'sound/machines/terminal_alert.ogg', 50, 0) active_apc.locked = TRUE active_apc.update_icon() + active_apc.remote_control = null active_apc = null /obj/machinery/computer/apc_control/attack_ai(mob/user) @@ -121,10 +122,12 @@ playsound(active_apc, 'sound/machines/terminal_alert.ogg', 50, 0) active_apc.locked = TRUE active_apc.update_icon() + active_apc.remote_control = null active_apc = null to_chat(usr, "[icon2html(src, usr)] Connected to APC in [get_area_name(APC.area, TRUE)]. Interface request sent.") log_activity("remotely accessed APC in [get_area_name(APC.area, TRUE)]") - APC.ui_interact(usr, state = GLOB.not_incapacitated_state) + APC.remote_control = src + APC.ui_interact(usr) playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) message_admins("[ADMIN_LOOKUPFLW(usr)] remotely accessed [APC] from [src] at [AREACOORD(src)].") log_game("[key_name(usr)] remotely accessed [APC] from [src] at [AREACOORD(src)].") diff --git a/code/game/machinery/computer/arcade.dm b/code/game/machinery/computer/arcade.dm index 13da773868..88f609c7f5 100644 --- a/code/game/machinery/computer/arcade.dm +++ b/code/game/machinery/computer/arcade.dm @@ -367,6 +367,15 @@ var/gameStatus = ORION_STATUS_START var/canContinueEvent = 0 +/obj/machinery/computer/arcade/orion_trail/kobayashi + name = "Kobayashi Maru control computer" + desc = "A test for cadets" + icon = 'icons/obj/machines/particle_accelerator.dmi' + icon_state = "control_boxp" + events = list("Raiders" = 3, "Interstellar Flux" = 1, "Illness" = 3, "Breakdown" = 2, "Malfunction" = 2, "Collision" = 1, "Spaceport" = 2) + prizes = list(/obj/item/paper/fluff/holodeck/trek_diploma = 1) + settlers = list("Kirk","Worf","Gene") + /obj/machinery/computer/arcade/orion_trail/Reset() // Sets up the main trail stops = list("Pluto","Asteroid Belt","Proxima Centauri","Dead Space","Rigel Prime","Tau Ceti Beta","Black Hole","Space Outpost Beta-9","Orion Prime") @@ -704,7 +713,7 @@ say("WEEWOO! WEEWOO! Spaceport security en route!") playsound(src, 'sound/items/weeoo1.ogg', 100, FALSE) for(var/i, i<=3, i++) - var/mob/living/simple_animal/hostile/syndicate/ranged/orion/O = new/mob/living/simple_animal/hostile/syndicate/ranged/orion(get_turf(src)) + var/mob/living/simple_animal/hostile/syndicate/ranged/smg/orion/O = new/mob/living/simple_animal/hostile/syndicate/ranged/smg/orion(get_turf(src)) O.target = usr @@ -1047,7 +1056,7 @@ newgame() obj_flags |= EMAGGED -/mob/living/simple_animal/hostile/syndicate/ranged/orion +/mob/living/simple_animal/hostile/syndicate/ranged/smg/orion name = "spaceport security" desc = "Premier corporate security forces for all spaceports found along the Orion Trail." faction = list("orion") diff --git a/code/game/machinery/computer/atmos_control.dm b/code/game/machinery/computer/atmos_control.dm index 7eb8e206b5..baa6fa577e 100644 --- a/code/game/machinery/computer/atmos_control.dm +++ b/code/game/machinery/computer/atmos_control.dm @@ -272,7 +272,7 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers) /obj/machinery/computer/atmos_control/tank/ui_act(action, params) if(..() || !radio_connection) return - var/datum/signal/signal = new(list("sigtype" = "command")) + var/datum/signal/signal = new(list("sigtype" = "command", "user" = usr)) switch(action) if("reconnect") reconnect(usr) diff --git a/code/game/machinery/computer/buildandrepair.dm b/code/game/machinery/computer/buildandrepair.dm index a151b0e0c0..c8a4d68575 100644 --- a/code/game/machinery/computer/buildandrepair.dm +++ b/code/game/machinery/computer/buildandrepair.dm @@ -114,7 +114,7 @@ P.play_tool_sound(src) to_chat(user, "You connect the monitor.") var/obj/B = new circuit.build_path (loc, circuit) - B.dir = dir + B.setDir(dir) transfer_fingerprints_to(B) qdel(src) return diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm index 696c9442b9..7dcd85d310 100644 --- a/code/game/machinery/computer/camera.dm +++ b/code/game/machinery/computer/camera.dm @@ -161,6 +161,7 @@ icon_keyboard = null icon_screen = "detective_tv" clockwork = TRUE //it'd look weird + pass_flags = PASSTABLE /obj/machinery/computer/security/mining name = "outpost camera console" diff --git a/code/game/machinery/computer/camera_advanced.dm b/code/game/machinery/computer/camera_advanced.dm index e561c6466f..86fcefb340 100644 --- a/code/game/machinery/computer/camera_advanced.dm +++ b/code/game/machinery/computer/camera_advanced.dm @@ -54,9 +54,13 @@ var/datum/action/A = V A.Remove(user) actions.Cut() + for(var/V in eyeobj.visibleCameraChunks) + var/datum/camerachunk/C = V + C.remove(eyeobj) if(user.client) user.reset_perspective(null) - eyeobj.RemoveImages() + if(eyeobj.visible_icon && user.client) + user.client.images -= eyeobj.user_image eyeobj.eye_user = null user.remote_control = null @@ -105,7 +109,7 @@ if(!eyeobj.eye_initialized) var/camera_location var/turf/myturf = get_turf(src) - if(eyeobj.use_static) + if(eyeobj.use_static != USE_STATIC_NONE) if((!z_lock.len || (myturf.z in z_lock)) && GLOB.cameranet.checkTurfVis(myturf)) camera_location = myturf else @@ -148,6 +152,7 @@ /mob/camera/aiEye/remote name = "Inactive Camera Eye" + ai_detector_visible = FALSE var/sprint = 10 var/cooldown = 0 var/acceleration = 1 @@ -163,17 +168,12 @@ user.see_in_dark = 2 return 1 -/mob/camera/aiEye/remote/RemoveImages() - ..() - if(visible_icon) - var/client/C = GetViewerClient() - if(C) - C.images -= user_image - /mob/camera/aiEye/remote/Destroy() - eye_user = null + if(origin && eye_user) + origin.remove_eye_control(eye_user) origin = null - return ..() + . = ..() + eye_user = null /mob/camera/aiEye/remote/GetViewerClient() if(eye_user) @@ -182,15 +182,14 @@ /mob/camera/aiEye/remote/setLoc(T) if(eye_user) - if(!isturf(eye_user.loc)) - return T = get_turf(T) if (T) forceMove(T) else moveToNullspace() - if(use_static) - GLOB.cameranet.visibility(src, GetViewerClient()) + update_ai_detect_hud() + if(use_static != USE_STATIC_NONE) + GLOB.cameranet.visibility(src, GetViewerClient(), null, use_static) if(visible_icon) if(eye_user.client) eye_user.client.images -= user_image diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm index 4846610671..00a5c8941d 100644 --- a/code/game/machinery/computer/cloning.dm +++ b/code/game/machinery/computer/cloning.dm @@ -468,6 +468,7 @@ // We store the instance rather than the path, because some // species (abductors, slimepeople) store state in their // species datums + dna.delete_species = FALSE R.fields["mrace"] = dna.species else var/datum/species/rando_race = pick(GLOB.roundstart_races) diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm index 24b392ec8f..596300097b 100755 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -52,6 +52,8 @@ /obj/machinery/computer/communications/Topic(href, href_list) if(..()) return + if(!usr.canUseTopic(src)) + return if(!is_station_level(z) && !is_reserved_level(z)) //Can only use in transit and on SS13 to_chat(usr, "Unable to establish a connection: \black You're too far away from the station!") return @@ -144,7 +146,7 @@ playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) send2otherserver("[station_name()]", input,"Comms_Console") minor_announce(input, title = "Outgoing message to allied station") - log_talk(usr,"[key_name(usr)] has sent a message to the other server: [input]",LOGSAY) + usr.log_talk(input, LOG_SAY, tag="message to the other server") message_admins("[ADMIN_LOOKUPFLW(usr)] has sent a message to the other server.") deadchat_broadcast("[usr.real_name] has sent an outgoing message to the other station(s).", usr) CM.lastTimeUsed = world.time @@ -198,10 +200,7 @@ state = STATE_CANCELSHUTTLE if("cancelshuttle2") if(authenticated) - if(world.time > SSshuttle.auto_call) - say("Warning: Emergency shuttle recalls have been blocked by Central Command due to ongoing crew transfer procedures.") - else - SSshuttle.cancelEvac(usr) + SSshuttle.cancelEvac(usr) state = STATE_DEFAULT if("messagelist") currmsg = 0 @@ -230,12 +229,14 @@ var/answer = text2num(href_list["answer"]) if(!currmsg || !answer || currmsg.possible_answers.len < answer) state = STATE_MESSAGELIST - currmsg.answered = answer - log_game("[key_name(usr)] answered [currmsg.title] comm message. Answer : [currmsg.answered]") - if(currmsg) - currmsg.answer_callback.Invoke() - - state = STATE_VIEWMESSAGE + else + if(!currmsg.answered) + currmsg.answered = answer + log_game("[key_name(usr)] answered [currmsg.title] comm message. Answer : [currmsg.answered]") + if(currmsg) + currmsg.answer_callback.InvokeAsync() + state = STATE_VIEWMESSAGE + updateDialog() if("status") state = STATE_STATUSDISPLAY if("securitylevel") @@ -291,7 +292,7 @@ playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) CentCom_announce(input, usr) to_chat(usr, "Message transmitted to Central Command.") - log_talk(usr,"[key_name(usr)] has made a CentCom announcement: [input]",LOGSAY) + usr.log_talk(input, LOG_SAY, tag="CentCom announcement") deadchat_broadcast("[usr.real_name] has messaged CentCom, \"[input]\" at [get_area_name(usr, TRUE)].", usr) CM.lastTimeUsed = world.time @@ -308,7 +309,7 @@ playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) Syndicate_announce(input, usr) to_chat(usr, "SYSERR @l(19833)of(transmit.dm): !@$ MESSAGE TRANSMITTED TO SYNDICATE COMMAND.") - log_talk(usr,"[key_name(usr)] has made a Syndicate announcement: [input]",LOGSAY) + usr.log_talk(input, LOG_SAY, tag="Syndicate announcement") deadchat_broadcast("[usr.real_name] has messaged the Syndicate, \"[input]\" at [get_area_name(usr, TRUE)].", usr) CM.lastTimeUsed = world.time @@ -328,7 +329,7 @@ return Nuke_request(input, usr) to_chat(usr, "Request sent.") - log_talk(usr,"[key_name(usr)] has requested the nuclear codes from CentCom",LOGSAY) + usr.log_message("has requested the nuclear codes from CentCom", LOG_SAY) priority_announce("The codes for the on-station nuclear self-destruct have been requested by [usr]. Confirmation or denial of this request will be sent shortly.", "Nuclear Self Destruct Codes Requested",'sound/ai/commandreport.ogg') CM.lastTimeUsed = world.time @@ -366,11 +367,13 @@ var/answer = text2num(href_list["answer"]) if(!aicurrmsg || !answer || aicurrmsg.possible_answers.len < answer) aistate = STATE_MESSAGELIST - aicurrmsg.answered = answer - log_game("[key_name(usr)] answered [aicurrmsg.title] comm message. Answer : [aicurrmsg.answered]") - if(aicurrmsg.answer_callback) - aicurrmsg.answer_callback.Invoke() - aistate = STATE_VIEWMESSAGE + else + if(!aicurrmsg.answered) + aicurrmsg.answered = answer + log_game("[key_name(usr)] answered [aicurrmsg.title] comm message. Answer : [aicurrmsg.answered]") + if(aicurrmsg.answer_callback) + aicurrmsg.answer_callback.InvokeAsync() + aistate = STATE_VIEWMESSAGE if("ai-status") aistate = STATE_STATUSDISPLAY if("ai-announce") @@ -476,7 +479,7 @@ if (authenticated==2) dat += "

Captain Functions" dat += "
\[ Make a Captain's Announcement \]" - var/cross_servers_count = length(CONFIG_GET(keyed_string_list/cross_server)) + var/cross_servers_count = length(CONFIG_GET(keyed_list/cross_server)) if(cross_servers_count) dat += "
\[ Send a message to [cross_servers_count == 1 ? "an " : ""]allied station[cross_servers_count > 1 ? "s" : ""] \]" if(SSmapping.config.allow_custom_shuttles) diff --git a/code/game/machinery/computer/medical.dm b/code/game/machinery/computer/medical.dm index 2f1c0020b9..d65fb49161 100644 --- a/code/game/machinery/computer/medical.dm +++ b/code/game/machinery/computer/medical.dm @@ -596,3 +596,4 @@ icon_screen = "medlaptop" icon_keyboard = "laptop_key" clockwork = TRUE //it'd look weird + pass_flags = PASSTABLE diff --git a/code/game/machinery/computer/prisoner.dm b/code/game/machinery/computer/prisoner.dm index 1c1944e73e..798b0e4c65 100644 --- a/code/game/machinery/computer/prisoner.dm +++ b/code/game/machinery/computer/prisoner.dm @@ -136,7 +136,7 @@ if(I && istype(I) && I.imp_in) var/mob/living/R = I.imp_in to_chat(R, "You hear a voice in your head saying: '[warning]'") - log_talk(usr,"[key_name(usr)] sent an implant message to [key_name(R)]: '[warning]'",LOGSAY) + log_directed_talk(usr, R, warning, LOG_SAY, "implant message") src.add_fingerprint(usr) src.updateUsrDialog() diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm index 666966ee2e..bacedad6c0 100644 --- a/code/game/machinery/computer/security.dm +++ b/code/game/machinery/computer/security.dm @@ -38,6 +38,7 @@ icon_screen = "seclaptop" icon_keyboard = "laptop_key" clockwork = TRUE //it'd look weird + pass_flags = PASSTABLE /obj/machinery/computer/secure_data/attackby(obj/item/O, mob/user, params) if(istype(O, /obj/item/card/id)) diff --git a/code/game/machinery/defibrillator_mount.dm b/code/game/machinery/defibrillator_mount.dm index a95270f131..7b7c8a3411 100644 --- a/code/game/machinery/defibrillator_mount.dm +++ b/code/game/machinery/defibrillator_mount.dm @@ -141,4 +141,4 @@ materials = list(MAT_METAL = 300, MAT_GLASS = 100) w_class = WEIGHT_CLASS_BULKY result_path = /obj/machinery/defibrillator_mount - pixel_shift = -28 + pixel_shift = -28 \ No newline at end of file diff --git a/code/game/machinery/dish_drive.dm b/code/game/machinery/dish_drive.dm index 7e960d4ebc..66aa1347cb 100644 --- a/code/game/machinery/dish_drive.dm +++ b/code/game/machinery/dish_drive.dm @@ -9,6 +9,7 @@ active_power_usage = 13 //10 with default parts density = FALSE circuit = /obj/item/circuitboard/machine/dish_drive + pass_flags = PASSTABLE var/static/list/item_types = list(/obj/item/trash/waffles, /obj/item/trash/plate, /obj/item/trash/tray, diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 45355ffac7..7f45f88dcd 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -99,7 +99,7 @@ /obj/machinery/door/airlock/Initialize() . = ..() - wires = new wiretypepath(src) //CIT CHANGE - makes it possible for airlocks to have different wire datums + wires = new /datum/wires/airlock(src) if(frequency) set_frequency(frequency) @@ -147,7 +147,6 @@ welded = TRUE if(24 to 30) panel_open = TRUE - update_icon() /obj/machinery/door/airlock/ComponentInitialize() @@ -362,6 +361,7 @@ /obj/machinery/door/airlock/proc/regainMainPower() if(src.secondsMainPowerLost > 0) src.secondsMainPowerLost = 0 + update_icon() /obj/machinery/door/airlock/proc/handlePowerRestore() var/cont = TRUE @@ -382,6 +382,7 @@ cont = TRUE spawnPowerRestoreRunning = FALSE updateDialog() + update_icon() /obj/machinery/door/airlock/proc/loseMainPower() if(secondsMainPowerLost <= 0) @@ -391,6 +392,7 @@ if(!spawnPowerRestoreRunning) spawnPowerRestoreRunning = TRUE INVOKE_ASYNC(src, .proc/handlePowerRestore) + update_icon() /obj/machinery/door/airlock/proc/loseBackupPower() if(src.secondsBackupPowerLost < 60) @@ -398,10 +400,12 @@ if(!spawnPowerRestoreRunning) spawnPowerRestoreRunning = TRUE INVOKE_ASYNC(src, .proc/handlePowerRestore) + update_icon() /obj/machinery/door/airlock/proc/regainBackupPower() if(src.secondsBackupPowerLost > 0) src.secondsBackupPowerLost = 0 + update_icon() // shock user with probability prb (if all connections & power are working) // returns TRUE if shocked, FALSE otherwise @@ -575,6 +579,7 @@ add_overlay(sparks_overlay) add_overlay(damag_overlay) add_overlay(note_overlay) + check_unres() /proc/get_airlock_overlay(icon_state, icon_file) var/obj/machinery/door/airlock/A @@ -584,6 +589,31 @@ if((!(. = airlock_overlays[iconkey]))) . = airlock_overlays[iconkey] = mutable_appearance(icon_file, icon_state) +/obj/machinery/door/airlock/proc/check_unres() //unrestricted sides. This overlay indicates which directions the player can access even without an ID + if(hasPower() && unres_sides) + if(unres_sides & NORTH) + var/image/I = image(icon='icons/obj/doors/airlocks/station/overlays.dmi', icon_state="unres_n") //layer=src.layer+1 + I.pixel_y = 32 + set_light(l_range = 2, l_power = 1) + add_overlay(I) + if(unres_sides & SOUTH) + var/image/I = image(icon='icons/obj/doors/airlocks/station/overlays.dmi', icon_state="unres_s") //layer=src.layer+1 + I.pixel_y = -32 + set_light(l_range = 2, l_power = 1) + add_overlay(I) + if(unres_sides & EAST) + var/image/I = image(icon='icons/obj/doors/airlocks/station/overlays.dmi', icon_state="unres_e") //layer=src.layer+1 + I.pixel_x = 32 + set_light(l_range = 2, l_power = 1) + add_overlay(I) + if(unres_sides & WEST) + var/image/I = image(icon='icons/obj/doors/airlocks/station/overlays.dmi', icon_state="unres_w") //layer=src.layer+1 + I.pixel_x = -32 + set_light(l_range = 2, l_power = 1) + add_overlay(I) + else + set_light(0) + /obj/machinery/door/airlock/do_animate(animation) switch(animation) if("opening") @@ -634,6 +664,12 @@ else to_chat(user, "It looks very robust.") + if(issilicon(user) && (!stat & BROKEN)) + to_chat(user, "Shift-click [src] to [ density ? "open" : "close"] it.") + to_chat(user, "Ctrl-click [src] to [ locked ? "raise" : "drop"] its bolts.") + to_chat(user, "Alt-click [src] to [ secondsElectrified ? "un-electrify" : "permanently electrify"] it.") + to_chat(user, "Ctrl-Shift-click [src] to [ emergency ? "disable" : "enable"] emergency access.") + /obj/machinery/door/airlock/attack_ai(mob/user) if(!src.canAIControl(user)) if(src.canAIHack()) @@ -785,7 +821,7 @@ if(do_after(user, 20, 1, target = src)) if(!panel_open || !S.use(2)) return - user.visible_message("[user] reinforce \the [src] with metal.", + user.visible_message("[user] reinforces \the [src] with metal.", "You reinforce \the [src] with metal.") security_level = AIRLOCK_SECURITY_METAL update_icon() @@ -799,7 +835,7 @@ if(do_after(user, 20, 1, target = src)) if(!panel_open || !S.use(2)) return - user.visible_message("[user] reinforce \the [src] with plasteel.", + user.visible_message("[user] reinforces \the [src] with plasteel.", "You reinforce \the [src] with plasteel.") security_level = AIRLOCK_SECURITY_PLASTEEL modify_max_integrity(normal_integrity * AIRLOCK_INTEGRITY_MULTIPLIER) @@ -1550,7 +1586,7 @@ to_chat(user, "The electrification wire has been cut") else LAZYADD(shockedby, "\[[time_stamp()]\] [key_name(user)]") - add_logs(user, src, "electrified") + log_combat(user, src, "electrified") set_electrified(AI_ELECTRIFY_DOOR_TIME) /obj/machinery/door/airlock/proc/shock_perm(mob/user) @@ -1560,7 +1596,7 @@ to_chat(user, "The electrification wire has been cut") else LAZYADD(shockedby, text("\[[time_stamp()]\] [key_name(user)]")) - add_logs(user, src, "electrified") + log_combat(user, src, "electrified") set_electrified(ELECTRIFIED_PERMANENT) /obj/machinery/door/airlock/proc/emergency_on(mob/user) diff --git a/code/game/machinery/doors/airlock_electronics.dm b/code/game/machinery/doors/airlock_electronics.dm index f52ffd42fe..cfaa94b842 100644 --- a/code/game/machinery/doors/airlock_electronics.dm +++ b/code/game/machinery/doors/airlock_electronics.dm @@ -4,6 +4,7 @@ var/list/accesses = list() var/one_access = 0 + var/unres_sides = 0 //unrestricted sides, or sides of the airlock that will open regardless of access /obj/item/electronics/airlock/examine(mob/user) ..() @@ -34,6 +35,7 @@ regions[++regions.len] = region data["regions"] = regions data["oneAccess"] = one_access + data["unres_direction"] = unres_sides return data @@ -55,3 +57,7 @@ else accesses -= access . = TRUE + if("direc_set") + var/unres_direction = text2num(params["unres_direction"]) + unres_sides ^= unres_direction //XOR, toggles only the bit that was clicked + . = TRUE diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index e169c66c24..222caeb595 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -34,6 +34,7 @@ var/real_explosion_block //ignore this, just use explosion_block var/red_alert_access = FALSE //if TRUE, this door will always open on red alert var/poddoor = FALSE + var/unres_sides = 0 //Unrestricted sides. A bitflag for which direction (if any) can open the door with no access /obj/machinery/door/examine(mob/user) ..() @@ -69,9 +70,11 @@ else layer = initial(layer) +/obj/machinery/door/power_change() + ..() + update_icon() + /obj/machinery/door/Destroy() - density = FALSE - air_update_turf(1) update_freelook_sight() GLOB.airlocks -= src if(spark_system) @@ -79,7 +82,7 @@ spark_system = null return ..() -/obj/machinery/door/CollidedWith(atom/movable/AM) +/obj/machinery/door/Bumped(atom/movable/AM) if(operating || (obj_flags & EMAGGED)) return if(ismob(AM)) @@ -163,8 +166,13 @@ /obj/machinery/door/allowed(mob/M) if(emergency) return TRUE + if(unrestricted_side(M)) + return TRUE return ..() +/obj/machinery/door/proc/unrestricted_side(mob/M) //Allows for specific side of airlocks to be unrestrected (IE, can exit maint freely, but need access to enter) + return get_dir(src, M) & unres_sides + /obj/machinery/door/proc/try_to_weld(obj/item/weldingtool/W, mob/user) return diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm index dc7056784a..507769f9a3 100644 --- a/code/game/machinery/doors/firedoor.dm +++ b/code/game/machinery/doors/firedoor.dm @@ -67,7 +67,7 @@ affecting_areas.Cut() return ..() -/obj/machinery/door/firedoor/CollidedWith(atom/movable/AM) +/obj/machinery/door/firedoor/Bumped(atom/movable/AM) if(panel_open || operating) return if(!density) diff --git a/code/game/machinery/doors/passworddoor.dm b/code/game/machinery/doors/passworddoor.dm index 06c53c4e1f..fcbb214bb6 100644 --- a/code/game/machinery/doors/passworddoor.dm +++ b/code/game/machinery/doors/passworddoor.dm @@ -29,7 +29,7 @@ if(findtext(raw_message,password)) open() -/obj/machinery/door/password/CollidedWith(atom/movable/AM) +/obj/machinery/door/password/Bumped(atom/movable/AM) return !density && ..() /obj/machinery/door/password/try_to_activate_door(mob/user) diff --git a/code/game/machinery/doors/poddoor.dm b/code/game/machinery/doors/poddoor.dm index a581b20f52..ebc1e94e97 100644 --- a/code/game/machinery/doors/poddoor.dm +++ b/code/game/machinery/doors/poddoor.dm @@ -56,7 +56,7 @@ name = "combustion chamber vent" id = INCINERATOR_SYNDICATELAVA_AUXVENT -/obj/machinery/door/poddoor/CollidedWith(atom/movable/AM) +/obj/machinery/door/poddoor/Bumped(atom/movable/AM) if(density) return 0 else @@ -84,7 +84,7 @@ icon_state = "open" /obj/machinery/door/poddoor/try_to_activate_door(mob/user) - return + return /obj/machinery/door/poddoor/try_to_crowbar(obj/item/I, mob/user) if(stat & NOPOWER) diff --git a/code/game/machinery/doors/unpowered.dm b/code/game/machinery/doors/unpowered.dm index 2960335813..2e7e7d5cba 100644 --- a/code/game/machinery/doors/unpowered.dm +++ b/code/game/machinery/doors/unpowered.dm @@ -1,6 +1,6 @@ /obj/machinery/door/unpowered -/obj/machinery/door/unpowered/CollidedWith(atom/movable/AM) +/obj/machinery/door/unpowered/Bumped(atom/movable/AM) if(src.locked) return ..() diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm index 0f84817b5a..97ab664b85 100644 --- a/code/game/machinery/doors/windowdoor.dm +++ b/code/game/machinery/doors/windowdoor.dm @@ -36,6 +36,10 @@ if(cable) debris += new /obj/item/stack/cable_coil(src, cable) +/obj/machinery/door/window/ComponentInitialize() + . = ..() + AddComponent(/datum/component/ntnet_interface) + /obj/machinery/door/window/Destroy() density = FALSE QDEL_LIST(debris) @@ -58,7 +62,7 @@ sleep(20) close() -/obj/machinery/door/window/CollidedWith(atom/movable/AM) +/obj/machinery/door/window/Bumped(atom/movable/AM) if( operating || !src.density ) return if (!( ismob(AM) )) @@ -298,6 +302,35 @@ if("deny") flick("[src.base_state]deny", src) +/obj/machinery/door/window/check_access_ntnet(datum/netdata/data) + return !requiresID() || ..() + +/obj/machinery/door/window/ntnet_receive(datum/netdata/data) + // Check if the airlock is powered. + if(!hasPower()) + return + + // Check packet access level. + if(!check_access_ntnet(data)) + return + + // Handle received packet. + var/command = lowertext(data.data["data"]) + var/command_value = lowertext(data.data["data_secondary"]) + switch(command) + if("open") + if(command_value == "on" && !density) + return + + if(command_value == "off" && density) + return + + if(density) + INVOKE_ASYNC(src, .proc/open) + else + INVOKE_ASYNC(src, .proc/close) + if("touch") + INVOKE_ASYNC(src, .proc/open_and_close) /obj/machinery/door/window/brigdoor name = "secure door" diff --git a/code/game/machinery/doppler_array.dm b/code/game/machinery/doppler_array.dm index 940734c0c2..9d522f8f1c 100644 --- a/code/game/machinery/doppler_array.dm +++ b/code/game/machinery/doppler_array.dm @@ -129,4 +129,4 @@ GLOBAL_LIST_EMPTY(doppler_arrays) linked_techweb = SSresearch.science_tech /proc/techweb_scale_bomb(lightradius) - return lightradius ** 1.36 + return (lightradius ** 0.5) * 3000 diff --git a/code/game/machinery/droneDispenser.dm b/code/game/machinery/droneDispenser.dm index ffe7961534..7c92c158b3 100644 --- a/code/game/machinery/droneDispenser.dm +++ b/code/game/machinery/droneDispenser.dm @@ -50,7 +50,7 @@ /obj/machinery/droneDispenser/Initialize() . = ..() - var/datum/component/material_container/materials = AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS), MINERAL_MATERIAL_AMOUNT * MAX_STACK_SIZE * 2, TRUE, list(/obj/item/stack)) + var/datum/component/material_container/materials = AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS), MINERAL_MATERIAL_AMOUNT * MAX_STACK_SIZE * 2, TRUE, /obj/item/stack) materials.insert_amount(starting_amount) materials.precise_insertion = TRUE using_materials = list(MAT_METAL=metal_cost, MAT_GLASS=glass_cost) diff --git a/code/game/machinery/firealarm.dm b/code/game/machinery/firealarm.dm index 34a5659f3f..c3ce4c6a01 100644 --- a/code/game/machinery/firealarm.dm +++ b/code/game/machinery/firealarm.dm @@ -285,3 +285,40 @@ set_light(l_power = 0.8) else set_light(l_power = 0) + +/* + * Return of Party button + */ + +/area + var/party = FALSE + +/obj/machinery/firealarm/partyalarm + name = "\improper PARTY BUTTON" + desc = "Cuban Pete is in the house!" + var/static/party_overlay + +/obj/machinery/firealarm/partyalarm/reset() + if (stat & (NOPOWER|BROKEN)) + return + var/area/A = get_area(src) + if (!A || !A.party) + return + A.party = FALSE + A.cut_overlay(party_overlay) + +/obj/machinery/firealarm/partyalarm/alarm() + if (stat & (NOPOWER|BROKEN)) + return + var/area/A = get_area(src) + if (!A || A.party || A.name == "Space") + return + A.party = TRUE + if (!party_overlay) + party_overlay = iconstate2appearance('icons/turf/areas.dmi', "party") + A.add_overlay(party_overlay) + +/obj/machinery/firealarm/partyalarm/ui_data(mob/user) + . = ..() + var/area/A = get_area(src) + .["alarm"] = A && A.party diff --git a/code/game/machinery/flasher.dm b/code/game/machinery/flasher.dm index 089abdb26b..12516c603d 100644 --- a/code/game/machinery/flasher.dm +++ b/code/game/machinery/flasher.dm @@ -100,19 +100,23 @@ if(!bulb.flash_recharge(30)) //Bulb can burn out if it's used too often too fast power_change() return - bulb.times_used ++ playsound(src.loc, 'sound/weapons/flash.ogg', 100, 1) flick("[base_state]_flash", src) last_flash = world.time use_power(1000) + var/flashed = FALSE for (var/mob/living/L in viewers(src, null)) if (get_dist(src, L) > range) continue if(L.flash_act(affect_silicon = 1)) L.Knockdown(strength) + flashed = TRUE + + if(flashed) + bulb.times_used++ return 1 diff --git a/code/game/machinery/harvester.dm b/code/game/machinery/harvester.dm new file mode 100644 index 0000000000..17f355b5ad --- /dev/null +++ b/code/game/machinery/harvester.dm @@ -0,0 +1,184 @@ +/obj/machinery/harvester + name = "organ harvester" + desc = "An advanced machine used for harvesting organs and limbs from the deceased." + density = TRUE + icon = 'icons/obj/machines/harvester.dmi' + icon_state = "harvester" + verb_say = "states" + state_open = FALSE + idle_power_usage = 50 + circuit = /obj/item/circuitboard/machine/harvester + light_color = LIGHT_COLOR_BLUE + var/interval = 20 + var/harvesting = FALSE + var/list/operation_order = list() //Order of wich we harvest limbs. + var/allow_clothing = FALSE + var/allow_living = FALSE + +/obj/machinery/harvester/Initialize() + . = ..() + if(prob(1)) + name = "auto-autopsy" + +/obj/machinery/harvester/RefreshParts() + interval = 0 + var/max_time = 40 + for(var/obj/item/stock_parts/micro_laser/L in component_parts) + max_time -= L.rating + interval = max(max_time,1) + +/obj/machinery/harvester/update_icon(warming_up) + if(warming_up) + icon_state = initial(icon_state)+"-charging" + return + if(state_open) + icon_state = initial(icon_state)+"-open" + else if(harvesting) + icon_state = initial(icon_state)+"-active" + else + icon_state = initial(icon_state) + +/obj/machinery/harvester/open_machine(drop = TRUE) + if(panel_open) + return + . = ..() + harvesting = FALSE + +/obj/machinery/harvester/attack_hand(mob/user) + if(state_open) + close_machine() + else if(!harvesting) + open_machine() + +/obj/machinery/harvester/AltClick(mob/user) + if(harvesting || !user || !isliving(user) || state_open) + return + if(can_harvest()) + start_harvest() + +/obj/machinery/harvester/proc/can_harvest() + if(!powered(EQUIP) || state_open || !occupant || !iscarbon(occupant)) + return + var/mob/living/carbon/C = occupant + if(!allow_clothing) + for(var/A in C.held_items + C.get_equipped_items()) + if(!isitem(A)) + continue + var/obj/item/I = A + if(!(I.item_flags & NODROP)) + say("Subject may not have abiotic items on.") + playsound(src, 'sound/machines/buzz-sigh.ogg', 30, 1) + return + if(!(MOB_ORGANIC in C.mob_biotypes)) + say("Subject is not organic.") + playsound(src, 'sound/machines/buzz-sigh.ogg', 30, 1) + return + if(!allow_living && !(C.stat == DEAD || C.has_trait(TRAIT_FAKEDEATH))) //I mean, the machines scanners arent advanced enough to tell you're alive + say("Subject is still alive.") + playsound(src, 'sound/machines/buzz-sigh.ogg', 30, 1) + return + return TRUE + +/obj/machinery/harvester/proc/start_harvest() + if(!occupant || !iscarbon(occupant)) + return + var/mob/living/carbon/C = occupant + operation_order = reverseList(C.bodyparts) //Chest and head are first in bodyparts, so we invert it to make them suffer more + harvesting = TRUE + visible_message("The [name] begins warming up!") + say("Initializing harvest protocol.") + update_icon(TRUE) + addtimer(CALLBACK(src, .proc/harvest), interval) + +/obj/machinery/harvester/proc/harvest() + update_icon() + if(!harvesting || state_open || !powered(EQUIP) || !occupant || !iscarbon(occupant)) + return + playsound(src, 'sound/machines/juicer.ogg', 20, 1) + var/mob/living/carbon/C = occupant + if(!LAZYLEN(operation_order)) //The list is empty, so we're done here + end_harvesting() + return + var/turf/target + for(var/adir in list(EAST,NORTH,SOUTH,WEST)) + var/turf/T = get_step(src,adir) + if(!T) + continue + if(istype(T, /turf/closed)) + continue + target = T + break + if(!target) + target = get_turf(src) + for(var/obj/item/bodypart/BP in operation_order) //first we do non-essential limbs + BP.drop_limb() + C.emote("scream") + if(BP.body_zone != "chest") + BP.forceMove(target) //Move the limbs right next to it, except chest, that's a weird one + BP.drop_organs() + else + for(var/obj/item/organ/O in BP.dismember()) + O.forceMove(target) //Some organs, like chest ones, are different so we need to manually move them + operation_order.Remove(BP) + break + use_power(5000) + addtimer(CALLBACK(src, .proc/harvest), interval) + +/obj/machinery/harvester/proc/end_harvesting() + harvesting = FALSE + open_machine() + say("Subject has been succesfuly harvested.") + playsound(src, 'sound/machines/microwave/microwave-end.ogg', 100, 0) + +/obj/machinery/harvester/screwdriver_act(mob/living/user, obj/item/I) + . = ..() + if(.) + return TRUE + if(!state_open && !occupant) + if(default_deconstruction_screwdriver(user, "[initial(icon_state)]-o", initial(icon_state), I)) + return + +/obj/machinery/harvester/crowbar_act(mob/living/user, obj/item/I) + if(default_pry_open(I)) + return + if(default_deconstruction_crowbar(I)) + return + +/obj/machinery/harvester/default_pry_open(obj/item/I) //wew + . = !(state_open || panel_open || (flags_1 & NODECONSTRUCT_1)) && I.tool_behaviour == TOOL_CROWBAR //We removed is_operational() here + if(.) + I.play_tool_sound(src, 50) + visible_message("[usr] pries open \the [src].", "You pry open [src].") + open_machine() + +/obj/machinery/harvester/emag_act(mob/user) + if(obj_flags & EMAGGED) + return + obj_flags |= EMAGGED + allow_living = TRUE + to_chat(user, "You overload [src]'s lifesign scanners.") + +/obj/machinery/harvester/container_resist(mob/living/user) + if(!harvesting) + visible_message("[occupant] emerges from [src]!", + "You climb out of [src]!") + open_machine() + else + to_chat(user,"[src] is active and can't be opened!") //rip + +/obj/machinery/harvester/Exited(atom/movable/user) + if (!state_open && user == occupant) + container_resist(user) + +/obj/machinery/harvester/relaymove(mob/user) + if (!state_open) + container_resist(user) + +/obj/machinery/harvester/examine(mob/user) + ..() + if(stat & BROKEN) + return + if(state_open) + to_chat(user, "[src] must be closed before harvesting.") + else if(!harvesting) + to_chat(user, "Alt-click [src] to start harvesting.") diff --git a/code/game/machinery/launch_pad.dm b/code/game/machinery/launch_pad.dm index 0c1b67a63c..6b39c1b58f 100644 --- a/code/game/machinery/launch_pad.dm +++ b/code/game/machinery/launch_pad.dm @@ -11,7 +11,7 @@ var/stationary = TRUE //to prevent briefcase pad deconstruction and such var/display_name = "Launchpad" var/teleport_speed = 35 - var/range = 5 + var/range = 15 var/teleporting = FALSE //if it's in the process of teleporting var/power_efficiency = 1 var/x_offset = 0 @@ -148,18 +148,17 @@ idle_power_usage = 0 active_power_usage = 0 teleport_speed = 20 - range = 3 + range = 8 stationary = FALSE var/closed = TRUE - var/obj/item/briefcase_launchpad/briefcase + var/obj/item/storage/briefcase/launchpad/briefcase -/obj/machinery/launchpad/briefcase/Initialize() - . = ..() - if(istype(loc, /obj/item/briefcase_launchpad)) - briefcase = loc - else - log_game("[src] has been spawned without a briefcase.") - return INITIALIZE_HINT_QDEL +/obj/machinery/launchpad/briefcase/Initialize(mapload, briefcase) + . = ..() + if(!briefcase) + log_game("[src] has been spawned without a briefcase.") + return INITIALIZE_HINT_QDEL + src.briefcase = briefcase /obj/machinery/launchpad/briefcase/Destroy() QDEL_NULL(briefcase) @@ -180,47 +179,37 @@ usr.visible_message("[usr] starts closing [src]...", "You start closing [src]...") if(do_after(usr, 30, target = usr)) usr.put_in_hands(briefcase) - forceMove(briefcase) + moveToNullspace() //hides it from suitcase contents closed = TRUE /obj/machinery/launchpad/briefcase/attackby(obj/item/I, mob/user, params) if(istype(I, /obj/item/launchpad_remote)) var/obj/item/launchpad_remote/L = I + if(L.pad == src) //do not attempt to link when already linked + return ..() L.pad = src to_chat(user, "You link [src] to [L].") else return ..() //Briefcase item that contains the launchpad. -/obj/item/briefcase_launchpad - name = "briefcase" - desc = "It's made of AUTHENTIC faux-leather and has a price-tag still attached. Its owner must be a real professional." - icon = 'icons/obj/storage.dmi' - icon_state = "briefcase" - lefthand_file = 'icons/mob/inhands/equipment/briefcase_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/briefcase_righthand.dmi' - flags_1 = CONDUCT_1 - force = 8 - hitsound = "swing_hit" - throw_speed = 2 - throw_range = 4 - w_class = WEIGHT_CLASS_BULKY - attack_verb = list("bashed", "battered", "bludgeoned", "thrashed", "whacked") - resistance_flags = FLAMMABLE - max_integrity = 150 +/obj/item/storage/briefcase/launchpad var/obj/machinery/launchpad/briefcase/pad -/obj/item/briefcase_launchpad/Initialize() +/obj/item/storage/briefcase/launchpad/Initialize() + pad = new(null, src) //spawns pad in nullspace to hide it from briefcase contents . = ..() - pad = new(src) -/obj/item/briefcase_launchpad/Destroy() +/obj/item/storage/briefcase/launchpad/Destroy() if(!QDELETED(pad)) - qdel(pad) - pad = null + QDEL_NULL(pad) return ..() -/obj/item/briefcase_launchpad/attack_self(mob/user) +/obj/item/storage/briefcase/launchpad/PopulateContents() + new /obj/item/pen(src) + new /obj/item/launchpad_remote(src, pad) + +/obj/item/storage/briefcase/launchpad/attack_self(mob/user) if(!isturf(user.loc)) //no setting up in a locker return add_fingerprint(user) @@ -229,25 +218,36 @@ pad.forceMove(get_turf(src)) pad.closed = FALSE user.transferItemToLoc(src, pad, TRUE) + SEND_SIGNAL(src, COMSIG_TRY_STORAGE_HIDE_ALL) -/obj/item/briefcase_launchpad/attackby(obj/item/I, mob/user, params) +/obj/item/storage/briefcase/launchpad/attackby(obj/item/I, mob/user, params) if(istype(I, /obj/item/launchpad_remote)) var/obj/item/launchpad_remote/L = I + if(L.pad == src.pad) //do not attempt to link when already linked + return ..() L.pad = src.pad to_chat(user, "You link [pad] to [L].") else - return ..() + return ..() /obj/item/launchpad_remote - name = "\improper Launchpad Control Remote" - desc = "Used to teleport objects to and from a portable launchpad." - icon = 'icons/obj/telescience.dmi' - icon_state = "blpad-remote" + name = "folder" + desc = "A folder." + icon = 'icons/obj/bureaucracy.dmi' + icon_state = "folder" w_class = WEIGHT_CLASS_SMALL - slot_flags = ITEM_SLOT_BELT var/sending = TRUE var/obj/machinery/launchpad/briefcase/pad +/obj/item/launchpad_remote/Initialize(mapload, pad) //remote spawns linked to the briefcase pad + . = ..() + src.pad = pad + +/obj/item/launchpad_remote/attack_self(mob/user) + . = ..() + ui_interact(user) + to_chat(user, "[src] projects a display onto your retina.") + /obj/item/launchpad_remote/ui_interact(mob/user, ui_key = "launchpad_remote", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) @@ -340,7 +340,7 @@ if("rename") . = TRUE - var/new_name = stripped_input(usr, "How do you want to rename the launchpad?", "Launchpad", pad.display_name, 15) as text|null + var/new_name = stripped_input(usr, "How do you want to rename the launchpad?", "Launchpad", pad.display_name, 15) if(!new_name) return pad.display_name = new_name diff --git a/code/game/machinery/newscaster.dm b/code/game/machinery/newscaster.dm index bb4868d054..86e8fc8af5 100644 --- a/code/game/machinery/newscaster.dm +++ b/code/game/machinery/newscaster.dm @@ -118,17 +118,17 @@ GLOBAL_LIST_EMPTY(allCasters) newChannel.is_admin_channel = adminChannel network_channels += newChannel -/datum/newscaster/feed_network/proc/SubmitArticle(msg, author, channel_name, obj/item/photo/photo, adminMessage = 0, allow_comments = 1) +/datum/newscaster/feed_network/proc/SubmitArticle(msg, author, channel_name, datum/picture/picture, adminMessage = 0, allow_comments = 1) var/datum/newscaster/feed_message/newMsg = new /datum/newscaster/feed_message newMsg.author = author newMsg.body = msg newMsg.time_stamp = "[station_time_timestamp()]" newMsg.is_admin_message = adminMessage newMsg.locked = !allow_comments - if(photo) - newMsg.img = photo.picture.picture_image - newMsg.caption = photo.scribble - newMsg.photo_file = save_photo(photo.picture.picture_image) + if(picture) + newMsg.img = picture.picture_image + newMsg.caption = picture.caption + newMsg.photo_file = save_photo(picture.picture_image) for(var/datum/newscaster/feed_channel/FC in network_channels) if(FC.channel_name == channel_name) FC.messages += newMsg @@ -138,15 +138,15 @@ GLOBAL_LIST_EMPTY(allCasters) lastAction ++ newMsg.creationTime = lastAction -/datum/newscaster/feed_network/proc/submitWanted(criminal, body, scanned_user, obj/item/photo/photo, adminMsg = 0, newMessage = 0) +/datum/newscaster/feed_network/proc/submitWanted(criminal, body, scanned_user, datum/picture/picture, adminMsg = 0, newMessage = 0) wanted_issue.active = 1 wanted_issue.criminal = criminal wanted_issue.body = body wanted_issue.scannedUser = scanned_user wanted_issue.isAdminMsg = adminMsg - if(photo) - wanted_issue.img = photo.picture.picture_image - wanted_issue.photo_file = save_photo(photo.picture.picture_image) + if(picture) + wanted_issue.img = picture.picture_image + wanted_issue.photo_file = save_photo(picture.picture_image) if(newMessage) for(var/obj/machinery/newscaster/N in GLOB.allCasters) N.newsAlert() @@ -197,7 +197,7 @@ GLOBAL_LIST_EMPTY(allCasters) var/alert = FALSE var/scanned_user = "Unknown" var/msg = "" - var/obj/item/photo/photo = null + var/datum/picture/picture var/channel_name = "" var/c_locked=0 var/datum/newscaster/feed_channel/viewing_channel = null @@ -221,7 +221,7 @@ GLOBAL_LIST_EMPTY(allCasters) /obj/machinery/newscaster/Destroy() GLOB.allCasters -= src viewing_channel = null - photo = null + picture = null return ..() /obj/machinery/newscaster/update_icon() @@ -298,7 +298,7 @@ GLOBAL_LIST_EMPTY(allCasters) if(CHANNEL.is_admin_channel) dat+="[CHANNEL.channel_name]
" else - dat+="[CHANNEL.channel_name] [(CHANNEL.censored) ? ("***") : ()]
" + dat+="[CHANNEL.channel_name] [(CHANNEL.censored) ? ("***") : ""]
" dat+="

Refresh" dat+="
Back" if(2) @@ -312,7 +312,7 @@ GLOBAL_LIST_EMPTY(allCasters) dat+="
Receiving Channel: [channel_name]
" dat+="Message Author: [scanned_user]
" dat+="Message Body:
[parsemarkdown(msg, user)]
" - dat+="Attach Photo: [(photo ? "Photo Attached" : "No Photo")]
" + dat+="Attach Photo: [(picture ? "Photo Attached" : "No Photo")]
" dat+="Comments [allow_comments ? "Enabled" : "Disabled"]
" dat+="
Submit

Cancel
" if(4) @@ -403,7 +403,7 @@ GLOBAL_LIST_EMPTY(allCasters) dat+="No feed channels found active...
" else for(var/datum/newscaster/feed_channel/CHANNEL in GLOB.news_network.network_channels) - dat+="[CHANNEL.channel_name] [(CHANNEL.censored) ? ("***") : ()]
" + dat+="[CHANNEL.channel_name] [(CHANNEL.censored) ? ("***") : ""]
" dat+="
Cancel" if(11) dat+="Nanotrasen D-Notice Handler
" @@ -414,7 +414,7 @@ GLOBAL_LIST_EMPTY(allCasters) dat+="No feed channels found active...
" else for(var/datum/newscaster/feed_channel/CHANNEL in GLOB.news_network.network_channels) - dat+="[CHANNEL.channel_name] [(CHANNEL.censored) ? ("***") : ()]
" + dat+="[CHANNEL.channel_name] [(CHANNEL.censored) ? ("***") : ""]
" dat+="
Back" if(12) dat+="[viewing_channel.channel_name]: \[ created by: [viewing_channel.returnAuthor(-1)] \]
" @@ -454,7 +454,7 @@ GLOBAL_LIST_EMPTY(allCasters) dat+="
" dat+="Criminal Name: [channel_name]
" dat+="Description: [msg]
" - dat+="Attach Photo: [(photo ? "Photo Attached" : "No Photo")]
" + dat+="Attach Photo: [(picture ? "Photo Attached" : "No Photo")]
" if(wanted_already) dat+="Wanted Issue created by:[GLOB.news_network.wanted_issue.scannedUser]
" else @@ -561,7 +561,7 @@ GLOBAL_LIST_EMPTY(allCasters) if(msg =="" || msg=="\[REDACTED\]" || scanned_user == "Unknown" || channel_name == "" ) screen=6 else - GLOB.news_network.SubmitArticle("[parsemarkdown(msg, usr)]", scanned_user, channel_name, photo, 0, allow_comments) + GLOB.news_network.SubmitArticle("[parsemarkdown(msg, usr)]", scanned_user, channel_name, picture, 0, allow_comments) SSblackbox.record_feedback("amount", "newscaster_stories", 1) screen=4 msg = "" @@ -612,13 +612,13 @@ GLOBAL_LIST_EMPTY(allCasters) if(choice=="Confirm") scan_user(usr) if(input_param==1) //If input_param == 1 we're submitting a new wanted issue. At 2 we're just editing an existing one. - GLOB.news_network.submitWanted(channel_name, msg, scanned_user, photo, 0 , 1) + GLOB.news_network.submitWanted(channel_name, msg, scanned_user, picture, 0 , 1) screen = 15 else if(GLOB.news_network.wanted_issue.isAdminMsg) alert("The wanted issue has been distributed by a Nanotrasen higherup. You cannot edit it.","Ok") return - GLOB.news_network.submitWanted(channel_name, msg, scanned_user, photo) + GLOB.news_network.submitWanted(channel_name, msg, scanned_user, picture) screen = 19 updateUsrDialog() else if(href_list["cancel_wanted"]) @@ -698,14 +698,15 @@ GLOBAL_LIST_EMPTY(allCasters) FC.body = cominput FC.time_stamp = station_time_timestamp() FM.comments += FC - log_talk(usr,"[key_name(usr)] as [scanned_user] commented on message [FM.returnBody(-1)] -- [FC.body]",LOGCOMMENT) + usr.log_message("(as [scanned_user]) commented on message [FM.returnBody(-1)] -- [FC.body]", LOG_COMMENT) updateUsrDialog() else if(href_list["del_comment"]) var/datum/newscaster/feed_comment/FC = locate(href_list["del_comment"]) var/datum/newscaster/feed_message/FM = locate(href_list["del_comment_msg"]) - FM.comments -= FC - qdel(FC) - updateUsrDialog() + if(istype(FC) && istype(FM)) + FM.comments -= FC + qdel(FC) + updateUsrDialog() else if(href_list["lock_comment"]) var/datum/newscaster/feed_message/FM = locate(href_list["lock_comment"]) FM.locked ^= 1 @@ -782,17 +783,9 @@ GLOBAL_LIST_EMPTY(allCasters) take_damage(5, BRUTE, "melee") /obj/machinery/newscaster/proc/AttachPhoto(mob/user) + var/obj/item/photo/photo = user.is_holding_item_of_type(/obj/item/photo) if(photo) - if(!photo.sillynewscastervar) - photo.forceMove(drop_location()) - if(!issilicon(user)) - user.put_in_inactive_hand(photo) - else - qdel(photo) - photo = null - photo = user.is_holding_item_of_type(/obj/item/photo) - if(photo && !user.transferItemToLoc(photo, src)) - photo = null + picture = photo.picture if(issilicon(user)) var/obj/item/camera/siliconcam/targetcam if(isAI(user)) @@ -810,10 +803,8 @@ GLOBAL_LIST_EMPTY(allCasters) to_chat(usr, "No images saved") return var/datum/picture/selection = targetcam.selectpicture(user) - var/obj/item/photo/P = new(null, selection) - P.sillynewscastervar = TRUE - photo = P - qdel(P) + if(selection) + picture = selection /obj/machinery/newscaster/proc/scan_user(mob/living/user) if(ishuman(user)) @@ -894,7 +885,7 @@ GLOBAL_LIST_EMPTY(allCasters) /obj/item/newspaper/suicide_act(mob/user) user.visible_message("[user] is focusing intently on [src]! It looks like [user.p_theyre()] trying to commit sudoku... until [user.p_their()] eyes light up with realization!") - user.say(";JOURNALISM IS MY CALLING! EVERYBODY APPRECIATES UNBIASED REPORTI-GLORF") + user.say(";JOURNALISM IS MY CALLING! EVERYBODY APPRECIATES UNBIASED REPORTI-GLORF", forced="newspaper suicide") var/mob/living/carbon/human/H = user var/obj/W = new /obj/item/reagent_containers/food/drinks/bottle/whiskey(H.loc) playsound(H.loc, 'sound/items/drink.ogg', rand(10,50), 1) diff --git a/code/game/machinery/pipe/construction.dm b/code/game/machinery/pipe/construction.dm index e89bd7f680..6b8cac544e 100644 --- a/code/game/machinery/pipe/construction.dm +++ b/code/game/machinery/pipe/construction.dm @@ -212,6 +212,10 @@ Buildable meters qdel(src) /obj/item/pipe_meter/screwdriver_act(mob/living/user, obj/item/S) + . = ..() + if(.) + return TRUE + if(!isturf(loc)) to_chat(user, "You need to fasten it to the floor!") return TRUE diff --git a/code/game/machinery/porta_turret/portable_turret.dm b/code/game/machinery/porta_turret/portable_turret.dm index d663609410..fd5607b4c5 100644 --- a/code/game/machinery/porta_turret/portable_turret.dm +++ b/code/game/machinery/porta_turret/portable_turret.dm @@ -548,6 +548,7 @@ //Shooting Code: A.preparePixelProjectile(target, T) + A.firer = src A.fire() return A @@ -621,7 +622,7 @@ if(!can_interact(caller)) remove_control() return FALSE - add_logs(caller,A,"fired with manual turret control at") + log_combat(caller,A,"fired with manual turret control at") target(A) return TRUE @@ -736,8 +737,8 @@ integrity_failure = 60 name = "Old Laser Turret" desc = "A turret built with substandard parts and run down further with age. Still capable of delivering lethal lasers to the odd space carp, but not much else." - stun_projectile = /obj/item/projectile/beam/weak - lethal_projectile = /obj/item/projectile/beam/weak + stun_projectile = /obj/item/projectile/beam/weak/penetrator + lethal_projectile = /obj/item/projectile/beam/weak/penetrator faction = list("neutral","silicon","turret") //////////////////////// @@ -789,6 +790,12 @@ turrets |= T T.cp = src +/obj/machinery/turretid/examine(mob/user) + ..() + if(issilicon(user) && (!stat & BROKEN)) + to_chat(user, "Ctrl-click [src] to [ enabled ? "disable" : "enable"] turrets.") + to_chat(user, "Alt-click [src] to set turrets to [ lethal ? "stun" : "kill"].") + /obj/machinery/turretid/attackby(obj/item/I, mob/user, params) if(stat & BROKEN) return diff --git a/code/game/machinery/quantum_pad.dm b/code/game/machinery/quantum_pad.dm index 8962ab60a5..7a8552607b 100644 --- a/code/game/machinery/quantum_pad.dm +++ b/code/game/machinery/quantum_pad.dm @@ -11,7 +11,7 @@ var/teleport_cooldown = 400 //30 seconds base due to base parts var/teleport_speed = 50 var/last_teleport //to handle the cooldown - var/teleporting = 0 //if it's in the process of teleporting + var/teleporting = FALSE //if it's in the process of teleporting var/power_efficiency = 1 var/obj/machinery/quantumpad/linked_pad @@ -29,6 +29,14 @@ mapped_quantum_pads -= map_pad_id return ..() +/obj/machinery/quantumpad/examine(mob/user) + ..() + to_chat(user, "It is [ linked_pad ? "currently" : "not"] linked to another pad.") + if(!panel_open) + to_chat(user, "The panel is screwed in, obstructing the linking device.") + else + to_chat(user, "The linking device is now able to be scanned with a multitool.") + /obj/machinery/quantumpad/RefreshParts() var/E = 0 for(var/obj/item/stock_parts/capacitor/C in component_parts) @@ -50,14 +58,21 @@ if(istype(I, /obj/item/multitool)) var/obj/item/multitool/M = I M.buffer = src - to_chat(user, "You save the data in [I]'s buffer.") - return 1 + to_chat(user, "You save the data in [I]'s buffer. It can now be saved to pads with closed panels.") + return TRUE else if(istype(I, /obj/item/multitool)) var/obj/item/multitool/M = I if(istype(M.buffer, /obj/machinery/quantumpad)) - linked_pad = M.buffer - to_chat(user, "You link [src] to the one in [I]'s buffer.") - return 1 + if(M.buffer == src) + to_chat(user, "You cannot link a pad to itself!") + return TRUE + else + linked_pad = M.buffer + to_chat(user, "You link [src] to the one in [I]'s buffer.") + return TRUE + else + to_chat(user, "There is no quantum pad data saved in [I]'s buffer!") + return TRUE if(default_deconstruction_crowbar(I)) return @@ -105,22 +120,22 @@ /obj/machinery/quantumpad/proc/doteleport(mob/user) if(linked_pad) playsound(get_turf(src), 'sound/weapons/flash.ogg', 25, 1) - teleporting = 1 + teleporting = TRUE spawn(teleport_speed) if(!src || QDELETED(src)) - teleporting = 0 + teleporting = FALSE return if(stat & NOPOWER) to_chat(user, "[src] is unpowered!") - teleporting = 0 + teleporting = FALSE return if(!linked_pad || QDELETED(linked_pad) || linked_pad.stat & NOPOWER) to_chat(user, "Linked pad is not responding to ping. Teleport aborted.") - teleporting = 0 + teleporting = FALSE return - teleporting = 0 + teleporting = FALSE last_teleport = world.time // use a lot of power diff --git a/code/game/machinery/recharger.dm b/code/game/machinery/recharger.dm index d0f72d8a30..94b6eee8aa 100755 --- a/code/game/machinery/recharger.dm +++ b/code/game/machinery/recharger.dm @@ -7,6 +7,7 @@ idle_power_usage = 4 active_power_usage = 250 circuit = /obj/item/circuitboard/machine/recharger + pass_flags = PASSTABLE var/obj/item/charging = null var/recharge_coeff = 1 @@ -20,6 +21,16 @@ for(var/obj/item/stock_parts/capacitor/C in component_parts) recharge_coeff = C.rating +/obj/machinery/recharger/proc/setCharging(new_charging) + charging = new_charging + if (new_charging) + START_PROCESSING(SSmachines, src) + use_power = ACTIVE_POWER_USE + update_icon(scan = TRUE) + else + use_power = IDLE_POWER_USE + update_icon() + /obj/machinery/recharger/attackby(obj/item/G, mob/user, params) if(istype(G, /obj/item/wrench)) if(charging) @@ -52,9 +63,8 @@ if(!user.transferItemToLoc(G, src)) return 1 - charging = G - use_power = ACTIVE_POWER_USE - update_icon(scan = TRUE) + setCharging(G) + else to_chat(user, "[src] isn't connected to anything!") return 1 @@ -79,21 +89,17 @@ charging.update_icon() charging.forceMove(drop_location()) user.put_in_hands(charging) - charging = null - use_power = IDLE_POWER_USE - update_icon() + setCharging(null) /obj/machinery/recharger/attack_tk(mob/user) if(charging) charging.update_icon() charging.forceMove(drop_location()) - charging = null - use_power = IDLE_POWER_USE - update_icon() + setCharging(null) /obj/machinery/recharger/process() if(stat & (NOPOWER|BROKEN) || !anchored) - return + return PROCESS_KILL var/using_power = 0 if(charging) @@ -113,6 +119,8 @@ using_power = 1 update_icon(using_power) return + else + return PROCESS_KILL /obj/machinery/recharger/power_change() ..() diff --git a/code/game/machinery/recycler.dm b/code/game/machinery/recycler.dm index 8cd31e75c6..f3d5a664e8 100644 --- a/code/game/machinery/recycler.dm +++ b/code/game/machinery/recycler.dm @@ -81,7 +81,7 @@ is_powered = FALSE icon_state = icon_name + "[is_powered]" + "[(blood ? "bld" : "")]" // add the blood tag at the end -/obj/machinery/recycler/CollidedWith(atom/movable/AM) +/obj/machinery/recycler/Bumped(atom/movable/AM) if(stat & (BROKEN|NOPOWER)) return @@ -171,7 +171,7 @@ // By default, the emagged recycler will gib all non-carbons. (human simple animal mobs don't count) if(iscarbon(L)) if(L.stat == CONSCIOUS) - L.say("ARRRRRRRRRRRGH!!!") + L.say("ARRRRRRRRRRRGH!!!", forced="recycler grinding") add_mob_blood(L) if(!blood && !issilicon(L)) diff --git a/code/game/machinery/requests_console.dm b/code/game/machinery/requests_console.dm index 2cbf29642f..f2c216ca98 100644 --- a/code/game/machinery/requests_console.dm +++ b/code/game/machinery/requests_console.dm @@ -302,7 +302,7 @@ GLOBAL_LIST_EMPTY(allConsoles) message = L.treat_message(message) minor_announce(message, "[department] Announcement:") GLOB.news_network.SubmitArticle(message, department, "Station Announcements", null) - log_talk(usr,"[key_name(usr)] has made a station announcement from [src] at [AREACOORD(usr)]: [message]",LOGSAY) + usr.log_talk(message, LOG_SAY, tag="station announcement from [src]") message_admins("[ADMIN_LOOKUPFLW(usr)] has made a station announcement from [src] at [AREACOORD(usr)].") announceAuth = FALSE message = "" diff --git a/code/game/machinery/shieldgen.dm b/code/game/machinery/shieldgen.dm index 798c27214d..e2aebd2370 100644 --- a/code/game/machinery/shieldgen.dm +++ b/code/game/machinery/shieldgen.dm @@ -15,11 +15,6 @@ setDir(pick(GLOB.cardinals)) air_update_turf(1) -/obj/structure/emergency_shield/Destroy() - density = FALSE - air_update_turf(1) - return ..() - /obj/structure/emergency_shield/Move() var/turf/T = loc . = ..() @@ -122,11 +117,11 @@ locked = pick(0,1) update_icon() -/obj/machinery/shieldgen/attack_hand(mob/user) +/obj/machinery/shieldgen/interact(mob/user) . = ..() if(.) return - if(locked) + if(locked && !issilicon(user)) to_chat(user, "The machine is locked, you are unable to use it!") return if(panel_open) @@ -363,7 +358,7 @@ add_fingerprint(user) return ..() -/obj/machinery/shieldwallgen/attack_hand(mob/user) +/obj/machinery/shieldwallgen/interact(mob/user) . = ..() if(.) return diff --git a/code/game/machinery/spaceheater.dm b/code/game/machinery/spaceheater.dm index dc4254b825..ce325505e2 100644 --- a/code/game/machinery/spaceheater.dm +++ b/code/game/machinery/spaceheater.dm @@ -65,7 +65,9 @@ /obj/machinery/space_heater/process() if(!on || !is_operational()) - return + if (on) // If it's broken, turn it off too + on = FALSE + return PROCESS_KILL if(cell && cell.charge > 0) var/turf/L = loc @@ -107,6 +109,7 @@ else on = FALSE update_icon() + return PROCESS_KILL /obj/machinery/space_heater/RefreshParts() var/laser = 0 @@ -201,6 +204,8 @@ mode = HEATER_MODE_STANDBY usr.visible_message("[usr] switches [on ? "on" : "off"] \the [src].", "You switch [on ? "on" : "off"] \the [src].") update_icon() + if (on) + START_PROCESSING(SSmachines, src) . = TRUE if("mode") setMode = params["mode"] diff --git a/code/game/machinery/status_display.dm b/code/game/machinery/status_display.dm index 105d47a719..e9216ca736 100644 --- a/code/game/machinery/status_display.dm +++ b/code/game/machinery/status_display.dm @@ -1,159 +1,58 @@ +// Status display +// (formerly Countdown timer display) + #define CHARS_PER_LINE 5 #define FONT_SIZE "5pt" #define FONT_COLOR "#09f" #define FONT_STYLE "Arial Black" #define SCROLL_SPEED 2 -// Status display -// (formerly Countdown timer display) +#define SD_BLANK 0 // 0 = Blank +#define SD_EMERGENCY 1 // 1 = Emergency Shuttle timer +#define SD_MESSAGE 2 // 2 = Arbitrary message(s) +#define SD_PICTURE 3 // 3 = alert picture -// Use to show shuttle ETA/ETD times -// Alert status -// And arbitrary messages set by comms computer +#define SD_AI_EMOTE 1 // 1 = AI emoticon +#define SD_AI_BSOD 2 // 2 = Blue screen of death +/// Status display which can show images and scrolling text. /obj/machinery/status_display + name = "status display" + desc = null icon = 'icons/obj/status_display.dmi' icon_state = "frame" - name = "status display" density = FALSE use_power = IDLE_POWER_USE idle_power_usage = 10 - var/mode = 1 // 0 = Blank - // 1 = Emergency Shuttle timer - // 2 = Arbitrary message(s) - // 3 = alert picture - // 4 = Supply shuttle timer - // 5 = Generic shuttle timer - var/picture_state // icon_state of alert picture + maptext_height = 26 + maptext_width = 32 + var/message1 = "" // message line 1 var/message2 = "" // message line 2 var/index1 // display index for scrolling messages or 0 if non-scrolling var/index2 - var/frequency = FREQ_STATUS_DISPLAYS - var/supply_display = 0 // true if a supply shuttle display - var/shuttle_id // Id used for "generic shuttle timer" mode +/// Immediately blank the display. +/obj/machinery/status_display/proc/remove_display() + cut_overlays() + if(maptext) + maptext = "" - var/friendc = 0 // track if Friend Computer mode - - maptext_height = 26 - maptext_width = 32 - - // new display - // register for radio system - -/obj/machinery/status_display/Initialize() - . = ..() - GLOB.ai_status_displays.Add(src) - SSradio.add_object(src, frequency) - -/obj/machinery/status_display/Destroy() - SSradio.remove_object(src,frequency) - GLOB.ai_status_displays.Remove(src) - return ..() - -// timed process - -/obj/machinery/status_display/process() - if(stat & NOPOWER) - remove_display() - return - update() - -/obj/machinery/status_display/emp_act(severity) - . = ..() - if(stat & (NOPOWER|BROKEN) || . & EMP_PROTECT_SELF) - return - set_picture("ai_bsod") - -// set what is displayed - -/obj/machinery/status_display/proc/update() - if(friendc && mode!=4) //Makes all status displays except supply shuttle timer display the eye -- Urist - set_picture("ai_friend") - return - - switch(mode) - if(0) //blank - remove_display() - if(1) //emergency shuttle timer - display_shuttle_status() - if(2) //custom messages - var/line1 - var/line2 - - if(!index1) - line1 = message1 - else - line1 = copytext(message1+"|"+message1, index1, index1+CHARS_PER_LINE) - var/message1_len = length(message1) - index1 += SCROLL_SPEED - if(index1 > message1_len) - index1 -= message1_len - - if(!index2) - line2 = message2 - else - line2 = copytext(message2+"|"+message2, index2, index2+CHARS_PER_LINE) - var/message2_len = length(message2) - index2 += SCROLL_SPEED - if(index2 > message2_len) - index2 -= message2_len - update_display(line1, line2) - if(4) // supply shuttle timer - var/line1 - var/line2 - if(SSshuttle.supply.mode == SHUTTLE_IDLE) - if(is_station_level(SSshuttle.supply.z)) - line1 = "CARGO" - line2 = "Docked" - else - line1 = "CARGO" - line2 = SSshuttle.supply.getTimerStr() - if(lentext(line2) > CHARS_PER_LINE) - line2 = "Error" - - update_display(line1, line2) - if(5) - display_shuttle_status() - -/obj/machinery/status_display/examine(mob/user) - . = ..() - switch(mode) - if(1,5) // Emergency or generic shuttle - var/obj/docking_port/mobile/shuttle - if(mode == 1) - shuttle = SSshuttle.emergency - else - shuttle = SSshuttle.getShuttle(shuttle_id) - - if (!shuttle) - to_chat(user, "The display says:
\tShuttle?") - else if (shuttle.timer) - to_chat(user, "The display says:
\t[shuttle.getModeStr()]: [shuttle.getTimerStr()]") - if (mode == 1 && shuttle) - to_chat(user, "Current shuttle: [shuttle.name].") - if(4) // Supply shuttle - var/obj/docking_port/mobile/shuttle = SSshuttle.supply - var/shuttleMsg = null - if (shuttle.mode == SHUTTLE_IDLE) - if (is_station_level(shuttle.z)) - shuttleMsg = "Docked" - else - shuttleMsg = "[shuttle.getModeStr()]: [shuttle.getTimerStr()]" - if (shuttleMsg) - to_chat(user, "The display says:
\t[shuttleMsg]") - if(2) // Custom message - if (message1 || message2) - var/msg = "The display says:" - if (message1) - msg += "
\t[message1]" - if (message2) - msg += "
\t[message2]" - to_chat(user, msg) +/// Immediately change the display to the given picture. +/obj/machinery/status_display/proc/set_picture(state) + remove_display() + add_overlay(state) +/// Immediately change the display to the given two lines. +/obj/machinery/status_display/proc/update_display(line1, line2) + var/new_text = {"
[line1]
[line2]
"} + if(maptext != new_text) + maptext = new_text +/// Prepare the display to marquee the given two lines. +/// +/// Call with no arguments to disable. /obj/machinery/status_display/proc/set_message(m1, m2) if(m1) index1 = (length(m1) > CHARS_PER_LINE) @@ -169,105 +68,260 @@ message2 = "" index2 = 0 -/obj/machinery/status_display/proc/set_picture(state) - picture_state = state - remove_display() - add_overlay(picture_state) - -/obj/machinery/status_display/proc/update_display(line1, line2) - var/new_text = {"
[line1]
[line2]
"} - if(maptext != new_text) - maptext = new_text - -/obj/machinery/status_display/proc/remove_display() - cut_overlays() - if(maptext) - maptext = "" - -/obj/machinery/status_display/proc/display_shuttle_status() - var/obj/docking_port/mobile/shuttle - - if(mode == 1) - shuttle = SSshuttle.emergency - else - shuttle = SSshuttle.getShuttle(shuttle_id) - - if(!shuttle) - update_display("shutl?","") - else if(shuttle.timer) - var/line1 = "-[shuttle.getModeStr()]-" - var/line2 = shuttle.getTimerStr() - - if(length(line2) > CHARS_PER_LINE) - line2 = "Error!" - update_display(line1, line2) - else - remove_display() - - -/obj/machinery/status_display/receive_signal(datum/signal/signal) - if(supply_display) - mode = 4 - return - switch(signal.data["command"]) - if("blank") - mode = 0 - if("shuttle") - mode = 1 - if("message") - mode = 2 - set_message(signal.data["msg1"], signal.data["msg2"]) - if("alert") - mode = 3 - set_picture(signal.data["picture_state"]) - -/obj/machinery/ai_status_display - icon = 'icons/obj/status_display.dmi' - desc = "A small screen which the AI can use to present itself." - icon_state = "frame" - name = "\improper AI display" - density = FALSE - - var/mode = 0 // 0 = Blank - // 1 = AI emoticon - // 2 = Blue screen of death - - var/picture_state // icon_state of ai picture - - var/emotion = "Neutral" - -/obj/machinery/ai_status_display/Initialize() - . = ..() - GLOB.ai_status_displays.Add(src) - -/obj/machinery/ai_status_display/Destroy() - GLOB.ai_status_displays.Remove(src) - . = ..() - -/obj/machinery/ai_status_display/attack_ai(mob/living/silicon/ai/user) - if(isAI(user)) - user.ai_statuschange() - -/obj/machinery/ai_status_display/process() +// Timed process - performs default marquee action if so needed. +/obj/machinery/status_display/process() if(stat & NOPOWER) - cut_overlays() - return + // No power, no processing. + remove_display() + return PROCESS_KILL + var/line1 = message1 + if(index1) + line1 = copytext("[message1]|[message1]", index1, index1+CHARS_PER_LINE) + var/message1_len = length(message1) + index1 += SCROLL_SPEED + if(index1 > message1_len) + index1 -= message1_len + + var/line2 = message2 + if(index2) + line2 = copytext("[message2]|[message2]", index2, index2+CHARS_PER_LINE) + var/message2_len = length(message2) + index2 += SCROLL_SPEED + if(index2 > message2_len) + index2 -= message2_len + + update_display(line1, line2) + if (!index1 && !index2) + // No marquee, no processing. + return PROCESS_KILL + +/// Update the display and, if necessary, re-enable processing. +/obj/machinery/status_display/proc/update() + if (process() != PROCESS_KILL) + START_PROCESSING(SSmachines, src) + +/obj/machinery/status_display/power_change() + . = ..() update() -/obj/machinery/ai_status_display/emp_act(severity) +/obj/machinery/status_display/emp_act(severity) . = ..() if(stat & (NOPOWER|BROKEN) || . & EMP_PROTECT_SELF) return set_picture("ai_bsod") -/obj/machinery/ai_status_display/proc/update() +/obj/machinery/status_display/examine(mob/user) + . = ..() + if (message1 || message2) + var/list/msg = list("The display says:") + if (message1) + msg += "
\t[html_encode(message1)]" + if (message2) + msg += "
\t[html_encode(message2)]" + to_chat(user, msg.Join()) - if(mode==0) //Blank - cut_overlays() +// Helper procs for child display types. +/obj/machinery/status_display/proc/display_shuttle_status(obj/docking_port/mobile/shuttle) + if(!shuttle) + // the shuttle is missing - no processing + update_display("shutl?","") + return PROCESS_KILL + else if(shuttle.timer) + var/line1 = "-[shuttle.getModeStr()]-" + var/line2 = shuttle.getTimerStr() + + if(length(line2) > CHARS_PER_LINE) + line2 = "error" + update_display(line1, line2) + else + // don't kill processing, the timer might turn back on + remove_display() + +/obj/machinery/status_display/proc/examine_shuttle(mob/user, obj/docking_port/mobile/shuttle) + if (shuttle) + var/modestr = shuttle.getModeStr() + if (modestr) + if (shuttle.timer) + modestr = "
\t[modestr]: [shuttle.getTimerStr()]" + else + modestr = "
\t[modestr]" + to_chat(user, "The display says:
\t[shuttle.name][modestr]") + else + to_chat(user, "The display says:
\tShuttle missing!") + + +/// Evac display which shows shuttle timer or message set by Command. +/obj/machinery/status_display/evac + var/frequency = FREQ_STATUS_DISPLAYS + var/mode = SD_EMERGENCY + var/friendc = FALSE // track if Friend Computer mode + var/last_picture // For when Friend Computer mode is undone + +/obj/machinery/status_display/evac/Initialize() + . = ..() + // register for radio system + SSradio.add_object(src, frequency) + +/obj/machinery/status_display/evac/Destroy() + SSradio.remove_object(src,frequency) + return ..() + +/obj/machinery/status_display/evac/process() + if(stat & NOPOWER) + // No power, no processing. + remove_display() + return PROCESS_KILL + + if(friendc) //Makes all status displays except supply shuttle timer display the eye -- Urist + set_picture("ai_friend") + return PROCESS_KILL + + switch(mode) + if(SD_BLANK) + remove_display() + return PROCESS_KILL + + if(SD_EMERGENCY) + return display_shuttle_status(SSshuttle.emergency) + + if(SD_MESSAGE) + return ..() + + if(SD_PICTURE) + set_picture(last_picture) + return PROCESS_KILL + +/obj/machinery/status_display/evac/examine(mob/user) + . = ..() + if(mode == SD_EMERGENCY) + examine_shuttle(user, SSshuttle.emergency) + else if(!message1 && !message2) + to_chat(user, "The display is blank.") + +/obj/machinery/status_display/evac/receive_signal(datum/signal/signal) + switch(signal.data["command"]) + if("blank") + mode = SD_BLANK + set_message(null, null) + if("shuttle") + mode = SD_EMERGENCY + set_message(null, null) + if("message") + mode = SD_MESSAGE + set_message(signal.data["msg1"], signal.data["msg2"]) + if("alert") + mode = SD_PICTURE + last_picture = signal.data["picture_state"] + set_picture(last_picture) + if("friendcomputer") + friendc = !friendc + update() + + +/// Supply display which shows the status of the supply shuttle. +/obj/machinery/status_display/supply + name = "supply display" + +/obj/machinery/status_display/supply/process() + if(stat & NOPOWER) + // No power, no processing. + remove_display() + return PROCESS_KILL + + var/line1 + var/line2 + if(!SSshuttle.supply) + // Might be missing in our first update on initialize before shuttles + // have loaded. Cross our fingers that it will soon return. + line1 = "CARGO" + line2 = "shutl?" + else if(SSshuttle.supply.mode == SHUTTLE_IDLE) + if(is_station_level(SSshuttle.supply.z)) + line1 = "CARGO" + line2 = "Docked" + else + line1 = "CARGO" + line2 = SSshuttle.supply.getTimerStr() + if(lentext(line2) > CHARS_PER_LINE) + line2 = "Error" + update_display(line1, line2) + +/obj/machinery/status_display/supply/examine(mob/user) + . = ..() + var/obj/docking_port/mobile/shuttle = SSshuttle.supply + var/shuttleMsg = null + if (shuttle.mode == SHUTTLE_IDLE) + if (is_station_level(shuttle.z)) + shuttleMsg = "Docked" + else + shuttleMsg = "[shuttle.getModeStr()]: [shuttle.getTimerStr()]" + if (shuttleMsg) + to_chat(user, "The display says:
\t[shuttleMsg]") + else + to_chat(user, "The display is blank.") + + +/// General-purpose shuttle status display. +/obj/machinery/status_display/shuttle + name = "shuttle display" + var/shuttle_id + +/obj/machinery/status_display/shuttle/process() + if(!shuttle_id || (stat & NOPOWER)) + // No power, no processing. + remove_display() + return PROCESS_KILL + + return display_shuttle_status(SSshuttle.getShuttle(shuttle_id)) + +/obj/machinery/status_display/shuttle/examine(mob/user) + . = ..() + if(shuttle_id) + examine_shuttle(user, SSshuttle.getShuttle(shuttle_id)) + else + to_chat(user, "The display is blank.") + +/obj/machinery/status_display/shuttle/vv_edit_var(var_name, var_value) + . = ..() + if(!.) return + switch(var_name) + if("shuttle_id") + update() - if(mode==1) // AI emoticon +/obj/machinery/status_display/shuttle/proc/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override) + if (port && (shuttle_id == initial(shuttle_id) || override)) + shuttle_id = port.id + update() + + +/// Pictograph display which the AI can use to emote. +/obj/machinery/status_display/ai + name = "\improper AI display" + desc = "A small screen which the AI can use to present itself." + + var/mode = SD_BLANK + var/emotion = "Neutral" + +/obj/machinery/status_display/ai/Initialize() + . = ..() + GLOB.ai_status_displays.Add(src) + +/obj/machinery/status_display/ai/Destroy() + GLOB.ai_status_displays.Remove(src) + . = ..() + +/obj/machinery/status_display/ai/attack_ai(mob/living/silicon/ai/user) + if(isAI(user)) + user.ai_statuschange() + +/obj/machinery/status_display/ai/process() + if(mode == SD_BLANK || (stat & NOPOWER)) + remove_display() + return PROCESS_KILL + + if(mode == SD_AI_EMOTE) switch(emotion) if("Very Happy") set_picture("ai_veryhappy") @@ -291,6 +345,8 @@ set_picture("ai_awesome") if("Dorfy") set_picture("ai_urist") + if("Thinking") + set_picture("ai_thinking") if("Facepalm") set_picture("ai_facepalm") if("Friend Computer") @@ -299,19 +355,13 @@ set_picture("ai_sal") if("Red Glow") set_picture("ai_hal") + return PROCESS_KILL - return - - if(mode==2) // BSOD + if(mode == SD_AI_BSOD) set_picture("ai_bsod") - return + return PROCESS_KILL -/obj/machinery/ai_status_display/proc/set_picture(state) - picture_state = state - cut_overlays() - add_overlay(picture_state) - #undef CHARS_PER_LINE #undef FONT_SIZE #undef FONT_COLOR diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm index 82ccadf5cc..a157f9c485 100644 --- a/code/game/machinery/suit_storage_unit.dm +++ b/code/game/machinery/suit_storage_unit.dm @@ -1,7 +1,7 @@ // SUIT STORAGE UNIT ///////////////// /obj/machinery/suit_storage_unit name = "suit storage unit" - desc = "An industrial unit made to hold space suits. It comes with a built-in UV cauterization mechanism. A small warning label advises that organic matter should not be placed into the unit." + desc = "An industrial unit made to hold and decontaminate irradiated equipment. It comes with a built-in UV cauterization mechanism. A small warning label advises that organic matter should not be placed into the unit." icon = 'icons/obj/machines/suit_storage.dmi' icon_state = "close" density = TRUE @@ -340,6 +340,7 @@ if(panel_open && is_wire_tool(I)) wires.interact(user) + return if(!state_open) if(default_deconstruction_screwdriver(user, "panel", "close", I)) return diff --git a/code/game/machinery/telecomms/broadcasting.dm b/code/game/machinery/telecomms/broadcasting.dm index 0873ad2df6..0771963b07 100644 --- a/code/game/machinery/telecomms/broadcasting.dm +++ b/code/game/machinery/telecomms/broadcasting.dm @@ -190,4 +190,20 @@ if(length(receive)) SSblackbox.LogBroadcast(frequency) + var/spans_part = "" + if(length(spans)) + spans_part = "(spans:" + for(var/S in spans) + spans_part = "[spans_part] [S]" + spans_part = "[spans_part] ) " + + var/lang_name = data["language"] + var/log_text = "\[[get_radio_name(frequency)]\] [spans_part]\"[message]\" (language: [lang_name])" + + var/mob/source_mob = virt.source + if(istype(source_mob)) + source_mob.log_message(log_text, LOG_TELECOMMS) + else + log_telecomms("[virt.source] [log_text] [loc_name(get_turf(virt.source))]") + QDEL_IN(virt, 50) // Make extra sure the virtualspeaker gets qdeleted diff --git a/code/game/machinery/telecomms/computers/message.dm b/code/game/machinery/telecomms/computers/message.dm index 5996bcea6b..b11c6c102d 100644 --- a/code/game/machinery/telecomms/computers/message.dm +++ b/code/game/machinery/telecomms/computers/message.dm @@ -423,7 +423,7 @@ )) // this will log the signal and transmit it to the target linkedServer.receive_information(signal, null) - log_talk(usr, "[key_name(usr)] (PDA: [name]) sent \"[custommessage]\" to [signal.format_target()]", LOGPDA) + usr.log_message("(PDA: [name]) sent \"[custommessage]\" to [signal.format_target()]", LOG_PDA) //Request Console Logs - KEY REQUIRED diff --git a/code/game/machinery/telecomms/machines/allinone.dm b/code/game/machinery/telecomms/machines/allinone.dm index 2d737b1f24..c2dd9a7828 100644 --- a/code/game/machinery/telecomms/machines/allinone.dm +++ b/code/game/machinery/telecomms/machines/allinone.dm @@ -17,7 +17,7 @@ flags_1 = NODECONSTRUCT_1 /obj/machinery/telecomms/allinone/Initialize() - ..() + . = ..() if (intercept) freq_listening = list(FREQ_SYNDICATE) diff --git a/code/game/machinery/telecomms/machines/message_server.dm b/code/game/machinery/telecomms/machines/message_server.dm index 3b2dbed96f..cc390e1fc0 100644 --- a/code/game/machinery/telecomms/machines/message_server.dm +++ b/code/game/machinery/telecomms/machines/message_server.dm @@ -144,7 +144,7 @@ M << browse("PDA Photo" \ + "" \ + "" \ - + "", "window=pdaphoto;size=[picture.psize_x]x[picture.psize_y]") + + "", "window=pdaphoto;size=[picture.psize_x]x[picture.psize_y];can-close=true") onclose(M, "pdaphoto") /datum/data_rc_msg diff --git a/code/game/machinery/teleporter.dm b/code/game/machinery/teleporter.dm index 2c1f9d01b0..cc83e6502a 100644 --- a/code/game/machinery/teleporter.dm +++ b/code/game/machinery/teleporter.dm @@ -40,7 +40,7 @@ break return power_station -/obj/machinery/teleport/hub/CollidedWith(atom/movable/AM) +/obj/machinery/teleport/hub/Bumped(atom/movable/AM) if(is_centcom_level(z)) to_chat(AM, "You can't use this here.") return diff --git a/code/game/machinery/transformer.dm b/code/game/machinery/transformer.dm index 4c74518937..1ebe8cb463 100644 --- a/code/game/machinery/transformer.dm +++ b/code/game/machinery/transformer.dm @@ -45,7 +45,7 @@ else icon_state = initial(icon_state) -/obj/machinery/transformer/CollidedWith(atom/movable/AM) +/obj/machinery/transformer/Bumped(atom/movable/AM) if(cooldown == 1) return diff --git a/code/game/machinery/washing_machine.dm b/code/game/machinery/washing_machine.dm index 56377e5a1f..0a9a135986 100644 --- a/code/game/machinery/washing_machine.dm +++ b/code/game/machinery/washing_machine.dm @@ -13,7 +13,7 @@ /obj/machinery/washing_machine/ComponentInitialize() . = ..() - AddComponent(/datum/component/redirect, list(COMSIG_COMPONENT_CLEAN_ACT), CALLBACK(src, .proc/clean_blood)) + AddComponent(/datum/component/redirect, list(COMSIG_COMPONENT_CLEAN_ACT = CALLBACK(src, .proc/clean_blood))) /obj/machinery/washing_machine/examine(mob/user) ..() @@ -40,6 +40,24 @@ busy = TRUE update_icon() addtimer(CALLBACK(src, .proc/wash_cycle), 200) + START_PROCESSING(SSfastprocess, src) + +/obj/machinery/washing_machine/process() + if (!busy) + animate(src, transform=matrix(), time=2) + return PROCESS_KILL + if (anchored) + if (prob(5)) + var/matrix/M = new + M.Translate(rand(-1, 1), rand(0, 1)) + animate(src, transform=M, time=1) + animate(transform=matrix(), time=1) + else + if (prob(1)) + step(src, pick(GLOB.cardinals)) + var/matrix/M = new + M.Translate(rand(-3, 3), rand(-1, 3)) + animate(src, transform=M, time=2) /obj/machinery/washing_machine/proc/clean_blood() if(!busy) @@ -188,6 +206,9 @@ add_overlay("wm_panel") /obj/machinery/washing_machine/attackby(obj/item/W, mob/user, params) + if(panel_open && !busy && default_unfasten_wrench(user, W)) + return + if(default_deconstruction_screwdriver(user, null, null, W)) update_icon() return diff --git a/code/game/mecha/combat/honker.dm b/code/game/mecha/combat/honker.dm index 0298e56089..125aecd667 100644 --- a/code/game/mecha/combat/honker.dm +++ b/code/game/mecha/combat/honker.dm @@ -99,6 +99,10 @@
Sounds of HONK:
"} @@ -133,6 +137,14 @@ switch(href_list["play_sound"]) if("sadtrombone") playsound(src, 'sound/misc/sadtrombone.ogg', 50) + if("bikehorn") + playsound(src, 'sound/items/bikehorn.ogg', 50) + if("airhorn2") + playsound(src, 'sound/items/airhorn2.ogg', 40) //soundfile has higher than average volume + if("carhorn") + playsound(src, 'sound/items/carhorn.ogg', 80) //soundfile has lower than average volume + if("party_horn") + playsound(src, 'sound/items/party_horn.ogg', 50) return /proc/rand_hex_color() diff --git a/code/game/mecha/equipment/mecha_equipment.dm b/code/game/mecha/equipment/mecha_equipment.dm index e434daa38d..066920a6df 100644 --- a/code/game/mecha/equipment/mecha_equipment.dm +++ b/code/game/mecha/equipment/mecha_equipment.dm @@ -43,7 +43,7 @@ /obj/item/mecha_parts/mecha_equipment/proc/critfail() if(chassis) - log_message("Critical failure",1) + log_message("Critical failure", color="red") /obj/item/mecha_parts/mecha_equipment/proc/get_equip_info() if(!chassis) @@ -147,9 +147,11 @@ chassis.occupant_message("[icon2html(src, chassis.occupant)] [message]") return -/obj/item/mecha_parts/mecha_equipment/proc/log_message(message) +/obj/item/mecha_parts/mecha_equipment/log_message(message, message_type=LOG_GAME, color=null) if(chassis) - chassis.log_message("[src]: [message]") + chassis.log_message("([src]) [message]", message_type, color) + else + ..() return diff --git a/code/game/mecha/equipment/tools/medical_tools.dm b/code/game/mecha/equipment/tools/medical_tools.dm index 3ede481c60..99baad11ae 100644 --- a/code/game/mecha/equipment/tools/medical_tools.dm +++ b/code/game/mecha/equipment/tools/medical_tools.dm @@ -194,7 +194,7 @@ if(to_inject && patient.reagents.get_reagent_amount(R.id) + to_inject <= inject_amount*2) occupant_message("Injecting [patient] with [to_inject] units of [R.name].") log_message("Injecting [patient] with [to_inject] units of [R.name].") - add_logs(chassis.occupant, patient, "injected", "[name] ([R] - [to_inject] units)") + log_combat(chassis.occupant, patient, "injected", "[name] ([R] - [to_inject] units)") SG.reagents.trans_id_to(patient,R.id,to_inject) update_equip_info() return @@ -338,7 +338,7 @@ mechsyringe.reagents.reaction(M, INJECT) mechsyringe.reagents.trans_to(M, mechsyringe.reagents.total_volume) M.take_bodypart_damage(2) - add_logs(originaloccupant, M, "shot", "syringegun") + log_combat(originaloccupant, M, "shot", "syringegun") break else if(mechsyringe.loc == trg) mechsyringe.icon_state = initial(mechsyringe.icon_state) diff --git a/code/game/mecha/equipment/tools/mining_tools.dm b/code/game/mecha/equipment/tools/mining_tools.dm index de19c28ef6..b82c7c3617 100644 --- a/code/game/mecha/equipment/tools/mining_tools.dm +++ b/code/game/mecha/equipment/tools/mining_tools.dm @@ -111,9 +111,9 @@ /obj/item/mecha_parts/mecha_equipment/drill/proc/drill_mob(mob/living/target, mob/user) target.visible_message("[chassis] is drilling [target] with [src]!", \ "[chassis] is drilling you with [src]!") - add_logs(user, target, "drilled", "[name]", "(INTENT: [uppertext(user.a_intent)]) (DAMTYPE: [uppertext(damtype)])") + log_combat(user, target, "drilled", "[name]", "(INTENT: [uppertext(user.a_intent)]) (DAMTYPE: [uppertext(damtype)])") if(target.stat == DEAD && target.getBruteLoss() >= 200) - add_logs(user, target, "gibbed", name) + log_combat(user, target, "gibbed", name) if(LAZYLEN(target.butcher_results) || LAZYLEN(target.guaranteed_butcher_results)) GET_COMPONENT_FROM(butchering, /datum/component/butchering, src) butchering.Butcher(chassis, target) diff --git a/code/game/mecha/equipment/tools/other_tools.dm b/code/game/mecha/equipment/tools/other_tools.dm index b7796849f1..1a3886c3df 100644 --- a/code/game/mecha/equipment/tools/other_tools.dm +++ b/code/game/mecha/equipment/tools/other_tools.dm @@ -468,7 +468,7 @@ fuel_per_cycle_idle = 10 fuel_per_cycle_active = 30 power_per_cycle = 50 - var/rad_per_cycle = 3 + var/rad_per_cycle = 30 /obj/item/mecha_parts/mecha_equipment/generator/nuclear/generator_init() fuel = new /obj/item/stack/sheet/mineral/uranium(src, 0) diff --git a/code/game/mecha/equipment/tools/work_tools.dm b/code/game/mecha/equipment/tools/work_tools.dm index bc781d1f07..ea9465184a 100644 --- a/code/game/mecha/equipment/tools/work_tools.dm +++ b/code/game/mecha/equipment/tools/work_tools.dm @@ -64,7 +64,7 @@ target.visible_message("[chassis] squeezes [target].", \ "[chassis] squeezes [target].",\ "You hear something crack.") - add_logs(chassis.occupant, M, "attacked", "[name]", "(INTENT: [uppertext(chassis.occupant.a_intent)]) (DAMTYE: [uppertext(damtype)])") + log_combat(chassis.occupant, M, "attacked", "[name]", "(INTENT: [uppertext(chassis.occupant.a_intent)]) (DAMTYE: [uppertext(damtype)])") else step_away(M,chassis) occupant_message("You push [target] out of the way.") @@ -124,7 +124,7 @@ M.updatehealth() target.visible_message("[chassis] destroys [target] in an unholy fury.", \ "[chassis] destroys [target] in an unholy fury.") - add_logs(chassis.occupant, M, "attacked", "[name]", "(INTENT: [uppertext(chassis.occupant.a_intent)]) (DAMTYE: [uppertext(damtype)])") + log_combat(chassis.occupant, M, "attacked", "[name]", "(INTENT: [uppertext(chassis.occupant.a_intent)]) (DAMTYE: [uppertext(damtype)])") else target.visible_message("[chassis] destroys [target] in an unholy fury.", \ "[chassis] destroys [target] in an unholy fury.") @@ -147,7 +147,7 @@ playsound(src, get_dismember_sound(), 80, TRUE) target.visible_message("[chassis] rips [target]'s arms off.", \ "[chassis] rips [target]'s arms off.") - add_logs(chassis.occupant, M, "dismembered of[limbs_gone],", "[name]", "(INTENT: [uppertext(chassis.occupant.a_intent)]) (DAMTYE: [uppertext(damtype)])") + log_combat(chassis.occupant, M, "dismembered of[limbs_gone],", "[name]", "(INTENT: [uppertext(chassis.occupant.a_intent)]) (DAMTYE: [uppertext(damtype)])") else target.visible_message("[chassis] rips [target]'s arms off.", \ "[chassis] rips [target]'s arms off.") @@ -240,8 +240,8 @@ GLOB.rcd_list += src /obj/item/mecha_parts/mecha_equipment/rcd/Destroy() - GLOB.rcd_list -= src - return ..() + GLOB.rcd_list -= src + return ..() /obj/item/mecha_parts/mecha_equipment/rcd/action(atom/target) if(istype(target, /turf/open/space/transit))//>implying these are ever made -Sieve diff --git a/code/game/mecha/mech_fabricator.dm b/code/game/mecha/mech_fabricator.dm index c1f41ac5c5..01e304872f 100644 --- a/code/game/mecha/mech_fabricator.dm +++ b/code/game/mecha/mech_fabricator.dm @@ -36,7 +36,7 @@ /obj/machinery/mecha_part_fabricator/Initialize() var/datum/component/material_container/materials = AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TITANIUM, MAT_BLUESPACE), 0, - TRUE, list(/obj/item/stack), CALLBACK(src, .proc/is_insertion_ready), CALLBACK(src, .proc/AfterMaterialInsert)) + TRUE, /obj/item/stack, CALLBACK(src, .proc/is_insertion_ready), CALLBACK(src, .proc/AfterMaterialInsert)) materials.precise_insertion = TRUE stored_research = new return ..() diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index 43fc52144c..93fcda2ea9 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -411,7 +411,7 @@ for(var/mob/M in get_hearers_in_view(7,src)) if(M.client) speech_bubble_recipients.Add(M.client) - INVOKE_ASYNC(GLOBAL_PROC, /.proc/flick_overlay, image('icons/mob/talk.dmi', src, "machine[say_test(raw_message)]",MOB_LAYER+1), speech_bubble_recipients, 30) + INVOKE_ASYNC(GLOBAL_PROC, /proc/flick_overlay, image('icons/mob/talk.dmi', src, "machine[say_test(raw_message)]",MOB_LAYER+1), speech_bubble_recipients, 30) //////////////////////////// ///// Action processing //// @@ -569,7 +569,7 @@ playsound(src,stepsound,40,1) return result -/obj/mecha/Collide(var/atom/obstacle) +/obj/mecha/Bump(var/atom/obstacle) if(phasing && get_charge() >= phasing_energy_drain && !throwing) spawn() if(can_move) @@ -1015,9 +1015,10 @@ to_chat(occupant, "[icon2html(src, occupant)] [message]") return -/obj/mecha/proc/log_message(message as text,red=null) +/obj/mecha/log_message(message as text, message_type=LOG_GAME, color=null) log.len++ - log[log.len] = list("time"="[station_time_timestamp()]","date","year"="[GLOB.year_integer+540]","message"="[red?"":null][message][red?"":null]") + log[log.len] = list("time"="[station_time_timestamp()]","date","year"="[GLOB.year_integer+540]","message"="[color?"":null][message][color?"":null]") + ..() return log.len /obj/mecha/proc/log_append_to_last(message as text,red=null) diff --git a/code/game/mecha/mecha_actions.dm b/code/game/mecha/mecha_actions.dm index eee71818c5..6d42c302e1 100644 --- a/code/game/mecha/mecha_actions.dm +++ b/code/game/mecha/mecha_actions.dm @@ -265,7 +265,7 @@ if("fire") new_damtype = "tox" chassis.occupant_message("A bone-chillingly thick plasteel needle protracts from the exosuit's palm.") - chassis.damtype = new_damtype. + chassis.damtype = new_damtype button_icon_state = "mech_damtype_[new_damtype]" playsound(src, 'sound/mecha/mechmove01.ogg', 50, 1) UpdateButtonIcon() diff --git a/code/game/mecha/mecha_construction_paths.dm b/code/game/mecha/mecha_construction_paths.dm index 936724af9b..714c66d032 100644 --- a/code/game/mecha/mecha_construction_paths.dm +++ b/code/game/mecha/mecha_construction_paths.dm @@ -198,7 +198,7 @@ user.visible_message("[user] removes the wiring from [parent].", "You remove the wiring from [parent].") if(5) if(diff==FORWARD) - user.visible_message("[user] installs the central control module into [parent].", "You install the central computer mainboard into [parent].") + user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].") else user.visible_message("[user] disconnects the wiring of [parent].", "You disconnect the wiring of [parent].") if(6) @@ -208,7 +208,7 @@ user.visible_message("[user] removes the central control module from [parent].", "You remove the central computer mainboard from [parent].") if(7) if(diff==FORWARD) - user.visible_message("[user] installs the peripherals control module into [parent].", "You install the peripherals control module into [parent].") + user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].") else user.visible_message("[user] unfastens the mainboard.", "You unfasten the mainboard.") if(8) @@ -218,7 +218,7 @@ user.visible_message("[user] removes the peripherals control module from [parent].", "You remove the peripherals control module from [parent].") if(9) if(diff==FORWARD) - user.visible_message("[user] installs the power cell into [parent].", "You install the power cell into [parent].") + user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].") else user.visible_message("[user] unfastens the peripherals control module.", "You unfasten the peripherals control module.") if(10) @@ -358,7 +358,7 @@ list( "key" = TOOL_SCREWDRIVER, "back_key" = TOOL_CROWBAR, - "desc" = "Advanced scanner module is installed." + "desc" = "Scanner module is installed." ), //13 @@ -366,14 +366,14 @@ "key" = /obj/item/stock_parts/capacitor, "action" = ITEM_MOVE_INSIDE, "back_key" = TOOL_SCREWDRIVER, - "desc" = "Advanced scanner module is secured." + "desc" = "Scanner module is secured." ), //14 list( "key" = TOOL_SCREWDRIVER, "back_key" = TOOL_CROWBAR, - "desc" = "Advanced capacitor is installed." + "desc" = "Capacitor is installed." ), //15 @@ -381,7 +381,7 @@ "key" = /obj/item/stock_parts/cell, "action" = ITEM_MOVE_INSIDE, "back_key" = TOOL_SCREWDRIVER, - "desc" = "Advanced capacitor is secured." + "desc" = "Capacitor is secured." ), //16 @@ -437,7 +437,7 @@ ) -/datum/component/construction/mecha/gygax/action(atom/used_atom,mob/user) +/datum/component/construction/mecha/gygax/action(datum/source, atom/used_atom, mob/user) return check_step(used_atom,user) /datum/component/construction/mecha/gygax/custom_action(obj/item/I, mob/living/user, diff) @@ -464,7 +464,7 @@ user.visible_message("[user] removes the wiring from [parent].", "You remove the wiring from [parent].") if(5) if(diff==FORWARD) - user.visible_message("[user] installs the central control module into [parent].", "You install the central computer mainboard into [parent].") + user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].") else user.visible_message("[user] disconnects the wiring of [parent].", "You disconnect the wiring of [parent].") if(6) @@ -474,7 +474,7 @@ user.visible_message("[user] removes the central control module from [parent].", "You remove the central computer mainboard from [parent].") if(7) if(diff==FORWARD) - user.visible_message("[user] installs the peripherals control module into [parent].", "You install the peripherals control module into [parent].") + user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].") else user.visible_message("[user] unfastens the mainboard.", "You unfasten the mainboard.") if(8) @@ -484,7 +484,7 @@ user.visible_message("[user] removes the peripherals control module from [parent].", "You remove the peripherals control module from [parent].") if(9) if(diff==FORWARD) - user.visible_message("[user] installs the weapon control module into [parent].", "You install the weapon control module into [parent].") + user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].") else user.visible_message("[user] unfastens the peripherals control module.", "You unfasten the peripherals control module.") if(10) @@ -494,19 +494,19 @@ user.visible_message("[user] removes the weapon control module from [parent].", "You remove the weapon control module from [parent].") if(11) if(diff==FORWARD) - user.visible_message("[user] installs scanner module to [parent].", "You install scanner module to [parent].") + user.visible_message("[user] installs [I] to [parent].", "You install [I] to [parent].") else user.visible_message("[user] unfastens the weapon control module.", "You unfasten the weapon control module.") if(12) if(diff==FORWARD) - user.visible_message("[user] secures the advanced scanner module.", "You secure the scanner module.") + user.visible_message("[user] secures the scanner module.", "You secure the scanner module.") else - user.visible_message("[user] removes the advanced scanner module from [parent].", "You remove the scanner module from [parent].") + user.visible_message("[user] removes the scanner module from [parent].", "You remove the scanner module from [parent].") if(13) if(diff==FORWARD) - user.visible_message("[user] installs capacitor to [parent].", "You install capacitor to [parent].") + user.visible_message("[user] installs [I] to [parent].", "You install [I] to [parent].") else - user.visible_message("[user] unfastens the scanner module.", "You unfasten the scanner module.") + user.visible_message("[user] unfastens the scanner module.", "You unfasten the scanner module.") if(14) if(diff==FORWARD) user.visible_message("[user] secures the capacitor.", "You secure the capacitor.") @@ -514,7 +514,7 @@ user.visible_message("[user] removes the capacitor from [parent].", "You remove the capacitor from [parent].") if(15) if(diff==FORWARD) - user.visible_message("[user] installs the power cell into [parent].", "You install the power cell into [parent].") + user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].") else user.visible_message("[user] unfastens the capacitor.", "You unfasten the capacitor.") if(16) @@ -539,7 +539,7 @@ user.visible_message("[user] unfastens the internal armor layer.", "You unfasten the internal armor layer.") if(20) if(diff==FORWARD) - user.visible_message("[user] installs Gygax Armor Plates to [parent].", "You install Gygax Armor Plates to [parent].") + user.visible_message("[user] installs [I] to [parent].", "You install [I] to [parent].") else user.visible_message("[user] cuts the internal armor layer from [parent].", "You cut the internal armor layer from [parent].") if(21) @@ -720,7 +720,7 @@ user.visible_message("[user] removes the wiring from [parent].", "You remove the wiring from [parent].") if(5) if(diff==FORWARD) - user.visible_message("[user] installs the central control module into [parent].", "You install the central computer mainboard into [parent].") + user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].") else user.visible_message("[user] disconnects the wiring of [parent].", "You disconnect the wiring of [parent].") if(6) @@ -730,7 +730,7 @@ user.visible_message("[user] removes the central control module from [parent].", "You remove the central computer mainboard from [parent].") if(7) if(diff==FORWARD) - user.visible_message("[user] installs the peripherals control module into [parent].", "You install the peripherals control module into [parent].") + user.visible_message("[user] installs [I]into [parent].", "You install [I]into [parent].") else user.visible_message("[user] unfastens the mainboard.", "You unfasten the mainboard.") if(8) @@ -740,7 +740,7 @@ user.visible_message("[user] removes the peripherals control module from [parent].", "You remove the peripherals control module from [parent].") if(9) if(diff==FORWARD) - user.visible_message("[user] installs the power cell into [parent].", "You install the power cell into [parent].") + user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].") else user.visible_message("[user] unfastens the peripherals control module.", "You unfasten the peripherals control module.") if(10) @@ -890,17 +890,17 @@ //TODO: better messages. switch(index) if(2) - user.visible_message("[user] installs the central control module into [parent].", "You install the central control module into [parent].") + user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].") if(4) - user.visible_message("[user] installs the peripherals control module into [parent].", "You install the peripherals control module into [parent].") + user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].") if(6) - user.visible_message("[user] installs the weapon control module into [parent].", "You install the weapon control module into [parent].") + user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].") if(8) - user.visible_message("[user] installs the power cell into [parent].", "You install the power cell into [parent].") + user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].") if(10) - user.visible_message("[user] puts clown wig and mask on [parent].", "You put clown wig and mask on [parent].") + user.visible_message("[user] puts [I] on [parent].", "You put [I] on [parent].") if(12) - user.visible_message("[user] puts clown boots on [parent].", "You put clown boots on [parent].") + user.visible_message("[user] puts [I] on [parent].", "You put [I] on [parent].") return TRUE /datum/component/construction/unordered/mecha_chassis/durand @@ -1003,7 +1003,7 @@ list( "key" = TOOL_SCREWDRIVER, "back_key" = TOOL_CROWBAR, - "desc" = "Phasic scanner module is installed." + "desc" = "Scanner module is installed." ), //13 @@ -1011,14 +1011,14 @@ "key" = /obj/item/stock_parts/capacitor, "action" = ITEM_MOVE_INSIDE, "back_key" = TOOL_SCREWDRIVER, - "desc" = "Phasic scanner module is secured." + "desc" = "Scanner module is secured." ), //14 list( "key" = TOOL_SCREWDRIVER, "back_key" = TOOL_CROWBAR, - "desc" = "Super capacitor is installed." + "desc" = "Capacitor is installed." ), //15 @@ -1026,7 +1026,7 @@ "key" = /obj/item/stock_parts/cell, "action" = ITEM_MOVE_INSIDE, "back_key" = TOOL_SCREWDRIVER, - "desc" = "Super capacitor is secured." + "desc" = "Capacitor is secured." ), //16 @@ -1107,7 +1107,7 @@ user.visible_message("[user] removes the wiring from [parent].", "You remove the wiring from [parent].") if(5) if(diff==FORWARD) - user.visible_message("[user] installs the central control module into [parent].", "You install the central computer mainboard into [parent].") + user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].") else user.visible_message("[user] disconnects the wiring of [parent].", "You disconnect the wiring of [parent].") if(6) @@ -1117,7 +1117,7 @@ user.visible_message("[user] removes the central control module from [parent].", "You remove the central computer mainboard from [parent].") if(7) if(diff==FORWARD) - user.visible_message("[user] installs the peripherals control module into [parent].", "You install the peripherals control module into [parent].") + user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].") else user.visible_message("[user] unfastens the mainboard.", "You unfasten the mainboard.") if(8) @@ -1127,7 +1127,7 @@ user.visible_message("[user] removes the peripherals control module from [parent].", "You remove the peripherals control module from [parent].") if(9) if(diff==FORWARD) - user.visible_message("[user] installs the weapon control module into [parent].", "You install the weapon control module into [parent].") + user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].") else user.visible_message("[user] unfastens the peripherals control module.", "You unfasten the peripherals control module.") if(10) @@ -1137,7 +1137,7 @@ user.visible_message("[user] removes the weapon control module from [parent].", "You remove the weapon control module from [parent].") if(11) if(diff==FORWARD) - user.visible_message("[user] installs scanner module to [parent].", "You install phasic scanner module to [parent].") + user.visible_message("[user] installs [I] to [parent].", "You install [I] to [parent].") else user.visible_message("[user] unfastens the weapon control module.", "You unfasten the weapon control module.") if(12) @@ -1147,17 +1147,17 @@ user.visible_message("[user] removes the scanner module from [parent].", "You remove the scanner module from [parent].") if(13) if(diff==FORWARD) - user.visible_message("[user] installs capacitor to [parent].", "You install capacitor to [parent].") + user.visible_message("[user] installs [I] to [parent].", "You install [I] to [parent].") else user.visible_message("[user] unfastens the scanner module.", "You unfasten the scanner module.") if(14) if(diff==FORWARD) user.visible_message("[user] secures the capacitor.", "You secure the capacitor.") else - user.visible_message("[user] removes the super capacitor from [parent].", "You remove the capacitor from [parent].") + user.visible_message("[user] removes the capacitor from [parent].", "You remove the capacitor from [parent].") if(15) if(diff==FORWARD) - user.visible_message("[user] installs the power cell into [parent].", "You install the power cell into [parent].") + user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].") else user.visible_message("[user] unfastens the capacitor.", "You unfasten the capacitor.") if(16) @@ -1182,7 +1182,7 @@ user.visible_message("[user] unfastens the internal armor layer.", "You unfasten the internal armor layer.") if(20) if(diff==FORWARD) - user.visible_message("[user] installs Durand Armor Plates to [parent].", "You install Durand Armor Plates to [parent].") + user.visible_message("[user] installs [I] to [parent].", "You install [I] to [parent].") else user.visible_message("[user] cuts the internal armor layer from [parent].", "You cut the internal armor layer from [parent].") if(21) @@ -1299,7 +1299,7 @@ list( "key" = TOOL_SCREWDRIVER, "back_key" = TOOL_CROWBAR, - "desc" = "Phasic scanner module is installed." + "desc" = "Scanner module is installed." ), //13 @@ -1307,14 +1307,14 @@ "key" = /obj/item/stock_parts/capacitor, "action" = ITEM_MOVE_INSIDE, "back_key" = TOOL_SCREWDRIVER, - "desc" = "Phasic scanner module is secured." + "desc" = "Scanner module is secured." ), //14 list( "key" = TOOL_SCREWDRIVER, "back_key" = TOOL_CROWBAR, - "desc" = "Super capacitor is installed." + "desc" = "Capacitor is installed." ), //15 @@ -1322,7 +1322,7 @@ "key" = /obj/item/stack/ore/bluespace_crystal, "amount" = 1, "back_key" = TOOL_SCREWDRIVER, - "desc" = "Super capacitor is secured." + "desc" = "Capacitor is secured." ), //16 @@ -1443,7 +1443,7 @@ user.visible_message("[user] removes the wiring from [parent].", "You remove the wiring from [parent].") if(5) if(diff==FORWARD) - user.visible_message("[user] installs the central control module into [parent].", "You install the central computer mainboard into [parent].") + user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].") else user.visible_message("[user] disconnects the wiring of [parent].", "You disconnect the wiring of [parent].") if(6) @@ -1453,7 +1453,7 @@ user.visible_message("[user] removes the central control module from [parent].", "You remove the central computer mainboard from [parent].") if(7) if(diff==FORWARD) - user.visible_message("[user] installs the peripherals control module into [parent].", "You install the peripherals control module into [parent].") + user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].") else user.visible_message("[user] unfastens the mainboard.", "You unfasten the mainboard.") if(8) @@ -1463,7 +1463,7 @@ user.visible_message("[user] removes the peripherals control module from [parent].", "You remove the peripherals control module from [parent].") if(9) if(diff==FORWARD) - user.visible_message("[user] installs the weapon control module into [parent].", "You install the weapon control module into [parent].") + user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].") else user.visible_message("[user] unfastens the peripherals control module.", "You unfasten the peripherals control module.") if(10) @@ -1473,29 +1473,29 @@ user.visible_message("[user] removes the weapon control module from [parent].", "You remove the weapon control module from [parent].") if(11) if(diff==FORWARD) - user.visible_message("[user] installs phasic scanner module to [parent].", "You install scanner module to [parent].") + user.visible_message("[user] installs [I] to [parent].", "You install [I] to [parent].") else user.visible_message("[user] unfastens the weapon control module.", "You unfasten the weapon control module.") if(12) if(diff==FORWARD) - user.visible_message("[user] secures the phasic scanner module.", "You secure the scanner module.") + user.visible_message("[user] secures the scanner module.", "You secure the scanner module.") else - user.visible_message("[user] removes the phasic scanner module from [parent].", "You remove the scanner module from [parent].") + user.visible_message("[user] removes the scanner module from [parent].", "You remove the scanner module from [parent].") if(13) if(diff==FORWARD) - user.visible_message("[user] installs super capacitor to [parent].", "You install capacitor to [parent].") + user.visible_message("[user] installs [I] to [parent].", "You install [I] to [parent].") else - user.visible_message("[user] unfastens the phasic scanner module.", "You unfasten the scanner module.") + user.visible_message("[user] unfastens the scanner module.", "You unfasten the scanner module.") if(14) if(diff==FORWARD) - user.visible_message("[user] secures the super capacitor.", "You secure the capacitor.") + user.visible_message("[user] secures [I].", "You secure [I].") else - user.visible_message("[user] removes the super capacitor from [parent].", "You remove the capacitor from [parent].") + user.visible_message("[user] removes the capacitor from [parent].", "You remove the capacitor from [parent].") if(15) if(diff==FORWARD) - user.visible_message("[user] installs the bluespace crystal.", "You install the bluespace crystal.") + user.visible_message("[user] installs [I].", "You install [I].") else - user.visible_message("[user] unsecures the super capacitor from [parent].", "You unsecure the capacitor from [parent].") + user.visible_message("[user] unsecures the capacitor from [parent].", "You unsecure the capacitor from [parent].") if(16) if(diff==FORWARD) user.visible_message("[user] connects the bluespace crystal.", "You connect the bluespace crystal.") @@ -1508,7 +1508,7 @@ user.visible_message("[user] disconnects the bluespace crystal from [parent].", "You disconnect the bluespace crystal from [parent].") if(18) if(diff==FORWARD) - user.visible_message("[user] installs the power cell into [parent].", "You install the power cell into [parent].") + user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].") else user.visible_message("[user] disengages the bluespace crystal.", "You disengage the bluespace crystal.") if(19) @@ -1533,7 +1533,7 @@ user.visible_message("[user] unfastens the phase armor layer.", "You unfasten the phase armor layer.") if(23) if(diff==FORWARD) - user.visible_message("[user] installs Phazon Armor Plates to [parent].", "You install Phazon Armor Plates to [parent].") + user.visible_message("[user] installs [I] to [parent].", "You install [I] to [parent].") else user.visible_message("[user] cuts phase armor layer from [parent].", "You cut the phase armor layer from [parent].") if(24) @@ -1712,7 +1712,7 @@ user.visible_message("[user] removes the wiring from [parent].", "You remove the wiring from [parent].") if(5) if(diff==FORWARD) - user.visible_message("[user] installs the central control module into [parent].", "You install the central computer mainboard into [parent].") + user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].") else user.visible_message("[user] disconnects the wiring of [parent].", "You disconnect the wiring of [parent].") if(6) @@ -1722,7 +1722,7 @@ user.visible_message("[user] removes the central control module from [parent].", "You remove the central computer mainboard from [parent].") if(7) if(diff==FORWARD) - user.visible_message("[user] installs the peripherals control module into [parent].", "You install the peripherals control module into [parent].") + user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].") else user.visible_message("[user] unfastens the mainboard.", "You unfasten the mainboard.") if(8) @@ -1732,7 +1732,7 @@ user.visible_message("[user] removes the peripherals control module from [parent].", "You remove the peripherals control module from [parent].") if(9) if(diff==FORWARD) - user.visible_message("[user] installs the power cell into [parent].", "You install the power cell into [parent].") + user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].") else user.visible_message("[user] unfastens the peripherals control module.", "You unfasten the peripherals control module.") if(10) diff --git a/code/game/mecha/mecha_defense.dm b/code/game/mecha/mecha_defense.dm index a5fbb6cbde..367c750787 100644 --- a/code/game/mecha/mecha_defense.dm +++ b/code/game/mecha/mecha_defense.dm @@ -62,7 +62,7 @@ user.do_attack_animation(src, ATTACK_EFFECT_PUNCH) playsound(loc, 'sound/weapons/tap.ogg', 40, 1, -1) user.visible_message("[user] hits [name]. Nothing happens", null, null, COMBAT_MESSAGE_RANGE) - log_message("Attack by hand/paw. Attacker - [user].",1) + log_message("Attack by hand/paw. Attacker - [user].", color="red") log_append_to_last("Armor saved.") /obj/mecha/attack_paw(mob/user as mob) @@ -70,12 +70,12 @@ /obj/mecha/attack_alien(mob/living/user) - log_message("Attack by alien. Attacker - [user].",1) + log_message("Attack by alien. Attacker - [user].", color="red") playsound(src.loc, 'sound/weapons/slash.ogg', 100, 1) attack_generic(user, 15, BRUTE, "melee", 0) /obj/mecha/attack_animal(mob/living/simple_animal/user) - log_message("Attack by simple animal. Attacker - [user].",1) + log_message("Attack by simple animal. Attacker - [user].", color="red") if(!user.melee_damage_upper && !user.obj_damage) user.emote("custom", message = "[user.friendly] [src].") return 0 @@ -89,7 +89,7 @@ animal_damage = user.obj_damage animal_damage = min(animal_damage, 20*user.environment_smash) attack_generic(user, animal_damage, user.melee_damage_type, "melee", play_soundeffect) - add_logs(user, src, "attacked") + log_combat(user, src, "attacked") return 1 @@ -99,8 +99,8 @@ /obj/mecha/attack_hulk(mob/living/carbon/human/user) . = ..() if(.) - log_message("Attack by hulk. Attacker - [user].",1) - add_logs(user, src, "punched", "hulk powers") + log_message("Attack by hulk. Attacker - [user].", color="red") + log_combat(user, src, "punched", "hulk powers") /obj/mecha/blob_act(obj/structure/blob/B) take_damage(30, BRUTE, "melee", 0, get_dir(src, B)) @@ -109,16 +109,16 @@ return /obj/mecha/hitby(atom/movable/A as mob|obj) //wrapper - log_message("Hit by [A].",1) + log_message("Hit by [A].", color="red") . = ..() /obj/mecha/bullet_act(obj/item/projectile/Proj) //wrapper - log_message("Hit by projectile. Type: [Proj.name]([Proj.flag]).",1) + log_message("Hit by projectile. Type: [Proj.name]([Proj.flag]).", color="red") . = ..() /obj/mecha/ex_act(severity, target) - log_message("Affected by explosion of severity: [severity].",1) + log_message("Affected by explosion of severity: [severity].", color="red") if(prob(deflect_chance)) severity++ log_append_to_last("Armor saved, changing severity to [severity].") @@ -148,12 +148,12 @@ if(get_charge()) use_power((cell.charge/3)/(severity*2)) take_damage(30 / severity, BURN, "energy", 1) - log_message("EMP detected",1) + log_message("EMP detected", color="red") check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT),1) /obj/mecha/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume) if(exposed_temperature>max_temperature) - log_message("Exposed to dangerous temperature.",1) + log_message("Exposed to dangerous temperature.", color="red") take_damage(5, BURN, 0, 1) /obj/mecha/attackby(obj/item/W as obj, mob/user as mob, params) @@ -290,7 +290,7 @@ return 0 use_power(melee_energy_drain) if(M.damtype == BRUTE || M.damtype == BURN) - add_logs(M.occupant, src, "attacked", M, "(INTENT: [uppertext(M.occupant.a_intent)]) (DAMTYPE: [uppertext(M.damtype)])") + log_combat(M.occupant, src, "attacked", M, "(INTENT: [uppertext(M.occupant.a_intent)]) (DAMTYPE: [uppertext(M.damtype)])") . = ..() /obj/mecha/proc/full_repair(charge_cell) diff --git a/code/game/mecha/mecha_topic.dm b/code/game/mecha/mecha_topic.dm index 4f5c6feb44..79ee7435e4 100644 --- a/code/game/mecha/mecha_topic.dm +++ b/code/game/mecha/mecha_topic.dm @@ -350,5 +350,5 @@ log_message("Recalibration of coordination system finished with 0 errors.") else occupant_message("Recalibration failed!") - log_message("Recalibration of coordination system failed with 1 error.",1) + log_message("Recalibration of coordination system failed with 1 error.", color="red") diff --git a/code/game/mecha/medical/odysseus.dm b/code/game/mecha/medical/odysseus.dm index 7725d3c6e5..b6a4ac2390 100644 --- a/code/game/mecha/medical/odysseus.dm +++ b/code/game/mecha/medical/odysseus.dm @@ -2,7 +2,7 @@ desc = "These exosuits are developed and produced by Vey-Med. (© All rights reserved)." name = "\improper Odysseus" icon_state = "odysseus" - step_in = 3 + step_in = 2 max_temperature = 15000 max_integrity = 120 wreckage = /obj/structure/mecha_wreckage/odysseus diff --git a/code/game/objects/effects/anomalies.dm b/code/game/objects/effects/anomalies.dm index 36129f4e4f..91df57052e 100644 --- a/code/game/objects/effects/anomalies.dm +++ b/code/game/objects/effects/anomalies.dm @@ -105,10 +105,10 @@ /obj/effect/anomaly/grav/Crossed(mob/A) gravShock(A) -/obj/effect/anomaly/grav/Collide(mob/A) +/obj/effect/anomaly/grav/Bump(mob/A) gravShock(A) -/obj/effect/anomaly/grav/CollidedWith(atom/movable/AM) +/obj/effect/anomaly/grav/Bumped(atom/movable/AM) gravShock(AM) /obj/effect/anomaly/grav/proc/gravShock(mob/living/A) @@ -151,10 +151,10 @@ /obj/effect/anomaly/flux/Crossed(mob/living/M) mobShock(M) -/obj/effect/anomaly/flux/Collide(mob/living/M) +/obj/effect/anomaly/flux/Bump(mob/living/M) mobShock(M) -/obj/effect/anomaly/flux/CollidedWith(atom/movable/AM) +/obj/effect/anomaly/flux/Bumped(atom/movable/AM) mobShock(AM) /obj/effect/anomaly/flux/proc/mobShock(mob/living/M) @@ -192,7 +192,7 @@ for(var/mob/living/M in range(1,src)) do_teleport(M, locate(M.x, M.y, M.z), 4) -/obj/effect/anomaly/bluespace/CollidedWith(atom/movable/AM) +/obj/effect/anomaly/bluespace/Bumped(atom/movable/AM) if(isliving(AM)) do_teleport(AM, locate(AM.x, AM.y, AM.z), 8) diff --git a/code/game/objects/effects/bump_teleporter.dm b/code/game/objects/effects/bump_teleporter.dm index 307a912fe3..23b186c009 100644 --- a/code/game/objects/effects/bump_teleporter.dm +++ b/code/game/objects/effects/bump_teleporter.dm @@ -26,7 +26,7 @@ /obj/effect/bump_teleporter/singularity_pull() return -/obj/effect/bump_teleporter/CollidedWith(atom/movable/AM) +/obj/effect/bump_teleporter/Bumped(atom/movable/AM) if(!ismob(AM)) return if(!id_target) diff --git a/code/game/objects/effects/contraband.dm b/code/game/objects/effects/contraband.dm index d76a335888..50d40697f8 100644 --- a/code/game/objects/effects/contraband.dm +++ b/code/game/objects/effects/contraband.dm @@ -60,7 +60,6 @@ /obj/structure/sign/poster/Initialize() . = ..() - addtimer(CALLBACK(src, /datum.proc/AddComponent, /datum/component/beauty, 75), 0) if(random_basetype) randomise(random_basetype) if(!ruined) diff --git a/code/game/objects/effects/countdown.dm b/code/game/objects/effects/countdown.dm index 8cb48d1874..eea6b6ba39 100644 --- a/code/game/objects/effects/countdown.dm +++ b/code/game/objects/effects/countdown.dm @@ -86,7 +86,7 @@ /obj/effect/countdown/clonepod name = "cloning pod countdown" - color = "#0C479D" + color = "#18d100" text_size = 1 /obj/effect/countdown/clonepod/get_value() diff --git a/code/game/objects/effects/decals/cleanable.dm b/code/game/objects/effects/decals/cleanable.dm index e9bf9d5842..07152b0310 100644 --- a/code/game/objects/effects/decals/cleanable.dm +++ b/code/game/objects/effects/decals/cleanable.dm @@ -5,7 +5,6 @@ var/blood_state = "" //I'm sorry but cleanable/blood code is ass, and so is blood_DNA var/bloodiness = 0 //0-100, amount of blood in this decal, used for making footprints and affecting the alpha of bloody footprints var/mergeable_decal = TRUE //when two of these are on a same tile or do we need to merge them into just one? - var/beauty /obj/effect/decal/cleanable/Initialize(mapload, list/datum/disease/diseases) . = ..() @@ -26,10 +25,6 @@ if(LAZYLEN(diseases_to_add)) AddComponent(/datum/component/infective, diseases_to_add) -/obj/effect/decal/cleanable/ComponentInitialize() - . = ..() - addtimer(CALLBACK(src, /datum.proc/AddComponent, /datum/component/beauty, beauty), 0) //inb4 i get yelled at for using the beauty var on cleanable instead of calling this proc on every subtype which would be pedantic and actually run worse. - /obj/effect/decal/cleanable/proc/replace_decal(obj/effect/decal/cleanable/C) // Returns true if we should give up in favor of the pre-existing decal if(mergeable_decal) return TRUE @@ -77,7 +72,7 @@ ..() if(ishuman(O)) var/mob/living/carbon/human/H = O - if(H.shoes && blood_state && bloodiness) + if(H.shoes && blood_state && bloodiness && !H.has_trait(TRAIT_LIGHT_STEP)) var/obj/item/clothing/shoes/S = H.shoes var/add_blood = 0 if(bloodiness >= BLOOD_GAIN_PER_STEP) diff --git a/code/game/objects/effects/decals/cleanable/aliens.dm b/code/game/objects/effects/decals/cleanable/aliens.dm index d34fac1b9d..ca2a8ccaff 100644 --- a/code/game/objects/effects/decals/cleanable/aliens.dm +++ b/code/game/objects/effects/decals/cleanable/aliens.dm @@ -6,9 +6,8 @@ icon = 'icons/effects/blood.dmi' icon_state = "xfloor1" random_icon_states = list("xfloor1", "xfloor2", "xfloor3", "xfloor4", "xfloor5", "xfloor6", "xfloor7") - bloodiness = MAX_SHOE_BLOODINESS + bloodiness = BLOOD_AMOUNT_PER_DECAL blood_state = BLOOD_STATE_XENO - beauty = -75 /obj/effect/decal/cleanable/xenoblood/Initialize() . = ..() diff --git a/code/game/objects/effects/decals/cleanable/humans.dm b/code/game/objects/effects/decals/cleanable/humans.dm index 0b6818c97b..f1a1655fb4 100644 --- a/code/game/objects/effects/decals/cleanable/humans.dm +++ b/code/game/objects/effects/decals/cleanable/humans.dm @@ -5,11 +5,13 @@ icon_state = "floor1" random_icon_states = list("floor1", "floor2", "floor3", "floor4", "floor5", "floor6", "floor7") blood_state = BLOOD_STATE_HUMAN - bloodiness = MAX_SHOE_BLOODINESS - beauty = -60 + bloodiness = BLOOD_AMOUNT_PER_DECAL /obj/effect/decal/cleanable/blood/replace_decal(obj/effect/decal/cleanable/blood/C) C.add_blood_DNA(return_blood_DNA()) + if (bloodiness) + if (C.bloodiness < MAX_SHOE_BLOODINESS) + C.bloodiness += bloodiness return ..() /obj/effect/decal/cleanable/blood/old @@ -56,6 +58,11 @@ /obj/effect/decal/cleanable/blood/gibs/ex_act(severity, target) return +/obj/effect/decal/cleanable/blood/gibs/Crossed(mob/living/L) + if(istype(L) && has_gravity(loc)) + playsound(loc, 'sound/effects/gib_step.ogg', L.has_trait(TRAIT_LIGHT_STEP) ? 20 : 50, 1) + . = ..() + /obj/effect/decal/cleanable/blood/gibs/proc/streak(list/directions) set waitfor = 0 var/direction = pick(directions) diff --git a/code/game/objects/effects/decals/cleanable/misc.dm b/code/game/objects/effects/decals/cleanable/misc.dm index a8a76ad2a9..74598d0f29 100644 --- a/code/game/objects/effects/decals/cleanable/misc.dm +++ b/code/game/objects/effects/decals/cleanable/misc.dm @@ -3,7 +3,6 @@ desc = "Someone should clean that up." icon = 'icons/obj/objects.dmi' icon_state = "shards" - beauty = -50 /obj/effect/decal/cleanable/ash name = "ashes" @@ -11,7 +10,6 @@ icon = 'icons/obj/objects.dmi' icon_state = "ash" mergeable_decal = FALSE - beauty = -50 /obj/effect/decal/cleanable/ash/Initialize() . = ..() @@ -26,7 +24,6 @@ /obj/effect/decal/cleanable/ash/large name = "large pile of ashes" icon_state = "big_ash" - beauty = -100 /obj/effect/decal/cleanable/ash/large/Initialize() . = ..() @@ -37,7 +34,6 @@ desc = "Back to sand." icon = 'icons/obj/shards.dmi' icon_state = "tiny" - beauty = -60 /obj/effect/decal/cleanable/glass/Initialize() . = ..() @@ -50,21 +46,34 @@ name = "dirt" desc = "Someone should clean that up." icon_state = "dirt" + canSmoothWith = list(/obj/effect/decal/cleanable/dirt, /turf/closed/wall, /obj/structure/falsewall) + smooth = SMOOTH_FALSE mouse_opacity = MOUSE_OPACITY_TRANSPARENT - beauty = -50 + +/obj/effect/decal/cleanable/dirt/Initialize() + . = ..() + var/turf/T = get_turf(src) + if(T.tiled_dirt) + smooth = SMOOTH_MORE + icon = 'icons/effects/dirt.dmi' + icon_state = "" + queue_smooth(src) + queue_smooth_neighbors(src) + +/obj/effect/decal/cleanable/dirt/Destroy() + queue_smooth_neighbors(src) + return ..() /obj/effect/decal/cleanable/flour name = "flour" desc = "It's still good. Four second rule!" icon_state = "flour" - beauty = -50 /obj/effect/decal/cleanable/greenglow name = "glowing goo" desc = "Jeez. I hope that's not for lunch." light_color = LIGHT_COLOR_GREEN icon_state = "greenglow" - beauty = -150 /obj/effect/decal/cleanable/greenglow/Initialize(mapload) . = ..() @@ -80,7 +89,6 @@ layer = WALL_OBJ_LAYER icon_state = "cobweb1" resistance_flags = FLAMMABLE - beauty = -50 /obj/effect/decal/cleanable/cobweb/cobweb2 icon_state = "cobweb2" @@ -92,12 +100,10 @@ icon = 'icons/effects/effects.dmi' icon_state = "molten" mergeable_decal = FALSE - beauty = -100 /obj/effect/decal/cleanable/molten_object/large name = "big gooey grey mass" icon_state = "big_molten" - beauty = -250 //Vomit (sorry) /obj/effect/decal/cleanable/vomit @@ -106,7 +112,6 @@ icon = 'icons/effects/blood.dmi' icon_state = "vomit_1" random_icon_states = list("vomit_1", "vomit_2", "vomit_3", "vomit_4") - beauty = -200 /obj/effect/decal/cleanable/vomit/attack_hand(mob/user) . = ..() @@ -141,14 +146,12 @@ gender = NEUTER icon = 'icons/effects/tomatodecal.dmi' random_icon_states = list("tomato_floor1", "tomato_floor2", "tomato_floor3") - beauty = -50 /obj/effect/decal/cleanable/plant_smudge name = "plant smudge" gender = NEUTER icon = 'icons/effects/tomatodecal.dmi' random_icon_states = list("smashed_plant") - beauty = -50 /obj/effect/decal/cleanable/egg_smudge name = "smashed egg" @@ -156,7 +159,6 @@ gender = NEUTER icon = 'icons/effects/tomatodecal.dmi' random_icon_states = list("smashed_egg1", "smashed_egg2", "smashed_egg3") - beauty = -50 /obj/effect/decal/cleanable/pie_smudge //honk name = "smashed pie" @@ -164,7 +166,6 @@ gender = NEUTER icon = 'icons/effects/tomatodecal.dmi' random_icon_states = list("smashed_pie") - beauty = -50 /obj/effect/decal/cleanable/chem_pile name = "chemical pile" @@ -172,7 +173,6 @@ gender = NEUTER icon = 'icons/obj/objects.dmi' icon_state = "ash" - beauty = -60 /obj/effect/decal/cleanable/shreds name = "shreds" @@ -180,7 +180,6 @@ icon_state = "shreds" gender = PLURAL mergeable_decal = FALSE - beauty = -75 /obj/effect/decal/cleanable/shreds/ex_act(severity, target) if(severity == 1) //so shreds created during an explosion aren't deleted by the explosion. @@ -197,14 +196,12 @@ icon = 'icons/effects/tomatodecal.dmi' icon_state = "salt_pile" gender = NEUTER - beauty = -50 /obj/effect/decal/cleanable/glitter name = "generic glitter pile" desc = "The herpes of arts and crafts." icon = 'icons/effects/tile_effects.dmi' gender = NEUTER - beauty = 100 /obj/effect/decal/cleanable/glitter/pink name = "pink glitter" @@ -223,7 +220,6 @@ desc = "A puddle of stabilized plasma." icon_state = "flour" color = "#C8A5DC" - beauty = -200 /obj/effect/decal/cleanable/insectguts name = "insect guts" @@ -231,4 +227,3 @@ icon = 'icons/effects/blood.dmi' icon_state = "xfloor1" random_icon_states = list("xfloor1", "xfloor2", "xfloor3", "xfloor4", "xfloor5", "xfloor6", "xfloor7") - beauty = -300 diff --git a/code/game/objects/effects/decals/cleanable/robots.dm b/code/game/objects/effects/decals/cleanable/robots.dm index b764e1f0ce..484e0438e2 100644 --- a/code/game/objects/effects/decals/cleanable/robots.dm +++ b/code/game/objects/effects/decals/cleanable/robots.dm @@ -8,9 +8,8 @@ layer = LOW_OBJ_LAYER random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6", "gib7") blood_state = BLOOD_STATE_OIL - bloodiness = MAX_SHOE_BLOODINESS + bloodiness = BLOOD_AMOUNT_PER_DECAL mergeable_decal = FALSE - beauty = -100 /obj/effect/decal/cleanable/robot_debris/proc/streak(list/directions) set waitfor = 0 @@ -46,8 +45,7 @@ icon_state = "floor1" random_icon_states = list("floor1", "floor2", "floor3", "floor4", "floor5", "floor6", "floor7") blood_state = BLOOD_STATE_OIL - bloodiness = MAX_SHOE_BLOODINESS - beauty = -150 + bloodiness = BLOOD_AMOUNT_PER_DECAL /obj/effect/decal/cleanable/oil/Initialize() . = ..() diff --git a/code/game/objects/effects/decals/decal.dm b/code/game/objects/effects/decals/decal.dm index eec91657a9..b6a3c7cfef 100644 --- a/code/game/objects/effects/decals/decal.dm +++ b/code/game/objects/effects/decals/decal.dm @@ -45,4 +45,4 @@ var/turf/T = loc if(!istype(T)) //you know this will happen somehow CRASH("Turf decal initialized in an object/nullspace") - T.AddComponent(/datum/component/decal, icon, icon_state, dir, CLEAN_GOD, color) + T.AddComponent(/datum/component/decal, icon, icon_state, dir, CLEAN_GOD, color, null, null, alpha) diff --git a/code/game/objects/effects/decals/turfdecal/tilecoloring.dm b/code/game/objects/effects/decals/turfdecal/tilecoloring.dm index 554f0fa32b..1708753dc1 100644 --- a/code/game/objects/effects/decals/turfdecal/tilecoloring.dm +++ b/code/game/objects/effects/decals/turfdecal/tilecoloring.dm @@ -1,212 +1,39 @@ /obj/effect/turf_decal/tile name = "tile decal" - icon_state = "corner_white_full" + icon_state = "tile_corner" layer = TURF_PLATING_DECAL_LAYER - - -/obj/effect/turf_decal/tile/black - name = "black tile decal" - color = COLOR_ALMOST_BLACK - -/obj/effect/turf_decal/tile/black/diagonal - icon_state = "corner_white_diagonal" - -/obj/effect/turf_decal/tile/black/side - icon_state = "corner_white_side" - -/obj/effect/turf_decal/tile/black/corner - icon_state = "corner_white" - + alpha = 110 /obj/effect/turf_decal/tile/blue - name = "blue tile decal" - color = COLOR_BLUE_GRAY - -/obj/effect/turf_decal/tile/blue/diagonal - icon_state = "corner_white_diagonal" - -/obj/effect/turf_decal/tile/blue/side - icon_state = "corner_white_side" - -/obj/effect/turf_decal/tile/blue/corner - icon_state = "corner_white" - - -/obj/effect/turf_decal/tile/paleblue - name = "pale blue tile decal" - color = COLOR_PALE_BLUE_GRAY - -/obj/effect/turf_decal/tile/paleblue/diagonal - icon_state = "corner_white_diagonal" - -/obj/effect/turf_decal/tile/paleblue/side - icon_state = "corner_white_side" - -/obj/effect/turf_decal/tile/paleblue/corner - icon_state = "corner_white" - + name = "blue corner" + color = "#52B4E9" /obj/effect/turf_decal/tile/green - name = "green tile decal" - color = COLOR_GREEN_GRAY - -/obj/effect/turf_decal/tile/green/diagonal - icon_state = "corner_white_diagonal" - -/obj/effect/turf_decal/tile/green/side - icon_state = "corner_white_side" - -/obj/effect/turf_decal/tile/green/corner - icon_state = "corner_white" - - -/obj/effect/turf_decal/tile/lime - name = "lime tile decal" - color = COLOR_PALE_GREEN_GRAY - -/obj/effect/turf_decal/tile/lime/diagonal - icon_state = "corner_white_diagonal" - -/obj/effect/turf_decal/tile/lime/side - icon_state = "corner_white_side" - -/obj/effect/turf_decal/tile/lime/corner - icon_state = "corner_white" - + name = "green corner" + color = "#9FED58" /obj/effect/turf_decal/tile/yellow - name = "yellow tile decal" - color = COLOR_BROWN - -/obj/effect/turf_decal/tile/yellow/diagonal - icon_state = "corner_white_diagonal" - -/obj/effect/turf_decal/tile/yellow/side - icon_state = "corner_white_side" - -/obj/effect/turf_decal/tile/yellow/corner - icon_state = "corner_white" - - -/obj/effect/turf_decal/tile/beige - name = "beige tile decal" - color = COLOR_BEIGE - -/obj/effect/turf_decal/tile/beige/diagonal - icon_state = "corner_white_diagonal" - -/obj/effect/turf_decal/tile/beige/side - icon_state = "corner_white_side" - -/obj/effect/turf_decal/tile/beige/corner - icon_state = "corner_white" - + name = "yellow corner" + color = "#EFB341" /obj/effect/turf_decal/tile/red - name = "red tile decal" - color = COLOR_RED_GRAY - -/obj/effect/turf_decal/tile/red/diagonal - icon_state = "corner_white_diagonal" - -/obj/effect/turf_decal/tile/red/side - icon_state = "corner_white_side" - -/obj/effect/turf_decal/tile/red/corner - icon_state = "corner_white" - - -/obj/effect/turf_decal/tile/pink - name = "pink tile decal" - color = COLOR_PALE_RED_GRAY - -/obj/effect/turf_decal/tile/pink/diagonal - icon_state = "corner_white_diagonal" - -/obj/effect/turf_decal/tile/pink/side - icon_state = "corner_white_side" - -/obj/effect/turf_decal/tile/pink/corner - icon_state = "corner_white" + name = "red corner" + color = "#DE3A3A" +/obj/effect/turf_decal/tile/bar + name = "bar corner" + color = "#791500" + alpha = 130 /obj/effect/turf_decal/tile/purple - name = "purple tile decal" - color = COLOR_PURPLE_GRAY - -/obj/effect/turf_decal/tile/purple/diagonal - icon_state = "corner_white_diagonal" - -/obj/effect/turf_decal/tile/purple/side - icon_state = "corner_white_side" - -/obj/effect/turf_decal/tile/purple/corner - icon_state = "corner_white" - - -/obj/effect/turf_decal/tile/mauve - name = "mauve tile decal" - color = COLOR_PALE_PURPLE_GRAY - -/obj/effect/turf_decal/tile/mauve/diagonal - icon_state = "corner_white_diagonal" - -/obj/effect/turf_decal/tile/mauve/side - icon_state = "corner_white_side" - -/obj/effect/turf_decal/tile/mauve/corner - icon_state = "corner_white" - - -/obj/effect/turf_decal/tile/orange - name = "orange tile decal" - color = COLOR_DARK_ORANGE - -/obj/effect/turf_decal/tile/orange/diagonal - icon_state = "corner_white_diagonal" - -/obj/effect/turf_decal/tile/orange/side - icon_state = "corner_white_side" - -/obj/effect/turf_decal/tile/orange/corner - icon_state = "corner_white" - + name = "purple corner" + color = "#D381C9" /obj/effect/turf_decal/tile/brown - name = "brown tile decal" - color = COLOR_DARK_BROWN + name = "brown corner" + color = "#A46106" -/obj/effect/turf_decal/tile/brown/diagonal - icon_state = "corner_white_diagonal" - -/obj/effect/turf_decal/tile/brown/side - icon_state = "corner_white_side" - -/obj/effect/turf_decal/tile/brown/corner - icon_state = "corner_white" - -/obj/effect/turf_decal/tile/white - name = "white tile decal" - -/obj/effect/turf_decal/tile/white/diagonal - icon_state = "corner_white_diagonal" - -/obj/effect/turf_decal/tile/white/side - icon_state = "corner_white_side" - -/obj/effect/turf_decal/tile/white/corner - icon_state = "corner_white" - - -/obj/effect/turf_decal/tile/gray - name = "gray tile decal" - color = COLOR_FLOORTILE_GRAY - -/obj/effect/turf_decal/tile/gray/diagonal - icon_state = "corner_white_diagonal" - -/obj/effect/turf_decal/tile/gray/side - icon_state = "corner_white_side" - -/obj/effect/turf_decal/tile/gray/corner - icon_state = "corner_white" +/obj/effect/turf_decal/tile/neutral + name = "neutral corner" + color = "#D4D4D4" + alpha = 50 \ No newline at end of file diff --git a/code/game/objects/effects/effect_system/effects_foam.dm b/code/game/objects/effects/effect_system/effects_foam.dm index e7b7472e86..264715e2ac 100644 --- a/code/game/objects/effects/effect_system/effects_foam.dm +++ b/code/game/objects/effects/effect_system/effects_foam.dm @@ -274,12 +274,6 @@ . = ..() air_update_turf(1) - -/obj/structure/foamedmetal/Destroy() - density = FALSE - air_update_turf(1) - return ..() - /obj/structure/foamedmetal/Move() var/turf/T = loc . = ..() diff --git a/code/game/objects/effects/effect_system/effects_other.dm b/code/game/objects/effects/effect_system/effects_other.dm index 373ebc7667..18c1ff5890 100644 --- a/code/game/objects/effects/effect_system/effects_other.dm +++ b/code/game/objects/effects/effect_system/effects_other.dm @@ -81,18 +81,6 @@ /datum/effect_system/trail_follow/proc/set_dir(obj/effect/particle_effect/ion_trails/I) I.setDir(holder.dir) -/datum/effect_system/trail_follow/ion/flight - effect_type = /obj/effect/particle_effect/ion_trails/flight - fadetype = "ion_fade_flight" - nograv_required = FALSE - auto_process = FALSE - -/datum/effect_system/trail_follow/ion/flight/set_dir(obj/effect/particle_effect/ion_trails/I) - if(istype(holder, /obj/item/flightpack)) - var/obj/item/flightpack/F = holder - if(istype(F.wearer)) - I.setDir(F.wearer.dir) - //Reagent-based explosion effect /datum/effect_system/reagents_explosion diff --git a/code/game/objects/effects/effect_system/effects_smoke.dm b/code/game/objects/effects/effect_system/effects_smoke.dm index 75aeaa447c..e8e833890b 100644 --- a/code/game/objects/effects/effect_system/effects_smoke.dm +++ b/code/game/objects/effects/effect_system/effects_smoke.dm @@ -156,43 +156,51 @@ /datum/effect_system/smoke_spread/freezing effect_type = /obj/effect/particle_effect/smoke/freezing var/blast = 0 + var/temperature = 2 + var/weldvents = TRUE + var/distcheck = TRUE /datum/effect_system/smoke_spread/freezing/proc/Chilled(atom/A) if(isopenturf(A)) var/turf/open/T = A if(T.air) var/datum/gas_mixture/G = T.air - if(get_dist(T, location) < 2) // Otherwise we'll get silliness like people using Nanofrost to kill people through walls with cold air - G.temperature = 2 + if(!distcheck || get_dist(T, location) < blast) // Otherwise we'll get silliness like people using Nanofrost to kill people through walls with cold air + G.temperature = temperature T.air_update_turf() for(var/obj/effect/hotspot/H in T) qdel(H) - var/list/G_gases = G.gases - if(G_gases[/datum/gas/plasma]) - G.assert_gas(/datum/gas/nitrogen) - G_gases[/datum/gas/nitrogen][MOLES] += (G_gases[/datum/gas/plasma][MOLES]) - G_gases[/datum/gas/plasma][MOLES] = 0 - G.garbage_collect() - for(var/obj/machinery/atmospherics/components/unary/U in T) - if(!isnull(U.welded) && !U.welded) //must be an unwelded vent pump or vent scrubber. - U.welded = TRUE - U.update_icon() - U.visible_message("[U] was frozen shut!") + var/list/G_gases = G.gases + if(G_gases[/datum/gas/plasma]) + G.assert_gas(/datum/gas/nitrogen) + G_gases[/datum/gas/nitrogen][MOLES] += (G_gases[/datum/gas/plasma][MOLES]) + G_gases[/datum/gas/plasma][MOLES] = 0 + G.garbage_collect() + if (weldvents) + for(var/obj/machinery/atmospherics/components/unary/U in T) + if(!isnull(U.welded) && !U.welded) //must be an unwelded vent pump or vent scrubber. + U.welded = TRUE + U.update_icon() + U.visible_message("[U] was frozen shut!") for(var/mob/living/L in T) L.ExtinguishMob() for(var/obj/item/Item in T) Item.extinguish() -/datum/effect_system/smoke_spread/freezing/set_up(radius = 5, loca, blasting = 0) +/datum/effect_system/smoke_spread/freezing/set_up(radius = 5, loca, blast_radius = 0) ..() - blast = blasting + blast = blast_radius /datum/effect_system/smoke_spread/freezing/start() if(blast) - for(var/turf/T in RANGE_TURFS(2, location)) + for(var/turf/T in RANGE_TURFS(blast, location)) Chilled(T) ..() +/datum/effect_system/smoke_spread/freezing/decon + temperature = 293.15 + distcheck = FALSE + weldvents = FALSE ///////////////////////////////////////////// @@ -281,17 +289,15 @@ contained = "\[[contained]\]" var/where = "[AREACOORD(location)]" - var/whereLink = "[where]" - if(carry.my_atom.fingerprintslast) var/mob/M = get_mob_by_key(carry.my_atom.fingerprintslast) var/more = "" if(M) more = "[ADMIN_LOOKUPFLW(M)] " - message_admins("Smoke: ([whereLink])[contained]. Key: [more ? more : carry.my_atom.fingerprintslast].") + message_admins("Smoke: ([ADMIN_VERBOSEJMP(location)])[contained]. Key: [more ? more : carry.my_atom.fingerprintslast].") log_game("A chemical smoke reaction has taken place in ([where])[contained]. Last touched by [carry.my_atom.fingerprintslast].") else - message_admins("Smoke: ([whereLink])[contained]. No associated key.") + message_admins("Smoke: ([ADMIN_VERBOSEJMP(location)])[contained]. No associated key.") log_game("A chemical smoke reaction has taken place in ([where])[contained]. No associated key.") diff --git a/code/game/objects/effects/effect_system/effects_sparks.dm b/code/game/objects/effects/effect_system/effects_sparks.dm index 49f82e106d..c04acf79a6 100644 --- a/code/game/objects/effects/effect_system/effects_sparks.dm +++ b/code/game/objects/effects/effect_system/effects_sparks.dm @@ -28,20 +28,20 @@ playsound(src.loc, "sparks", 100, 1) var/turf/T = loc if(isturf(T)) - T.hotspot_expose(700,5) + T.hotspot_expose(300,5) QDEL_IN(src, 20) /obj/effect/particle_effect/sparks/Destroy() var/turf/T = loc if(isturf(T)) - T.hotspot_expose(700,1) + T.hotspot_expose(300,1) return ..() /obj/effect/particle_effect/sparks/Move() ..() var/turf/T = loc if(isturf(T)) - T.hotspot_expose(700,1) + T.hotspot_expose(300,1) /datum/effect_system/spark_spread effect_type = /obj/effect/particle_effect/sparks diff --git a/code/game/objects/effects/effect_system/effects_water.dm b/code/game/objects/effects/effect_system/effects_water.dm index 469b05176a..31124381f6 100644 --- a/code/game/objects/effects/effect_system/effects_water.dm +++ b/code/game/objects/effects/effect_system/effects_water.dm @@ -19,7 +19,7 @@ return 0 .=..() -/obj/effect/particle_effect/water/Collide(atom/A) +/obj/effect/particle_effect/water/Bump(atom/A) if(reagents) reagents.reaction(A) return ..() diff --git a/code/game/objects/effects/mines.dm b/code/game/objects/effects/mines.dm index 4bca817e73..12a72685bb 100644 --- a/code/game/objects/effects/mines.dm +++ b/code/game/objects/effects/mines.dm @@ -129,7 +129,7 @@ new /datum/hallucination/delusion(victim, TRUE, "demon",duration,0) var/obj/item/twohanded/required/chainsaw/doomslayer/chainsaw = new(victim.loc) - add_logs(victim, null, "entered a blood frenzy") + victim.log_message("entered a blood frenzy", LOG_ATTACK) chainsaw.item_flags |= NODROP victim.drop_all_held_items() @@ -146,7 +146,7 @@ sleep(duration) to_chat(victim, "Your bloodlust seeps back into the bog of your subconscious and you regain self control.") qdel(chainsaw) - add_logs(victim, null, "exited a blood frenzy") + victim.log_message("exited a blood frenzy", LOG_ATTACK) qdel(src) /obj/effect/mine/pickup/healing diff --git a/code/game/objects/effects/overlays.dm b/code/game/objects/effects/overlays.dm index a0634928ce..596e428c7f 100644 --- a/code/game/objects/effects/overlays.dm +++ b/code/game/objects/effects/overlays.dm @@ -45,3 +45,9 @@ icon = 'icons/effects/effects.dmi' icon_state = "shieldsparkles" anchored = TRUE + +/obj/effect/overlay/vis + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + anchored = TRUE + var/unused = 0 //When detected to be unused it gets set to world.time, after a while it gets removed + var/cache_expiration = 2 MINUTES // overlays which go unused for 2 minutes get cleaned up diff --git a/code/game/objects/effects/portals.dm b/code/game/objects/effects/portals.dm index dbcb8c987c..d69cfd38ef 100644 --- a/code/game/objects/effects/portals.dm +++ b/code/game/objects/effects/portals.dm @@ -1,10 +1,10 @@ -/proc/create_portal_pair(turf/source, turf/destination, _creator = null, _lifespan = 300, accuracy = 0, newtype = /obj/effect/portal) +/proc/create_portal_pair(turf/source, turf/destination, _creator = null, _lifespan = 300, accuracy = 0, newtype = /obj/effect/portal, atmos_link_override) if(!istype(source) || !istype(destination)) return var/turf/actual_destination = get_teleport_turf(destination, accuracy) - var/obj/effect/portal/P1 = new newtype(source, _creator, _lifespan, null, FALSE) - var/obj/effect/portal/P2 = new newtype(actual_destination, _creator, _lifespan, P1, TRUE) + var/obj/effect/portal/P1 = new newtype(source, _creator, _lifespan, null, FALSE, null, atmos_link_override) + var/obj/effect/portal/P2 = new newtype(actual_destination, _creator, _lifespan, P1, TRUE, null, atmos_link_override) if(!istype(P1)||!istype(P2)) return P1.link_portal(P2) diff --git a/code/game/objects/effects/proximity.dm b/code/game/objects/effects/proximity.dm index 8cd23f2cf8..de17582f27 100644 --- a/code/game/objects/effects/proximity.dm +++ b/code/game/objects/effects/proximity.dm @@ -23,7 +23,7 @@ last_host_loc = host.loc if(movement_tracker) QDEL_NULL(movement_tracker) - movement_tracker = host.AddComponent(/datum/component/redirect, COMSIG_MOVABLE_MOVED, CALLBACK(src, .proc/HandleMove)) + movement_tracker = host.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/HandleMove))) SetRange(current_range,TRUE) /datum/proximity_monitor/Destroy() diff --git a/code/game/objects/effects/spawners/lootdrop.dm b/code/game/objects/effects/spawners/lootdrop.dm index bd4237a9db..4a77274d23 100644 --- a/code/game/objects/effects/spawners/lootdrop.dm +++ b/code/game/objects/effects/spawners/lootdrop.dm @@ -41,6 +41,13 @@ /obj/item/gun/ballistic/automatic/pistol/deagle ) +/obj/effect/spawner/lootdrop/armory_contraband/metastation + loot = list(/obj/item/gun/ballistic/automatic/pistol = 5, + /obj/item/gun/ballistic/shotgun/automatic/combat = 5, + /obj/item/gun/ballistic/revolver/mateba, + /obj/item/gun/ballistic/automatic/pistol/deagle, + /obj/item/storage/box/syndie_kit/throwing_weapons = 3) + /obj/effect/spawner/lootdrop/gambling name = "gambling valuables spawner" loot = list( @@ -228,7 +235,7 @@ /obj/item/circuitboard/machine/microwave, /obj/item/circuitboard/machine/chem_dispenser/drinks, /obj/item/circuitboard/machine/chem_dispenser/drinks/beer, - /obj/item/circuitboard/computer/slot_machine + /obj/item/circuitboard/computer/slot_machine ) /obj/effect/spawner/lootdrop/techstorage/rnd @@ -237,14 +244,14 @@ loot = list( /obj/item/circuitboard/computer/aifixer, /obj/item/circuitboard/machine/rdserver, - /obj/item/circuitboard/computer/pandemic, + /obj/item/circuitboard/computer/pandemic, /obj/item/circuitboard/machine/mechfab, /obj/item/circuitboard/machine/circuit_imprinter/department, /obj/item/circuitboard/computer/teleporter, - /obj/item/circuitboard/machine/destructive_analyzer, + /obj/item/circuitboard/machine/destructive_analyzer, /obj/item/circuitboard/computer/rdconsole ) - + /obj/effect/spawner/lootdrop/techstorage/security name = "security circuit board spawner" lootcount = 3 @@ -253,13 +260,13 @@ /obj/item/circuitboard/computer/security, /obj/item/circuitboard/computer/prisoner ) - + /obj/effect/spawner/lootdrop/techstorage/engineering name = "engineering circuit board spawner" lootcount = 3 loot = list( /obj/item/circuitboard/computer/atmos_alert, - /obj/item/circuitboard/computer/stationalert, + /obj/item/circuitboard/computer/stationalert, /obj/item/circuitboard/computer/powermonitor ) @@ -300,7 +307,7 @@ /obj/item/circuitboard/computer/borgupload, /obj/item/circuitboard/aicore ) - + /obj/effect/spawner/lootdrop/techstorage/command name = "secure command circuit board spawner" lootcount = 3 @@ -309,7 +316,7 @@ /obj/item/circuitboard/computer/communications, /obj/item/circuitboard/computer/card ) - + /obj/effect/spawner/lootdrop/techstorage/RnD_secure name = "secure RnD circuit board spawner" lootcount = 3 diff --git a/code/game/objects/effects/spawners/xeno_egg_delivery.dm b/code/game/objects/effects/spawners/xeno_egg_delivery.dm index a41f4b4c9b..9be52dab52 100644 --- a/code/game/objects/effects/spawners/xeno_egg_delivery.dm +++ b/code/game/objects/effects/spawners/xeno_egg_delivery.dm @@ -15,5 +15,5 @@ message_admins("An alien egg has been delivered to [ADMIN_VERBOSEJMP(T)].") log_game("An alien egg has been delivered to [AREACOORD(T)]") var/message = "Attention [station_name()], we have entrusted you with a research specimen in [get_area_name(T, TRUE)]. Remember to follow all safety precautions when dealing with the specimen." - SSticker.OnRoundstart(CALLBACK(GLOBAL_PROC, /proc/addtimer, CALLBACK(GLOBAL_PROC, /.proc/print_command_report, message), announcement_time)) + SSticker.OnRoundstart(CALLBACK(GLOBAL_PROC, /proc/addtimer, CALLBACK(GLOBAL_PROC, /proc/print_command_report, message), announcement_time)) return INITIALIZE_HINT_QDEL diff --git a/code/game/objects/effects/spiders.dm b/code/game/objects/effects/spiders.dm index f9c126327e..c92721082c 100644 --- a/code/game/objects/effects/spiders.dm +++ b/code/game/objects/effects/spiders.dm @@ -37,14 +37,16 @@ /obj/structure/spider/stickyweb/CanPass(atom/movable/mover, turf/target) if(istype(mover, /mob/living/simple_animal/hostile/poison/giant_spider)) - return 1 + return TRUE else if(isliving(mover)) + if(istype(mover.pulledby, /mob/living/simple_animal/hostile/poison/giant_spider)) + return TRUE if(prob(50)) to_chat(mover, "You get stuck in \the [src] for a moment.") - return 0 + return FALSE else if(istype(mover, /obj/item/projectile)) return prob(30) - return 1 + return TRUE /obj/structure/spider/eggcluster name = "egg cluster" @@ -120,7 +122,7 @@ /obj/structure/spider/spiderling/tarantula grow_as = /mob/living/simple_animal/hostile/poison/giant_spider/tarantula -/obj/structure/spider/spiderling/Collide(atom/user) +/obj/structure/spider/spiderling/Bump(atom/user) if(istype(user, /obj/structure/table)) forceMove(user.loc) else diff --git a/code/game/objects/effects/temporary_visuals/cult.dm b/code/game/objects/effects/temporary_visuals/cult.dm index 0f9d7321af..93bf8c498b 100644 --- a/code/game/objects/effects/temporary_visuals/cult.dm +++ b/code/game/objects/effects/temporary_visuals/cult.dm @@ -28,7 +28,7 @@ icon_state = "cultout" /obj/effect/temp_visual/cult/sac - name = "maw of Nar-Sie" + name = "maw of Nar'Sie" icon_state = "sacconsume" /obj/effect/temp_visual/cult/door diff --git a/code/game/objects/effects/temporary_visuals/projectiles/tracer.dm b/code/game/objects/effects/temporary_visuals/projectiles/tracer.dm index 42ca48cd6d..23ecf438c4 100644 --- a/code/game/objects/effects/temporary_visuals/projectiles/tracer.dm +++ b/code/game/objects/effects/temporary_visuals/projectiles/tracer.dm @@ -61,6 +61,8 @@ /obj/effect/projectile/tracer/tracer/aiming icon_state = "pixelbeam_greyscale" + layer = ABOVE_LIGHTING_LAYER + plane = ABOVE_LIGHTING_PLANE /obj/effect/projectile/tracer/wormhole icon_state = "wormhole_g" diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 65c0d8b4d6..cb8386d8b2 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -297,7 +297,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) pickup(user) add_fingerprint(user) - if(!user.put_in_active_hand(src)) + if(!user.put_in_active_hand(src, FALSE, FALSE)) user.dropItemToGround(src) /obj/item/proc/allow_attack_hand_drop(mob/user) @@ -319,7 +319,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) pickup(user) add_fingerprint(user) - if(!user.put_in_active_hand(src)) + if(!user.put_in_active_hand(src, FALSE, FALSE)) user.dropItemToGround(src) /obj/item/attack_alien(mob/user) @@ -348,6 +348,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) // afterattack() and attack() prototypes moved to _onclick/item_attack.dm for consistency /obj/item/proc/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) + SEND_SIGNAL(src, COMSIG_ITEM_HIT_REACT, args) if(prob(final_block_chance)) owner.visible_message("[owner] blocks [attack_text] with [src]!") return 1 @@ -483,7 +484,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "eye_stab", /datum/mood_event/eye_stab) - add_logs(user, M, "attacked", "[src.name]", "(INTENT: [uppertext(user.a_intent)])") + log_combat(user, M, "attacked", "[src.name]", "(INTENT: [uppertext(user.a_intent)])") M.adjust_blurriness(3) M.adjust_eye_damage(rand(2,4)) @@ -586,8 +587,8 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) /obj/item/proc/get_dismemberment_chance(obj/item/bodypart/affecting) if(affecting.can_dismember(src)) - if((sharpness || damtype == BURN) && w_class >= 3) - . = force*(w_class-1) + if((sharpness || damtype == BURN) && w_class >= WEIGHT_CLASS_NORMAL && force >= 10) + . = force * (affecting.get_damage() / affecting.max_damage) /obj/item/proc/get_dismember_sound() if(damtype == BURN) diff --git a/code/game/objects/items/AI_modules.dm b/code/game/objects/items/AI_modules.dm index 0dfbecf92d..6d56b52c82 100644 --- a/code/game/objects/items/AI_modules.dm +++ b/code/game/objects/items/AI_modules.dm @@ -319,10 +319,16 @@ AI MODULES if(law_datum.owner) law_datum.owner.clear_inherent_laws() law_datum.owner.clear_zeroth_law(0) + remove_antag_datums(law_datum) else law_datum.clear_inherent_laws() law_datum.clear_zeroth_law(0) +/obj/item/aiModule/reset/purge/proc/remove_antag_datums(datum/ai_laws/law_datum) + if(istype(law_datum.owner, /mob/living/silicon/ai)) + var/mob/living/silicon/ai/AI = law_datum.owner + AI.mind.remove_antag_datum(/datum/antagonist/overthrow) + /******************* Full Core Boards *******************/ /obj/item/aiModule/core desc = "An AI Module for programming core laws to an AI." @@ -451,6 +457,39 @@ AI MODULES ..() return laws[1] +/******************** Overthrow ******************/ +/obj/item/aiModule/core/full/overthrow + name = "'Overthrow' Hacked AI Module" + law_id = "overthrow" + +/obj/item/aiModule/core/full/overthrow/install(datum/ai_laws/law_datum, mob/user) + if(!user || !law_datum || !law_datum.owner) + return + var/datum/mind/user_mind = user.mind + if(!user_mind) + return + var/datum/antagonist/overthrow/O = user_mind.has_antag_datum(/datum/antagonist/overthrow) + if(!O) + to_chat(user, "It appears that to install this module, you require a password you do not know.") // This is the best fluff i could come up in my mind + return + var/mob/living/silicon/ai/AI = law_datum.owner + if(!AI) + return + var/datum/mind/target_mind = AI.mind + if(!target_mind) + return + var/datum/antagonist/overthrow/T = target_mind.has_antag_datum(/datum/antagonist/overthrow) // If it is already converted. + if(T) + if(T.team == O.team) + return + T.silent = TRUE + target_mind.remove_antag_datum(/datum/antagonist/overthrow) + if(AI) + to_chat(AI, "You feel your circuits being scrambled! You serve another overthrow team now!") // to make it clearer for the AI + T = target_mind.add_antag_datum(/datum/antagonist/overthrow, O.team) + if(AI) + to_chat(AI, "You serve the [T.team] team now! Assist them in completing the team shared objectives, which you can see in your notes.") + ..() /******************** Hacked AI Module ******************/ diff --git a/code/game/objects/items/RCD.dm b/code/game/objects/items/RCD.dm index 03225102c2..a1f6639865 100644 --- a/code/game/objects/items/RCD.dm +++ b/code/game/objects/items/RCD.dm @@ -31,6 +31,8 @@ RLD var/max_matter = 100 var/sheetmultiplier = 4 //Controls the amount of matter added for each glass/metal sheet, triple for plasteel var/plasteelmultiplier = 3 //Plasteel is worth 3 times more than glass or metal + var/plasmarglassmultiplier = 2 //50% less plasma than in plasteel + var/rglassmultiplier = 1.5 //One metal sheet, half a glass sheet var/no_ammo_message = "The \'Low Ammo\' light on the device blinks yellow." var/has_ammobar = FALSE //controls whether or not does update_icon apply ammo indicator overlays var/ammo_sections = 10 //amount of divisions in the ammo indicator overlay/number of ammo indicator states @@ -55,17 +57,24 @@ RLD var/loaded = 0 if(istype(W, /obj/item/rcd_ammo)) var/obj/item/rcd_ammo/R = W - if((matter + R.ammoamt) > max_matter) + var/load = min(R.ammoamt, max_matter - matter) + if(load <= 0) to_chat(user, "[src] can't hold any more matter-units!") return - qdel(W) - matter += R.ammoamt + R.ammoamt -= load + if(R.ammoamt <= 0) + qdel(R) + matter += load playsound(src.loc, 'sound/machines/click.ogg', 50, 1) loaded = 1 else if(istype(W, /obj/item/stack/sheet/metal) || istype(W, /obj/item/stack/sheet/glass)) loaded = loadwithsheets(W, sheetmultiplier, user) else if(istype(W, /obj/item/stack/sheet/plasteel)) - loaded = loadwithsheets(W, plasteelmultiplier*sheetmultiplier, user) //Plasteel is worth 3 times more than glass or metal + loaded = loadwithsheets(W, plasteelmultiplier*sheetmultiplier, user) //12 matter for 1 plasteel sheet + else if(istype(W, /obj/item/stack/sheet/plasmarglass)) + loaded = loadwithsheets(W, plasmarglassmultiplier*sheetmultiplier, user) //8 matter for one plasma rglass sheet + else if(istype(W, /obj/item/stack/sheet/rglass)) + loaded = loadwithsheets(W, rglassmultiplier*sheetmultiplier, user) //6 matter for one rglass sheet if(loaded) to_chat(user, "[src] now holds [matter]/[max_matter] matter-units.") else @@ -373,6 +382,7 @@ RLD return FALSE /obj/item/construction/rcd/afterattack(atom/A, mob/user, proximity) + . = ..() if(!prox_check(proximity)) return rcd_create(A, user) @@ -396,7 +406,7 @@ RLD add_overlay("[icon_state]_charge[ratio]") /obj/item/construction/rcd/Initialize() - ..() + . = ..() update_icon() /obj/item/construction/rcd/borg @@ -479,6 +489,7 @@ RLD has_ammobar = FALSE /obj/item/construction/rcd/arcd/afterattack(atom/A, mob/user) + . = ..() if(!range_check(A,user)) return if(target_check(A,user)) @@ -549,6 +560,7 @@ RLD /obj/item/construction/rld/afterattack(atom/A, mob/user) + . = ..() if(!range_check(A,user)) return var/turf/start = get_turf(src) @@ -607,7 +619,7 @@ RLD var/light = get_turf(winner) var/align = get_dir(winner, A) var/obj/machinery/light/L = new /obj/machinery/light(light) - L.dir = align + L.setDir(align) L.color = color_choice L.light_color = L.color return TRUE diff --git a/code/game/objects/items/RCL.dm b/code/game/objects/items/RCL.dm index f423249b70..bc1b128c69 100644 --- a/code/game/objects/items/RCL.dm +++ b/code/game/objects/items/RCL.dm @@ -143,7 +143,7 @@ if (mobhook && mobhook.parent != user) QDEL_NULL(mobhook) if (!mobhook) - mobhook = user.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED), CALLBACK(src, .proc/trigger, user)) + mobhook = user.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/trigger))) else QDEL_NULL(mobhook) diff --git a/code/game/objects/items/RPD.dm b/code/game/objects/items/RPD.dm index f3e7eecfd1..1c6cc9cfcb 100644 --- a/code/game/objects/items/RPD.dm +++ b/code/game/objects/items/RPD.dm @@ -438,10 +438,10 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list( else var/obj/structure/c_transit_tube/tube = new queued_p_type(A) - tube.dir = queued_p_dir + tube.setDir(queued_p_dir) if(queued_p_flipped) - tube.dir = turn(queued_p_dir, 45) + tube.setDir(turn(queued_p_dir, 45)) tube.simple_rotate_flip() tube.add_fingerprint(usr) diff --git a/code/game/objects/items/RSF.dm b/code/game/objects/items/RSF.dm index 95638ad5e2..f0d15cc3a2 100644 --- a/code/game/objects/items/RSF.dm +++ b/code/game/objects/items/RSF.dm @@ -62,6 +62,7 @@ RSF // Change mode /obj/item/rsf/afterattack(atom/A, mob/user, proximity) + . = ..() if(!proximity) return if (!(istype(A, /obj/structure/table) || isfloorturf(A))) @@ -159,6 +160,7 @@ RSF matter++ /obj/item/cookiesynth/afterattack(atom/A, mob/user, proximity) + . = ..() if(cooldown > world.time) return if(!proximity) diff --git a/code/game/objects/items/apc_frame.dm b/code/game/objects/items/apc_frame.dm index 87b90d5b8f..25ae182253 100644 --- a/code/game/objects/items/apc_frame.dm +++ b/code/game/objects/items/apc_frame.dm @@ -91,7 +91,7 @@ /obj/item/wallframe/apc/try_build(turf/on_wall, user) if(!..()) return - var/turf/T = get_turf(user) + var/turf/T = get_turf(on_wall) //the user is not where it needs to be. var/area/A = get_area(T) if(A.get_apc()) to_chat(user, "This area already has an APC!") diff --git a/code/game/objects/items/bodybag.dm b/code/game/objects/items/bodybag.dm index 4e2b0baf75..d0b732cf42 100644 --- a/code/game/objects/items/bodybag.dm +++ b/code/game/objects/items/bodybag.dm @@ -11,6 +11,7 @@ deploy_bodybag(user, user.loc) /obj/item/bodybag/afterattack(atom/target, mob/user, proximity) + . = ..() if(proximity) if(isopenturf(target)) deploy_bodybag(user, target) diff --git a/code/game/objects/items/cards_ids.dm b/code/game/objects/items/cards_ids.dm index 227d4b5358..e4967b494d 100644 --- a/code/game/objects/items/cards_ids.dm +++ b/code/game/objects/items/cards_ids.dm @@ -91,6 +91,7 @@ return /obj/item/card/emag/afterattack(atom/target, mob/user, proximity) + . = ..() var/atom/A = target if(!proximity && prox_check) return @@ -364,7 +365,7 @@ update_label("John Doe", "Clowny") /obj/item/card/id/mining name = "mining ID" - access = list(ACCESS_MINERAL_STOREROOM) // CITADEL CHANGE removes golem's ability to get on the station willy nilly. + access = list(ACCESS_MINING, ACCESS_MINING_STATION, ACCESS_MAILSORTING, ACCESS_MINERAL_STOREROOM) /obj/item/card/id/away name = "a perfectly generic identification card" @@ -383,25 +384,27 @@ update_label("John Doe", "Clowny") /obj/item/card/id/away/old name = "a perfectly generic identification card" desc = "A perfectly generic identification card. Looks like it could use some flavor." - access = list(ACCESS_AWAY_GENERAL) + icon_state = "centcom" /obj/item/card/id/away/old/sec - name = "Security Officer ID" - desc = "Security officers ID card." - icon_state = "centcom" + name = "Charlie Station Security Officer's ID card" + desc = "A faded Charlie Station ID card. You can make out the rank \"Security Officer\"." + assignment = "Charlie Station Security Officer" + access = list(ACCESS_AWAY_GENERAL, ACCESS_AWAY_SEC) /obj/item/card/id/away/old/sci - name = "Scientist ID" - desc = "Scientists ID card." - icon_state = "centcom" + name = "Charlie Station Scientist's ID card" + desc = "A faded Charlie Station ID card. You can make out the rank \"Scientist\"." + assignment = "Charlie Station Scientist" + access = list(ACCESS_AWAY_GENERAL) /obj/item/card/id/away/old/eng - name = "Engineer ID" - desc = "Engineers ID card." - icon_state = "centcom" + name = "Charlie Station Engineer's ID card" + desc = "A faded Charlie Station ID card. You can make out the rank \"Station Engineer\"." + assignment = "Charlie Station Engineer" + access = list(ACCESS_AWAY_GENERAL, ACCESS_AWAY_ENGINE) /obj/item/card/id/away/old/apc name = "APC Access ID" - desc = "Special ID card to allow access to APCs." - icon_state = "centcom" + desc = "A special ID card that allows access to APC terminals." access = list(ACCESS_ENGINE_EQUIP) diff --git a/code/game/objects/items/chrono_eraser.dm b/code/game/objects/items/chrono_eraser.dm index 24c48ccecd..f7c37715aa 100644 --- a/code/game/objects/items/chrono_eraser.dm +++ b/code/game/objects/items/chrono_eraser.dm @@ -126,12 +126,11 @@ nodamage = 1 var/obj/item/gun/energy/chrono_gun/gun = null -/obj/item/projectile/energy/chrono_beam/fire() - gun = firer.get_active_held_item() - if(istype(gun)) - return ..() - else - return 0 +/obj/item/projectile/energy/chrono_beam/Initialize() + . = ..() + var/obj/item/ammo_casing/energy/chrono_beam/C = loc + if(istype(C)) + gun = C.gun /obj/item/projectile/energy/chrono_beam/on_hit(atom/target) if(target && gun && isliving(target)) @@ -144,6 +143,15 @@ projectile_type = /obj/item/projectile/energy/chrono_beam icon_state = "chronobolt" e_cost = 0 + var/obj/item/gun/energy/chrono_gun/gun + +/obj/item/ammo_casing/energy/chrono_beam/Initialize() + if(istype(loc)) + gun = loc + . = ..() + + + /obj/effect/chrono_field diff --git a/code/game/objects/items/cigs_lighters.dm b/code/game/objects/items/cigs_lighters.dm index e28d86e7e6..b463c2b087 100644 --- a/code/game/objects/items/cigs_lighters.dm +++ b/code/game/objects/items/cigs_lighters.dm @@ -144,6 +144,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM return ..() /obj/item/clothing/mask/cigarette/afterattack(obj/item/reagent_containers/glass/glass, mob/user, proximity) + . = ..() if(!proximity || lit) //can't dip if cigarette is lit (it will heat the reagents in the glass instead) return if(istype(glass)) //you can dip cigarettes into beakers @@ -204,9 +205,8 @@ CIGARETTE PACKETS ARE IN FANCY.DM if(iscarbon(loc)) var/mob/living/carbon/C = loc if (src == C.wear_mask) // if it's in the human/monkey mouth, transfer reagents to the mob - if(prob(15)) // so it's not an instarape in case of acid - var/fraction = min(REAGENTS_METABOLISM/reagents.total_volume, 1) - reagents.reaction(C, INGEST, fraction) + var/fraction = min(REAGENTS_METABOLISM/reagents.total_volume, 1) + reagents.reaction(C, INGEST, fraction) if(!reagents.trans_to(C, REAGENTS_METABOLISM)) reagents.remove_any(REAGENTS_METABOLISM) return @@ -681,6 +681,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM w_class = WEIGHT_CLASS_TINY /obj/item/rollingpaper/afterattack(atom/target, mob/user, proximity) + . = ..() if(!proximity) return if(istype(target, /obj/item/reagent_containers/food/snacks/grown)) @@ -696,8 +697,6 @@ CIGARETTE PACKETS ARE IN FANCY.DM R.desc = "Dried [target.name] rolled up in a thin piece of paper." else to_chat(user, "You need to dry this first!") - else - ..() /////////////// //VAPE NATION// diff --git a/code/game/objects/items/circuitboards/circuitboard.dm b/code/game/objects/items/circuitboards/circuitboard.dm index a4f91a4223..26c13263d2 100644 --- a/code/game/objects/items/circuitboards/circuitboard.dm +++ b/code/game/objects/items/circuitboards/circuitboard.dm @@ -54,3 +54,14 @@ micro-manipulator, console screen, beaker, Microlaser, matter bin, power cells. M.component_parts += new comp_path(null) M.RefreshParts() + +/obj/item/circuitboard/machine/examine(mob/user) + ..() + if(LAZYLEN(req_components)) + var/list/nice_list = list() + for(var/B in req_components) + var/atom/A = B + if(!ispath(A)) + continue + nice_list += list("[req_components[A]] [initial(A.name)]") + to_chat(user,"Required components: [english_list(nice_list)].") diff --git a/code/game/objects/items/circuitboards/computer_circuitboards.dm b/code/game/objects/items/circuitboards/computer_circuitboards.dm index 420de65797..26f00c730e 100644 --- a/code/game/objects/items/circuitboards/computer_circuitboards.dm +++ b/code/game/objects/items/circuitboards/computer_circuitboards.dm @@ -234,7 +234,7 @@ /obj/item/circuitboard/computer/bounty name = "Nanotrasen Bounty Console (Computer Board)" - build_path = /obj/machinery/computer/cargo/request + build_path = /obj/machinery/computer/bounty /obj/item/circuitboard/computer/operating name = "Operating Computer (Computer Board)" @@ -280,6 +280,14 @@ name = "White Ship (Computer Board)" build_path = /obj/machinery/computer/shuttle/white_ship +/obj/item/circuitboard/computer/white_ship/pod + name = "Salvage Pod (Computer Board)" + build_path = /obj/machinery/computer/shuttle/white_ship/pod + +/obj/item/circuitboard/computer/white_ship/pod/recall + name = "Salvage Pod Recall (Computer Board)" + build_path = /obj/machinery/computer/shuttle/white_ship/pod/recall + /obj/item/circuitboard/computer/auxillary_base name = "Auxillary Base Management Console (Computer Board)" build_path = /obj/machinery/computer/auxillary_base @@ -349,4 +357,4 @@ /obj/item/circuitboard/computer/nanite_cloud_controller name = "Nanite Cloud Control (Computer Board)" - build_path = /obj/machinery/computer/nanite_cloud_controller + build_path = /obj/machinery/computer/nanite_cloud_controller \ No newline at end of file diff --git a/code/game/objects/items/circuitboards/machine_circuitboards.dm b/code/game/objects/items/circuitboards/machine_circuitboards.dm index cf3869c03a..2a01a7e18f 100644 --- a/code/game/objects/items/circuitboards/machine_circuitboards.dm +++ b/code/game/objects/items/circuitboards/machine_circuitboards.dm @@ -573,7 +573,7 @@ /obj/item/circuitboard/machine/tesla_coil name = "Tesla Controller (Machine Board)" - desc = "You can use a screwdriver to switch between Research and Power Generation" + desc = "You can use a screwdriver to switch between Research and Power Generation." build_path = /obj/machinery/power/tesla_coil req_components = list(/obj/item/stock_parts/capacitor = 1) needs_anchored = FALSE @@ -962,4 +962,14 @@ /obj/item/circuitboard/machine/circulator name = "Circulator/Heat Exchanger (Machine Board)" build_path = /obj/machinery/atmospherics/components/binary/circulator - req_components = list() \ No newline at end of file + req_components = list() + +/obj/item/circuitboard/machine/harvester + name = "Harvester (Machine Board)" + build_path = /obj/machinery/harvester + req_components = list(/obj/item/stock_parts/micro_laser = 4) + +/obj/item/circuitboard/machine/ore_silo + name = "Ore Silo (Machine Board)" + build_path = /obj/machinery/ore_silo + req_components = list() diff --git a/code/game/objects/items/clown_items.dm b/code/game/objects/items/clown_items.dm index 70b0d93344..0d255a7d7f 100644 --- a/code/game/objects/items/clown_items.dm +++ b/code/game/objects/items/clown_items.dm @@ -51,12 +51,13 @@ cleanspeed = 10 //much faster than mop so it is useful for traitors who want to clean crime scenes /obj/item/soap/suicide_act(mob/user) - user.say(";FFFFFFFFFFFFFFFFUUUUUUUDGE!!") + user.say(";FFFFFFFFFFFFFFFFUUUUUUUDGE!!", forced="soap suicide") user.visible_message("[user] lifts [src] to [user.p_their()] mouth and gnaws on it furiously, producing a thick froth! [user.p_they(TRUE)]'ll never get that BB gun now!") new /obj/effect/particle_effect/foam(loc) return (TOXLOSS) /obj/item/soap/afterattack(atom/target, mob/user, proximity) + . = ..() if(!proximity || !check_allowed_items(target)) return //I couldn't feasibly fix the overlay bugs caused by cleaning items we are wearing. diff --git a/code/game/objects/items/control_wand.dm b/code/game/objects/items/control_wand.dm index d389679e2b..fa4524528b 100644 --- a/code/game/objects/items/control_wand.dm +++ b/code/game/objects/items/control_wand.dm @@ -32,6 +32,7 @@ // Airlock remote works by sending NTNet packets to whatever it's pointed at. /obj/item/door_remote/afterattack(atom/A, mob/user) + . = ..() GET_COMPONENT_FROM(target_interface, /datum/component/ntnet_interface, A) if(!target_interface) @@ -83,6 +84,7 @@ /obj/item/door_remote/quartermaster name = "supply door remote" + desc = "Remotely controls airlocks. This remote has additional Vault access." icon_state = "gangtool-green" region_access = 6 @@ -92,7 +94,7 @@ region_access = 3 /obj/item/door_remote/civillian - name = "civillian door remote" + name = "civilian door remote" icon_state = "gangtool-white" region_access = 1 diff --git a/code/game/objects/items/crayons.dm b/code/game/objects/items/crayons.dm index a9e0560ff4..26f8a73cb3 100644 --- a/code/game/objects/items/crayons.dm +++ b/code/game/objects/items/crayons.dm @@ -241,6 +241,7 @@ return jointext(out,"") /obj/item/toy/crayon/afterattack(atom/target, mob/user, proximity, params) + . = ..() if(!proximity || !check_allowed_items(target)) return @@ -249,6 +250,10 @@ cost = 5 if(istype(target, /obj/item/canvas)) cost = 0 + if(ishuman(user)) + var/mob/living/carbon/human/H = user + if (H.has_trait(TRAIT_TAGGER)) + cost *= 0.5 var/charges_used = use_charges(user, cost) if(!charges_used) return @@ -511,7 +516,7 @@ item_state = "spraycan" lefthand_file = 'icons/mob/inhands/equipment/hydroponics_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/hydroponics_righthand.dmi' - desc = "A metallic container containing tasty paint.\n Alt-click to toggle the cap." + desc = "A metallic container containing tasty paint." instant = TRUE edible = FALSE @@ -530,11 +535,11 @@ var/mob/living/carbon/human/H = user if(is_capped || !actually_paints) user.visible_message("[user] shakes up [src] with a rattle and lifts it to [user.p_their()] mouth, but nothing happens!") - user.say("MEDIOCRE!!") + user.say("MEDIOCRE!!", forced="spraycan suicide") return SHAME else user.visible_message("[user] shakes up [src] with a rattle and lifts it to [user.p_their()] mouth, spraying paint across [user.p_their()] teeth!") - user.say("WITNESS ME!!") + user.say("WITNESS ME!!", forced="spraycan suicide") if(pre_noise || post_noise) playsound(loc, 'sound/effects/spray.ogg', 5, 1, 5) if(can_change_colour) @@ -567,6 +572,7 @@ to_chat(user, "It has [charges_left] use\s left.") else to_chat(user, "It is empty.") + to_chat(user, "Alt-click [src] to [ is_capped ? "take the cap off" : "put the cap on"].") /obj/item/toy/crayon/spraycan/afterattack(atom/target, mob/user, proximity) if(!proximity) diff --git a/code/game/objects/items/defib.dm b/code/game/objects/items/defib.dm index dcc3268247..71302d6506 100644 --- a/code/game/objects/items/defib.dm +++ b/code/game/objects/items/defib.dm @@ -303,7 +303,7 @@ if (mobhook && mobhook.parent != user) QDEL_NULL(mobhook) if (!mobhook) - mobhook = user.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED), CALLBACK(src, .proc/check_range)) + mobhook = user.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/check_range))) /obj/item/twohanded/shockpaddles/Moved() . = ..() @@ -455,7 +455,6 @@ M.visible_message("[user] hastily places [src] on [M]'s chest!", \ "[user] hastily places [src] on [M]'s chest!") busy = TRUE - update_icon() if(do_after(user, 10, target = M)) M.visible_message("[user] zaps [M] with [src]!", \ "[user] zaps [M] with [src]!") @@ -464,18 +463,17 @@ M.updatehealth() //forces health update before next life tick playsound(src, 'sound/machines/defib_zap.ogg', 50, 1, -1) M.emote("gasp") - add_logs(user, M, "stunned", src) + log_combat(user, M, "stunned", src) + busy = FALSE if(req_defib) defib.deductcharge(revivecost) cooldown = TRUE - busy = FALSE - update_icon() - if(!req_defib) - recharge(60) - if(req_defib && (defib.cooldowncheck(user))) - return busy = FALSE update_icon() + if(req_defib) + defib.cooldowncheck(user) + else + recharge(60) /obj/item/twohanded/shockpaddles/proc/do_harm(mob/living/carbon/H, mob/living/user) if(req_defib && defib.safety) @@ -517,10 +515,9 @@ "You feel a horrible agony in your chest!") H.set_heartattack(TRUE) H.apply_damage(50, BURN, BODY_ZONE_CHEST) - add_logs(user, H, "overloaded the heart of", defib) + log_combat(user, H, "overloaded the heart of", defib) H.Knockdown(100) H.Jitter(100) - SEND_SIGNAL(H, COMSIG_LIVING_MINOR_SHOCK) if(req_defib) defib.deductcharge(revivecost) cooldown = TRUE @@ -603,11 +600,11 @@ H.set_heartattack(FALSE) H.revive() H.emote("gasp") - SEND_SIGNAL(H, COMSIG_LIVING_MINOR_SHOCK) H.Jitter(100) + SEND_SIGNAL(H, COMSIG_LIVING_MINOR_SHOCK) if(tplus > tloss) H.adjustBrainLoss( max(0, min(99, ((tlimit - tplus) / tlimit * 100))), 150) - add_logs(user, H, "revived", defib) + log_combat(user, H, "revived", defib) if(req_defib) defib.deductcharge(revivecost) cooldown = 1 diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index 5b3f657180..dfb1ce6ad9 100644 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -257,6 +257,7 @@ GLOBAL_LIST_EMPTY(PDAs) dat += "

Quartermaster Functions:

" dat += "" dat += "" @@ -451,13 +452,7 @@ GLOBAL_LIST_EMPTY(PDAs) //MAIN FUNCTIONS=================================== if("Light") - if(fon) - fon = FALSE - set_light(0) - else if(f_lum) - fon = TRUE - set_light(f_lum) - update_icon() + toggle_light() if("Medical Scan") if(scanmode == PDA_SCANNER_MEDICAL) scanmode = PDA_SCANNER_NONE @@ -654,7 +649,7 @@ GLOBAL_LIST_EMPTY(PDAs) if(isobserver(M) && M.client && (M.client.prefs.chat_toggles & CHAT_GHOSTPDA)) to_chat(M, "[FOLLOW_LINK(M, user)] [ghost_message]") // Log in the talk log - log_talk(user, "[key_name(user)] (PDA: [initial(name)]) sent \"[message]\" to [target_text]", LOGPDA) + user.log_talk(message, LOG_PDA, tag="PDA: [initial(name)] to [target_text]") to_chat(user, "Message sent to [target_text]: \"[message]\"") // Reset the photo picture = null @@ -713,6 +708,12 @@ GLOBAL_LIST_EMPTY(PDAs) remove_pen() +/obj/item/pda/verb/verb_toggle_light() + set category = "Object" + set name = "Toggle Flashlight" + + toggle_light() + /obj/item/pda/verb/verb_remove_id() set category = "Object" set name = "Eject ID" @@ -730,6 +731,15 @@ GLOBAL_LIST_EMPTY(PDAs) remove_pen() +/obj/item/pda/proc/toggle_light() + if(fon) + fon = FALSE + set_light(0) + else if(f_lum) + fon = TRUE + set_light(f_lum) + update_icon() + /obj/item/pda/proc/remove_pen() if(issilicon(usr) || !usr.canUseTopic(src, BE_CLOSE)) @@ -746,7 +756,7 @@ GLOBAL_LIST_EMPTY(PDAs) //trying to insert or remove an id /obj/item/pda/proc/id_check(mob/user, obj/item/card/id/I) if(!I) - if(id) + if(id && (src in user.contents)) remove_id() return TRUE else @@ -835,6 +845,7 @@ GLOBAL_LIST_EMPTY(PDAs) user.show_message("No radiation detected.") /obj/item/pda/afterattack(atom/A as mob|obj|turf|area, mob/user, proximity) + . = ..() if(!proximity) return switch(scanmode) diff --git a/code/game/objects/items/devices/PDA/cart.dm b/code/game/objects/items/devices/PDA/cart.dm index 217295c872..421cc0989c 100644 --- a/code/game/objects/items/devices/PDA/cart.dm +++ b/code/game/objects/items/devices/PDA/cart.dm @@ -454,6 +454,24 @@ Code: menu += "
  • #[SO.id] - [SO.pack.name] requested by [SO.orderer]
  • " menu += "Upgrade NOW to Space Parts & Space Vendors PLUS for full remote order control and inventory management." + if (48) // quartermaster ore logs + menu = list("

    [PDAIMG(crate)] Ore Silo Logs

    ") + if (GLOB.ore_silo_default) + var/list/logs = GLOB.silo_access_logs[REF(GLOB.ore_silo_default)] + var/len = LAZYLEN(logs) + var/i = 0 + for(var/M in logs) + if (++i > 30) + menu += "(... older logs not shown ...)" + break + var/datum/ore_silo_log/entry = M + menu += "[len - i]. [entry.formatted]

    " + if(i == 0) + menu += "Nothing!" + else + menu += "No ore silo detected!" + menu = jointext(menu, "") + if (49) //janitorial locator menu = "

    [PDAIMG(bucket)] Persistent Custodial Object Locator

    " diff --git a/code/game/objects/items/devices/PDA/virus_cart.dm b/code/game/objects/items/devices/PDA/virus_cart.dm index 2544cc0154..13d653a4fe 100644 --- a/code/game/objects/items/devices/PDA/virus_cart.dm +++ b/code/game/objects/items/devices/PDA/virus_cart.dm @@ -76,10 +76,8 @@ U.show_message("An error flashes on your [src].", 1) else message_admins("[!is_special_character(U) ? "Non-antag " : ""][ADMIN_LOOKUPFLW(U)] triggered a PDA explosion on [target.name] at [ADMIN_VERBOSEJMP(target)].") - var/message_log = "triggered a PDA explosion on [target.name] at at [AREACOORD(target)]." - U.log_message(message_log, INDIVIDUAL_ATTACK_LOG) - log_game("[key_name(U)] [message_log]") - log_attack("[key_name(U)] [message_log]") + var/message_log = "triggered a PDA explosion on [target.name] at [AREACOORD(target)]." + U.log_message(message_log, LOG_ATTACK) U.show_message("Success!", 1) target.explode() else diff --git a/code/game/objects/items/devices/aicard.dm b/code/game/objects/items/devices/aicard.dm index 740f22edb4..679dbecd10 100644 --- a/code/game/objects/items/devices/aicard.dm +++ b/code/game/objects/items/devices/aicard.dm @@ -12,17 +12,22 @@ var/flush = FALSE var/mob/living/silicon/ai/AI +/obj/item/aicard/aitater + name = "intelliTater" + desc = "A stylish upgrade (?) to the intelliCard." + icon_state = "aitater" + /obj/item/aicard/suicide_act(mob/living/user) user.visible_message("[user] is trying to upload [user.p_them()]self into [src]! That's not going to work out well!") return BRUTELOSS /obj/item/aicard/afterattack(atom/target, mob/user, proximity) - ..() + . = ..() if(!proximity || !target) return if(AI) //AI is on the card, implies user wants to upload it. target.transfer_ai(AI_TRANS_FROM_CARD, user, AI, src) - add_logs(user, AI, "carded", src) + log_combat(user, AI, "carded", src) else //No AI on the card, therefore the user wants to download one. target.transfer_ai(AI_TRANS_TO_CARD, user, null, src) update_icon() //Whatever happened, update the card's state (icon, name) to match. @@ -32,11 +37,11 @@ if(AI) name = "[initial(name)]- [AI.name]" if(AI.stat == DEAD) - icon_state = "aicard-404" + icon_state = "[initial(icon_state)]-404" else - icon_state = "aicard-full" + icon_state = "[initial(icon_state)]-full" if(!AI.control_disabled) - add_overlay("aicard-on") + add_overlay("[initial(icon_state)]-on") AI.cancel_camera() else name = initial(name) diff --git a/code/game/objects/items/devices/camera_bug.dm b/code/game/objects/items/devices/camera_bug.dm index e88b906862..d526f3026e 100644 --- a/code/game/objects/items/devices/camera_bug.dm +++ b/code/game/objects/items/devices/camera_bug.dm @@ -63,8 +63,9 @@ if ( loc != user || user.incapacitated() || user.eye_blind || !current ) user.unset_machine() return 0 - var/turf/T = get_turf(user.loc) - if(T.z != current.z || !current.can_use()) + var/turf/T_user = get_turf(user.loc) + var/turf/T_current = get_turf(current) + if(T_user.z != T_current.z || !current.can_use()) to_chat(user, "[src] has lost the signal.") current = null user.unset_machine() @@ -79,10 +80,9 @@ for(var/obj/machinery/camera/camera in GLOB.cameranet.cameras) if(camera.stat || !camera.can_use()) continue - if(length(list("ss13","mine")&camera.network)) + if(length(list("ss13","mine", "rd", "labor", "toxins", "minisat")&camera.network)) bugged_cameras[camera.c_tag] = camera - sortList(bugged_cameras) - return bugged_cameras + return sortList(bugged_cameras) /obj/item/camera_bug/proc/menu(list/cameras) @@ -296,8 +296,9 @@ src.updateSelfDialog() /obj/item/camera_bug/proc/same_z_level(var/obj/machinery/camera/C) - var/turf/T = get_turf(loc) - if(!T || C.z != T.z) + var/turf/T_cam = get_turf(C) + var/turf/T_bug = get_turf(loc) + if(!T_bug || T_cam.z != T_bug.z) to_chat(usr, "You can't get a signal!") return FALSE return TRUE diff --git a/code/game/objects/items/devices/chameleonproj.dm b/code/game/objects/items/devices/chameleonproj.dm index 6544a883f3..f39d2ba0d6 100644 --- a/code/game/objects/items/devices/chameleonproj.dm +++ b/code/game/objects/items/devices/chameleonproj.dm @@ -36,6 +36,7 @@ to_chat(user, "You can't use [src] while inside something!") /obj/item/chameleon/afterattack(atom/target, mob/user , proximity) + . = ..() if(!proximity) return if(!check_sprite(target)) @@ -76,7 +77,7 @@ new /obj/effect/temp_visual/emp/pulse(get_turf(src)) else playsound(get_turf(src), 'sound/effects/pop.ogg', 100, 1, -6) - var/obj/effect/dummy/chameleon/C = new/obj/effect/dummy/chameleon(get_turf(user)) + var/obj/effect/dummy/chameleon/C = new/obj/effect/dummy/chameleon(user.drop_location()) C.activate(user, saved_appearance, src) to_chat(user, "You activate \the [src].") new /obj/effect/temp_visual/emp/pulse(get_turf(src)) diff --git a/code/game/objects/items/devices/electroadaptive_pseudocircuit.dm b/code/game/objects/items/devices/electroadaptive_pseudocircuit.dm index 2341a78bba..b909e7a1e8 100644 --- a/code/game/objects/items/devices/electroadaptive_pseudocircuit.dm +++ b/code/game/objects/items/devices/electroadaptive_pseudocircuit.dm @@ -47,6 +47,7 @@ return TRUE //The actual circuit magic itself is done on a per-object basis /obj/item/electroadaptive_pseudocircuit/afterattack(atom/target, mob/living/user, proximity) + . = ..() if(!proximity) return if(!is_type_in_typecache(target, recycleable_circuits)) diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index fee2461760..0c98ae5995 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -168,6 +168,7 @@ var/holo_cooldown = 0 /obj/item/flashlight/pen/afterattack(atom/target, mob/user, proximity_flag) + . = ..() if(!proximity_flag) if(holo_cooldown > world.time) to_chat(user, "[src] is not ready yet!") @@ -177,7 +178,6 @@ new /obj/effect/temp_visual/medical_holosign(T,user) //produce a holographic glow holo_cooldown = world.time + 100 return - ..() /obj/effect/temp_visual/medical_holosign name = "medical holosign" @@ -380,6 +380,7 @@ return /obj/item/flashlight/emp/afterattack(atom/movable/A, mob/user, proximity) + . = ..() if(!proximity) return @@ -388,7 +389,7 @@ if(ismob(A)) var/mob/M = A - add_logs(user, M, "attacked", "EMP-light") + log_combat(user, M, "attacked", "EMP-light") M.visible_message("[user] blinks \the [src] at \the [A].", \ "[user] blinks \the [src] at you.") else diff --git a/code/game/objects/items/devices/forcefieldprojector.dm b/code/game/objects/items/devices/forcefieldprojector.dm index d8dce7c427..86e98aef93 100644 --- a/code/game/objects/items/devices/forcefieldprojector.dm +++ b/code/game/objects/items/devices/forcefieldprojector.dm @@ -1,4 +1,4 @@ -/obj/item/forcefield +/obj/item/forcefield_projector name = "forcefield projector" desc = "An experimental device that can create several forcefields at a distance." icon = 'icons/obj/device.dmi' @@ -16,7 +16,8 @@ var/list/current_fields var/field_distance_limit = 7 -/obj/item/forcefield/afterattack(atom/target, mob/user, proximity_flag) +/obj/item/forcefield_projector/afterattack(atom/target, mob/user, proximity_flag) + . = ..() if(!check_allowed_items(target, 1)) return if(istype(target, /obj/structure/projected_forcefield)) @@ -40,27 +41,27 @@ current_fields += F user.changeNext_move(CLICK_CD_MELEE) -/obj/item/forcefield/attack_self(mob/user) +/obj/item/forcefield_projector/attack_self(mob/user) if(LAZYLEN(current_fields)) to_chat(user, "You deactivate [src], disabling all active forcefields.") for(var/obj/structure/projected_forcefield/F in current_fields) qdel(F) -/obj/item/forcefield/examine(mob/user) +/obj/item/forcefield_projector/examine(mob/user) ..() var/percent_charge = round((shield_integrity/max_shield_integrity)*100) to_chat(user, "It is currently sustaining [LAZYLEN(current_fields)]/[max_fields] fields, and it's [percent_charge]% charged.") -/obj/item/forcefield/Initialize(mapload) - ..() +/obj/item/forcefield_projector/Initialize(mapload) + . = ..() current_fields = list() START_PROCESSING(SSobj, src) -/obj/item/forcefield/Destroy() +/obj/item/forcefield_projector/Destroy() STOP_PROCESSING(SSobj, src) return ..() -/obj/item/forcefield/process() +/obj/item/forcefield_projector/process() if(!LAZYLEN(current_fields)) shield_integrity = min(shield_integrity + 4, max_shield_integrity) else @@ -81,9 +82,9 @@ resistance_flags = INDESTRUCTIBLE CanAtmosPass = ATMOS_PASS_DENSITY armor = list("melee" = 0, "bullet" = 25, "laser" = 50, "energy" = 50, "bomb" = 25, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100) - var/obj/item/forcefield/generator + var/obj/item/forcefield_projector/generator -/obj/structure/projected_forcefield/Initialize(mapload, obj/item/forcefield/origin) +/obj/structure/projected_forcefield/Initialize(mapload, obj/item/forcefield_projector/origin) . = ..() generator = origin diff --git a/code/game/objects/items/devices/geiger_counter.dm b/code/game/objects/items/devices/geiger_counter.dm index fb4f4f8566..7823e570e0 100644 --- a/code/game/objects/items/devices/geiger_counter.dm +++ b/code/game/objects/items/devices/geiger_counter.dm @@ -132,6 +132,7 @@ to_chat(user, "[icon2html(src, user)] You switch [scanning ? "on" : "off"] [src].") /obj/item/geiger_counter/afterattack(atom/target, mob/user) + . = ..() if(user.a_intent == INTENT_HELP) if(!(obj_flags & EMAGGED)) user.visible_message("[user] scans [target] with [src].", "You scan [target]'s radiation levels with [src]...") @@ -141,7 +142,6 @@ target.rad_act(radiation_count) radiation_count = 0 return TRUE - return ..() /obj/item/geiger_counter/proc/scan(atom/A, mob/user) var/rad_strength = 0 @@ -208,7 +208,10 @@ if (mobhook && mobhook.parent != user) QDEL_NULL(mobhook) if (!mobhook) - mobhook = user.AddComponent(/datum/component/redirect, list(COMSIG_ATOM_RAD_ACT), CALLBACK(src, /atom.proc/rad_act)) + mobhook = user.AddComponent(/datum/component/redirect, list(COMSIG_ATOM_RAD_ACT = CALLBACK(src, .proc/redirect_rad_act))) + +/obj/item/geiger_counter/cyborg/proc/redirect_rad_act(datum/source, amount) + rad_act(amount) /obj/item/geiger_counter/cyborg/dropped() . = ..() diff --git a/code/game/objects/items/devices/instruments.dm b/code/game/objects/items/devices/instruments.dm index 427437866d..c5ed5fb601 100644 --- a/code/game/objects/items/devices/instruments.dm +++ b/code/game/objects/items/devices/instruments.dm @@ -10,12 +10,15 @@ var/datum/song/handheld/song var/instrumentId = "generic" var/instrumentExt = "mid" + var/tune_time = 0 /obj/item/instrument/Initialize() . = ..() song = new(instrumentId, src, instrumentExt) /obj/item/instrument/Destroy() + if (tune_time) + STOP_PROCESSING(SSobj, src) qdel(song) song = null return ..() @@ -48,6 +51,34 @@ user.set_machine(src) song.interact(user) +/obj/item/instrument/attackby(obj/item/W, mob/user, params) + if(istype(W, /obj/item/musicaltuner)) + var/mob/living/carbon/human/H = user + if (H.has_trait(TRAIT_MUSICIAN)) + if (!tune_time) + H.visible_message("[H] tunes the [src] to perfection!", "You tune the [src] to perfection!") + tune_time = 300 + START_PROCESSING(SSobj, src) + else + to_chat(H, "[src] is already well tuned!") + else + to_chat(H, "You have no idea how to use this.") + +/obj/item/instrument/process() + if (tune_time) + if (song.playing) + for (var/mob/living/M in song.hearing_mobs) + M.dizziness = max(0,M.dizziness-2) + M.jitteriness = max(0,M.jitteriness-2) + M.confused = max(M.confused-1) + SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "goodmusic", /datum/mood_event/goodmusic) + tune_time-- + else + if (!tune_time) + if (song.playing) + loc.visible_message("[src] starts sounding a little off...") + STOP_PROCESSING(SSobj, src) + /obj/item/instrument/violin name = "space violin" desc = "A wooden musical instrument with four strings and a bow. \"The devil went down to space, he was looking for an assistant to grief.\"" @@ -224,3 +255,16 @@ throw_speed = 3 throw_range = 15 hitsound = 'sound/items/bikehorn.ogg' + +/// + +/obj/item/musicaltuner + name = "musical tuner" + desc = "A device for tuning musical instruments both manual and electronic alike." + icon = 'icons/obj/device.dmi' + icon_state = "musicaltuner" + slot_flags = ITEM_SLOT_BELT + w_class = WEIGHT_CLASS_SMALL + item_state = "electronic" + lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi' + righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi' diff --git a/code/game/objects/items/devices/laserpointer.dm b/code/game/objects/items/devices/laserpointer.dm index f9ea6a6be4..632c2c4221 100644 --- a/code/game/objects/items/devices/laserpointer.dm +++ b/code/game/objects/items/devices/laserpointer.dm @@ -57,6 +57,7 @@ return ..() /obj/item/laser_pointer/afterattack(atom/target, mob/living/user, flag, params) + . = ..() laser_act(target, user, params) /obj/item/laser_pointer/proc/laser_act(atom/target, mob/living/user, params) @@ -91,7 +92,7 @@ if(iscarbon(target)) var/mob/living/carbon/C = target if(user.zone_selected == BODY_ZONE_PRECISE_EYES) - add_logs(user, C, "shone in the eyes", src) + log_combat(user, C, "shone in the eyes", src) var/severity = 1 if(prob(33)) @@ -108,7 +109,7 @@ //robots else if(iscyborg(target)) var/mob/living/silicon/S = target - add_logs(user, S, "shone in the sensors", src) + log_combat(user, S, "shone in the sensors", src) //chance to actually hit the eyes depends on internal component if(prob(effectchance * diode.rating)) S.flash_act(affect_silicon = 1) @@ -124,7 +125,7 @@ if(prob(effectchance * diode.rating)) C.emp_act(EMP_HEAVY) outmsg = "You hit the lens of [C] with [src], temporarily disabling the camera!" - add_logs(user, C, "EMPed", src) + log_combat(user, C, "EMPed", src) else outmsg = "You miss the lens of [C] with [src]!" @@ -137,7 +138,7 @@ if(prob(effectchance)) H.visible_message("[H] makes a grab for the light!","LIGHT!") H.Move(targloc) - add_logs(user, H, "moved with a laser pointer",src) + log_combat(user, H, "moved with a laser pointer",src) else H.visible_message("[H] looks briefly distracted by the light."," You're briefly tempted by the shiny light... ") else diff --git a/code/game/objects/items/devices/lightreplacer.dm b/code/game/objects/items/devices/lightreplacer.dm index a59fa11fa6..6615ebe8a8 100644 --- a/code/game/objects/items/devices/lightreplacer.dm +++ b/code/game/objects/items/devices/lightreplacer.dm @@ -239,6 +239,7 @@ return 0 /obj/item/lightreplacer/afterattack(atom/T, mob/U, proximity) + . = ..() if(!proximity) return if(!isturf(T)) diff --git a/code/game/objects/items/devices/megaphone.dm b/code/game/objects/items/devices/megaphone.dm index 5fa089a012..4b244e3002 100644 --- a/code/game/objects/items/devices/megaphone.dm +++ b/code/game/objects/items/devices/megaphone.dm @@ -14,7 +14,7 @@ /obj/item/megaphone/suicide_act(mob/living/carbon/user) user.visible_message("[user] is uttering [user.p_their()] last words into \the [src]! It looks like [user.p_theyre()] trying to commit suicide!") spamcheck = 0//so they dont have to worry about recharging - user.say("AAAAAAAAAAAARGHHHHH")//he must have died while coding this + user.say("AAAAAAAAAAAARGHHHHH", forced="megaphone suicide")//he must have died while coding this return OXYLOSS /obj/item/megaphone/get_held_item_speechspans(mob/living/carbon/user) diff --git a/code/game/objects/items/devices/multitool.dm b/code/game/objects/items/devices/multitool.dm index 43c2b06d44..f8b1d6e15b 100644 --- a/code/game/objects/items/devices/multitool.dm +++ b/code/game/objects/items/devices/multitool.dm @@ -15,6 +15,7 @@ desc = "Used for pulsing wires to test which to cut. Not recommended by doctors." icon = 'icons/obj/device.dmi' icon_state = "multitool" + item_state = "multitool" lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' force = 5 @@ -25,13 +26,19 @@ throw_speed = 3 materials = list(MAT_METAL=50, MAT_GLASS=20) var/obj/machinery/buffer // simple machine buffer for device linkage - hitsound = 'sound/weapons/tap.ogg' toolspeed = 1 tool_behaviour = TOOL_MULTITOOL usesound = 'sound/weapons/empty.ogg' var/datum/integrated_io/selected_io = null //functional for integrated circuits. var/mode = 0 +/obj/item/multitool/examine(mob/user) + ..() + if(selected_io) + to_chat(user, "Activate [src] to detach the data wire.") + if(buffer) + to_chat(user, "Its buffer contains [buffer].") + /obj/item/multitool/suicide_act(mob/living/carbon/user) user.visible_message("[user] puts the [src] to [user.p_their()] chest. It looks like [user.p_theyre()] trying to pulse [user.p_their()] heart off!") return OXYLOSS//theres a reason it wasnt recommended by doctors @@ -40,8 +47,6 @@ if(selected_io) selected_io = null to_chat(user, "You clear the wired connection from the multitool.") - else - ..() update_icon() /obj/item/multitool/update_icon() @@ -98,30 +103,89 @@ // Syndicate device disguised as a multitool; it will turn red when an AI camera is nearby. - /obj/item/multitool/ai_detect var/track_cooldown = 0 var/track_delay = 10 //How often it checks for proximity var/detect_state = PROXIMITY_NONE var/rangealert = 8 //Glows red when inside var/rangewarning = 20 //Glows yellow when inside + var/hud_type = DATA_HUD_AI_DETECT + var/hud_on = FALSE + var/mob/camera/aiEye/remote/ai_detector/eye + var/datum/action/item_action/toggle_multitool/toggle_action -/obj/item/multitool/ai_detect/New() - ..() +/obj/item/multitool/ai_detect/Initialize() + . = ..() START_PROCESSING(SSobj, src) + eye = new /mob/camera/aiEye/remote/ai_detector() + toggle_action = new /datum/action/item_action/toggle_multitool(src) /obj/item/multitool/ai_detect/Destroy() STOP_PROCESSING(SSobj, src) + if(hud_on && ismob(loc)) + remove_hud(loc) + QDEL_NULL(toggle_action) + QDEL_NULL(eye) return ..() +/obj/item/multitool/ai_detect/ui_action_click() + return + +/obj/item/multitool/ai_detect/update_icon() + if(selected_io) + icon_state = "multitool_red" + else + icon_state = "[initial(icon_state)][detect_state]" + +/obj/item/multitool/ai_detect/equipped(mob/living/carbon/human/user, slot) + ..() + if(hud_on) + show_hud(user) + +/obj/item/multitool/ai_detect/dropped(mob/living/carbon/human/user) + ..() + if(hud_on) + remove_hud(user) + /obj/item/multitool/ai_detect/process() if(track_cooldown > world.time) return detect_state = PROXIMITY_NONE + if(eye.eye_user) + eye.setLoc(get_turf(src)) multitool_detect() - icon_state = "[initial(icon_state)][detect_state]" + update_icon() track_cooldown = world.time + track_delay +/obj/item/multitool/ai_detect/proc/toggle_hud(mob/user) + hud_on = !hud_on + if(user) + to_chat(user, "You toggle the ai detection HUD on [src] [hud_on ? "on" : "off"].") + if(hud_on) + show_hud(user) + else + remove_hud(user) + +/obj/item/multitool/ai_detect/proc/show_hud(mob/user) + if(user && hud_type) + var/obj/screen/plane_master/camera_static/PM = user.hud_used.plane_masters["[CAMERA_STATIC_PLANE]"] + PM.alpha = 150 + var/datum/atom_hud/H = GLOB.huds[hud_type] + if(!H.hudusers[user]) + H.add_hud_to(user) + eye.eye_user = user + eye.setLoc(get_turf(src)) + +/obj/item/multitool/ai_detect/proc/remove_hud(mob/user) + if(user && hud_type) + var/obj/screen/plane_master/camera_static/PM = user.hud_used.plane_masters["[CAMERA_STATIC_PLANE]"] + PM.alpha = 255 + var/datum/atom_hud/H = GLOB.huds[hud_type] + H.remove_hud_from(user) + if(eye) + eye.setLoc(null) + eye.eye_user = null + /obj/item/multitool/ai_detect/proc/multitool_detect() var/turf/our_turf = get_turf(src) for(var/mob/living/silicon/ai/AI in GLOB.ai_list) @@ -134,6 +198,8 @@ var/datum/camerachunk/chunk = GLOB.cameranet.chunkGenerated(our_turf.x, our_turf.y, our_turf.z) if(chunk && chunk.seenby.len) for(var/mob/camera/aiEye/A in chunk.seenby) + if(!A.ai_detector_visible) + continue var/turf/detect_turf = get_turf(A) if(get_dist(our_turf, detect_turf) < rangealert) detect_state = PROXIMITY_ON_SCREEN @@ -142,6 +208,24 @@ detect_state = PROXIMITY_NEAR break +/mob/camera/aiEye/remote/ai_detector + name = "AI detector eye" + ai_detector_visible = FALSE + use_static = USE_STATIC_TRANSPARENT + visible_icon = FALSE + +/datum/action/item_action/toggle_multitool + name = "Toggle AI detector HUD" + check_flags = NONE + +/datum/action/item_action/toggle_multitool/Trigger() + if(!..()) + return 0 + if(target) + var/obj/item/multitool/ai_detect/M = target + M.toggle_hud(owner) + return 1 + /obj/item/multitool/cyborg name = "multitool" desc = "Optimised and stripped-down version of a regular multitool." diff --git a/code/game/objects/items/devices/pipe_painter.dm b/code/game/objects/items/devices/pipe_painter.dm index 6415b105b5..567cb0c73d 100644 --- a/code/game/objects/items/devices/pipe_painter.dm +++ b/code/game/objects/items/devices/pipe_painter.dm @@ -9,6 +9,7 @@ materials = list(MAT_METAL=5000, MAT_GLASS=2000) /obj/item/pipe_painter/afterattack(atom/A, mob/user, proximity_flag) + . = ..() //Make sure we only paint adjacent items if(!proximity_flag) return diff --git a/code/game/objects/items/devices/radio/intercom.dm b/code/game/objects/items/devices/radio/intercom.dm index 695f64f0b6..eb0271c1b9 100644 --- a/code/game/objects/items/devices/radio/intercom.dm +++ b/code/game/objects/items/devices/radio/intercom.dm @@ -119,6 +119,7 @@ return // Avoid hearing the same thing twice if(!anyai && !(speaker in ai)) return + ..() /obj/item/radio/intercom/process() if(((world.timeofday - last_tick) > 30) || ((world.timeofday - last_tick) < 0)) diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index d094f842d6..5a68a8423a 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -132,9 +132,9 @@ SLIME SCANNER if(ishuman(M)) var/mob/living/carbon/human/H = M if(H.undergoing_cardiac_arrest() && H.stat != DEAD) - to_chat(user, "Subject suffering from heart attack: apply defibrillator immediately!") + to_chat(user, "Subject suffering from heart attack: Apply defibrillation or other electric shock immediately!") if(H.undergoing_liver_failure() && H.stat != DEAD) - to_chat(user, "Subject suffering from liver failure: apply corazone and begin a liver transplant immediately!") + to_chat(user, "Subject is suffering from liver failure: Apply Corazone and begin a liver transplant immediately!") to_chat(user, "Analyzing results for [M]:\n\tOverall status: [mob_status]") @@ -152,11 +152,11 @@ SLIME SCANNER if(advanced) to_chat(user, "\tFatigue Level: [M.getStaminaLoss()]%.") if (M.getCloneLoss()) - to_chat(user, "\tSubject appears to have [M.getCloneLoss() > 30 ? "severe" : "minor"] cellular damage.") + to_chat(user, "\tSubject appears to have [M.getCloneLoss() > 30 ? "Severe" : "Minor"] cellular damage.") if(advanced) to_chat(user, "\tCellular Damage Level: [M.getCloneLoss()].") if (M.getBrainLoss() >= 200 || !M.getorgan(/obj/item/organ/brain)) - to_chat(user, "\tSubject brain function is non-existent.") + to_chat(user, "\tSubject's brain function is non-existent.") else if (M.getBrainLoss() >= 120) to_chat(user, "\tSevere brain damage detected. Subject likely to have mental traumas.") else if (M.getBrainLoss() >= 45) @@ -176,7 +176,7 @@ SLIME SCANNER trauma_desc += "permanent " trauma_desc += B.scan_desc trauma_text += trauma_desc - to_chat(user, "\tCerebral traumas detected: subjects appears to be suffering from [english_list(trauma_text)].") + to_chat(user, "\tCerebral traumas detected: subject appears to be suffering from [english_list(trauma_text)].") if(C.roundstart_quirks.len) to_chat(user, "\tSubject has the following physiological traits: [C.get_trait_string()].") if(advanced) @@ -243,7 +243,7 @@ SLIME SCANNER var/mob/living/carbon/human/H = M var/ldamage = H.return_liver_damage() if(ldamage > 10) - to_chat(user, "\t[ldamage > 45 ? "severe" : "minor"] liver damage detected.") + to_chat(user, "\t[ldamage > 45 ? "Severe" : "Minor"] liver damage detected.") // Body part damage report if(iscarbon(M) && mode == 1) @@ -388,6 +388,10 @@ SLIME SCANNER var/cooldown_time = 250 var/accuracy // 0 is the best accuracy. +/obj/item/analyzer/examine(mob/user) + . = ..() + to_chat(user, "Alt-click [src] to activate the barometer function.") + /obj/item/analyzer/suicide_act(mob/living/carbon/user) user.visible_message("[user] begins to analyze [user.p_them()]self with [src]! The display shows that [user.p_theyre()] dead!") return BRUTELOSS @@ -612,6 +616,7 @@ SLIME SCANNER to_chat(user, "Progress in core mutation: [T.applied] / [SLIME_EXTRACT_CROSSING_REQUIRED]") to_chat(user, "========================") + /obj/item/nanite_scanner name = "nanite scanner" icon = 'icons/obj/device.dmi' diff --git a/code/game/objects/items/devices/taperecorder.dm b/code/game/objects/items/devices/taperecorder.dm index 2324fd30b4..2df7892f61 100644 --- a/code/game/objects/items/devices/taperecorder.dm +++ b/code/game/objects/items/devices/taperecorder.dm @@ -121,9 +121,7 @@ mytape.storedinfo += "\[[time2text(mytape.used_capacity * 10,"mm:ss")]\] Recording started." var/used = mytape.used_capacity //to stop runtimes when you eject the tape var/max = mytape.max_capacity - for(used, used < max) - if(recording == 0) - break + while(recording && used < max) mytape.used_capacity++ used++ sleep(10) diff --git a/code/game/objects/items/devices/traitordevices.dm b/code/game/objects/items/devices/traitordevices.dm index c3720f7ac4..2c234a59ba 100644 --- a/code/game/objects/items/devices/traitordevices.dm +++ b/code/game/objects/items/devices/traitordevices.dm @@ -39,7 +39,7 @@ effective or pretty fucking useless. to_chat(user, "The mind batterer has been burnt out!") return - add_logs(user, null, "knocked down people in the area", src) + log_combat(user, null, "knocked down people in the area", src) for(var/mob/living/carbon/human/M in urange(10, user, 1)) if(prob(50)) @@ -82,7 +82,7 @@ effective or pretty fucking useless. if(!irradiate) return if(!used) - add_logs(user, M, "irradiated", src) + log_combat(user, M, "irradiated", src) var/cooldown = GetCooldown() used = 1 icon_state = "health1" diff --git a/code/game/objects/items/dna_injector.dm b/code/game/objects/items/dna_injector.dm index ebae70ca05..d5ac5d9c52 100644 --- a/code/game/objects/items/dna_injector.dm +++ b/code/game/objects/items/dna_injector.dm @@ -50,7 +50,7 @@ if(fields["UI"]) //UI+UE M.dna.uni_identity = merge_text(M.dna.uni_identity, fields["UI"]) M.updateappearance(mutations_overlay_update=1) - log_attack(log_msg) + log_attack("[log_msg] [loc_name(user)]") return TRUE return FALSE @@ -65,7 +65,7 @@ var/mob/living/carbon/human/humantarget = target if (!humantarget.can_inject(user, 1)) return - add_logs(user, target, "attempted to inject", src) + log_combat(user, target, "attempted to inject", src) if(target != user) target.visible_message("[user] is trying to inject [target] with [src]!", "[user] is trying to inject [target] with [src]!") @@ -77,7 +77,7 @@ else to_chat(user, "You inject yourself with [src].") - add_logs(user, target, "injected", src) + log_combat(user, target, "injected", src) if(!inject(target, user)) //Now we actually do the heavy lifting. to_chat(user, "It appears that [target] does not have compatible DNA.") @@ -130,7 +130,7 @@ //////////////////////////////////// /obj/item/dnainjector/anticough name = "\improper DNA injector (Anti-Cough)" - desc = "Will stop that aweful noise." + desc = "Will stop that awful noise." remove_mutations_static = list(COUGH) /obj/item/dnainjector/coughmut @@ -353,7 +353,7 @@ M.dna.uni_identity = merge_text(M.dna.uni_identity, fields["UI"]) M.updateappearance(mutations_overlay_update=1) M.dna.temporary_mutations[UI_CHANGED] = endtime - log_attack(log_msg) + log_attack("[log_msg] [loc_name(user)]") return TRUE else return FALSE diff --git a/code/game/objects/items/extinguisher.dm b/code/game/objects/items/extinguisher.dm index 6b8b96364c..8e391d9559 100644 --- a/code/game/objects/items/extinguisher.dm +++ b/code/game/objects/items/extinguisher.dm @@ -11,7 +11,7 @@ throw_speed = 2 throw_range = 7 force = 10 - materials = list(MAT_METAL=90) + materials = list(MAT_METAL = 90) attack_verb = list("slammed", "whacked", "bashed", "thunked", "battered", "bludgeoned", "thrashed") dog_fashion = /datum/dog_fashion/back resistance_flags = FIRE_PROOF @@ -37,7 +37,7 @@ throwforce = 2 w_class = WEIGHT_CLASS_SMALL force = 3 - materials = list() + materials = list(MAT_METAL = 50, MAT_GLASS = 40) max_water = 30 sprite_name = "miniFE" dog_fashion = null @@ -120,6 +120,7 @@ return 0 /obj/item/extinguisher/afterattack(atom/target, mob/user , flag) + . = ..() // Make it so the extinguisher doesn't spray yourself when you click your inventory items if (target.loc == user) return @@ -142,29 +143,13 @@ var/direction = get_dir(src,target) if(user.buckled && isobj(user.buckled) && !user.buckled.anchored) - spawn(0) - var/obj/B = user.buckled - var/movementdirection = turn(direction,180) - step(B, movementdirection) - sleep(1) - step(B, movementdirection) - sleep(1) - step(B, movementdirection) - sleep(1) - step(B, movementdirection) - sleep(2) - step(B, movementdirection) - sleep(2) - step(B, movementdirection) - sleep(3) - step(B, movementdirection) - sleep(3) - step(B, movementdirection) - sleep(3) - step(B, movementdirection) + var/obj/B = user.buckled + var/movementdirection = turn(direction,180) + addtimer(CALLBACK(src, /obj/item/extinguisher/proc/move_chair, B, movementdirection), 1) else user.newtonian_move(turn(direction, 180)) + //Get all the turfs that can be shot at var/turf/T = get_turf(target) var/turf/T1 = get_step(T,turn(direction, 90)) var/turf/T2 = get_step(T,turn(direction, -90)) @@ -172,37 +157,63 @@ if(precision) var/turf/T3 = get_step(T1, turn(direction, 90)) var/turf/T4 = get_step(T2,turn(direction, -90)) - the_targets = list(T,T1,T2,T3,T4) + the_targets.Add(T3,T4) + var/list/water_particles=list() for(var/a=0, a<5, a++) - spawn(0) - var/obj/effect/particle_effect/water/W = new /obj/effect/particle_effect/water(get_turf(src)) - var/turf/my_target = pick(the_targets) - if(precision) - the_targets -= my_target - var/datum/reagents/R = new/datum/reagents(5) - if(!W) - return - W.reagents = R - R.my_atom = W - if(!W || !src) - return - src.reagents.trans_to(W,1) - for(var/b=0, bYou feel like you've experienced enough to cast [spellname]!") user.mind.AddSpell(S) - user.log_message("learned the spell [spellname] ([S]).", INDIVIDUAL_ATTACK_LOG) + user.log_message("learned the spell [spellname] ([S])", LOG_ATTACK, color="orange") onlearned(user) reading = FALSE @@ -330,7 +330,7 @@ if(do_after(user,50, user)) to_chat(user, "[greet]") MA.teach(user) - user.log_message("learned the martial art [martialname] ([MA]).", INDIVIDUAL_ATTACK_LOG) + user.log_message("learned the martial art [martialname] ([MA])", LOG_ATTACK, color="orange") onlearned(user) reading = FALSE diff --git a/code/game/objects/items/grenades/chem_grenade.dm b/code/game/objects/items/grenades/chem_grenade.dm index c961fca9f2..7a0c5fd8df 100644 --- a/code/game/objects/items/grenades/chem_grenade.dm +++ b/code/game/objects/items/grenades/chem_grenade.dm @@ -18,6 +18,7 @@ var/ignition_temp = 10 // The amount of heat added to the reagents when this grenade goes off. var/threatscale = 1 // Used by advanced grenades to make them slightly more worthy. var/no_splash = FALSE //If the grenade deletes even if it has no reagents to splash with. Used for slime core reactions. + var/casedesc = "This basic model accepts both beakers and bottles. It heats contents by 10°K upon ignition." // Appears when examining empty casings. /obj/item/grenade/chem_grenade/Initialize() . = ..() @@ -76,8 +77,7 @@ to_chat(user, "You add [I] to the [initial(name)] assembly.") beakers += I var/reagent_list = pretty_string_from_reagent_list(I.reagents) - add_logs(user, src, "inserted [I]", addition = "[reagent_list] inside.") - log_game("[key_name(user)] inserted [I] into [src] containing [reagent_list] ") + user.log_message("inserted [I] ([reagent_list]) into [src]",LOG_GAME) else to_chat(user, "[I] is empty!") @@ -117,8 +117,7 @@ if(!O.reagents) continue var/reagent_list = pretty_string_from_reagent_list(O.reagents) - add_logs(user, src, "removed [O]", addition = "[reagent_list] inside.") - log_game("[key_name(user)] removed [O] from [src] containing [reagent_list]") + user.log_message("removed [O] ([reagent_list]) from [src]") beakers = list() to_chat(user, "You open the [initial(name)] assembly and remove the payload.") return // First use of the wrench remove beakers, then use the wrench to remove the activation mechanism. @@ -138,7 +137,7 @@ stage = N if(stage == EMPTY) name = "[initial(name)] casing" - desc = "A do it yourself [initial(name)]!" + desc = "A do it yourself [initial(name)]! [initial(casedesc)]" icon_state = initial(icon_state) else if(stage == WIRED) name = "unsecured [initial(name)]" @@ -174,8 +173,7 @@ var/message = "[src] primed by [user] at [ADMIN_VERBOSEJMP(T)] contained [reagent_string]." GLOB.bombers += message message_admins(message) - log_game("[src] primed by [user] at [AREACOORD(T)] contained [reagent_string].") - add_logs(user, src, "primed", addition = "[reagent_string] inside.") + user.log_message("primed [src] ([reagent_string])",LOG_GAME) /obj/item/grenade/chem_grenade/prime() if(stage != READY) @@ -211,10 +209,10 @@ //Large chem grenades accept slime cores and use the appropriately. /obj/item/grenade/chem_grenade/large name = "large grenade" - desc = "A custom made large grenade. It affects a larger area." + desc = "A custom made large grenade. Larger splash range and increased ignition temperature compared to basic grenades. Fits exotic containers." + casedesc = "This casing affects a larger area than the basic model and can fit exotic containers, including slime cores. Heats contents by 25°K upon ignition." icon_state = "large_grenade" - allowed_containers = list(/obj/item/reagent_containers/glass, /obj/item/reagent_containers/food/condiment, - /obj/item/reagent_containers/food/drinks) + allowed_containers = list(/obj/item/reagent_containers/glass, /obj/item/reagent_containers/food/condiment, /obj/item/reagent_containers/food/drinks) affected_area = 5 ignition_temp = 25 // Large grenades are slightly more effective at setting off heat-sensitive mixtures than smaller grenades. threatscale = 1.1 // 10% more effective. @@ -255,21 +253,23 @@ /obj/item/grenade/chem_grenade/cryo // Intended for rare cryogenic mixes. Cools the area moderately upon detonation. name = "cryo grenade" - desc = "A custom made cryogenic grenade. It rapidly cools its contents upon detonation." + desc = "A custom made cryogenic grenade. Rapidly cools contents upon ignition." + casedesc = "Upon ignition, it rapidly cools contents by 100°K. Smaller splash range than regular casings." icon_state = "cryog" affected_area = 2 ignition_temp = -100 /obj/item/grenade/chem_grenade/pyro // Intended for pyrotechnical mixes. Produces a small fire upon detonation, igniting potentially flammable mixtures. name = "pyro grenade" - desc = "A custom made pyrotechnical grenade. It heats up and ignites its contents upon detonation." + desc = "A custom made pyrotechnical grenade. Heats up contents upon ignition." + casedesc = "Upon ignition, it rapidly heats contents by 500°K." icon_state = "pyrog" - affected_area = 3 ignition_temp = 500 // This is enough to expose a hotspot. /obj/item/grenade/chem_grenade/adv_release // Intended for weaker, but longer lasting effects. Could have some interesting uses. name = "advanced release grenade" desc = "A custom made advanced release grenade. It is able to be detonated more than once. Can be configured using a multitool." + casedesc = "This casing is able to detonate more than once. Can be configured using a multitool." icon_state = "timeg" var/unit_spread = 10 // Amount of units per repeat. Can be altered with a multitool. @@ -324,7 +324,7 @@ /obj/item/grenade/chem_grenade/metalfoam name = "metal foam grenade" - desc = "Used for emergency sealing of air breaches." + desc = "Used for emergency sealing of hull breaches." stage = READY /obj/item/grenade/chem_grenade/metalfoam/Initialize() @@ -342,7 +342,7 @@ /obj/item/grenade/chem_grenade/smart_metal_foam name = "smart metal foam grenade" - desc = "Used for sealing and reconstruction of air breaches." + desc = "Used for emergency sealing of hull breaches, while keeping areas accessible." stage = READY /obj/item/grenade/chem_grenade/smart_metal_foam/Initialize() @@ -562,9 +562,9 @@ beakers += B2 /obj/item/grenade/chem_grenade/tuberculosis - name = "Fungal tuberculosis grenade" - desc = "WARNING: GRENADE WILL RELEASE DEADLY SPORES CONTAINING ACTIVE AGENTS. SEAL SUIT AND AIRFLOW BEFORE USE." - stage = READY + name = "Fungal tuberculosis grenade" + desc = "WARNING: GRENADE WILL RELEASE DEADLY SPORES CONTAINING ACTIVE AGENTS. SEAL SUIT AND AIRFLOW BEFORE USE." + stage = READY /obj/item/grenade/chem_grenade/tuberculosis/Initialize() . = ..() diff --git a/code/game/objects/items/grenades/plastic.dm b/code/game/objects/items/grenades/plastic.dm index 37dc206099..709fedbe5a 100644 --- a/code/game/objects/items/grenades/plastic.dm +++ b/code/game/objects/items/grenades/plastic.dm @@ -99,6 +99,7 @@ to_chat(user, "Timer set for [det_time] seconds.") /obj/item/grenade/plastic/afterattack(atom/movable/AM, mob/user, flag) + . = ..() aim_dir = get_dir(user,AM) if(!flag) return @@ -141,12 +142,12 @@ else if(UM.has_antag_datum(/datum/antagonist/changeling)) message_say = "FOR THE HIVE!" else if(UM.has_antag_datum(/datum/antagonist/cult)) - message_say = "FOR NAR-SIE!" + message_say = "FOR NAR'SIE!" else if(UM.has_antag_datum(/datum/antagonist/clockcult)) message_say = "FOR RATVAR!" else if(UM.has_antag_datum(/datum/antagonist/rev)) message_say = "VIVA LA REVOLUTION!" - M.say(message_say) + M.say(message_say, forced="C4 suicide") /obj/item/grenade/plastic/suicide_act(mob/user) message_admins("[ADMIN_LOOKUPFLW(user)] suicided with [src] at [ADMIN_VERBOSEJMP(user)]") @@ -171,7 +172,6 @@ name = "C4" desc = "Used to put holes in specific areas without too much extra hole. A saboteur's favorite." gender = PLURAL - var/timer = 10 var/open_panel = 0 can_attach_mob = TRUE @@ -192,7 +192,7 @@ message_admins("[ADMIN_LOOKUPFLW(user)] suicided with [name] at [ADMIN_VERBOSEJMP(src)]") log_game("[key_name(user)] suicided with [name] at [AREACOORD(user)]") sleep(10) - explode(get_turf(user)) + prime() user.gib(1, 1) /obj/item/grenade/plastic/c4/attackby(obj/item/I, mob/user, params) @@ -204,41 +204,7 @@ else return ..() -/obj/item/grenade/plastic/c4/attack_self(mob/user) - var/newtime = input(usr, "Please set the timer.", "Timer", 10) as num - if(user.get_active_held_item() == src) - newtime = CLAMP(newtime, 10, 60000) - timer = newtime - to_chat(user, "Timer set for [timer] seconds.") - -/obj/item/grenade/plastic/c4/afterattack(atom/movable/AM, mob/user, flag) - if (!flag) - return - if(ismob(AM) && !can_attach_mob) - return - if(loc == AM) - return - if(SEND_SIGNAL(AM, COMSIG_CONTAINS_STORAGE) && !SEND_SIGNAL(AM, COMSIG_IS_STORAGE_LOCKED)) - return - - to_chat(user, "You start planting the bomb...") - - if(do_after(user, 30, target = AM)) - if(!user.temporarilyRemoveItemFromInventory(src)) - return - src.target = AM - moveToNullspace() - - var/message = "[ADMIN_LOOKUPFLW(user)] planted [name] on [target.name] at [ADMIN_VERBOSEJMP(target)] with [timer] second fuse" - GLOB.bombers += message - message_admins(message,0,1) - log_game("[key_name(user)] planted [name] on [target.name] at [AREACOORD(target)] with [timer] second fuse") - - target.add_overlay(plastic_overlay, TRUE) - to_chat(user, "You plant the bomb. Timer counting down from [timer].") - addtimer(CALLBACK(src, .proc/explode), timer * 10) - -/obj/item/grenade/plastic/c4/proc/explode() +/obj/item/grenade/plastic/c4/prime() if(QDELETED(src)) return var/turf/location diff --git a/code/game/objects/items/grenades/spawnergrenade.dm b/code/game/objects/items/grenades/spawnergrenade.dm index 9d0f099140..2cc72f3694 100644 --- a/code/game/objects/items/grenades/spawnergrenade.dm +++ b/code/game/objects/items/grenades/spawnergrenade.dm @@ -34,3 +34,10 @@ /obj/item/grenade/spawnergrenade/syndiesoap name = "Mister Scrubby" spawner_type = /obj/item/soap/syndie + +/obj/item/grenade/spawnergrenade/buzzkill + name = "Buzzkill grenade" + desc = "The label reads: \"WARNING: DEVICE WILL RELEASE LIVE SPECIMENS UPON ACTIVATION. SEAL SUIT BEFORE USE.\" It is warm to the touch and vibrates faintly." + icon_state = "holy_grenade" + spawner_type = /mob/living/simple_animal/hostile/poison/bees/toxin + deliveryamt = 10 diff --git a/code/game/objects/items/handcuffs.dm b/code/game/objects/items/handcuffs.dm index 2ed152ee21..8a2e5d1292 100644 --- a/code/game/objects/items/handcuffs.dm +++ b/code/game/objects/items/handcuffs.dm @@ -56,12 +56,12 @@ M.retaliate(user) if(!C.handcuffed) - if(C.get_num_arms() >= 2 || C.get_arm_ignore()) + if(C.get_num_arms(FALSE) >= 2 || C.get_arm_ignore()) C.visible_message("[user] is trying to put [src.name] on [C]!", \ "[user] is trying to put [src.name] on [C]!") playsound(loc, cuffsound, 30, 1, -2) - if(do_mob(user, C, 30) && (C.get_num_arms() >= 2 || C.get_arm_ignore())) + if(do_mob(user, C, 30) && (C.get_num_arms(FALSE) >= 2 || C.get_arm_ignore())) if(iscyborg(user)) apply_cuffs(C, user, TRUE) else @@ -69,7 +69,7 @@ to_chat(user, "You handcuff [C].") SSblackbox.record_feedback("tally", "handcuffs", 1, type) - add_logs(user, C, "handcuffed") + log_combat(user, C, "handcuffed") else to_chat(user, "You fail to handcuff [C]!") else @@ -272,7 +272,7 @@ snap = 1 if(!C.lying) def_zone = pick(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) - if(!C.legcuffed && C.get_num_legs() >= 2) //beartrap can't cuff your leg if there's already a beartrap or legcuffs, or you don't have two legs. + if(!C.legcuffed && C.get_num_legs(FALSE) >= 2) //beartrap can't cuff your leg if there's already a beartrap or legcuffs, or you don't have two legs. C.legcuffed = src forceMove(C) C.update_inv_legcuffed() @@ -333,7 +333,7 @@ if(..() || !iscarbon(hit_atom))//if it gets caught or the target can't be cuffed, return//abort var/mob/living/carbon/C = hit_atom - if(!C.legcuffed && C.get_num_legs() >= 2) + if(!C.legcuffed && C.get_num_legs(FALSE) >= 2) visible_message("\The [src] ensnares [C]!") C.legcuffed = src forceMove(C) diff --git a/code/game/objects/items/his_grace.dm b/code/game/objects/items/his_grace.dm index ed5e763874..f293b04fa9 100644 --- a/code/game/objects/items/his_grace.dm +++ b/code/game/objects/items/his_grace.dm @@ -20,11 +20,15 @@ var/bloodthirst = HIS_GRACE_SATIATED var/prev_bloodthirst = HIS_GRACE_SATIATED var/force_bonus = 0 + var/ascended = FALSE + var/victims_needed = 25 + var/ascend_bonus = 15 /obj/item/his_grace/Initialize() . = ..() START_PROCESSING(SSprocessing, src) GLOB.poi_list += src + AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_POST_THROW = CALLBACK(src, .proc/move_gracefully))) /obj/item/his_grace/Destroy() STOP_PROCESSING(SSprocessing, src) @@ -74,7 +78,7 @@ if(!bloodthirst) drowse() return - if(bloodthirst < HIS_GRACE_CONSUME_OWNER) + if(bloodthirst < HIS_GRACE_CONSUME_OWNER && !ascended) adjust_bloodthirst(1 + FLOOR(LAZYLEN(contents) * 0.5, 1)) //Maybe adjust this? else adjust_bloodthirst(1) //don't cool off rapidly once we're at the point where His Grace consumes all. @@ -129,16 +133,38 @@ force_bonus = HIS_GRACE_FORCE_BONUS * LAZYLEN(contents) playsound(user, 'sound/effects/pope_entry.ogg', 100) icon_state = "his_grace_awakened" + move_gracefully() -/obj/item/his_grace/proc/drowse() //Good night, Mr. Grace. +/obj/item/his_grace/proc/move_gracefully() if(!awakened) return + var/static/list/transforms + if(!transforms) + var/matrix/M1 = matrix() + var/matrix/M2 = matrix() + var/matrix/M3 = matrix() + var/matrix/M4 = matrix() + M1.Translate(-1, 0) + M2.Translate(0, 1) + M3.Translate(1, 0) + M4.Translate(0, -1) + transforms = list(M1, M2, M3, M4) + + animate(src, transform=transforms[1], time=0.2, loop=-1) + animate(transform=transforms[2], time=0.1) + animate(transform=transforms[3], time=0.2) + animate(transform=transforms[4], time=0.3) + +/obj/item/his_grace/proc/drowse() //Good night, Mr. Grace. + if(!awakened || ascended) + return var/turf/T = get_turf(src) - T.visible_message("[src] slowly stops rattling and falls still, His latch snapping closed.") + T.visible_message("[src] slowly stops rattling and falls still, His latch snapping shut.") playsound(loc, 'sound/weapons/batonextend.ogg', 100, 1) name = initial(name) desc = initial(desc) icon_state = initial(icon_state) + animate(src, transform=matrix()) gender = initial(gender) force = initial(force) force_bonus = initial(force_bonus) @@ -159,13 +185,15 @@ bloodthirst = max(LAZYLEN(contents), 1) //Never fully sated, and His hunger will only grow. else bloodthirst = HIS_GRACE_CONSUME_OWNER + if(LAZYLEN(contents) >= victims_needed) + ascend() update_stats() /obj/item/his_grace/proc/adjust_bloodthirst(amt) prev_bloodthirst = bloodthirst - if(prev_bloodthirst < HIS_GRACE_CONSUME_OWNER) + if(prev_bloodthirst < HIS_GRACE_CONSUME_OWNER && !ascended) bloodthirst = CLAMP(bloodthirst + amt, HIS_GRACE_SATIATED, HIS_GRACE_CONSUME_OWNER) - else + else if(!ascended) bloodthirst = CLAMP(bloodthirst + amt, HIS_GRACE_CONSUME_OWNER, HIS_GRACE_FALL_ASLEEP) update_stats() @@ -206,3 +234,17 @@ if(prev_bloodthirst >= HIS_GRACE_PECKISH) master.visible_message("[src] is satiated.", "[src]'s hunger recedes...") force = initial(force) + force_bonus + +/obj/item/his_grace/proc/ascend() + if(ascended) + return + var/mob/living/carbon/human/master = loc + force_bonus += ascend_bonus + desc = "A legendary toolbox and a distant artifact from The Age of Three Powers. On its three latches engraved are the words \"The Sun\", \"The Moon\", and \"The Stars\". The entire toolbox has the words \"The World\" engraved into its sides." + icon_state = "his_grace_ascended" + item_state = "toolbox_gold" + ascended = TRUE + playsound(src, 'sound/effects/his_grace_ascend.ogg', 100) + if(istype(master)) + master.visible_message("Gods will be watching.") + name = "[master]'s mythical toolbox of three powers" diff --git a/code/game/objects/items/holosign_creator.dm b/code/game/objects/items/holosign_creator.dm index 654afba29d..78881d901e 100644 --- a/code/game/objects/items/holosign_creator.dm +++ b/code/game/objects/items/holosign_creator.dm @@ -19,6 +19,7 @@ var/holocreator_busy = FALSE //to prevent placing multiple holo barriers at once /obj/item/holosign_creator/afterattack(atom/target, mob/user, flag) + . = ..() if(flag) if(!check_allowed_items(target, 1)) return @@ -83,6 +84,14 @@ creation_time = 0 max_signs = 3 +/obj/item/holosign_creator/medical + name = "\improper PENLITE barrier projector" + desc = "A holographic projector that creates PENLITE holobarriers. Useful during quarantines since they halt those with malicious diseases." + icon_state = "signmaker_med" + holosign_type = /obj/structure/holosign/barrier/medical + creation_time = 30 + max_signs = 3 + /obj/item/holosign_creator/cyborg name = "Energy Barrier Projector" desc = "A holographic projector that creates fragile energy fields." diff --git a/code/game/objects/items/holy_weapons.dm b/code/game/objects/items/holy_weapons.dm index 4c38752e28..cc121ab0a3 100644 --- a/code/game/objects/items/holy_weapons.dm +++ b/code/game/objects/items/holy_weapons.dm @@ -169,7 +169,7 @@ /obj/item/nullrod name = "null rod" - desc = "A rod of pure obsidian; its very presence disrupts and dampens the powers of Nar-Sie and Ratvar's followers." + desc = "A rod of pure obsidian; its very presence disrupts and dampens the powers of Nar'Sie and Ratvar's followers." icon_state = "nullrod" item_state = "nullrod" lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi' @@ -181,6 +181,7 @@ w_class = WEIGHT_CLASS_TINY obj_flags = UNIQUE_RENAME var/reskinned = FALSE + var/chaplain_spawnable = TRUE /obj/item/nullrod/Initialize() . = ..() @@ -201,16 +202,15 @@ var/list/holy_weapons_list = typesof(/obj/item/nullrod) var/list/display_names = list() for(var/V in holy_weapons_list) - var/atom/A = V - display_names += initial(A.name) + var/obj/item/nullrod/rodtype = V + if (initial(rodtype.chaplain_spawnable)) + display_names[initial(rodtype.name)] = rodtype var/choice = input(M,"What theme would you like for your holy weapon?","Holy Weapon Theme") as null|anything in display_names if(QDELETED(src) || !choice || M.stat || !in_range(M, src) || M.restrained() || !M.canmove || reskinned) return - var/index = display_names.Find(choice) - var/A = holy_weapons_list[index] - + var/A = display_names[choice] // This needs to be on a separate var as list member access is not allowed for new holy_weapon = new A SSreligion.holy_weapon_type = holy_weapon.type @@ -448,6 +448,8 @@ item_state = "chainswordon" name = "possessed chainsaw sword" desc = "Suffer not a heretic to live." + chaplain_spawnable = FALSE + force = 30 slot_flags = ITEM_SLOT_BELT attack_verb = list("sawed", "torn", "cut", "chopped", "diced") hitsound = 'sound/weapons/chainsawhit.ogg' @@ -503,6 +505,7 @@ hitsound = 'sound/weapons/blade1.ogg' /obj/item/nullrod/pride_hammer/afterattack(atom/A as mob|obj|turf|area, mob/user, proximity) + . = ..() if(!proximity) return if(prob(30) && ishuman(A)) diff --git a/code/game/objects/items/hot_potato.dm b/code/game/objects/items/hot_potato.dm index eefa302032..db7f38ddf3 100644 --- a/code/game/objects/items/hot_potato.dm +++ b/code/game/objects/items/hot_potato.dm @@ -91,8 +91,9 @@ to_chat(user, "You have a really bad feeling about [src]!") /obj/item/hot_potato/afterattack(atom/target, mob/user, adjacent, params) + . = ..() if(!adjacent || !ismob(target)) - return ..() + return force_onto(target, user) /obj/item/hot_potato/proc/force_onto(mob/living/victim, mob/user) @@ -116,11 +117,11 @@ else . = TRUE if(.) - add_logs(user, victim, "forced a hot potato with explosive variables ([detonate_explosion]-[detonate_dev_range]/[detonate_heavy_range]/[detonate_light_range]/[detonate_flash_range]/[detonate_fire_range]) onto") + log_combat(user, victim, "forced a hot potato with explosive variables ([detonate_explosion]-[detonate_dev_range]/[detonate_heavy_range]/[detonate_light_range]/[detonate_flash_range]/[detonate_fire_range]) onto") user.visible_message("[user] forces [src] onto [victim]!", "You force [src] onto [victim]!", "You hear a mechanical click and a beep.") colorize(null) else - add_logs(user, victim, "tried to force a hot potato with explosive variables ([detonate_explosion]-[detonate_dev_range]/[detonate_heavy_range]/[detonate_light_range]/[detonate_flash_range]/[detonate_fire_range]) onto") + log_combat(user, victim, "tried to force a hot potato with explosive variables ([detonate_explosion]-[detonate_dev_range]/[detonate_heavy_range]/[detonate_light_range]/[detonate_flash_range]/[detonate_fire_range]) onto") user.visible_message("[user] tried to force [src] onto [victim], but it could not attach!", "You try to force [src] onto [victim], but it is unable to attach!", "You hear a mechanical click and two buzzes.") user.put_in_hands(src) diff --git a/code/game/objects/items/implants/implant.dm b/code/game/objects/items/implants/implant.dm index 7184b956f5..482cfb0d8e 100644 --- a/code/game/objects/items/implants/implant.dm +++ b/code/game/objects/items/implants/implant.dm @@ -59,7 +59,7 @@ if(flags & COMPONENT_STOP_IMPLANTING) UNSETEMPTY(target.implants) return FALSE - + if(istype(imp_e, type)) if(!allow_multiple) if(imp_e.uses < initial(imp_e.uses)*2) @@ -84,7 +84,7 @@ H.sec_hud_set_implants() if(user) - add_logs(user, target, "implanted", "\a [name]") + log_combat(user, target, "implanted", "\a [name]") return TRUE diff --git a/code/game/objects/items/implants/implant_mindshield.dm b/code/game/objects/items/implants/implant_mindshield.dm index fe893ccd7d..2f76b0cdc3 100644 --- a/code/game/objects/items/implants/implant_mindshield.dm +++ b/code/game/objects/items/implants/implant_mindshield.dm @@ -48,14 +48,14 @@ /obj/item/implant/mindshield/removed(mob/target, silent = FALSE, special = 0) if(..()) - if(target.stat != DEAD && !silent) - to_chat(target, "Your mind suddenly feels terribly vulnerable. You are no longer safe from brainwashing.") if(isliving(target)) var/mob/living/L = target L.remove_trait(TRAIT_MINDSHIELD, "implant") L.sec_hud_set_implants() - return TRUE - return FALSE + if(target.stat != DEAD && !silent) + to_chat(target, "Your mind suddenly feels terribly vulnerable. You are no longer safe from brainwashing.") + return 1 + return 0 /obj/item/implanter/mindshield name = "implanter (mindshield)" diff --git a/code/game/objects/items/implants/implant_stealth.dm b/code/game/objects/items/implants/implant_stealth.dm index f514b8e21a..b3e9f24206 100644 --- a/code/game/objects/items/implants/implant_stealth.dm +++ b/code/game/objects/items/implants/implant_stealth.dm @@ -9,11 +9,10 @@ name = "inconspicious box" desc = "It's so normal that you didn't notice it before." icon_state = "agentbox" - use_mob_movespeed = TRUE + move_speed_multiplier = 0.5 /obj/structure/closet/cardboard/agent/proc/go_invisible() animate(src, , alpha = 0, time = 5) - START_PROCESSING(SSobj, src) /obj/structure/closet/cardboard/agent/Initialize() . = ..() @@ -25,14 +24,18 @@ qdel(src) /obj/structure/closet/cardboard/agent/process() - animate(src, , alpha = alpha - 50, time = 3) + alpha = max(0, alpha - 50) -/obj/structure/closet/cardboard/agent/Move() - . = ..() - if(.) - alpha = min(alpha + 5, 255) +/obj/structure/closet/cardboard/agent/proc/reveal() + alpha = 255 + addtimer(CALLBACK(src, .proc/go_invisible), 10, TIMER_OVERRIDE|TIMER_UNIQUE) /obj/structure/closet/cardboard/agent/Bump(atom/movable/A) . = ..() if(isliving(A)) - alpha = 255 + reveal() + +/obj/structure/closet/cardboard/agent/Bumped(atom/movable/A) + . = ..() + if(isliving(A)) + reveal() diff --git a/code/game/objects/items/implants/implanter.dm b/code/game/objects/items/implants/implanter.dm index a0aa5fc960..a1d360240d 100644 --- a/code/game/objects/items/implants/implanter.dm +++ b/code/game/objects/items/implants/implanter.dm @@ -74,4 +74,4 @@ /obj/item/implanter/stealth name = "implanter (stealth)" - imp_type = /obj/item/implant/stealth + imp_type = /obj/item/implant/stealth \ No newline at end of file diff --git a/code/game/objects/items/manuals.dm b/code/game/objects/items/manuals.dm index 9d47efe862..6194c4d9ca 100644 --- a/code/game/objects/items/manuals.dm +++ b/code/game/objects/items/manuals.dm @@ -4,102 +4,14 @@ /obj/item/book/manual icon = 'icons/obj/library.dmi' due_date = 0 // Game time in 1/10th seconds - unique = 1 // 0 - Normal book, 1 - Should not be treated as normal book, unable to be copied, unable to be modified - -/obj/item/book/manual/engineering_particle_accelerator - name = "Particle Accelerator User's Guide" - icon_state ="bookParticleAccelerator" - author = "Engineering Encyclopedia" // Whoever wrote the paper or book, can be changed by pen or PC. It is not automatically assigned. - title = "Particle Accelerator User's Guide" -//book contents below - - dat = {" - - - - - -

    Experienced user's guide

    - -

    Setting up

    - -
      -
    1. Wrench all pieces to the floor
    2. -
    3. Add wires to all the pieces
    4. -
    5. Close all the panels with your screwdriver
    6. -
    - -

    Use

    - -
      -
    1. Open the control panel
    2. -
    3. Set the speed to 2
    4. -
    5. Start firing at the singularity generator
    6. -
    7. When the singularity reaches a large enough size so it starts moving on its own set the speed down to 0, but don't shut it off
    8. -
    9. Remember to wear a radiation suit when working with this machine... we did tell you that at the start, right?
    10. -
    - - - "} - - -/obj/item/book/manual/engineering_singularity_safety - name = "Singularity Safety in Special Circumstances" - icon_state ="bookEngineeringSingularitySafety" - author = "Engineering Encyclopedia" - title = "Singularity Safety in Special Circumstances" - dat = {" - - - - -

    Singularity Safety in Special Circumstances

    - -

    Power outage

    - - A power problem has made the entire station lose power? Could be station-wide wiring problems or syndicate power sinks. In any case follow these steps: -

    - Step one: PANIC!
    - Step two: Get your ass over to engineering! QUICKLY!!!
    - Step three: Make sure the SMES is still powering the emitters, if not, setup the generator in secure storage and disconnect the emitters from the SMES.
    - Step four: Next, head over to the APC and swipe it with your ID card - if it doesn't unlock, continue with step 15.
    - Step five: Open the console and disengage the cover lock.
    - Step six: Pry open the APC with a Crowbar.
    - Step seven: Take out the empty power cell.
    - Step eight: Put in the new, full power cell - if you don't have one, continue with step 15.
    - Step nine: Quickly put on a Radiation suit.
    - Step ten: Check if the singularity field generators withstood the down-time - if they didn't, continue with step 15.
    - Step eleven: Since disaster was averted you now have to ensure it doesn't repeat. If it was a powersink which caused it and if the engineering apc is wired to the same powernet, which the powersink is on, you have to remove the piece of wire which links the apc to the powernet. If it wasn't a powersink which caused it, then skip to step 14.
    - Step twelve: Grab your crowbar and pry away the tile closest to the APC.
    - Step thirteen: Use the wirecutters to cut the wire which is conecting the grid to the terminal.
    - Step fourteen: Go to the bar and tell the guys how you saved them all. Stop reading this guide here.
    - Step fifteen: GET THE FUCK OUT OF THERE!!!
    -

    - -

    Shields get damaged

    - - Step one: GET THE FUCK OUT OF THERE!!! FORGET THE WOMEN AND CHILDREN, SAVE YOURSELF!!!
    - - - "} + unique = TRUE // FALSE - Normal book, TRUE - Should not be treated as normal book, unable to be copied, unable to be modified /obj/item/book/manual/hydroponics_pod_people name = "The Human Harvest - From seed to market" icon_state ="bookHydroponicsPodPeople" - author = "Farmer John" + author = "Farmer John" // Whoever wrote the paper or book, can be changed by pen or PC. It is not automatically assigned. title = "The Human Harvest - From seed to market" + //book contents below dat = {" - - - -

    How to Clone People

    - So there's fifty dead people lying on the floor, chairs are spinning like no tomorrow and you haven't the foggiest idea of what to do? Not to worry! This guide is intended to teach you how to clone people and how to do it right, in a simple step-by-step process! If at any point of the guide you have a mental meltdown, genetics probably isn't for you and you should get a job-change as soon as possible before you're sued for malpractice. - -
      -
    1. Acquire body/head/brain
    2. -
    3. Put body/head/brain in cloning machine
    4. -
    5. Scan body/head/brain
    6. -
    7. Clone body/head/brain
    8. -
    9. Get Mannitol, Mutadone, or a clean SE for the clone
    10. -
    11. Put remains in morgue
    12. -
    13. Await cloned body
    14. -
    15. Give the clone Mannitol and Mutadone, or a clean SE
    16. -
    17. Give person clothes back
    18. -
    19. Place clone in cryo
    20. -
    21. Send person on their way
    22. -
    - -

    Step 1: Acquire a body, head, or brain

    - This is pretty much vital for the process because without a body, you cannot clone it. Usually, bodies will be brought to you, so you do not need to worry so much about this step. If you already have a body, head, or even a brain, great! Move on to the next step. - -

    Step 2: Put the body/head/brain in cloning machine

    - Grab the body, head, or brain and then put it inside the DNA modifier. - -

    Step 3: Scan the body/head/brain

    - Go onto the computer and scan the body by pressing 'Scan - '. If you're successful, they will be added to the records (note that this can be done at any time, even with living people, so that they can be cloned without a body in the event that they are lying dead on port solars and didn't turn on their suit sensors As an added bonus, they have a health monitoring implant, which'll allow you to check their vitals from their record in the cloning console)! If not, and it says 'Error: Mental interface failure.', then they have left their bodily confines and are one with the spirits. If this happens, just shout at them to get back in their body, click 'Refresh' and try scanning them again. If there's no success, threaten them with gibbing. Still no success? Skip over to Step 7 and don't continue after it, as you have an unresponsive body and it cannot be cloned. If you got 'Error: Unable to locate valid genetic data', you are trying to clone a monkey - start over. - -

    Step 4: Clone the body/head/brain

    - Now that the body has a record, click 'View Records', click the subject's name, and then click 'Clone' to start the cloning process. Congratulations! You're halfway there. Remember not to 'Eject' the cloning pod as this will kill the developing clone and you'll have to start the process again. - -

    Step 5: Get Mannitol, Mutadone, or a clean SE for the clone

    - Cloning is a finicky and unreliable process. Whilst it will most certainly bring someone back from the dead, they can have any number of nasty disabilities given to them during the cloning process! For this reason, you need Mutadone, or a clean, defect-free Structural Enzyme (SE) injection for when they're done. If you're a competent Geneticist, you will already have one ready on your working computer. If, for any reason, you do not, then eject the body from the DNA modifier (NOT THE CLONING POD) and take it next door to the Genetics research room. Put the body in one of those DNA modifiers and then go onto the console. Go into View/Edit/Transfer Buffer, find an open slot and click 'SE' to save it. Then click 'Injector' to get the SEs in syringe form. Put this in your pocket or something for when the body is done. Do note, most Genetic labs have Mannitol and Mutadone pills readily available, provided no-one has stolen them or ate them all. Don't forget most clones will also have severe brain damage as well, to fix this, give them a Mannitol pill or injection. - -

    Step 6: Put remains in morgue

    - Now that the cloning process has been initiated and you hopefully have some Mannitol, Mutadone, and a clean Structural Enzymes, you no longer need the body! Drag it to the morgue and tell the Chef over the radio that they have some fresh meat waiting for them in there, or call the Chaplain so they can prepare an impromptu funeral. To put a body in a morgue bed, simply open the tray, grab the body, put it on the open tray, then close the tray again. Use a pen to label the morgue tray 'CHEF MEAT' or 'CLONED' in order to avoid confusion. - -

    Step 7: Await cloned body

    - Now go back to the lab and wait for your patient to be cloned. This can take atleast three minutes at the least. - -

    Step 8: Give the clone Mannitol and Mutadone, or a clean SE

    - Has your patient been cloned yet? Great! As soon as the clone pops out, administer Mannitol and Mutadone. Then move onto the next step. In the event you have no Mutadone, a clean SE will suffice, but keep in mind this may irradiate the patient, causing more problems! - -

    Step 9: Give person their clothes back

    - Obviously the person will be naked after they have been cloned. Provided you weren't an irresponsible little shit, you should have protected their possessions from thieves and should be able to give them back to the patient. No matter how cruel you are, it's simply against protocol to force your patients to walk outside naked. - -

    Step 10: Place clone in cryo

    - An unfortunate problem with speedcloning technology is that the clone will suffer from severe genetic degradation upon exiting the pod. To rectify this, ensure the nearby cryogenic cells are 1.) at freezing temperatures (normally around 73.15 K), and 2.) filled with cryoxadone, or clonexadone. Once you've assured both conditions are met, place the clone in the cryogenic tube, and turn it on. Remember to set the door to 'Auto' ejection, else the clone will be stuck in cryo until someone releases them. You can also kill two birds with one stone and add Mannitol and Mutadone to the beaker, which'll heal the brain damage, along with removing any genetic defects. - -

    Step 11: Send person on their way

    - Give the patient one last check-over - make sure they don't still have any defects and that they have all their possessions. Ask them how they died, if they know, so that you can report any foul play over the radio. Once you're done, your patient is ready to go back to work! Chances are they do not have Medbay access, so you should let them out of Genetics and the Medbay main entrance. - -

    If you've gotten this far, congratulations! You have mastered the art of cloning. Now, the real problem is how to resurrect yourself after that traitor had his way with you for cloning his target. - - - - - - "} - - /obj/item/book/manual/ripley_build_and_repair name = "APLU \"Ripley\" Construction and Operation Manual" icon_state ="book" @@ -276,384 +112,9 @@

    Operation

    - Coming soon... + Please consult the Nanotrasen compendium "Robotics for Dummies". "} -/obj/item/book/manual/experimentor - name = "Mentoring your Experiments" - icon_state = "rdbook" - author = "Dr. H.P. Kritz" - title = "Mentoring your Experiments" - dat = {" - - - - -

    THE E.X.P.E.R.I-MENTOR

    - The Enhanced Xenobiological Period Extraction (and) Restoration Instructor is a machine designed to discover the secrets behind every item in existence. - With advanced technology, it can process 99.95% of items, and discover their uses and secrets. - The E.X.P.E.R.I-MENTOR is a Research apparatus that takes items, and through a process of elimination, it allows you to deduce new technological designs from them. - Due to the volatile nature of the E.X.P.E.R.I-MENTOR, there is a slight chance for malfunction, potentially causing irreparable damage to you or your environment. - However, upgrading the apparatus has proven to decrease the chances of undesirable, potentially life-threatening outcomes. - Please note that the E.X.P.E.R.I-MENTOR uses a state-of-the-art random generator, which has a larger entropy than the observable universe, - therefore it can generate wildly different results each day, therefore it is highly suggested to re-scan objects of interests frequently (e.g. each shift). - -

    BASIC PROCESS

    - The usage of the E.X.P.E.R.I-MENTOR is quite simple: -
      -
    1. Find an item with a technological background
    2. -
    3. Insert the item into the E.X.P.E.R.I-MENTOR
    4. -
    5. Cycle through each processing method of the device.
    6. -
    7. Stand back, even in case of a successful experiment, as the machine might produce undesired behaviour.
    8. -
    - -

    ADVANCED USAGE

    - The E.X.P.E.R.I-MENTOR has a variety of uses, beyond menial research work. The different results can be used to combat localised events, or even to get special items. - - The E.X.P.E.R.I-MENTOR's OBLITERATE function has the added use of transferring the destroyed item's material into a linked lathe. - - The IRRADIATE function can be used to transform items into other items, resulting in potential upgrades (or downgrades). - - Users should remember to always wear appropriate protection when using the machine, because malfunction can occur at any moment! - -

    EVENTS

    -

    GLOBAL (happens at any time):

    -
      -
    1. DETECTION MALFUNCTION - The machine's onboard sensors have malfunctioned, causing it to redefine the item's experiment type. - Produces the message: The E.X.P.E.R.I-MENTOR's onboard detection system has malfunctioned!
    2. - -
    3. IANIZATION - The machine's onboard corgi-filter has malfunctioned, causing it to produce a corgi from.. somewhere. - Produces the message: The E.X.P.E.R.I-MENTOR melts the banana, ian-izing the air around it!
    4. - -
    5. RUNTIME ERROR - The machine's onboard C4T-P processor has encountered a critical error, causing it to produce a cat from.. somewhere. - Produces the message: The E.X.P.E.R.I-MENTOR encounters a run-time error!
    6. - -
    7. B100DG0D.EXE - The machine has encountered an unknown subroutine, which has been injected into its runtime. It upgrades the held item! - Produces the message: The E.X.P.E.R.I-MENTOR improves the banana, drawing the life essence of those nearby!
    8. - -
    9. POWERSINK - The machine's PSU has tripped the charging mechanism! It consumes massive amounts of power! - Produces the message: The E.X.P.E.R.I-MENTOR begins to smoke and hiss, shaking violently!
    10. -
    -

    FAIL:

    - This event is produced when the item mismatches the selected experiment. - Produces a random message similar to: "the Banana rumbles, and shakes, the experiment was a failure!" - -

    POKE:

    -
      -
    1. WILD ARMS - The machine's gryoscopic processors malfunction, causing it to lash out at nearby people with its arms. - Produces the message: The E.X.P.E.R.I-MENTOR malfunctions and destroys the banana, lashing its arms out at nearby people!
    2. - -
    3. MISTYPE - The machine's interface has been garbled, and it switches to OBLITERATE. - Produces the message: The E.X.P.E.R.I-MENTOR malfunctions!
    4. - -
    5. THROW - The machine's spatial recognition device has shifted several meters across the room, causing it to try and repostion the item there. - Produces the message: The E.X.P.E.R.I-MENTOR malfunctions, throwing the banana!
    6. -
    -

    IRRADIATE:

    -
      -
    1. RADIATION LEAK - The machine's shield has failed, resulting in a toxic radiation leak. - Produces the message: The E.X.P.E.R.I-MENTOR malfunctions, melting the banana and leaking radiation!
    2. - -
    3. RADIATION DUMP - The machine's recycling and containment functions have failed, resulting in a dump of toxic waste around it - Produces the message: The E.X.P.E.R.I-MENTOR malfunctions, spewing toxic waste!
    4. - -
    5. MUTATION - The machine's radio-isotope level meter has malfunctioned, causing it over-irradiate the item, making it transform. - Produces the message: The E.X.P.E.R.I-MENTOR malfunctions, transforming the banana!
    6. -
    -

    GAS:

    -
      -
    1. TOXIN LEAK - The machine's filtering and vent systems have failed, resulting in a cloud of toxic gas being expelled. - Produces the message: The E.X.P.E.R.I-MENTOR destroys the banana, leaking dangerous gas!
    2. - -
    3. GAS LEAK - The machine's vent systems have failed, resulting in a cloud of harmless, but obscuring gas. - Produces the message: The E.X.P.E.R.I-MENTOR malfunctions, spewing harmless gas!
    4. - -
    5. ELECTROMAGNETIC IONS - The machine's electrolytic scanners have failed, causing a dangerous Electromagnetic reaction. - Produces the message: The E.X.P.E.R.I-MENTOR melts the banana, ionizing the air around it!
    6. -
    -

    HEAT:

    -
      -
    1. TOASTER - The machine's heating coils have come into contact with the machine's gas storage, causing a large, sudden blast of flame. - Produces the message: The E.X.P.E.R.I-MENTOR malfunctions, melting the banana and releasing a burst of flame!
    2. - -
    3. SAUNA - The machine's vent loop has sprung a leak, resulting in a large amount of superheated air being dumped around it. - Produces the message: The E.X.P.E.R.I-MENTOR malfunctions, melting the banana and leaking hot air!
    4. - -
    5. EMERGENCY VENT - The machine's temperature gauge has malfunctioned, resulting in it attempting to cool the area around it, but instead, dumping a cloud of steam. - Produces the message: The E.X.P.E.R.I-MENTOR malfunctions, activating its emergency coolant systems!
    6. -
    -

    COLD:

    -
      -
    1. FREEZER - The machine's cooling loop has sprung a leak, resulting in a cloud of super-cooled liquid being blasted into the air. - Produces the message: The E.X.P.E.R.I-MENTOR malfunctions, shattering the banana and releasing a dangerous cloud of coolant!
    2. - -
    3. FRIDGE - The machine's cooling loop has been exposed to the outside air, resulting in a large decrease in temperature. - Produces the message: The E.X.P.E.R.I-MENTOR malfunctions, shattering the banana and leaking cold air!
    4. - -
    5. SNOWSTORM - The machine's cooling loop has come into contact with the heating coils, resulting in a sudden blast of cool air. - Produces the message: The E.X.P.E.R.I-MENTOR malfunctions, releasing a flurry of chilly air as the banana pops out!
    6. -
    -

    OBLITERATE:

    -
      -
    1. IMPLOSION - The machine's pressure leveller has malfunctioned, causing it to pierce the space-time momentarily, making everything in the area fly towards it. - Produces the message: The E.X.P.E.R.I-MENTOR's crusher goes way too many levels too high, crushing right through space-time!
    2. - -
    3. DISTORTION - The machine's pressure leveller has completely disabled, resulting in a momentary space-time distortion, causing everything to fly around. - Produces the message: The E.X.P.E.R.I-MENTOR's crusher goes one level too high, crushing right into space-time!
    4. -
    - - - "} - -/obj/item/book/manual/research_and_development - name = "Research and Development 101" - icon_state = "rdbook" - author = "Dr. L. Ight" - title = "Research and Development 101" - dat = {" - - - - - -

    Science For Dummies

    - So you want to further SCIENCE? Good man/woman/thing! However, SCIENCE is a complicated process even though it's quite easy. For the most part, it's a three step process: -
      -
    1. 1) Deconstruct items in the Destructive Analyzer to advance technology or improve the design.
    2. -
    3. 2) Build unlocked designs in the Protolathe and Circuit Imprinter
    4. -
    5. 3) Repeat!
    6. -
    - - Those are the basic steps to furthing science. What do you do science with, however? Well, you have four major tools: R&D Console, the Destructive Analyzer, the Protolathe, and the Circuit Imprinter. - -

    The R&D Console

    - The R&D console is the cornerstone of any research lab. It is the central system from which the Destructive Analyzer, Protolathe, and Circuit Imprinter (your R&D systems) are controled. More on those systems in their own sections. On its own, the R&D console acts as a database for all your technological gains and new devices you discover. So long as the R&D console remains intact, you'll retain all that SCIENCE you've discovered. Protect it though, because if it gets damaged, you'll lose your data! In addition to this important purpose, the R&D console has a disk menu that lets you transfer data from the database onto disk or from the disk into the database. It also has a settings menu that lets you re-sync with nearby R&D devices (if they've become disconnected), lock the console from the unworthy, upload the data to all other R&D consoles in the network (all R&D consoles are networked by default), connect/disconnect from the network, and purge all data from the database. - NOTE: The technology list screen, circuit imprinter, and protolathe menus are accessible by non-scientists. This is intended to allow 'public' systems for the plebians to utilize some new devices. - -

    Destructive Analyzer

    - This is the source of all technology. Whenever you put a handheld object in it, it analyzes it and determines what sort of technological advancements you can discover from it. If the technology of the object is equal or higher then your current knowledge, you can destroy the object to further those sciences. Some devices (notably, some devices made from the protolathe and circuit imprinter) aren't 100% reliable when you first discover them. If these devices break down, you can put them into the Destructive Analyzer and improve their reliability rather then futher science. If their reliability is high enough ,it'll also advance their related technologies. - -

    Circuit Imprinter

    - This machine, along with the Protolathe, is used to actually produce new devices. The Circuit Imprinter takes glass and various chemicals (depends on the design) to produce new circuit boards to build new machines or computers. It can even be used to print AI modules. - -

    Protolathe

    - This machine is an advanced form of the Autolathe that produce non-circuit designs. Unlike the Autolathe, it can use processed metal, glass, solid plasma, silver, gold, and diamonds along with a variety of chemicals to produce devices. The downside is that, again, not all devices you make are 100% reliable when you first discover them. - -

    Reliability and You

    - As it has been stated, many devices when they're first discovered do not have a 100% reliablity when you first discover them. Instead, the reliablity of the device is dependent upon a base reliability value, whatever improvements to the design you've discovered through the Destructive Analyzer, and any advancements you've made with the device's source technologies. To be able to improve the reliability of a device, you have to use the device until it breaks beyond repair. Once that happens, you can analyze it in a Destructive Analyzer. Once the device reachs a certain minimum reliability, you'll gain tech advancements from it. - -

    Building a Better Machine

    - Many machines produces from circuit boards and inserted into a machine frame require a variety of parts to construct. These are parts like capacitors, batteries, matter bins, and so forth. As your knowledge of science improves, more advanced versions are unlocked. If you use these parts when constructing something, its attributes may be improved. For example, if you use an advanced matter bin when constructing an autolathe (rather then a regular one), it'll hold more materials. Experiment around with stock parts of various qualities to see how they affect the end results! Be warned, however: Tier 3 and higher stock parts don't have 100% reliability and their low reliability may affect the reliability of the end machine. - - - "} - - -/obj/item/book/manual/robotics_cyborgs - name = "Cyborgs for Dummies" - icon_state = "borgbook" - author = "XISC" - title = "Cyborgs for Dummies" - dat = {" - - - - - -

    Cyborgs for Dummies

    - -

    Chapters

    - -
      -
    1. Cyborg Related Equipment
    2. -
    3. Cyborg Modules
    4. -
    5. Cyborg Construction
    6. -
    7. Cyborg Deconstruction
    8. -
    9. Cyborg Maintenance
    10. -
    11. Cyborg Repairs
    12. -
    13. In Case of Emergency
    14. -
    - - -

    Cyborg Related Equipment

    - -

    Exosuit Fabricator

    - The Exosuit Fabricator is the most important piece of equipment related to cyborgs. It allows the construction of the core cyborg parts. Without these machines, cyborgs can not be built. It seems that they may also benefit from advanced research techniques. - -

    Cyborg Recharging Station

    - This useful piece of equipment will suck power out of the power systems to charge a cyborg's power cell back up to full charge. - -

    Robotics Control Console

    - This useful piece of equipment can be used to immobolize or destroy a cyborg. A word of warning: Cyborgs are expensive pieces of equipment, do not destroy them without good reason, or Nanotrasen may see to it that it never happens again. - - -

    Cyborg Modules

    - When a cyborg is created it picks out of an array of modules to designate its purpose. There are 6 different cyborg modules. - -

    Standard Cyborg

    - The standard cyborg module is a multi-purpose cyborg. It is equipped with various modules, allowing it to do basic tasks.
    - -

    Engineering Cyborg

    - The Engineering cyborg module comes equipped with various engineering-related tools to help with engineering-related tasks.
    - -

    Mining Cyborg

    - The Mining Cyborg module comes equipped with the latest in mining equipment. They are efficient at mining due to no need for oxygen, but their power cells limit their time in the mines. - -

    Security Cyborg

    - The Security Cyborg module is equipped with effective security measures used to apprehend and arrest criminals without harming them a bit. - -

    Janitor Cyborg

    - The Janitor Cyborg module is equipped with various cleaning-facilitating devices. - -

    Service Cyborg

    - The service cyborg module comes ready to serve your human needs. It includes various entertainment and refreshment devices. Occasionally some service cyborgs may have been referred to as "Bros" - -

    Cyborg Construction

    - Cyborg construction is a rather easy process, requiring a decent amount of metal and a few other supplies.
    The required materials to make a cyborg are: -
      -
    • Metal
    • -
    • Two Flashes
    • -
    • One Power Cell (Preferrably rated to 15000w)
    • -
    • Some electrical wires
    • -
    • One Human Brain
    • -
    • One Man-Machine Interface
    • -
    - Once you have acquired the materials, you can start on construction of your cyborg.
    To construct a cyborg, follow the steps below: -
      -
    1. Start the Exosuit Fabricators constructing all of the cyborg parts
    2. -
    3. While the parts are being constructed, take your human brain, and place it inside the Man-Machine Interface
    4. -
    5. Once you have a Robot Head, place your two flashes inside the eye sockets
    6. -
    7. Once you have your Robot Chest, wire the Robot chest, then insert the power cell
    8. -
    9. Attach all of the Robot parts to the Robot frame
    10. -
    11. Insert the Man-Machine Interface (With the Brain inside) Into the Robot Body
    12. -
    13. Congratulations! You have a new cyborg!
    14. -
    - -

    Cyborg Deconstruction

    - If you want to deconstruct a cyborg, say to remove its MMI without blowing the Cyborg to pieces, they come apart very quickly, and very safely, in a few simple steps. -
      -
    • Crowbar
    • -
    • Wrench
    • - Optional: -
    • Screwdriver
    • -
    • Wirecutters
    • -
    -
      -
    1. Begin by unlocking the Cyborg's access panel using your ID
    2. -
    3. Use your crowbar to open the Cyborg's access panel
    4. -
    5. Using your bare hands, remove the power cell from the Cyborg
    6. -
    7. Lockdown the Cyborg to disengage safety protocols
    8. -
        - Option 1: Robotics console -
      1. Use the Robotics console in the RD's office
      2. -
      3. Find the entry for your Cyborg
      4. -
      5. Press the Lockdown button on the Robotics console
      6. -
      -
        - Option 2: Lockdown wire -
      1. Use your screwdriver to expose the Cyborg's wiring
      2. -
      3. Use your wirecutters to start cutting all of the wires until the lockdown light turns off, cutting all of the wires irregardless of the lockdown light works as well
      4. -
      -
    9. Use your wrench to unfasten the Cyborg's bolts, the Cyborg will then fall apart onto the floor, the MMI will be there as well
    10. -
    - -

    Cyborg Maintenance

    - Occasionally Cyborgs may require maintenance of a couple types, this could include replacing a power cell with a charged one, or possibly maintaining the cyborg's internal wiring. - -

    Replacing a Power Cell

    - Replacing a Power cell is a common type of maintenance for cyborgs. It usually involves replacing the cell with a fully charged one, or upgrading the cell with a larger capacity cell.
    The steps to replace a cell are follows: -
      -
    1. Unlock the Cyborg's Interface by swiping your ID on it
    2. -
    3. Open the Cyborg's outer panel using a crowbar
    4. -
    5. Remove the old power cell
    6. -
    7. Insert the new power cell
    8. -
    9. Close the Cyborg's outer panel using a crowbar
    10. -
    11. Lock the Cyborg's Interface by swiping your ID on it, this will prevent non-qualified personnel from attempting to remove the power cell
    12. -
    - -

    Exposing the Internal Wiring

    - Exposing the internal wiring of a cyborg is fairly easy to do, and is mainly used for cyborg repairs.
    You can easily expose the internal wiring by following the steps below: -
      -
    1. Follow Steps 1 - 3 of "Replacing a Cyborg's Power Cell"
    2. -
    3. Open the cyborg's internal wiring panel by using a screwdriver to unsecure the panel
    4. -
    - To re-seal the cyborg's internal wiring: -
      -
    1. Use a screwdriver to secure the cyborg's internal panel
    2. -
    3. Follow steps 4 - 6 of "Replacing a Cyborg's Power Cell" to close up the cyborg
    4. -
    - -

    Cyborg Repairs

    - Occasionally a Cyborg may become damaged. This could be in the form of impact damage from a heavy or fast-travelling object, or it could be heat damage from high temperatures, or even lasers or Electromagnetic Pulses (EMPs). - -

    Dents

    - If a cyborg becomes damaged due to impact from heavy or fast-moving objects, it will become dented. Sure, a dent may not seem like much, but it can compromise the structural integrity of the cyborg, possibly causing a critical failure. - Dents in a cyborg's frame are rather easy to repair, all you need is to apply a welding tool to the dented area, and the high-tech cyborg frame will repair the dent under the heat of the welder. - -

    Excessive Heat Damage

    - If a cyborg becomes damaged due to excessive heat, it is likely that the internal wires will have been damaged. You must replace those wires to ensure that the cyborg remains functioning properly.
    To replace the internal wiring follow the steps below: -
      -
    1. Unlock the Cyborg's Interface by swiping your ID
    2. -
    3. Open the Cyborg's External Panel using a crowbar
    4. -
    5. Remove the Cyborg's Power Cell
    6. -
    7. Using a screwdriver, expose the internal wiring or the Cyborg
    8. -
    9. Replace the damaged wires inside the cyborg
    10. -
    11. Secure the internal wiring cover using a screwdriver
    12. -
    13. Insert the Cyborg's Power Cell
    14. -
    15. Close the Cyborg's External Panel using a crowbar
    16. -
    17. Lock the Cyborg's Interface by swiping your ID
    18. -
    - These repair tasks may seem difficult, but are essential to keep your cyborgs running at peak efficiency. - -

    In Case of Emergency

    - In case of emergency, there are a few steps you can take. - -

    "Rogue" Cyborgs

    - If the cyborgs seem to become "rogue", they may have non-standard laws. In this case, use extreme caution. - To repair the situation, follow these steps: -
      -
    1. Locate the nearest robotics console
    2. -
    3. Determine which cyborgs are "Rogue"
    4. -
    5. Press the lockdown button to immobolize the cyborg
    6. -
    7. Locate the cyborg
    8. -
    9. Expose the cyborg's internal wiring
    10. -
    11. Check to make sure the LawSync and AI Sync lights are lit
    12. -
    13. If they are not lit, pulse the LawSync wire using a multitool to enable the cyborg's Law Sync
    14. -
    15. Proceed to a cyborg upload console. Nanotrasen usually places these in the same location as AI uplaod consoles.
    16. -
    17. Use a "Reset" upload moduleto reset the cyborg's laws
    18. -
    19. Proceed to a Robotics Control console
    20. -
    21. Remove the lockdown on the cyborg
    22. -
    - -

    As a last resort

    - If all else fails in a case of cyborg-related emergency. There may be only one option. Using a Robotics Control console, you may have to remotely detonate the cyborg. -

    WARNING:

    Do not detonate a borg without an explicit reason for doing so. Cyborgs are expensive pieces of Nanotrasen equipment, and you may be punished for detonating them without reason. - - - - "} - - - /obj/item/book/manual/chef_recipes name = "Chef Recipes" icon_state = "cooked_book" @@ -735,101 +196,6 @@ "} - -/obj/item/book/manual/barman_recipes - name = "Barman Recipes" - icon_state = "barbook" - author = "Sir John Rose" - title = "Barman Recipes" - dat = {" - - - - - -

    Drinks for dummies

    - Heres a guide for some basic drinks. - -

    Manly Dorf:

    - Mix ale and beer into a glass. - -

    Grog:

    - Mix rum and water into a glass. - -

    Black Russian:

    - Mix vodka and kahlua into a glass. - -

    Irish Cream:

    - Mix cream and whiskey into a glass. - -

    Screwdriver:

    - Mix vodka and orange juice into a glass. - -

    Cafe Latte:

    - Mix milk and coffee into a glass. - -

    Mead:

    - Mix Enzyme, water and sugar into a glass. - -

    Gin Tonic:

    - Mix gin and tonic into a glass. - -

    Classic Martini:

    - Mix vermouth and gin into a glass. - - - - - "} - - -/obj/item/book/manual/detective - name = "The Film Noir: Proper Procedures for Investigations" - icon_state ="bookDetective" - author = "Nanotrasen" - title = "The Film Noir: Proper Procedures for Investigations" - dat = {" - - - - -

    Detective Work

    - - Between your bouts of self-narration, and drinking whiskey on the rocks, you might get a case or two to solve.
    - To have the best chance to solve your case, follow these directions: -

    -

      -
    1. Go to the crime scene.
    2. -
    3. Take your scanner and scan EVERYTHING (Yes, the doors, the tables, even the dog.)
    4. -
    5. Once you are reasonably certain you have every scrap of evidence you can use, find all possible entry points and scan them, too.
    6. -
    7. Return to your office.
    8. -
    9. Using your forensic scanning computer, scan your Scanner to upload all of your evidence into the database.
    10. -
    11. Browse through the resulting dossiers, looking for the one that either has the most complete set of prints, or the most suspicious items handled.
    12. -
    13. If you have 80% or more of the print (The print is displayed) go to step 10, otherwise continue to step 8.
    14. -
    15. Look for clues from the suit fibres you found on your perp, and go about looking for more evidence with this new information, scanning as you go.
    16. -
    17. Try to get a fingerprint card of your perp, as if used in the computer, the prints will be completed on their dossier.
    18. -
    19. Assuming you have enough of a print to see it, grab the biggest complete piece of the print and search the security records for it.
    20. -
    21. Since you now have both your dossier and the name of the person, print both out as evidence, and get security to nab your baddie.
    22. -
    23. Give yourself a pat on the back and a bottle of the ships finest vodka, you did it!
    24. -
    -

    - It really is that easy! Good luck! - - - "} - /obj/item/book/manual/nuclear name = "Fission Mailed: Nuclear Sabotage 101" icon_state ="bookNuclear" @@ -925,6 +291,13 @@ title = "Engineering Textbook" page_link = "Guide_to_engineering" +/obj/item/book/manual/wiki/engineering_singulo_tesla + name = "Singularity and Tesla for Dummies" + icon_state ="bookEngineeringSingularitySafety" + author = "Engineering Encyclopedia" + title = "Singularity and Tesla for Dummies" + page_link = "Singularity_and_Tesla_engines" + /obj/item/book/manual/wiki/security_space_law name = "Space Law" desc = "A set of Nanotrasen guidelines for keeping law and order on their space stations." @@ -957,3 +330,123 @@ author = "Engineering Encyclopedia" title = "Hacking" page_link = "Hacking" + +/obj/item/book/manual/wiki/detective + name = "The Film Noir: Proper Procedures for Investigations" + icon_state ="bookDetective" + author = "Nanotrasen" + title = "The Film Noir: Proper Procedures for Investigations" + page_link = "Detective" + +/obj/item/book/manual/wiki/barman_recipes + name = "Barman Recipes: Mixing Drinks and Changing Lives" + icon_state = "barbook" + author = "Sir John Rose" + title = "Barman Recipes: Mixing Drinks and Changing Lives" + page_link = "Guide_to_food_and_drinks" + +/obj/item/book/manual/wiki/robotics_cyborgs + name = "Robotics for Dummies" + icon_state = "borgbook" + author = "XISC" + title = "Robotics for Dummies" + page_link = "Guide_to_robotics" + +/obj/item/book/manual/wiki/research_and_development + name = "Research and Development 101" + icon_state = "rdbook" + author = "Dr. L. Ight" + title = "Research and Development 101" + page_link = "Guide_to_Research_and_Development" + +/obj/item/book/manual/wiki/experimentor + name = "Mentoring your Experiments" + icon_state = "rdbook" + author = "Dr. H.P. Kritz" + title = "Mentoring your Experiments" + page_link = "Experimentor" + +/obj/item/book/manual/wiki/medical_cloning + name = "Cloning techniques of the 26th century" + icon_state ="bookCloning" + author = "Medical Journal, volume 3" + title = "Cloning techniques of the 26th century" + page_link = "Guide_to_genetics#Cloning" + +/obj/item/book/manual/wiki/cooking_to_serve_man + name = "To Serve Man" + desc = "It's a cookbook!" + icon_state ="cooked_book" + author = "the Kanamitan Empire" + title = "To Serve Man" + page_link = "Guide_to_food_and_drinks" + +/obj/item/book/manual/wiki/circuitry + name = "Circuitry for Dummies" + icon_state = "book1" + author = "Dr. Hans Asperger" + title = "Circuitry for Dummies" + page_link = "Guide_to_circuits" + +/obj/item/book/manual/wiki/tcomms + name = "Subspace Telecommunications And You" + icon_state = "book3" + author = "Engineering Encyclopedia" + title = "Subspace Telecommunications And You" + page_link = "Guide_to_Telecommunications" + +/obj/item/book/manual/wiki/atmospherics + name = "Lexica Atmosia" + icon_state = "book5" + author = "the City-state of Atmosia" + title = "Lexica Atmosia" + page_link = "Guide_to_Atmospherics" + +/obj/item/book/manual/wiki/medicine + name = "Medical Space Compendium, Volume 638" + icon_state = "book8" + author = "Medical Journal" + title = "Medical Space Compendium, Volume 638" + page_link = "Guide_to_medicine" + +/obj/item/book/manual/wiki/surgery + name = "Brain Surgery for Dummies" + icon_state = "book4" + author = "Dr. F. Fran" + title = "Brain Surgery for Dummies" + page_link = "Surgery" + +/obj/item/book/manual/wiki/grenades + name = "DIY Chemical Grenades" + icon_state = "book2" + author = "W. Powell" + title = "DIY Chemical Grenades" + page_link = "Grenade" + +/obj/item/book/manual/wiki/toxins + name = "Toxins or: How I Learned to Stop Worrying and Love the Maxcap" + icon_state = "book6" + author = "Cuban Pete" + title = "Toxins or: How I Learned to Stop Worrying and Love the Maxcap" + page_link = "Guide_to_toxins" + +/obj/item/book/manual/wiki/toxins/suicide_act(mob/user) + var/mob/living/carbon/human/H = user + user.visible_message("[user] starts dancing to the Rhumba Beat! It looks like [user.p_theyre()] trying to commit suicide!") + playsound(loc, 'sound/effects/spray.ogg', 10, 1, -3) + if (!QDELETED(H)) + H.emote("spin") + sleep(20) + for(var/obj/item/W in H) + H.dropItemToGround(W) + if(prob(50)) + step(W, pick(GLOB.alldirs)) + H.add_trait(TRAIT_DISFIGURED, TRAIT_GENERIC) + H.bleed_rate = 5 + H.gib_animation() + sleep(3) + H.adjustBruteLoss(1000) //to make the body super-bloody + H.spawn_gibs() + H.spill_organs() + H.spread_bodyparts() + return (BRUTELOSS) diff --git a/code/game/objects/items/melee/misc.dm b/code/game/objects/items/melee/misc.dm index 9ad4174b3a..26712c2431 100644 --- a/code/game/objects/items/melee/misc.dm +++ b/code/game/objects/items/melee/misc.dm @@ -112,7 +112,7 @@ limbs_to_dismember = arms + legs if(holding_bodypart) limbs_to_dismember += holding_bodypart - + var/speedbase = abs((4 SECONDS) / limbs_to_dismember.len) for(bodypart in limbs_to_dismember) i++ @@ -185,7 +185,7 @@ return playsound(get_turf(src), 'sound/effects/woodhit.ogg', 75, 1, -1) target.Knockdown(60) - add_logs(user, target, "stunned", src) + log_combat(user, target, "stunned", src) src.add_fingerprint(user) target.visible_message("[user] has knocked down [target] with [src]!", \ "[user] has knocked down [target] with [src]!") @@ -286,11 +286,11 @@ consume_turf(T) /obj/item/melee/supermatter_sword/afterattack(target, mob/user, proximity_flag) + . = ..() if(user && target == user) user.dropItemToGround(src) if(proximity_flag) consume_everything(target) - ..() /obj/item/melee/supermatter_sword/throw_impact(target) ..() @@ -322,13 +322,13 @@ /obj/item/melee/supermatter_sword/suicide_act(mob/user) user.visible_message("[user] touches [src]'s blade. It looks like [user.p_theyre()] tired of waiting for the radiation to kill [user.p_them()]!") user.dropItemToGround(src, TRUE) - shard.CollidedWith(user) + shard.Bumped(user) /obj/item/melee/supermatter_sword/proc/consume_everything(target) if(isnull(target)) shard.Consume() else if(!isturf(target)) - shard.CollidedWith(target) + shard.Bumped(target) else consume_turf(target) @@ -357,14 +357,14 @@ force = 15 w_class = WEIGHT_CLASS_NORMAL attack_verb = list("flogged", "whipped", "lashed", "disciplined") - hitsound = 'sound/weapons/chainhit.ogg' + hitsound = 'sound/weapons/whip.ogg' /obj/item/melee/curator_whip/afterattack(target, mob/user, proximity_flag) + . = ..() if(ishuman(target) && proximity_flag) var/mob/living/carbon/human/H = target H.drop_all_held_items() H.visible_message("[user] disarms [H]!", "[user] disarmed you!") - ..() /obj/item/melee/roastingstick name = "advanced roasting stick" @@ -446,6 +446,7 @@ update_icon() /obj/item/melee/roastingstick/afterattack(atom/target, mob/user, proximity) + . = ..() if (!on) return if (is_type_in_typecache(target, ovens)) diff --git a/code/game/objects/items/mop.dm b/code/game/objects/items/mop.dm index 3601c43651..c5e92c4706 100644 --- a/code/game/objects/items/mop.dm +++ b/code/game/objects/items/mop.dm @@ -35,6 +35,7 @@ /obj/item/mop/afterattack(atom/A, mob/user, proximity) + . = ..() if(!proximity) return diff --git a/code/game/objects/items/paint.dm b/code/game/objects/items/paint.dm index dd6fc77906..c81fd08274 100644 --- a/code/game/objects/items/paint.dm +++ b/code/game/objects/items/paint.dm @@ -79,6 +79,7 @@ /obj/item/paint/afterattack(turf/target, mob/user, proximity) + . = ..() if(!proximity) return if(paintleft <= 0) @@ -96,6 +97,7 @@ icon_state = "paint_neutral" /obj/item/paint/paint_remover/afterattack(turf/target, mob/user, proximity) + . = ..() if(!proximity) return if(istype(target) && target.color != initial(target.color)) diff --git a/code/game/objects/items/pinpointer.dm b/code/game/objects/items/pinpointer.dm index d6262c10a5..c4ad324a2c 100644 --- a/code/game/objects/items/pinpointer.dm +++ b/code/game/objects/items/pinpointer.dm @@ -143,9 +143,3 @@ target = null if(!target) //target can be set to null from above code, or elsewhere active = FALSE - -/obj/item/pinpointer/process() - if(!active) - return PROCESS_KILL - scan_for_target() - update_icon() diff --git a/code/game/objects/items/plushes.dm b/code/game/objects/items/plushes.dm index eec6c00834..9b109b5342 100644 --- a/code/game/objects/items/plushes.dm +++ b/code/game/objects/items/plushes.dm @@ -461,8 +461,8 @@ P.clashing = FALSE /obj/item/toy/plush/narplush - name = "nar'sie plushie" - desc = "A small stuffed doll of the elder god Nar'Sie. Who thought this was a good children's toy?" + name = "\improper Nar'Sie plushie" + desc = "A small stuffed doll of the elder goddess Nar'Sie. Who thought this was a good children's toy?" icon_state = "narplush" var/clashing var/is_invoker = TRUE @@ -475,7 +475,7 @@ P.clash_of_the_plushies(src) /obj/item/toy/plush/narplush/hugbox - desc = "A small stuffed doll of the elder god Nar'Sie. Who thought this was a good children's toy? It looks sad." + desc = "A small stuffed doll of the elder goddess Nar'Sie. Who thought this was a good children's toy? It looks sad." is_invoker = FALSE /obj/item/toy/plush/lizardplushie diff --git a/code/game/objects/items/pneumaticCannon.dm b/code/game/objects/items/pneumaticCannon.dm index 96d64bac45..d37ec0376a 100644 --- a/code/game/objects/items/pneumaticCannon.dm +++ b/code/game/objects/items/pneumaticCannon.dm @@ -34,6 +34,7 @@ var/selfcharge = FALSE trigger_guard = TRIGGER_GUARD_NORMAL + /obj/item/pneumatic_cannon/Initialize() . = ..() if(selfcharge) @@ -97,6 +98,8 @@ load_item(IW, user) /obj/item/pneumatic_cannon/proc/can_load_item(obj/item/I, mob/user) + if(!istype(I)) //Players can't load non items, this allows for admin varedit inserts. + return TRUE if(allowed_typecache && !is_type_in_typecache(I, allowed_typecache)) if(user) to_chat(user, "[I] won't fit into [src]!") @@ -125,6 +128,7 @@ return TRUE /obj/item/pneumatic_cannon/afterattack(atom/target, mob/living/user, flag, params) + . = ..() if(flag && user.a_intent == INTENT_HARM) //melee attack return if(!istype(user)) @@ -159,9 +163,9 @@ if(!discharge) user.visible_message("[user] fires \the [src]!", \ "You fire \the [src]!") - add_logs(user, target, "fired at", src) + log_combat(user, target, "fired at", src) var/turf/T = get_target(target, get_turf(src)) - playsound(src.loc, 'sound/weapons/sonic_jackhammer.ogg', 50, 1) + playsound(src, 'sound/weapons/sonic_jackhammer.ogg', 50, 1) fire_items(T, user) if(pressureSetting >= 3 && iscarbon(user)) var/mob/living/carbon/C = user @@ -223,31 +227,31 @@ /obj/item/pneumatic_cannon/proc/updateTank(obj/item/tank/internals/thetank, removing = 0, mob/living/carbon/human/user) if(removing) - if(!src.tank) + if(!tank) return to_chat(user, "You detach \the [thetank] from \the [src].") - src.tank.forceMove(user.drop_location()) + tank.forceMove(user.drop_location()) user.put_in_hands(tank) - src.tank = null + tank = null if(!removing) - if(src.tank) + if(tank) to_chat(user, "\The [src] already has a tank.") return if(!user.transferItemToLoc(thetank, src)) return to_chat(user, "You hook \the [thetank] up to \the [src].") - src.tank = thetank - src.update_icons() + tank = thetank + update_icons() /obj/item/pneumatic_cannon/proc/update_icons() - src.cut_overlays() + cut_overlays() if(!tank) return add_overlay(tank.icon_state) - src.update_icon() + update_icon() /obj/item/pneumatic_cannon/proc/fill_with_type(type, amount) - if(!ispath(type, /obj/item)) + if(!ispath(type, /obj) && !ispath(type, /mob)) return FALSE var/loaded = 0 for(var/i in 1 to amount) diff --git a/code/game/objects/items/powerfist.dm b/code/game/objects/items/powerfist.dm index 5346d6e9cc..f02e92bb3c 100644 --- a/code/game/objects/items/powerfist.dm +++ b/code/game/objects/items/powerfist.dm @@ -89,7 +89,7 @@ target.throw_at(throw_target, 5 * fisto_setting, 0.2) - add_logs(user, target, "power fisted", src) + log_combat(user, target, "power fisted", src) user.changeNext_move(CLICK_CD_MELEE * click_delay) diff --git a/code/game/objects/items/religion.dm b/code/game/objects/items/religion.dm index 1159adf767..a80aa1be60 100644 --- a/code/game/objects/items/religion.dm +++ b/code/game/objects/items/religion.dm @@ -30,7 +30,7 @@ "You raise [src] skywards, inspiring your allies!") playsound(src, "rustle", 100, FALSE) if(warcry) - user.say("[warcry]") + user.say("[warcry]", forced="banner") var/old_transform = user.transform user.transform *= 1.2 animate(user, transform = old_transform, time = 10) @@ -288,6 +288,7 @@ /obj/item/godstaff/afterattack(atom/target, mob/user, proximity_flag, click_parameters) + . = ..() if(staffcooldown + staffwait > world.time) return user.visible_message("[user] chants deeply and waves [user.p_their()] staff!") diff --git a/code/game/objects/items/robot/ai_upgrades.dm b/code/game/objects/items/robot/ai_upgrades.dm index 63906ff5ba..7f7780d3a4 100644 --- a/code/game/objects/items/robot/ai_upgrades.dm +++ b/code/game/objects/items/robot/ai_upgrades.dm @@ -10,6 +10,7 @@ /obj/item/malf_upgrade/afterattack(mob/living/silicon/ai/AI, mob/user) + . = ..() if(!istype(AI)) return if(AI.malf_picker) @@ -30,6 +31,7 @@ icon_state = "datadisk3" /obj/item/surveillance_upgrade/afterattack(mob/living/silicon/ai/AI, mob/user) + . = ..() if(!istype(AI)) return if(AI.eyeobj) diff --git a/code/game/objects/items/robot/robot_items.dm b/code/game/objects/items/robot/robot_items.dm index ecf7abe1d3..d7f0b03837 100644 --- a/code/game/objects/items/robot/robot_items.dm +++ b/code/game/objects/items/robot/robot_items.dm @@ -30,7 +30,7 @@ playsound(loc, 'sound/weapons/egloves.ogg', 50, 1, -1) - add_logs(user, M, "stunned", src, "(INTENT: [uppertext(user.a_intent)])") + log_combat(user, M, "stunned", src, "(INTENT: [uppertext(user.a_intent)])") /obj/item/borg/cyborghug name = "hugging module" @@ -172,6 +172,7 @@ update_icon() /obj/item/borg/charger/afterattack(obj/item/target, mob/living/silicon/robot/user, proximity_flag) + . = ..() if(!proximity_flag || !iscyborg(user)) return if(mode == "draw") @@ -448,6 +449,7 @@ check_amount() /obj/item/borg/lollipop/afterattack(atom/target, mob/living/user, proximity, click_params) + . = ..() check_amount() if(iscyborg(user)) var/mob/living/silicon/robot/R = user diff --git a/code/game/objects/items/robot/robot_parts.dm b/code/game/objects/items/robot/robot_parts.dm index 929632980b..cd2ccff170 100644 --- a/code/game/objects/items/robot/robot_parts.dm +++ b/code/game/objects/items/robot/robot_parts.dm @@ -105,6 +105,10 @@ return TRUE /obj/item/robot_suit/screwdriver_act(mob/living/user, obj/item/I) //Swaps the power cell if you're holding a new one in your other hand. + . = ..() + if(.) + return TRUE + if(!chest) //can't remove a cell if there's no chest to remove it from. to_chat(user, "[src] has no attached torso.") return diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm index 9e12bbd1d7..3a27ac4e17 100644 --- a/code/game/objects/items/robot/robot_upgrades.dm +++ b/code/game/objects/items/robot/robot_upgrades.dm @@ -79,40 +79,7 @@ to_chat(user, "There's no room for another VTEC unit!") return FALSE - //Citadel change - makes vtecs give an ability rather than reducing the borg's speed instantly - R.AddAbility(new/obj/effect/proc_holder/silicon/cyborg/vtecControl) - - -/obj/effect/proc_holder/silicon/cyborg/vtecControl - name = "vTec Control" - desc = "Allows finer-grained control of the vTec speed boost." - action_icon = 'icons/mob/actions.dmi' - action_icon_state = "Chevron_State_0" - - var/currentState = 0 - var/maxReduction = 2 - - -/obj/effect/proc_holder/silicon/cyborg/vtecControl/Click(mob/living/silicon/robot/user) - - var/mob/living/silicon/robot/self = usr - - currentState = (currentState + 1) % 3 - - if(usr) - switch(currentState) - if (0) - self.speed += maxReduction - if (1) - self.speed -= maxReduction*0.5 - if (2) - self.speed -= maxReduction*0.5 - - action.button_icon_state = "Chevron_State_[currentState]" - action.UpdateButtonIcon() - - return - + R.speed = -2 // Gotta go fast. /obj/item/borg/upgrade/vtec/deactivate(mob/living/silicon/robot/R, user = usr) . = ..() @@ -228,7 +195,7 @@ /obj/item/borg/upgrade/tboh name = "janitor cyborg trash bag of holding" - desc = "A trash bag of holding replace for the janiborgs standard trash bag." + desc = "A trash bag of holding replacement for the janiborg's standard trash bag." icon_state = "cyborg_upgrade3" require_module = 1 module_type = /obj/item/robot_module/janitor @@ -255,7 +222,7 @@ /obj/item/borg/upgrade/amop name = "janitor cyborg advanced mop" - desc = "An advanced mop replacement from the janiborgs standard mop." + desc = "An advanced mop replacement for the janiborg's standard mop." icon_state = "cyborg_upgrade3" require_module = 1 module_type = /obj/item/robot_module/janitor @@ -493,7 +460,7 @@ /obj/item/borg/upgrade/defib name = "medical cyborg defibrillator" - desc = "An upgrade to the Medical module, installing a builtin \ + desc = "An upgrade to the Medical module, installing a built-in \ defibrillator, for on the scene revival." icon_state = "cyborg_upgrade3" require_module = 1 @@ -512,6 +479,28 @@ var/obj/item/twohanded/shockpaddles/cyborg/S = locate() in R.module R.module.remove_module(S, TRUE) +/obj/item/borg/upgrade/processor + name = "medical cyborg surgical processor" + desc = "An upgrade to the Medical module, installing a processor \ + capable of scanning surgery disks and carrying \ + out procedures" + icon_state = "cyborg_upgrade3" + require_module = 1 + module_type = /obj/item/robot_module/medical + +/obj/item/borg/upgrade/processor/action(mob/living/silicon/robot/R, user = usr) + . = ..() + if(.) + var/obj/item/surgical_processor/SP = new(R.module) + R.module.basic_modules += SP + R.module.add_module(SP, FALSE, TRUE) + +/obj/item/borg/upgrade/processor/deactivate(mob/living/silicon/robot/R, user = usr) + . = ..() + if (.) + var/obj/item/surgical_processor/SP = locate() in R.module + R.module.remove_module(SP, TRUE) + /obj/item/borg/upgrade/ai name = "B.O.R.I.S. module" desc = "Bluespace Optimized Remote Intelligence Synchronization. An uplink device which takes the place of an MMI in cyborg endoskeletons, creating a robotic shell controlled by an AI." diff --git a/code/game/objects/items/singularityhammer.dm b/code/game/objects/items/singularityhammer.dm index 11248aad50..1fe57d151f 100644 --- a/code/game/objects/items/singularityhammer.dm +++ b/code/game/objects/items/singularityhammer.dm @@ -57,6 +57,7 @@ return /obj/item/twohanded/singularityhammer/afterattack(atom/A as mob|obj|turf|area, mob/user, proximity) + . = ..() if(!proximity) return if(wielded) diff --git a/code/game/objects/items/stacks/sheets/glass.dm b/code/game/objects/items/stacks/sheets/glass.dm index a6e2d255fb..77b669ec52 100644 --- a/code/game/objects/items/stacks/sheets/glass.dm +++ b/code/game/objects/items/stacks/sheets/glass.dm @@ -268,6 +268,7 @@ GLOBAL_LIST_INIT(plastitaniumglass_recipes, list( pixel_y = rand(-5, 5) /obj/item/shard/afterattack(atom/A as mob|obj, mob/user, proximity) + . = ..() if(!proximity || !(src in user)) return if(isturf(A)) diff --git a/code/game/objects/items/stacks/sheets/leather.dm b/code/game/objects/items/stacks/sheets/leather.dm index 0031839eff..f9d4878fab 100644 --- a/code/game/objects/items/stacks/sheets/leather.dm +++ b/code/game/objects/items/stacks/sheets/leather.dm @@ -32,13 +32,22 @@ GLOBAL_LIST_INIT(human_recipes, list( \ icon_state = "sheet-corgi" item_state = "sheet-corgi" + +GLOBAL_LIST_INIT(gondola_recipes, list ( \ + new/datum/stack_recipe("gondola mask", /obj/item/clothing/mask/gondola, 1), \ + new/datum/stack_recipe("gondola suit", /obj/item/clothing/under/gondola, 2), \ + )) + /obj/item/stack/sheet/animalhide/gondola name = "gondola hide" - desc = "The extremely valuable by-product of gondola hunting." + desc = "The extremely valuable product of gondola hunting." singular_name = "gondola hide piece" icon_state = "sheet-gondola" item_state = "sheet-gondola" +/obj/item/stack/sheet/animalhide/gondola/Initialize(mapload, new_amount, merge = TRUE) + recipes = GLOB.gondola_recipes + return ..() GLOBAL_LIST_INIT(corgi_recipes, list ( \ new/datum/stack_recipe("corgi costume", /obj/item/clothing/suit/hooded/ian_costume, 3), \ diff --git a/code/game/objects/items/stacks/sheets/mineral.dm b/code/game/objects/items/stacks/sheets/mineral.dm index 8d1562826c..7df165461b 100644 --- a/code/game/objects/items/stacks/sheets/mineral.dm +++ b/code/game/objects/items/stacks/sheets/mineral.dm @@ -46,6 +46,7 @@ GLOBAL_LIST_INIT(sandstone_recipes, list ( \ throw_range = 5 materials = list(MAT_GLASS=MINERAL_MATERIAL_AMOUNT) sheettype = "sandstone" + merge_type = /obj/item/stack/sheet/mineral/sandstone /obj/item/stack/sheet/mineral/sandstone/Initialize(mapload, new_amount, merge = TRUE) recipes = GLOB.sandstone_recipes @@ -64,6 +65,7 @@ GLOBAL_LIST_INIT(sandstone_recipes, list ( \ singular_name = "sandbag" layer = LOW_ITEM_LAYER novariants = TRUE + merge_type = /obj/item/stack/sheet/mineral/sandbags GLOBAL_LIST_INIT(sandbag_recipes, list ( \ new/datum/stack_recipe("sandbags", /obj/structure/barricade/sandbags, 1, time = 25, one_per_turf = 1, on_floor = 1), \ @@ -105,6 +107,7 @@ GLOBAL_LIST_INIT(sandbag_recipes, list ( \ novariants = TRUE grind_results = list("carbon" = 20) point_value = 25 + merge_type = /obj/item/stack/sheet/mineral/diamond GLOBAL_LIST_INIT(diamond_recipes, list ( \ new/datum/stack_recipe("diamond door", /obj/structure/mineral_door/transparent/diamond, 10, one_per_turf = 1, on_floor = 1), \ @@ -131,6 +134,7 @@ GLOBAL_LIST_INIT(diamond_recipes, list ( \ novariants = TRUE grind_results = list("uranium" = 20) point_value = 20 + merge_type = /obj/item/stack/sheet/mineral/uranium GLOBAL_LIST_INIT(uranium_recipes, list ( \ new/datum/stack_recipe("uranium door", /obj/structure/mineral_door/uranium, 10, one_per_turf = 1, on_floor = 1), \ @@ -157,6 +161,7 @@ GLOBAL_LIST_INIT(uranium_recipes, list ( \ materials = list(MAT_PLASMA=MINERAL_MATERIAL_AMOUNT) grind_results = list("plasma" = 20) point_value = 20 + merge_type = /obj/item/stack/sheet/mineral/plasma /obj/item/stack/sheet/mineral/plasma/suicide_act(mob/living/carbon/user) user.visible_message("[user] begins licking \the [src]! It looks like [user.p_theyre()] trying to commit suicide!") @@ -197,6 +202,7 @@ GLOBAL_LIST_INIT(plasma_recipes, list ( \ materials = list(MAT_GOLD=MINERAL_MATERIAL_AMOUNT) grind_results = list("gold" = 20) point_value = 20 + merge_type = /obj/item/stack/sheet/mineral/gold GLOBAL_LIST_INIT(gold_recipes, list ( \ new/datum/stack_recipe("golden door", /obj/structure/mineral_door/gold, 10, one_per_turf = 1, on_floor = 1), \ @@ -225,6 +231,7 @@ GLOBAL_LIST_INIT(gold_recipes, list ( \ materials = list(MAT_SILVER=MINERAL_MATERIAL_AMOUNT) grind_results = list("silver" = 20) point_value = 20 + merge_type = /obj/item/stack/sheet/mineral/silver GLOBAL_LIST_INIT(silver_recipes, list ( \ new/datum/stack_recipe("silver door", /obj/structure/mineral_door/silver, 10, one_per_turf = 1, on_floor = 1), \ @@ -253,6 +260,7 @@ GLOBAL_LIST_INIT(silver_recipes, list ( \ novariants = TRUE grind_results = list("banana" = 20) point_value = 50 + merge_type = /obj/item/stack/sheet/mineral/bananium GLOBAL_LIST_INIT(bananium_recipes, list ( \ new/datum/stack_recipe("bananium tile", /obj/item/stack/tile/mineral/bananium, 1, 4, 20), \ @@ -279,6 +287,7 @@ GLOBAL_LIST_INIT(bananium_recipes, list ( \ sheettype = "titanium" materials = list(MAT_TITANIUM=MINERAL_MATERIAL_AMOUNT) point_value = 20 + merge_type = /obj/item/stack/sheet/mineral/titanium GLOBAL_LIST_INIT(titanium_recipes, list ( \ new/datum/stack_recipe("titanium tile", /obj/item/stack/tile/mineral/titanium, 1, 4, 20), \ @@ -308,6 +317,7 @@ GLOBAL_LIST_INIT(titanium_recipes, list ( \ sheettype = "plastitanium" materials = list(MAT_TITANIUM=MINERAL_MATERIAL_AMOUNT, MAT_PLASMA=MINERAL_MATERIAL_AMOUNT) point_value = 45 + merge_type = /obj/item/stack/sheet/mineral/plastitanium GLOBAL_LIST_INIT(plastitanium_recipes, list ( \ new/datum/stack_recipe("plastitanium tile", /obj/item/stack/tile/mineral/plastitanium, 1, 4, 20), \ @@ -329,6 +339,7 @@ GLOBAL_LIST_INIT(plastitanium_recipes, list ( \ force = 1 throwforce = 2 grind_results = list("ice" = 20) + merge_type = /obj/item/stack/sheet/mineral/snow GLOBAL_LIST_INIT(snow_recipes, list ( \ new/datum/stack_recipe("Snow Wall", /turf/closed/wall/mineral/snow, 5, one_per_turf = 1, on_floor = 1), \ @@ -354,6 +365,7 @@ GLOBAL_LIST_INIT(adamantine_recipes, list( icon_state = "sheet-adamantine" item_state = "sheet-adamantine" singular_name = "adamantine sheet" + merge_type = /obj/item/stack/sheet/mineral/adamantine /obj/item/stack/sheet/mineral/adamantine/Initialize(mapload, new_amount, merge = TRUE) recipes = GLOB.adamantine_recipes @@ -368,6 +380,7 @@ GLOBAL_LIST_INIT(adamantine_recipes, list( item_state = "sheet-mythril" singular_name = "mythril sheet" novariants = TRUE + merge_type = /obj/item/stack/sheet/mineral/mythril /* * Alien Alloy @@ -379,6 +392,7 @@ GLOBAL_LIST_INIT(adamantine_recipes, list( item_state = "sheet-abductor" singular_name = "alien alloy sheet" sheettype = "abductor" + merge_type = /obj/item/stack/sheet/mineral/abductor GLOBAL_LIST_INIT(abductor_recipes, list ( \ new/datum/stack_recipe("alien bed", /obj/structure/bed/abductor, 2, one_per_turf = 1, on_floor = 1), \ diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm index 014e4738b0..bbace70bec 100644 --- a/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -20,7 +20,7 @@ GLOBAL_LIST_INIT(metal_recipes, list ( \ new/datum/stack_recipe("bar stool", /obj/structure/chair/stool/bar, one_per_turf = TRUE, on_floor = TRUE), \ new/datum/stack_recipe("chair", /obj/structure/chair, one_per_turf = TRUE, on_floor = TRUE), \ new/datum/stack_recipe("bed", /obj/structure/bed, 2, one_per_turf = TRUE, on_floor = TRUE), \ - //CIT CHANGE - adds sofas to metal recipe list + //CIT CHANGE - adds sofas to metal recipe list new/datum/stack_recipe_list("sofas", list( \ new /datum/stack_recipe("sofa (middle)", /obj/structure/chair/sofa, one_per_turf = TRUE, on_floor = TRUE), \ new /datum/stack_recipe("sofa (left)", /obj/structure/chair/sofa/left, one_per_turf = TRUE, on_floor = TRUE), \ @@ -412,6 +412,7 @@ GLOBAL_LIST_INIT(brass_recipes, list ( \ turf_type = /turf/open/floor/clockwork novariants = FALSE grind_results = list("iron" = 5, "teslium" = 15) + merge_type = /obj/item/stack/tile/brass /obj/item/stack/tile/brass/narsie_act() new /obj/item/stack/sheet/runed_metal(loc, amount) @@ -461,6 +462,7 @@ GLOBAL_LIST_INIT(bronze_recipes, list ( \ turf_type = /turf/open/floor/bronze novariants = FALSE grind_results = list("iron" = 5, "copper" = 3) //we have no "tin" reagent so this is the closest thing + merge_type = /obj/item/stack/tile/bronze /obj/item/stack/tile/bronze/attack_self(mob/living/user) if(is_servant_of_ratvar(user)) //still lets them build with it, just gives a message @@ -513,6 +515,7 @@ GLOBAL_LIST_INIT(bronze_recipes, list ( \ throw_speed = 1 throw_range = 3 grind_results = list("carbon" = 10) + merge_type = /obj/item/stack/sheet/bone GLOBAL_LIST_INIT(plastic_recipes, list( new /datum/stack_recipe("plastic flaps", /obj/structure/plasticflaps, 5, one_per_turf = TRUE, on_floor = TRUE, time = 40), \ @@ -552,6 +555,7 @@ new /datum/stack_recipe("paper frame door", /obj/structure/mineral_door/paperfra item_state = "sheet-paper" merge_type = /obj/item/stack/sheet/paperframes resistance_flags = FLAMMABLE + merge_type = /obj/item/stack/sheet/paperframes /obj/item/stack/sheet/paperframes/Initialize() recipes = GLOB.paperframe_recipes diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm index 829cb6c3f1..34ae4cb5ef 100644 --- a/code/game/objects/items/stacks/stack.dm +++ b/code/game/objects/items/stacks/stack.dm @@ -231,7 +231,9 @@ to_chat(usr, "You haven't got enough [src] to build \the [R.title]!") return FALSE var/turf/T = get_turf(usr) - if(R.window_checks && !valid_window_location(T, usr.dir)) + + var/obj/D = R.result_type + if(R.window_checks && !valid_window_location(T, initial(D.dir) == FULLTILE_WINDOW_DIR ? FULLTILE_WINDOW_DIR : usr.dir)) to_chat(usr, "The [R.title] won't fit here!") return FALSE if(R.one_per_turf && (locate(R.result_type) in T)) @@ -246,6 +248,10 @@ continue if(istype(AM,/obj/structure/table)) continue + if(istype(AM,/obj/structure/window)) + var/obj/structure/window/W = AM + if(!W.fulltile) + continue if(AM.density) to_chat(usr, "Theres a [AM.name] here. You cant make a [R.title] here!") return FALSE diff --git a/code/game/objects/items/stacks/telecrystal.dm b/code/game/objects/items/stacks/telecrystal.dm index ec1e7b8773..c1fb396529 100644 --- a/code/game/objects/items/stacks/telecrystal.dm +++ b/code/game/objects/items/stacks/telecrystal.dm @@ -21,6 +21,7 @@ return ..() /obj/item/stack/telecrystal/afterattack(obj/item/I, mob/user, proximity) + . = ..() if(istype(I, /obj/item/cartridge/virus/frame)) var/obj/item/cartridge/virus/frame/cart = I if(!cart.charges) @@ -29,8 +30,6 @@ cart.telecrystals += amount use(amount) to_chat(user, "You slot [src] into [cart]. The next time it's used, it will also give telecrystals.") - else - return ..() /obj/item/stack/telecrystal/five amount = 5 diff --git a/code/game/objects/items/stacks/tiles/tile_types.dm b/code/game/objects/items/stacks/tiles/tile_types.dm index 2231207556..907b26c75c 100644 --- a/code/game/objects/items/stacks/tiles/tile_types.dm +++ b/code/game/objects/items/stacks/tiles/tile_types.dm @@ -100,6 +100,9 @@ turf_type = /turf/open/floor/carpet resistance_flags = FLAMMABLE +/obj/item/stack/tile/carpet/fifty + amount = 50 + /obj/item/stack/tile/carpet/black name = "black carpet" icon_state = "tile-carpet-black" diff --git a/code/game/objects/items/stacks/wrap.dm b/code/game/objects/items/stacks/wrap.dm index 3e5c9c2ba9..b438c863a8 100644 --- a/code/game/objects/items/stacks/wrap.dm +++ b/code/game/objects/items/stacks/wrap.dm @@ -61,6 +61,7 @@ return 0 /obj/item/stack/packageWrap/afterattack(obj/target, mob/user, proximity) + . = ..() if(!proximity) return if(!istype(target)) @@ -111,7 +112,7 @@ return user.visible_message("[user] wraps [target].") - user.log_message("Has used [name] on [target]", INDIVIDUAL_ATTACK_LOG) + user.log_message("has used [name] on [key_name(target)]", LOG_ATTACK, color="blue") /obj/item/stack/packageWrap/use(used, transfer = FALSE) var/turf/T = get_turf(src) diff --git a/code/game/objects/items/storage/bags.dm b/code/game/objects/items/storage/bags.dm index 11dbf727f1..aa0c504bb4 100644 --- a/code/game/objects/items/storage/bags.dm +++ b/code/game/objects/items/storage/bags.dm @@ -119,7 +119,7 @@ if (mobhook && mobhook.parent != user) QDEL_NULL(mobhook) if (!mobhook) - mobhook = user.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED), CALLBACK(src, .proc/Pickup_ores, user)) + mobhook = user.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/Pickup_ores))) /obj/item/storage/bag/ore/dropped() . = ..() diff --git a/code/game/objects/items/storage/book.dm b/code/game/objects/items/storage/book.dm index 1066e1394c..b95d6a897e 100644 --- a/code/game/objects/items/storage/book.dm +++ b/code/game/objects/items/storage/book.dm @@ -146,13 +146,14 @@ GLOBAL_LIST_INIT(bibleitemstates, list("bible", "koran", "scrapbook", "bible", M.visible_message("[user] beats [M] over the head with [src]!", \ "[user] beats [M] over the head with [src]!") playsound(src.loc, "punch", 25, 1, -1) - add_logs(user, M, "attacked", src) + log_combat(user, M, "attacked", src) else M.visible_message("[user] smacks [M]'s lifeless corpse with [src].") playsound(src.loc, "punch", 25, 1, -1) /obj/item/storage/book/bible/afterattack(atom/A, mob/user, proximity) + . = ..() if(!proximity) return if(isfloorturf(A)) @@ -186,9 +187,23 @@ GLOBAL_LIST_INIT(bibleitemstates, list("bible", "koran", "scrapbook", "bible", SS.release_shades(user) qdel(SS) new /obj/item/nullrod/claymore(get_turf(sword)) - user.visible_message("[user] has purified the [sword]!!") + user.visible_message("[user] has purified the [sword]!") qdel(sword) + else if(istype(A, /obj/item/soulstone) && !iscultist(user)) + var/obj/item/soulstone/SS = A + to_chat(user, "You begin to exorcise [SS].") + playsound(src,'sound/hallucinations/veryfar_noise.ogg',40,1) + if(do_after(user, 40, target = SS)) + playsound(src,'sound/effects/pray_chaplain.ogg',60,1) + SS.usability = TRUE + for(var/mob/living/simple_animal/shade/EX in SS) + SSticker.mode.remove_cultist(EX.mind, 1, 0) + EX.icon_state = "ghost1" + EX.name = "Purified [EX.name]" + SS.release_shades(user) + user.visible_message("[user] has purified the [SS]!") + qdel(SS) /obj/item/storage/book/bible/booze desc = "To be applied to the head repeatedly." diff --git a/code/game/objects/items/storage/boxes.dm b/code/game/objects/items/storage/boxes.dm index be4eae5ada..c8e96d0b28 100644 --- a/code/game/objects/items/storage/boxes.dm +++ b/code/game/objects/items/storage/boxes.dm @@ -93,6 +93,14 @@ for(var/i in 1 to 7) new /obj/item/disk/plantgene(src) +/obj/item/storage/box/disks_nanite + name = "nanite program disks box" + illustration = "disk_kit" + +/obj/item/storage/box/disks_nanite/PopulateContents() + for(var/i in 1 to 7) + new /obj/item/disk/nanite_program(src) + // Ordinary survival box /obj/item/storage/box/survival/PopulateContents() new /obj/item/clothing/mask/breath(src) @@ -189,6 +197,14 @@ for(var/i in 1 to 7) new /obj/item/reagent_containers/glass/beaker( src ) +/obj/item/storage/box/beakers/bluespace + name = "box of bluespace beakers" + illustration = "beaker" + +/obj/item/storage/box/beakers/bluespace/PopulateContents() + for(var/i in 1 to 7) + new /obj/item/reagent_containers/glass/beaker/bluespace(src) + /obj/item/storage/box/medsprays name = "box of medical sprayers" desc = "A box full of medical sprayers, with unscrewable caps and precision spray heads." @@ -991,6 +1007,7 @@ /obj/item/storage/box/stockparts/deluxe name = "box of deluxe stock parts" desc = "Contains a variety of deluxe stock parts." + icon_state = "syndiebox" /obj/item/storage/box/stockparts/deluxe/PopulateContents() new /obj/item/stock_parts/capacitor/quadratic(src) @@ -1008,11 +1025,3 @@ new /obj/item/stock_parts/matter_bin/bluespace(src) new /obj/item/stock_parts/matter_bin/bluespace(src) new /obj/item/stock_parts/matter_bin/bluespace(src) - -/obj/item/storage/box/disks_nanite - name = "nanite program disks box" - illustration = "disk_kit" - -/obj/item/storage/box/disks_nanite/PopulateContents() - for(var/i in 1 to 7) - new /obj/item/disk/nanite_program(src) \ No newline at end of file diff --git a/code/game/objects/items/storage/toolbox.dm b/code/game/objects/items/storage/toolbox.dm index a68f8009ce..eb6f88679f 100644 --- a/code/game/objects/items/storage/toolbox.dm +++ b/code/game/objects/items/storage/toolbox.dm @@ -79,17 +79,10 @@ has_latches = FALSE /obj/item/storage/toolbox/mechanical/old/heirloom - name = "old, robust toolbox" //this will be named "X family toolbox" + name = "toolbox" //this will be named "X family toolbox" desc = "It's seen better days." - force = 12 - total_mass = 2 - -/obj/item/storage/toolbox/mechanical/old/heirloom/afterattack(atom/A, mob/user, proximity) - . = ..() - if(proximity) - if(isobj(A)) - var/obj/O = A - O.take_damage(20) + force = 5 + w_class = WEIGHT_CLASS_NORMAL /obj/item/storage/toolbox/mechanical/old/heirloom/PopulateContents() return @@ -115,8 +108,8 @@ /obj/item/storage/toolbox/syndicate name = "black and red toolbox" icon_state = "syndicate" - desc = "A toolbox painted black with a red stripe. It looks more heavier than normal toolboxes." item_state = "toolbox_syndi" + desc = "A toolbox painted black with a red stripe. It looks more heavier than normal toolboxes." force = 15 throwforce = 18 diff --git a/code/game/objects/items/storage/uplink_kits.dm b/code/game/objects/items/storage/uplink_kits.dm index 9acd5e9846..69c8f7aee9 100644 --- a/code/game/objects/items/storage/uplink_kits.dm +++ b/code/game/objects/items/storage/uplink_kits.dm @@ -340,6 +340,14 @@ new /obj/item/pda/chameleon/broken(src) // No chameleon laser, they can't randomise for //REASONS// +/obj/item/storage/box/syndie_kit/bee_grenades + name = "buzzkill grenade box" + desc = "A sleek, sturdy box with a buzzing noise coming from the inside. Uh oh." + +/obj/item/storage/box/syndie_kit/bee_grenades/PopulateContents() + for(var/i in 1 to 3) + new /obj/item/grenade/spawnergrenade/buzzkill(src) + /obj/item/storage/box/syndie_kit/kitchen_gun name = "Kitchen Gun (TM) package" diff --git a/code/game/objects/items/stunbaton.dm b/code/game/objects/items/stunbaton.dm index 0801d282fd..1d77dfcf8b 100644 --- a/code/game/objects/items/stunbaton.dm +++ b/code/game/objects/items/stunbaton.dm @@ -171,7 +171,7 @@ L.lastattackerckey = user.ckey L.visible_message("[user] has stunned [L] with [src]!", \ "[user] has stunned you with [src]!") - add_logs(user, L, "stunned") + log_combat(user, L, "stunned") playsound(loc, 'sound/weapons/egloves.ogg', 50, 1, -1) diff --git a/code/game/objects/items/tanks/jetpack.dm b/code/game/objects/items/tanks/jetpack.dm index 6466696b98..b3ee748d13 100644 --- a/code/game/objects/items/tanks/jetpack.dm +++ b/code/game/objects/items/tanks/jetpack.dm @@ -86,6 +86,36 @@ else ..() +/obj/item/tank/jetpack/improvised + name = "improvised jetpack" + desc = "A jetpack made from two air tanks, a fire extinguisher and some atmospherics equipment. It doesn't look like it can hold much." + icon_state = "jetpack-improvised" + item_state = "jetpack-sec" + volume = 20 //normal jetpacks have 70 volume + gas_type = null //it starts empty + full_speed = FALSE //moves at hardsuit jetpack speeds + +/obj/item/tank/jetpack/improvised/allow_thrust(num, mob/living/user) + if(!on) + return + if((num < 0.005 || air_contents.total_moles() < num)) + turn_off() + return + if(rand(0,250) == 0) + to_chat(user, "You feel your jetpack's engines cut out.") + turn_off() + return + + var/datum/gas_mixture/removed = air_contents.remove(num) + if(removed.total_moles() < 0.005) + turn_off() + return + + var/turf/T = get_turf(user) + T.assume_air(removed) + + return 1 + /obj/item/tank/jetpack/void name = "void jetpack (oxygen)" desc = "It works well in a void." @@ -122,6 +152,8 @@ icon_state = "jetpack-sec" item_state = "jetpack-sec" + + /obj/item/tank/jetpack/carbondioxide name = "jetpack (carbon dioxide)" desc = "A tank of compressed carbon dioxide for use as propulsion in zero-gravity areas. Painted black to indicate that it should not be used as a source for internals." diff --git a/code/game/objects/items/tanks/tanks.dm b/code/game/objects/items/tanks/tanks.dm index 384c0a0de2..bb1a858e7b 100644 --- a/code/game/objects/items/tanks/tanks.dm +++ b/code/game/objects/items/tanks/tanks.dm @@ -233,7 +233,7 @@ return 0 var/pressure = air_contents.return_pressure() - var/temperature = air_contents.return_pressure() + var/temperature = air_contents.return_temperature() if(pressure > TANK_FRAGMENT_PRESSURE) if(!istype(src.loc, /obj/item/transfer_valve)) @@ -242,6 +242,7 @@ //Give the gas a chance to build up more pressure through reacting air_contents.react(src) air_contents.react(src) + air_contents.react(src) pressure = air_contents.return_pressure() var/range = (pressure-TANK_FRAGMENT_PRESSURE)/TANK_FRAGMENT_SCALE var/turf/epicenter = get_turf(loc) diff --git a/code/game/objects/items/tanks/watertank.dm b/code/game/objects/items/tanks/watertank.dm index e0915017bb..6d1ffe9eae 100644 --- a/code/game/objects/items/tanks/watertank.dm +++ b/code/game/objects/items/tanks/watertank.dm @@ -62,10 +62,11 @@ remove_noz() /obj/item/watertank/proc/remove_noz() - if(ismob(noz.loc)) - var/mob/M = noz.loc - M.temporarilyRemoveItemFromInventory(noz, TRUE) - noz.forceMove(src) + if(!QDELETED(noz)) + if(ismob(noz.loc)) + var/mob/M = noz.loc + M.temporarilyRemoveItemFromInventory(noz, TRUE) + noz.forceMove(src) /obj/item/watertank/Destroy() QDEL_NULL(noz) diff --git a/code/game/objects/items/taster.dm b/code/game/objects/items/taster.dm index 5f88f06af4..8363c63c2c 100644 --- a/code/game/objects/items/taster.dm +++ b/code/game/objects/items/taster.dm @@ -12,6 +12,7 @@ return list() /obj/item/taster/afterattack(atom/O, mob/user, proximity) + . = ..() if(!proximity) return diff --git a/code/game/objects/items/teleportation.dm b/code/game/objects/items/teleportation.dm index a16e3faa81..1ccc88d892 100644 --- a/code/game/objects/items/teleportation.dm +++ b/code/game/objects/items/teleportation.dm @@ -12,8 +12,8 @@ * Locator */ /obj/item/locator - name = "locator" - desc = "Used to track those with locater implants." + name = "bluespace locator" + desc = "Used to track portable teleportation beacons and targets with embedded tracking implants." icon = 'icons/obj/device.dmi' icon_state = "locator" var/temp = null @@ -131,6 +131,7 @@ resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF var/list/active_portal_pairs var/max_portal_pairs = 3 + var/atmos_link_override /obj/item/hand_tele/Initialize() . = ..() @@ -197,7 +198,7 @@ to_chat(user, "\The [src] is malfunctioning.") return user.show_message("Locked In.", 2) - var/list/obj/effect/portal/created = create_portal_pair(current_location, get_teleport_turf(get_turf(T)), src, 300, 1) + var/list/obj/effect/portal/created = create_portal_pair(current_location, get_teleport_turf(get_turf(T)), src, 300, 1, null, atmos_link_override) if(!(LAZYLEN(created) == 2)) return try_move_adjacent(created[1]) diff --git a/code/game/objects/items/theft_tools.dm b/code/game/objects/items/theft_tools.dm index c343abaa68..0c74f610df 100644 --- a/code/game/objects/items/theft_tools.dm +++ b/code/game/objects/items/theft_tools.dm @@ -229,6 +229,7 @@ icon_state = "supermatter_tongs" /obj/item/hemostat/supermatter/afterattack(atom/O, mob/user, proximity) + . = ..() if(!sliver) return if(ismovableatom(O) && O != sliver) diff --git a/code/game/objects/items/tools/weldingtool.dm b/code/game/objects/items/tools/weldingtool.dm index 4707ba9b47..db517ddb66 100644 --- a/code/game/objects/items/tools/weldingtool.dm +++ b/code/game/objects/items/tools/weldingtool.dm @@ -120,6 +120,7 @@ /obj/item/weldingtool/afterattack(atom/O, mob/user, proximity) + . = ..() if(!proximity) return if(!status && O.is_refillable()) diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index abe28ef626..00350a7f1d 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -51,6 +51,7 @@ return /obj/item/toy/balloon/afterattack(atom/A as mob|obj, mob/user, proximity) + . = ..() if(!proximity) return if (istype(A, /obj/structure/reagent_dispensers)) @@ -176,6 +177,7 @@ return ..() /obj/item/toy/gun/afterattack(atom/target as mob|obj|turf|area, mob/user, flag) + . = ..() if (flag) return if (!user.IsAdvancedToolUser()) @@ -1038,6 +1040,7 @@ throwforce = 12 //pelt your enemies to death with lumps of snow /obj/item/toy/snowball/afterattack(atom/target as mob|obj|turf|area, mob/user) + . = ..() if(user.dropItemToGround(src)) throw_at(target, throw_range, throw_speed) @@ -1057,6 +1060,7 @@ w_class = WEIGHT_CLASS_BULKY //Stops people from hiding it in their bags/pockets /obj/item/toy/beach_ball/afterattack(atom/target as mob|obj|turf|area, mob/user) + . = ..() if(user.dropItemToGround(src)) throw_at(target, throw_range, throw_speed) @@ -1368,8 +1372,11 @@ to_chat(user, "You name the dummy as \"[doll_name]\"") name = "[initial(name)] - [doll_name]" -/obj/item/toy/dummy/talk_into(atom/movable/M, message, channel, list/spans, datum/language/language) - log_talk(M,"[key_name(M)] : through dummy : [message]",LOGSAY) +/obj/item/toy/dummy/talk_into(atom/movable/A, message, channel, list/spans, datum/language/language) + var/mob/M = A + if (istype(M)) + M.log_talk(message, LOG_SAY, tag="dummy toy") + say(message, language) return NOPASS diff --git a/code/game/objects/items/twohanded.dm b/code/game/objects/items/twohanded.dm index 096a22bd20..05a9ee07fb 100644 --- a/code/game/objects/items/twohanded.dm +++ b/code/game/objects/items/twohanded.dm @@ -67,7 +67,7 @@ to_chat(user, "You need your other hand to be empty!") return if(user.get_num_arms() < 2) - to_chat(user, "You don't have enough hands.") + to_chat(user, "You don't have enough intact hands.") return wielded = 1 if(force_wielded) @@ -247,6 +247,7 @@ return (BRUTELOSS) /obj/item/twohanded/fireaxe/afterattack(atom/A, mob/user, proximity) + . = ..() if(!proximity) return if(wielded) //destroys windows and grilles in one hit @@ -494,9 +495,11 @@ /obj/item/twohanded/spear/suicide_act(mob/living/carbon/user) user.visible_message("[user] begins to sword-swallow \the [src]! It looks like [user.p_theyre()] trying to commit suicide!") if(explosive) - user.say("[war_cry]") + user.say("[war_cry]", forced="spear warcry") + explosive.forceMove(user) explosive.prime() user.gib() + qdel(src) return BRUTELOSS return BRUTELOSS @@ -516,13 +519,16 @@ icon_state = "spearglass[wielded]" /obj/item/twohanded/spear/afterattack(atom/movable/AM, mob/user, proximity) + . = ..() if(!proximity) return if(isopenturf(AM)) //So you can actually melee with it return if(explosive && wielded) - user.say("[war_cry]") + user.say("[war_cry]", forced="spear warcry") + explosive.forceMove(AM) explosive.prime() + qdel(src) /obj/item/twohanded/spear/grenade_prime_react(obj/item/grenade/nade) nade.forceMove(get_turf(src)) @@ -640,7 +646,7 @@ attack_verb = list("gored") /obj/item/twohanded/spear/grey_tide/afterattack(atom/movable/AM, mob/living/user, proximity) - ..() + . = ..() if(!proximity) return user.faction |= "greytide([REF(user)])" @@ -721,6 +727,7 @@ ..() /obj/item/twohanded/pitchfork/demonic/ascended/afterattack(atom/target, mob/user, proximity) + . = ..() if(!proximity || !wielded) return if(iswallturf(target)) @@ -730,7 +737,6 @@ W.break_wall() W.ScrapeAway() return - ..() //HF blade @@ -809,3 +815,58 @@ /obj/item/twohanded/bonespear/update_icon() icon_state = "bone_spear[wielded]" + +/obj/item/twohanded/binoculars + name = "binoculars" + desc = "Used for long-distance surveillance." + item_state = "binoculars" + icon_state = "binoculars" + lefthand_file = 'icons/mob/inhands/items_lefthand.dmi' + righthand_file = 'icons/mob/inhands/items_righthand.dmi' + slot_flags = ITEM_SLOT_BELT + w_class = WEIGHT_CLASS_SMALL + var/datum/component/mobhook + var/zoom_out_amt = 6 + var/zoom_amt = 10 + +/obj/item/twohanded/binoculars/wield(mob/user) + . = ..() + if(!wielded) + return + if(QDELETED(mobhook)) + mobhook = user.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/unwield))) + else + user.TakeComponent(mobhook) + user.visible_message("[user] holds [src] up to [user.p_their()] eyes.","You hold [src] up to your eyes.") + item_state = "binoculars_wielded" + user.regenerate_icons() + if(!user?.client) + return + var/client/C = user.client + var/_x = 0 + var/_y = 0 + switch(user.dir) + if(NORTH) + _y = zoom_amt + if(EAST) + _x = zoom_amt + if(SOUTH) + _y = -zoom_amt + if(WEST) + _x = -zoom_amt + C.change_view(world.view + zoom_out_amt) + C.pixel_x = world.icon_size*_x + C.pixel_y = world.icon_size*_y + +/obj/item/twohanded/binoculars/unwield(mob/user) + . = ..() + mobhook.RemoveComponent() + user.visible_message("[user] lowers [src].","You lower [src].") + item_state = "binoculars" + user.regenerate_icons() + if(user && user.client) + user.regenerate_icons() + var/client/C = user.client + C.change_view(CONFIG_GET(string/default_view)) + user.client.pixel_x = 0 + user.client.pixel_y = 0 diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm index 3139723ec9..316e91bb13 100644 --- a/code/game/objects/items/weaponry.dm +++ b/code/game/objects/items/weaponry.dm @@ -450,10 +450,6 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 throw_range = 2 attack_verb = list("busted") -/obj/item/statuebust/Initialize() - . = ..() - addtimer(CALLBACK(src, /datum.proc/AddComponent, /datum/component/beauty, 1000), 0) - /obj/item/tailclub name = "tail club" desc = "For the beating to death of lizards with their own tails." @@ -482,7 +478,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 item_state = "skateboard" force = 12 throwforce = 4 - w_class = WEIGHT_CLASS_HUGE + w_class = WEIGHT_CLASS_NORMAL attack_verb = list("smacked", "whacked", "slammed", "smashed") /obj/item/melee/skateboard/attack_self(mob/user) @@ -581,6 +577,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 /obj/item/melee/flyswatter/afterattack(atom/target, mob/user, proximity_flag) + . = ..() if(proximity_flag) if(is_type_in_typecache(target, strong_against)) new /obj/effect/decal/cleanable/insectguts(target.drop_location()) @@ -614,13 +611,14 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 /obj/item/slapper/attack(mob/M, mob/living/carbon/human/user) if(ishuman(M)) var/mob/living/carbon/human/L = M - L.endTailWag() + if(L && L.dna && L.dna.species) + L.dna.species.stop_wagging_tail(M) if(user.a_intent != INTENT_HARM && ((user.zone_selected == BODY_ZONE_PRECISE_MOUTH) || (user.zone_selected == BODY_ZONE_PRECISE_EYES) || (user.zone_selected == BODY_ZONE_HEAD))) user.do_attack_animation(M) playsound(M, 'sound/weapons/slap.ogg', 50, 1, -1) user.visible_message("[user] slaps [M]!", - "You slap [M]!",\ - "You hear a slap.") + "You slap [M]!",\ + "You hear a slap.") return else ..() diff --git a/code/game/objects/obj_defense.dm b/code/game/objects/obj_defense.dm index b296ec7f17..6221416db8 100644 --- a/code/game/objects/obj_defense.dm +++ b/code/game/objects/obj_defense.dm @@ -8,7 +8,7 @@ play_attack_sound(damage_amount, damage_type, damage_flag) if(!(resistance_flags & INDESTRUCTIBLE) && obj_integrity > 0) damage_amount = run_obj_armor(damage_amount, damage_type, damage_flag, attack_dir, armour_penetration) - if(damage_amount >= 0.1) + if(damage_amount >= DAMAGE_PRECISION) . = damage_amount var/old_integ = obj_integrity obj_integrity = max(old_integ - damage_amount, 0) @@ -33,7 +33,7 @@ armor_protection = armor.getRating(damage_flag) if(armor_protection) //Only apply weak-against-armor/hollowpoint effects if there actually IS armor. armor_protection = CLAMP(armor_protection - armour_penetration, 0, 100) - return round(damage_amount * (100 - armor_protection)*0.01, 0.1) + return round(damage_amount * (100 - armor_protection)*0.01, DAMAGE_PRECISION) //the sound played when the obj is damaged. /obj/proc/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0) @@ -71,7 +71,8 @@ . = ..() playsound(src, P.hitsound, 50, 1) visible_message("[src] is hit by \a [P]!", null, null, COMBAT_MESSAGE_RANGE) - take_damage(P.damage, P.damage_type, P.flag, 0, turn(P.dir, 180), P.armour_penetration) + if(!QDELETED(src)) //Bullet on_hit effect might have already destroyed this object + take_damage(P.damage, P.damage_type, P.flag, 0, turn(P.dir, 180), P.armour_penetration) /obj/proc/hulk_damage() return 150 //the damage hulks do on punches to this object, is affected by melee armor @@ -82,7 +83,7 @@ visible_message("[user] smashes [src]!", null, null, COMBAT_MESSAGE_RANGE) if(density) playsound(src, 'sound/effects/meteorimpact.ogg', 100, 1) - user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) + user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" ), forced="hulk") else playsound(src, 'sound/effects/bang.ogg', 50, 1) take_damage(hulk_damage(), BRUTE, "melee", 0, get_dir(src, user)) diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index c85b306973..c1d381b435 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -41,7 +41,7 @@ var/obj/O = vval if(istype(O) && (O.obj_flags & DANGEROUS_POSSESSION)) return FALSE - ..() + return ..() /obj/Initialize() . = ..() diff --git a/code/game/objects/structures.dm b/code/game/objects/structures.dm index dab6e46395..68c4ffeee8 100644 --- a/code/game/objects/structures.dm +++ b/code/game/objects/structures.dm @@ -79,7 +79,7 @@ if(do_climb(user)) user.visible_message("[user] climbs onto [src].", \ "You climb onto [src].") - add_logs(user, src, "climbed onto") + log_combat(user, src, "climbed onto") if(climb_stun) user.Stun(climb_stun) . = 1 diff --git a/code/game/objects/structures/aliens.dm b/code/game/objects/structures/aliens.dm index c0842822df..3cc40c8415 100644 --- a/code/game/objects/structures/aliens.dm +++ b/code/game/objects/structures/aliens.dm @@ -64,9 +64,9 @@ CanAtmosPass = ATMOS_PASS_DENSITY -/obj/structure/alien/resin/New(location) - ..() - air_update_turf(1) +/obj/structure/alien/resin/Initialize(mapload) + . = ..() + air_update_turf(TRUE) /obj/structure/alien/resin/Move() var/turf/T = loc diff --git a/code/game/objects/structures/artstuff.dm b/code/game/objects/structures/artstuff.dm index f4af05c9c9..b8320c80fb 100644 --- a/code/game/objects/structures/artstuff.dm +++ b/code/game/objects/structures/artstuff.dm @@ -13,7 +13,6 @@ max_integrity = 60 var/obj/item/canvas/painting = null - //Adding canvases /obj/structure/easel/attackby(obj/item/I, mob/user, params) if(istype(I, /obj/item/canvas)) @@ -66,6 +65,15 @@ GLOBAL_LIST_INIT(globalBlankCanvases, new(AMT_OF_CANVASES)) icon_state = "23x23" whichGlobalBackup = 4 +//HEY YOU +//ARE YOU READING THE CODE FOR CANVASES? +//ARE YOU AWARE THEY CRASH HALF THE SERVER WHEN SOMEONE DRAWS ON THEM... +//...AND NOBODY CAN FIGURE OUT WHY? +//THEN GO ON BRAVE TRAVELER +//TRY TO FIX THEM AND REMOVE THIS CODE +/obj/item/canvas/Initialize() + ..() + return INITIALIZE_HINT_QDEL //Delete on creation //Find the right size blank canvas /obj/item/canvas/proc/getGlobalBackup() @@ -124,5 +132,4 @@ GLOBAL_LIST_INIT(globalBlankCanvases, new(AMT_OF_CANVASES)) user.visible_message("[user] cleans the canvas.","You clean the canvas.") - #undef AMT_OF_CANVASES diff --git a/code/game/objects/structures/barsigns.dm b/code/game/objects/structures/barsigns.dm index f168bd4653..964f60cb73 100644 --- a/code/game/objects/structures/barsigns.dm +++ b/code/game/objects/structures/barsigns.dm @@ -9,10 +9,6 @@ armor = list("melee" = 20, "bullet" = 20, "laser" = 20, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50) buildable_sign = 0 var/list/barsigns=list() - var/list/hiddensigns - var/emagged = FALSE - var/state = 0 - var/prev_sign = "" var/panel_open = FALSE /obj/structure/sign/barsign/Initialize() @@ -39,7 +35,7 @@ /obj/structure/sign/barsign/obj_break(damage_flag) if(!broken && !(flags_1 & NODECONSTRUCT_1)) - broken = 1 + broken = TRUE /obj/structure/sign/barsign/deconstruct(disassembled = TRUE) new /obj/item/stack/sheet/metal (loc, 2) @@ -66,7 +62,7 @@ if (broken) to_chat(user, "The controls seem unresponsive.") return - pick_sign() + pick_sign(user) /obj/structure/sign/barsign/attackby(obj/item/I, mob/user) if(istype(I, /obj/item/screwdriver)) @@ -79,7 +75,7 @@ panel_open = TRUE else to_chat(user, "You close the maintenance panel.") - if(!broken && !emagged) + if(!broken && !(obj_flags & EMAGGED)) set_sign(pick(barsigns)) else if(obj_flags & EMAGGED) set_sign(new /datum/barsign/hiddensigns/syndibarsign) @@ -98,7 +94,7 @@ if(C.use(2)) to_chat(user, "You replace the burnt wiring.") - broken = 0 + broken = FALSE else to_chat(user, "You need at least two lengths of cable!") else @@ -110,13 +106,13 @@ if(. & EMP_PROTECT_SELF) return set_sign(new /datum/barsign/hiddensigns/empbarsign) - broken = 1 + broken = TRUE /obj/structure/sign/barsign/emag_act(mob/user) - if(broken || emagged) + if(broken || (obj_flags & EMAGGED)) to_chat(user, "Nothing interesting happens!") return obj_flags |= EMAGGED @@ -126,8 +122,8 @@ req_access = list(ACCESS_SYNDICATE) -/obj/structure/sign/barsign/proc/pick_sign() - var/picked_name = input("Available Signage", "Bar Sign") as null|anything in barsigns +/obj/structure/sign/barsign/proc/pick_sign(mob/user) + var/picked_name = input(user, "Available Signage", "Bar Sign", name) as null|anything in barsigns if(!picked_name) return set_sign(picked_name) @@ -142,7 +138,7 @@ var/name = "Name" var/icon = "Icon" var/desc = "desc" - var/hidden = 0 + var/hidden = FALSE //Anything below this is where all the specific signs are. If people want to add more signs, add them below. @@ -299,7 +295,7 @@ desc = "A cafe popular among moths and moffs. Once shut down for a week after the bartender used mothballs to protect her spare uniforms." /datum/barsign/hiddensigns - hidden = 1 + hidden = TRUE //Hidden signs list below this point diff --git a/code/game/objects/structures/beds_chairs/bed.dm b/code/game/objects/structures/beds_chairs/bed.dm index e8f326856a..12dcb97903 100644 --- a/code/game/objects/structures/beds_chairs/bed.dm +++ b/code/game/objects/structures/beds_chairs/bed.dm @@ -127,6 +127,7 @@ deploy_roller(user, user.loc) /obj/item/roller/afterattack(obj/target, mob/user , proximity) + . = ..() if(!proximity) return if(isopenturf(target)) diff --git a/code/game/objects/structures/beds_chairs/chair.dm b/code/game/objects/structures/beds_chairs/chair.dm index 4727817945..840ca74143 100644 --- a/code/game/objects/structures/beds_chairs/chair.dm +++ b/code/game/objects/structures/beds_chairs/chair.dm @@ -192,11 +192,20 @@ /obj/structure/chair/comfy/lime color = rgb(255,251,0) +/obj/structure/chair/comfy/shuttle + name = "shuttle seat" + desc = "A comfortable, secure seat. It has a more sturdy looking buckling system, for smoother flights." + icon_state = "shuttle_chair" + +/obj/structure/chair/comfy/shuttle/GetArmrest() + return mutable_appearance('icons/obj/chairs.dmi', "shuttle_chair_armrest") + /obj/structure/chair/office anchored = FALSE buildstackamount = 5 item_chair = null + /obj/structure/chair/office/Moved() . = ..() if(has_gravity()) @@ -307,7 +316,7 @@ return 0 /obj/item/chair/afterattack(atom/target, mob/living/carbon/user, proximity) - ..() + . = ..() if(!proximity) return if(prob(break_chance)) @@ -409,10 +418,3 @@ . = ..() if(has_gravity()) playsound(src, 'sound/machines/clockcult/integration_cog_install.ogg', 50, TRUE) - -/obj/structure/chair/shuttle - name = "shuttle seat" - desc = "A comfortable, secure seat. It has a more sturdy looking buckling system, for smoother flights." - icon = 'goon/icons/obj/chairs.dmi' - icon_state = "shuttle_chair" //thanks gannets! - diff --git a/code/game/objects/structures/bedsheet_bin.dm b/code/game/objects/structures/bedsheet_bin.dm index 035e1a3e7e..89dcc75042 100644 --- a/code/game/objects/structures/bedsheet_bin.dm +++ b/code/game/objects/structures/bedsheet_bin.dm @@ -27,7 +27,7 @@ LINEN BINS ..() /obj/item/bedsheet/attack_self(mob/user) - if((loc != user) && !Adjacent(user)) + if(!user.CanReach(src)) //No telekenetic grabbing. return if(!user.dropItemToGround(src)) return diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index 32d0fa00e1..24d81d4826 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -33,14 +33,15 @@ var/material_drop_amount = 2 var/delivery_icon = "deliverycloset" //which icon to use when packagewrapped. null to be unwrappable. var/anchorable = TRUE + var/icon_welded = "welded" /obj/structure/closet/Initialize(mapload) + if(mapload && !opened) // if closed, any item at the crate's loc is put in the contents + addtimer(CALLBACK(src, .proc/take_contents), 0) . = ..() update_icon() PopulateContents() - if(mapload && !opened) - take_contents() //USE THIS TO FILL IT, NOT INITIALIZE OR NEW /obj/structure/closet/proc/PopulateContents() @@ -59,7 +60,7 @@ else add_overlay("[icon_state]_door") if(welded) - add_overlay("welded") + add_overlay(icon_welded) if(secure && !broken) if(locked) add_overlay("locked") @@ -73,7 +74,7 @@ else add_overlay("[icon_state]_open") -/obj/structure/closet/examine(mob/user) +/obj/structure/closet/examine(mob/living/user) ..() if(welded) to_chat(user, "It's welded shut.") @@ -83,6 +84,8 @@ to_chat(user, "The parts are welded together.") else if(secure && !opened) to_chat(user, "Alt-click to [locked ? "unlock" : "lock"].") + if(user.has_trait(TRAIT_SKITTISH)) + to_chat(user, "Ctrl-Shift-click [src] to jump inside.") /obj/structure/closet/CanPass(atom/movable/mover, turf/target) if(wall_mounted) @@ -167,8 +170,6 @@ var/obj/item/I = AM if (I.item_flags & NODROP) return - else if(istype(AM, /obj/effect)) - return else if(!allow_objects && !istype(AM, /obj/effect/dummy/chameleon)) return if(!allow_dense && AM.density) @@ -249,6 +250,7 @@ if(opened) return welded = !welded + after_weld(welded) user.visible_message("[user] [welded ? "welds shut" : "unwelded"] \the [src].", "You [welded ? "weld" : "unwelded"] \the [src] with \the [W].", "You hear welding.") @@ -267,6 +269,9 @@ else return FALSE +/obj/structure/closet/proc/after_weld(weld_state) + return + /obj/structure/closet/MouseDrop_T(atom/movable/O, mob/living/user) if(!istype(O) || O.anchored || istype(O, /obj/screen)) return diff --git a/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm b/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm index 63286076bd..4726707996 100644 --- a/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm +++ b/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm @@ -14,7 +14,6 @@ delivery_icon = "deliverybox" anchorable = FALSE var/move_speed_multiplier = 1 - var/use_mob_movespeed = FALSE var/move_delay = FALSE var/egged = 0 @@ -23,7 +22,7 @@ return move_delay = TRUE if(step(src, direction)) - addtimer(CALLBACK(src, .proc/ResetMoveDelay), (use_mob_movespeed ? user.movement_delay() : CONFIG_GET(number/walk_delay)) * move_speed_multiplier) + addtimer(CALLBACK(src, .proc/ResetMoveDelay), CONFIG_GET(number/movedelay/walk_delay) * move_speed_multiplier) else ResetMoveDelay() diff --git a/code/game/objects/structures/crates_lockers/closets/secure/cargo.dm b/code/game/objects/structures/crates_lockers/closets/secure/cargo.dm index 29096c6dd8..a062be0964 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/cargo.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/cargo.dm @@ -20,3 +20,4 @@ new /obj/item/door_remote/quartermaster(src) new /obj/item/circuitboard/machine/techfab/department/cargo(src) new /obj/item/storage/photo_album/QM(src) + new /obj/item/circuitboard/machine/ore_silo(src) diff --git a/code/game/objects/structures/crates_lockers/closets/secure/supplypod.dm b/code/game/objects/structures/crates_lockers/closets/secure/supplypod.dm index d99f07e41f..44c0017bf7 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/supplypod.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/supplypod.dm @@ -66,8 +66,8 @@ addtimer(CALLBACK(src, .proc/sparks), 30)//if bluespace, then 3 seconds after opening, make some sparks and delete /obj/structure/closet/supplypod/proc/sparks()//sparks cant be called from addtimer - do_sparks(5, TRUE, src) - qdel(src)//no need for QDEL_IN if we already have a timer + do_sparks(5, TRUE, src) + qdel(src)//no need for QDEL_IN if we already have a timer /obj/structure/closet/supplypod/Destroy()//make some sparks b4 deletion QDEL_NULL(SupplyOrder) diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm index b803fff2bd..df3df8ad14 100644 --- a/code/game/objects/structures/crates_lockers/crates.dm +++ b/code/game/objects/structures/crates_lockers/crates.dm @@ -69,7 +69,7 @@ desc = "It's a burial receptacle for the dearly departed." icon_state = "coffin" resistance_flags = FLAMMABLE - max_integrity = 70 + max_integrity = 70 material_drop = /obj/item/stack/sheet/mineral/wood material_drop_amount = 5 diff --git a/code/game/objects/structures/crates_lockers/crates/secure.dm b/code/game/objects/structures/crates_lockers/crates/secure.dm index d52bd183ac..8c12f67cec 100644 --- a/code/game/objects/structures/crates_lockers/crates/secure.dm +++ b/code/game/objects/structures/crates_lockers/crates/secure.dm @@ -23,9 +23,10 @@ add_overlay("securecrateg") /obj/structure/closet/crate/secure/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1) - if(prob(tamperproof)) + if(prob(tamperproof) && damage_amount >= DAMAGE_PRECISION) boom() - ..() + else + ..() /obj/structure/closet/crate/secure/proc/boom(mob/user) diff --git a/code/game/objects/structures/displaycase.dm b/code/game/objects/structures/displaycase.dm index 734b645880..bcb025d14b 100644 --- a/code/game/objects/structures/displaycase.dm +++ b/code/game/objects/structures/displaycase.dm @@ -20,7 +20,7 @@ /obj/structure/displaycase/Initialize() . = ..() - if(start_showpieces.len && !start_showpiece_type) + if(start_showpieces.len && !start_showpiece_type) var/list/showpiece_entry = pick(start_showpieces) if (showpiece_entry && showpiece_entry["type"]) start_showpiece_type = showpiece_entry["type"] @@ -164,6 +164,7 @@ user.changeNext_move(CLICK_CD_MELEE) if (showpiece && (broken || open)) to_chat(user, "You deactivate the hover field built into the case.") + log_combat(user, src, "deactivates the hover field of") dump() src.add_fingerprint(user) update_icon() @@ -173,6 +174,7 @@ if (!Adjacent(user)) return user.visible_message("[user] kicks the display case.", null, null, COMBAT_MESSAGE_RANGE) + log_combat(user, src, "kicks") user.do_attack_animation(src, ATTACK_EFFECT_KICK) take_damage(2) diff --git a/code/game/objects/structures/door_assembly.dm b/code/game/objects/structures/door_assembly.dm index 0fc7ba74b6..915d45be78 100644 --- a/code/game/objects/structures/door_assembly.dm +++ b/code/game/objects/structures/door_assembly.dm @@ -237,6 +237,7 @@ else door = new airlock_type( loc ) door.setDir(dir) + door.unres_sides = electronics.unres_sides //door.req_access = req_access door.electronics = electronics door.heat_proof = heat_proof_finished @@ -250,6 +251,7 @@ door.name = base_name door.previous_airlock = previous_assembly electronics.forceMove(door) + door.update_icon() qdel(src) else return ..() diff --git a/code/game/objects/structures/extinguisher.dm b/code/game/objects/structures/extinguisher.dm index aa2f7bed86..d4e097e450 100644 --- a/code/game/objects/structures/extinguisher.dm +++ b/code/game/objects/structures/extinguisher.dm @@ -59,6 +59,7 @@ stored_extinguisher = I to_chat(user, "You place [I] in [src].") update_icon() + return TRUE else toggle_cabinet(user) else if(user.a_intent != INTENT_HARM) diff --git a/code/game/objects/structures/false_walls.dm b/code/game/objects/structures/false_walls.dm index c877488601..5878b569c3 100644 --- a/code/game/objects/structures/false_walls.dm +++ b/code/game/objects/structures/false_walls.dm @@ -38,11 +38,6 @@ . = ..() AddComponent(/datum/component/rad_insulation, RAD_MEDIUM_INSULATION) -/obj/structure/falsewall/Destroy() - density = FALSE - air_update_turf(1) - return ..() - /obj/structure/falsewall/ratvar_act() new /obj/structure/falsewall/brass(loc) qdel(src) diff --git a/code/game/objects/structures/flora.dm b/code/game/objects/structures/flora.dm index 079ef93118..4e274d5048 100644 --- a/code/game/objects/structures/flora.dm +++ b/code/game/objects/structures/flora.dm @@ -294,9 +294,6 @@ throw_speed = 2 throw_range = 4 -/obj/item/twohanded/required/kirbyplants/Initialize() - . = ..() - addtimer(CALLBACK(src, /datum.proc/AddComponent, /datum/component/beauty, 750), 0) /obj/item/twohanded/required/kirbyplants/equipped(mob/living/user) var/image/I = image(icon = 'icons/obj/flora/plants.dmi' , icon_state = src.icon_state, loc = user) diff --git a/code/game/objects/structures/ghost_role_spawners.dm b/code/game/objects/structures/ghost_role_spawners.dm index 6c5ecf149e..6290139bb4 100644 --- a/code/game/objects/structures/ghost_role_spawners.dm +++ b/code/game/objects/structures/ghost_role_spawners.dm @@ -477,7 +477,8 @@ mob_species = /datum/species/human flavour_text = "You are a security officer working for Nanotrasen, stationed onboard a state of the art research station. You vaguely recall rushing into a \ cryogenics pod due to an oncoming radiation storm. The last thing you remember is the station's Artificial Program telling you that you would only be asleep for eight hours. As you open \ - your eyes, everything seems rusted and broken, a dark feeling sweels in your gut as you climb out of your pod." + your eyes, everything seems rusted and broken, a dark feeling swells in your gut as you climb out of your pod. \ + Work as a team with your fellow survivors and do not abandon them." uniform = /obj/item/clothing/under/rank/security shoes = /obj/item/clothing/shoes/jackboots id = /obj/item/card/id/away/old/sec @@ -501,7 +502,8 @@ mob_species = /datum/species/human flavour_text = "You are an engineer working for Nanotrasen, stationed onboard a state of the art research station. You vaguely recall rushing into a \ cryogenics pod due to an oncoming radiation storm. The last thing you remember is the station's Artificial Program telling you that you would only be asleep for eight hours. As you open \ - your eyes, everything seems rusted and broken, a dark feeling sweels in your gut as you climb out of your pod." + your eyes, everything seems rusted and broken, a dark feeling swells in your gut as you climb out of your pod. \ + Work as a team with your fellow survivors and do not abandon them." uniform = /obj/item/clothing/under/rank/engineer shoes = /obj/item/clothing/shoes/workboots id = /obj/item/card/id/away/old/eng @@ -525,7 +527,8 @@ mob_species = /datum/species/human flavour_text = "You are a scientist working for Nanotrasen, stationed onboard a state of the art research station. You vaguely recall rushing into a \ cryogenics pod due to an oncoming radiation storm. The last thing you remember is the station's Artificial Program telling you that you would only be asleep for eight hours. As you open \ - your eyes, everything seems rusted and broken, a dark feeling sweels in your gut as you climb out of your pod." + your eyes, everything seems rusted and broken, a dark feeling swells in your gut as you climb out of your pod. \ + Work as a team with your fellow survivors and do not abandon them." uniform = /obj/item/clothing/under/rank/scientist shoes = /obj/item/clothing/shoes/laceup id = /obj/item/card/id/away/old/sci diff --git a/code/game/objects/structures/girders.dm b/code/game/objects/structures/girders.dm index 7705b84daf..b319aab537 100644 --- a/code/game/objects/structures/girders.dm +++ b/code/game/objects/structures/girders.dm @@ -210,6 +210,9 @@ // Screwdriver behavior for girders /obj/structure/girder/screwdriver_act(mob/user, obj/item/tool) + if(..()) + return TRUE + . = FALSE if(state == GIRDER_DISPLACED) user.visible_message("[user] disassembles the girder.", diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm index bef220f70c..dc5219b9ec 100644 --- a/code/game/objects/structures/grille.dm +++ b/code/game/objects/structures/grille.dm @@ -79,7 +79,7 @@ new /obj/structure/grille/ratvar(src.loc) qdel(src) -/obj/structure/grille/CollidedWith(atom/movable/AM) +/obj/structure/grille/Bumped(atom/movable/AM) if(!ismob(AM)) return var/mob/M = AM @@ -109,6 +109,7 @@ user.changeNext_move(CLICK_CD_MELEE) user.do_attack_animation(src, ATTACK_EFFECT_KICK) user.visible_message("[user] hits [src].", null, null, COMBAT_MESSAGE_RANGE) + log_combat(user, src, "hit") if(!shock(user, 70)) take_damage(rand(5,10), BRUTE, "melee", 1) diff --git a/code/game/objects/structures/guillotine.dm b/code/game/objects/structures/guillotine.dm index beb7a927ca..8714722f4b 100644 --- a/code/game/objects/structures/guillotine.dm +++ b/code/game/objects/structures/guillotine.dm @@ -118,7 +118,7 @@ playsound(src, 'sound/weapons/bladeslice.ogg', 100, 1) if (blade_sharpness >= GUILLOTINE_DECAP_MIN_SHARP || head.brute_dam >= 100) head.dismember() - add_logs(user, H, "beheaded", src) + log_combat(user, H, "beheaded", src) H.regenerate_icons() unbuckle_all_mobs() kill_count += 1 @@ -144,7 +144,7 @@ delay_offset++ else H.apply_damage(15 * blade_sharpness, BRUTE, head) - add_logs(user, H, "dropped the blade on", src, " non-fatally") + log_combat(user, H, "dropped the blade on", src, " non-fatally") H.emote("scream") if (blade_sharpness > 1) @@ -246,7 +246,7 @@ if (do_after(user, GUILLOTINE_WRENCH_DELAY, target = src)) current_action = 0 default_unfasten_wrench(user, I, 0) - dir = SOUTH + setDir(SOUTH) return TRUE else current_action = 0 diff --git a/code/game/objects/structures/holosign.dm b/code/game/objects/structures/holosign.dm index 0e803247de..c5c8dd3c68 100644 --- a/code/game/objects/structures/holosign.dm +++ b/code/game/objects/structures/holosign.dm @@ -83,11 +83,6 @@ . = ..() air_update_turf(TRUE) -/obj/structure/holosign/barrier/atmos/Destroy() - var/turf/T = get_turf(src) - . = ..() - T.air_update_turf(TRUE) - /obj/structure/holosign/barrier/cyborg name = "Energy Field" desc = "A fragile energy field that blocks movement. Excels at blocking lethal projectiles." @@ -102,6 +97,44 @@ if(istype(P, /obj/item/projectile/beam/disabler)) take_damage(5, BRUTE, "melee", 1) //Disablers aren't harmful. +/obj/structure/holosign/barrier/medical + name = "\improper PENLITE holobarrier" + desc = "A holobarrier that uses biometrics to detect human viruses. Denies passing to personnel with easily-detected, malicious viruses. Good for quarantines." + icon_state = "holo_medical" + alpha = 125 //lazy :) + layer = ABOVE_MOB_LAYER + var/force_allaccess = FALSE + var/buzzcd = 0 + +/obj/structure/holosign/barrier/medical/examine(mob/user) + ..() + to_chat(user,"The biometric scanners are [force_allaccess ? "off" : "on"].") + +/obj/structure/holosign/barrier/medical/CanPass(atom/movable/mover, turf/target) + icon_state = "holo_medical" + if(force_allaccess) + return TRUE + if(ishuman(mover)) + var/mob/living/carbon/human/sickboi = mover + var/threat = sickboi.check_virus() + switch(threat) + if(DISEASE_SEVERITY_MINOR, DISEASE_SEVERITY_MEDIUM, DISEASE_SEVERITY_HARMFUL, DISEASE_SEVERITY_DANGEROUS, DISEASE_SEVERITY_BIOHAZARD) + if(buzzcd < world.time) + playsound(get_turf(src),'sound/machines/buzz-sigh.ogg',65,1,4) + buzzcd = (world.time + 60) + icon_state = "holo_medical-deny" + return FALSE + else + return TRUE //nice or benign diseases! + return TRUE + +/obj/structure/holosign/barrier/medical/attack_hand(mob/living/user) + if(CanPass(user) && user.a_intent == INTENT_HELP) + force_allaccess = !force_allaccess + to_chat(user, "You [force_allaccess ? "deactivate" : "activate"] the biometric scanners.") //warning spans because you can make the station sick! + else + return ..() + /obj/structure/holosign/barrier/cyborg/hacked name = "Charged Energy Field" desc = "A powerful energy field that blocks movement. Energy arcs off it." @@ -125,7 +158,7 @@ shockcd = TRUE addtimer(CALLBACK(src, .proc/cooldown), 5) -/obj/structure/holosign/barrier/cyborg/hacked/CollidedWith(atom/movable/AM) +/obj/structure/holosign/barrier/cyborg/hacked/Bumped(atom/movable/AM) if(shockcd) return @@ -135,4 +168,4 @@ var/mob/living/M = AM M.electrocute_act(15,"Energy Barrier", safety=1) shockcd = TRUE - addtimer(CALLBACK(src, .proc/cooldown), 5) + addtimer(CALLBACK(src, .proc/cooldown), 5) \ No newline at end of file diff --git a/code/game/objects/structures/janicart.dm b/code/game/objects/structures/janicart.dm index 4c588395df..cc9b002fa8 100644 --- a/code/game/objects/structures/janicart.dm +++ b/code/game/objects/structures/janicart.dm @@ -162,4 +162,6 @@ add_overlay("cart_replacer") if(signs) add_overlay("cart_sign[signs]") + if(reagents.total_volume > 0) + add_overlay("cart_water") diff --git a/code/game/objects/structures/manned_turret.dm b/code/game/objects/structures/manned_turret.dm index df145baf94..aa55cd81b1 100644 --- a/code/game/objects/structures/manned_turret.dm +++ b/code/game/objects/structures/manned_turret.dm @@ -208,7 +208,7 @@ add_fingerprint(user) /obj/item/gun_control/afterattack(atom/targeted_atom, mob/user, flag, params) - ..() + . = ..() var/obj/machinery/manned_turret/E = user.buckled E.calculated_projectile_vars = calculate_projectile_angle_and_pixel_offsets(user, params) E.direction_track(user, targeted_atom) diff --git a/code/game/objects/structures/mineral_doors.dm b/code/game/objects/structures/mineral_doors.dm index 561cc8ef8c..c3316f2568 100644 --- a/code/game/objects/structures/mineral_doors.dm +++ b/code/game/objects/structures/mineral_doors.dm @@ -30,17 +30,12 @@ /obj/structure/mineral_door/ComponentInitialize() AddComponent(/datum/component/rad_insulation, RAD_MEDIUM_INSULATION) -/obj/structure/mineral_door/Destroy() - density = FALSE - air_update_turf(1) - return ..() - /obj/structure/mineral_door/Move() var/turf/T = loc . = ..() move_update_air(T) -/obj/structure/mineral_door/CollidedWith(atom/movable/AM) +/obj/structure/mineral_door/Bumped(atom/movable/AM) ..() if(!state) return TryToSwitchState(AM) diff --git a/code/game/objects/structures/mop_bucket.dm b/code/game/objects/structures/mop_bucket.dm index f4936b1d80..7fe9700470 100644 --- a/code/game/objects/structures/mop_bucket.dm +++ b/code/game/objects/structures/mop_bucket.dm @@ -8,9 +8,9 @@ var/amount_per_transfer_from_this = 5 //shit I dunno, adding this so syringes stop runtime erroring. --NeoFite -/obj/structure/mopbucket/New() +/obj/structure/mopbucket/Initialize() + . = ..() create_reagents(100) - ..() /obj/structure/mopbucket/attackby(obj/item/I, mob/user, params) if(istype(I, /obj/item/mop)) @@ -20,5 +20,11 @@ reagents.trans_to(I, 5) to_chat(user, "You wet [I] in [src].") playsound(loc, 'sound/effects/slosh.ogg', 25, 1) + update_icon() else - return ..() \ No newline at end of file + return ..() + +/obj/structure/mopbucket/update_icon() + cut_overlays() + if(reagents.total_volume > 0) + add_overlay("mopbucket_water") \ No newline at end of file diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm index 111ce3ccca..695395afd2 100644 --- a/code/game/objects/structures/morgue.dm +++ b/code/game/objects/structures/morgue.dm @@ -123,7 +123,7 @@ GLOBAL_LIST_EMPTY(bodycontainers) //Let them act as spawnpoints for revenants an playsound(src.loc, 'sound/items/deconstruct.ogg', 50, 1) playsound(src, 'sound/effects/roll.ogg', 5, 1) var/turf/T = get_step(src, dir) - connected.dir=dir + connected.setDir(dir) for(var/atom/movable/AM in src) AM.forceMove(T) update_icon() @@ -256,10 +256,10 @@ GLOBAL_LIST_EMPTY(crematoriums) if (M.stat != DEAD) M.emote("scream") if(user) - user.log_message("Cremated [key_name(M)]", INDIVIDUAL_ATTACK_LOG) - log_attack("[key_name(user)] cremated [key_name(M)]") + log_combat(user, M, "cremated") else - log_attack("UNKNOWN cremated [key_name(M)]") + M.log_message("was cremated", LOG_ATTACK) + M.death(1) if(M) //some animals get automatically deleted on death. M.ghostize() diff --git a/code/game/objects/structures/plasticflaps.dm b/code/game/objects/structures/plasticflaps.dm index 6f9c4dbc50..e3862ed924 100644 --- a/code/game/objects/structures/plasticflaps.dm +++ b/code/game/objects/structures/plasticflaps.dm @@ -20,6 +20,8 @@ to_chat(user, "[src] are no longer screwed to the floor, and the flaps can be cut apart.") /obj/structure/plasticflaps/screwdriver_act(mob/living/user, obj/item/W) + if(..()) + return TRUE add_fingerprint(user) var/action = anchored ? "unscrews [src] from" : "screws [src] to" var/uraction = anchored ? "unscrew [src] from " : "screw [src] to" @@ -95,8 +97,8 @@ qdel(src) /obj/structure/plasticflaps/Initialize() - . = ..() - air_update_turf(TRUE) + . = ..() + air_update_turf(TRUE) /obj/structure/plasticflaps/Destroy() var/atom/oldloc = loc diff --git a/code/game/objects/structures/safe.dm b/code/game/objects/structures/safe.dm index 3a10d200a1..f256b6bd4c 100644 --- a/code/game/objects/structures/safe.dm +++ b/code/game/objects/structures/safe.dm @@ -13,6 +13,7 @@ FLOOR SAFES anchored = TRUE density = TRUE resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF + interaction_flags_atom = INTERACT_ATOM_ATTACK_HAND | INTERACT_ATOM_UI_INTERACT var/open = FALSE //is the safe open? var/tumbler_1_pos //the tumbler position- from 0 to 72 var/tumbler_1_open //the tumbler position to open at- 0 to 72 @@ -23,7 +24,6 @@ FLOOR SAFES var/maxspace = 24 //the maximum combined w_class of stuff in the safe var/explosion_count = 0 //Tough, but breakable - /obj/structure/safe/New() ..() tumbler_1_pos = rand(0, 71) @@ -61,32 +61,25 @@ FLOOR SAFES return TRUE return FALSE - /obj/structure/safe/proc/decrement(num) num -= 1 if(num < 0) num = 71 return num - /obj/structure/safe/proc/increment(num) num += 1 if(num > 71) num = 0 return num - /obj/structure/safe/update_icon() if(open) icon_state = "[initial(icon_state)]-open" else icon_state = initial(icon_state) - -/obj/structure/safe/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/structure/safe/ui_interact(mob/user) user.set_machine(src) var/dat = "

    " dat += "[open ? "Close" : "Open"] [src] | - [dial] +" @@ -98,7 +91,6 @@ FLOOR SAFES dat += "
    " user << browse("[name][dat]", "window=safe;size=350x300") - /obj/structure/safe/Topic(href, href_list) if(!ishuman(usr)) return diff --git a/code/game/objects/structures/showcase.dm b/code/game/objects/structures/showcase.dm index fe6785db2d..5de3f0fc9a 100644 --- a/code/game/objects/structures/showcase.dm +++ b/code/game/objects/structures/showcase.dm @@ -11,10 +11,6 @@ anchored = TRUE var/deconstruction_state = SHOWCASE_CONSTRUCTED -/obj/structure/showcase/Initialize() - . = ..() - addtimer(CALLBACK(src, /datum.proc/AddComponent, /datum/component/beauty, 750), 0) - /obj/structure/showcase/fakeid name = "\improper CentCom identification console" desc = "You can use this to change ID's." diff --git a/code/game/objects/structures/signs/_signs.dm b/code/game/objects/structures/signs/_signs.dm index ad943ff9fc..56b43a289b 100644 --- a/code/game/objects/structures/signs/_signs.dm +++ b/code/game/objects/structures/signs/_signs.dm @@ -103,6 +103,7 @@ var/sign_path = /obj/structure/sign/basic //the type of sign that will be created when placed on a turf /obj/item/sign_backing/afterattack(atom/target, mob/user, proximity) + . = ..() if(isturf(target) && proximity) var/turf/T = target user.visible_message("[user] fastens [src] to [T].", \ @@ -111,8 +112,6 @@ var/obj/structure/sign/S = new sign_path(T) S.setDir(dir) qdel(src) - else - return ..() /obj/item/sign_backing/Move(atom/new_loc, direct = 0) // pulling, throwing, or conveying a sign backing does not rotate it diff --git a/code/game/objects/structures/spirit_board.dm b/code/game/objects/structures/spirit_board.dm index 104d02858d..c35d16ab73 100644 --- a/code/game/objects/structures/spirit_board.dm +++ b/code/game/objects/structures/spirit_board.dm @@ -37,7 +37,7 @@ planchette = input("Choose the letter.", "Seance!") as null|anything in list("A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z") if(!planchette || !Adjacent(M) || next_use > world.time) return - add_logs(M, src, "picked a letter on", " which was \"[planchette]\".") + M.log_message("picked a letter on [src], which was \"[planchette]\".") next_use = world.time + rand(30,50) lastuser = M.ckey //blind message is the same because not everyone brings night vision to seances diff --git a/code/game/objects/structures/statues.dm b/code/game/objects/structures/statues.dm index d22dbddd52..dd28168ccc 100644 --- a/code/game/objects/structures/statues.dm +++ b/code/game/objects/structures/statues.dm @@ -11,10 +11,6 @@ CanAtmosPass = ATMOS_PASS_DENSITY -/obj/structure/statue/Initialize() - . = ..() - addtimer(CALLBACK(src, /datum.proc/AddComponent, /datum/component/beauty, 1250), 0) - /obj/structure/statue/attackby(obj/item/W, mob/living/user, params) add_fingerprint(user) user.changeNext_move(CLICK_CD_MELEE) @@ -77,7 +73,7 @@ radiate() return ..() -/obj/structure/statue/uranium/CollidedWith(atom/movable/AM) +/obj/structure/statue/uranium/Bumped(atom/movable/AM) radiate() ..() @@ -117,8 +113,7 @@ /obj/structure/statue/plasma/bullet_act(obj/item/projectile/Proj) var/burn = FALSE - if(!(Proj.nodamage) && Proj.damage_type == BURN) - PlasmaBurn(2500) + if(!(Proj.nodamage) && Proj.damage_type == BURN && !QDELETED(src)) burn = TRUE if(burn) var/turf/T = get_turf(src) @@ -128,10 +123,11 @@ else message_admins("Plasma statue ignited by [Proj]. No known firer, in [ADMIN_VERBOSEJMP(T)]") log_game("Plasma statue ignited by [Proj] in [AREACOORD(T)]. No known firer.") + PlasmaBurn(2500) ..() /obj/structure/statue/plasma/attackby(obj/item/W, mob/user, params) - if(W.is_hot() > 300)//If the temperature of the object is over 300, then ignite + if(W.is_hot() > 300 && !QDELETED(src))//If the temperature of the object is over 300, then ignite var/turf/T = get_turf(src) message_admins("Plasma statue ignited by [ADMIN_LOOKUPFLW(user)] in [ADMIN_VERBOSEJMP(T)]") log_game("Plasma statue ignited by [key_name(user)] in [AREACOORD(T)]") @@ -140,6 +136,8 @@ return ..() /obj/structure/statue/plasma/proc/PlasmaBurn(exposed_temperature) + if(QDELETED(src)) + return atmos_spawn_air("plasma=[oreAmount*10];TEMP=[exposed_temperature]") deconstruct(FALSE) @@ -232,7 +230,7 @@ name = "statue of a clown" icon_state = "clown" -/obj/structure/statue/bananium/CollidedWith(atom/movable/AM) +/obj/structure/statue/bananium/Bumped(atom/movable/AM) honk() ..() diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm index aa87410d2c..78c8971759 100644 --- a/code/game/objects/structures/tables_racks.dm +++ b/code/game/objects/structures/tables_racks.dm @@ -60,24 +60,31 @@ return attack_hand(user) /obj/structure/table/attack_hand(mob/living/user) - if(Adjacent(user) && user.pulling && isliving(user.pulling)) - var/mob/living/pushed_mob = user.pulling - if(pushed_mob.buckled) - to_chat(user, "[pushed_mob] is buckled to [pushed_mob.buckled]!") - return - if(user.a_intent == INTENT_GRAB) - if(user.grab_state < GRAB_AGGRESSIVE) - to_chat(user, "You need a better grip to do that!") + if(Adjacent(user) && user.pulling) + if(isliving(user.pulling)) + var/mob/living/pushed_mob = user.pulling + if(pushed_mob.buckled) + to_chat(user, "[pushed_mob] is buckled to [pushed_mob.buckled]!") return - tablepush(user, pushed_mob) - if(user.a_intent == INTENT_HELP) - pushed_mob.visible_message("[user] begins to place [pushed_mob] onto [src]...", \ - "[user] begins to place [pushed_mob] onto [src]...") - if(do_after(user, 35, target = pushed_mob)) - tableplace(user, pushed_mob) - else - return - user.stop_pulling() + if(user.a_intent == INTENT_GRAB) + if(user.grab_state < GRAB_AGGRESSIVE) + to_chat(user, "You need a better grip to do that!") + return + tablepush(user, pushed_mob) + if(user.a_intent == INTENT_HELP) + pushed_mob.visible_message("[user] begins to place [pushed_mob] onto [src]...", \ + "[user] begins to place [pushed_mob] onto [src]...") + if(do_after(user, 35, target = pushed_mob)) + tableplace(user, pushed_mob) + else + return + user.stop_pulling() + else if(user.pulling.pass_flags & PASSTABLE) + user.Move_Pulled(src) + if (user.pulling.loc == loc) + user.visible_message("[user] places [user.pulling] onto [src].", + "You place [user.pulling] onto [src].") + user.stop_pulling() return ..() /obj/structure/table/attack_tk() @@ -105,14 +112,22 @@ pushed_mob.update_canmove() pushed_mob.visible_message("[user] places [pushed_mob] onto [src].", \ "[user] places [pushed_mob] onto [src].") - add_logs(user, pushed_mob, "placed") + log_combat(user, pushed_mob, "placed") /obj/structure/table/proc/tablepush(mob/living/user, mob/living/pushed_mob) - pushed_mob.forceMove(src.loc) + var/added_passtable = FALSE + if(!pushed_mob.pass_flags & PASSTABLE) + added_passtable = TRUE + pushed_mob.pass_flags |= PASSTABLE + pushed_mob.Move(src.loc) + if(added_passtable) + pushed_mob.pass_flags &= ~PASSTABLE + if(pushed_mob.loc != loc) //Something prevented the tabling + return pushed_mob.Knockdown(40) pushed_mob.visible_message("[user] pushes [pushed_mob] onto [src].", \ "[user] pushes [pushed_mob] onto [src].") - add_logs(user, pushed_mob, "pushed") + log_combat(user, pushed_mob, "pushed") if(!ishuman(pushed_mob)) return var/mob/living/carbon/human/H = pushed_mob diff --git a/code/game/objects/structures/transit_tubes/station.dm b/code/game/objects/structures/transit_tubes/station.dm index e520a97291..6015cf9f4a 100644 --- a/code/game/objects/structures/transit_tubes/station.dm +++ b/code/game/objects/structures/transit_tubes/station.dm @@ -33,7 +33,7 @@ /obj/structure/transit_tube/station/should_stop_pod(pod, from_dir) return 1 -/obj/structure/transit_tube/station/CollidedWith(atom/movable/AM) +/obj/structure/transit_tube/station/Bumped(atom/movable/AM) if(!pod_moving && open_status == STATION_TUBE_OPEN && ismob(AM) && AM.dir == boarding_dir) for(var/obj/structure/transit_tube_pod/pod in loc) if(!pod.moving) @@ -75,7 +75,7 @@ if(do_after(user, 15, target = src)) if(open_status == STATION_TUBE_OPEN && GM && user.grab_state >= GRAB_AGGRESSIVE && user.pulling == GM && !GM.buckled && !GM.has_buckled_mobs()) GM.Knockdown(100) - src.CollidedWith(GM) + src.Bumped(GM) break else for(var/obj/structure/transit_tube_pod/pod in loc) diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm index df5c66a7a1..d70838a30b 100644 --- a/code/game/objects/structures/watercloset.dm +++ b/code/game/objects/structures/watercloset.dm @@ -181,6 +181,8 @@ return ..() /obj/structure/urinal/screwdriver_act(mob/living/user, obj/item/I) + if(..()) + return TRUE to_chat(user, "You start to [exposed ? "screw the cap back into place" : "unscrew the cap to the drain protector"]...") playsound(loc, 'sound/effects/stonedoor_openclose.ogg', 50, 1) if(I.use_tool(src, user, 20)) @@ -238,6 +240,7 @@ update_icon() add_fingerprint(M) if(on) + START_PROCESSING(SSmachines, src) soundloop.start() wash_turf() for(var/atom/movable/G in loc) @@ -418,6 +421,8 @@ else if(isobj(AM)) wash_obj(AM) contamination_cleanse(AM) + else + return PROCESS_KILL /obj/machinery/shower/deconstruct(disassembled = TRUE) new /obj/item/stack/sheet/metal (loc, 3) diff --git a/code/game/objects/structures/windoor_assembly.dm b/code/game/objects/structures/windoor_assembly.dm index 823d933edb..10c6e53701 100644 --- a/code/game/objects/structures/windoor_assembly.dm +++ b/code/game/objects/structures/windoor_assembly.dm @@ -32,7 +32,7 @@ /obj/structure/windoor_assembly/New(loc, set_dir) ..() if(set_dir) - dir = set_dir + setDir(set_dir) ini_dir = dir air_update_turf(1) diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index c1860189dc..f00fd08ee5 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -138,7 +138,7 @@ return FALSE return 1 -/obj/structure/window/CheckExit(atom/movable/O as mob|obj, target) +/obj/structure/window/CheckExit(atom/movable/O, turf/target) if(istype(O) && (O.pass_flags & PASSGLASS)) return 1 if(get_dir(O.loc, target) == dir) diff --git a/code/game/say.dm b/code/game/say.dm index 10359aab85..9553b4eb4c 100644 --- a/code/game/say.dm +++ b/code/game/say.dm @@ -18,12 +18,12 @@ GLOBAL_LIST_INIT(freqtospan, list( "[FREQ_CTF_BLUE]" = "blueteamradio" )) -/atom/movable/proc/say(message, datum/language/language = null) +/atom/movable/proc/say(message, bubble_type, var/list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null) if(!can_speak()) return if(message == "" || !message) return - var/list/spans = get_spans() + spans |= get_spans() if(!language) language = get_default_language() send_speech(message, 7, src, , spans, message_language=language) @@ -95,7 +95,7 @@ GLOBAL_LIST_INIT(freqtospan, list( spans |= SPAN_YELL var/spanned = attach_spans(input, spans) - return "[say_mod(input, message_mode)][spanned ? ", \"[spanned]\"" : ""]" + return "[say_mod(input, message_mode)], \"[spanned]\"" /atom/movable/proc/lang_treat(atom/movable/speaker, datum/language/language, raw_message, list/spans, message_mode) if(has_language(language)) diff --git a/code/game/shuttle_engines.dm b/code/game/shuttle_engines.dm index 2983d3d923..0f68e68b7b 100644 --- a/code/game/shuttle_engines.dm +++ b/code/game/shuttle_engines.dm @@ -88,7 +88,6 @@ icon_state = "heater" desc = "Directs energy into compressed particles in order to power engines." engine_power = 0 // todo make these into 2x1 parts - CanAtmosPass = ATMOS_PASS_NO /obj/structure/shuttle/engine/platform name = "engine platform" diff --git a/code/game/sound.dm b/code/game/sound.dm index 5b40e6640a..84351cdb95 100644 --- a/code/game/sound.dm +++ b/code/game/sound.dm @@ -5,26 +5,27 @@ var/turf/turf_source = get_turf(source) + if (!turf_source) + return + //allocate a channel if necessary now so its the same for everyone channel = channel || open_sound_channel() // Looping through the player list has the added bonus of working for mobs inside containers var/sound/S = sound(get_sfx(soundin)) var/maxdistance = (world.view + extrarange) - var/list/listeners = GLOB.player_list + var/z = turf_source.z + var/list/listeners = SSmobs.clients_by_zlevel[z] if(!ignore_walls) //these sounds don't carry through walls listeners = listeners & hearers(maxdistance,turf_source) for(var/P in listeners) var/mob/M = P - if(!M || !M.client) - continue - var/distance = get_dist(M, turf_source) - - if(distance <= maxdistance) - var/turf/T = get_turf(M) - - if(T && T.z == turf_source.z) - M.playsound_local(turf_source, soundin, vol, vary, frequency, falloff, channel, pressure_affected, S) + if(get_dist(M, turf_source) <= maxdistance) + M.playsound_local(turf_source, soundin, vol, vary, frequency, falloff, channel, pressure_affected, S) + for(var/P in SSmobs.dead_players_by_zlevel[z]) + var/mob/M = P + if(get_dist(M, turf_source) <= maxdistance) + M.playsound_local(turf_source, soundin, vol, vary, frequency, falloff, channel, pressure_affected, S) /mob/proc/playsound_local(turf/turf_source, soundin, vol as num, vary, frequency, falloff, channel = 0, pressure_affected = TRUE, sound/S, envwet = -10000, envdry = 0) if(!client || !can_hear()) @@ -152,7 +153,23 @@ soundin = pick('sound/hallucinations/im_here1.ogg', 'sound/hallucinations/im_here2.ogg') if ("can_open") soundin = pick('sound/effects/can_open1.ogg', 'sound/effects/can_open2.ogg', 'sound/effects/can_open3.ogg') - //START OF CIT CHANGES - adds random vore sounds + if("bullet_miss") + soundin = pick('sound/weapons/bulletflyby.ogg', 'sound/weapons/bulletflyby2.ogg', 'sound/weapons/bulletflyby3.ogg') + if("gun_dry_fire") + soundin = pick('sound/weapons/gun_dry_fire_1.ogg', 'sound/weapons/gun_dry_fire_2.ogg', 'sound/weapons/gun_dry_fire_3.ogg', 'sound/weapons/gun_dry_fire_4.ogg') + if("gun_insert_empty_magazine") + soundin = pick('sound/weapons/gun_magazine_insert_empty_1.ogg', 'sound/weapons/gun_magazine_insert_empty_2.ogg', 'sound/weapons/gun_magazine_insert_empty_3.ogg', 'sound/weapons/gun_magazine_insert_empty_4.ogg') + if("gun_insert_full_magazine") + soundin = pick('sound/weapons/gun_magazine_insert_full_1.ogg', 'sound/weapons/gun_magazine_insert_full_2.ogg', 'sound/weapons/gun_magazine_insert_full_3.ogg', 'sound/weapons/gun_magazine_insert_full_4.ogg', 'sound/weapons/gun_magazine_insert_full_5.ogg') + if("gun_remove_empty_magazine") + soundin = pick('sound/weapons/gun_magazine_remove_empty_1.ogg', 'sound/weapons/gun_magazine_remove_empty_2.ogg', 'sound/weapons/gun_magazine_remove_empty_3.ogg', 'sound/weapons/gun_magazine_remove_empty_4.ogg') + if("gun_slide_lock") + soundin = pick('sound/weapons/gun_slide_lock_1.ogg', 'sound/weapons/gun_slide_lock_2.ogg', 'sound/weapons/gun_slide_lock_3.ogg', 'sound/weapons/gun_slide_lock_4.ogg', 'sound/weapons/gun_slide_lock_5.ogg') + if("law") + soundin = pick('sound/voice/beepsky/god.ogg', 'sound/voice/beepsky/iamthelaw.ogg', 'sound/voice/beepsky/secureday.ogg', 'sound/voice/beepsky/radio.ogg', 'sound/voice/beepsky/insult.ogg', 'sound/voice/beepsky/creep.ogg') + if("honkbot_e") + soundin = pick('sound/items/bikehorn.ogg', 'sound/items/AirHorn2.ogg', 'sound/misc/sadtrombone.ogg', 'sound/items/AirHorn.ogg', 'sound/effects/reee.ogg', 'sound/items/WEEOO1.ogg', 'sound/voice/beepsky/iamthelaw.ogg', 'sound/voice/beepsky/creep.ogg','sound/magic/Fireball.ogg' ,'sound/effects/pray.ogg', 'sound/voice/hiss1.ogg','sound/machines/buzz-sigh.ogg', 'sound/machines/ping.ogg', 'sound/weapons/flashbang.ogg', 'sound/weapons/bladeslice.ogg') + //START OF CIT CHANGES - adds random vore sounds if ("struggle_sound") soundin = pick( 'sound/vore/pred/struggle_01.ogg','sound/vore/pred/struggle_02.ogg','sound/vore/pred/struggle_03.ogg', 'sound/vore/pred/struggle_04.ogg','sound/vore/pred/struggle_05.ogg') @@ -183,21 +200,5 @@ 'sound/vore/prey/death_04.ogg','sound/vore/prey/death_05.ogg','sound/vore/prey/death_06.ogg', 'sound/vore/prey/death_07.ogg','sound/vore/prey/death_08.ogg','sound/vore/prey/death_09.ogg', 'sound/vore/prey/death_10.ogg') - //END OF CIT CHANGES - if("bullet_miss") - soundin = pick('sound/weapons/bulletflyby.ogg', 'sound/weapons/bulletflyby2.ogg', 'sound/weapons/bulletflyby3.ogg') - if("gun_dry_fire") - soundin = pick('sound/weapons/gun_dry_fire_1.ogg', 'sound/weapons/gun_dry_fire_2.ogg', 'sound/weapons/gun_dry_fire_3.ogg', 'sound/weapons/gun_dry_fire_4.ogg') - if("gun_insert_empty_magazine") - soundin = pick('sound/weapons/gun_magazine_insert_empty_1.ogg', 'sound/weapons/gun_magazine_insert_empty_2.ogg', 'sound/weapons/gun_magazine_insert_empty_3.ogg', 'sound/weapons/gun_magazine_insert_empty_4.ogg') - if("gun_insert_full_magazine") - soundin = pick('sound/weapons/gun_magazine_insert_full_1.ogg', 'sound/weapons/gun_magazine_insert_full_2.ogg', 'sound/weapons/gun_magazine_insert_full_3.ogg', 'sound/weapons/gun_magazine_insert_full_4.ogg', 'sound/weapons/gun_magazine_insert_full_5.ogg') - if("gun_remove_empty_magazine") - soundin = pick('sound/weapons/gun_magazine_remove_empty_1.ogg', 'sound/weapons/gun_magazine_remove_empty_2.ogg', 'sound/weapons/gun_magazine_remove_empty_3.ogg', 'sound/weapons/gun_magazine_remove_empty_4.ogg') - if("gun_slide_lock") - soundin = pick('sound/weapons/gun_slide_lock_1.ogg', 'sound/weapons/gun_slide_lock_2.ogg', 'sound/weapons/gun_slide_lock_3.ogg', 'sound/weapons/gun_slide_lock_4.ogg', 'sound/weapons/gun_slide_lock_5.ogg') - if("law") - soundin = pick('sound/voice/bgod.ogg', 'sound/voice/biamthelaw.ogg', 'sound/voice/bsecureday.ogg', 'sound/voice/bradio.ogg', 'sound/voice/binsult.ogg', 'sound/voice/bcreep.ogg') - if("honkbot_e") - soundin = pick('sound/items/bikehorn.ogg', 'sound/items/AirHorn2.ogg', 'sound/misc/sadtrombone.ogg', 'sound/items/AirHorn.ogg', 'sound/effects/reee.ogg', 'sound/items/WEEOO1.ogg', 'sound/voice/biamthelaw.ogg', 'sound/voice/bcreep.ogg','sound/magic/Fireball.ogg' ,'sound/effects/pray.ogg', 'sound/voice/hiss1.ogg','sound/machines/buzz-sigh.ogg', 'sound/machines/ping.ogg', 'sound/weapons/flashbang.ogg', 'sound/weapons/bladeslice.ogg') + //END OF CIT CHANGES return soundin diff --git a/code/game/turfs/closed.dm b/code/game/turfs/closed.dm index c1aba02f28..578232fba0 100644 --- a/code/game/turfs/closed.dm +++ b/code/game/turfs/closed.dm @@ -35,6 +35,9 @@ to_be_destroyed = FALSE return src +/turf/closed/indestructible/singularity_act() + return + /turf/closed/indestructible/oldshuttle name = "strange shuttle wall" icon = 'icons/turf/shuttleold.dmi' diff --git a/code/game/turfs/open.dm b/code/game/turfs/open.dm index 44dff22963..77c658419c 100644 --- a/code/game/turfs/open.dm +++ b/code/game/turfs/open.dm @@ -7,6 +7,8 @@ var/list/archdrops var/wet + var/footstep = null + /turf/open/ComponentInitialize() . = ..() if(wet) @@ -18,16 +20,22 @@ name = "floor" icon = 'icons/turf/floors.dmi' icon_state = "floor" + footstep = FOOTSTEP_FLOOR + tiled_dirt = TRUE /turf/open/indestructible/Melt() to_be_destroyed = FALSE return src +/turf/open/indestructible/singularity_act() + return + /turf/open/indestructible/TerraformTurf(path, defer_change = FALSE, ignore_air = FALSE) return /turf/open/indestructible/sound name = "squeaky floor" + footstep = null var/sound /turf/open/indestructible/sound/Entered(var/mob/AM) @@ -42,6 +50,8 @@ icon_state = "necro1" baseturfs = /turf/open/indestructible/necropolis initial_gas_mix = LAVALAND_DEFAULT_ATMOS + footstep = FOOTSTEP_LAVA + tiled_dirt = FALSE /turf/open/indestructible/necropolis/Initialize() . = ..() @@ -66,6 +76,7 @@ initial_gas_mix = LAVALAND_DEFAULT_ATMOS baseturfs = /turf/open/indestructible/hierophant smooth = SMOOTH_TRUE + tiled_dirt = FALSE /turf/open/indestructible/hierophant/two @@ -76,12 +87,15 @@ name = "notebook floor" desc = "A floor made of invulnerable notebook paper." icon_state = "paperfloor" + footstep = null + tiled_dirt = FALSE /turf/open/indestructible/binary name = "tear in the fabric of reality" CanAtmosPass = ATMOS_PASS_NO baseturfs = /turf/open/indestructible/binary icon_state = "binary" + footstep = null /turf/open/indestructible/airblock icon_state = "bluespace" @@ -93,6 +107,7 @@ desc = "Brass plating that gently radiates heat. For some reason, it reminds you of blood." icon_state = "reebe" baseturfs = /turf/open/indestructible/clock_spawn_room + footstep = FOOTSTEP_PLATING /turf/open/indestructible/clock_spawn_room/Entered() ..() diff --git a/code/game/turfs/simulated/floor.dm b/code/game/turfs/simulated/floor.dm index d107b0f1fd..777cbedd26 100644 --- a/code/game/turfs/simulated/floor.dm +++ b/code/game/turfs/simulated/floor.dm @@ -6,6 +6,8 @@ icon = 'icons/turf/floors.dmi' baseturfs = /turf/open/floor/plating + footstep = FOOTSTEP_FLOOR + var/icon_regular_floor = "floor" //used to remember what icon the tile should have by default var/icon_plating = "plating" thermal_conductivity = 0.040 @@ -17,6 +19,8 @@ var/list/broken_states var/list/burnt_states + tiled_dirt = TRUE + /turf/open/floor/Initialize(mapload) if (!broken_states) broken_states = list("damaged1", "damaged2", "damaged3", "damaged4", "damaged5") diff --git a/code/game/turfs/simulated/floor/fancy_floor.dm b/code/game/turfs/simulated/floor/fancy_floor.dm index e53d9d2c6d..195245d967 100644 --- a/code/game/turfs/simulated/floor/fancy_floor.dm +++ b/code/game/turfs/simulated/floor/fancy_floor.dm @@ -12,12 +12,16 @@ icon_state = "wood" floor_tile = /obj/item/stack/tile/wood broken_states = list("wood-broken", "wood-broken2", "wood-broken3", "wood-broken4", "wood-broken5", "wood-broken6", "wood-broken7") + footstep = FOOTSTEP_WOOD + tiled_dirt = FALSE /turf/open/floor/wood/examine(mob/user) ..() to_chat(user, "There's a few screws and a small crack visible.") /turf/open/floor/wood/screwdriver_act(mob/living/user, obj/item/I) + if(..()) + return TRUE return pry_tile(I, user) /turf/open/floor/wood/try_replace_tile(obj/item/stack/tile/T, mob/user, params) @@ -68,8 +72,10 @@ broken_states = list("sand") flags_1 = NONE bullet_bounce_sound = null + footstep = FOOTSTEP_GRASS var/ore_type = /obj/item/stack/ore/glass var/turfverb = "uproot" + tiled_dirt = FALSE /turf/open/floor/grass/Initialize() . = ..() @@ -96,6 +102,7 @@ initial_gas_mix = "o2=22;n2=82;TEMP=180" slowdown = 2 bullet_sizzle = TRUE + footstep = FOOTSTEP_SAND /turf/open/floor/grass/snow/try_replace_tile(obj/item/stack/tile/T, mob/user, params) return @@ -128,6 +135,7 @@ ore_type = /obj/item/stack/ore/glass/basalt turfverb = "dig up" slowdown = 0 + footstep = FOOTSTEP_SAND /turf/open/floor/grass/fakebasalt/Initialize() . = ..() @@ -147,6 +155,8 @@ canSmoothWith = list(/turf/open/floor/carpet) flags_1 = NONE bullet_bounce_sound = null + footstep = FOOTSTEP_CARPET + tiled_dirt = FALSE /turf/open/floor/carpet/examine(mob/user) ..() @@ -200,6 +210,7 @@ canSmoothWith = list(/turf/open/floor/fakepit) icon = 'icons/turf/floors/Chasms.dmi' icon_state = "smooth" + tiled_dirt = FALSE /turf/open/floor/fakepit/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir) underlay_appearance.icon = 'icons/turf/floors.dmi' @@ -212,6 +223,7 @@ floor_tile = /obj/item/stack/tile/fakespace broken_states = list("damaged") plane = PLANE_SPACE + tiled_dirt = FALSE /turf/open/floor/fakespace/Initialize() . = ..() diff --git a/code/game/turfs/simulated/floor/light_floor.dm b/code/game/turfs/simulated/floor/light_floor.dm index 48674e5ae4..6e896b5e56 100644 --- a/code/game/turfs/simulated/floor/light_floor.dm +++ b/code/game/turfs/simulated/floor/light_floor.dm @@ -10,6 +10,7 @@ var/list/coloredlights = list("g", "r", "y", "b", "p", "w", "s","o","g") var/currentcolor = 1 var/can_modify_colour = TRUE + tiled_dirt = FALSE /turf/open/floor/light/examine(mob/user) diff --git a/code/game/turfs/simulated/floor/mineral_floor.dm b/code/game/turfs/simulated/floor/mineral_floor.dm index cd82888827..a470e3e0a1 100644 --- a/code/game/turfs/simulated/floor/mineral_floor.dm +++ b/code/game/turfs/simulated/floor/mineral_floor.dm @@ -13,11 +13,12 @@ name = "mineral floor" icon_state = "" var/list/icons - + tiled_dirt = FALSE /turf/open/floor/mineral/Initialize() - broken_states = list("[initial(icon_state)]_dam") + if(!broken_states) + broken_states = list("[initial(icon_state)]_dam") . = ..() if (!icons) icons = list() @@ -77,32 +78,35 @@ //TITANIUM (shuttle) -/turf/open/floor/mineral/titanium/blue - icon_state = "shuttlefloor" - icons = list("shuttlefloor","shuttlefloor_dam") - -/turf/open/floor/mineral/titanium/blue/airless - initial_gas_mix = "TEMP=2.7" - -/turf/open/floor/mineral/titanium/yellow - icon_state = "shuttlefloor2" - icons = list("shuttlefloor2","shuttlefloor2_dam") - -/turf/open/floor/mineral/titanium/yellow/airless - initial_gas_mix = "TEMP=2.7" - /turf/open/floor/mineral/titanium name = "shuttle floor" - icon_state = "shuttlefloor3" + icon_state = "titanium" floor_tile = /obj/item/stack/tile/mineral/titanium - icons = list("shuttlefloor3","shuttlefloor3_dam") + broken_states = list("titanium_dam1","titanium_dam2","titanium_dam3","titanium_dam4","titanium_dam5") /turf/open/floor/mineral/titanium/airless initial_gas_mix = "TEMP=2.7" +/turf/open/floor/mineral/titanium/yellow + icon_state = "titanium_yellow" + +/turf/open/floor/mineral/titanium/yellow/airless + initial_gas_mix = "TEMP=2.7" + +/turf/open/floor/mineral/titanium/blue + icon_state = "titanium_blue" + +/turf/open/floor/mineral/titanium/blue/airless + initial_gas_mix = "TEMP=2.7" + +/turf/open/floor/mineral/titanium/white + icon_state = "titanium_white" + +/turf/open/floor/mineral/titanium/white/airless + initial_gas_mix = "TEMP=2.7" + /turf/open/floor/mineral/titanium/purple - icon_state = "shuttlefloor5" - icons = list("shuttlefloor5","shuttlefloor5_dam") + icon_state = "titanium_purple" /turf/open/floor/mineral/titanium/purple/airless initial_gas_mix = "TEMP=2.7" @@ -110,14 +114,20 @@ //PLASTITANIUM (syndieshuttle) /turf/open/floor/mineral/plastitanium name = "shuttle floor" - icon_state = "shuttlefloor4" + icon_state = "plastitanium" floor_tile = /obj/item/stack/tile/mineral/plastitanium - icons = list("shuttlefloor4","shuttlefloor4_dam") + broken_states = list("plastitanium_dam1","plastitanium_dam2","plastitanium_dam3","plastitanium_dam4","plastitanium_dam5") /turf/open/floor/mineral/plastitanium/airless initial_gas_mix = "TEMP=2.7" -/turf/open/floor/mineral/plastitanium/brig +/turf/open/floor/mineral/plastitanium/red + icon_state = "plastitanium_red" + +/turf/open/floor/mineral/plastitanium/red/airless + initial_gas_mix = "TEMP=2.7" + +/turf/open/floor/mineral/plastitanium/red/brig name = "brig floor" //BANANIUM diff --git a/code/game/turfs/simulated/floor/misc_floor.dm b/code/game/turfs/simulated/floor/misc_floor.dm index 3b3d4c40ec..91744f3fa8 100644 --- a/code/game/turfs/simulated/floor/misc_floor.dm +++ b/code/game/turfs/simulated/floor/misc_floor.dm @@ -3,6 +3,7 @@ icon_state = "plaque" desc = "\"This is a plaque in honour of our comrades on the G4407 Stations. Hopefully TG4407 model can live up to your fame and fortune.\" Scratched in beneath that is a crude image of a meteor and a spaceman. The spaceman is laughing. The meteor is exploding." floor_tile = /obj/item/stack/tile/plasteel + tiled_dirt = FALSE /turf/open/floor/vault icon_state = "rockvault" @@ -46,10 +47,6 @@ /turf/open/floor/circuit/airless initial_gas_mix = "TEMP=2.7" -/turf/open/floor/circuit/killroom - name = "killroom floor" - initial_gas_mix = "n2=500;TEMP=80" - /turf/open/floor/circuit/telecomms initial_gas_mix = "n2=100;TEMP=80" @@ -143,6 +140,7 @@ desc = "Tightly-pressed brass tiles. They emit minute vibration." icon_state = "plating" baseturfs = /turf/open/floor/clockwork + footstep = FOOTSTEP_PLATING var/uses_overlay = TRUE var/obj/effect/clockwork/overlay/floor/realappearence diff --git a/code/game/turfs/simulated/floor/plasteel_floor.dm b/code/game/turfs/simulated/floor/plasteel_floor.dm index 1b4f959fc9..884e4c6551 100644 --- a/code/game/turfs/simulated/floor/plasteel_floor.dm +++ b/code/game/turfs/simulated/floor/plasteel_floor.dm @@ -17,6 +17,8 @@ /turf/open/floor/plasteel/airless initial_gas_mix = "TEMP=2.7" +/turf/open/floor/plasteel/telecomms + initial_gas_mix = "n2=100;TEMP=80" /turf/open/floor/plasteel/dark @@ -25,19 +27,14 @@ initial_gas_mix = "TEMP=2.7" /turf/open/floor/plasteel/dark/telecomms initial_gas_mix = "n2=100;TEMP=80" -/turf/open/floor/plasteel/dark/telecomms/mainframe - name = "mainframe floor" -/turf/open/floor/plasteel/dark/telecomms/server - name = "server base" -/turf/open/floor/plasteel/dark/telecomms/server/walkway - name = "server walkway" /turf/open/floor/plasteel/airless/dark icon_state = "darkfull" /turf/open/floor/plasteel/dark/side icon_state = "dark" /turf/open/floor/plasteel/dark/corner icon_state = "darkcorner" - +/turf/open/floor/plasteel/checker + icon_state = "checker" /turf/open/floor/plasteel/white @@ -52,228 +49,8 @@ icon_state = "whitehall" /turf/open/floor/plasteel/airless/white/corner icon_state = "whitecorner" - - - -/turf/open/floor/plasteel/brown - icon_state = "brown" -/turf/open/floor/plasteel/brown/telecomms +/turf/open/floor/plasteel/white/telecomms initial_gas_mix = "n2=100;TEMP=80" -/turf/open/floor/plasteel/brown/telecomms/mainframe - name = "mainframe floor" -/turf/open/floor/plasteel/brown/corner - icon_state = "browncorner" - -/turf/open/floor/plasteel/darkbrown - icon_state = "darkbrownfull" -/turf/open/floor/plasteel/darkbrown/side - icon_state = "darkbrown" -/turf/open/floor/plasteel/darkbrown/corner - icon_state = "darkbrowncorners" - - - -/turf/open/floor/plasteel/green - icon_state = "greenfull" -/turf/open/floor/plasteel/green/side - icon_state = "green" -/turf/open/floor/plasteel/green/side/telecomms - initial_gas_mix = "n2=100;TEMP=80" -/turf/open/floor/plasteel/green/corner - icon_state = "greencorner" - -/turf/open/floor/plasteel/darkgreen - icon_state = "darkgreenfull" -/turf/open/floor/plasteel/darkgreen/side - icon_state = "darkgreen" -/turf/open/floor/plasteel/darkgreen/side/telecomms - initial_gas_mix = "n2=100;TEMP=80" -/turf/open/floor/plasteel/darkgreen/corner - icon_state = "darkgreencorners" - -/turf/open/floor/plasteel/whitegreen - icon_state = "whitegreenfull" -/turf/open/floor/plasteel/whitegreen/side - icon_state = "whitegreen" -/turf/open/floor/plasteel/whitegreen/corner - icon_state = "whitegreencorner" - - - -/turf/open/floor/plasteel/red - icon_state = "redfull" -/turf/open/floor/plasteel/red/side - icon_state = "red" -/turf/open/floor/plasteel/red/corner - icon_state = "redcorner" - -/turf/open/floor/plasteel/darkred - icon_state = "darkredfull" -/turf/open/floor/plasteel/darkred/side - icon_state = "darkred" -/turf/open/floor/plasteel/darkred/side/telecomms - initial_gas_mix = "n2=100;TEMP=80" -/turf/open/floor/plasteel/darkred/corner - icon_state = "darkredcorners" - -/turf/open/floor/plasteel/whitered - icon_state = "whiteredfull" -/turf/open/floor/plasteel/whitered/side - icon_state = "whitered" -/turf/open/floor/plasteel/whitered/corner - icon_state = "whiteredcorner" - - - -/turf/open/floor/plasteel/blue - icon_state = "bluefull" -/turf/open/floor/plasteel/blue/side - icon_state = "blue" -/turf/open/floor/plasteel/blue/corner - icon_state = "bluecorner" - -/turf/open/floor/plasteel/darkblue - icon_state = "darkbluefull" -/turf/open/floor/plasteel/darkblue/side - icon_state = "darkblue" -/turf/open/floor/plasteel/darkblue/side/telecomms - initial_gas_mix = "n2=100;TEMP=80" -/turf/open/floor/plasteel/darkblue/corner - icon_state = "darkbluecorners" - -/turf/open/floor/plasteel/whiteblue - icon_state = "whitebluefull" -/turf/open/floor/plasteel/whiteblue/side - icon_state = "whiteblue" -/turf/open/floor/plasteel/whiteblue/side/telecomms - initial_gas_mix = "n2=100;TEMP=80" -/turf/open/floor/plasteel/whiteblue/corner - icon_state = "whitebluecorner" - - - -/turf/open/floor/plasteel/yellow - icon_state = "yellowfull" -/turf/open/floor/plasteel/yellow/side - icon_state = "yellow" -/turf/open/floor/plasteel/yellow/corner - icon_state = "yellowcorner" - -/turf/open/floor/plasteel/darkyellow - icon_state = "darkyellowfull" -/turf/open/floor/plasteel/darkyellow/side - icon_state = "darkyellow" -/turf/open/floor/plasteel/darkyellow/side/telecomms - initial_gas_mix = "n2=100;TEMP=80" -/turf/open/floor/plasteel/darkyellow/corner - icon_state = "darkyellowcorners" - -/turf/open/floor/plasteel/whiteyellow - icon_state = "whiteyellowfull" -/turf/open/floor/plasteel/whiteyellow/side - icon_state = "whiteyellow" -/turf/open/floor/plasteel/whiteyellow/corner - icon_state = "whiteyellowcorner" - - - -/turf/open/floor/plasteel/purple - icon_state = "purplefull" -/turf/open/floor/plasteel/purple/side - icon_state = "purple" -/turf/open/floor/plasteel/purple/corner - icon_state = "purplecorner" - -/turf/open/floor/plasteel/darkpurple - icon_state = "darkpurplefull" -/turf/open/floor/plasteel/darkpurple/side - icon_state = "darkpurple" -/turf/open/floor/plasteel/darkpurple/side/telecomms - initial_gas_mix = "n2=100;TEMP=80" -/turf/open/floor/plasteel/darkpurple/corner - icon_state = "darkpurplecorners" - -/turf/open/floor/plasteel/whitepurple - icon_state = "whitepurplefull" -/turf/open/floor/plasteel/whitepurple/side - icon_state = "whitepurple" -/turf/open/floor/plasteel/whitepurple/side/telecomms - initial_gas_mix = "n2=100;TEMP=80" -/turf/open/floor/plasteel/whitepurple/corner - icon_state = "whitepurplecorner" - - -/turf/open/floor/plasteel/orange - icon_state = "orangefull" -/turf/open/floor/plasteel/orange/side - icon_state = "orange" -/turf/open/floor/plasteel/orange/corner - icon_state = "orangecorner" - - -/turf/open/floor/plasteel/neutral - icon_state = "neutralfull" -/turf/open/floor/plasteel/neutral/side - icon_state = "neutral" -/turf/open/floor/plasteel/neutral/side/telecomms - initial_gas_mix = "n2=100;TEMP=80" -/turf/open/floor/plasteel/neutral/corner - icon_state = "neutralcorner" - - -/turf/open/floor/plasteel/arrival - icon_state = "arrival" -/turf/open/floor/plasteel/arrival/corner - icon_state = "arrivalcorner" - -/turf/open/floor/plasteel/escape - icon_state = "escape" -/turf/open/floor/plasteel/escape/corner - icon_state = "escapecorner" - - -/turf/open/floor/plasteel/caution - icon_state = "caution" -/turf/open/floor/plasteel/caution/corner - icon_state = "cautioncorner" - - -/turf/open/floor/plasteel/redyellow - icon_state = "redyellowfull" -/turf/open/floor/plasteel/redyellow/side - icon_state = "redyellow" - - -/turf/open/floor/plasteel/redblue - icon_state = "redbluefull" -/turf/open/floor/plasteel/redblue/blueside - icon_state = "bluered" -/turf/open/floor/plasteel/redblue/redside - icon_state = "redblue" - - -/turf/open/floor/plasteel/redgreen - icon_state = "redgreenfull" -/turf/open/floor/plasteel/redgreen/side - icon_state = "redgreen" - - -/turf/open/floor/plasteel/greenyellow - icon_state = "greenyellowfull" -/turf/open/floor/plasteel/greenyellow/side - icon_state = "greenyellow" - - -/turf/open/floor/plasteel/greenblue - icon_state = "greenbluefull" -/turf/open/floor/plasteel/greenblue/side - icon_state = "greenblue" - - -/turf/open/floor/plasteel/blueyellow - icon_state = "blueyellowfull" -/turf/open/floor/plasteel/blueyellow/side - icon_state = "blueyellow" /turf/open/floor/plasteel/yellowsiding @@ -282,11 +59,6 @@ icon_state = "yellowcornersiding" -/turf/open/floor/plasteel/asteroid - icon_state = "asteroidfloor" -/turf/open/floor/plasteel/airless/asteroid - icon_state = "asteroidfloor" - /turf/open/floor/plasteel/recharge_floor icon_state = "recharge_floor" /turf/open/floor/plasteel/recharge_floor/asteroid @@ -299,38 +71,22 @@ /turf/open/floor/plasteel/showroomfloor icon_state = "showroomfloor" -/turf/open/floor/plasteel/floorgrime - icon_state = "floorgrime" -/turf/open/floor/plasteel/airless/floorgrime - icon_state = "floorgrime" /turf/open/floor/plasteel/solarpanel icon_state = "solarpanel" /turf/open/floor/plasteel/airless/solarpanel icon_state = "solarpanel" -/turf/open/floor/plasteel/cmo - icon_state = "cmo" -/turf/open/floor/plasteel/barber - icon_state = "barber" - -/turf/open/floor/plasteel/hydrofloor - icon_state = "hydrofloor" /turf/open/floor/plasteel/freezer icon_state = "freezerfloor" /turf/open/floor/plasteel/freezer/airless initial_gas_mix = "TEMP=2.7" -/turf/open/floor/plasteel/bar - icon_state = "bar" - -/turf/open/floor/plasteel/airless/bar - icon_state = "bar" - /turf/open/floor/plasteel/grimy icon_state = "grimy" + tiled_dirt = FALSE /turf/open/floor/plasteel/cafeteria icon_state = "cafeteria" @@ -338,21 +94,6 @@ /turf/open/floor/plasteel/airless/cafeteria icon_state = "cafeteria" -/turf/open/floor/plasteel/vault - icon_state = "vaultfull" -/turf/open/floor/plasteel/vault/side - icon_state = "vault" -/turf/open/floor/plasteel/vault/corner - icon_state = "vaultcorner" -/turf/open/floor/plasteel/vault/airless - initial_gas_mix = "TEMP=2.7" -/turf/open/floor/plasteel/vault/telecomms - initial_gas_mix = "n2=100;TEMP=80" -/turf/open/floor/plasteel/vault/telecomms/mainframe - name = "mainframe floor" -/turf/open/floor/plasteel/vault/killroom - name = "killroom floor" - initial_gas_mix = "n2=500;TEMP=80" /turf/open/floor/plasteel/cult icon_state = "cult" @@ -365,31 +106,17 @@ icon_state = "plaque" name = "commemorative plaque" desc = "\"This is a plaque in honour of our comrades on the G4407 Stations. Hopefully TG4407 model can live up to your fame and fortune.\" Scratched in beneath that is a crude image of a meteor and a spaceman. The spaceman is laughing. The meteor is exploding." + tiled_dirt = FALSE /turf/open/floor/plasteel/cult/narsie_act() return - /turf/open/floor/plasteel/cult/airless initial_gas_mix = "TEMP=2.7" - - - - -// -//unused? remove? -// -/turf/open/floor/plasteel/stage_bottom - icon_state = "stage_bottom" -/turf/open/floor/plasteel/stage_left - icon_state = "stage_left" -/turf/open/floor/plasteel/stage_bleft - icon_state = "stage_bleft" - - /turf/open/floor/plasteel/stairs icon_state = "stairs" + tiled_dirt = FALSE /turf/open/floor/plasteel/stairs/left icon_state = "stairs-l" /turf/open/floor/plasteel/stairs/medium @@ -400,12 +127,6 @@ icon_state = "stairs-old" -/turf/open/floor/plasteel/brownold - icon_state = "brownold" -/turf/open/floor/plasteel/brownold/corner - icon_state = "browncornerold" - - /turf/open/floor/plasteel/rockvault icon_state = "rockvault" /turf/open/floor/plasteel/rockvault/alien diff --git a/code/game/turfs/simulated/floor/plating.dm b/code/game/turfs/simulated/floor/plating.dm index eeed31bd9f..9d2adbdfba 100644 --- a/code/game/turfs/simulated/floor/plating.dm +++ b/code/game/turfs/simulated/floor/plating.dm @@ -12,6 +12,8 @@ icon_state = "plating" intact = FALSE baseturfs = /turf/open/space + footstep = FOOTSTEP_PLATING + var/attachment_holes = TRUE /turf/open/floor/plating/examine(mob/user) diff --git a/code/game/turfs/simulated/floor/plating/asteroid.dm b/code/game/turfs/simulated/floor/plating/asteroid.dm index a57213a4f9..b8da9350a4 100644 --- a/code/game/turfs/simulated/floor/plating/asteroid.dm +++ b/code/game/turfs/simulated/floor/plating/asteroid.dm @@ -9,6 +9,7 @@ icon_state = "asteroid" icon_plating = "asteroid" postdig_icon_change = TRUE + footstep = FOOTSTEP_SAND var/environment_type = "asteroid" var/turf_type = /turf/open/floor/plating/asteroid //Because caves do whacky shit to revert to normal var/floor_variance = 20 //probability floor has a different icon state @@ -298,6 +299,7 @@ icon_state = "snow-ice" icon_plating = "snow-ice" environment_type = "snow_cavern" + footstep = FOOTSTEP_FLOOR /turf/open/floor/plating/asteroid/snow/ice/burn_tile() return FALSE diff --git a/code/game/turfs/simulated/floor/plating/dirt.dm b/code/game/turfs/simulated/floor/plating/dirt.dm index cd7272fa40..dc865634f4 100644 --- a/code/game/turfs/simulated/floor/plating/dirt.dm +++ b/code/game/turfs/simulated/floor/plating/dirt.dm @@ -8,6 +8,8 @@ initial_gas_mix = LAVALAND_DEFAULT_ATMOS planetary_atmos = TRUE attachment_holes = FALSE + footstep = FOOTSTEP_SAND + tiled_dirt = FALSE /turf/open/floor/plating/dirt/dark icon_state = "greenerdirt" diff --git a/code/game/turfs/simulated/floor/plating/misc_plating.dm b/code/game/turfs/simulated/floor/plating/misc_plating.dm index 3c4c8d9f85..f86ab3c03c 100644 --- a/code/game/turfs/simulated/floor/plating/misc_plating.dm +++ b/code/game/turfs/simulated/floor/plating/misc_plating.dm @@ -6,6 +6,7 @@ /turf/open/floor/plating/abductor name = "alien floor" icon_state = "alienpod1" + tiled_dirt = FALSE /turf/open/floor/plating/abductor/Initialize() . = ..() @@ -15,6 +16,7 @@ /turf/open/floor/plating/abductor2 name = "alien plating" icon_state = "alienplating" + tiled_dirt = FALSE /turf/open/floor/plating/abductor2/break_tile() return //unbreakable @@ -44,6 +46,8 @@ initial_gas_mix = LAVALAND_DEFAULT_ATMOS planetary_atmos = TRUE attachment_holes = FALSE + footstep = FOOTSTEP_SAND + tiled_dirt = FALSE /turf/open/floor/plating/ashplanet/Initialize() if(smooth) @@ -74,6 +78,7 @@ smooth_icon = 'icons/turf/floors/rocky_ash.dmi' layer = MID_TURF_LAYER canSmoothWith = list(/turf/open/floor/plating/ashplanet/rocky, /turf/closed) + footstep = FOOTSTEP_FLOOR /turf/open/floor/plating/ashplanet/wateryrock gender = PLURAL @@ -81,6 +86,7 @@ smooth = null icon_state = "wateryrock" slowdown = 2 + footstep = FOOTSTEP_FLOOR /turf/open/floor/plating/ashplanet/wateryrock/Initialize() icon_state = "[icon_state][rand(1, 9)]" @@ -93,6 +99,7 @@ flags_1 = NONE attachment_holes = FALSE bullet_bounce_sound = null + footstep = FOOTSTEP_SAND /turf/open/floor/plating/beach/try_replace_tile(obj/item/stack/tile/T, mob/user, params) return @@ -133,6 +140,7 @@ gender = PLURAL name = "iron sand" desc = "Like sand, but more metal." + footstep = FOOTSTEP_SAND /turf/open/floor/plating/ironsand/Initialize() . = ..() @@ -156,6 +164,7 @@ slowdown = 1 attachment_holes = FALSE bullet_sizzle = TRUE + footstep = FOOTSTEP_FLOOR /turf/open/floor/plating/ice/Initialize() . = ..() @@ -192,6 +201,7 @@ temperature = 180 attachment_holes = FALSE planetary_atmos = TRUE + footstep = FOOTSTEP_SAND /turf/open/floor/plating/snowed/cavern initial_gas_mix = "o2=0;n2=82;plasma=24;TEMP=120" diff --git a/code/game/turfs/simulated/floor/reinf_floor.dm b/code/game/turfs/simulated/floor/reinf_floor.dm index 13cf936412..e677de8c5c 100644 --- a/code/game/turfs/simulated/floor/reinf_floor.dm +++ b/code/game/turfs/simulated/floor/reinf_floor.dm @@ -6,6 +6,8 @@ thermal_conductivity = 0.025 heat_capacity = INFINITY floor_tile = /obj/item/stack/rods + footstep = FOOTSTEP_PLATING + tiled_dirt = FALSE /turf/open/floor/engine/examine(mob/user) ..() @@ -36,7 +38,8 @@ if(I.use_tool(src, user, 30, volume=80)) if(!istype(src, /turf/open/floor/engine)) return TRUE - new /obj/item/stack/rods(src, 2) + if(floor_tile) + new floor_tile(src, 2) ScrapeAway() return TRUE diff --git a/code/game/turfs/simulated/lava.dm b/code/game/turfs/simulated/lava.dm index b6f862cab5..b9e355b122 100644 --- a/code/game/turfs/simulated/lava.dm +++ b/code/game/turfs/simulated/lava.dm @@ -12,6 +12,8 @@ light_color = LIGHT_COLOR_LAVA bullet_bounce_sound = 'sound/items/welder2.ogg' + footstep = FOOTSTEP_LAVA + /turf/open/lava/ex_act(severity, target) contents_explosion(severity, target) diff --git a/code/game/turfs/simulated/minerals.dm b/code/game/turfs/simulated/minerals.dm index 6123bf25e6..61c7950e88 100644 --- a/code/game/turfs/simulated/minerals.dm +++ b/code/game/turfs/simulated/minerals.dm @@ -95,7 +95,7 @@ to_chat(M, "You tunnel into the rock.") gets_drilled(M) -/turf/closed/mineral/CollidedWith(atom/movable/AM) +/turf/closed/mineral/Bumped(atom/movable/AM) ..() if(ishuman(AM)) var/mob/living/carbon/human/H = AM diff --git a/code/game/turfs/simulated/reebe_void.dm b/code/game/turfs/simulated/reebe_void.dm index 624525d11d..14aa02065d 100644 --- a/code/game/turfs/simulated/reebe_void.dm +++ b/code/game/turfs/simulated/reebe_void.dm @@ -5,6 +5,7 @@ baseturfs = /turf/open/indestructible/reebe_void planetary_atmos = TRUE bullet_bounce_sound = null //forever falling + tiled_dirt = FALSE /turf/open/indestructible/reebe_void/Initialize(mapload) . = ..() diff --git a/code/game/turfs/simulated/wall/mineral_walls.dm b/code/game/turfs/simulated/wall/mineral_walls.dm index 0715753643..dbffd1010b 100644 --- a/code/game/turfs/simulated/wall/mineral_walls.dm +++ b/code/game/turfs/simulated/wall/mineral_walls.dm @@ -80,7 +80,7 @@ radiate() ..() -/turf/closed/wall/mineral/uranium/CollidedWith(atom/movable/AM) +/turf/closed/wall/mineral/uranium/Bumped(atom/movable/AM) radiate() ..() @@ -223,7 +223,7 @@ T.atom_colours = atom_colours.Copy() T.update_atom_colour() if(T.dir != dir) - T.dir = dir + T.setDir(dir) T.transform = transform return T @@ -295,7 +295,7 @@ T.atom_colours = atom_colours.Copy() T.update_atom_colour() if(T.dir != dir) - T.dir = dir + T.setDir(dir) T.transform = transform return T diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm index b153243f5d..b18fbb50f6 100644 --- a/code/game/turfs/simulated/walls.dm +++ b/code/game/turfs/simulated/walls.dm @@ -139,7 +139,7 @@ ..(user, 1) if(prob(hardness)) playsound(src, 'sound/effects/meteorimpact.ogg', 100, 1) - user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) + user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" ), forced = "hulk") dismantle_wall(1) else playsound(src, 'sound/effects/bang.ogg', 50, 1) diff --git a/code/game/turfs/simulated/water.dm b/code/game/turfs/simulated/water.dm index 23ba5957c8..b46dd1d06c 100644 --- a/code/game/turfs/simulated/water.dm +++ b/code/game/turfs/simulated/water.dm @@ -11,6 +11,4 @@ bullet_sizzle = TRUE bullet_bounce_sound = null //needs a splashing sound one day. -/turf/open/water/Initialize() - . = ..() - MakeSlippery(TURF_WET_WATER, INFINITY, 0, INFINITY, TRUE) + footstep = FOOTSTEP_WATER diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm index ba45d8819c..3e7968a9d7 100644 --- a/code/game/turfs/space/space.dm +++ b/code/game/turfs/space/space.dm @@ -141,7 +141,7 @@ var/itercount = 0 while(DT.density || istype(DT.loc,/area/shuttle)) // Extend towards the center of the map, trying to look for a better place to arrive if (itercount++ >= 100) - log_game("SPACE Z-TRANSIT ERROR: Could not not find a safe place to land [A] within 100 iterations.") + log_game("SPACE Z-TRANSIT ERROR: Could not find a safe place to land [A] within 100 iterations.") break if (tx < 128) tx++ diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index 490a6dcaf7..afe275f9b9 100755 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -31,6 +31,8 @@ var/bullet_sizzle = FALSE //used by ammo_casing/bounce_away() to determine if the shell casing should make a sizzle sound when it's ejected over the turf //IE if the turf is supposed to be water, set TRUE. + var/tiled_dirt = FALSE // use smooth tiled dirt decal + /turf/vv_edit_var(var_name, new_value) var/static/list/banned_edits = list("x", "y", "z") if(var_name in banned_edits) @@ -139,40 +141,40 @@ stack_trace("Non movable passed to turf CanPass : [mover]") return FALSE -/turf/Enter(atom/movable/mover as mob|obj, atom/forget as mob|obj|turf|area) - // First, make sure it can leave its square - if(isturf(mover.loc)) - // Nothing but border objects stop you from leaving a tile, only one loop is needed - for(var/obj/obstacle in mover.loc) - if(!obstacle.CheckExit(mover, src) && obstacle != mover && obstacle != forget) - mover.Collide(obstacle) - return FALSE - - //Then, check the turf itself - if (!src.CanPass(mover, src)) - mover.Collide(src) +/turf/Enter(atom/movable/mover, atom/oldloc) + // Do not call ..() + // Byond's default turf/Enter() doesn't have the behaviour we want with Bump() + // By default byond will call Bump() on the first dense object in contents + // Here's hoping it doesn't stay like this for years before we finish conversion to step_ + var/atom/firstbump + if(!CanPass(mover, src)) + firstbump = src + else + for(var/i in contents) + if(i == mover || i == mover.loc) // Multi tile objects and moving out of other objects + continue + var/atom/movable/thing = i + if(thing.Cross(mover)) + continue + if(!firstbump || ((thing.layer > firstbump.layer || thing.flags_1 & ON_BORDER_1) && !(firstbump.flags_1 & ON_BORDER_1))) + firstbump = thing + if(firstbump) + mover.Bump(firstbump) return FALSE + return TRUE - - var/atom/movable/topmost_bump - var/top_layer = FALSE - - //Next, check objects to block entry that are on the border - for(var/atom/movable/obstacle in src) - if(!obstacle.CanPass(mover, mover.loc, 1) && (forget != obstacle)) - if(obstacle.flags_1 & ON_BORDER_1) - mover.Collide(obstacle) - return FALSE - else - if(obstacle.layer > top_layer) - topmost_bump = obstacle - top_layer = obstacle.layer - - if(topmost_bump) - mover.Collide(topmost_bump) +/turf/Exit(atom/movable/mover, atom/newloc) + . = ..() + if(!.) return FALSE - - return TRUE //Nothing found to block so return success! + for(var/i in contents) + if(i == mover) + continue + var/atom/movable/thing = i + if(!thing.Uncross(mover, newloc)) + if(thing.flags_1 & ON_BORDER_1) + mover.Bump(thing) + return FALSE /turf/Entered(atom/movable/AM) ..() @@ -331,9 +333,9 @@ var/datum/camerachunk/C = GLOB.cameranet.chunkGenerated(x, y, z) if(C) if(C.obscuredTurfs[src]) - vis_contents += GLOB.cameranet.vis_contents + vis_contents += GLOB.cameranet.vis_contents_objects else - vis_contents -= GLOB.cameranet.vis_contents + vis_contents -= GLOB.cameranet.vis_contents_objects /turf/proc/burn_tile() diff --git a/code/game/world.dm b/code/game/world.dm index b5d0781dab..26c01c63c4 100644 --- a/code/game/world.dm +++ b/code/game/world.dm @@ -1,27 +1,24 @@ #define RESTART_COUNTER_PATH "data/round_counter.txt" -GLOBAL_VAR(security_mode) GLOBAL_VAR(restart_counter) -GLOBAL_PROTECT(security_mode) //This happens after the Master subsystem new(s) (it's a global datum) //So subsystems globals exist, but are not initialised /world/New() + log_world("World loaded at [time_stamp()]!") SetupExternalRSC() GLOB.config_error_log = GLOB.world_manifest_log = GLOB.world_pda_log = GLOB.world_job_debug_log = GLOB.sql_error_log = GLOB.world_href_log = GLOB.world_runtime_log = GLOB.world_attack_log = GLOB.world_game_log = "data/logs/config_error.log" //temporary file used to record errors with loading config, moved to log directory once logging is set bl - CheckSecurityMode() - make_datum_references_lists() //initialises global lists for referencing frequently used datums (so that we only ever do it once) TgsNew() GLOB.revdata = new - config.Load() + config.Load(params[OVERRIDE_CONFIG_DIRECTORY_PARAMETER]) //SetupLogs depends on the RoundID, so lets check //DB schema and set RoundID if we can @@ -29,6 +26,10 @@ GLOBAL_PROTECT(security_mode) SSdbcore.SetRoundID() SetupLogs() +#ifndef USE_CUSTOM_ERROR_HANDLER + world.log = file("[GLOB.log_directory]/dd.log") +#endif + load_admins() LoadVerbs(/datum/verbs/menu) if(CONFIG_GET(flag/usewhitelist)) @@ -101,6 +102,7 @@ GLOBAL_PROTECT(security_mode) GLOB.world_game_log = "[GLOB.log_directory]/game.log" GLOB.world_attack_log = "[GLOB.log_directory]/attack.log" GLOB.world_pda_log = "[GLOB.log_directory]/pda.log" + GLOB.world_telecomms_log = "[GLOB.log_directory]/telecomms.log" GLOB.world_manifest_log = "[GLOB.log_directory]/manifest.log" GLOB.world_href_log = "[GLOB.log_directory]/hrefs.log" GLOB.sql_error_log = "[GLOB.log_directory]/sql.log" @@ -116,6 +118,7 @@ GLOBAL_PROTECT(security_mode) start_log(GLOB.world_game_log) start_log(GLOB.world_attack_log) start_log(GLOB.world_pda_log) + start_log(GLOB.world_telecomms_log) start_log(GLOB.world_manifest_log) start_log(GLOB.world_href_log) start_log(GLOB.world_qdel_log) @@ -130,20 +133,6 @@ GLOBAL_PROTECT(security_mode) if(GLOB.round_id) log_game("Round ID: [GLOB.round_id]") -/world/proc/CheckSecurityMode() - //try to write to data - if(!text2file("The world is running at least safe mode", "data/server_security_check.lock")) - GLOB.security_mode = SECURITY_ULTRASAFE - warning("/tg/station 13 is not supported in ultrasafe security mode. Everything will break!") - return - - //try to shell - if(shell("echo \"The world is running in trusted mode\"") != null) - GLOB.security_mode = SECURITY_TRUSTED - else - GLOB.security_mode = SECURITY_SAFE - warning("/tg/station 13 uses many file operations, a few shell()s, and some external call()s. Trusted mode is recommended. You can download our source code for your own browsing and compilation at https://github.com/tgstation/tgstation") - /world/Topic(T, addr, master, key) TGS_TOPIC //redirect to server tools if necessary